dataiku-sdk 0.12.3 → 0.12.5
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.
- package/README.md +118 -7
- package/dist/packages/types/src/index.d.ts +5 -0
- package/dist/packages/types/src/index.js +5 -0
- package/dist/src/cli/coerce.d.ts +1 -3
- package/dist/src/cli/coerce.js +1 -17
- package/dist/src/cli/commands/app.js +709 -14
- package/dist/src/cli/commands/code-env.js +2 -2
- package/dist/src/cli/commands/dashboard.js +1 -1
- package/dist/src/cli/commands/dataset.js +2 -2
- package/dist/src/cli/commands/folder.js +1 -1
- package/dist/src/cli/commands/insight.js +2 -2
- package/dist/src/cli/commands/notebook.js +2 -2
- package/dist/src/cli/commands/recipe.js +3 -3
- package/dist/src/cli/commands/scenario.js +1 -1
- package/dist/src/cli/commands/sql.js +1 -1
- package/dist/src/cli/commands/variable.js +1 -1
- package/dist/src/cli/commands/wiki.js +1 -1
- package/dist/src/cli/contract.d.ts +12 -3
- package/dist/src/cli/contract.js +805 -49
- package/dist/src/cli/flags.js +8 -0
- package/dist/src/cli/helpers/app-permissions.d.ts +63 -0
- package/dist/src/cli/helpers/app-permissions.js +239 -0
- package/dist/src/cli/helpers/app-successor.d.ts +106 -0
- package/dist/src/cli/helpers/app-successor.js +625 -0
- package/dist/src/cli/helpers/cleanup.js +46 -12
- package/dist/src/cli/output.d.ts +12 -1
- package/dist/src/cli/output.js +53 -6
- package/dist/src/cli/usage.d.ts +1 -1
- package/dist/src/cli/usage.js +5 -2
- package/dist/src/cli.js +329 -32
- package/dist/src/client.d.ts +6 -0
- package/dist/src/client.js +28 -1
- package/dist/src/errors.d.ts +1 -1
- package/dist/src/resources/applications.d.ts +191 -1
- package/dist/src/resources/applications.js +549 -10
- package/dist/src/resources/datasets.js +8 -0
- package/dist/src/resources/futures.js +7 -2
- package/dist/src/skill.js +80 -15
- package/dist/src/utils/cleanup-ledger.d.ts +34 -1
- package/dist/src/utils/cleanup-ledger.js +118 -7
- package/dist/src/utils/dss-url.d.ts +6 -0
- package/dist/src/utils/dss-url.js +17 -0
- package/dist/src/utils/project-incarnation.d.ts +6 -0
- package/dist/src/utils/project-incarnation.js +27 -0
- package/dist/src/utils/stable-hash.d.ts +11 -0
- package/dist/src/utils/stable-hash.js +27 -0
- package/node_modules/@sinclair/typebox/build/cjs/compiler/compiler.js +26 -46
- package/node_modules/@sinclair/typebox/build/cjs/parser/runtime/guard.d.ts +1 -1
- package/node_modules/@sinclair/typebox/build/cjs/parser/runtime/token.d.ts +2 -2
- package/node_modules/@sinclair/typebox/build/cjs/syntax/mapping.d.ts +1 -1
- package/node_modules/@sinclair/typebox/build/cjs/system/evaluate.d.ts +5 -0
- package/node_modules/@sinclair/typebox/build/cjs/system/evaluate.js +11 -0
- package/node_modules/@sinclair/typebox/build/cjs/system/index.d.ts +1 -0
- package/node_modules/@sinclair/typebox/build/cjs/system/index.js +1 -0
- package/node_modules/@sinclair/typebox/build/cjs/type/object/object.d.ts +2 -2
- package/node_modules/@sinclair/typebox/build/cjs/type/object/object.js +18 -2
- package/node_modules/@sinclair/typebox/build/cjs/value/parse/parse.d.ts +1 -1
- package/node_modules/@sinclair/typebox/build/esm/compiler/compiler.mjs +27 -47
- package/node_modules/@sinclair/typebox/build/esm/parser/runtime/guard.d.mts +1 -1
- package/node_modules/@sinclair/typebox/build/esm/parser/runtime/token.d.mts +2 -2
- package/node_modules/@sinclair/typebox/build/esm/syntax/mapping.d.mts +1 -1
- package/node_modules/@sinclair/typebox/build/esm/system/evaluate.d.mts +5 -0
- package/node_modules/@sinclair/typebox/build/esm/system/evaluate.mjs +7 -0
- package/node_modules/@sinclair/typebox/build/esm/system/index.d.mts +1 -0
- package/node_modules/@sinclair/typebox/build/esm/system/index.mjs +1 -0
- package/node_modules/@sinclair/typebox/build/esm/type/composite/composite.mjs +2 -2
- package/node_modules/@sinclair/typebox/build/esm/type/const/const.mjs +3 -3
- package/node_modules/@sinclair/typebox/build/esm/type/instantiate/instantiate.mjs +2 -2
- package/node_modules/@sinclair/typebox/build/esm/type/mapped/mapped.mjs +3 -3
- package/node_modules/@sinclair/typebox/build/esm/type/module/compute.mjs +2 -2
- package/node_modules/@sinclair/typebox/build/esm/type/object/object.d.mts +2 -2
- package/node_modules/@sinclair/typebox/build/esm/type/object/object.mjs +18 -2
- package/node_modules/@sinclair/typebox/build/esm/type/omit/omit.mjs +3 -3
- package/node_modules/@sinclair/typebox/build/esm/type/partial/partial.mjs +3 -3
- package/node_modules/@sinclair/typebox/build/esm/type/pick/pick.mjs +3 -3
- package/node_modules/@sinclair/typebox/build/esm/type/record/record.mjs +3 -3
- package/node_modules/@sinclair/typebox/build/esm/type/required/required.mjs +3 -3
- package/node_modules/@sinclair/typebox/build/esm/type/type/json.mjs +2 -2
- package/node_modules/@sinclair/typebox/build/esm/value/delta/delta.mjs +4 -4
- package/node_modules/@sinclair/typebox/build/esm/value/parse/parse.d.mts +1 -1
- package/node_modules/@sinclair/typebox/package.json +1 -1
- package/package.json +7 -5
- package/packages/types/dist/index.d.ts +5 -0
- package/packages/types/dist/index.js +5 -0
package/README.md
CHANGED
|
@@ -23,23 +23,28 @@ Bun is the primary development runtime and package manager. Examples below assum
|
|
|
23
23
|
|
|
24
24
|
## CLI contract
|
|
25
25
|
|
|
26
|
-
-
|
|
27
|
-
-
|
|
26
|
+
- Command results write exactly one JSON value to stdout, including `doctor`, `batch`, and `cleanup` failure reports; use the exit code and result fields.
|
|
27
|
+
- Dispatch/runtime failures write one JSONL error event to stderr with `type:"error"`, `ok:false`, `error`, `code`, and `exitCode`, while stdout stays empty.
|
|
28
28
|
- Non-fatal diagnostics and `--verbose` traces are JSONL stderr events (`type:"warning"` / `type:"trace"`); no prose trace lines are part of the contract.
|
|
29
29
|
- `--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.
|
|
30
30
|
- No prompts, help screens, tables, banners, or prose output are part of the contract.
|
|
31
|
-
- Exit codes: `0` success, `1` usage/configuration error, `2` DSS/internal error, `3` transient DSS error, `4`
|
|
31
|
+
- 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.
|
|
32
32
|
- 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.
|
|
33
33
|
- `--raw` is only for recipe payload commands. Without `--output`, stdout is raw bytes; with `--output PATH`, stdout is the JSON string equal to `PATH` and the file contains the exact raw bytes.
|
|
34
34
|
|
|
35
|
-
Discover the agent
|
|
35
|
+
Discover the agent contract and command surface with compact, scoped, `--json` calls:
|
|
36
36
|
|
|
37
37
|
```text
|
|
38
|
-
dss agent contract
|
|
39
|
-
dss commands run
|
|
38
|
+
dss agent contract --fields protocol,agentContractVersion,cli,stdio,planning,compatibility --json
|
|
39
|
+
dss commands run --fields dataset.create --json
|
|
40
|
+
dss commands run --fields dataset.create.usage,dataset.create.description,dataset.create.flags,dataset.create.examples --json
|
|
41
|
+
dss commands run --fields dataset --json
|
|
42
|
+
dss agent contract --fields commands.actions --json
|
|
40
43
|
```
|
|
41
44
|
|
|
42
|
-
|
|
45
|
+
For JSON outputs, prefer `--json`: compact single-line JSON cuts the full registry's context usage by about 40% (~220k tokens versus ~358k pretty-printed). Bootstrap by scoping `agent contract` to `protocol,agentContractVersion,cli,stdio,planning,compatibility` (~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, 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.
|
|
46
|
+
|
|
47
|
+
`--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": {...}}`). Enumerate every resource and action with `dss agent contract --fields commands.actions --json` (~1k tokens); the ~220k-token unscoped registry remains a compatibility surface, not a discovery workflow. An unknown resource or action exits with code 1 and a JSON error envelope on stderr containing the valid options.
|
|
43
48
|
|
|
44
49
|
## Agent skill installation
|
|
45
50
|
|
|
@@ -116,6 +121,112 @@ dss recipe get-payload compute_orders --project-key MYPROJ
|
|
|
116
121
|
dss recipe get-payload compute_orders --raw --project-key MYPROJ
|
|
117
122
|
dss recipe get-payload compute_orders --raw --output code.py --project-key MYPROJ
|
|
118
123
|
dss install-skill --dry-run
|
|
124
|
+
dss app validate-manifest --project-key MYAPP_INSTANCE
|
|
125
|
+
dss app compare-manifest my-app --project-key MYAPP_INSTANCE
|
|
126
|
+
dss app create-instance my-app --data '{"targetProjectKey":"MYAPP_INSTANCE"}' --wait --record-cleanup cleanup.jsonl
|
|
127
|
+
dss app manifest-version --project-key MYAPP_TEMPLATE
|
|
128
|
+
dss app set-manifest-version --manifest-version 1.4.0 --project-key MYAPP_TEMPLATE
|
|
129
|
+
dss app create-successor-instance my-app --from MYAPP_INSTANCE --to MYAPP_INSTANCE_V2 --copy-permissions --record-cleanup cleanup.jsonl
|
|
130
|
+
dss app verify-instance my-app --project-key MYAPP_INSTANCE_V2 --expect-version 1.4.0
|
|
131
|
+
dss app permissions-snapshot --project-key MYAPP_INSTANCE --output permissions.json
|
|
132
|
+
dss app permissions-diff --project-key MYAPP_INSTANCE --file permissions.json
|
|
133
|
+
dss app permissions-restore --project-key MYAPP_INSTANCE --file permissions.json --dry-run
|
|
134
|
+
dss cleanup --file cleanup.jsonl
|
|
135
|
+
dss cleanup --file cleanup.jsonl --apply
|
|
119
136
|
```
|
|
120
137
|
|
|
138
|
+
### Application release safety
|
|
139
|
+
|
|
140
|
+
Use the app commands as explicit release gates around a stable template, instance project key,
|
|
141
|
+
and permission set:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Validate source-verifiable manifest references.
|
|
145
|
+
dss app validate-manifest --project-key APP_TEMPLATE
|
|
146
|
+
|
|
147
|
+
# Detect governed template/instance drift. Only projectKey and projectAppType are normalized away.
|
|
148
|
+
dss app compare-manifest APP_ID --project-key RELEASE_INSTANCE
|
|
149
|
+
|
|
150
|
+
# Read the raw `version` from the public app manifest (string fields only; never appVersion).
|
|
151
|
+
dss app manifest-version --project-key APP_TEMPLATE
|
|
152
|
+
|
|
153
|
+
# Write version/versionNotes through the public app-manifest endpoint. This is NOT a publish
|
|
154
|
+
# transaction: it only changes the raw manifest metadata. --expect-hash SHA256 is a non-atomic
|
|
155
|
+
# stale-read guard, not a conditional write: it refuses the write when the manifest already
|
|
156
|
+
# changed since you read that hash, but DSS accepts every PUT unconditionally. This command can
|
|
157
|
+
# overwrite a write landing between its read and PUT, and the final read cannot detect that lost
|
|
158
|
+
# update when this command's payload wins. Every result reports
|
|
159
|
+
# concurrencyControl: "client-side-non-atomic-stale-read-check".
|
|
160
|
+
dss app set-manifest-version --manifest-version 1.4.0 --project-key APP_TEMPLATE
|
|
161
|
+
|
|
162
|
+
# Create an instance only after its target key is confirmed absent, wait on the DSS future, and
|
|
163
|
+
# record deterministic cleanup.
|
|
164
|
+
dss app create-instance APP_ID \
|
|
165
|
+
--data '{"targetProjectKey":"RELEASE_INSTANCE","targetProjectName":"Release instance"}' \
|
|
166
|
+
--wait --record-cleanup cleanup.jsonl
|
|
167
|
+
|
|
168
|
+
# Roll out a new template version to an existing instance as an additive successor: the old
|
|
169
|
+
# instance is never modified or deleted, and the command always waits on the DSS future
|
|
170
|
+
# (there is no --wait flag). The recorded cleanup entry targets only the new project key. If DSS
|
|
171
|
+
# accepts creation but returns no future ID, cleanup stops unresolved instead of racing creation.
|
|
172
|
+
dss app create-successor-instance APP_ID \
|
|
173
|
+
--from RELEASE_INSTANCE --to RELEASE_INSTANCE_V2 \
|
|
174
|
+
--name "Release instance v2" --copy-permissions --record-cleanup cleanup.jsonl
|
|
175
|
+
|
|
176
|
+
# API readiness gate for the successor. apiReady:true with status API_VERIFIED_UI_PENDING is an
|
|
177
|
+
# API-verified state only — never visual verification. The API key authenticates public REST only;
|
|
178
|
+
# visual confirmation stays an external SSO gate (pre-authenticated SSO browser session or a
|
|
179
|
+
# dedicated UI test identity).
|
|
180
|
+
dss app verify-instance APP_ID --project-key RELEASE_INSTANCE_V2 --expect-version 1.4.0
|
|
181
|
+
|
|
182
|
+
# Retirement of the predecessor is a separate, separately guarded step after the successor is
|
|
183
|
+
# verified. It is never performed implicitly by the successor flow.
|
|
184
|
+
dss app delete-instance --project-key RELEASE_INSTANCE
|
|
185
|
+
|
|
186
|
+
# Snapshot, compare, preview, and restore project permissions.
|
|
187
|
+
dss app permissions-snapshot --project-key RELEASE_INSTANCE --output permissions.json
|
|
188
|
+
dss app permissions-diff --project-key RELEASE_INSTANCE --file permissions.json
|
|
189
|
+
dss app permissions-restore --project-key RELEASE_INSTANCE --file permissions.json --dry-run
|
|
190
|
+
dss app permissions-restore --project-key RELEASE_INSTANCE --file permissions.json
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Permission snapshots are written with mode `0600` and an integrity hash covering the canonical DSS
|
|
194
|
+
URL, the concrete project incarnation (`creationTag`), capture metadata, and permissions. Diff and
|
|
195
|
+
restore reject snapshots from another DSS server, project key, or observed incarnation. These are
|
|
196
|
+
client-side, non-atomic stale-identity checks: DSS exposes no conditional permission PUT, so the
|
|
197
|
+
checks narrow and detect key-reuse races but cannot serialize the final check with the write.
|
|
198
|
+
Snapshots contain access-control identities; commit them only when repository policy permits.
|
|
199
|
+
`validate-manifest` checks `SCENARIO_RUN` scenario IDs, `DOWNLOAD_FILE`
|
|
200
|
+
managed-folder IDs, and runtime-form parameter names against supported public project APIs.
|
|
201
|
+
|
|
202
|
+
Some DSS deployments hide unknown project keys behind `403` instead of returning `404`.
|
|
203
|
+
Instance creation requires confirmed target absence before POST: an inaccessible target not present
|
|
204
|
+
in the visible project list is still unconfirmed and is rejected rather than risking cleanup
|
|
205
|
+
against a pre-existing project. A definitive create rejection never produces a cleanup entry.
|
|
206
|
+
|
|
207
|
+
Every new cleanup entry records the canonical DSS URL. App-instance cleanup records a
|
|
208
|
+
`creationTag` hash observed after the DSS future identifies the target key; unconfirmed creation
|
|
209
|
+
stops unresolved. The future target and later `creationTag` are independent, non-atomic
|
|
210
|
+
observations: the public API exposes neither an immutable project ID joined to the future nor a
|
|
211
|
+
conditional DELETE. Cleanup rechecks type and `creationTag` immediately before deletion, rejecting
|
|
212
|
+
detected key reuse, but cannot eliminate replacement in the remaining check-to-DELETE gap.
|
|
213
|
+
`cleanup --apply` validates the full ledger before issuing any request and rejects legacy entries
|
|
214
|
+
without server identity, mixed-server ledgers, entries for another DSS URL, and app cleanup entries
|
|
215
|
+
without a valid incarnation binding.
|
|
216
|
+
|
|
217
|
+
Saving `version`/`versionNotes` in the public app manifest is a metadata write, not a publish
|
|
218
|
+
transaction. If the manifest PUT or its verification read has an ambiguous transport/server
|
|
219
|
+
failure, the command exits non-zero with `persisted:null`, `after:null`, and
|
|
220
|
+
`outcome:"indeterminate"` rather than claiming the write failed or succeeded. Existing instances
|
|
221
|
+
are never upgraded in place: new instances inherit the template's
|
|
222
|
+
raw `version`, and an existing instance is rolled forward by creating an additive successor (the
|
|
223
|
+
old instance is preserved) followed by a separate, guarded retirement. `verify-instance` never
|
|
224
|
+
reports visual verification: its output is `apiReady:true` with
|
|
225
|
+
`status:"API_VERIFIED_UI_PENDING"` and `uiPublicationVerified:false`. Its `visual-ui` gate names
|
|
226
|
+
the required authentication and evidence: open the instance in a pre-authenticated SSO browser or
|
|
227
|
+
with a dedicated UI test identity, then exercise the affected tiles, forms, and actions. The CLI
|
|
228
|
+
never marks that external check complete. The public DSS APIs used by this SDK do not expose a
|
|
229
|
+
supported app-template publish/recreate/rename workflow, recipient-level app sharing setter, or
|
|
230
|
+
UI-click smoke test. The CLI does not guess private endpoints for those operations.
|
|
231
|
+
|
|
121
232
|
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": "..." }`.
|
|
@@ -30,6 +30,11 @@ export declare const ProjectDetailsSchema: import("@sinclair/typebox").TObject<{
|
|
|
30
30
|
name: import("@sinclair/typebox").TString;
|
|
31
31
|
shortDesc: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
32
32
|
projectStatus: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
33
|
+
projectAppType: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
34
|
+
creationTag: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
35
|
+
versionNumber: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
36
|
+
lastModifiedOn: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TNumber, import("@sinclair/typebox").TString]>>;
|
|
37
|
+
}>>;
|
|
33
38
|
ownerLogin: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
34
39
|
tags: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
|
|
35
40
|
versionTag: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
@@ -86,6 +86,11 @@ export const ProjectDetailsSchema = Type.Object({
|
|
|
86
86
|
name: Type.String(),
|
|
87
87
|
shortDesc: Type.Optional(Type.String()),
|
|
88
88
|
projectStatus: Type.Optional(Type.String()),
|
|
89
|
+
projectAppType: Type.Optional(Type.String()),
|
|
90
|
+
creationTag: Type.Optional(Type.Object({
|
|
91
|
+
versionNumber: Type.Optional(Type.Number()),
|
|
92
|
+
lastModifiedOn: Type.Optional(Type.Union([Type.Number(), Type.String(),])),
|
|
93
|
+
}, { additionalProperties: true, })),
|
|
89
94
|
ownerLogin: Type.Optional(Type.String()),
|
|
90
95
|
tags: Type.Optional(Type.Array(Type.String())),
|
|
91
96
|
versionTag: Type.Optional(Type.Object({
|
package/dist/src/cli/coerce.d.ts
CHANGED
|
@@ -4,10 +4,8 @@ export declare function jobBuildTargetType(v: string | boolean | undefined): Job
|
|
|
4
4
|
export declare function jobBuildTargetTypeFromFlags(flags: Record<string, string | boolean>): JobBuildTargetType;
|
|
5
5
|
export declare function maxLogLinesFromFlags(flags: Record<string, string | boolean>): number | undefined;
|
|
6
6
|
export declare function jobLogFilterFromFlag(v: string | boolean | undefined): JobLogFilter | undefined;
|
|
7
|
-
export
|
|
7
|
+
export { sha256Hex, stableHash, stableJson, } from "../utils/stable-hash.js";
|
|
8
8
|
export declare function normalizeLineEndings(value: string): string;
|
|
9
|
-
export declare function stableJson(value: unknown): string;
|
|
10
|
-
export declare function stableHash(value: unknown): string;
|
|
11
9
|
export declare function splitCsvFlag(v: string | boolean | undefined): string[];
|
|
12
10
|
export declare function recipeInputDatasetsFromFlags(flags: Record<string, string | boolean>): string[] | undefined;
|
|
13
11
|
export declare function rewritePairsFromFlags(flags: Record<string, string | boolean>, flagName: string): Record<string, string>;
|
package/dist/src/cli/coerce.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { createHash, } from "node:crypto";
|
|
2
1
|
import { readFileSync, } from "node:fs";
|
|
3
2
|
import { UsageError, } from "./usage.js";
|
|
4
3
|
export function num(v) {
|
|
@@ -37,25 +36,10 @@ export function jobLogFilterFromFlag(v) {
|
|
|
37
36
|
}
|
|
38
37
|
throw new UsageError("Invalid --log-filter value. Use stdout, stderr, user, or errors.", "invalid_enum");
|
|
39
38
|
}
|
|
40
|
-
export
|
|
41
|
-
return createHash("sha256").update(value).digest("hex");
|
|
42
|
-
}
|
|
39
|
+
export { sha256Hex, stableHash, stableJson, } from "../utils/stable-hash.js";
|
|
43
40
|
export function normalizeLineEndings(value) {
|
|
44
41
|
return value.replace(/\r\n/g, "\n");
|
|
45
42
|
}
|
|
46
|
-
export function stableJson(value) {
|
|
47
|
-
if (value === undefined)
|
|
48
|
-
return "undefined";
|
|
49
|
-
if (value === null || typeof value !== "object")
|
|
50
|
-
return JSON.stringify(value);
|
|
51
|
-
if (Array.isArray(value))
|
|
52
|
-
return `[${value.map((item) => stableJson(item)).join(",")}]`;
|
|
53
|
-
const entries = Object.entries(value).sort(([a,], [b,]) => a.localeCompare(b));
|
|
54
|
-
return `{${entries.map(([key, item,]) => `${JSON.stringify(key)}:${stableJson(item)}`).join(",")}}`;
|
|
55
|
-
}
|
|
56
|
-
export function stableHash(value) {
|
|
57
|
-
return sha256Hex(stableJson(value));
|
|
58
|
-
}
|
|
59
43
|
export function splitCsvFlag(v) {
|
|
60
44
|
if (typeof v !== "string")
|
|
61
45
|
return [];
|