Every SAS developer eventually writes the same utility macro twice - once because they needed it, and again in the next project because nobody could find the first one. SASjs Core is the library that stops that happening: over 250 fully documented macros covering everything from dataset inspection and metadata lookups to Viya REST calls, all MIT licensed and free for commercial use. This post is a short tour of what is in it, and the five ways to get it into your environment.

What is in the library

The macros are grouped into nine folders, by the platform they target and the job they do:

  • BASE - macro functions and procedures that run on any SAS platform, no X command required (mf_, mp_)
  • DDL - creating and changing tables (mddl_)
  • FCMP - macros that generate proc fcmp functions (mcf_)
  • LUA - LUA modules wrapped as macros, for the proc lua interpreter (ml_)
  • META - metadata server access on SAS 9 and Enterprise BI (mm_)
  • METAX - the metadata macros that need an enabled X command (mmx_)
  • SERVER - for apps running on SASjs Server (ms_)
  • VIYA - interfacing with SAS Viya (mv_, mvf_)
  • XPLATFORM - macros written to behave the same on Viya, SAS 9 and SASjs Server (mx_)

Each macro carries its documentation in a doxygen header - parameters, return values, and the related macros you probably want next. Those same comments generate the published documentation, so the reference and the code cannot drift apart.

Five ways to install

1. Add the folders to your SASAUTOS path. Clone the repo somewhere your SAS system can read, then:

%let repoloc=/your/path/core;
options insert=(sasautos="&repoloc/base");
options insert=(sasautos="&repoloc/ddl");
options insert=(sasautos="&repoloc/fcmp");
options insert=(sasautos="&repoloc/lua");
options insert=(sasautos="&repoloc/meta");
options insert=(sasautos="&repoloc/metax");
options insert=(sasautos="&repoloc/server");
options insert=(sasautos="&repoloc/viya");
options insert=(sasautos="&repoloc/xplatform");

2. Compile the whole set in two lines. If your SAS session has internet access, the build generates a single file containing every macro:

filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc;

3. Install it as an npm package. JavaScript and CLI projects pull the macros in from npm and pin them to a version, the same way as any other dependency:

npm install @sasjs/core

That writes the library into node_modules/@sasjs/core - the same nine folders as the repo, in the project and ready to be brought into the build.

4. Install it as a SAS package. SASjs Core is published to SASPAC, the SAS Packages Archive, as a package for Bartosz Jablonski’s SAS Packages Framework. The framework is a single file - enable it, then install and load the package:

/* a folder for the packages - the fileref must be named "packages", */
/* and the folder must already exist (WORK is the portable choice) */
filename packages "%sysfunc(pathname(work))";

/* the framework is a single file */
filename SPFinit url "https://bit.ly/SPFinit";

/* enable the framework */
%include SPFinit;

/* download and unpack the package */
%installPackage(sasjscore)

/* optional: print the package help to the log */
%helpPackage(sasjscore)

/* compile the macros into the session */
%loadPackage(sasjscore)

The macro reference for the framework - %installPackage, %helpPackage, %loadPackage, %unloadPackage - is in the SPF documentation.

This is a different way of owning the code rather than a different copy of it. The package is one zip holding the macros plus the framework’s generated load, unload and help files, so %loadPackage() compiles the set into a session and %unloadPackage() takes it back out - useful when a job needs the macros but a shared server’s SASAUTOS should not carry them. Installation is versioned, and it tracks the source: the archive currently carries 5.2.10, the same version as the npm release, so a build can pin the library the way it pins anything else. For repeated use, run %installPackage(SPFinit) once to put the framework in that folder - point the fileref at a permanent directory rather than WORK if it needs to survive the session - and the two internet-facing lines collapse to %include packages(SPFinit.sas); with no network access needed at run time.

5. Let the SASjs CLI compile them in. With @sasjs/core in the project’s package.json, nothing has to be installed where the SAS server can see it. Name the macros your program needs in its doxygen header, run sasjs compile, and the CLI resolves each one and inlines it as precode - producing a single self-contained program in sasjsbuild/ with no SASAUTOS path, no macro catalogue and no filesystem dependency at run time:

/**
  @file
  @brief Monthly extract
  <h4> SAS Macros </h4>
  @li mf_getuser.sas
  @li mp_jsonout.sas
**/

%put %mf_getuser();
sasjs compile

The @li entries are the compiler’s only dependency source, so a macro that is called but not declared is not inlined - and the job fails at run time with “Apparent invocation of macro X not resolved”. The folders it searches are macroFolders in sasjs/sasjsconfig.json, which is where node_modules/@sasjs/core/base and its siblings belong. There is more in the sasjs compile documentation, and the dependency convention itself is set out in the library README.

Tests and quality rules

The macros are tested with sasjs test and checked with sasjs lint against the repo’s own quality rules. That matters beyond the library itself - it is the same tooling you can point at your own macros, which is how the lint rules and the test harness were hardened in the first place.

Where else it turns up

The same macros ship inside SASjs Server, our open source REST API for Desktop SAS, and they are a dependency of Data Controller for SAS - the SAS data editing tool with a review and approve workflow and a full audit trail. Data Controller pulls the library in as an npm package in its SAS build, so its SAS-side services run on the same macros described here.

The library lives at github.com/sasjs/core. If you have written a macro you think belongs in it, contributions are welcome - the contributing guide sets out the house rules.