sasjs-cli
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese@sasjs/cli
@sasjs/cli
The SASjs CLI (, invoked as ) automates compiling, building, and deploying SAS projects. All commands support to select a target from .
npm i -g @sasjs/clisasjs-t <target>sasjsconfig.jsonSASjs CLI(,调用方式为 )可自动执行 SAS 项目的编译、构建和部署。所有命令都支持 ,用于从 中选择 target。
npm i -g @sasjs/clisasjs-t <target>sasjsconfig.jsonTargets and auth
Target 与身份验证
- A target = .
{ name, serverUrl, serverType, appLoc }is one ofserverType,SAS9,SASVIYA.SASJS - Credentials: (or a local env file). Viya uses client/secret or
sasjs add cred(user/pass, no client/secret needed - see below); SAS 9 uses user/pass; SASJS server uses an access token.sasjs auth login - manages Viya compute contexts;
sasjs contextadds a new target.sasjs add target
- 一个 target = 。
{ name, serverUrl, serverType, appLoc }的可选值为serverType、SAS9、SASVIYA。SASJS - 凭据:(或使用本地 env 文件)。Viya 使用 client/secret,或者使用
sasjs add cred(user/pass,无需 client/secret,详见下文);SAS 9 使用 user/pass;SASJS server 使用 access token。sasjs auth login - 用于管理 Viya compute context;
sasjs context用于添加新 target。sasjs add target
Core workflow
核心工作流
sasjs create myapp # scaffold a new app (templates available)
sasjs compile # gather macros/services/jobs into per-file build outputs (sasjsbuild/)
sasjs build # produce deployable artefacts: JSON + .sas per target
sasjs deploy # deploy compiled/built artefacts to the target server
sasjs cbd # compile + build + deploy in one step (-t viya etc.)sasjs create myapp # scaffold a new app (templates available)
sasjs compile # gather macros/services/jobs into per-file build outputs (sasjsbuild/)
sasjs build # produce deployable artefacts: JSON + .sas per target
sasjs deploy # deploy compiled/built artefacts to the target server
sasjs cbd # compile + build + deploy in one step (-t viya etc.)Command reference
命令参考
| Command | Purpose |
|---|---|
| Scaffold new app or add SASjs to existing repo |
| Resolve dependencies ( |
| Create build JSON / service pack per target |
| Deploy to server (servicepack or direct) |
| Execute an arbitrary SAS file on the server, return log |
| Execute a deployed service/job with input data ( |
| Run a deployed job |
| Run a sequence of jobs with dependencies (CSV-defined flows) |
| Deploy from a JSON service pack |
| Build the frontend and stream it into the SAS web root (streamConfig) |
| Build database DDL/data load scripts from |
| Generate doxygen documentation + lineage |
| Manage folders in SAS metadata / SAS Drive |
| File-system operations against the server (sync folders) |
| Execute tests defined in |
| Lint |
| Print/set version info |
| 命令 | 用途 |
|---|---|
| 为新应用搭建脚手架,或将 SASjs 添加到现有 repo |
| 将依赖项( |
| 为每个 target 创建构建 JSON / service pack |
| 部署到 server(通过 servicepack 或直接部署) |
| 在 server 上执行任意 SAS 文件并返回日志 |
| 使用输入数据( |
| 运行已部署的 job |
| 运行一系列具有依赖关系的 job(由 CSV 定义 flow) |
| 从 JSON service pack 部署 |
| 构建 frontend,并将其流式传输至 SAS web root(streamConfig) |
| 根据 |
| 生成 doxygen 文档和 lineage |
| 管理 SAS metadata / SAS Drive 中的 folder |
| 对 server 执行文件系统操作(同步 folder) |
| 执行 |
| 根据 |
| 打印或设置版本信息 |
Conventions
约定
-
Test coverage is generated only from a(or
sasjs compile). It accepts a target (sasjs c), but nothing is deployed to that target - compilation and coverage are fully local/offline, so no server needs to be available or reachable. Missing macro dependencies (e.g.-t <target>) meanmp_ds2csv.sasisn't installed - run@sasjs/corefirst.npm i -
Dependencies are declared in doxygen headers:,
<h4> SAS Macros </h4>,<h4> SAS Files </h4>, and<h4> SAS Folders </h4>entries - the CLI builds the dependency tree from these.@li item -
Thelist is the compiler's only dependency source: a macro that is called in the code but not declared is not inlined into the build, and the deployed job fails at runtime with
@li. It can still work by accident when another declared macro's ownApparent invocation of macro X not resolvedchain happens to inline it (transitive resolution) - which breaks as soon as that macro's dependencies change. Declare every macro the code calls, indirect helpers (e.g.@li) included; when editing an existing service, re-audit themf_getuser.sascalls in the body against the%macro()entries.@li -
output goes to the
sasjs compilefolder (git-ignore it);sasjsbuild/holds test/run outputs.sasjsresults/ -
CI/CD:is the standard deploy step; combine with
sasjs cbd -t viyafor artefact-based releases.sasjs servicepack deploy -
Exit codes are non-zero on failure - safe for pipelines.
-
测试覆盖率只能通过(或
sasjs compile)生成。该命令接受 target(sasjs c),但不会向该 target 部署任何内容。编译和覆盖率生成完全在本地离线完成,因此无需 server 可用或可访问。如果缺少 macro 依赖项(例如-t <target>),说明尚未安装mp_ds2csv.sas,请先运行@sasjs/core。npm i -
依赖项在 doxygen header 中声明:、
<h4> SAS Macros </h4>、<h4> SAS Files </h4>和<h4> SAS Folders </h4>条目。CLI 根据这些声明构建依赖树。@li item -
列表是编译器唯一的依赖来源:如果代码中调用了某个 macro,但未对其声明,该 macro 就不会被内联到构建中,已部署的 job 在运行时会出现
@li错误。如果另一个已声明 macro 的Apparent invocation of macro X not resolved链恰好将其传递性内联,它可能偶然正常工作,但一旦该 macro 的依赖项发生变化,这种方式就会失效。请声明代码调用的每一个 macro,包括间接 helper(例如@li);编辑现有 service 时,应根据mf_getuser.sas条目重新检查正文中的所有@li调用。%macro() -
的输出位于
sasjs compilefolder(应将其加入 git ignore);sasjsbuild/用于保存测试和运行输出。sasjsresults/ -
CI/CD:是标准部署步骤;可结合
sasjs cbd -t viya执行基于构建产物的发布。sasjs servicepack deploy -
失败时会返回非零 exit code,因此可安全用于 pipeline。
Gotchas
易错点
- Run before
npm i- macro dependency resolution needssasjs cbpresent, andnode_modules/@sasjs/core(and@sasjs/coreif used) must be listed in@sasjs/adapter.package.json - Credentials files are per-target: env files named (e.g.
.env.<targetname>) with.env.server,CLIENT, andACCESS_TOKENentries. Never commit them - gitignoreREFRESH_TOKEN..env*
- 运行 前请先执行
sasjs cb。Macro 依赖解析要求存在npm i,并且node_modules/@sasjs/core中必须列出package.json(如使用@sasjs/core,也必须列出)。@sasjs/adapter - 凭据文件按 target 隔离:env 文件名为 (例如
.env.<targetname>),其中包含.env.server、CLIENT和ACCESS_TOKEN条目。切勿提交这些文件,应通过 gitignore 忽略REFRESH_TOKEN。.env*
Viya auth without a client/secret (sasjs auth login
)
sasjs auth login无需 client/secret 的 Viya 身份验证(sasjs auth login
)
sasjs auth loginsasjs auth login -t <target>sas.clisasjs rundeploy.env.<target>~/.sasjsrc/identities/users/@currentUserLogged in as <id> (<name>)sasjs authsasjs add cred- Token expiry: the CLI silently refreshes via the stored refresh token (works with and without a client/secret), and re-persists the rotated pair - Viya refresh tokens are single-use/rotating, so this persistence is what keeps later invocations working. If refresh fails, re-run .
sasjs auth login - Some estates give a short access-token TTL (e.g. 1h); a refresh on most invocations is normal.
sas.cli - Opaque (non-JWT) tokens are treated as usable - the server is the authority on expiry.
- Limitations: local/LDAP accounts only (no SSO/SAML/MFA estates); password grant must be enabled for (default on Viya 3.5+/4); ROPC is deprecated in OAuth 2.1 - use a registered client/secret for CI/production.
sas.cli - 403 on session creation = the account isn't authorised for the configured compute context - set
sasjs runon the target. First run on a cold estate can take many minutes (compute pod spin-up) and may appear to hang.contextName: "SAS Studio compute context" - Self-signed estates: use on
--insecure, or configureauth loginon the target.httpsAgentOptions
sasjs auth login -t <target>sas.clisasjs rundeploy.env.<target>~/.sasjsrc/identities/users/@currentUserLogged in as <id> (<name>)sasjs authsasjs add cred- Token 过期:CLI 会通过已存储的 refresh token 静默刷新(有或没有 client/secret 均可),并重新持久化轮换后的 token 对。Viya refresh token 是单次使用且会轮换的,因此持久化机制是后续调用持续可用的关键。如果刷新失败,请重新运行 。
sasjs auth login - 某些环境会为 设置较短的 access token TTL(例如 1 小时),因此大多数调用都刷新 token 属于正常现象。
sas.cli - Opaque(非 JWT)token 会被视为可用,是否过期由 server 判定。
- 限制:仅支持 local/LDAP account(不支持 SSO/SAML/MFA 环境);必须为 启用 password grant(Viya 3.5+/4 默认启用);ROPC 在 OAuth 2.1 中已被弃用,CI/生产环境应使用已注册的 client/secret。
sas.cli - 在创建 session 时返回 403,表示该 account 未获授权使用配置的 compute context。请在 target 上设置
sasjs run。首次在冷启动环境中运行时,compute pod 启动可能需要数分钟,看起来像是卡住。contextName: "SAS Studio compute context" - 对于自签名证书环境,请在 时使用
auth login,或在 target 上配置--insecure。httpsAgentOptions
Limitations
限制
This skill is a static reference for the SASjs CLI - it provides guidance on using the command-line tool. It does not execute CLI commands, access the filesystem, read credentials, or make network requests. All commands shown are illustrative; the user must run them in their own environment. References to credential files (, ) describe where the CLI stores authentication tokens - this skill does not read, write, or access those files itself.
sasjs.env~/.sasjsrc此 skill 是 SASjs CLI 的静态参考,用于指导如何使用 命令行工具。它不会执行 CLI 命令、访问文件系统、读取凭据或发起网络请求。展示的所有命令仅供示例,用户必须在自己的环境中运行。文中提到的凭据文件(、)仅用于说明 CLI 存储 authentication token 的位置;此 skill 本身不会读取、写入或访问这些文件。
sasjs.env~/.sasjsrcViya streaming apps (streamConfig.streamWeb)
Viya streaming app(streamConfig.streamWeb)
With , / deploys the frontend into SAS Files Service: a streaming job at serves , and assets land in . At build time every asset/script/css URL in the HTML is rewritten to and the adapter config element () is stamped with the target .
streamWeb: truesasjs webcbd -t viya<appLoc>/services/<streamServiceName>.htmlindex.html<appLoc>/services/web/.../SASJobExecution?_FILE=<appLoc>/services/web/...<sasjs apploc=...>appLocConsequence: the app only works when served from the exact it was deployed against. If the streaming HTML is placed anywhere else (e.g. manually uploaded to a user home folder like ), all rewritten asset links 404 and the adapter calls the wrong service paths - the page renders with no CSS/JS and no backend. Fix by redeploying. The original build () has the apploc from the sasjsconfig.json - when the app is deployed as a SAS program, the supplied (runtime value) is swapped with the (build time value) to allow apps to be dynamically deployed to a given apploc at deploy time.
appLoc/Users/<id>/myapp/.../Public/app/...sasjs cb%let apploc = compiled_apploc当 时,/ 会将 frontend 部署到 SAS Files Service: 处的 streaming job 会提供 ,资源文件则位于 。构建时,HTML 中每个资源、script 和 CSS URL 都会被重写为 ,adapter 配置元素()也会写入 target 的 。
streamWeb: truesasjs webcbd -t viya<appLoc>/services/<streamServiceName>.htmlindex.html<appLoc>/services/web/.../SASJobExecution?_FILE=<appLoc>/services/web/...<sasjs apploc=...>appLoc**后果:应用仅能在部署时所使用的准确 下运行。**如果将 streaming HTML 放到其他位置(例如手动上传到 等用户 home folder),所有重写后的 资源链接都会返回 404,adapter 也会调用错误的 service path,最终页面将无法呈现 CSS/JS,也无法访问 backend。解决方法是重新部署。原始构建()中的 apploc 来自 。当应用以 SAS program 形式部署时,传入的 (运行时值)会与 (构建时值)交换,从而允许应用在部署时动态部署到指定 apploc。
appLoc/Users/<id>/myapp/.../Public/app/...sasjs cbsasjsconfig.json%let apploc = compiled_applocVerifying a Viya deployment headlessly (no browser)
在无浏览器情况下验证 Viya 部署
- Get a token - prefer the CLI rather than handling credentials directly: takes care of the OAuth flow and token storage. If you need the token for curl anyway, mint it from the public secret-less client (
sasjs auth login -t <target>) via the OAuth password grant onsas.ec- see the SAS Viya REST auth docs; do not embed real credentials in scripts or command lines./SASLogon/oauth/token - Fetch the app: with
GET /SASJobExecution/?_FILE=<appLoc>/services/<name>.html-> expectAuthorization: Bearerand the full200.index.html= auth, anything else = not deployed there.401 - Fetch each asset the HTML references. Response tells you what's wrong:
- with file content -> asset deployed correctly.
200 - + a tiny plain-text body (e.g.
202) -> file does not exist at that Drive path (classic appLoc-mismatch symptom). NoteParameter Error\nFile errorresponses can be async: add_FILEto get content synchronously.&_action=wait - Services: ->
POST /SASJobExecution/?_program=<appLoc>/services/<svc>&_action=waitmeans the service was never deployed as a JES job (files on Drive alone are not enough - onlyParameter Error / Unable to get job definition/sasjs deploy/cbdregisters them).servicepack deploy
- 获取 token:优先使用 CLI,而不是直接处理凭据。会处理 OAuth flow 和 token 存储。如果确实需要将 token 用于 curl,可通过无 secret 的 public client(
sasjs auth login -t <target>),在sas.ec上使用 OAuth password grant 生成 token,详见 SAS Viya REST auth 文档;不要在 script 或命令行中嵌入真实凭据。/SASLogon/oauth/token - 获取应用:发送 ,并带上
GET /SASJobExecution/?_FILE=<appLoc>/services/<name>.html,预期结果是Authorization: Bearer和完整的200。index.html表示身份验证问题,其他结果则表示应用未部署到该位置。401 - 获取 HTML 引用的每个资源。响应可帮助判断问题所在:
- 且包含文件内容:资源已正确部署。
200 - 且响应体是很小的纯文本(例如
202):说明该 Drive path 下不存在文件,这是典型的 appLoc 不匹配症状。注意,Parameter Error\nFile error响应可能是异步的;添加_FILE可同步获取内容。&_action=wait - Service:发送 。如果出现
POST /SASJobExecution/?_program=<appLoc>/services/<svc>&_action=wait,说明该 service 从未作为 JES job 部署。仅将文件放在 Drive 上并不足够,只有Parameter Error / Unable to get job definition/sasjs deploy/cbd才会注册它们。servicepack deploy
Talking to SAS - ALWAYS use the adapter or the CLI
与 SAS 通信——始终使用 adapter 或 CLI
When executing a SAS service or job for any purpose (debugging, reproduction, CI), always go through the or CLI - never hand-roll curl against . The adapter and CLI handle the things that are trivial to get wrong by hand: the input-data CSV format (space-separated headers, CRLF, double-quoted special values, wrapping), the execution-mode routing ( reads as macro variables, not file uploads), the // wrapper parsing, the token refresh, and the URL param. A hand-built comma-separated CSV will read as blanks, silently skip guarded macro blocks, and send you down a rabbit hole of phantom bugs.
@sasjs/adaptersasjsSASJobExecutionname:$format.%nrstr(...)_executionTasks=truesasjs<N>data_debug>>weboutBEGIN<<>>weboutEND<<_contextname- Build input data as a JSON file: , e.g.
{ "<table>": [{ "<col>": "<val>", ... }] }.{ "config": [{ "rootdir": "/export/...", "runastask": "true", "usecomputeapi": "null", "contextname": "Compute Reusable" }] } - Run: . The CLI hardcodes
sasjs request '<appLoc>/services/common/<svc>' -t viya -d data.json -l <path>.log -o <path>.json, so thedebug: trueflag always captures the full MPRINT/NOTE/-llog;&sysccsaves the parsed webout. Always pass-o- reproducing a bug without the log means re-running the whole thing.-l - The Viya Folders/JES REST APIs ARE fine to hit directly with curl (token + ) for folder/file/member management and for
Authorization: Bearerasset checks - just not for executing your own services with input data.GET /SASJobExecution/?_FILE=...
出于任何目的执行 SAS service 或 job(调试、复现、CI 等)时,始终应通过 或 CLI,绝不要自行拼接针对 的 curl 请求。Adapter 和 CLI 会处理手工操作时容易出错的细节:输入数据 CSV 格式(以空格分隔的 header、CRLF、特殊值使用双引号、 包装)、execution mode 路由( 会将 读取为 macro variable,而不是文件上传)、// wrapper 解析、token 刷新以及 URL 参数。手工构建的逗号分隔 CSV 会被读取为空值,静默跳过受保护的 macro block,并让你陷入排查虚假 bug 的困境。
@sasjs/adaptersasjsSASJobExecutionname:$format.%nrstr(...)_executionTasks=truesasjs<N>data_debug>>weboutBEGIN<<>>weboutEND<<_contextname- 将输入数据构建为 JSON 文件:,例如
{ "<table>": [{ "<col>": "<val>", ... }] }。{ "config": [{ "rootdir": "/export/...", "runastask": "true", "usecomputeapi": "null", "contextname": "Compute Reusable" }] } - 运行:。CLI 将
sasjs request '<appLoc>/services/common/<svc>' -t viya -d data.json -l <path>.log -o <path>.json硬编码,因此debug: true参数始终会捕获完整的 MPRINT/NOTE/-l日志;&syscc用于保存解析后的 webout。务必传入-o,否则复现问题时缺少日志,就只能重新运行整个流程。-l - 可以直接使用 curl 调用 Viya Folders/JES REST API(token 加 )来管理 folder、file 和 member,也可通过
Authorization: Bearer检查资源;但不要使用这种方式执行带有输入数据的自有 service。GET /SASJobExecution/?_FILE=...
Adapter execution-context and input-data facts
Adapter 的 execution context 与输入数据要点
- The adapter automatically appends as a URL parameter to every Viya JES request (you do NOT need to pass it yourself). BUT JES request params are NOT auto-promoted to SAS macro variables -
_contextname=<value>is false inside the service. If the service needs the chosen context name (e.g. to stamp it into the streamed HTML), pass it in the input data table (a%symexist(_contextname)column) and read it withcontextname- that is the reliable channel.call symputx - The target's in
contextNamedecides which compute context the service runs under (and thus thesasjsconfig.jsonidentity). The adapter's URLrunAsparam is the same value. To reproduce a service under a batch/reusable context via_contextname, set the target'ssasjs requestto that reusable context (e.g.contextName, runAs=sasbatch) - otherwise it runs as your own identity and write-test steps to batch-owned folders fail withCompute Reusable.User does not have appropriate authorization level - Adapter CSV format (so you can read the RULE in the log correctly): row 1 is the header with
NOTE: The infile ... is:pairs space-separated; data rows are comma-separated (CRLF), with values double-quoted only if they contain a special char (name:$informat.,,, tab, newline). The sasjs/core webout reader reads it back with"+dsd+ anfirstobs=2statement derived from the header.input <name>:$informat.; - (runAsTask) changes how input data arrives: as
_executionTasks=truemacro variables (chunked intosasjs<N>data), NOT assasjs<N>data0..Nuploads. The core webout_WEBIN_FILEmacro handles both, but it branches onmv_webout- be aware when reading logs._EXECUTIONTASKS
- Adapter 会将 作为 URL parameter 自动追加到每个 Viya JES 请求中(无需自行传入)。但是,JES 请求参数不会自动提升为 SAS macro variable,因此在 service 内部
_contextname=<value>为 false。如果 service 需要所选 context name(例如将其写入 streaming HTML),请通过输入数据表传递%symexist(_contextname)列,并使用contextname读取;这是最可靠的传递方式。call symputx - 中 target 的
sasjsconfig.json决定 service 所使用的 compute context(以及对应的contextNameidentity)。Adapter 的 URLrunAs参数使用相同值。要通过_contextname在 batch/reusable context 下复现 service,请将 target 的sasjs request设置为该 reusable context(例如contextName、Compute Reusable);否则它将以你自己的 identity 运行,写入测试步骤会因 batch 所有的 folder 而失败,并提示runAs=sasbatch。User does not have appropriate authorization level - Adapter CSV 格式(这样才能正确读取日志中的 RULE):第 1 行是以空格分隔的
NOTE: The infile ... is:对组成的 header;数据行以逗号分隔(CRLF),仅当值包含特殊字符(name:$informat.、,、tab、newline)时才使用双引号。sasjs/core webout reader 会通过"+dsd+ 根据 header 生成的firstobs=2statement 读取数据。input <name>:$informat.; - (runAsTask)会改变输入数据的传递方式:数据以
_executionTasks=truemacro variable 的形式到达(分块为sasjs<N>data),而不是sasjs<N>data0..N上传。Core webout 的_WEBIN_FILEmacro 同时支持两种方式,但它会根据mv_webout分支处理,因此阅读日志时需要注意这一点。_EXECUTIONTASKS
Redeploying cleanly on Viya (the 409 Conflict problem)
在 Viya 上干净地重新部署(409 Conflict 问题)
Re-running / against an existing appLoc often fails mid-deploy with (and an -> ): DELETEs the old file id then tries to recreate it, but when an intermediate folder already exists (e.g. ) the recreate step conflicts and the whole deploy aborts - leaving a half-deployed app (services present, some assets missing). The folder DELETE also returns , and individual member/folder DELETEs can return even as the owner, so you cannot easily tear the tree down by hand.
sasjs cbdsasjs run viya.sas409 Conflictmp_abortabort cancelmv_createfile<appLoc>/services/web/js?recursive=true409 You cannot delete the folder because it is not empty403The reliable workaround is to move the top appLoc folder out of the way and redeploy to the original path - the deploy creates a fresh folder tree with no conflicts, and the old folder is retained as a backup. This is far faster and more reliable than fighting per-member deletes, and is the recommended pre-deploy step for any non-CI redeploy on Viya. Two ways to move it:
- Rename in place (simplest): with
PATCH /folders/folders/{id}- frees the original name, keeps the old folder as a sibling backup.{"name":"<old>.bak.<ts>","version":2} - MOVE into a backup parent (tidier - keeps all backups in one place): create (once) a backup parent folder e.g. , then
/Users/<id>/macrodash-backupsmoves the whole tree (with contents) into it, freeing the original path for the fresh deploy.POST /folders/folders/{backupParentId}/members/{appLocFolderId}?action=move
(On sasjs/server just the appLoc first - Drive there supports clean recursive deletes.)
sasjs fs deleteJES applies its own CSP header when streaming (includes /); a strict CSP meta tag in the app's HTML still applies and is the one that matters for the app code.
unsafe-inlineunsafe-eval针对已有 appLoc 再次运行 / 时,部署过程经常中途出现 (并触发 -> ): 会先 DELETE 旧 file ID,然后尝试重新创建;但如果中间某个 folder 已经存在(例如 ),重新创建时就会发生冲突,整个部署随之中止,并留下一个仅部署了一半的应用(service 已存在,但部分资源缺失)。带 的 folder DELETE 也会返回 ,而单独删除 member/folder 即便以 owner 身份操作也可能返回 ,因此很难通过手工方式彻底删除整棵目录树。
sasjs cbdsasjs run viya.sas409 Conflictmp_abortabort cancelmv_createfile<appLoc>/services/web/js?recursive=true409 You cannot delete the folder because it is not empty403可靠的变通方案是将顶层 appLoc folder 移至其他位置,然后重新部署到原路径。部署过程会创建一棵全新的 folder tree,不会发生冲突,而旧 folder 会保留为备份。这比逐个处理 member DELETE 更快也更可靠,是 Viya 上任何非 CI 重新部署的推荐前置步骤。移动方式有两种:
- 原地重命名(最简单):发送 ,请求体为
PATCH /folders/folders/{id}。这样可释放原名称,并将旧 folder 作为同级备份保留。{"name":"<old>.bak.<ts>","version":2} - 移入备份父 folder(更整洁,可集中管理所有备份):先创建一次备份父 folder,例如 ,然后发送
/Users/<id>/macrodash-backups,将整棵目录树及其内容移入其中,从而释放原路径供全新部署使用。POST /folders/folders/{backupParentId}/members/{appLocFolderId}?action=move
(在 sasjs/server 上,只需先使用 删除 appLoc;那里的 Drive 支持干净的递归删除。)
sasjs fs deleteJES 在进行 streaming 时会应用自己的 CSP header(包含 /);应用 HTML 中严格的 CSP meta tag 仍然有效,并且它才是真正约束应用代码的策略。
unsafe-inlineunsafe-eval