Files
dc/.agents/skills/sasjs-framework/SKILL.md
T
hermes f7db8719f5
Build / Build-and-ng-test (pull_request) Successful in 5m8s
Lighthouse Checks / lighthouse (pull_request) Successful in 21m24s
Build / Build-and-test-development (pull_request) Successful in 25m20s
fix: agent skills and nextviya deploys
2026-08-19 17:17:30 +01:00

103 lines
6.4 KiB
Markdown

---
name: sasjs-framework
description: Building full SASjs applications — project structure, sasjsconfig.json, services/jobs/macros folders, multi-target (SAS 9 / Viya / SASjs server) configuration, streaming frontends, mocks and tests. Use when creating or modifying a SASjs app, editing sasjsconfig.json, or writing backend services returning JSON to a web frontend.
---
# SASjs Framework — Building SASjs Applications
A SASjs app = a web frontend (any framework: Angular, React, vanilla) + SAS backend code organised in a standard layout, compiled and deployed by `@sasjs/cli` to SAS 9, Viya, or SASjs server. Frontend talks to SAS via `@sasjs/adapter`; backend services return JSON via `_webout`.
## Standard project layout
```
sasjs/
sasjsconfig.json # project + target configuration
macros/ # project-specific macros (macroFolders)
services/ # web services called from the frontend
jobs/ # jobs (scheduled / flow / long-running)
programs/ # plain programs (initProgram, termProgram, utilities)
db/ # DDL + static data per library (sasjs db)
tests/ # tests run by `sasjs test`
mocks/ # mock responses for offline frontend dev (syncFolder)
doxy/ # extra doxygen content for `sasjs doc`
```
## sasjsconfig.json
Root config holds defaults; each entry in `targets[]` can override them. Key sections:
- `macroFolders`, `binaryFolders` — where the CLI finds macros/binaries
- `serviceConfig.serviceFolders` — service source folders; `initProgram` runs before every service (set up libnames, options)
- `jobConfig.jobFolders` — job source folders
- `programFolders` — programs compiled/deployed with the app
- `streamConfig` — `streamWeb: true` streams the built frontend into SAS so it is served by the platform itself (no separate web server needed); `webSourcePath` points at the frontend build output
- `syncFolder` — folder synced to the server (e.g. mocks)
- `testConfig` — init/term programs for `sasjs test`
- `targets[]` — per-environment overrides: `serverUrl`, `serverType` (`SAS9`/`SASVIYA`/`SASJS`), `appLoc` (deploy root, e.g. `/Public/app/myapp`), target-specific macroFolders (e.g. `targets/viya/macros_viya` for platform shims), `httpsAgentOptions`, `deployConfig`
The full JSON schema is bundled at `sasjsconfig-schema.json` next to this file — validate config changes against it. Reference it with `"$schema": "https://cli.sasjs.io/sasjsconfig-schema.json"`.
## Streamed frontend files on Viya (mime types)
When `streamWeb: true`, the CLI uploads the frontend (`index.html`, renamed per `streamServiceName`, plus css/js) to the Viya Files service using the `%mv_createfile` macro. That macro creates the file in a very particular way to ensure it streams correctly:
- POSTs to `/files/files` with the content type derived from the extension (`%mf_mimetype`)
- sets `typeDefName=file_html` (via `%mv_getViyaFileExtParms`) so the file is recognised as HTML
- sends `Content-Disposition` **without** `attachment` for HTML/SVG so it renders in the browser
**Never update a streamed frontend file in place** with a `filename filesrvc` fileref + data step rewrite — the Files service then treats it as a generic blob and the mime type is lost, so the app no longer streams (browser downloads it or shows raw text). To modify a streamed file at runtime (eg patching the compute `contextname` in the html), read it (a `filesrvc` fileref is fine for *reading*), write the modified content to a temp fileref, and **re-create the file with `%mv_createfile(path=..., name=..., inref=...)`** (it deletes the old file and re-POSTs with the correct mime type).
## Service contract (frontend ↔ SAS)
1. Adapter POSTs to `services/<folder>/<name>` with input tables (arrays of objects) → work datasets named after the JS keys.
2. Service SAS code runs after `initProgram`; it reads inputs, does work, and writes output JSON to `_webout`.
3. Conventional pattern using @sasjs/core macros:
```sas
/**
@file
@brief Example service returning data
<h4> SAS Macros </h4>
@li mp_jsonout.sas
@li mp_abort.sas
**/
/* validation / logic here */
%mp_jsonout(OPEN)
%mp_jsonout(OBJ,results,dslabel=results)
%mp_jsonout(CLOSE)
```
4. On error, abort cleanly with `%mp_abort(...)` (`mf_abort` is deprecated) so the adapter receives a structured error in the JSON, not a half-written response. Do **not** call `%mp_abort` inside an `%if/%else` block — the macro processor may keep executing beyond the abort. Use the conditional `iftrue=` parameter instead, e.g.:
```sas
%mp_abort(iftrue= (%mf_existds(work.results)=0)
,mac=&_program
,msg=%str(No results found)
)
```
If the abort happens inside a `%include` block, SAS cannot exit to `_webout` cleanly — after the include, call `%mp_abort(mode=INCLUDE)` (outside any macro wrapper), which checks `work.mp_abort_errds` for an abort status.
## Multi-target discipline
- Keep backend code platform-neutral in shared folders; put platform-specific shims in `targets/<name>/macros_*` folders and register them only on that target.
- Platform capability macros exist in @sasjs/core (`mm_*` metadata, `mv_*` Viya, `ms_*` server) — don't branch on server type by hand.
## Quality gates (follow the conventions of mature apps like Data Controller)
- Run `sasjs lint` after touching any `.sas` file; fix all warnings in files you touched.
- The linter enforces 2-space indentation everywhere, including continuation lines inside `/* ... */` block comments — never align comment text with 3+ spaces.
- Add tests and run `sasjs test` for backend logic changes. When testing macros, always wrap the macro under test with `%mp_assertscope(SNAPSHOT)` / `%mp_assertscope(COMPARE, ...)` to catch macro-variable scope leakage, and wrap any platform-branching code in `%macro` wrappers (no open conditional macro code in test programs).
- Provide mocks in `sasjs/mocks` so the frontend can be developed without a live SAS server.
- Never auto-commit or bump versions; releases are pipeline-driven (conventional commits).
- Markdown files: no hard wrapping — one paragraph per line.
- Apps must work offline/on-prem: no external CDN assets in the frontend bundle.
## Reference implementations
Look at existing apps for patterns: folder layouts, `sasjsconfig.json` multi-target setups, service structure, streaming builds, and test/mock conventions, eg:
* https://git.datacontroller.io/dc/dc
* https://github.com/sasjs/react-seed-app
* https://github.com/sasjs/macro-dash