关于 sasjs-server
SASjs Server 是用于调用 SAS 可执行程序的开源 Node.js 封装,可在 SAS 服务器或本地桌面运行。它提供文件存储、URL 作业执行、Web 应用流式传输和 REST API,面向部署及开发 SAS 应用的团队。
主要功能
- 01存储 SAS 程序与内容的文件系统
- 02通过 URL 执行存储程序
- 03从 SAS 内容提供 Web 应用
- 04提供带 Swagger 文档的 REST API
- 05支持桌面与多用户服务器模式
适用场景
- 01在本地运行 SAS 程序与开发环境
- 02通过 HTTP 接口执行已部署作业
- 03从 SAS 内容目录提供前端应用
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sasjs/ skills --skill sasjs-server安装后在 Claude Code 中输入/sasjs-server确认已加载。
详细介绍
@sasjs/server
SASjs Server 是一个开源 NodeJS 封装程序,用于调用 SAS 二进制可执行文件。它可在真实 SAS 服务或本地桌面上运行,并提供:
- 用于存储 SAS 程序和内容的文件系统(SASjs Drive)
- 通过 URL 执行存储程序(相当于 SAS 9 Stored Processes / Viya Jobs)
- Web 应用流式传输(直接从 SAS 内容提供前端应用)
- 带有 Swagger 文档的 REST API
- 可移植性:使用 @sasjs/cli 构建的 SASjs Server 应用可直接部署到 SAS 9 / Viya,无需更改
模式
- 桌面模式(
MODE=desktop,默认):单用户、无身份验证、无数据库。默认启用 CORS。 - 服务模式(
MODE=server):多用户,启用身份验证,需要数据库(DB_CONNECT、DB_TYPE=mongodb|cosmos_mongodb)。默认禁用 CORS——如需启用,请配置WHITELIST。
安装
从 GitHub releases 下载相应的 zip,运行前请验证:固定到特定发布标签(不要使用 latest),检查已发布的 SHA256 校验和;或者更好地,从源代码构建。
curl -L https://github.com/sasjs/server/releases/download/R/<asset>.zip > <asset>.zip # replace R with the pinned release tag
sha256sum <asset>.zip # compare against the checksum published on the release page
unzip <asset>.zip && ./api-linux
[通过 Curl-pipe-bash 下载以及盲目下载 latest 都会带来供应链风险。固定标签并验证校验和也能让基础设施可复现。]
首次运行时,程序会提示输入 SAS 可执行文件路径以及存储程序/临时文件的文件系统位置(除非已通过环境变量设置)。也支持 Docker(仓库中的 DockerfileApi、docker-compose 文件)。
通过环境变量配置
在 /etc/environment 中设置、导出、添加到命令前缀,或放入可执行文件旁的 .env 文件中。主要变量:
| 变量 | 用途 |
|---|---|
MODE | desktop(默认)或 server |
SAS_PATH | sas.exe / sas.sh 的路径 |
RUN_TIMES | 以逗号分隔的运行时优先级,例如 sas,js,py——选项:sas、js、py、r。每种运行时都需要设置相应路径:SAS_PATH、NODE_PATH、PYTHON_PATH、R_PATH |
SASJS_ROOT | 工作目录:SAS WORK、暂存文件、drive、配置 |
DRIVE_LOCATION | 存放文件、sasjs 包、appStreamConfig.json 的位置 |
PROTOCOL / PORT | http(默认)或 https(需要 PRIVATE_KEY、CERT_CHAIN,可选 CA_ROOT);默认端口为 5000 |
SAS_OPTIONS / SASV9_OPTIONS | 自动应用于会话的额外 SAS 系统选项(Windows 与 Unix 不同),例如 -NOXCMD |
DB_CONNECT / DB_TYPE | MongoDB 连接字符串/类型——服务模式必需 |
AUTH_PROVIDERS + LDAP_* | LDAP 身份验证:LDAP_URL、LDAP_BIND_DN、LDAP_BIND_PASSWORD、LDAP_USERS_BASE_DN、LDAP_GROUPS_BASE_DN |
CORS / WHITELIST | 仅当 CORS=enable 时才会应用 CORS,且只有 WHITELIST 中的来源(以空格分隔)才会收到 Access-Control-Allow-Origin——白名单为空时,跨源调用一律无法使用 |
MOCK_SERVERTYPE / STATIC_MOCK_LOCATION | 为前端测试模拟针对 sasjs server 的 sas9/sasviya API 响应(仅提供静态预置文件,不含逻辑) |
针对 API 进行开发
- @sasjs/adapter / CLI 目标的服务类型为
SASJS(serverType: 'SASJS');身份验证基于令牌。 - REST API 通过运行实例上的 Swagger 自动提供文档。
- 服务端执行使用 @sasjs/core 中的
ms_*宏(例如ms_createfile、ms_adduser2group)——通过 CLI 部署的服务/作业在其他平台上也能正常运行。 - 仓库布局(供贡献者参考):
api/(Express/TypeScript 后端:控制器、路由、中间件、模型)、web/(前端)、restClient/(REST 示例)、mongo-seed/(服务模式数据库种子)。
使用 JS 运行时模拟服务(无需 SAS)
使用 RUN_TIMES=js(并设置 NODE_PATH)时,SASjs Drive 上的任何 .js 文件都可作为可执行存储程序——react-seed-app / Data Controller 通过此方式为前端开发提供模拟后端。**按设计,这会在服务端完整执行代码。**请将 JS 运行时视为权限边界:
- 只应在受信任的本地/桌面环境中启用
js(不得采用多租户模式或公开暴露) - 仅允许受信任的作者写入/上传 Drive;认证提供方(
AUTH_PROVIDERS、LDAP)和仅桌面模式(MODE=desktop,默认)是安全保障 - 除非已严格限制 Drive 认证和上传,否则不要在多用户生产服务器上启用
js运行时
桌面模式(MODE=desktop)没有认证,因此可以轻松进行本地模拟——也正因为没有认证,默认的 JS 运行时信任假设才在此模式下成立。
编写 JS 存储程序(文档:https://server.sasjs.io/storedprograms/#js-programs):
- 运行时模板会预先声明
const fs = require('fs')、_program、weboutPath、_SASJS_TOKENFILE、_SASJS_WEBOUT_HEADERS、_SASJS_USERNAME/_SASJS_USERID/_SASJS_DISPLAYNAME、_METAPERSON、_METAUSER、SASJSPROCESSMODE。不要重新声明fs——在程序中使用const fs = require('fs')会导致程序崩溃,并报错Identifier 'fs' has already been declared。 - 输出:将 JSON 字符串赋给
_webout(例如_webout = JSON.stringify({...}));仅当其非空时才会写回。console.log()的输出会作为响应中的log返回(类似 SAS 日志)。自定义响应标头可逐行写入_SASJS_WEBOUT_HEADERS文件。 - 模拟真实服务时,请在 JSON 中包含标准 SASjs 自动字段:
_PROGRAM(取自_program)、SYSDATE/SYSTIME(格式为DDMMMYY/HH:mm)、_METAUSER、SASJSPROCESSMODE。 - URL/请求体参数会以
const <name> = \`` 字符串的形式传入。 - 输入表(
sasjs_tables机制)会以两种形式传入:内联 CSV const,或者——当适配器发送 multipart 时——作为上传到会话文件夹中的<name>.csv文件,并由生成的模块作用域 const 引用(两种情况都要处理):_WEBIN_FILE_COUNT(始终会创建)、_WEBIN_NAME<n>(表/字段名称)、_WEBIN_FILENAME<n>(原始文件名)、_WEBIN_FILEREF<n>(文件内容,是fs.readFileSync返回的 Buffer——请调用.toString('utf8'))- 这些 const 不在
globalThis上——应通过this['+name+']读取(尽可能避免动态代码求值;对任何受攻击者影响内容上的动态代码求值都应保持警惕),或在模块作用域使用typeof守卫(服务端 JS,无 CSP) - 适配器 CSV 的特殊情况:表头行是以空格分隔的
name:format.条目(例如rootdir:$char256.)——请去掉:format后缀;行以 CRLF 结尾;包含特殊字符的值会用双引号括起,并用""转义
- 适配器响应结构:
sasjs.request()会解析为已解包的 webout JSON——输出表会直接作为行对象数组出现在响应中(res.mytable[0].COL)。表名为result完全没问题(此时res.result就是该数组);不要自行添加res.result解包层,否则恰好会破坏这种情况。 - 第三方 npm 包在运行时无法解析——请先打包服务(例如
npx webpack --mode none --target node --entry <file> --output-path sasjsbuild/... --output-filename <name>.js),然后运行sasjs build/sasjs deploy。
部署模拟程序:
sasjs fs sync在纯 JS 服务器上不起作用(它会生成并运行 SAS 代码来计算远程文件的哈希值)。请改用 Drive API 直接上传文件:先DELETE,再调用POST /SASjsApi/drive/file?_filePath=<appLoc>/services/<folder>/<name>.js(使用 multipartfile字段)。桌面模式下不需要身份验证标头;服务器模式下,从_SASJS_TOKENFILE读取Authorization标头行(这是主机本地的身份验证材料——不要记录它,并且仅在确实需要调用者身份的服务中读取)。- 模拟对象可以使用预先声明的
fs维护状态。优先使用真实路径,而不是/tmp:SASjs Drive 根目录可由weboutPath推导得出(<root>/sessions/<id>/webout.txt->path.resolve(weboutPath, '..', '..', '..', 'drive'));模拟的configure类服务可以将已配置的文件夹视为真实本地路径(服务器本身就是本地的)。require('path')和其他核心模块均可使用(只有fs是预先声明的)。 - JS 程序甚至可以调用服务器自身的 REST API(
http://127.0.0.1:$PORT/SASjsApi/...),例如通过GET和PATCH /SASjsApi/drive/file改写 Drive 上流式传输的index.html。
注意事项:
- 打包的二进制文件(
api-linux等)会拒绝某些全局导出的NODE_OPTIONS(例如--network-family-autoselection)——请使用NODE_OPTIONS="" ./api-linux启动。 - AppStream URL 会重定向到以斜杠结尾的地址(
/AppStream/MyApp-> 301 ->/AppStream/MyApp/)——测试和自动化脚本应直接使用带结尾斜杠的 URL。
限制
此技能是 SASjs Server 的静态参考资料,提供安装、配置和运行服务器的指导。它不会执行代码、运行 shell 命令、访问文件系统、连接数据库或发起网络请求。对环境变量、身份验证令牌和服务器配置的引用,描述的是服务器软件在运行时使用的内容——此技能本身不会读取、写入或访问这些值。“执行”“运行时”和“进程”等术语指的是 SASjs Server 软件的行为,而不是此技能执行的操作。