dataiku-sdk 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/README.md +246 -19
  2. package/dist/build-metadata.json +1 -1
  3. package/dist/packages/types/src/index.d.ts +39 -4
  4. package/dist/packages/types/src/index.js +31 -2
  5. package/dist/src/auth.js +1 -1
  6. package/dist/src/cli/coerce.js +11 -2
  7. package/dist/src/cli/commands/analysis.js +4 -3
  8. package/dist/src/cli/commands/api-service.js +66 -18
  9. package/dist/src/cli/commands/app.js +4 -3
  10. package/dist/src/cli/commands/bundle.js +51 -16
  11. package/dist/src/cli/commands/code-env.js +219 -57
  12. package/dist/src/cli/commands/code.d.ts +19 -0
  13. package/dist/src/cli/commands/code.js +87 -15
  14. package/dist/src/cli/commands/dashboard.js +7 -6
  15. package/dist/src/cli/commands/data-quality.js +9 -8
  16. package/dist/src/cli/commands/dataset.js +17 -11
  17. package/dist/src/cli/commands/doctor.js +4 -2
  18. package/dist/src/cli/commands/flow-zone.js +42 -13
  19. package/dist/src/cli/commands/folder.js +9 -8
  20. package/dist/src/cli/commands/future.js +2 -1
  21. package/dist/src/cli/commands/insight.js +8 -7
  22. package/dist/src/cli/commands/job.js +4 -3
  23. package/dist/src/cli/commands/meaning.js +5 -4
  24. package/dist/src/cli/commands/ml-task.js +3 -2
  25. package/dist/src/cli/commands/model-evaluation-store.js +4 -3
  26. package/dist/src/cli/commands/notebook.js +82 -50
  27. package/dist/src/cli/commands/project-git.js +8 -5
  28. package/dist/src/cli/commands/project-library.d.ts +21 -0
  29. package/dist/src/cli/commands/project-library.js +128 -56
  30. package/dist/src/cli/commands/project.js +19 -4
  31. package/dist/src/cli/commands/recipe.js +51 -25
  32. package/dist/src/cli/commands/saved-model.js +4 -3
  33. package/dist/src/cli/commands/scenario.js +9 -8
  34. package/dist/src/cli/commands/sql.d.ts +10 -0
  35. package/dist/src/cli/commands/sql.js +42 -19
  36. package/dist/src/cli/commands/statistics.js +7 -6
  37. package/dist/src/cli/commands/variable.js +2 -1
  38. package/dist/src/cli/commands/webapp.js +68 -13
  39. package/dist/src/cli/commands/wiki.js +7 -6
  40. package/dist/src/cli/contract.d.ts +16 -1
  41. package/dist/src/cli/contract.js +967 -186
  42. package/dist/src/cli/env.d.ts +9 -0
  43. package/dist/src/cli/env.js +20 -2
  44. package/dist/src/cli/flags.d.ts +4 -0
  45. package/dist/src/cli/flags.js +29 -1
  46. package/dist/src/cli/helpers/cleanup.js +104 -3
  47. package/dist/src/cli/helpers/flow-zone.d.ts +3 -0
  48. package/dist/src/cli/helpers/flow-zone.js +33 -3
  49. package/dist/src/cli/helpers/recipe.d.ts +20 -0
  50. package/dist/src/cli/helpers/recipe.js +158 -3
  51. package/dist/src/cli/output.d.ts +2 -0
  52. package/dist/src/cli/output.js +33 -6
  53. package/dist/src/cli/runtime.d.ts +35 -1
  54. package/dist/src/cli/runtime.js +125 -18
  55. package/dist/src/cli/types.d.ts +7 -0
  56. package/dist/src/cli.js +226 -95
  57. package/dist/src/client.d.ts +63 -1
  58. package/dist/src/client.js +305 -53
  59. package/dist/src/errors.d.ts +8 -2
  60. package/dist/src/errors.js +42 -0
  61. package/dist/src/index.d.ts +4 -3
  62. package/dist/src/index.js +2 -1
  63. package/dist/src/resources/api-services.d.ts +48 -6
  64. package/dist/src/resources/api-services.js +54 -8
  65. package/dist/src/resources/bundles.d.ts +51 -6
  66. package/dist/src/resources/bundles.js +39 -9
  67. package/dist/src/resources/code-envs.d.ts +25 -3
  68. package/dist/src/resources/code-envs.js +104 -2
  69. package/dist/src/resources/datasets.d.ts +20 -0
  70. package/dist/src/resources/datasets.js +232 -52
  71. package/dist/src/resources/folders.js +2 -1
  72. package/dist/src/resources/jobs.d.ts +35 -10
  73. package/dist/src/resources/jobs.js +92 -17
  74. package/dist/src/resources/notebooks.d.ts +77 -7
  75. package/dist/src/resources/notebooks.js +143 -19
  76. package/dist/src/resources/project-git.d.ts +12 -0
  77. package/dist/src/resources/project-git.js +39 -8
  78. package/dist/src/resources/project-library.d.ts +122 -7
  79. package/dist/src/resources/project-library.js +494 -25
  80. package/dist/src/resources/projects.d.ts +5 -4
  81. package/dist/src/resources/projects.js +21 -19
  82. package/dist/src/resources/scenarios.d.ts +30 -0
  83. package/dist/src/resources/scenarios.js +73 -27
  84. package/dist/src/resources/sql.d.ts +6 -0
  85. package/dist/src/resources/sql.js +23 -3
  86. package/dist/src/resources/webapps.d.ts +35 -4
  87. package/dist/src/resources/webapps.js +54 -5
  88. package/dist/src/schemas.d.ts +2 -2
  89. package/dist/src/schemas.js +1 -1
  90. package/dist/src/skill.d.ts +18 -0
  91. package/dist/src/skill.js +93 -9
  92. package/dist/src/utils/flow-analysis.d.ts +53 -0
  93. package/dist/src/utils/flow-analysis.js +382 -0
  94. package/dist/src/utils/project-archive.d.ts +41 -2
  95. package/dist/src/utils/project-archive.js +159 -16
  96. package/dist/src/utils/response-file.d.ts +2 -0
  97. package/dist/src/utils/response-file.js +34 -0
  98. package/package.json +9 -7
  99. package/packages/types/dist/index.d.ts +39 -4
  100. package/packages/types/dist/index.js +31 -2
  101. package/plugin.json +1 -1
  102. package/skills/dataiku-dss/SKILL.md +44 -197
  103. package/skills/dataiku-dss/references/app-releases.md +27 -0
  104. package/skills/dataiku-dss/references/authentication.md +39 -0
  105. package/skills/dataiku-dss/references/coding.md +8 -0
  106. package/skills/dataiku-dss/references/discovery.md +30 -0
  107. package/skills/dataiku-dss/references/flow-maps.md +12 -0
  108. package/skills/dataiku-dss/references/mutations.md +33 -0
  109. package/skills/dataiku-dss/references/troubleshooting.md +29 -0
package/README.md CHANGED
@@ -23,33 +23,118 @@ Bun is the only supported runtime and the package manager. Examples below assume
23
23
  `--no-env-file` disables Bun's automatic preloading only; the CLI still applies its documented `.env` handling unless `DATAIKU_DISABLE_ENV=1` is set.
24
24
  `dss version` reports whether the running code came from `source` or `dist`, the runtime (always `bun`), the packaged build revision when available, and `staleBuild` when that revision differs from the checkout. Release builds generate `dist/build-metadata.json`; source snapshots without Git metadata still build but report no build revision.
25
25
 
26
- ## CLI contract
26
+ ## Self-provisioning live tests
27
+
28
+ From a checkout, `test:live` is a separate Bun script, not a `dss` command. It reads
29
+ the existing `.env` without changing it and needs project-creation access plus a
30
+ writable managed storage connection. No imported tutorials are required.
31
+
32
+ ```sh
33
+ bun run test:live setup
34
+ bun run test:live run --case core.dataset.baseline
35
+ bun run test:live run --case "core.recipe.*"
36
+ bun run test:live run # all core cases + migrated integration suites
37
+ bun run test:live run --profile ml --case "ml.*"
38
+ bun run test:live status
39
+ bun run test:live clean # delete only this lab, including its root project
40
+ # CI: setup + run + cleanup, even when cases fail
41
+ bun run test:live all
42
+ ```
43
+
44
+ `setup` is idempotent for a ready lab; `run` reuses its datasets, graph and collaboration
45
+ fixtures. Cases use temporary resources or restore baseline values. Cases accept exact
46
+ IDs, comma-separated lists, repeated `--case`, and trailing-prefix `*` matching; quote
47
+ wildcards. Selected runs omit the legacy suites. Unknown, setup-only or inactive-profile
48
+ or empty selections fail before credentials, state creation or provisioning; `--case` is valid only
49
+ for `run`/`all`. `run` refuses
50
+ an incomplete or cleaned lab rather than silently rebuilding it. Clean failed setup
51
+ before provisioning a replacement. Authentication and transport failures retain their
52
+ original errors; they are not evidence that the lab is missing.
53
+
54
+ Core fixtures include deterministic CSVs with nulls, duplicates, Unicode and quoting;
55
+ server-provisioned managed datasets; sync, Prepare, join, fuzzy-join, grouping and Python
56
+ recipes; folders, scenarios, variables, wiki, notebooks, dashboards, insights, libraries,
57
+ metrics and quality rules. Project export/import/duplicate cases use separate owned
58
+ projects. Managed dataset types, paths and recipe output schemas come from DSS rather
59
+ than tutorial-specific connection guesses.
60
+
61
+ Profiles add to core: `ml` trains and deploys a small decision tree and checks clustering;
62
+ `applications` requires `DATAIKU_LIVE_APP_TEMPLATE_ID`; `infrastructure` requires
63
+ `DATAIKU_SQL_CONNECTION` or `DATAIKU_SQL_DATASET_FULL_NAME` for read-only SQL.
64
+ The SQL case permits only the fixed, table-free `SELECT 1 AS one` probe with an
65
+ explicit target and an owned project whose incarnation is checked before execution.
66
+ It does not authorize arbitrary SQL, alternate query inputs or global mutations. Missing
67
+ prerequisites are recorded as **blocked**, never passed. Required blocked cases exit
68
+ nonzero; optional blocked cases remain visible in reports. Global administration,
69
+ external Git mutations and unsupported capabilities are not silently exercised.
70
+
71
+ For an admin-only disposable SQL target (verified on the hosted trial), create a uniquely
72
+ named connection with `POST /public/api/admin/connections/` and body
73
+ `{"name":"<unique-name>","type":"JDBC","params":{"driver":"org.sqlite.JDBC","jdbcurl":"jdbc:sqlite::memory:","properties":[]},"usableBy":"ALLOWED","allowedGroups":[],"allowWrite":false,"allowManagedDatasets":false}`.
74
+ Run `DATAIKU_SQL_CONNECTION=<name> bun run test:live all --profile infrastructure --case infrastructure.sql-select`.
75
+ In a `finally` block, verify that the connection still matches the created definition, then
76
+ remove it with `DELETE /public/api/admin/connections/<name>`. `all` cleans the owned projects,
77
+ not this separately created connection. The in-memory database creates no database file.
78
+
79
+ State is ignored by Git under `.live-tests/<server-hash>/`. Use `--state-dir PATH` for
80
+ another lab or `--manifest PATH` to select an existing manifest for `run`, `clean` or
81
+ `status` (not `setup`/`all`). Keep the manifest and
82
+ `cleanup.jsonl`: cleanup requires exact project identities and creation-incarnation
83
+ hashes, never a prefix sweep. A changed server/project identity or unconfirmed creation
84
+ fails closed; investigate its journal before manual recovery. Locks prevent concurrent
85
+ lab runs; after an uncatchable process kill, confirm its recorded process is gone before
86
+ removing a stale lock. Interrupting a run preserves the lab; `all` attempts cleanup.
87
+
88
+ Each iteration retains logs and `report.json` with cases, timing, executed actions,
89
+ capability reasons, coverage and external-project metadata integrity. Unavailable project
90
+ metadata is reported separately in `integrity.unreadable`, not as confirmed drift;
91
+ integrity remains unverified and the run fails until those reads succeed. `clean` retains
92
+ `cleanup-report.json`, including deletion failures; starting teardown invalidates lab
93
+ readiness even if cleanup only partially succeeds. If cleanup and integrity verification
94
+ both fail, the cleanup error remains primary and the report preserves both results.
95
+ Planned lifecycle commands retain ownership checks; local outputs stay inside the lab
96
+ for both `--output` and `--output-file`. Treat local reports and exported archives as private project
97
+ data. Coverage is an explicit inventory of every registered action, not a claim that
98
+ every action has a live test: unexercised actions remain **uncovered**. Add cases through
99
+ the typed catalogue in `tests/live-cases.ts`, `LiveContext.check` and guarded helpers,
100
+ then update `tests/live-coverage.ts` when the
101
+ registry changes; catalogue drift fails the offline gate. Plan/dry-run calls do not count
102
+ as executed live coverage.
103
+
104
+ Regular `bun run check` and `bun run lint` include the live runner and fixtures.
105
+ For focused verification:
106
+
107
+ ```sh
108
+ bun run check:live
109
+ bun test tests/live-context.test.ts tests/live-runner.test.ts tests/live-coverage.test.ts
110
+ ```
27
111
 
28
- - Command results write exactly one compact JSON value to stdout; void success is `{ok:true}`. `doctor`, `batch`, and `cleanup` failure reports are their direct result objects on stdout with a nonzero exit code — use the exit code and result fields.
29
- - Dispatch/runtime failures write one compact structured error object on stdout (`type:"error"`, `ok:false`, `error`, `code`, `category`, `exitCode`) with a nonzero exit code; stderr carries JSONL diagnostics only.
30
- - Non-fatal diagnostics and `--verbose` traces are JSONL stderr events (`type:"warning"` / `type:"trace"`), flushed before both success and failure output; no prose trace lines are part of the contract.
31
- - `--fields a,b,c` projects those fields from an object or array-of-objects result; dotted paths (`a.b.c`) drill into nested objects, and missing fields become `null`; string and scalar results pass through unchanged.
32
- - No prompts, help screens, tables, banners, or prose output are part of the contract.
33
- - Exit codes: `0` success, `1` usage/configuration error, `2` DSS/internal error, `3` transient DSS error, `4` a failed long-running result or synchronous assertion.
34
- - `--retries N` controls idempotent GET retries only. `dss sql query --start-retries N` explicitly retries transient failures while starting a query; use it only when executing the SQL more than once is safe.
35
- - The exit code is the success signal. For portable multi-step mutations, prefer `dss batch`; shell chaining and pipeline exit semantics differ across POSIX shells, Windows PowerShell, PowerShell 7, and Command Prompt.
36
- - Recipe payload commands write the payload as a JSON string on stdout; use `--output PATH` to write the exact bytes to a file instead, with stdout carrying the JSON string equal to `PATH`.
112
+ ## CLI contract
37
113
 
38
- Discover the agent contract and command surface with scoped calls:
114
+ The complete agent-facing contract — stdout JSON discipline, stderr JSONL diagnostics, the error
115
+ envelope, exit codes, `--fields` projection, command discovery, and planning/safety rules — is the
116
+ skill bundle rooted at [`skills/dataiku-dss/SKILL.md`](skills/dataiku-dss/SKILL.md). The short
117
+ entrypoint routes agents to focused references; the installed command registry remains the source
118
+ of truth for command syntax and schemas. Human
119
+ essentials: exactly one compact JSON value on stdout per command (void success is `{ok:true}`),
120
+ failures as one structured JSON error object on stdout with a nonzero exit code, stderr reserved
121
+ for JSONL diagnostics only, and exit codes `0` success / `1` usage error / `2` DSS or internal
122
+ error / `3` transient DSS error / `4` failed long-running result or assertion. `--retries N`
123
+ controls idempotent GET retries only; `dss sql query --start-retries N` retries transient failures
124
+ while starting a query. For portable multi-step mutations, prefer `dss batch`; shell chaining and
125
+ pipeline exit semantics differ across platforms.
126
+
127
+ Discover the command surface with scoped calls:
39
128
 
40
129
  ```text
41
130
  dss commands run
42
- dss commands run --fields dataset
43
- dss commands run --fields dataset.create
44
131
  dss commands run --fields dataset.create.usage,dataset.create.description,dataset.create.flags,dataset.create.examples
45
132
  dss commands run --output commands.json
46
133
  dss agent contract --fields protocol,agentContractVersion,cli,stdio,planning,compatibility
47
- dss agent contract --fields commands.actions
48
134
  ```
49
135
 
50
- `dss commands run` prints the compact resource/action summary — every resource keyed to its action names, about 1k tokens — and never dumps registry entries to stdout. Bootstrap contract discovery with the scoped `agent contract` call above: `protocol,agentContractVersion,cli,stdio,planning,compatibility` cover protocol/schema compatibility, stdout/stderr stream semantics, preferred discovery commands, planning rules, and compatibility guarantees in ~250 tokens; request `schemas` or `commands` only when you actually need them. Before choosing syntax, scope `commands run` with `--fields`: `--fields RESOURCE.ACTION` returns one complete registry entry, `--fields RESOURCE` returns every action of one resource, and appending `.FIELD` paths projects the metadata you need — the four-field per-action projection `usage,description,flags,examples` is the smallest self-sufficient starting point for constructing an invocation. Inspect `flags`, `structuredExamples`, `schemas`, `requiresAuth`, `requiresProject`, `sideEffect`, `async`, `idempotency`, `dryRun`, `cleanupCommand`, `unsafeOutputs`, `outputShape`, `inputContract`, and `exitCodes` instead of guessing.
51
-
52
- `--fields` takes a comma-separated list, so request several actions in one call. Each key is echoed exactly as requested (`--fields dataset.create` returns `{"dataset.create": {...}}`); an empty `--fields` is a usage error, never a silent full dump. The full registry (~220k tokens) is exported only via `--output PATH`: the command writes the registry, or the selected `--fields` subset, as compact JSON to `PATH`, and stdout carries the compact `{"path":"PATH"}` result — never the registry itself. An unknown resource or action exits with code 1 and a compact JSON error object on stdout containing the valid options.
136
+ `dss commands run` prints the compact resource/action summary; registry entries never dump to stdout — they travel only via `--output PATH`. See the canonical skill for
137
+ the full `--fields` projection rules and planning workflow.
53
138
 
54
139
  ## Agent skill installation
55
140
 
@@ -62,7 +147,7 @@ dss install-skill --global --agent omp
62
147
 
63
148
  `--list-agents` only reports targetable agents; it does not write files. Auto-detection checks supported agent binaries/config directories (`claude`, `codex`, `cursor`, `pi`, `omp`). Passing `--agent NAME` forces one entry and reports `via:"flag"`.
64
149
 
65
- Project installs write `SKILL.md` under the target workspace:
150
+ Project installs write `SKILL.md` and its sibling `references/` directory under the target workspace:
66
151
 
67
152
  - Claude: `.claude/skills/dataiku-dss/SKILL.md`
68
153
  - Codex: `.codex/skills/dataiku-dss/SKILL.md`
@@ -70,7 +155,42 @@ Project installs write `SKILL.md` under the target workspace:
70
155
  - Pi: `.pi/skills/dataiku-dss/SKILL.md`
71
156
  - OMP: `.omp/skills/dataiku-dss/SKILL.md`
72
157
 
73
- Global installs write under the agent's home config path, for example OMP: `~/.omp/agent/skills/dataiku-dss/SKILL.md`.
158
+ Global installs write under the agent's home config path, for example OMP: `~/.omp/agent/skills/dataiku-dss/SKILL.md`. The reported `target` is the home directory for global installs and the resolved workspace directory for project installs; `installed[].path` names each entrypoint.
159
+
160
+ Each entry in the `installed` array reports pre-install bundle state:
161
+
162
+ - `status`: `missing` when the entrypoint is absent; `stale` when any bundled file is missing or differs; `current` when every bundled file matches.
163
+ - `changed`: whether any bundled file would (or did) change. Byte-identical files are not rewritten.
164
+ - `expectedSha256` and `actualSha256`: the canonical and existing **entrypoint** hashes. The latter is absent when the entrypoint is missing.
165
+ - `files`: each bundled file's portable `relativePath`, destination `path`, `status`, `changed`, and hashes. Missing or stale references are detected even when `SKILL.md` itself is current.
166
+
167
+ `--dry-run` and `--plan` never write. Real installs replace changed files through same-directory temporary files and rename, writing references before the entrypoint. Atomicity is per file, not a bundle-wide transaction. Unrelated files in the destination are preserved.
168
+
169
+ ### Token-efficient skill structure
170
+
171
+ The entrypoint contains bootstrap/discovery, output interpretation, and universal safety rules. Seven focused files under [references/](skills/dataiku-dss/references/) cover authentication, discovery, mutations, application releases, flow maps, coding, and troubleshooting. All are linked directly from `SKILL.md` with task-specific read conditions; agents should not preload the whole directory.
172
+
173
+ The entrypoint measures **750 o200k_base tokens**, down from **851** in the previous revision (12% less) and **4,272** before progressive disclosure. The token-budget test now caps it at **825** tokens. Claude V5 reconstruction counts fell **1,420 → 1,250** and GLM5 **858 → 752**. Safety rules and all seven reference links remain. Reference content consumes context only when read; all five agent installers ship the complete bundle.
174
+
175
+ All seven references are token-budgeted (each measured `o200k_base` baseline plus 5% headroom). Per-file baselines live in [the token-budget tests](tests/cli/agent-token-budget.test.ts); run `bun run test:tokens` to check them.
176
+
177
+ References total **4,179 → 3,545 tokens (15.2% less)**. With the 750-token entrypoint, the whole bundle totals **4,295**; this is a sum of file counts, not a recommendation to preload them. All references shrink across ten encodings; whole-bundle Claude V5 reconstruction **8,200 → 7,362**, GLM5 **4,943 → 4,305**. Runnable examples and safety conditions are retained.
178
+
179
+ This uses progressive disclosure from the [Agent Skills specification](https://agentskills.io/specification) and [Anthropic's authoring guidance](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices): concise metadata/instructions, direct relative reference links, and domain-focused documents. No scripts or assets are needed here; generated command metadata is queried from the CLI rather than duplicated in the skill.
180
+
181
+ `bun run test:tokens` enforces the pinned OpenAI `o200k_base` budgets. To also check ten native encodings (OpenAI, Claude, GLM, Qwen, DeepSeek, and Kimi), point the optional development-only gate at an OMP native module:
182
+
183
+ ```bash
184
+ DSS_TOKENIZER_MODULE=/absolute/path/to/oh-my-pi/packages/natives/native/index.js bun run test:tokens
185
+ ```
186
+
187
+ Without this variable, only the native cross-model case is skipped. A configured missing/incompatible module fails rather than estimating tokens. The cross-model gate permits 10% growth over its recorded text baselines for bootstrap and action discovery; the pinned OpenAI gate also enforces the skill ceiling above. Claude counts use ctok reconstructions, not an official tokenizer, and all counts exclude provider message/tool framing. No native dependency is added to the CLI.
188
+
189
+ Measured full `dataset.create` discovery versus its `usage,description,flags,examples` projection: OpenAI **1,059 → 356**, Claude V5 reconstruction **1,771 → 640**, GLM5 **1,015 → 347** tokens. Use the projection when those fields suffice; fetch the full action when schema details are needed. This is selective disclosure, not lossless compression.
190
+
191
+ Boolean flags accept bare flags or explicit `=true`/`=false` values, including aliases. Invalid boolean values fail before dispatch. Direct, batch, and local commands share execution-mode resolution; `--plan --dry-run` returns a plan with `plannedAndDryRun:true` when both modes are supported. Unreadable JSON/text payload files produce `validation_failed` usage errors (exit 1) with the flag, path, and filesystem cause.
192
+
193
+ For raw streaming downloads, `--request-timeout MS` bounds each pending body read, not the total transfer duration: large progressing transfers remain supported. Buffered text/JSON consumers retain their bounded body-read budget. Request retries do not replay partially consumed streams. Project, bundle, and API-service archives and managed-folder downloads are written to private temporary files beside the destination, then renamed on success. Failures leave no partial output and preserve any existing destination.
74
194
 
75
195
  ## Credentials
76
196
 
@@ -285,6 +405,48 @@ never marks that external check complete. The public DSS APIs used by this SDK d
285
405
  supported app-template publish/recreate/rename workflow, recipient-level app sharing setter, or
286
406
  UI-click smoke test. The CLI does not guess private endpoints for those operations.
287
407
 
408
+ ## Flow visualization and zone planning
409
+
410
+ `project map` returns one agent-oriented JSON view of the Flow: normalized nodes and edges,
411
+ joined zone metadata, cycle-safe topological layers, weakly connected components, diagnostics, and
412
+ a stable `topologyFingerprint`. Zone joins add `zoneId`/`zoneName` to each node; the top-level
413
+ `zones` array preserves zone color, position, item count, and visible node IDs.
414
+
415
+ ```bash
416
+ dss project map --project-key MYPROJ
417
+ dss project map --render mermaid --project-key MYPROJ
418
+ dss project map --render ascii --max-nodes 100 --max-edges 200 --project-key MYPROJ
419
+ ```
420
+
421
+ Rendering is optional and remains inside the JSON result as `rendering.content`; stdout never
422
+ switches to an unstructured diagram stream. Layers are computed after collapsing strongly connected
423
+ components, so cycles are reported without blocking the analysis. Diagnostics cover cycles,
424
+ disconnected components, isolated/default-zone nodes, cross-zone edges, duplicate assignments, and
425
+ truncated analysis. When limits truncate the returned nodes or edges, the topology fingerprint still
426
+ covers the full normalized Flow while layers/components/diagnostics cover the returned subset.
427
+
428
+ The public API exposes zone positions and membership, not individual node pixel coordinates. The CLI
429
+ therefore preserves only supported zone-level visual metadata and never fabricates node coordinates.
430
+ Use the declarative export/apply loop for visual organization:
431
+
432
+ ```bash
433
+ dss flow-zone plan --project-key MYPROJ > flow-zones.json
434
+ dss flow-zone organize --file flow-zones.json --dry-run --project-key MYPROJ
435
+ dss flow-zone organize --file flow-zones.json --project-key MYPROJ
436
+ ```
437
+
438
+ `flow-zone plan` emits JSON accepted directly by `flow-zone organize`, including every
439
+ current zone's supported metadata and explicit items. Reapplying an unchanged plan produces no
440
+ redundant moves. `organize` compares the plan's topology fingerprint before mutation and recomputes
441
+ it after mutation; a mismatch fails rather than claiming a visual-only change. Zone names, colors,
442
+ positions, and membership are deliberately excluded from the fingerprint; flow node identity/kind and
443
+ edges are included.
444
+
445
+ Recipe/code analysis is a separate audit. `project map` and `flow-zone plan` do not fetch,
446
+ hash, interpret, or grade recipe payloads. Use the recipe inspection/diff/assertion commands in a
447
+ separate workflow when code quality or semantic review is required; never mix those findings into a
448
+ layout plan.
449
+
288
450
  ## Project Git source-control safety
289
451
 
290
452
  Project Git commands require DSS 12.4.2 or newer plus read and write access to the project
@@ -330,6 +492,71 @@ applies only to external project-library operations and does not persist a remot
330
492
  The `project-git` resource does not manage these settings, so public/auth-less and
331
493
  already-configured remotes are the supported automation paths.
332
494
 
495
+ ## Coding, notebooks, and project libraries
496
+
497
+ `project-library` manages files in a project's internal `lib/` tree. External Git-backed
498
+ libraries are a different surface: inspect and change those with `project-git list-libraries`,
499
+ `set-library`, `push-library`, and the related future commands. Internal paths are canonicalized;
500
+ leading slashes are removed, while traversal (`..`) and empty segments are rejected.
501
+
502
+ Use a read/diff/guarded-write sequence for internal files. `get-bytes` preserves binary data and
503
+ returns its SHA-256; `diff` caps text output and detects binary files instead of dumping bytes.
504
+ `put --expect-sha256` re-reads the remote bytes and refuses a stale overwrite. New files and
505
+ folders never overwrite existing items; `--if-not-exists` turns an existing target into a skip.
506
+
507
+ ```bash
508
+ dss project-library get-bytes python/mylib/utils.py --output ./utils.py --project-key MYPROJ
509
+ dss project-library diff python/mylib/utils.py --file ./utils.py --project-key MYPROJ
510
+ dss project-library put python/mylib/utils.py --file ./utils.py --expect-sha256 HASH --dry-run --project-key MYPROJ
511
+ dss project-library put python/mylib/utils.py --file ./utils.py --expect-sha256 HASH --project-key MYPROJ
512
+ ```
513
+
514
+ For one-off Python, prefer a file so shell quoting cannot change the source. `code run` creates an
515
+ observable throwaway custom-Python scenario, waits with a bounded timeout, caps returned logs, and
516
+ deletes only that generated scenario unless `--keep` is set.
517
+
518
+ ```bash
519
+ dss code run --file inspect.py --env py311 --project-key MYPROJ
520
+ dss recipe diff prepare_orders --file recipe.py --project-key MYPROJ
521
+ dss recipe set-payload prepare_orders --file recipe.py --dry-run --project-key MYPROJ
522
+ dss recipe set-payload prepare_orders --file recipe.py --backup-dir .dss-backups/recipes --project-key MYPROJ
523
+ dss recipe run prepare_orders --dry-run --project-key MYPROJ
524
+ ```
525
+
526
+ Recipe payload diffs normalize LF/CRLF. `set-payload` backs up payload, graph, settings, code-env,
527
+ and version metadata by default; use `restore --backup FILE --dry-run` before applying a rollback.
528
+ `recipe run --dry-run` performs live output resolution without creating a job; static
529
+ `--plan` reports `exact:false` rather than inventing that live payload.
530
+
531
+ Notebook saves are save-or-create operations. Read first, preserve the full notebook object, then
532
+ use the persisted hash from save/dry-run output with `--expect-hash`. Jupyter output clearing uses
533
+ the official DELETE endpoint. `unload-jupyter --all` is deliberately composed: list active
534
+ notebooks, list their sessions, then delete each session; DSS has no unload-all endpoint.
535
+
536
+ ```bash
537
+ dss notebook get-jupyter analysis.ipynb --project-key MYPROJ
538
+ dss notebook save-jupyter analysis.ipynb --data-file notebook.json --dry-run --project-key MYPROJ
539
+ dss notebook save-jupyter analysis.ipynb --data-file notebook.json --expect-hash HASH --project-key MYPROJ
540
+ dss notebook clear-jupyter-outputs analysis.ipynb --dry-run --project-key MYPROJ
541
+ dss notebook unload-jupyter --all --dry-run --project-key MYPROJ
542
+ ```
543
+
544
+ Code-environment reads expose definitions, deployment mode, installed/requested packages, project
545
+ versions, usages, and bounded build logs. Fetch the definition/hash before `set-definition` or
546
+ `set-packages --expect-hash`; package, image, Jupyter, create, and delete operations can return DSS
547
+ futures with `--no-wait`.
548
+
549
+ Webapp updates use GET–deep-merge–PUT; API-service `save-settings` is explicit full replacement.
550
+ Run either with `--dry-run` to inspect `currentHash`/`nextHash`, then apply with
551
+ `--expect-hash`. Webapp restart futures support `--wait`. API packages and project bundles
552
+ forward release notes and explicit Deployer target IDs.
553
+
554
+ An agent plan with `exact:false` is an honesty boundary: live state is required and no endpoint or
555
+ payload was guessed. Use the command's own `--dry-run` when it resolves that state. The supported
556
+ public DSS API exposes no plugin-authoring lifecycle, notebook execution/checkpoint operation, or
557
+ webapp/API-service delete. Use project Git for plugin source, `code run`/recipes for execution,
558
+ and the authenticated DSS UI for unsupported lifecycle operations.
559
+
333
560
  For fake-DSS smoke tests, return project lists as JSON arrays such as `[{ "projectKey": "MYPROJ", "name": "My Project" }]` from `/public/api/projects/`; recipe payload commands read `/public/api/projects/<PROJECT>/recipes/<NAME>?includePayload=true` and expect a JSON object shaped like `{ "recipe": { "name": "<NAME>", "type": "python" }, "payload": "..." }`.
334
561
 
335
562
  ## License
@@ -1 +1 @@
1
- {"format":1,"buildRevision":"894cf4823fd8a3ffb25cdaa93a09bcd222454565"}
1
+ {"format":1,"buildRevision":"aa9d13ec085be8f8637265cabcc8466df4817c88"}
@@ -430,7 +430,6 @@ export type ConnectionSummary = Static<typeof ConnectionSummarySchema>;
430
430
  export declare const CodeEnvSummarySchema: import("@sinclair/typebox").TObject<{
431
431
  envName: import("@sinclair/typebox").TString;
432
432
  envLang: import("@sinclair/typebox").TString;
433
- pythonInterpreter: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
434
433
  deploymentMode: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
435
434
  }>;
436
435
  export type CodeEnvSummary = Static<typeof CodeEnvSummarySchema>;
@@ -438,10 +437,42 @@ export declare const CodeEnvDetailsSchema: import("@sinclair/typebox").TObject<{
438
437
  envName: import("@sinclair/typebox").TString;
439
438
  envLang: import("@sinclair/typebox").TString;
440
439
  pythonInterpreter: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
440
+ deploymentMode: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
441
441
  requestedPackages: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
442
442
  installedPackages: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
443
+ definitionHash: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
443
444
  }>;
444
445
  export type CodeEnvDetails = Static<typeof CodeEnvDetailsSchema>;
446
+ export declare const CodeEnvLogSummarySchema: import("@sinclair/typebox").TObject<{
447
+ name: import("@sinclair/typebox").TString;
448
+ }>;
449
+ export type CodeEnvLogSummary = Static<typeof CodeEnvLogSummarySchema>;
450
+ export declare const CodeEnvLogSummaryArraySchema: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
451
+ name: import("@sinclair/typebox").TString;
452
+ }>>;
453
+ export type CodeEnvLogSummaryArray = Static<typeof CodeEnvLogSummaryArraySchema>;
454
+ export declare const CodeEnvLogResultSchema: import("@sinclair/typebox").TObject<{
455
+ log: import("@sinclair/typebox").TString;
456
+ bytes: import("@sinclair/typebox").TNumber;
457
+ truncated: import("@sinclair/typebox").TBoolean;
458
+ tailed: import("@sinclair/typebox").TBoolean;
459
+ }>;
460
+ export type CodeEnvLogResult = Static<typeof CodeEnvLogResultSchema>;
461
+ export declare const CodeEnvGetLogOptionsSchema: import("@sinclair/typebox").TObject<{
462
+ maxBytes: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
463
+ maxLines: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
464
+ }>;
465
+ export type CodeEnvGetLogOptions = Static<typeof CodeEnvGetLogOptionsSchema>;
466
+ export declare const CodeEnvUpdateImagesOptionsSchema: import("@sinclair/typebox").TObject<{
467
+ envVersion: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
468
+ wait: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
469
+ }>;
470
+ export type CodeEnvUpdateImagesOptions = Static<typeof CodeEnvUpdateImagesOptionsSchema>;
471
+ export declare const CodeEnvVersionForProjectSchema: import("@sinclair/typebox").TObject<{
472
+ version: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
473
+ bundleId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
474
+ }>;
475
+ export type CodeEnvVersionForProject = Static<typeof CodeEnvVersionForProjectSchema>;
445
476
  export declare const CodeEnvActionResultSchema: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>;
446
477
  export type CodeEnvActionResult = Static<typeof CodeEnvActionResultSchema>;
447
478
  export declare const CodeEnvCreateOptionsSchema: import("@sinclair/typebox").TObject<{
@@ -457,6 +488,7 @@ export type CodeEnvPackageList = Static<typeof CodeEnvPackageListSchema>;
457
488
  export declare const CodeEnvSetPackagesOptionsSchema: import("@sinclair/typebox").TObject<{
458
489
  packages: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>]>;
459
490
  installCorePackages: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
491
+ expectHash: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
460
492
  }>;
461
493
  export type CodeEnvSetPackagesOptions = Static<typeof CodeEnvSetPackagesOptionsSchema>;
462
494
  export declare const CodeEnvUpdatePackagesOptionsSchema: import("@sinclair/typebox").TObject<{
@@ -583,7 +615,7 @@ export declare const DataQualityComputeResultSchema: import("@sinclair/typebox")
583
615
  export type DataQualityComputeResult = Static<typeof DataQualityComputeResultSchema>;
584
616
  export declare const JupyterCellSchema: import("@sinclair/typebox").TObject<{
585
617
  cell_type: import("@sinclair/typebox").TString;
586
- source: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
618
+ source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>]>;
587
619
  metadata: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>>;
588
620
  outputs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnknown>>;
589
621
  execution_count: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TNull, import("@sinclair/typebox").TNumber]>>;
@@ -606,7 +638,7 @@ export declare const JupyterNotebookContentSchema: import("@sinclair/typebox").T
606
638
  nbformat_minor: import("@sinclair/typebox").TNumber;
607
639
  cells: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
608
640
  cell_type: import("@sinclair/typebox").TString;
609
- source: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
641
+ source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>]>;
610
642
  metadata: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>>;
611
643
  outputs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnknown>>;
612
644
  execution_count: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TNull, import("@sinclair/typebox").TNumber]>>;
@@ -646,6 +678,9 @@ export declare const SqlNotebookContentSchema: import("@sinclair/typebox").TObje
646
678
  }>>;
647
679
  }>;
648
680
  export type SqlNotebookContent = Static<typeof SqlNotebookContentSchema>;
681
+ /** Execution history of a SQL notebook: cell ID to the runs recorded for it. */
682
+ export declare const SqlNotebookHistorySchema: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnknown>>;
683
+ export type SqlNotebookHistory = Static<typeof SqlNotebookHistorySchema>;
649
684
  export declare const SqlQuerySchemaSchema: import("@sinclair/typebox").TObject<{
650
685
  name: import("@sinclair/typebox").TString;
651
686
  type: import("@sinclair/typebox").TString;
@@ -677,6 +712,7 @@ export declare const FlowMapOptionsSchema: import("@sinclair/typebox").TObject<{
677
712
  maxNodes: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
678
713
  maxEdges: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
679
714
  includeRaw: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
715
+ render: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"ascii">, import("@sinclair/typebox").TLiteral<"mermaid">]>>;
680
716
  }>;
681
717
  export type FlowMapOptions = Static<typeof FlowMapOptionsSchema>;
682
718
  /**
@@ -853,7 +889,6 @@ export declare const FolderItemArraySchema: import("@sinclair/typebox").TArray<i
853
889
  export declare const CodeEnvSummaryArraySchema: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
854
890
  envName: import("@sinclair/typebox").TString;
855
891
  envLang: import("@sinclair/typebox").TString;
856
- pythonInterpreter: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
857
892
  deploymentMode: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
858
893
  }>>;
859
894
  export declare const WikiArticleDataArraySchema: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
@@ -444,16 +444,39 @@ export const ConnectionSummarySchema = Type.Object({
444
444
  export const CodeEnvSummarySchema = Type.Object({
445
445
  envName: Type.String(),
446
446
  envLang: Type.String(),
447
- pythonInterpreter: Type.Optional(Type.String()),
448
447
  deploymentMode: Type.Optional(Type.String()),
449
448
  }, { additionalProperties: true, });
450
449
  export const CodeEnvDetailsSchema = Type.Object({
451
450
  envName: Type.String(),
452
451
  envLang: Type.String(),
453
452
  pythonInterpreter: Type.Optional(Type.String()),
453
+ deploymentMode: Type.Optional(Type.String()),
454
454
  requestedPackages: Type.Array(Type.String()),
455
455
  installedPackages: Type.Array(Type.String()),
456
+ definitionHash: Type.Optional(Type.String()),
456
457
  });
458
+ export const CodeEnvLogSummarySchema = Type.Object({
459
+ name: Type.String(),
460
+ }, { additionalProperties: true, });
461
+ export const CodeEnvLogSummaryArraySchema = Type.Array(CodeEnvLogSummarySchema);
462
+ export const CodeEnvLogResultSchema = Type.Object({
463
+ log: Type.String(),
464
+ bytes: Type.Number(),
465
+ truncated: Type.Boolean(),
466
+ tailed: Type.Boolean(),
467
+ }, { additionalProperties: false, });
468
+ export const CodeEnvGetLogOptionsSchema = Type.Object({
469
+ maxBytes: Type.Optional(Type.Number()),
470
+ maxLines: Type.Optional(Type.Number()),
471
+ }, { additionalProperties: false, });
472
+ export const CodeEnvUpdateImagesOptionsSchema = Type.Object({
473
+ envVersion: Type.Optional(Type.String()),
474
+ wait: Type.Optional(Type.Boolean()),
475
+ }, { additionalProperties: false, });
476
+ export const CodeEnvVersionForProjectSchema = Type.Object({
477
+ version: Type.Optional(Type.String()),
478
+ bundleId: Type.Optional(Type.String()),
479
+ }, { additionalProperties: true, });
457
480
  export const CodeEnvActionResultSchema = Type.Record(Type.String(), Type.Unknown());
458
481
  export const CodeEnvCreateOptionsSchema = Type.Object({
459
482
  envLang: Type.String(),
@@ -469,6 +492,7 @@ export const CodeEnvPackageListSchema = Type.Union([
469
492
  export const CodeEnvSetPackagesOptionsSchema = Type.Object({
470
493
  packages: CodeEnvPackageListSchema,
471
494
  installCorePackages: Type.Optional(Type.Boolean()),
495
+ expectHash: Type.Optional(Type.String()),
472
496
  }, { additionalProperties: false, });
473
497
  export const CodeEnvUpdatePackagesOptionsSchema = Type.Object({
474
498
  forceRebuildEnv: Type.Optional(Type.Boolean()),
@@ -569,7 +593,9 @@ export const DataQualityComputeResultSchema = Type.Object({
569
593
  // ---------------------------------------------------------------------------
570
594
  export const JupyterCellSchema = Type.Object({
571
595
  cell_type: Type.String(),
572
- source: Type.Array(Type.String()),
596
+ // nbformat permits a cell's source to be either a single string or an
597
+ // array of strings; DSS returns whichever form the notebook carries.
598
+ source: Type.Union([Type.String(), Type.Array(Type.String()),]),
573
599
  metadata: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
574
600
  outputs: Type.Optional(Type.Array(Type.Unknown())),
575
601
  execution_count: Type.Optional(Type.Union([Type.Null(), Type.Number(),])),
@@ -617,6 +643,8 @@ export const SqlNotebookContentSchema = Type.Object({
617
643
  connection: Type.String(),
618
644
  cells: Type.Array(SqlNotebookCellSchema),
619
645
  }, { additionalProperties: true, });
646
+ /** Execution history of a SQL notebook: cell ID to the runs recorded for it. */
647
+ export const SqlNotebookHistorySchema = Type.Record(Type.String(), Type.Array(Type.Unknown()));
620
648
  // ---------------------------------------------------------------------------
621
649
  // SQL Queries
622
650
  // ---------------------------------------------------------------------------
@@ -642,6 +670,7 @@ export const FlowMapOptionsSchema = Type.Object({
642
670
  maxNodes: Type.Optional(Type.Number()),
643
671
  maxEdges: Type.Optional(Type.Number()),
644
672
  includeRaw: Type.Optional(Type.Boolean()),
673
+ render: Type.Optional(Type.Union([Type.Literal("ascii"), Type.Literal("mermaid"),])),
645
674
  });
646
675
  // ---------------------------------------------------------------------------
647
676
  // Project Git
package/dist/src/auth.js CHANGED
@@ -1,7 +1,7 @@
1
- import { DataikuClient, } from "./client.js";
2
1
  import { DataikuError, } from "./errors.js";
3
2
  export async function validateCredentials(url, apiKey, options = {}) {
4
3
  try {
4
+ const { DataikuClient, } = await import("./client.js");
5
5
  const client = new DataikuClient({
6
6
  url,
7
7
  apiKey,
@@ -169,6 +169,15 @@ function selectSingleSource(flags, sourceFlags) {
169
169
  }
170
170
  return provided[0];
171
171
  }
172
+ function readInputText(path, flag) {
173
+ try {
174
+ return readFileSync(path, "utf-8");
175
+ }
176
+ catch (error) {
177
+ const cause = error.code;
178
+ throw new UsageError(`Could not read ${flag} file: ${path}`, "validation_failed", "Verify that the path names an existing, readable file.", { flag, path, ...(cause ? { cause, } : {}), });
179
+ }
180
+ }
172
181
  function resolveJsonSourceText(flags, kind) {
173
182
  const source = selectSingleSource(flags, JSON_SOURCE_FLAGS);
174
183
  if (source === undefined)
@@ -182,7 +191,7 @@ function resolveJsonSourceText(flags, kind) {
182
191
  if (source === "data-file") {
183
192
  const fileValue = flags["data-file"];
184
193
  if (typeof fileValue === "string") {
185
- const jsonText = readFileSync(fileValue, "utf-8");
194
+ const jsonText = readInputText(fileValue, "--data-file");
186
195
  return kind === "object"
187
196
  ? parseJsonObject(jsonText, fileValue)
188
197
  : parseJsonValue(jsonText, fileValue);
@@ -241,7 +250,7 @@ export function textInput(flags) {
241
250
  if (source === "file") {
242
251
  const fileValue = flags["file"];
243
252
  if (typeof fileValue === "string")
244
- return readFileSync(fileValue, "utf-8");
253
+ return readInputText(fileValue, "--file");
245
254
  }
246
255
  const contentValue = flags["content"];
247
256
  if (typeof contentValue === "string")
@@ -1,4 +1,5 @@
1
1
  import { requiredStringFlag, } from "../coerce.js";
2
+ import { executionMode, } from "../flags.js";
2
3
  import { readIfExists, skipResult, } from "../output.js";
3
4
  import { requireArgs, } from "../usage.js";
4
5
  export const analysisCommands = {
@@ -23,7 +24,7 @@ export const analysisCommands = {
23
24
  const inputDataset = requiredStringFlag(f, "input-dataset", usage);
24
25
  const projectKey = f["project-key"];
25
26
  const options = { inputDataset, projectKey, };
26
- if (f["dry-run"] === true) {
27
+ if (executionMode(f).dryRun) {
27
28
  return {
28
29
  dryRun: true,
29
30
  action: "create",
@@ -45,11 +46,11 @@ export const analysisCommands = {
45
46
  handler: async (c, a, f) => {
46
47
  requireArgs(a, 1, "dss analysis delete <analysisId> [--if-exists] [--dry-run] [--project-key KEY]");
47
48
  const projectKey = f["project-key"];
48
- if (f["dry-run"] === true || f["if-exists"] === true) {
49
+ if (executionMode(f).dryRun || f["if-exists"] === true) {
49
50
  const current = await readIfExists(() => c.analyses.get(a[0], projectKey));
50
51
  if (!current)
51
52
  return skipResult("analysis", a[0], "missing");
52
- if (f["dry-run"] === true) {
53
+ if (executionMode(f).dryRun) {
53
54
  return { dryRun: true, action: "delete", resource: "analysis", id: a[0], current, };
54
55
  }
55
56
  }