dataiku-sdk 0.12.1 → 0.12.3
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 +46 -11
- package/bin/dss.js +25 -30
- package/dist/src/cli/commands/api-service.js +0 -1
- package/dist/src/cli/commands/notebook.js +5 -1
- package/dist/src/cli/output.js +1 -1
- package/dist/src/cli.js +44 -14
- package/dist/src/errors.d.ts +9 -1
- package/dist/src/errors.js +39 -6
- package/dist/src/resources/api-services.js +1 -0
- package/dist/src/resources/notebooks.js +9 -5
- package/dist/src/resources/sql.js +18 -25
- package/dist/src/skill.js +54 -27
- package/package.json +16 -10
package/README.md
CHANGED
|
@@ -2,7 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
Agent-only TypeScript SDK and `dss` CLI for Dataiku DSS automation.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Platform support
|
|
6
|
+
|
|
7
|
+
The published `dss` CLI supports Linux, macOS, and Windows under Bun >= 1.3.14 or Node.js >= 22.15.0. The release gate runs Bun 1.3.14 with Node 24 on all three operating systems, plus a lightweight minimum-Node 22.15 package smoke on Linux. The runtime dependency is pure JavaScript, so the same package also runs on runtime-supported x64 and ARM64 systems.
|
|
8
|
+
|
|
9
|
+
Run directly with Bun:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
bunx --bun dataiku-sdk version
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Or install the npm binary:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
npm install --global dataiku-sdk
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Bun is the primary development runtime and package manager. Examples below assume an installed `dss` binary. From a checkout, use `bun --no-env-file src/cli.ts ...` or the cross-runtime `bun --no-env-file ./bin/dss.js ...` launcher. Node users can invoke the same launcher as `node ./bin/dss.js ...`; if `dist/` is absent, it delegates to Bun. From another working directory, pass the checkout's absolute `bin/dss.js` path to Bun or Node.
|
|
6
22
|
`--no-env-file` disables Bun's automatic preloading only; the CLI still applies its documented `.env` handling unless `DATAIKU_DISABLE_ENV=1` is set.
|
|
7
23
|
|
|
8
24
|
## CLI contract
|
|
@@ -13,12 +29,12 @@ Examples below assume the installed `dss` binary. From this checkout, use `./bin
|
|
|
13
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.
|
|
14
30
|
- No prompts, help screens, tables, banners, or prose output are part of the contract.
|
|
15
31
|
- Exit codes: `0` success, `1` usage/configuration error, `2` DSS/internal error, `3` transient DSS error, `4` completed command with failed long-running DSS work.
|
|
16
|
-
- The exit code is the success signal
|
|
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.
|
|
17
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.
|
|
18
34
|
|
|
19
35
|
Discover the agent protocol and complete machine-readable command surface:
|
|
20
36
|
|
|
21
|
-
```
|
|
37
|
+
```text
|
|
22
38
|
dss agent contract
|
|
23
39
|
dss commands run
|
|
24
40
|
```
|
|
@@ -27,7 +43,7 @@ Agents should parse `agent contract` once for protocol/schema compatibility, the
|
|
|
27
43
|
|
|
28
44
|
## Agent skill installation
|
|
29
45
|
|
|
30
|
-
```
|
|
46
|
+
```text
|
|
31
47
|
dss install-skill --list-agents
|
|
32
48
|
dss install-skill --agent omp --target .
|
|
33
49
|
dss install-skill --agent omp --target . --dry-run
|
|
@@ -48,22 +64,41 @@ Global installs write under the agent's home config path, for example OMP: `~/.o
|
|
|
48
64
|
|
|
49
65
|
## Credentials
|
|
50
66
|
|
|
51
|
-
Use environment variables for ephemeral runs
|
|
52
|
-
For disposable agent tests, set `DSS_CONFIG_DIR` to a temporary directory so saved credentials never touch your real profile.
|
|
67
|
+
Use environment variables for ephemeral runs. For disposable agent tests, set `DSS_CONFIG_DIR` to a temporary directory so saved credentials never touch your real profile.
|
|
53
68
|
Credential precedence is flags first, then `DATAIKU_*` environment variables, then saved credentials in `DSS_CONFIG_DIR` or the platform config directory.
|
|
54
69
|
Set `DATAIKU_DISABLE_ENV=1` when a test must ignore both `.env` files and `DATAIKU_*` environment variables.
|
|
55
70
|
When `.env` loading is enabled, the CLI reads `.env` from the CLI build/root directory and from the command's current working directory; put test-specific `.env` files in the directory where you invoke `dss`.
|
|
56
71
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
72
|
+
POSIX shell:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
export DATAIKU_URL=https://dss.example.com
|
|
76
|
+
export DATAIKU_API_KEY=your-api-key
|
|
77
|
+
export DATAIKU_PROJECT_KEY=MYPROJ
|
|
78
|
+
dss project list
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
PowerShell:
|
|
82
|
+
|
|
83
|
+
```powershell
|
|
84
|
+
$env:DATAIKU_URL = "https://dss.example.com"
|
|
85
|
+
$env:DATAIKU_API_KEY = "your-api-key"
|
|
86
|
+
$env:DATAIKU_PROJECT_KEY = "MYPROJ"
|
|
87
|
+
dss project list
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Windows Command Prompt:
|
|
91
|
+
|
|
92
|
+
```bat
|
|
93
|
+
set "DATAIKU_URL=https://dss.example.com"
|
|
94
|
+
set "DATAIKU_API_KEY=your-api-key"
|
|
95
|
+
set "DATAIKU_PROJECT_KEY=MYPROJ"
|
|
61
96
|
dss project list
|
|
62
97
|
```
|
|
63
98
|
|
|
64
99
|
Persist credentials when needed:
|
|
65
100
|
|
|
66
|
-
```
|
|
101
|
+
```text
|
|
67
102
|
dss auth login --url https://dss.example.com --api-key YOUR_KEY --project-key MYPROJ
|
|
68
103
|
```
|
|
69
104
|
|
package/bin/dss.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawnSync, } from "node:child_process";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import * as path from "node:path";
|
|
5
5
|
import { fileURLToPath, pathToFileURL, } from "node:url";
|
|
6
6
|
|
|
7
7
|
const args = process.argv.slice(2,);
|
|
8
8
|
const optionArgs = args.includes("--",) ? args.slice(0, args.indexOf("--",),) : args;
|
|
9
|
-
const here = dirname(fileURLToPath(import.meta.url,),);
|
|
10
|
-
const distCliPath = resolve(here, "../dist/src/cli.js",);
|
|
11
|
-
const sourceCliPath = resolve(here, "../src/cli.ts",);
|
|
12
|
-
const cliPath = existsSync(distCliPath,) ? distCliPath : sourceCliPath;
|
|
9
|
+
const here = path.dirname(fileURLToPath(import.meta.url,),);
|
|
10
|
+
const distCliPath = path.resolve(here, "../dist/src/cli.js",);
|
|
11
|
+
const sourceCliPath = path.resolve(here, "../src/cli.ts",);
|
|
12
|
+
const cliPath = fs.existsSync(distCliPath,) ? distCliPath : sourceCliPath;
|
|
13
13
|
const cliUrl = pathToFileURL(cliPath,).href;
|
|
14
14
|
|
|
15
15
|
function flagValue(names,) {
|
|
@@ -40,11 +40,6 @@ async function loadSavedTlsSettings() {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
function supportsSystemCa(nodeBin,) {
|
|
44
|
-
const probe = spawnSync(nodeBin, ["--use-system-ca", "-e", "",], { stdio: "ignore", },);
|
|
45
|
-
return !probe.error && probe.status === 0;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
43
|
const savedTls = await loadSavedTlsSettings();
|
|
49
44
|
const env = { ...process.env, };
|
|
50
45
|
const explicitCaCert = flagValue(["--ca-cert", "--extra-ca-certs",],);
|
|
@@ -62,12 +57,13 @@ if (hasFlag(["--insecure", "--skip-tls-verify",],)) {
|
|
|
62
57
|
env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
63
58
|
}
|
|
64
59
|
|
|
65
|
-
const
|
|
60
|
+
const runningOnBun = Boolean(process.versions.bun,);
|
|
66
61
|
const usesSourceCli = cliPath === sourceCliPath;
|
|
67
|
-
const
|
|
62
|
+
const runtimeBin = runningOnBun ? process.execPath : usesSourceCli ? "bun" : process.execPath;
|
|
63
|
+
const runtimeArgs = runningOnBun || usesSourceCli ? ["--no-env-file",] : ["--use-system-ca",];
|
|
68
64
|
const result = spawnSync(
|
|
69
|
-
|
|
70
|
-
[...
|
|
65
|
+
runtimeBin,
|
|
66
|
+
[...runtimeArgs, cliPath, ...args,],
|
|
71
67
|
{
|
|
72
68
|
stdio: "inherit",
|
|
73
69
|
env,
|
|
@@ -77,25 +73,24 @@ const result = spawnSync(
|
|
|
77
73
|
if (result.error) {
|
|
78
74
|
const message = usesSourceCli
|
|
79
75
|
? `Unable to start Bun runtime for source dss CLI (${result.error.message}).`
|
|
80
|
-
: `Unable to start
|
|
76
|
+
: `Unable to start ${
|
|
77
|
+
runningOnBun ? "Bun" : "Node"
|
|
78
|
+
} runtime for packaged dss CLI (${result.error.message}); falling back to the current runtime.`;
|
|
81
79
|
if (usesSourceCli) {
|
|
82
80
|
process.stderr.write(`${
|
|
83
|
-
JSON.stringify(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
},
|
|
92
|
-
null,
|
|
93
|
-
2,
|
|
94
|
-
)
|
|
81
|
+
JSON.stringify({
|
|
82
|
+
type: "error",
|
|
83
|
+
ok: false,
|
|
84
|
+
error: message,
|
|
85
|
+
code: "internal_error",
|
|
86
|
+
category: "internal",
|
|
87
|
+
exitCode: 2,
|
|
88
|
+
},)
|
|
95
89
|
}\n`,);
|
|
96
|
-
process.
|
|
90
|
+
process.exitCode = 2;
|
|
91
|
+
} else {
|
|
92
|
+
await import(cliUrl);
|
|
97
93
|
}
|
|
98
|
-
await import(cliUrl);
|
|
99
94
|
} else if (result.signal) {
|
|
100
95
|
process.kill(process.pid, result.signal,);
|
|
101
96
|
} else {
|
|
@@ -59,7 +59,6 @@ export const apiServiceCommands = {
|
|
|
59
59
|
handler: async (c, a, f) => {
|
|
60
60
|
requireArgs(a, 1, "dss api-service list-packages <serviceId> [--project-key KEY]");
|
|
61
61
|
const projectKey = f["project-key"];
|
|
62
|
-
await c.apiServices.getSettings(a[0], projectKey);
|
|
63
62
|
return c.apiServices.listPackages(a[0], projectKey);
|
|
64
63
|
},
|
|
65
64
|
usage: "dss api-service list-packages <serviceId> [--project-key KEY]",
|
|
@@ -44,7 +44,11 @@ export const notebookCommands = {
|
|
|
44
44
|
const current = await c.notebooks.getJupyter(a[0], pk);
|
|
45
45
|
const next = {
|
|
46
46
|
...current,
|
|
47
|
-
cells: current.cells.map((cell) =>
|
|
47
|
+
cells: current.cells.map((cell) => {
|
|
48
|
+
if (cell.cell_type !== "code")
|
|
49
|
+
return cell;
|
|
50
|
+
return { ...cell, outputs: [], execution_count: 0, };
|
|
51
|
+
}),
|
|
48
52
|
};
|
|
49
53
|
return {
|
|
50
54
|
dryRun: true,
|
package/dist/src/cli/output.js
CHANGED
|
@@ -73,7 +73,7 @@ export function transientBodyWithTargetContext(body, target, elapsedMs) {
|
|
|
73
73
|
}
|
|
74
74
|
export function addTransientTargetContext(error, target, elapsedMs) {
|
|
75
75
|
if (error instanceof DataikuError && error.category === "transient") {
|
|
76
|
-
throw new DataikuError(error.status, error.statusText, transientBodyWithTargetContext(error.body, target, elapsedMs), error.retry, error.requestId);
|
|
76
|
+
throw new DataikuError(error.status, error.statusText, transientBodyWithTargetContext(error.body, target, elapsedMs), error.retry, error.requestId, { target, elapsedMs, });
|
|
77
77
|
}
|
|
78
78
|
throw error;
|
|
79
79
|
}
|
package/dist/src/cli.js
CHANGED
|
@@ -12,7 +12,7 @@ import { COMMANDS_RUN_HINT, missingActionError, noCommandError, requireArgs, unk
|
|
|
12
12
|
import { cliVersionResult, } from "./cli/version.js";
|
|
13
13
|
import { DataikuClient, } from "./client.js";
|
|
14
14
|
import { getCredentialsPath, } from "./config.js";
|
|
15
|
-
import { ClientValidationError, DataikuError, dataikuErrorCode, } from "./errors.js";
|
|
15
|
+
import { canonicalStatusText, ClientValidationError, DataikuError, dataikuErrorCode, } from "./errors.js";
|
|
16
16
|
import { AGENTS, detectAgents, findWorkspaceRoot, installSkill, planSkillInstalls, } from "./skill.js";
|
|
17
17
|
import { appendCleanupLedgerEntry, readCleanupLedger, } from "./utils/cleanup-ledger.js";
|
|
18
18
|
// ---------------------------------------------------------------------------
|
|
@@ -833,16 +833,41 @@ function rawCommandContext() {
|
|
|
833
833
|
: undefined),
|
|
834
834
|
};
|
|
835
835
|
}
|
|
836
|
-
|
|
836
|
+
const SAFE_RESPONSE_METADATA_KEYS = [
|
|
837
|
+
"requestId",
|
|
838
|
+
"request_id",
|
|
839
|
+
"errorId",
|
|
840
|
+
"elapsedMs",
|
|
841
|
+
];
|
|
842
|
+
function safeResponseMetadata(body) {
|
|
837
843
|
try {
|
|
838
844
|
const parsed = JSON.parse(body);
|
|
839
|
-
|
|
840
|
-
|
|
845
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
846
|
+
return {};
|
|
847
|
+
const metadata = {};
|
|
848
|
+
for (const key of SAFE_RESPONSE_METADATA_KEYS) {
|
|
849
|
+
const value = parsed[key];
|
|
850
|
+
if ((typeof value === "string" && value.length > 0)
|
|
851
|
+
|| (typeof value === "number" && Number.isFinite(value))
|
|
852
|
+
|| typeof value === "boolean") {
|
|
853
|
+
metadata[key] = value;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
return metadata;
|
|
841
857
|
}
|
|
842
858
|
catch {
|
|
843
|
-
return
|
|
859
|
+
return {};
|
|
844
860
|
}
|
|
845
861
|
}
|
|
862
|
+
function requestIdFromBody(body) {
|
|
863
|
+
const metadata = safeResponseMetadata(body);
|
|
864
|
+
for (const key of ["requestId", "request_id", "errorId",]) {
|
|
865
|
+
const value = metadata[key];
|
|
866
|
+
if (typeof value === "string")
|
|
867
|
+
return value;
|
|
868
|
+
}
|
|
869
|
+
return undefined;
|
|
870
|
+
}
|
|
846
871
|
const MISSING_PROJECT_KEY_ERROR_PREFIX = "projectKey is required";
|
|
847
872
|
function errorExitCode(err) {
|
|
848
873
|
if (err instanceof CommandResultFailure)
|
|
@@ -884,13 +909,18 @@ function buildErrorReport(err) {
|
|
|
884
909
|
};
|
|
885
910
|
}
|
|
886
911
|
if (err instanceof DataikuError) {
|
|
887
|
-
const errorMessage = err.category === "not_found"
|
|
888
|
-
&& err.message.includes("Dataiku instance not found")
|
|
889
|
-
&& context.resource
|
|
912
|
+
const errorMessage = err.category === "not_found" && context.resource
|
|
890
913
|
? `Not found: ${context.resource}${context.action ? ` ${context.action}` : ""}`
|
|
891
914
|
+ `${context.projectKey ? ` in project ${context.projectKey}` : ""}`
|
|
892
|
-
+
|
|
893
|
-
|
|
915
|
+
+ " — verify the object identifier and project key."
|
|
916
|
+
+ `\nHint: ${err.retryHint}`
|
|
917
|
+
: err.safeMessage;
|
|
918
|
+
const safeMetadata = safeResponseMetadata(err.body);
|
|
919
|
+
if (err.trustedTarget)
|
|
920
|
+
safeMetadata.target = err.trustedTarget;
|
|
921
|
+
if (err.trustedElapsedMs !== undefined)
|
|
922
|
+
safeMetadata.elapsedMs = err.trustedElapsedMs;
|
|
923
|
+
const safeBody = JSON.stringify(safeMetadata);
|
|
894
924
|
return {
|
|
895
925
|
type: "error",
|
|
896
926
|
ok: false,
|
|
@@ -904,8 +934,8 @@ function buildErrorReport(err) {
|
|
|
904
934
|
requestId: err.requestId ?? requestIdFromBody(err.body),
|
|
905
935
|
details: {
|
|
906
936
|
dssCategory: err.category,
|
|
907
|
-
statusText: err.
|
|
908
|
-
body:
|
|
937
|
+
statusText: canonicalStatusText(err.status),
|
|
938
|
+
body: safeBody,
|
|
909
939
|
...(err.retry ? { retry: err.retry, } : {}),
|
|
910
940
|
},
|
|
911
941
|
...context,
|
|
@@ -969,7 +999,7 @@ async function main() {
|
|
|
969
999
|
if (metaCommand) {
|
|
970
1000
|
writeCommandResult(metaCommand.result);
|
|
971
1001
|
if (metaCommand.exitCode !== 0)
|
|
972
|
-
process.
|
|
1002
|
+
process.exitCode = metaCommand.exitCode;
|
|
973
1003
|
return;
|
|
974
1004
|
}
|
|
975
1005
|
if (!commands[resource])
|
|
@@ -1033,5 +1063,5 @@ async function main() {
|
|
|
1033
1063
|
}
|
|
1034
1064
|
main().catch((err) => {
|
|
1035
1065
|
writeErrorReport(err);
|
|
1036
|
-
process.
|
|
1066
|
+
process.exitCode = errorExitCode(err);
|
|
1037
1067
|
});
|
package/dist/src/errors.d.ts
CHANGED
|
@@ -15,6 +15,11 @@ export interface DataikuRetryMetadata {
|
|
|
15
15
|
delaysMs: number[];
|
|
16
16
|
timedOut: boolean;
|
|
17
17
|
}
|
|
18
|
+
export interface DataikuErrorTrustedMetadata {
|
|
19
|
+
target?: string;
|
|
20
|
+
elapsedMs?: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function canonicalStatusText(status: number): string;
|
|
18
23
|
export declare class ClientValidationError extends Error {
|
|
19
24
|
readonly code: StableErrorCode;
|
|
20
25
|
readonly hint?: string;
|
|
@@ -31,7 +36,10 @@ export declare class DataikuError extends Error {
|
|
|
31
36
|
retryHint: string;
|
|
32
37
|
retry?: DataikuRetryMetadata;
|
|
33
38
|
requestId?: string;
|
|
34
|
-
|
|
39
|
+
readonly trustedTarget?: string;
|
|
40
|
+
readonly trustedElapsedMs?: number;
|
|
41
|
+
constructor(status: number, statusText: string, body: string, retry?: DataikuRetryMetadata, requestId?: string, trustedMetadata?: DataikuErrorTrustedMetadata);
|
|
42
|
+
get safeMessage(): string;
|
|
35
43
|
private static extractSummary;
|
|
36
44
|
private static formatRetryMetadata;
|
|
37
45
|
private static buildDetails;
|
package/dist/src/errors.js
CHANGED
|
@@ -12,6 +12,25 @@ export function dataikuErrorCode(category) {
|
|
|
12
12
|
return "internal_error";
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
+
const CANONICAL_STATUS_TEXT = {
|
|
16
|
+
400: "Bad Request",
|
|
17
|
+
401: "Unauthorized",
|
|
18
|
+
403: "Forbidden",
|
|
19
|
+
404: "Not Found",
|
|
20
|
+
408: "Request Timeout",
|
|
21
|
+
409: "Conflict",
|
|
22
|
+
422: "Unprocessable Entity",
|
|
23
|
+
425: "Too Early",
|
|
24
|
+
429: "Too Many Requests",
|
|
25
|
+
500: "Internal Server Error",
|
|
26
|
+
501: "Not Implemented",
|
|
27
|
+
502: "Bad Gateway",
|
|
28
|
+
503: "Service Unavailable",
|
|
29
|
+
504: "Gateway Timeout",
|
|
30
|
+
};
|
|
31
|
+
export function canonicalStatusText(status) {
|
|
32
|
+
return CANONICAL_STATUS_TEXT[status] ?? (status === 0 ? "Network Error" : "HTTP Error");
|
|
33
|
+
}
|
|
15
34
|
export class ClientValidationError extends Error {
|
|
16
35
|
code;
|
|
17
36
|
hint;
|
|
@@ -276,8 +295,10 @@ export class DataikuError extends Error {
|
|
|
276
295
|
retryHint;
|
|
277
296
|
retry;
|
|
278
297
|
requestId;
|
|
279
|
-
|
|
280
|
-
|
|
298
|
+
trustedTarget;
|
|
299
|
+
trustedElapsedMs;
|
|
300
|
+
constructor(status, statusText, body, retry, requestId, trustedMetadata) {
|
|
301
|
+
const details = DataikuError.buildDetails(status, body, retry);
|
|
281
302
|
super(details.message);
|
|
282
303
|
this.status = status;
|
|
283
304
|
this.statusText = statusText;
|
|
@@ -288,8 +309,20 @@ export class DataikuError extends Error {
|
|
|
288
309
|
this.retryHint = details.retryHint;
|
|
289
310
|
this.retry = retry;
|
|
290
311
|
this.requestId = requestId;
|
|
312
|
+
this.trustedTarget = trustedMetadata?.target;
|
|
313
|
+
this.trustedElapsedMs = trustedMetadata?.elapsedMs;
|
|
314
|
+
}
|
|
315
|
+
get safeMessage() {
|
|
316
|
+
const retrySummary = DataikuError.formatRetryMetadata(this.retry);
|
|
317
|
+
return [
|
|
318
|
+
`${this.status} ${canonicalStatusText(this.status)}`,
|
|
319
|
+
`Error type: ${this.category}`,
|
|
320
|
+
`Retryable: ${this.retryable ? "yes" : "no"}`,
|
|
321
|
+
`Hint: ${this.retryHint}`,
|
|
322
|
+
...(retrySummary ? [retrySummary,] : []),
|
|
323
|
+
].join("\n");
|
|
291
324
|
}
|
|
292
|
-
static extractSummary(_status,
|
|
325
|
+
static extractSummary(_status, body) {
|
|
293
326
|
try {
|
|
294
327
|
const parsed = JSON.parse(body);
|
|
295
328
|
if (parsed.message)
|
|
@@ -316,14 +349,14 @@ export class DataikuError extends Error {
|
|
|
316
349
|
`Timed out: ${retry.timedOut ? "yes" : "no"}`,
|
|
317
350
|
].join(" | ");
|
|
318
351
|
}
|
|
319
|
-
static buildDetails(status,
|
|
320
|
-
const summary = DataikuError.extractSummary(status,
|
|
352
|
+
static buildDetails(status, body, retry) {
|
|
353
|
+
const summary = DataikuError.extractSummary(status, body);
|
|
321
354
|
const taxonomy = classifyDataikuError(status, body);
|
|
322
355
|
const retrySummary = DataikuError.formatRetryMetadata(retry);
|
|
323
356
|
return {
|
|
324
357
|
...taxonomy,
|
|
325
358
|
message: [
|
|
326
|
-
`${status} ${
|
|
359
|
+
`${status} ${canonicalStatusText(status)}: ${summary}`,
|
|
327
360
|
`Error type: ${taxonomy.category}`,
|
|
328
361
|
`Retryable: ${taxonomy.retryable ? "yes" : "no"}`,
|
|
329
362
|
`Hint: ${taxonomy.retryHint}`,
|
|
@@ -28,6 +28,7 @@ export class ApiServicesResource extends BaseResource {
|
|
|
28
28
|
}
|
|
29
29
|
/** List deployable packages for an API service. */
|
|
30
30
|
async listPackages(serviceId, projectKey) {
|
|
31
|
+
await this.getSettings(serviceId, projectKey);
|
|
31
32
|
return this.client.get(`${this.servicePath(serviceId, projectKey)}/packages`);
|
|
32
33
|
}
|
|
33
34
|
/** Get an API service package summary. */
|
|
@@ -36,11 +36,15 @@ export class NotebooksResource extends BaseResource {
|
|
|
36
36
|
*/
|
|
37
37
|
async clearJupyterOutputs(name, projectKey) {
|
|
38
38
|
const notebook = await this.getJupyter(name, projectKey);
|
|
39
|
-
const clearedCells = notebook.cells.map((cell) =>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
const clearedCells = notebook.cells.map((cell) => {
|
|
40
|
+
if (cell.cell_type !== "code")
|
|
41
|
+
return cell;
|
|
42
|
+
return {
|
|
43
|
+
...cell,
|
|
44
|
+
outputs: [],
|
|
45
|
+
execution_count: 0,
|
|
46
|
+
};
|
|
47
|
+
});
|
|
44
48
|
await this.saveJupyter(name, { ...notebook, cells: clearedCells, }, projectKey);
|
|
45
49
|
}
|
|
46
50
|
/** List running kernel sessions for a Jupyter notebook. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DataikuError, } from "../errors.js";
|
|
1
|
+
import { ClientValidationError, DataikuError, } from "../errors.js";
|
|
2
2
|
import { BaseResource, } from "./base.js";
|
|
3
3
|
const UNSUPPORTED_SQL_DATASET_CONNECTION_DETAIL = "neither of sql nor hdfs type";
|
|
4
4
|
function isUnsupportedSqlDatasetConnectionError(error) {
|
|
@@ -161,28 +161,23 @@ export class SqlResource extends BaseResource {
|
|
|
161
161
|
const datasetFullName = opts.datasetFullName;
|
|
162
162
|
if (!datasetFullName)
|
|
163
163
|
return null;
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (!connection)
|
|
174
|
-
return null;
|
|
175
|
-
return {
|
|
176
|
-
...opts,
|
|
177
|
-
connection,
|
|
178
|
-
datasetFullName: undefined,
|
|
179
|
-
database: opts.database ?? asString(params?.schema) ?? asString(params?.catalog),
|
|
180
|
-
projectKey,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
catch {
|
|
164
|
+
const identifier = splitDatasetIdentifier(datasetFullName, opts.projectKey);
|
|
165
|
+
const projectKey = identifier.projectKey
|
|
166
|
+
? identifier.projectKey
|
|
167
|
+
: this.resolveProjectKey(opts.projectKey);
|
|
168
|
+
const dsEnc = encodeURIComponent(identifier.datasetName);
|
|
169
|
+
const raw = await this.client.get(`/public/api/projects/${encodeURIComponent(projectKey)}/datasets/${dsEnc}`);
|
|
170
|
+
const params = asRecord(raw.params);
|
|
171
|
+
const connection = asString(params?.connection);
|
|
172
|
+
if (!connection)
|
|
184
173
|
return null;
|
|
185
|
-
|
|
174
|
+
return {
|
|
175
|
+
...opts,
|
|
176
|
+
connection,
|
|
177
|
+
datasetFullName: undefined,
|
|
178
|
+
database: opts.database ?? asString(params?.schema) ?? asString(params?.catalog),
|
|
179
|
+
projectKey,
|
|
180
|
+
};
|
|
186
181
|
}
|
|
187
182
|
/**
|
|
188
183
|
* Execute a SQL query end-to-end: start, stream all rows, verify, return combined result.
|
|
@@ -198,9 +193,7 @@ export class SqlResource extends BaseResource {
|
|
|
198
193
|
withSqlErrorContext(error);
|
|
199
194
|
const retryOpts = await this.resolveDatasetQueryFallback(queryOpts);
|
|
200
195
|
if (!retryOpts) {
|
|
201
|
-
throw new
|
|
202
|
-
cause: error,
|
|
203
|
-
});
|
|
196
|
+
throw new ClientValidationError(buildUnsupportedSqlDatasetConnectionMessage(queryOpts.datasetFullName));
|
|
204
197
|
}
|
|
205
198
|
try {
|
|
206
199
|
return await this.executeQuery(retryOpts);
|
package/dist/src/skill.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { execFileSync, } from "node:child_process";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import * as path from "node:path";
|
|
5
5
|
const SKILL_BODY = `# Dataiku DSS agent CLI
|
|
6
6
|
|
|
7
7
|
Use \`dss\` when an agent needs to inspect or change Dataiku DSS resources: projects, datasets, recipes, jobs, scenarios, folders, notebooks, SQL, variables, code envs, and connections.
|
|
8
|
-
If the installed \`dss\` binary is unavailable but the repository checkout is the current workspace,
|
|
8
|
+
If the installed \`dss\` binary is unavailable but the repository checkout is the current workspace, prefer \`bun --no-env-file src/cli.ts ...\` or \`bun --no-env-file ./bin/dss.js ...\`. Node users can invoke the same cross-runtime launcher as \`node ./bin/dss.js ...\`; when \`dist/\` has not been built, it delegates to Bun. From another working directory, pass the checkout's absolute \`bin/dss.js\` path to Bun or Node.
|
|
9
9
|
\`--no-env-file\` disables Bun's automatic preloading only; the CLI still applies its documented \`.env\` handling unless \`DATAIKU_DISABLE_ENV=1\` is set.
|
|
10
10
|
|
|
11
11
|
## Contract
|
|
@@ -20,7 +20,7 @@ If the installed \`dss\` binary is unavailable but the repository checkout is th
|
|
|
20
20
|
|
|
21
21
|
## Discover commands
|
|
22
22
|
|
|
23
|
-
\`\`\`
|
|
23
|
+
\`\`\`text
|
|
24
24
|
dss agent contract
|
|
25
25
|
dss commands run
|
|
26
26
|
\`\`\`
|
|
@@ -31,30 +31,57 @@ Set \`DATAIKU_DISABLE_ENV=1\` when a test must ignore both \`.env\` files and \`
|
|
|
31
31
|
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\`.
|
|
32
32
|
For disposable agent tests, set \`DSS_CONFIG_DIR\` to a temporary directory so saved credentials never touch the real profile.
|
|
33
33
|
|
|
34
|
+
## Planning, safety, and generic inputs
|
|
35
|
+
|
|
36
|
+
- Before any registry entry with \`sideEffect:"write"\`, run the exact argv with \`--plan\` first. Planning is local: it returns the derived operation without resolving credentials or calling DSS. Check \`destructive\`, \`idempotency\`, \`async\`, \`unsafeOutputs\`, and \`exitCodes\` before execution.
|
|
37
|
+
- 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
|
+
- 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
|
+
- 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\`. 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
|
+
- Before live mutation tests, use \`dss fixtures --json\` to discover compatible test resources instead of guessing project objects.
|
|
42
|
+
|
|
34
43
|
## Authentication
|
|
35
44
|
|
|
36
|
-
Prefer environment variables for ephemeral agent runs:
|
|
45
|
+
Prefer environment variables for ephemeral agent runs. Use the syntax for the active shell:
|
|
37
46
|
|
|
38
|
-
|
|
47
|
+
POSIX shell:
|
|
48
|
+
|
|
49
|
+
\`\`\`sh
|
|
39
50
|
export DATAIKU_URL=https://dss.example.com
|
|
40
51
|
export DATAIKU_API_KEY=your-api-key
|
|
41
52
|
export DATAIKU_PROJECT_KEY=MYPROJ
|
|
42
53
|
\`\`\`
|
|
43
54
|
|
|
55
|
+
PowerShell:
|
|
56
|
+
|
|
57
|
+
\`\`\`powershell
|
|
58
|
+
$env:DATAIKU_URL = "https://dss.example.com"
|
|
59
|
+
$env:DATAIKU_API_KEY = "your-api-key"
|
|
60
|
+
$env:DATAIKU_PROJECT_KEY = "MYPROJ"
|
|
61
|
+
\`\`\`
|
|
62
|
+
|
|
63
|
+
Windows Command Prompt:
|
|
64
|
+
|
|
65
|
+
\`\`\`bat
|
|
66
|
+
set "DATAIKU_URL=https://dss.example.com"
|
|
67
|
+
set "DATAIKU_API_KEY=your-api-key"
|
|
68
|
+
set "DATAIKU_PROJECT_KEY=MYPROJ"
|
|
69
|
+
\`\`\`
|
|
70
|
+
|
|
44
71
|
To persist credentials for later invocations:
|
|
45
72
|
|
|
46
73
|
\`\`\`bash
|
|
47
74
|
dss auth login --url https://dss.example.com --api-key YOUR_KEY --project-key MYPROJ
|
|
48
75
|
\`\`\`
|
|
49
76
|
|
|
50
|
-
The command saves credentials and returns \`{"saved":true,"path":"..."}\`.
|
|
77
|
+
The command saves credentials and returns \`{"saved":true,"path":"..."}\`. \`DSS_CONFIG_DIR\` wins when set. Otherwise credentials use \`XDG_CONFIG_HOME/dataiku/credentials.json\`, the \`dataiku/credentials.json\` directory under \`APPDATA\` on Windows, or \`~/.config/dataiku/credentials.json\`.
|
|
51
78
|
\`auth login\` validates by listing accessible projects before saving credentials, so the API key must be allowed to call DSS project-list APIs.
|
|
52
79
|
|
|
53
80
|
TLS flags: \`--insecure\` disables certificate verification; \`--ca-cert PATH\` adds a PEM CA bundle. Environment equivalents: \`NODE_TLS_REJECT_UNAUTHORIZED\`, \`NODE_EXTRA_CA_CERTS\`.
|
|
54
81
|
|
|
55
82
|
## Common workflows
|
|
56
83
|
|
|
57
|
-
\`\`\`
|
|
84
|
+
\`\`\`text
|
|
58
85
|
dss version
|
|
59
86
|
dss project list
|
|
60
87
|
dss doctor --fast
|
|
@@ -77,10 +104,10 @@ For fake-DSS smoke tests, return project lists as JSON arrays such as \`[{"proje
|
|
|
77
104
|
|
|
78
105
|
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.
|
|
79
106
|
|
|
80
|
-
-
|
|
81
|
-
-
|
|
107
|
+
- For portable multi-step writes, prefer \`dss batch\` (payload: a JSON array of argv arrays). It runs fail-fast, returns one envelope with per-step \`ok\`/\`result\`/\`error\`, and exits non-zero if any step fails.
|
|
108
|
+
- If separate processes are required, inspect each exit code and stop before launching the next step. Do not rely on shell chaining: syntax differs between POSIX shells, Windows PowerShell 5.1, PowerShell 7, and Command Prompt.
|
|
109
|
+
- Never pipe a mutation into a command that prints a fixed string or merges stderr: a pipeline may return the helper's exit code and report a failed mutation as success.
|
|
82
110
|
- To branch in code, key off the exit code or the JSON ack on stdout — never a hardcoded label.
|
|
83
|
-
- For multi-step writes, prefer \`dss batch\` (payload: a JSON array of argv arrays): it runs fail-fast, returns one envelope with per-step \`ok\`/\`result\`/\`error\`, and exits non-zero if any step fails — no shell chaining or per-step parsing.
|
|
84
111
|
|
|
85
112
|
## Platform & debugging notes
|
|
86
113
|
|
|
@@ -127,7 +154,7 @@ export const AGENTS = {
|
|
|
127
154
|
name: "Claude Code",
|
|
128
155
|
binary: "claude",
|
|
129
156
|
configDir: ".claude",
|
|
130
|
-
globalPath: (home) => join(home, ".claude", "skills", "dataiku-dss"),
|
|
157
|
+
globalPath: (home) => path.join(home, ".claude", "skills", "dataiku-dss"),
|
|
131
158
|
projectPath: ".claude/skills/dataiku-dss",
|
|
132
159
|
filename: "SKILL.md",
|
|
133
160
|
content: skillContent,
|
|
@@ -136,7 +163,7 @@ export const AGENTS = {
|
|
|
136
163
|
name: "Codex",
|
|
137
164
|
binary: "codex",
|
|
138
165
|
configDir: ".codex",
|
|
139
|
-
globalPath: (home) => join(home, ".codex", "skills", "dataiku-dss"),
|
|
166
|
+
globalPath: (home) => path.join(home, ".codex", "skills", "dataiku-dss"),
|
|
140
167
|
projectPath: ".codex/skills/dataiku-dss",
|
|
141
168
|
filename: "SKILL.md",
|
|
142
169
|
content: skillContent,
|
|
@@ -145,7 +172,7 @@ export const AGENTS = {
|
|
|
145
172
|
name: "Cursor",
|
|
146
173
|
binary: "cursor",
|
|
147
174
|
configDir: ".cursor",
|
|
148
|
-
globalPath: (home) => join(home, ".cursor", "skills", "dataiku-dss"),
|
|
175
|
+
globalPath: (home) => path.join(home, ".cursor", "skills", "dataiku-dss"),
|
|
149
176
|
projectPath: ".cursor/skills/dataiku-dss",
|
|
150
177
|
filename: "SKILL.md",
|
|
151
178
|
content: skillContent,
|
|
@@ -154,7 +181,7 @@ export const AGENTS = {
|
|
|
154
181
|
name: "Pi",
|
|
155
182
|
binary: "pi",
|
|
156
183
|
configDir: ".pi",
|
|
157
|
-
globalPath: (home) => join(home, ".pi", "agent", "skills", "dataiku-dss"),
|
|
184
|
+
globalPath: (home) => path.join(home, ".pi", "agent", "skills", "dataiku-dss"),
|
|
158
185
|
projectPath: ".pi/skills/dataiku-dss",
|
|
159
186
|
filename: "SKILL.md",
|
|
160
187
|
content: skillContent,
|
|
@@ -162,9 +189,9 @@ export const AGENTS = {
|
|
|
162
189
|
omp: {
|
|
163
190
|
name: "OhMyPi",
|
|
164
191
|
binary: "omp",
|
|
165
|
-
configDir: join(".omp", "agent"),
|
|
192
|
+
configDir: path.join(".omp", "agent"),
|
|
166
193
|
configDirRequired: true,
|
|
167
|
-
globalPath: (home) => join(home, ".omp", "agent", "skills", "dataiku-dss"),
|
|
194
|
+
globalPath: (home) => path.join(home, ".omp", "agent", "skills", "dataiku-dss"),
|
|
168
195
|
projectPath: ".omp/skills/dataiku-dss",
|
|
169
196
|
filename: "SKILL.md",
|
|
170
197
|
content: skillContent,
|
|
@@ -184,11 +211,11 @@ function binaryExists(name) {
|
|
|
184
211
|
}
|
|
185
212
|
}
|
|
186
213
|
export function detectAgents() {
|
|
187
|
-
const home = homedir();
|
|
214
|
+
const home = os.homedir();
|
|
188
215
|
const found = [];
|
|
189
216
|
for (const [id, def,] of Object.entries(AGENTS)) {
|
|
190
217
|
const hasBinary = binaryExists(def.binary);
|
|
191
|
-
const hasConfigDir = existsSync(join(home, def.configDir));
|
|
218
|
+
const hasConfigDir = fs.existsSync(path.join(home, def.configDir));
|
|
192
219
|
if (hasBinary && (!def.configDirRequired || hasConfigDir)) {
|
|
193
220
|
found.push({ id, def, via: "binary", });
|
|
194
221
|
}
|
|
@@ -213,10 +240,10 @@ export function findWorkspaceRoot(startDir) {
|
|
|
213
240
|
let dir = startDir;
|
|
214
241
|
for (let i = 0; i < 20; i++) {
|
|
215
242
|
for (const marker of WORKSPACE_MARKERS) {
|
|
216
|
-
if (existsSync(join(dir, marker)))
|
|
243
|
+
if (fs.existsSync(path.join(dir, marker)))
|
|
217
244
|
return dir;
|
|
218
245
|
}
|
|
219
|
-
const parent = dirname(dir);
|
|
246
|
+
const parent = path.dirname(dir);
|
|
220
247
|
if (parent === dir)
|
|
221
248
|
break;
|
|
222
249
|
dir = parent;
|
|
@@ -224,17 +251,17 @@ export function findWorkspaceRoot(startDir) {
|
|
|
224
251
|
return startDir;
|
|
225
252
|
}
|
|
226
253
|
export function planSkillInstalls(agents, opts) {
|
|
227
|
-
const home = homedir();
|
|
254
|
+
const home = os.homedir();
|
|
228
255
|
const results = [];
|
|
229
256
|
for (const { id, def, via, } of agents) {
|
|
230
257
|
const dir = opts.global
|
|
231
258
|
? def.globalPath(home)
|
|
232
259
|
: def.projectPath
|
|
233
|
-
? join(opts.cwd, def.projectPath)
|
|
260
|
+
? path.join(opts.cwd, def.projectPath)
|
|
234
261
|
: undefined;
|
|
235
262
|
if (!dir)
|
|
236
263
|
continue;
|
|
237
|
-
results.push({ agent: id, path: join(dir, def.filename), via, });
|
|
264
|
+
results.push({ agent: id, path: path.join(dir, def.filename), via, });
|
|
238
265
|
}
|
|
239
266
|
return results;
|
|
240
267
|
}
|
|
@@ -244,8 +271,8 @@ export function installSkill(agents, opts) {
|
|
|
244
271
|
const def = AGENTS[result.agent];
|
|
245
272
|
if (!def)
|
|
246
273
|
continue;
|
|
247
|
-
mkdirSync(dirname(result.path), { recursive: true, });
|
|
248
|
-
writeFileSync(result.path, def.content(), "utf-8");
|
|
274
|
+
fs.mkdirSync(path.dirname(result.path), { recursive: true, });
|
|
275
|
+
fs.writeFileSync(result.path, def.content(), "utf-8");
|
|
249
276
|
}
|
|
250
277
|
return results;
|
|
251
278
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dataiku-sdk",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"description": "Dataiku DSS SDK and CLI for programmatic access to DSS REST APIs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"workspaces": [
|
|
@@ -17,25 +17,28 @@
|
|
|
17
17
|
"packages/types/dist/"
|
|
18
18
|
],
|
|
19
19
|
"engines": {
|
|
20
|
-
"
|
|
20
|
+
"node": ">=22.15.0",
|
|
21
|
+
"bun": ">=1.3.14"
|
|
21
22
|
},
|
|
22
23
|
"scripts": {
|
|
23
|
-
"build": "tsc &&
|
|
24
|
-
"prepack": "
|
|
25
|
-
"prepublishOnly": "
|
|
24
|
+
"build": "tsc && tsc -p packages/types/tsconfig.json",
|
|
25
|
+
"prepack": "tsc && tsc -p packages/types/tsconfig.json",
|
|
26
|
+
"prepublishOnly": "tsc && tsc -p packages/types/tsconfig.json",
|
|
26
27
|
"check": "tsc --noEmit",
|
|
27
28
|
"lint": "oxlint src/",
|
|
28
29
|
"lint:fix": "oxlint --fix src/",
|
|
29
30
|
"format": "dprint fmt",
|
|
30
31
|
"format:check": "dprint check",
|
|
31
32
|
"test": "bun test",
|
|
32
|
-
"test:
|
|
33
|
-
"test:integration
|
|
34
|
-
"test:integration:
|
|
35
|
-
"test:integration:rigorous
|
|
33
|
+
"test:platform": "bun scripts/platform-smoke.mjs",
|
|
34
|
+
"test:integration": "cross-env RUN_DATAIKU_INTEGRATION=1 bun test tests/integration-playground.test.ts",
|
|
35
|
+
"test:integration:mutating": "cross-env RUN_DATAIKU_INTEGRATION=1 RUN_DATAIKU_INTEGRATION_MUTATING=1 bun test tests/integration-playground.test.ts",
|
|
36
|
+
"test:integration:rigorous": "cross-env RUN_DATAIKU_INTEGRATION=1 bun test tests/integration-rigorous.test.ts",
|
|
37
|
+
"test:integration:rigorous:mutating": "cross-env RUN_DATAIKU_INTEGRATION=1 RUN_DATAIKU_INTEGRATION_MUTATING=1 bun test tests/integration-rigorous.test.ts"
|
|
36
38
|
},
|
|
37
39
|
"devDependencies": {
|
|
38
40
|
"@types/bun": "^1.3.14",
|
|
41
|
+
"cross-env": "^10.1.0",
|
|
39
42
|
"dprint": "^0.54.0",
|
|
40
43
|
"oxlint": "^1.68.0",
|
|
41
44
|
"typescript": "^6.0.3"
|
|
@@ -53,5 +56,8 @@
|
|
|
53
56
|
},
|
|
54
57
|
"publishConfig": {
|
|
55
58
|
"access": "public"
|
|
56
|
-
}
|
|
59
|
+
},
|
|
60
|
+
"bundleDependencies": [
|
|
61
|
+
"@sinclair/typebox"
|
|
62
|
+
]
|
|
57
63
|
}
|