dataiku-sdk 0.12.4 → 0.12.6
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 +119 -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 +17 -2
- 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 +9 -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 +13 -1
- package/dist/src/client.js +46 -6
- 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/resources/sql.d.ts +5 -0
- package/dist/src/resources/sql.js +5 -4
- package/dist/src/skill.js +78 -19
- 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 +9 -5
- package/packages/types/dist/index.d.ts +5 -0
- package/packages/types/dist/index.js +5 -0
package/dist/src/skill.js
CHANGED
|
@@ -10,22 +10,30 @@ If the installed \`dss\` binary is unavailable but the repository checkout is th
|
|
|
10
10
|
|
|
11
11
|
## Contract
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
13
|
+
- Command results write exactly one JSON value to stdout, including \`doctor\`, \`batch\`, and \`cleanup\` failure reports; use the exit code and result fields.
|
|
14
|
+
- Dispatch/runtime failures write one JSONL error event to stderr with \`type:"error"\`, \`ok:false\`, \`error\`, \`code\`, and \`exitCode\`, while stdout stays empty.
|
|
15
15
|
- Non-fatal warnings and \`--verbose\` HTTP traces are JSONL stderr events (\`type:"warning"\` / \`type:"trace"\`), never prose.
|
|
16
16
|
- No prompts, help screens, tables, banners, or prose output are part of the contract.
|
|
17
|
-
- Exit codes: 0 success, 1 usage/configuration error, 2 DSS or internal error, 3 transient/retryable DSS error, 4
|
|
17
|
+
- Exit codes: 0 success, 1 usage/configuration error, 2 DSS or internal error, 3 transient/retryable DSS error, 4 a failed long-running result or synchronous assertion.
|
|
18
|
+
- Pass \`--json\` for compact single-line JSON on stdout; use it for agent discovery and other JSON results to minimize tokens. Without it, success JSON is pretty-printed.
|
|
18
19
|
- \`--raw\` is the only stdout escape hatch: recipe payload commands emit raw bytes to stdout unless \`--output PATH\` is also set; with \`--output\`, stdout is the JSON string equal to \`PATH\` and the file receives exact raw bytes.
|
|
19
20
|
- \`--fields a,b,c\` projects those fields from object or array-of-objects results; dotted paths (\`a.b.c\`) drill into nested objects, and missing fields become \`null\`; string and scalar results pass through unchanged.
|
|
20
21
|
|
|
21
22
|
## Discover commands
|
|
22
23
|
|
|
23
24
|
\`\`\`text
|
|
24
|
-
dss agent contract
|
|
25
|
-
dss commands run
|
|
25
|
+
dss agent contract --fields protocol,agentContractVersion,cli,stdio,planning,compatibility --json
|
|
26
|
+
dss commands run --fields dataset.create --json
|
|
27
|
+
dss commands run --fields dataset.create.usage,dataset.create.description,dataset.create.flags,dataset.create.examples --json
|
|
28
|
+
dss commands run --fields dataset --json
|
|
29
|
+
dss agent contract --fields commands.actions --json
|
|
26
30
|
\`\`\`
|
|
27
31
|
|
|
28
|
-
|
|
32
|
+
Bootstrap with the scoped \`agent contract\` call above: \`protocol,agentContractVersion,cli,stdio,planning,compatibility\` cover protocol/schema compatibility, stderr event semantics, preferred discovery commands, non-JSON escape hatches, planning rules, and compatibility guarantees in ~250 tokens. Request \`schemas\` (the JSON schemas) or \`commands\` (the contract's discovery section) only when you actually need them.
|
|
33
|
+
|
|
34
|
+
Before choosing command syntax, look the action up in the command registry: \`--fields RESOURCE.ACTION\` returns one complete entry, and appended \`.FIELD\` paths return only the metadata you need. Prefer the four-field projection \`usage,description,flags,examples\` by default — it is the smallest self-sufficient starting point for constructing an invocation. The registry entry is the canonical schema for flags, positional arguments, side effects, auth requirements, output shape, idempotency, dry-run support, structured examples, payload schemas, unsafe outputs, cleanup hints, and exit codes.
|
|
35
|
+
|
|
36
|
+
\`--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 hundreds-of-thousands-token unscoped registry is compatibility-only. An unknown resource or action exits with code 1 and a JSON error envelope on stderr containing the valid options.
|
|
29
37
|
Credential lookup order is flags first, then \`DATAIKU_*\` environment variables, then saved credentials.
|
|
30
38
|
Set \`DATAIKU_DISABLE_ENV=1\` when a test must ignore both \`.env\` files and \`DATAIKU_*\` environment variables.
|
|
31
39
|
When \`.env\` loading is enabled, the CLI reads \`.env\` from the command's current working directory first and then the CLI build/root directory; the invocation directory wins on conflicting keys. Put test-specific \`.env\` files in the directory where you invoke \`dss\`.
|
|
@@ -37,7 +45,7 @@ For disposable agent tests, set \`DSS_CONFIG_DIR\` to a temporary directory so s
|
|
|
37
45
|
- Use \`--dry-run\` only when that action's registry entry has \`dryRun:true\`. \`--plan\` explains the operation; \`--dry-run\` exercises the action-specific simulation path. Never add an unsupported flag.
|
|
38
46
|
- When a create/upload action advertises \`--record-cleanup\`, pass \`--record-cleanup cleanup.jsonl\`. \`dss cleanup --file cleanup.jsonl\` previews the recorded cleanup steps in reverse order and does not mutate DSS; add \`--apply\` only after checking the preview.
|
|
39
47
|
- For JSON payload actions, follow \`inputContract\`, \`requiredFlags\`, and \`requiredOneOf\`. Prefer \`--data-file PATH\` or \`--stdin\` when advertised instead of inline \`--data\`; this preserves exact JSON across shells and keeps large or sensitive payloads out of process arguments.
|
|
40
|
-
- Authenticated actions advertise \`--request-timeout MS\` and \`--retries N
|
|
48
|
+
- Authenticated actions advertise \`--request-timeout MS\` and \`--retries N\`; \`--retries\` applies to idempotent GET requests. Long-running actions separately advertise controls such as \`--timeout MS\`, \`--poll-interval MS\`, and log limits; use only the flags in that action's registry entry.
|
|
41
49
|
- Before live mutation tests, use \`dss fixtures --json\` to discover compatible test resources instead of guessing project objects.
|
|
42
50
|
|
|
43
51
|
## Authentication
|
|
@@ -84,25 +92,74 @@ TLS flags: \`--insecure\` disables certificate verification; \`--ca-cert PATH\`
|
|
|
84
92
|
\`\`\`text
|
|
85
93
|
dss version
|
|
86
94
|
dss project list
|
|
87
|
-
dss doctor --fast
|
|
88
95
|
dss dataset list --project-key MYPROJ
|
|
89
|
-
dss dataset list --project-key MYPROJ --fields name,type
|
|
90
|
-
dss dataset preview orders --max-rows 10 --project-key MYPROJ
|
|
91
|
-
dss recipe get-payload compute_orders --project-key MYPROJ
|
|
92
|
-
dss recipe get-payload compute_orders --raw --project-key MYPROJ
|
|
93
96
|
dss recipe get-payload compute_orders --raw --output code.py --project-key MYPROJ
|
|
94
97
|
dss recipe diff compute_orders --file code.py --project-key MYPROJ
|
|
95
98
|
dss recipe set-payload compute_orders --file code.py --project-key MYPROJ
|
|
96
99
|
dss job build-and-wait orders --include-logs --project-key MYPROJ
|
|
97
|
-
dss scenario run daily_build --project-key MYPROJ
|
|
98
100
|
dss sql query --connection analytics --sql "select 1" --project-key MYPROJ
|
|
99
|
-
dss sql query --dataset MYPROJ.orders --sql-file query.sql
|
|
100
|
-
dss notebook clear-jupyter-outputs exploration --dry-run --project-key MYPROJ
|
|
101
|
-
dss api-service list-packages churn-service --project-key MYPROJ
|
|
102
101
|
dss batch --data-file steps.json
|
|
103
102
|
\`\`\`
|
|
104
103
|
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":"..."}\`.
|
|
105
104
|
|
|
105
|
+
## Application release safety
|
|
106
|
+
|
|
107
|
+
Treat app release as explicit validate, compare, version, successor, verify, and permission gates.
|
|
108
|
+
The public app-manifest \`version\` field is raw metadata: writing it is NOT a publish transaction.
|
|
109
|
+
New instances inherit the template's raw \`version\`; existing instances are never upgraded in
|
|
110
|
+
place — create an additive successor (the old instance is preserved), verify it, then retire the
|
|
111
|
+
old one as a separate guarded step. Never infer private publish/recreate/rename,
|
|
112
|
+
recipient-sharing, or UI-click operations that the public DSS API does not expose.
|
|
113
|
+
|
|
114
|
+
\`\`\`text
|
|
115
|
+
dss app validate-manifest --project-key APP_TEMPLATE
|
|
116
|
+
dss app compare-manifest APP_ID --project-key RELEASE_INSTANCE
|
|
117
|
+
dss app manifest-version --project-key APP_TEMPLATE
|
|
118
|
+
dss app set-manifest-version --manifest-version 1.4.0 --project-key APP_TEMPLATE
|
|
119
|
+
# targetProjectKey in instance.json must be confirmed absent
|
|
120
|
+
dss app create-instance APP_ID --data-file instance.json --wait --record-cleanup cleanup.jsonl
|
|
121
|
+
dss app create-successor-instance APP_ID --from RELEASE_INSTANCE --to RELEASE_INSTANCE_V2 --copy-permissions --record-cleanup cleanup.jsonl
|
|
122
|
+
dss app verify-instance APP_ID --project-key RELEASE_INSTANCE_V2 --expect-version 1.4.0
|
|
123
|
+
dss cleanup --file cleanup.jsonl
|
|
124
|
+
dss app permissions-snapshot --project-key RELEASE_INSTANCE --output permissions.json
|
|
125
|
+
dss app permissions-diff --project-key RELEASE_INSTANCE --file permissions.json
|
|
126
|
+
dss app permissions-restore --project-key RELEASE_INSTANCE --file permissions.json --dry-run
|
|
127
|
+
\`\`\`
|
|
128
|
+
|
|
129
|
+
An invalid manifest exits non-zero with the validation result in the structured error details.
|
|
130
|
+
Review the cleanup preview before \`dss cleanup --file cleanup.jsonl --apply\`. Every new entry is
|
|
131
|
+
bound to the canonical DSS URL. App cleanup records a \`creationTag\` hash observed after the DSS
|
|
132
|
+
future identifies its target key; unconfirmed creation stops unresolved. The future target and
|
|
133
|
+
later \`creationTag\` are independent, non-atomic observations because the public API exposes
|
|
134
|
+
neither an immutable project ID joined to the future nor a conditional DELETE. Cleanup rechecks
|
|
135
|
+
type and \`creationTag\` immediately before deletion, rejecting detected key reuse but unable to
|
|
136
|
+
eliminate replacement in the remaining check-to-DELETE gap. Apply validates the full ledger before
|
|
137
|
+
any request and rejects legacy, mixed-server, mismatched-server, or unbound app cleanup entries.
|
|
138
|
+
The successor's cleanup ledger entry targets only the new project key;
|
|
139
|
+
the predecessor is never targeted. Some DSS deployments return 403 for an unknown target project:
|
|
140
|
+
instance creation requires confirmed target absence before POST, so an inaccessible target absent
|
|
141
|
+
from the visible project list is still rejected as unconfirmed rather than risking cleanup against
|
|
142
|
+
a pre-existing project. A definitive create rejection never produces a cleanup entry.
|
|
143
|
+
|
|
144
|
+
\`app set-manifest-version\` reports
|
|
145
|
+
\`concurrencyControl:"client-side-non-atomic-stale-read-check"\`. \`--expect-hash SHA256\` refuses the
|
|
146
|
+
write when the manifest already changed, but the PUT itself stays unconditional: this command can
|
|
147
|
+
overwrite a writer that commits inside the read-then-write window, and the post-write read cannot
|
|
148
|
+
detect that lost update when this command's payload wins. Never treat the hash as a serializing lock.
|
|
149
|
+
An ambiguous manifest PUT or verification read exits non-zero with \`persisted:null\`,
|
|
150
|
+
\`after:null\`, and \`outcome:"indeterminate"\`; it never claims success or rejection.
|
|
151
|
+
|
|
152
|
+
The API key authenticates public REST only. \`app verify-instance\` reports \`apiReady:true\`,
|
|
153
|
+
\`status:"API_VERIFIED_UI_PENDING"\`, and \`uiPublicationVerified:false\`. Its \`visual-ui\` gate
|
|
154
|
+
requires a pre-authenticated SSO browser session or dedicated UI test identity and evidence from
|
|
155
|
+
exercising the affected tiles, forms, and actions; the CLI never marks that external gate complete.
|
|
156
|
+
Permission snapshots have an integrity hash bound to the canonical DSS URL, project key, and
|
|
157
|
+
observed concrete project incarnation from \`creationTag\`; diff and restore reject detected server,
|
|
158
|
+
key, or incarnation mismatches. DSS exposes no conditional permission PUT, so these client-side checks
|
|
159
|
+
narrow and detect key-reuse races but cannot serialize the final check with the write. Snapshots
|
|
160
|
+
contain access-control identities; keep them mode \`0600\` and commit them only when repository
|
|
161
|
+
policy permits.
|
|
162
|
+
|
|
106
163
|
## Confirming mutations
|
|
107
164
|
|
|
108
165
|
Mutations print a small JSON ack to stdout and exit 0 on success (e.g. \`{"updated":"NAME","resource":"recipe"}\`); on failure they print the error envelope to stderr and exit non-zero. The exit code is the source of truth.
|
|
@@ -122,10 +179,11 @@ Mutations print a small JSON ack to stdout and exit 0 on success (e.g. \`{"updat
|
|
|
122
179
|
- \`dss api-service list-packages SERVICE\` first verifies the parent service through its settings. A \`not_found\` error means the service is missing (verify the service ID and project key); an empty array means the service exists but has no deployable packages. Do not reinterpret \`not_found\` as an empty package list or retry the lower-level packages route.
|
|
123
180
|
- \`dss notebook clear-jupyter-outputs NAME --dry-run\` returns the full \`current\` and \`next\` notebook states. Applying it clears \`outputs\` and resets \`execution_count\` to \`0\` only on code cells, preserving markdown and raw cells unchanged.
|
|
124
181
|
- \`dss sql query ... --dataset PROJECT.NAME\` first queries through the dataset. If DSS rejects that dataset connection as neither SQL nor HDFS, the CLI reads dataset metadata and retries with \`params.connection\` (using its schema or catalog as the database when available). A readable dataset with no usable connection exits with \`validation_failed\` and advises \`--connection\`; dataset metadata \`404\` and \`403\` errors propagate as \`not_found\` and \`permission_denied\`.
|
|
182
|
+
- \`dss sql query ... --start-retries N\` opts the query-start POST into transient retries with exponential backoff. A lost response can cause DSS to execute the SQL more than once, so use it only for SQL whose repetition is safe; ordinary \`--retries N\` remains GET-only.
|
|
125
183
|
|
|
126
184
|
## Error envelope
|
|
127
185
|
|
|
128
|
-
|
|
186
|
+
For dispatch/runtime failures, parse stderr as JSONL; the final line is an error event:
|
|
129
187
|
|
|
130
188
|
\`\`\`json
|
|
131
189
|
{
|
|
@@ -140,6 +198,7 @@ Parse each stderr line as JSON; on non-zero exit the final line is an error even
|
|
|
140
198
|
}
|
|
141
199
|
\`\`\`
|
|
142
200
|
|
|
201
|
+
\`doctor\`, \`batch\`, and \`cleanup\` report command-level failures on stdout and leave stderr empty. Use the exit code before choosing a stream.
|
|
143
202
|
Use \`code\`, \`category\`, \`exitCode\`, \`retryable\`, \`status\`, and \`details\` for recovery logic. Do not scrape message text when a structured field is available.
|
|
144
203
|
Treat \`details.body\` as sanitized metadata only: it contains at most \`requestId\`/\`request_id\`/\`errorId\`/\`elapsedMs\` plus locally trusted target/timing fields, not the arbitrary DSS response body. \`details.statusText\` is canonical text derived from the numeric status, not a remote reason phrase. Base recovery on top-level \`code\`, \`category\`, \`status\`, \`retryable\`, \`requestId\`, \`hint\`, and \`details.dssCategory\`; never parse or expose assumed server-body fields.
|
|
145
204
|
`;
|
|
@@ -148,8 +207,8 @@ name: dataiku-dss
|
|
|
148
207
|
description: >-
|
|
149
208
|
Agent-only JSON CLI for Dataiku DSS. Use to inspect or mutate DSS projects,
|
|
150
209
|
datasets, recipes, jobs, scenarios, folders, notebooks, SQL, variables,
|
|
151
|
-
code envs, and connections. Discover
|
|
152
|
-
dss commands run.
|
|
210
|
+
code envs, and connections. Discover scoped command metadata with
|
|
211
|
+
dss commands run --fields RESOURCE.ACTION --json.
|
|
153
212
|
---
|
|
154
213
|
|
|
155
214
|
`;
|
|
@@ -7,9 +7,42 @@ export interface CleanupLedgerEntry {
|
|
|
7
7
|
name?: string;
|
|
8
8
|
path?: string;
|
|
9
9
|
projectKey?: string;
|
|
10
|
+
/** Canonical DSS base URL the entry was recorded against. Absent only on legacy ledgers. */
|
|
11
|
+
dssUrl?: string;
|
|
10
12
|
cleanup: {
|
|
11
13
|
argv: string[];
|
|
12
14
|
};
|
|
13
15
|
}
|
|
14
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Prove that a cleanup ledger path can be written before any remote mutation.
|
|
18
|
+
* A parent directory is created when missing (matching append behavior); an
|
|
19
|
+
* existing ledger file is opened for append; a not-yet-existing ledger file is
|
|
20
|
+
* probed by creating and removing a sibling file, so nothing is left behind.
|
|
21
|
+
* Throws a plain Error with a non-secret message on any failure.
|
|
22
|
+
*/
|
|
23
|
+
export declare function preflightCleanupLedgerPath(filePath: string): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Atomically bind a cleanup ledger path to one DSS server before a mutation.
|
|
26
|
+
* The adjacent owner-only reservation closes the empty-ledger race: processes
|
|
27
|
+
* targeting different servers cannot both pass preflight and mutate before
|
|
28
|
+
* either cleanup entry is appended. The reservation intentionally persists
|
|
29
|
+
* even when a mutation fails, because another same-server process may already
|
|
30
|
+
* rely on it.
|
|
31
|
+
*/
|
|
32
|
+
export declare function reserveCleanupLedgerDssUrl(filePath: string, dssUrl: string): Promise<void>;
|
|
33
|
+
export interface CleanupLedgerBindingViolation {
|
|
34
|
+
index: number;
|
|
35
|
+
resource: string;
|
|
36
|
+
action: string;
|
|
37
|
+
reason: "missing" | "mismatch";
|
|
38
|
+
/** Canonical URL the entry was bound to, for mismatch reasons. */
|
|
39
|
+
found?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* First entry not exactly bound to `expectedDssUrl` (both canonicalized), in
|
|
43
|
+
* ledger order. Legacy entries without a `dssUrl` count as missing. Intentionally
|
|
44
|
+
* never exposes argv/ids: the violation is identifiable by index alone.
|
|
45
|
+
*/
|
|
46
|
+
export declare function findCleanupLedgerBindingViolation(entries: CleanupLedgerEntry[], expectedDssUrl: string): CleanupLedgerBindingViolation | undefined;
|
|
47
|
+
export declare function appendCleanupLedgerEntry(filePath: string, entry: CleanupLedgerEntry, dssUrl: string): Promise<void>;
|
|
15
48
|
export declare function readCleanupLedger(filePath: string): Promise<CleanupLedgerEntry[]>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { canonicalDssUrl, } from "./dss-url.js";
|
|
3
4
|
function isCleanupLedgerEntry(value) {
|
|
4
5
|
if (!value || typeof value !== "object")
|
|
5
6
|
return false;
|
|
@@ -12,16 +13,126 @@ function isCleanupLedgerEntry(value) {
|
|
|
12
13
|
return false;
|
|
13
14
|
if (!candidate.cleanup || typeof candidate.cleanup !== "object")
|
|
14
15
|
return false;
|
|
16
|
+
if (candidate.dssUrl !== undefined && typeof candidate.dssUrl !== "string")
|
|
17
|
+
return false;
|
|
15
18
|
const cleanup = candidate.cleanup;
|
|
16
19
|
return Array.isArray(cleanup.argv) && cleanup.argv.every((arg) => typeof arg === "string");
|
|
17
20
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Prove that a cleanup ledger path can be written before any remote mutation.
|
|
23
|
+
* A parent directory is created when missing (matching append behavior); an
|
|
24
|
+
* existing ledger file is opened for append; a not-yet-existing ledger file is
|
|
25
|
+
* probed by creating and removing a sibling file, so nothing is left behind.
|
|
26
|
+
* Throws a plain Error with a non-secret message on any failure.
|
|
27
|
+
*/
|
|
28
|
+
export async function preflightCleanupLedgerPath(filePath) {
|
|
29
|
+
const resolved = path.resolve(filePath);
|
|
30
|
+
const parent = path.dirname(resolved);
|
|
31
|
+
await fs.mkdir(parent, { recursive: true, });
|
|
32
|
+
let stats;
|
|
33
|
+
try {
|
|
34
|
+
stats = await fs.stat(resolved);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
if (error.code !== "ENOENT") {
|
|
38
|
+
throw new Error(`Could not preflight cleanup ledger ${resolved}: ${error instanceof Error ? error.message : String(error)}`, { cause: error, });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (stats?.isDirectory()) {
|
|
42
|
+
throw new Error(`Cleanup ledger path is a directory, not a file: ${resolved}`);
|
|
43
|
+
}
|
|
44
|
+
if (stats !== undefined) {
|
|
45
|
+
try {
|
|
46
|
+
const handle = await fs.open(resolved, "a");
|
|
47
|
+
await handle.close();
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
const code = error.code;
|
|
51
|
+
throw new Error(code === "EACCES" || code === "EPERM"
|
|
52
|
+
? `Cleanup ledger file is not writable: ${resolved}`
|
|
53
|
+
: `Could not preflight cleanup ledger ${resolved}: ${error instanceof Error ? error.message : String(error)}`, { cause: error, });
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const probePrefix = `${resolved}.preflight-`;
|
|
58
|
+
try {
|
|
59
|
+
const probe = await fs.mkdtemp(probePrefix);
|
|
60
|
+
await fs.rm(probe, { recursive: true, force: true, });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
throw new Error(`Cleanup ledger directory is not writable: ${parent}${error instanceof Error ? ` (${error.message})` : ""}`, { cause: error, });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Atomically bind a cleanup ledger path to one DSS server before a mutation.
|
|
68
|
+
* The adjacent owner-only reservation closes the empty-ledger race: processes
|
|
69
|
+
* targeting different servers cannot both pass preflight and mutate before
|
|
70
|
+
* either cleanup entry is appended. The reservation intentionally persists
|
|
71
|
+
* even when a mutation fails, because another same-server process may already
|
|
72
|
+
* rely on it.
|
|
73
|
+
*/
|
|
74
|
+
export async function reserveCleanupLedgerDssUrl(filePath, dssUrl) {
|
|
75
|
+
const resolved = path.resolve(filePath);
|
|
76
|
+
const bindingPath = `${resolved}.dss-url`;
|
|
77
|
+
const expected = canonicalDssUrl(dssUrl);
|
|
78
|
+
await fs.mkdir(path.dirname(resolved), { recursive: true, });
|
|
79
|
+
try {
|
|
80
|
+
await fs.writeFile(bindingPath, `${expected}\n`, {
|
|
81
|
+
encoding: "utf-8",
|
|
82
|
+
flag: "wx",
|
|
83
|
+
mode: 0o600,
|
|
84
|
+
});
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (error.code !== "EEXIST")
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
const raw = await fs.readFile(bindingPath, "utf-8");
|
|
92
|
+
let found;
|
|
93
|
+
try {
|
|
94
|
+
found = canonicalDssUrl(raw.trim());
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
throw new Error("Cleanup ledger DSS binding is invalid.", { cause: error, });
|
|
98
|
+
}
|
|
99
|
+
if (found !== expected) {
|
|
100
|
+
throw new Error("Cleanup ledger is reserved for a different DSS server.");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* First entry not exactly bound to `expectedDssUrl` (both canonicalized), in
|
|
105
|
+
* ledger order. Legacy entries without a `dssUrl` count as missing. Intentionally
|
|
106
|
+
* never exposes argv/ids: the violation is identifiable by index alone.
|
|
107
|
+
*/
|
|
108
|
+
export function findCleanupLedgerBindingViolation(entries, expectedDssUrl) {
|
|
109
|
+
const expected = canonicalDssUrl(expectedDssUrl);
|
|
110
|
+
for (const [index, entry,] of entries.entries()) {
|
|
111
|
+
const bound = typeof entry.dssUrl === "string" ? canonicalDssUrl(entry.dssUrl) : undefined;
|
|
112
|
+
if (!bound) {
|
|
113
|
+
return { index, resource: entry.resource, action: entry.action, reason: "missing", };
|
|
114
|
+
}
|
|
115
|
+
if (bound !== expected) {
|
|
116
|
+
return {
|
|
117
|
+
index,
|
|
118
|
+
resource: entry.resource,
|
|
119
|
+
action: entry.action,
|
|
120
|
+
reason: "mismatch",
|
|
121
|
+
found: bound,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
export async function appendCleanupLedgerEntry(filePath, entry, dssUrl) {
|
|
128
|
+
const resolved = path.resolve(filePath);
|
|
129
|
+
await fs.mkdir(path.dirname(resolved), { recursive: true, });
|
|
130
|
+
await reserveCleanupLedgerDssUrl(resolved, dssUrl);
|
|
131
|
+
const bound = { ...entry, dssUrl: canonicalDssUrl(dssUrl), };
|
|
132
|
+
await fs.appendFile(resolved, `${JSON.stringify(bound)}\n`, "utf-8");
|
|
22
133
|
}
|
|
23
134
|
export async function readCleanupLedger(filePath) {
|
|
24
|
-
const content = await readFile(resolve(filePath), "utf-8");
|
|
135
|
+
const content = await fs.readFile(path.resolve(filePath), "utf-8");
|
|
25
136
|
return content
|
|
26
137
|
.split(/\r?\n/)
|
|
27
138
|
.map((line) => line.trim())
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical identity for a DSS base URL stored in local safety artifacts.
|
|
3
|
+
* Formatting differences do not break binding, and embedded URL credentials
|
|
4
|
+
* are never serialized or echoed.
|
|
5
|
+
*/
|
|
6
|
+
export function canonicalDssUrl(raw) {
|
|
7
|
+
const trimmed = raw.trim().replace(/\/+$/, "");
|
|
8
|
+
try {
|
|
9
|
+
const parsed = new URL(trimmed);
|
|
10
|
+
parsed.username = "";
|
|
11
|
+
parsed.password = "";
|
|
12
|
+
return parsed.toString().replace(/\/+$/, "");
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return trimmed.replace(/^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)[^/@]*@/, "$1");
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fingerprint one concrete DSS project incarnation using only the immutable
|
|
3
|
+
* creationTag. Mutable project metadata, including projectAppType and
|
|
4
|
+
* versionTag, is intentionally excluded.
|
|
5
|
+
*/
|
|
6
|
+
export declare function projectIncarnationHash(projectKey: string, projectDetails: unknown): string | undefined;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { stableHash, } from "./stable-hash.js";
|
|
2
|
+
function plainRecord(value) {
|
|
3
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
4
|
+
? value
|
|
5
|
+
: undefined;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Fingerprint one concrete DSS project incarnation using only the immutable
|
|
9
|
+
* creationTag. Mutable project metadata, including projectAppType and
|
|
10
|
+
* versionTag, is intentionally excluded.
|
|
11
|
+
*/
|
|
12
|
+
export function projectIncarnationHash(projectKey, projectDetails) {
|
|
13
|
+
const details = plainRecord(projectDetails);
|
|
14
|
+
if (!details)
|
|
15
|
+
return undefined;
|
|
16
|
+
const returnedKey = details["projectKey"];
|
|
17
|
+
if (typeof returnedKey !== "string" || returnedKey.trim() !== projectKey)
|
|
18
|
+
return undefined;
|
|
19
|
+
const creationTag = plainRecord(details["creationTag"]);
|
|
20
|
+
if (!creationTag)
|
|
21
|
+
return undefined;
|
|
22
|
+
const lastModifiedOn = creationTag["lastModifiedOn"];
|
|
23
|
+
if (!(typeof lastModifiedOn === "number" && Number.isFinite(lastModifiedOn))
|
|
24
|
+
&& !(typeof lastModifiedOn === "string" && lastModifiedOn.trim().length > 0))
|
|
25
|
+
return undefined;
|
|
26
|
+
return stableHash({ projectKey, creationTag, });
|
|
27
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function sha256Hex(value: string): string;
|
|
2
|
+
/** Locale-independent UTF-16 code-unit order for deterministic machine output. */
|
|
3
|
+
export declare function compareStrings(a: string, b: string): number;
|
|
4
|
+
/**
|
|
5
|
+
* Deterministic JSON rendering: object keys are emitted in sorted order so two
|
|
6
|
+
* structurally identical values always produce the same string (and therefore
|
|
7
|
+
* the same hash) regardless of key insertion order. Array order is preserved
|
|
8
|
+
* because it is semantic.
|
|
9
|
+
*/
|
|
10
|
+
export declare function stableJson(value: unknown): string;
|
|
11
|
+
export declare function stableHash(value: unknown): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createHash, } from "node:crypto";
|
|
2
|
+
export function sha256Hex(value) {
|
|
3
|
+
return createHash("sha256").update(value).digest("hex");
|
|
4
|
+
}
|
|
5
|
+
/** Locale-independent UTF-16 code-unit order for deterministic machine output. */
|
|
6
|
+
export function compareStrings(a, b) {
|
|
7
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Deterministic JSON rendering: object keys are emitted in sorted order so two
|
|
11
|
+
* structurally identical values always produce the same string (and therefore
|
|
12
|
+
* the same hash) regardless of key insertion order. Array order is preserved
|
|
13
|
+
* because it is semantic.
|
|
14
|
+
*/
|
|
15
|
+
export function stableJson(value) {
|
|
16
|
+
if (value === undefined)
|
|
17
|
+
return "undefined";
|
|
18
|
+
if (value === null || typeof value !== "object")
|
|
19
|
+
return JSON.stringify(value);
|
|
20
|
+
if (Array.isArray(value))
|
|
21
|
+
return `[${value.map((item) => stableJson(item)).join(",")}]`;
|
|
22
|
+
const entries = Object.entries(value).sort(([a,], [b,]) => compareStrings(a, b));
|
|
23
|
+
return `{${entries.map(([key, item,]) => `${JSON.stringify(key)}:${stableJson(item)}`).join(",")}}`;
|
|
24
|
+
}
|
|
25
|
+
export function stableHash(value) {
|
|
26
|
+
return sha256Hex(stableJson(value));
|
|
27
|
+
}
|
|
@@ -91,35 +91,6 @@ var Character;
|
|
|
91
91
|
Character.IsNumeric = IsNumeric;
|
|
92
92
|
})(Character || (Character = {}));
|
|
93
93
|
// ------------------------------------------------------------------
|
|
94
|
-
// MemberExpression
|
|
95
|
-
// ------------------------------------------------------------------
|
|
96
|
-
var MemberExpression;
|
|
97
|
-
(function (MemberExpression) {
|
|
98
|
-
function IsFirstCharacterNumeric(value) {
|
|
99
|
-
if (value.length === 0)
|
|
100
|
-
return false;
|
|
101
|
-
return Character.IsNumeric(value.charCodeAt(0));
|
|
102
|
-
}
|
|
103
|
-
function IsAccessor(value) {
|
|
104
|
-
if (IsFirstCharacterNumeric(value))
|
|
105
|
-
return false;
|
|
106
|
-
for (let i = 0; i < value.length; i++) {
|
|
107
|
-
const code = value.charCodeAt(i);
|
|
108
|
-
const check = Character.IsAlpha(code) || Character.IsNumeric(code) || Character.DollarSign(code) || Character.IsUnderscore(code);
|
|
109
|
-
if (!check)
|
|
110
|
-
return false;
|
|
111
|
-
}
|
|
112
|
-
return true;
|
|
113
|
-
}
|
|
114
|
-
function EscapeHyphen(key) {
|
|
115
|
-
return key.replace(/'/g, "\\'");
|
|
116
|
-
}
|
|
117
|
-
function Encode(object, key) {
|
|
118
|
-
return IsAccessor(key) ? `${object}.${key}` : `${object}['${EscapeHyphen(key)}']`;
|
|
119
|
-
}
|
|
120
|
-
MemberExpression.Encode = Encode;
|
|
121
|
-
})(MemberExpression || (MemberExpression = {}));
|
|
122
|
-
// ------------------------------------------------------------------
|
|
123
94
|
// Identifier
|
|
124
95
|
// ------------------------------------------------------------------
|
|
125
96
|
var Identifier;
|
|
@@ -140,15 +111,21 @@ var Identifier;
|
|
|
140
111
|
Identifier.Encode = Encode;
|
|
141
112
|
})(Identifier || (Identifier = {}));
|
|
142
113
|
// ------------------------------------------------------------------
|
|
143
|
-
//
|
|
114
|
+
// StringConstant
|
|
144
115
|
// ------------------------------------------------------------------
|
|
145
|
-
|
|
146
|
-
(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
116
|
+
function StringConstant(value) {
|
|
117
|
+
if (!(0, index_12.IsString)(value))
|
|
118
|
+
throw Error('ConstantString: Not a String');
|
|
119
|
+
const canonical = JSON.stringify(value).slice(1, -1);
|
|
120
|
+
const escaped = canonical.replace(/'/g, "\\'");
|
|
121
|
+
return `'${escaped}'`;
|
|
122
|
+
}
|
|
123
|
+
// ------------------------------------------------------------------
|
|
124
|
+
// MemberExpression
|
|
125
|
+
// ------------------------------------------------------------------
|
|
126
|
+
function MemberExpression(value, key) {
|
|
127
|
+
return `${value}[${StringConstant(key)}]`;
|
|
128
|
+
}
|
|
152
129
|
// ------------------------------------------------------------------
|
|
153
130
|
// Errors
|
|
154
131
|
// ------------------------------------------------------------------
|
|
@@ -172,7 +149,7 @@ exports.TypeCompilerTypeGuardError = TypeCompilerTypeGuardError;
|
|
|
172
149
|
var Policy;
|
|
173
150
|
(function (Policy) {
|
|
174
151
|
function IsExactOptionalProperty(value, key, expression) {
|
|
175
|
-
return index_3.TypeSystemPolicy.ExactOptionalPropertyTypes ? `(
|
|
152
|
+
return index_3.TypeSystemPolicy.ExactOptionalPropertyTypes ? `(${StringConstant(key)} in ${value} ? ${expression} : true)` : `(${MemberExpression(value, key)} !== undefined ? ${expression} : true)`;
|
|
176
153
|
}
|
|
177
154
|
Policy.IsExactOptionalProperty = IsExactOptionalProperty;
|
|
178
155
|
function IsObjectLike(value) {
|
|
@@ -317,8 +294,11 @@ var TypeCompiler;
|
|
|
317
294
|
if (typeof schema.const === 'number' || typeof schema.const === 'boolean') {
|
|
318
295
|
yield `(${value} === ${schema.const})`;
|
|
319
296
|
}
|
|
297
|
+
else if (typeof schema.const === 'string') {
|
|
298
|
+
yield `(${value} === ${StringConstant(schema.const)})`;
|
|
299
|
+
}
|
|
320
300
|
else {
|
|
321
|
-
|
|
301
|
+
throw Error('Invalid Literal Value');
|
|
322
302
|
}
|
|
323
303
|
}
|
|
324
304
|
function* FromNever(schema, references, value) {
|
|
@@ -352,12 +332,12 @@ var TypeCompiler;
|
|
|
352
332
|
yield `Object.getOwnPropertyNames(${value}).length <= ${schema.maxProperties}`;
|
|
353
333
|
const knownKeys = Object.getOwnPropertyNames(schema.properties);
|
|
354
334
|
for (const knownKey of knownKeys) {
|
|
355
|
-
const memberExpression = MemberExpression
|
|
335
|
+
const memberExpression = MemberExpression(value, knownKey);
|
|
356
336
|
const property = schema.properties[knownKey];
|
|
357
337
|
if (schema.required && schema.required.includes(knownKey)) {
|
|
358
338
|
yield* Visit(property, references, memberExpression);
|
|
359
339
|
if ((0, extends_undefined_1.ExtendsUndefinedCheck)(property) || IsAnyOrUnknown(property))
|
|
360
|
-
yield `(
|
|
340
|
+
yield `(${StringConstant(knownKey)} in ${value})`;
|
|
361
341
|
}
|
|
362
342
|
else {
|
|
363
343
|
const expression = CreateExpression(property, references, memberExpression);
|
|
@@ -369,13 +349,13 @@ var TypeCompiler;
|
|
|
369
349
|
yield `Object.getOwnPropertyNames(${value}).length === ${knownKeys.length}`;
|
|
370
350
|
}
|
|
371
351
|
else {
|
|
372
|
-
const keys = `[${knownKeys.map((key) =>
|
|
352
|
+
const keys = `[${knownKeys.map((key) => `${StringConstant(key)}`).join(', ')}]`;
|
|
373
353
|
yield `Object.getOwnPropertyNames(${value}).every(key => ${keys}.includes(key))`;
|
|
374
354
|
}
|
|
375
355
|
}
|
|
376
356
|
if (typeof schema.additionalProperties === 'object') {
|
|
377
357
|
const expression = CreateExpression(schema.additionalProperties, references, `${value}[key]`);
|
|
378
|
-
const keys = `[${knownKeys.map((key) =>
|
|
358
|
+
const keys = `[${knownKeys.map((key) => `${StringConstant(key)}`).join(', ')}]`;
|
|
379
359
|
yield `(Object.getOwnPropertyNames(${value}).every(key => ${keys}.includes(key) || ${expression}))`;
|
|
380
360
|
}
|
|
381
361
|
}
|
|
@@ -423,7 +403,7 @@ var TypeCompiler;
|
|
|
423
403
|
yield `${variable}.test(${value})`;
|
|
424
404
|
}
|
|
425
405
|
if (schema.format !== undefined) {
|
|
426
|
-
yield `format(
|
|
406
|
+
yield `format(${StringConstant(schema.format)}, ${value})`;
|
|
427
407
|
}
|
|
428
408
|
}
|
|
429
409
|
function* FromSymbol(schema, references, value) {
|
|
@@ -471,7 +451,7 @@ var TypeCompiler;
|
|
|
471
451
|
function* FromKind(schema, references, value) {
|
|
472
452
|
const instance = state.instances.size;
|
|
473
453
|
state.instances.set(instance, schema);
|
|
474
|
-
yield `kind(
|
|
454
|
+
yield `kind(${StringConstant(schema[index_7.Kind])}, ${instance}, ${value})`;
|
|
475
455
|
}
|
|
476
456
|
function* Visit(schema, references, value, useHoisting = true) {
|
|
477
457
|
const references_ = (0, index_12.IsString)(schema.$id) ? [...references, schema] : references;
|
|
@@ -645,7 +625,7 @@ var TypeCompiler;
|
|
|
645
625
|
/** Compiles a TypeBox type for optimal runtime type checking. Types must be valid TypeBox types of TSchema */
|
|
646
626
|
function Compile(schema, references = []) {
|
|
647
627
|
const generatedCode = Code(schema, references, { language: 'javascript' });
|
|
648
|
-
const compiledFunction =
|
|
628
|
+
const compiledFunction = (0, index_3.Evaluate)('kind', 'format', 'hash', generatedCode);
|
|
649
629
|
const instances = new Map(state.instances);
|
|
650
630
|
function typeRegistryFunction(kind, instance, value) {
|
|
651
631
|
if (!index_8.TypeRegistry.Has(kind) || !instances.has(instance))
|
|
@@ -20,4 +20,4 @@ export declare function IsTuple(value: unknown): value is ITuple;
|
|
|
20
20
|
/** Returns true if the value is a Union Parser */
|
|
21
21
|
export declare function IsUnion(value: unknown): value is IUnion;
|
|
22
22
|
/** Returns true if the value is a Parser */
|
|
23
|
-
export declare function IsParser(value: unknown): value is
|
|
23
|
+
export declare function IsParser(value: unknown): value is IArray<unknown> | IConst<unknown> | IContext<unknown> | IIdent<unknown> | INumber<unknown> | IOptional<unknown> | IRef<unknown> | IString<unknown> | ITuple<unknown> | IUnion<unknown>;
|
|
@@ -3,6 +3,6 @@ export declare function Const(value: string, code: string): [] | [string, string
|
|
|
3
3
|
/** Scans for the next Ident token */
|
|
4
4
|
export declare function Ident(code: string): [] | [string, string];
|
|
5
5
|
/** Scans for the next number token */
|
|
6
|
-
export declare function Number(code: string): [
|
|
6
|
+
export declare function Number(code: string): [] | [string, string];
|
|
7
7
|
/** Scans the next Literal String value */
|
|
8
|
-
export declare function String(options: string[], code: string): [
|
|
8
|
+
export declare function String(options: string[], code: string): [] | [string, string];
|
|
@@ -121,7 +121,7 @@ export declare function AsyncIteratorMapping(input: [unknown, unknown, unknown,
|
|
|
121
121
|
export type TIteratorMapping<Input extends [unknown, unknown, unknown, unknown], Context extends T.TProperties> = Input extends ['Iterator', '<', infer Type extends T.TSchema, '>'] ? T.TIterator<Type> : never;
|
|
122
122
|
export declare function IteratorMapping(input: [unknown, unknown, unknown, unknown], context: unknown): T.TIterator<T.TSchema>;
|
|
123
123
|
export type TArgumentMapping<Input extends [unknown, unknown, unknown, unknown], Context extends T.TProperties> = Input extends ['Argument', '<', infer Type extends T.TSchema, '>'] ? Type extends T.TLiteral<infer Index extends number> ? T.TArgument<Index> : T.TNever : never;
|
|
124
|
-
export declare function ArgumentMapping(input: [unknown, unknown, unknown, unknown], context: unknown): T.
|
|
124
|
+
export declare function ArgumentMapping(input: [unknown, unknown, unknown, unknown], context: unknown): T.TArgument<number> | T.TNever;
|
|
125
125
|
export type TAwaitedMapping<Input extends [unknown, unknown, unknown, unknown], Context extends T.TProperties> = Input extends ['Awaited', '<', infer Type extends T.TSchema, '>'] ? T.TAwaited<Type> : never;
|
|
126
126
|
export declare function AwaitedMapping(input: [unknown, unknown, unknown, unknown], context: unknown): T.TSchema;
|
|
127
127
|
export type TArrayMapping<Input extends [unknown, unknown, unknown, unknown], Context extends T.TProperties> = Input extends ['Array', '<', infer Type extends T.TSchema, '>'] ? T.TArray<Type> : never;
|