dataiku-sdk 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -17
- package/dist/build-metadata.json +1 -1
- package/dist/packages/types/src/index.d.ts +39 -4
- package/dist/packages/types/src/index.js +31 -2
- package/dist/src/cli/commands/api-service.js +62 -16
- package/dist/src/cli/commands/bundle.js +49 -15
- package/dist/src/cli/commands/code-env.js +210 -49
- package/dist/src/cli/commands/code.d.ts +19 -0
- package/dist/src/cli/commands/code.js +87 -15
- package/dist/src/cli/commands/dataset.js +8 -3
- package/dist/src/cli/commands/flow-zone.js +33 -5
- package/dist/src/cli/commands/notebook.js +72 -41
- package/dist/src/cli/commands/project-git.js +8 -5
- package/dist/src/cli/commands/project-library.d.ts +21 -0
- package/dist/src/cli/commands/project-library.js +121 -50
- package/dist/src/cli/commands/project.js +16 -2
- package/dist/src/cli/commands/recipe.js +37 -12
- package/dist/src/cli/commands/sql.d.ts +10 -0
- package/dist/src/cli/commands/sql.js +39 -17
- package/dist/src/cli/commands/webapp.js +67 -13
- package/dist/src/cli/contract.d.ts +15 -0
- package/dist/src/cli/contract.js +870 -107
- package/dist/src/cli/env.d.ts +9 -0
- package/dist/src/cli/env.js +20 -2
- package/dist/src/cli/flags.js +9 -0
- package/dist/src/cli/helpers/cleanup.js +104 -3
- package/dist/src/cli/helpers/flow-zone.d.ts +3 -0
- package/dist/src/cli/helpers/flow-zone.js +33 -3
- package/dist/src/cli/helpers/recipe.d.ts +20 -0
- package/dist/src/cli/helpers/recipe.js +158 -3
- package/dist/src/cli/output.d.ts +2 -0
- package/dist/src/cli/output.js +33 -6
- package/dist/src/cli/runtime.d.ts +35 -1
- package/dist/src/cli/runtime.js +125 -18
- package/dist/src/cli/types.d.ts +7 -0
- package/dist/src/cli.js +135 -28
- package/dist/src/client.d.ts +60 -0
- package/dist/src/client.js +237 -42
- package/dist/src/errors.d.ts +8 -2
- package/dist/src/errors.js +40 -0
- package/dist/src/index.d.ts +4 -3
- package/dist/src/index.js +2 -1
- package/dist/src/resources/api-services.d.ts +48 -6
- package/dist/src/resources/api-services.js +54 -8
- package/dist/src/resources/bundles.d.ts +51 -6
- package/dist/src/resources/bundles.js +39 -9
- package/dist/src/resources/code-envs.d.ts +25 -3
- package/dist/src/resources/code-envs.js +104 -2
- package/dist/src/resources/datasets.d.ts +20 -0
- package/dist/src/resources/datasets.js +232 -52
- package/dist/src/resources/jobs.d.ts +35 -10
- package/dist/src/resources/jobs.js +92 -17
- package/dist/src/resources/notebooks.d.ts +77 -7
- package/dist/src/resources/notebooks.js +143 -19
- package/dist/src/resources/project-git.d.ts +12 -0
- package/dist/src/resources/project-git.js +39 -8
- package/dist/src/resources/project-library.d.ts +122 -7
- package/dist/src/resources/project-library.js +494 -25
- package/dist/src/resources/projects.d.ts +5 -2
- package/dist/src/resources/projects.js +18 -2
- package/dist/src/resources/scenarios.d.ts +30 -0
- package/dist/src/resources/scenarios.js +73 -27
- package/dist/src/resources/sql.d.ts +6 -0
- package/dist/src/resources/sql.js +22 -2
- package/dist/src/resources/webapps.d.ts +35 -4
- package/dist/src/resources/webapps.js +54 -5
- package/dist/src/schemas.d.ts +2 -2
- package/dist/src/schemas.js +1 -1
- package/dist/src/skill.d.ts +9 -0
- package/dist/src/skill.js +37 -4
- package/dist/src/utils/flow-analysis.d.ts +53 -0
- package/dist/src/utils/flow-analysis.js +382 -0
- package/dist/src/utils/project-archive.d.ts +41 -2
- package/dist/src/utils/project-archive.js +159 -16
- package/package.json +4 -4
- package/packages/types/dist/index.d.ts +39 -4
- package/packages/types/dist/index.js +31 -2
- package/plugin.json +1 -1
- package/skills/dataiku-dss/SKILL.md +74 -47
|
@@ -1,18 +1,42 @@
|
|
|
1
1
|
import { readFileSync, } from "node:fs";
|
|
2
|
-
import {
|
|
2
|
+
import { writeFile, } from "node:fs/promises";
|
|
3
3
|
import { join, } from "node:path";
|
|
4
4
|
import { deepMerge, } from "../../utils/deep-merge.js";
|
|
5
5
|
import { jobLogFilterFromFlag, jsonInput, maxLogLinesFromFlags, normalizeLineEndings, num, recipeInputDatasetsFromFlags, requiredStringFlag, rewritePairsFromFlags, sha256Hex, splitCsvFlag, stableHash, } from "../coerce.js";
|
|
6
6
|
import { moveCreatedItemsToZone, resolveFlowZoneIdFromFlags, } from "../helpers/flow-zone.js";
|
|
7
|
-
import { readRecipeBackup, recipeBackupDocument, recipeBackupPath, recipeCodeEnv, recipeGraph, recipeInputItemRef, recipeRoleInputItems, recipeRunShouldWait, } from "../helpers/recipe.js";
|
|
7
|
+
import { ensureRecipeBackupDir, readRecipeBackup, recipeBackupDocument, recipeBackupPath, recipeCodeEnv, recipeGraph, recipeInputItemRef, recipeRoleInputItems, recipeRunShouldWait, writeRecipeBackup, } from "../helpers/recipe.js";
|
|
8
8
|
import { encodedProjectEndpoint, readIfExists, skipResult, } from "../output.js";
|
|
9
9
|
import { requireArgs, UsageError, } from "../usage.js";
|
|
10
|
+
/** Read a local recipe file before any DSS request, mapping read failures to usage validation. */
|
|
11
|
+
function readRecipeFile(filePath, flagName) {
|
|
12
|
+
try {
|
|
13
|
+
return readFileSync(filePath, "utf-8");
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
17
|
+
throw new UsageError(`Could not read ${flagName} ${filePath}: ${reason}.`, "not_found", "Verify the file path and that it is readable.");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Read a set-payload backup file before any DSS request, mapping read failures to usage validation. */
|
|
21
|
+
function readRecipeBackupFile(backupPath) {
|
|
22
|
+
try {
|
|
23
|
+
return readRecipeBackup(backupPath);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
27
|
+
throw new UsageError(`Could not read --backup ${backupPath}: ${reason}.`, "not_found", "Verify the backup file path and that it is readable.");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
10
30
|
function formatLineDiff(remoteName, localPath, remoteContent, localContent) {
|
|
11
|
-
|
|
31
|
+
// Line-ending differences are not content differences: compare and split on
|
|
32
|
+
// CRLF-normalized text, mirroring assert-unchanged's normalized payload hash.
|
|
33
|
+
const normalizedLocal = normalizeLineEndings(localContent);
|
|
34
|
+
const normalizedRemote = normalizeLineEndings(remoteContent);
|
|
35
|
+
if (normalizedLocal === normalizedRemote) {
|
|
12
36
|
return "No differences.";
|
|
13
37
|
}
|
|
14
|
-
const localLines =
|
|
15
|
-
const remoteLines =
|
|
38
|
+
const localLines = normalizedLocal.split("\n");
|
|
39
|
+
const remoteLines = normalizedRemote.split("\n");
|
|
16
40
|
const lines = [`--- remote:${remoteName}`, `+++ local:${localPath}`, "",];
|
|
17
41
|
const maxLen = Math.max(localLines.length, remoteLines.length);
|
|
18
42
|
for (let i = 0; i < maxLen; i++) {
|
|
@@ -104,7 +128,7 @@ export const recipeCommands = {
|
|
|
104
128
|
return c.recipes.run(a[0], options);
|
|
105
129
|
},
|
|
106
130
|
usage: "dss recipe run <name> [--wait|--no-wait] [--build-mode MODE] [--include-logs] [--log-filter stdout|stderr|user|errors] [--summary] [--max-log-lines N] [--timeout MS] [--poll-interval MS] [--partition PARTITION] [--dry-run] [--project-key KEY]",
|
|
107
|
-
description: "Run a recipe by resolving its outputs and submitting the correct dataset or managed-folder build job.",
|
|
131
|
+
description: "Run a recipe by resolving its outputs and submitting the correct dataset or managed-folder build job. --timeout defaults to 120000 ms and --poll-interval to 2000 ms.",
|
|
108
132
|
examples: [
|
|
109
133
|
"dss recipe run compute_orders --wait",
|
|
110
134
|
"dss recipe run compute_exports --include-logs --log-filter stdout --summary --timeout 600000",
|
|
@@ -344,6 +368,8 @@ export const recipeCommands = {
|
|
|
344
368
|
if (!filePath) {
|
|
345
369
|
throw new UsageError("--file is required. Usage: dss recipe diff <name> --file PATH");
|
|
346
370
|
}
|
|
371
|
+
// Read and validate the local file before any DSS request.
|
|
372
|
+
const localContent = readRecipeFile(filePath, "--file");
|
|
347
373
|
const result = await c.recipes.get(a[0], {
|
|
348
374
|
includePayload: true,
|
|
349
375
|
projectKey: f["project-key"],
|
|
@@ -351,7 +377,6 @@ export const recipeCommands = {
|
|
|
351
377
|
if (!result.payload) {
|
|
352
378
|
throw new Error(`Recipe "${a[0]}" has no code payload to diff.`);
|
|
353
379
|
}
|
|
354
|
-
const localContent = readFileSync(filePath, "utf-8");
|
|
355
380
|
return formatLineDiff(a[0], filePath, result.payload, localContent);
|
|
356
381
|
},
|
|
357
382
|
usage: "dss recipe diff <name> --file PATH [--project-key KEY]",
|
|
@@ -506,7 +531,7 @@ export const recipeCommands = {
|
|
|
506
531
|
const filePath = f["file"];
|
|
507
532
|
if (!filePath)
|
|
508
533
|
throw new UsageError("--file is required.");
|
|
509
|
-
const content =
|
|
534
|
+
const content = readRecipeFile(filePath, "--file");
|
|
510
535
|
const pk = f["project-key"];
|
|
511
536
|
const shouldBackup = f["no-backup"] !== true;
|
|
512
537
|
const backupDir = shouldBackup
|
|
@@ -530,8 +555,8 @@ export const recipeCommands = {
|
|
|
530
555
|
};
|
|
531
556
|
}
|
|
532
557
|
if (backupDir && backupPath) {
|
|
533
|
-
|
|
534
|
-
|
|
558
|
+
ensureRecipeBackupDir(backupDir);
|
|
559
|
+
writeRecipeBackup(backupPath, `${JSON.stringify(recipeBackupDocument(a[0], pk, current), null, 2)}\n`);
|
|
535
560
|
}
|
|
536
561
|
await c.recipes.replace(a[0], { ...current, payload: content, }, pk);
|
|
537
562
|
return {
|
|
@@ -555,7 +580,7 @@ export const recipeCommands = {
|
|
|
555
580
|
const usage = "dss recipe restore <name> --backup FILE [--payload-only] [--dry-run] [--project-key KEY]";
|
|
556
581
|
requireArgs(a, 1, usage);
|
|
557
582
|
const backupPath = requiredStringFlag(f, "backup", usage);
|
|
558
|
-
const backup =
|
|
583
|
+
const backup = readRecipeBackupFile(backupPath);
|
|
559
584
|
const payload = typeof backup.payload === "string" ? backup.payload : "";
|
|
560
585
|
const pk = f["project-key"];
|
|
561
586
|
const current = await c.recipes.get(a[0], { includePayload: true, projectKey: pk, });
|
|
@@ -598,7 +623,7 @@ export const recipeCommands = {
|
|
|
598
623
|
const usage = "dss recipe assert-unchanged <name> --since BACKUP [--project-key KEY]";
|
|
599
624
|
requireArgs(a, 1, usage);
|
|
600
625
|
const backupPath = requiredStringFlag(f, "since", usage);
|
|
601
|
-
const backup =
|
|
626
|
+
const backup = readRecipeBackupFile(backupPath);
|
|
602
627
|
const current = await c.recipes.get(a[0], {
|
|
603
628
|
includePayload: true,
|
|
604
629
|
projectKey: f["project-key"],
|
|
@@ -1,2 +1,12 @@
|
|
|
1
1
|
import type { CommandMeta } from "../types.js";
|
|
2
|
+
export declare function resolveSqlInput(args: string[], flags: Record<string, string | boolean>): string;
|
|
3
|
+
export interface SqlQueryInvocation {
|
|
4
|
+
query: string;
|
|
5
|
+
connection?: string;
|
|
6
|
+
datasetFullName?: string;
|
|
7
|
+
database?: string;
|
|
8
|
+
projectKey?: string;
|
|
9
|
+
type: "sql";
|
|
10
|
+
}
|
|
11
|
+
export declare function resolveSqlQueryInvocation(args: string[], flags: Record<string, string | boolean>, projectKeyOverride?: string): SqlQueryInvocation;
|
|
2
12
|
export declare const sqlCommands: Record<string, CommandMeta>;
|
|
@@ -2,6 +2,7 @@ import { readFileSync, } from "node:fs";
|
|
|
2
2
|
import { mkdir, writeFile, } from "node:fs/promises";
|
|
3
3
|
import { dirname, resolve, } from "node:path";
|
|
4
4
|
import { readStdinText, stripUtf8Bom, } from "../coerce.js";
|
|
5
|
+
import { enqueueCliWarning, } from "../output.js";
|
|
5
6
|
import { UsageError, } from "../usage.js";
|
|
6
7
|
const SQL_QUERY_USAGE = "dss sql query (SQL | --sql QUERY | --sql-file PATH | --sql - | --stdin) (--connection CONN | --dataset FULL_NAME) [--database DB] [--output PATH|--output-file PATH] [--preview N] [--start-retries N] [--request-timeout MS] [--project-key KEY]";
|
|
7
8
|
const DEFAULT_SQL_PREVIEW_ROWS = 5;
|
|
@@ -34,7 +35,7 @@ function parseSqlStartRetries(value) {
|
|
|
34
35
|
}
|
|
35
36
|
return parsed;
|
|
36
37
|
}
|
|
37
|
-
function resolveSqlInput(args, flags) {
|
|
38
|
+
export function resolveSqlInput(args, flags) {
|
|
38
39
|
const sources = [];
|
|
39
40
|
if (typeof flags["sql"] === "string") {
|
|
40
41
|
sources.push({
|
|
@@ -69,34 +70,55 @@ function resolveSqlInput(args, flags) {
|
|
|
69
70
|
}
|
|
70
71
|
return query;
|
|
71
72
|
}
|
|
73
|
+
export function resolveSqlQueryInvocation(args, flags, projectKeyOverride) {
|
|
74
|
+
const connection = flags["connection"];
|
|
75
|
+
const datasetFullName = flags["dataset"];
|
|
76
|
+
if ((connection ? 1 : 0) + (datasetFullName ? 1 : 0) !== 1) {
|
|
77
|
+
throw new UsageError(`Pass exactly one of --connection or --dataset. Usage: ${SQL_QUERY_USAGE}`);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
query: resolveSqlInput(args, flags),
|
|
81
|
+
connection,
|
|
82
|
+
datasetFullName,
|
|
83
|
+
database: flags["database"],
|
|
84
|
+
projectKey: projectKeyOverride ?? flags["project-key"],
|
|
85
|
+
type: "sql",
|
|
86
|
+
};
|
|
87
|
+
}
|
|
72
88
|
export const sqlCommands = {
|
|
73
89
|
query: {
|
|
74
90
|
handler: async (c, a, f) => {
|
|
75
|
-
const connection = f["connection"];
|
|
76
|
-
const datasetFullName = f["dataset"];
|
|
77
|
-
if ((connection ? 1 : 0) + (datasetFullName ? 1 : 0) !== 1) {
|
|
78
|
-
throw new UsageError(`Pass exactly one of --connection or --dataset. Usage: ${SQL_QUERY_USAGE}`);
|
|
79
|
-
}
|
|
80
91
|
const outputFile = f["output"]
|
|
81
92
|
?? f["output-file"];
|
|
82
93
|
const previewProvided = f["preview"] !== undefined;
|
|
83
|
-
if (previewProvided && !outputFile) {
|
|
84
|
-
throw new UsageError(`--preview requires --output or --output-file. Usage: ${SQL_QUERY_USAGE}`, "validation_failed");
|
|
85
|
-
}
|
|
86
94
|
const previewCount = previewProvided
|
|
87
95
|
? parseSqlPreviewCount(f["preview"])
|
|
88
96
|
: DEFAULT_SQL_PREVIEW_ROWS;
|
|
89
|
-
const query = resolveSqlInput(a, f);
|
|
90
97
|
const result = await c.sql.query({
|
|
91
|
-
|
|
92
|
-
connection,
|
|
93
|
-
datasetFullName,
|
|
94
|
-
database: f["database"],
|
|
95
|
-
projectKey: f["project-key"],
|
|
98
|
+
...resolveSqlQueryInvocation(a, f),
|
|
96
99
|
retryMaxAttempts: parseSqlStartRetries(f["start-retries"]),
|
|
97
100
|
});
|
|
98
|
-
if (!outputFile)
|
|
101
|
+
if (!outputFile && !previewProvided)
|
|
99
102
|
return result;
|
|
103
|
+
if (!outputFile) {
|
|
104
|
+
const truncated = result.rows.length > previewCount;
|
|
105
|
+
if (truncated) {
|
|
106
|
+
enqueueCliWarning({
|
|
107
|
+
code: "sql_preview_truncated",
|
|
108
|
+
rowCount: result.rows.length,
|
|
109
|
+
previewRows: previewCount,
|
|
110
|
+
hint: "Use --output PATH to write the full result without placing it on stdout.",
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
queryId: result.queryId,
|
|
115
|
+
schema: result.schema,
|
|
116
|
+
columns: result.columns ?? result.schema,
|
|
117
|
+
rowCount: result.rows.length,
|
|
118
|
+
preview: result.rows.slice(0, previewCount),
|
|
119
|
+
truncated,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
100
122
|
const outputPath = resolve(outputFile);
|
|
101
123
|
await mkdir(dirname(outputPath), { recursive: true, });
|
|
102
124
|
await writeFile(outputPath, `${JSON.stringify(result, null, 2)}\n`, "utf-8");
|
|
@@ -111,7 +133,7 @@ export const sqlCommands = {
|
|
|
111
133
|
};
|
|
112
134
|
},
|
|
113
135
|
usage: SQL_QUERY_USAGE,
|
|
114
|
-
description: "Run
|
|
136
|
+
description: "Run potentially mutating SQL against a DSS connection or dataset. Use --preview N for bounded stdout or --output PATH for full rows. --start-retries may execute SQL more than once; use it only when repetition is safe.",
|
|
115
137
|
examples: [
|
|
116
138
|
"dss sql query 'SELECT * FROM orders LIMIT 10' --connection my_pg",
|
|
117
139
|
"dss sql query --sql-file query.sql --connection my_pg",
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ClientValidationError, } from "../../errors.js";
|
|
2
|
+
import { deepMerge, } from "../../utils/deep-merge.js";
|
|
3
|
+
import { stableHash, } from "../../utils/stable-hash.js";
|
|
4
|
+
import { num, requiredJsonInput, } from "../coerce.js";
|
|
2
5
|
import { requireArgs, } from "../usage.js";
|
|
6
|
+
const UPDATE_SETTINGS_USAGE = "dss webapp update-settings <webappId> (--data JSON|--data-file PATH|--stdin) [--expect-hash SHA256] [--dry-run] [--project-key KEY]";
|
|
7
|
+
const RESTART_USAGE = "dss webapp restart-backend <webappId> [--wait] [--timeout MS] [--poll-interval MS] [--project-key KEY]";
|
|
8
|
+
function validateExpectHash(value) {
|
|
9
|
+
if (value === undefined || value === false)
|
|
10
|
+
return undefined;
|
|
11
|
+
if (typeof value !== "string" || !/^[0-9a-fA-F]{64}$/.test(value)) {
|
|
12
|
+
throw new ClientValidationError("Expected webapp hash must be a 64-character SHA-256 hex digest.", "validation_failed", "Run this update with --dry-run and capture currentHash before retrying.");
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
3
16
|
export const webappCommands = {
|
|
4
17
|
list: {
|
|
5
18
|
handler: (c, _a, f) => c.webapps.list(f["project-key"]),
|
|
@@ -26,14 +39,45 @@ export const webappCommands = {
|
|
|
26
39
|
examples: ["dss webapp create --data-file webapp.json",],
|
|
27
40
|
},
|
|
28
41
|
"update-settings": {
|
|
29
|
-
handler: (c, a, f) => {
|
|
30
|
-
requireArgs(a, 1,
|
|
42
|
+
handler: async (c, a, f) => {
|
|
43
|
+
requireArgs(a, 1, UPDATE_SETTINGS_USAGE);
|
|
31
44
|
const body = requiredJsonInput(f, "--data, --data-file, or --stdin is required (webapp settings).");
|
|
32
|
-
|
|
45
|
+
const projectKey = f["project-key"];
|
|
46
|
+
const expectHash = validateExpectHash(f["expect-hash"]);
|
|
47
|
+
if (f["dry-run"] === true) {
|
|
48
|
+
const current = await c.webapps.getSettings(a[0], projectKey);
|
|
49
|
+
const currentHash = stableHash(current);
|
|
50
|
+
if (expectHash !== undefined && currentHash !== expectHash.toLowerCase()) {
|
|
51
|
+
throw new ClientValidationError(`The webapp ${JSON.stringify(a[0])} changed since it was read.`, "validation_failed", "Re-read the webapp settings and retry with the current hash value.", {
|
|
52
|
+
id: a[0],
|
|
53
|
+
expectedHash: expectHash.toLowerCase(),
|
|
54
|
+
actualHash: currentHash,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const next = deepMerge(current, body);
|
|
58
|
+
return {
|
|
59
|
+
dryRun: true,
|
|
60
|
+
action: "update-settings",
|
|
61
|
+
resource: "webapp",
|
|
62
|
+
id: a[0],
|
|
63
|
+
current,
|
|
64
|
+
next,
|
|
65
|
+
currentHash,
|
|
66
|
+
nextHash: stableHash(next),
|
|
67
|
+
...(expectHash !== undefined
|
|
68
|
+
? { expectHash: expectHash.toLowerCase(), provenanceVerified: true, }
|
|
69
|
+
: {}),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const updated = await c.webapps.updateSettings(a[0], body, projectKey, { expectHash, });
|
|
73
|
+
return { updated: a[0], ...updated, };
|
|
33
74
|
},
|
|
34
|
-
usage:
|
|
35
|
-
description: "
|
|
36
|
-
examples: [
|
|
75
|
+
usage: UPDATE_SETTINGS_USAGE,
|
|
76
|
+
description: "Merge supplied fields into a webapp's settings (GET-merge-PUT) and PUT the full object, so fields outside the patch are never dropped. --expect-hash refuses the write when the object changed since it was fetched; --dry-run reports current, next, and both hashes without writing.",
|
|
77
|
+
examples: [
|
|
78
|
+
"dss webapp update-settings WEBAPP_ID --data-file webapp.json",
|
|
79
|
+
'dss webapp update-settings WEBAPP_ID --dry-run --data=\'{"params":{"designOptions":{"namingRule":"x"}}}\'',
|
|
80
|
+
],
|
|
37
81
|
},
|
|
38
82
|
"stop-backend": {
|
|
39
83
|
handler: async (c, a, f) => {
|
|
@@ -47,13 +91,23 @@ export const webappCommands = {
|
|
|
47
91
|
},
|
|
48
92
|
"restart-backend": {
|
|
49
93
|
handler: async (c, a, f) => {
|
|
50
|
-
requireArgs(a, 1,
|
|
51
|
-
|
|
52
|
-
|
|
94
|
+
requireArgs(a, 1, RESTART_USAGE);
|
|
95
|
+
const projectKey = f["project-key"];
|
|
96
|
+
if (f["wait"] === true) {
|
|
97
|
+
return c.webapps.restartBackendAndWait(a[0], projectKey, {
|
|
98
|
+
pollIntervalMs: num(f["poll-interval"], "--poll-interval"),
|
|
99
|
+
timeoutMs: num(f["timeout"], "--timeout"),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
const future = await c.webapps.startOrRestartBackend(a[0], projectKey);
|
|
103
|
+
return { restarted: true, future, };
|
|
53
104
|
},
|
|
54
|
-
usage:
|
|
55
|
-
description: "Start or restart a webapp's backend.",
|
|
56
|
-
examples: [
|
|
105
|
+
usage: RESTART_USAGE,
|
|
106
|
+
description: "Start or restart a webapp's backend. The documented endpoint returns a restart future; --wait settles it and returns the FutureWaitResult.",
|
|
107
|
+
examples: [
|
|
108
|
+
"dss webapp restart-backend WEBAPP_ID",
|
|
109
|
+
"dss webapp restart-backend WEBAPP_ID --wait --timeout=60000",
|
|
110
|
+
],
|
|
57
111
|
},
|
|
58
112
|
"backend-state": {
|
|
59
113
|
handler: (c, a, f) => {
|
|
@@ -32,6 +32,17 @@ export type CommandFlagMetadata = {
|
|
|
32
32
|
aliases?: string[];
|
|
33
33
|
allowEmptyValue?: boolean;
|
|
34
34
|
};
|
|
35
|
+
export interface CommandPositionalMetadata {
|
|
36
|
+
name: string;
|
|
37
|
+
required: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface CommandRequiredInputAlternative {
|
|
40
|
+
flags?: string[];
|
|
41
|
+
positionals?: string[];
|
|
42
|
+
}
|
|
43
|
+
export interface CommandRequiredInputGroup {
|
|
44
|
+
oneOf: CommandRequiredInputAlternative[];
|
|
45
|
+
}
|
|
35
46
|
export interface CommandStructuredExample {
|
|
36
47
|
shell: string;
|
|
37
48
|
argv?: string[];
|
|
@@ -57,6 +68,7 @@ export interface CommandRegistryEntry {
|
|
|
57
68
|
structuredExamples: CommandStructuredExample[];
|
|
58
69
|
flags: CommandFlagMetadata[];
|
|
59
70
|
positionals: string[];
|
|
71
|
+
positionalArguments: CommandPositionalMetadata[];
|
|
60
72
|
sideEffect: CommandSideEffect;
|
|
61
73
|
requiresAuth: boolean;
|
|
62
74
|
requiresProject: boolean;
|
|
@@ -70,6 +82,7 @@ export interface CommandRegistryEntry {
|
|
|
70
82
|
dryRun: boolean;
|
|
71
83
|
requiredFlags: string[];
|
|
72
84
|
requiredOneOf?: CommandFlagChoice[];
|
|
85
|
+
requiredInputGroups?: CommandRequiredInputGroup[];
|
|
73
86
|
optionalFlags: string[];
|
|
74
87
|
payloadSchema?: CommandPayloadSchema;
|
|
75
88
|
schemas: CommandAgentSchemas;
|
|
@@ -96,10 +109,12 @@ export declare function commandActionSummary(registry: Record<string, Record<str
|
|
|
96
109
|
export declare function buildAgentContract(): Record<string, unknown>;
|
|
97
110
|
export declare function commandPlanShape(resource: string, action: string, args: string[], flags: Record<string, string | boolean>, entry: CommandRegistryEntry, projectKey: string | undefined): {
|
|
98
111
|
endpoint?: string;
|
|
112
|
+
exact?: boolean;
|
|
99
113
|
identifiers?: Record<string, unknown>;
|
|
100
114
|
method?: string;
|
|
101
115
|
payload?: unknown;
|
|
102
116
|
localWrites?: unknown;
|
|
117
|
+
reason?: string;
|
|
103
118
|
wait?: unknown;
|
|
104
119
|
requests?: unknown;
|
|
105
120
|
};
|