dataiku-sdk 3.4.0 → 3.5.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 +3 -3
- package/dist/build-metadata.json +1 -1
- package/dist/src/cli/command-syntax.json +14524 -0
- package/dist/src/cli/commands/analysis.js +6 -9
- package/dist/src/cli/commands/api-deployer.js +15 -33
- package/dist/src/cli/commands/api-service.js +17 -27
- package/dist/src/cli/commands/app.js +22 -39
- package/dist/src/cli/commands/bundle.js +15 -24
- package/dist/src/cli/commands/business-app.js +10 -17
- package/dist/src/cli/commands/code-env.js +23 -36
- package/dist/src/cli/commands/code.js +4 -4
- package/dist/src/cli/commands/connection.js +12 -22
- package/dist/src/cli/commands/continuous-activity.js +6 -9
- package/dist/src/cli/commands/dashboard.js +8 -13
- package/dist/src/cli/commands/data-collection.js +9 -16
- package/dist/src/cli/commands/data-quality.js +14 -26
- package/dist/src/cli/commands/dataset.js +27 -50
- package/dist/src/cli/commands/discussion.js +7 -10
- package/dist/src/cli/commands/doctor.js +3 -3
- package/dist/src/cli/commands/flow-zone.js +8 -17
- package/dist/src/cli/commands/folder.js +12 -20
- package/dist/src/cli/commands/future.js +7 -10
- package/dist/src/cli/commands/group.js +7 -11
- package/dist/src/cli/commands/insight.js +7 -11
- package/dist/src/cli/commands/job.js +13 -23
- package/dist/src/cli/commands/knowledge-bank.js +5 -6
- package/dist/src/cli/commands/llm.js +5 -8
- package/dist/src/cli/commands/macro.js +9 -16
- package/dist/src/cli/commands/meaning.js +7 -11
- package/dist/src/cli/commands/metrics.js +7 -10
- package/dist/src/cli/commands/ml-task.js +12 -20
- package/dist/src/cli/commands/model-evaluation-store.js +7 -11
- package/dist/src/cli/commands/notebook.js +15 -27
- package/dist/src/cli/commands/plugin.js +35 -68
- package/dist/src/cli/commands/project-deployer.js +10 -22
- package/dist/src/cli/commands/project-folder.js +10 -17
- package/dist/src/cli/commands/project-git.js +38 -70
- package/dist/src/cli/commands/project-library.js +15 -23
- package/dist/src/cli/commands/project.js +9 -26
- package/dist/src/cli/commands/recipe.d.ts +16 -0
- package/dist/src/cli/commands/recipe.js +83 -94
- package/dist/src/cli/commands/saved-model.js +23 -39
- package/dist/src/cli/commands/scenario.js +20 -34
- package/dist/src/cli/commands/sql.js +4 -4
- package/dist/src/cli/commands/statistics.js +11 -18
- package/dist/src/cli/commands/streaming-endpoint.js +7 -11
- package/dist/src/cli/commands/user.js +11 -22
- package/dist/src/cli/commands/variable.js +3 -4
- package/dist/src/cli/commands/webapp.js +10 -16
- package/dist/src/cli/commands/wiki.js +9 -13
- package/dist/src/cli/commands/workspace.js +8 -14
- package/dist/src/cli/contract.d.ts +5 -15
- package/dist/src/cli/contract.js +156 -253
- package/dist/src/cli/doctor.js +1 -0
- package/dist/src/cli/env.d.ts +2 -0
- package/dist/src/cli/env.js +15 -1
- package/dist/src/cli/helpers/app-permissions.js +2 -1
- package/dist/src/cli/helpers/flow-zone.js +2 -1
- package/dist/src/cli/helpers/recipe.js +2 -1
- package/dist/src/cli/syntax.d.ts +83 -0
- package/dist/src/cli/syntax.js +217 -0
- package/dist/src/cli/types.d.ts +3 -0
- package/dist/src/cli/usage.d.ts +1 -1
- package/dist/src/cli/usage.js +4 -2
- package/dist/src/cli/version.js +2 -0
- package/dist/src/cli.js +37 -64
- package/dist/src/client.js +7 -6
- package/dist/src/errors.d.ts +12 -1
- package/dist/src/errors.js +28 -3
- package/dist/src/index.d.ts +1 -3
- package/dist/src/index.js +2 -2
- package/dist/src/resources/api-services.js +2 -3
- package/dist/src/resources/applications.js +2 -4
- package/dist/src/resources/code-envs.js +2 -2
- package/dist/src/resources/data-quality.js +4 -3
- package/dist/src/resources/datasets.d.ts +13 -0
- package/dist/src/resources/datasets.js +5 -4
- package/dist/src/resources/flow-zones.js +4 -2
- package/dist/src/resources/folders.js +4 -2
- package/dist/src/resources/futures.js +1 -3
- package/dist/src/resources/insights.js +3 -2
- package/dist/src/resources/jobs.js +4 -6
- package/dist/src/resources/macros.js +2 -4
- package/dist/src/resources/notebooks.js +2 -3
- package/dist/src/resources/project-git.js +9 -11
- package/dist/src/resources/project-library.d.ts +0 -2
- package/dist/src/resources/project-library.js +2 -7
- package/dist/src/resources/projects.js +4 -3
- package/dist/src/resources/recipes.d.ts +28 -0
- package/dist/src/resources/recipes.js +116 -84
- package/dist/src/resources/sql.js +8 -3
- package/dist/src/resources/statistics.js +2 -1
- package/dist/src/resources/variables.js +2 -1
- package/dist/src/resources/webapps.js +2 -3
- package/dist/src/schemas.d.ts +1 -2
- package/dist/src/schemas.js +1 -1
- package/dist/src/skill.js +6 -7
- package/dist/src/utils/cleanup-ledger.js +9 -8
- package/dist/src/utils/polling.d.ts +3 -0
- package/dist/src/utils/polling.js +3 -0
- package/dist/src/utils/project-archive.js +2 -2
- package/dist/src/utils/stable-hash.d.ts +3 -1
- package/dist/src/utils/stable-hash.js +2 -0
- package/package.json +4 -4
- package/plugin.json +1 -1
- package/skills/dataiku-dss/SKILL.md +2 -3
- package/skills/dataiku-dss/references/authentication.md +3 -3
- package/skills/dataiku-dss/references/coding.md +1 -1
- package/dist/src/utils/pagination.d.ts +0 -8
- package/dist/src/utils/pagination.js +0 -23
|
@@ -5,8 +5,9 @@ import { projectIncarnationHash, } from "../../utils/project-incarnation.js";
|
|
|
5
5
|
import { jsonInput, num, requiredJsonInput, requiredStringFlag, } from "../coerce.js";
|
|
6
6
|
import { executionMode, } from "../flags.js";
|
|
7
7
|
import { CommandResultFailure, } from "../output.js";
|
|
8
|
+
import { commandUsage, withUsage, } from "../syntax.js";
|
|
8
9
|
import { requireArgs, UsageError, } from "../usage.js";
|
|
9
|
-
const INSPECT_ARCHIVE_USAGE = "
|
|
10
|
+
const INSPECT_ARCHIVE_USAGE = commandUsage("project", "inspect-archive");
|
|
10
11
|
function flowRenderFormat(value) {
|
|
11
12
|
if (value === undefined)
|
|
12
13
|
return undefined;
|
|
@@ -19,28 +20,24 @@ function inspectArchiveCommand(args) {
|
|
|
19
20
|
requireArgs(args, 1, INSPECT_ARCHIVE_USAGE);
|
|
20
21
|
return inspectProjectArchive(args[0]);
|
|
21
22
|
}
|
|
22
|
-
export const projectCommands = {
|
|
23
|
+
export const projectCommands = withUsage("project", {
|
|
23
24
|
list: {
|
|
24
25
|
handler: (c) => c.projects.list(),
|
|
25
|
-
usage: "dss project list",
|
|
26
26
|
description: "List all accessible projects.",
|
|
27
27
|
examples: ["dss project list",],
|
|
28
28
|
},
|
|
29
29
|
get: {
|
|
30
30
|
handler: (c, _a, f) => c.projects.get(f["project-key"]),
|
|
31
|
-
usage: "dss project get [--project-key KEY]",
|
|
32
31
|
description: "Get project settings and metadata.",
|
|
33
32
|
examples: ["dss project get", "dss project get --project-key MYPROJ",],
|
|
34
33
|
},
|
|
35
34
|
metadata: {
|
|
36
35
|
handler: (c, _a, f) => c.projects.metadata(f["project-key"]),
|
|
37
|
-
usage: "dss project metadata [--project-key KEY]",
|
|
38
36
|
description: "Get project-level metadata (tags, labels, custom fields).",
|
|
39
37
|
examples: ["dss project metadata", "dss project metadata --project-key MYPROJ",],
|
|
40
38
|
},
|
|
41
39
|
flow: {
|
|
42
40
|
handler: (c, _a, f) => c.projects.flow(f["project-key"]),
|
|
43
|
-
usage: "dss project flow [--project-key KEY]",
|
|
44
41
|
description: "Get the raw flow graph (all datasets, recipes, and edges).",
|
|
45
42
|
examples: ["dss project flow", "dss project flow --project-key MYPROJ",],
|
|
46
43
|
},
|
|
@@ -57,7 +54,6 @@ export const projectCommands = {
|
|
|
57
54
|
num(f["max-nodes"], "--max-nodes");
|
|
58
55
|
num(f["max-edges"], "--max-edges");
|
|
59
56
|
},
|
|
60
|
-
usage: "dss project map [--max-nodes N] [--max-edges N] [--include-raw] [--render ascii|mermaid] [--project-key KEY]",
|
|
61
57
|
description: "Get an analyzed flow map with zones, layers, components, and diagnostics.",
|
|
62
58
|
examples: [
|
|
63
59
|
"dss project map",
|
|
@@ -68,20 +64,19 @@ export const projectCommands = {
|
|
|
68
64
|
},
|
|
69
65
|
create: {
|
|
70
66
|
handler: (c, a, f) => {
|
|
71
|
-
const usage = "
|
|
67
|
+
const usage = commandUsage("project", "create");
|
|
72
68
|
requireArgs(a, 2, usage);
|
|
73
69
|
const owner = f["owner"];
|
|
74
70
|
if (!owner)
|
|
75
71
|
throw new UsageError(`--owner is required. Usage: ${usage}`);
|
|
76
72
|
return c.projects.createProject(a[0], a[1], owner, jsonInput(f));
|
|
77
73
|
},
|
|
78
|
-
usage: "dss project create <projectKey> <name> --owner LOGIN [--data JSON|--data-file PATH|--stdin]",
|
|
79
74
|
description: "Create a new project with owner login and optional settings.",
|
|
80
75
|
examples: ["dss project create MY_PROJ MyProject --owner alice",],
|
|
81
76
|
},
|
|
82
77
|
delete: {
|
|
83
78
|
handler: async (c, a, f) => {
|
|
84
|
-
const usage = "
|
|
79
|
+
const usage = commandUsage("project", "delete");
|
|
85
80
|
requireArgs(a, 1, usage);
|
|
86
81
|
const projectKey = a[0];
|
|
87
82
|
const expectedIncarnation = f["expect-project-incarnation"] === undefined
|
|
@@ -148,35 +143,32 @@ export const projectCommands = {
|
|
|
148
143
|
: {}),
|
|
149
144
|
};
|
|
150
145
|
},
|
|
151
|
-
usage: "dss project delete <projectKey> [--drop-data] [--if-exists] [--dry-run] [--expect-project-incarnation HASH]",
|
|
152
146
|
description: "Delete a project (destructive). --drop-data also clears managed datasets; --if-exists treats an absent project as already deleted; --dry-run verifies without deleting; --expect-project-incarnation HASH refuses deletion unless the project still matches the recorded incarnation.",
|
|
153
147
|
examples: ["dss project delete MY_PROJ",],
|
|
154
148
|
},
|
|
155
149
|
duplicate: {
|
|
156
150
|
handler: (c, a, f) => {
|
|
157
|
-
requireArgs(a, 3, "
|
|
151
|
+
requireArgs(a, 3, commandUsage("project", "duplicate"));
|
|
158
152
|
return c.projects.duplicate(a[0], a[1], a[2], jsonInput(f));
|
|
159
153
|
},
|
|
160
|
-
usage: "dss project duplicate <sourceKey> <targetKey> <targetName> [--data JSON|--data-file PATH|--stdin]",
|
|
161
154
|
description: "Duplicate a project into a new project key.",
|
|
162
155
|
examples: ["dss project duplicate SRC NEW NewProject",],
|
|
163
156
|
},
|
|
164
157
|
export: {
|
|
165
158
|
handler: async (c, a, f) => {
|
|
166
|
-
requireArgs(a, 1, "
|
|
159
|
+
requireArgs(a, 1, commandUsage("project", "export"));
|
|
167
160
|
const out = f["output"];
|
|
168
161
|
if (!out)
|
|
169
162
|
throw new UsageError("--output PATH is required.", "missing_required_flag");
|
|
170
163
|
await c.projects.exportArchive(a[0], out, jsonInput(f));
|
|
171
164
|
return { path: out, };
|
|
172
165
|
},
|
|
173
|
-
usage: "dss project export <projectKey> --output PATH [--data JSON|--data-file PATH|--stdin]",
|
|
174
166
|
description: "Export a project to a local archive (.zip).",
|
|
175
167
|
examples: ["dss project export MY_PROJ --output ./my_proj.zip",],
|
|
176
168
|
},
|
|
177
169
|
import: {
|
|
178
170
|
handler: async (c, a, f) => {
|
|
179
|
-
const usage = "
|
|
171
|
+
const usage = commandUsage("project", "import");
|
|
180
172
|
requireArgs(a, 1, usage);
|
|
181
173
|
const settings = jsonInput(f) ?? {};
|
|
182
174
|
const rawTarget = f["target-project-key"];
|
|
@@ -200,7 +192,6 @@ export const projectCommands = {
|
|
|
200
192
|
}
|
|
201
193
|
return result;
|
|
202
194
|
},
|
|
203
|
-
usage: "dss project import <filePath> [--target-project-key KEY] [--data JSON|--data-file PATH|--stdin]",
|
|
204
195
|
description: "Upload and process a project archive, optionally overriding its project key. The archive is validated locally before upload; verified success reports the used project key, explicit request/actual remapping, and the landed incarnation hash.",
|
|
205
196
|
examples: [
|
|
206
197
|
"dss project import ./my_proj.zip",
|
|
@@ -210,7 +201,6 @@ export const projectCommands = {
|
|
|
210
201
|
"inspect-archive": {
|
|
211
202
|
handler: async (_c, a) => inspectArchiveCommand(a),
|
|
212
203
|
localHandler: inspectArchiveCommand,
|
|
213
|
-
usage: INSPECT_ARCHIVE_USAGE,
|
|
214
204
|
description: "Read-only local inspection of a project export archive: member names, sizes, manifest validity, archive issues, and the source project key. Never contacts DSS.",
|
|
215
205
|
examples: ["dss project inspect-archive ./my_proj.zip",],
|
|
216
206
|
},
|
|
@@ -220,13 +210,11 @@ export const projectCommands = {
|
|
|
220
210
|
await c.projects.setPermissions(f["project-key"], body);
|
|
221
211
|
return { updated: true, };
|
|
222
212
|
},
|
|
223
|
-
usage: "dss project permissions-set (--data JSON|--data-file PATH|--stdin) [--project-key KEY]",
|
|
224
213
|
description: "Replace a project's permissions.",
|
|
225
214
|
examples: ["dss project permissions-set --data-file perms.json --project-key MY_PROJ",],
|
|
226
215
|
},
|
|
227
216
|
"permissions-get": {
|
|
228
217
|
handler: (c, _a, f) => c.projects.getPermissions(f["project-key"]),
|
|
229
|
-
usage: "dss project permissions-get [--project-key KEY]",
|
|
230
218
|
description: "Get a project's permissions.",
|
|
231
219
|
examples: ["dss project permissions-get --project-key MY_PROJ",],
|
|
232
220
|
},
|
|
@@ -244,7 +232,6 @@ export const projectCommands = {
|
|
|
244
232
|
await c.projects.setMetadata(f["project-key"], metadata);
|
|
245
233
|
return { updated: true, };
|
|
246
234
|
},
|
|
247
|
-
usage: "dss project metadata-set (--data JSON|--data-file PATH|--stdin) [--dry-run] [--project-key KEY]",
|
|
248
235
|
description: "Replace project metadata with a full object obtained from a previous metadata GET. Fields absent from the payload are removed.",
|
|
249
236
|
examples: [
|
|
250
237
|
"dss project metadata-set --data-file metadata.json --project-key MY_PROJ --dry-run",
|
|
@@ -252,7 +239,6 @@ export const projectCommands = {
|
|
|
252
239
|
},
|
|
253
240
|
"tags-get": {
|
|
254
241
|
handler: (c, _a, f) => c.projects.tags(f["project-key"]),
|
|
255
|
-
usage: "dss project tags-get [--project-key KEY]",
|
|
256
242
|
description: "Get project-level tags as a dictionary of tag name to display settings.",
|
|
257
243
|
examples: ["dss project tags-get", "dss project tags-get --project-key MY_PROJ",],
|
|
258
244
|
},
|
|
@@ -270,7 +256,6 @@ export const projectCommands = {
|
|
|
270
256
|
await c.projects.setTags(f["project-key"], tags);
|
|
271
257
|
return { updated: true, };
|
|
272
258
|
},
|
|
273
|
-
usage: "dss project tags-set (--data JSON|--data-file PATH|--stdin) [--dry-run] [--project-key KEY]",
|
|
274
259
|
description: "Replace project tags with a full object obtained from a previous tags GET. Tags absent from the payload are removed.",
|
|
275
260
|
examples: [
|
|
276
261
|
'dss project tags-set --data \'{"tags":{"production":{"color":"#28aadd"}}}\' --project-key MY_PROJ --dry-run',
|
|
@@ -278,7 +263,6 @@ export const projectCommands = {
|
|
|
278
263
|
},
|
|
279
264
|
"settings-get": {
|
|
280
265
|
handler: (c, _a, f) => c.projects.getSettings(f["project-key"]),
|
|
281
|
-
usage: "dss project settings-get [--project-key KEY]",
|
|
282
266
|
description: "Get a project's settings.",
|
|
283
267
|
examples: ["dss project settings-get --project-key MY_PROJ",],
|
|
284
268
|
},
|
|
@@ -291,8 +275,7 @@ export const projectCommands = {
|
|
|
291
275
|
await c.projects.setSettings(projectKey, next);
|
|
292
276
|
return { updated: true, };
|
|
293
277
|
},
|
|
294
|
-
usage: "dss project settings-set (--data JSON|--data-file PATH|--stdin) [--project-key KEY]",
|
|
295
278
|
description: "Update a project's settings via JSON merge.",
|
|
296
279
|
examples: ["dss project settings-set --data-file settings.json --project-key MY_PROJ",],
|
|
297
280
|
},
|
|
298
|
-
};
|
|
281
|
+
});
|
|
@@ -1,2 +1,18 @@
|
|
|
1
1
|
import type { CommandMeta } from "../types.js";
|
|
2
|
+
/** Maps `recipe create` flags to SDK options; shared by the handler and `--plan`. */
|
|
3
|
+
export declare function recipeCreateOptionsFromFlags(f: Record<string, string | boolean>): {
|
|
4
|
+
type: string;
|
|
5
|
+
name: string | undefined;
|
|
6
|
+
inputDatasets: string[] | undefined;
|
|
7
|
+
outputDataset: string | undefined;
|
|
8
|
+
outputFolder: string | undefined;
|
|
9
|
+
outputConnection: string | undefined;
|
|
10
|
+
joinOn?: string[] | undefined;
|
|
11
|
+
joinType?: string | undefined;
|
|
12
|
+
fuzzyOn?: string[] | undefined;
|
|
13
|
+
fuzzyDistance?: string | undefined;
|
|
14
|
+
fuzzyThreshold?: number | undefined;
|
|
15
|
+
fuzzyNormalize: boolean;
|
|
16
|
+
projectKey: string | undefined;
|
|
17
|
+
};
|
|
2
18
|
export declare const recipeCommands: Record<string, CommandMeta>;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { readFileSync, } from "node:fs";
|
|
2
2
|
import { writeFile, } from "node:fs/promises";
|
|
3
3
|
import { join, } from "node:path";
|
|
4
|
+
import { ClientValidationError, } from "../../errors.js";
|
|
4
5
|
import { deepMerge, } from "../../utils/deep-merge.js";
|
|
5
6
|
import { jobLogFilterFromFlag, jsonInput, maxLogLinesFromFlags, normalizeLineEndings, num, recipeInputDatasetsFromFlags, requiredJsonInput, requiredStringFlag, rewritePairsFromFlags, sha256Hex, splitCsvFlag, stableHash, } from "../coerce.js";
|
|
6
7
|
import { executionMode, } from "../flags.js";
|
|
7
8
|
import { moveCreatedItemsToZone, resolveFlowZoneIdFromFlags, } from "../helpers/flow-zone.js";
|
|
8
9
|
import { ensureRecipeBackupDir, readRecipeBackup, recipeBackupDocument, recipeBackupPath, recipeCodeEnv, recipeGraph, recipeInputItemRef, recipeRoleInputItems, recipeRunShouldWait, writeRecipeBackup, } from "../helpers/recipe.js";
|
|
9
10
|
import { encodedProjectEndpoint, readIfExists, skipResult, } from "../output.js";
|
|
11
|
+
import { commandUsage, withUsage, } from "../syntax.js";
|
|
10
12
|
import { requireArgs, UsageError, } from "../usage.js";
|
|
11
13
|
/** Read a local recipe file before any DSS request, mapping read failures to usage validation. */
|
|
12
14
|
function readRecipeFile(filePath, flagName) {
|
|
@@ -59,27 +61,80 @@ function formatLineDiff(remoteName, localPath, remoteContent, localContent) {
|
|
|
59
61
|
}
|
|
60
62
|
return lines.join("\n");
|
|
61
63
|
}
|
|
62
|
-
|
|
64
|
+
/** Maps `recipe create` flags to SDK options; shared by the handler and `--plan`. */
|
|
65
|
+
export function recipeCreateOptionsFromFlags(f) {
|
|
66
|
+
const type = f["type"];
|
|
67
|
+
if (!type) {
|
|
68
|
+
throw new UsageError(`--type is required. Usage: ${commandUsage("recipe", "create")}`);
|
|
69
|
+
}
|
|
70
|
+
const outputDataset = f["output"];
|
|
71
|
+
const outputFolder = f["output-folder"];
|
|
72
|
+
if (outputDataset && outputFolder) {
|
|
73
|
+
throw new UsageError("--output and --output-folder are mutually exclusive.");
|
|
74
|
+
}
|
|
75
|
+
if (!outputDataset && !outputFolder) {
|
|
76
|
+
throw new UsageError(`--output or --output-folder is required. Usage: ${commandUsage("recipe", "create")}`);
|
|
77
|
+
}
|
|
78
|
+
if (outputFolder && !f["output-connection"]) {
|
|
79
|
+
throw new UsageError("--output-connection is required when using --output-folder.");
|
|
80
|
+
}
|
|
81
|
+
const name = f["name"];
|
|
82
|
+
const pk = f["project-key"];
|
|
83
|
+
const inputDatasets = recipeInputDatasetsFromFlags(f);
|
|
84
|
+
const joinColumns = splitCsvFlag(f["join-on"]);
|
|
85
|
+
const fuzzyColumns = splitCsvFlag(f["fuzzy-on"]);
|
|
86
|
+
const rawFuzzyDistance = f["fuzzy-distance"];
|
|
87
|
+
let fuzzyDistance;
|
|
88
|
+
if (typeof rawFuzzyDistance === "string") {
|
|
89
|
+
const normalized = rawFuzzyDistance.trim().toUpperCase();
|
|
90
|
+
if (![
|
|
91
|
+
"DAMERAU_LEVENSHTEIN",
|
|
92
|
+
"HAMMING",
|
|
93
|
+
"JACCARD",
|
|
94
|
+
"COSINE",
|
|
95
|
+
"EUCLIDEAN",
|
|
96
|
+
].includes(normalized)) {
|
|
97
|
+
throw new UsageError("--fuzzy-distance must be one of DAMERAU_LEVENSHTEIN, HAMMING, JACCARD, COSINE, or EUCLIDEAN.", "invalid_enum");
|
|
98
|
+
}
|
|
99
|
+
fuzzyDistance = normalized;
|
|
100
|
+
}
|
|
101
|
+
const fuzzyThreshold = num(f["fuzzy-threshold"], "--fuzzy-threshold");
|
|
102
|
+
const payload = {
|
|
103
|
+
type,
|
|
104
|
+
name,
|
|
105
|
+
inputDatasets,
|
|
106
|
+
outputDataset,
|
|
107
|
+
outputFolder,
|
|
108
|
+
outputConnection: f["output-connection"],
|
|
109
|
+
...(joinColumns.length > 0 ? { joinOn: joinColumns, } : {}),
|
|
110
|
+
...(typeof f["join-type"] === "string" ? { joinType: f["join-type"], } : {}),
|
|
111
|
+
...(fuzzyColumns.length > 0 ? { fuzzyOn: fuzzyColumns, } : {}),
|
|
112
|
+
...(fuzzyDistance ? { fuzzyDistance, } : {}),
|
|
113
|
+
...(fuzzyThreshold !== undefined ? { fuzzyThreshold, } : {}),
|
|
114
|
+
fuzzyNormalize: f["normalize"] === true,
|
|
115
|
+
projectKey: pk,
|
|
116
|
+
};
|
|
117
|
+
return payload;
|
|
118
|
+
}
|
|
119
|
+
export const recipeCommands = withUsage("recipe", {
|
|
63
120
|
list: {
|
|
64
121
|
handler: (c, _a, f) => c.recipes.list(f["project-key"]),
|
|
65
|
-
usage: "dss recipe list [--project-key KEY]",
|
|
66
122
|
description: "List all recipes in a project.",
|
|
67
123
|
examples: ["dss recipe list",],
|
|
68
124
|
},
|
|
69
125
|
metadata: {
|
|
70
126
|
handler: (c, a, f) => {
|
|
71
|
-
requireArgs(a, 1, "
|
|
127
|
+
requireArgs(a, 1, commandUsage("recipe", "metadata"));
|
|
72
128
|
return c.recipes.metadata(a[0], {
|
|
73
129
|
projectKey: f["project-key"],
|
|
74
130
|
});
|
|
75
131
|
},
|
|
76
|
-
usage: "dss recipe metadata <name> [--project-key KEY]",
|
|
77
132
|
description: "Get recipe metadata (label, description, tags, custom fields).",
|
|
78
133
|
examples: ["dss recipe metadata compute_orders",],
|
|
79
134
|
},
|
|
80
135
|
"metadata-set": {
|
|
81
136
|
handler: async (c, a, f) => {
|
|
82
|
-
const usage = "
|
|
137
|
+
const usage = commandUsage("recipe", "metadata-set");
|
|
83
138
|
requireArgs(a, 1, usage);
|
|
84
139
|
const metadata = requiredJsonInput(f, "--data, --data-file, or --stdin is required (full metadata object).");
|
|
85
140
|
const pk = f["project-key"];
|
|
@@ -95,7 +150,6 @@ export const recipeCommands = {
|
|
|
95
150
|
await c.recipes.setMetadata(a[0], metadata, { projectKey: pk, });
|
|
96
151
|
return { updated: a[0], resource: "recipe", };
|
|
97
152
|
},
|
|
98
|
-
usage: "dss recipe metadata-set <name> (--data JSON|--data-file PATH|--stdin) [--dry-run] [--project-key KEY]",
|
|
99
153
|
description: "Replace recipe metadata with a full object obtained from a previous metadata GET. Fields absent from the payload are removed.",
|
|
100
154
|
examples: [
|
|
101
155
|
'dss recipe metadata-set compute_orders --data \'{"label":"Orders"}\' --dry-run',
|
|
@@ -103,13 +157,12 @@ export const recipeCommands = {
|
|
|
103
157
|
},
|
|
104
158
|
get: {
|
|
105
159
|
handler: (c, a, f) => {
|
|
106
|
-
requireArgs(a, 1, "
|
|
160
|
+
requireArgs(a, 1, commandUsage("recipe", "get"));
|
|
107
161
|
return c.recipes.get(a[0], {
|
|
108
162
|
includePayload: f["include-payload"] === true && f["no-payload"] !== true,
|
|
109
163
|
projectKey: f["project-key"],
|
|
110
164
|
});
|
|
111
165
|
},
|
|
112
|
-
usage: "dss recipe get <name> [--include-payload|--no-payload] [--project-key KEY]",
|
|
113
166
|
description: "Get compact recipe settings unless --include-payload is set.",
|
|
114
167
|
examples: [
|
|
115
168
|
"dss recipe get compute_orders",
|
|
@@ -119,18 +172,17 @@ export const recipeCommands = {
|
|
|
119
172
|
},
|
|
120
173
|
"validate-graph": {
|
|
121
174
|
handler: (c, a, f) => {
|
|
122
|
-
requireArgs(a, 1, "
|
|
175
|
+
requireArgs(a, 1, commandUsage("recipe", "validate-graph"));
|
|
123
176
|
return c.recipes.validateGraph(a[0], {
|
|
124
177
|
projectKey: f["project-key"],
|
|
125
178
|
});
|
|
126
179
|
},
|
|
127
|
-
usage: "dss recipe validate-graph <name> [--project-key KEY]",
|
|
128
180
|
description: "Validate declared recipe input/output graph references before building.",
|
|
129
181
|
examples: ["dss recipe validate-graph compute_orders",],
|
|
130
182
|
},
|
|
131
183
|
run: {
|
|
132
184
|
handler: async (c, a, f) => {
|
|
133
|
-
requireArgs(a, 1, "
|
|
185
|
+
requireArgs(a, 1, commandUsage("recipe", "run"));
|
|
134
186
|
const pk = f["project-key"];
|
|
135
187
|
const wait = recipeRunShouldWait(f);
|
|
136
188
|
const options = {
|
|
@@ -163,7 +215,6 @@ export const recipeCommands = {
|
|
|
163
215
|
}
|
|
164
216
|
return c.recipes.run(a[0], options);
|
|
165
217
|
},
|
|
166
|
-
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]",
|
|
167
218
|
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.",
|
|
168
219
|
examples: [
|
|
169
220
|
"dss recipe run compute_orders --wait",
|
|
@@ -173,7 +224,7 @@ export const recipeCommands = {
|
|
|
173
224
|
},
|
|
174
225
|
delete: {
|
|
175
226
|
handler: async (c, a, f) => {
|
|
176
|
-
requireArgs(a, 1, "
|
|
227
|
+
requireArgs(a, 1, commandUsage("recipe", "delete"));
|
|
177
228
|
const pk = f["project-key"];
|
|
178
229
|
if (executionMode(f).dryRun || f["if-exists"] === true) {
|
|
179
230
|
const current = await readIfExists(() => c.recipes.get(a[0], { projectKey: pk, includePayload: true, }));
|
|
@@ -186,19 +237,17 @@ export const recipeCommands = {
|
|
|
186
237
|
await c.recipes.delete(a[0], pk);
|
|
187
238
|
return { deleted: a[0], resource: "recipe", };
|
|
188
239
|
},
|
|
189
|
-
usage: "dss recipe delete <name> [--if-exists] [--dry-run] [--project-key KEY]",
|
|
190
240
|
description: "Delete a recipe.",
|
|
191
241
|
examples: ["dss recipe delete compute_orders", "dss recipe delete compute_orders --if-exists",],
|
|
192
242
|
},
|
|
193
243
|
download: {
|
|
194
244
|
handler: (c, a, f) => {
|
|
195
|
-
requireArgs(a, 1, "
|
|
245
|
+
requireArgs(a, 1, commandUsage("recipe", "download"));
|
|
196
246
|
return c.recipes.download(a[0], {
|
|
197
247
|
outputPath: f["output"],
|
|
198
248
|
projectKey: f["project-key"],
|
|
199
249
|
});
|
|
200
250
|
},
|
|
201
|
-
usage: "dss recipe download <name> [--output PATH] [--project-key KEY]",
|
|
202
251
|
description: "Download recipe definition as JSON.",
|
|
203
252
|
examples: [
|
|
204
253
|
"dss recipe download compute_orders",
|
|
@@ -207,13 +256,12 @@ export const recipeCommands = {
|
|
|
207
256
|
},
|
|
208
257
|
"download-code": {
|
|
209
258
|
handler: (c, a, f) => {
|
|
210
|
-
requireArgs(a, 1, "
|
|
259
|
+
requireArgs(a, 1, commandUsage("recipe", "download-code"));
|
|
211
260
|
return c.recipes.downloadCode(a[0], {
|
|
212
261
|
outputPath: f["output"],
|
|
213
262
|
projectKey: f["project-key"],
|
|
214
263
|
});
|
|
215
264
|
},
|
|
216
|
-
usage: "dss recipe download-code <name> [--output PATH] [--project-key KEY]",
|
|
217
265
|
description: "Download the code payload of a recipe.",
|
|
218
266
|
examples: [
|
|
219
267
|
"dss recipe download-code compute_orders",
|
|
@@ -222,57 +270,9 @@ export const recipeCommands = {
|
|
|
222
270
|
},
|
|
223
271
|
create: {
|
|
224
272
|
handler: async (c, _a, f) => {
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
const outputDataset = f["output"];
|
|
230
|
-
const outputFolder = f["output-folder"];
|
|
231
|
-
if (outputDataset && outputFolder) {
|
|
232
|
-
throw new UsageError("--output and --output-folder are mutually exclusive.");
|
|
233
|
-
}
|
|
234
|
-
if (!outputDataset && !outputFolder) {
|
|
235
|
-
throw new UsageError("--output or --output-folder is required. Usage: dss recipe create --type TYPE [--input DS] (--output DS | --output-folder FOLDER_ID)");
|
|
236
|
-
}
|
|
237
|
-
if (outputFolder && !f["output-connection"]) {
|
|
238
|
-
throw new UsageError("--output-connection is required when using --output-folder.");
|
|
239
|
-
}
|
|
240
|
-
const name = f["name"];
|
|
241
|
-
const pk = f["project-key"];
|
|
242
|
-
const inputDatasets = recipeInputDatasetsFromFlags(f);
|
|
243
|
-
const joinColumns = splitCsvFlag(f["join-on"]);
|
|
244
|
-
const fuzzyColumns = splitCsvFlag(f["fuzzy-on"]);
|
|
245
|
-
const rawFuzzyDistance = f["fuzzy-distance"];
|
|
246
|
-
let fuzzyDistance;
|
|
247
|
-
if (typeof rawFuzzyDistance === "string") {
|
|
248
|
-
const normalized = rawFuzzyDistance.trim().toUpperCase();
|
|
249
|
-
if (![
|
|
250
|
-
"DAMERAU_LEVENSHTEIN",
|
|
251
|
-
"HAMMING",
|
|
252
|
-
"JACCARD",
|
|
253
|
-
"COSINE",
|
|
254
|
-
"EUCLIDEAN",
|
|
255
|
-
].includes(normalized)) {
|
|
256
|
-
throw new UsageError("--fuzzy-distance must be one of DAMERAU_LEVENSHTEIN, HAMMING, JACCARD, COSINE, or EUCLIDEAN.", "invalid_enum");
|
|
257
|
-
}
|
|
258
|
-
fuzzyDistance = normalized;
|
|
259
|
-
}
|
|
260
|
-
const fuzzyThreshold = num(f["fuzzy-threshold"], "--fuzzy-threshold");
|
|
261
|
-
const payload = {
|
|
262
|
-
type,
|
|
263
|
-
name,
|
|
264
|
-
inputDatasets,
|
|
265
|
-
outputDataset,
|
|
266
|
-
outputFolder,
|
|
267
|
-
outputConnection: f["output-connection"],
|
|
268
|
-
...(joinColumns.length > 0 ? { joinOn: joinColumns, } : {}),
|
|
269
|
-
...(typeof f["join-type"] === "string" ? { joinType: f["join-type"], } : {}),
|
|
270
|
-
...(fuzzyColumns.length > 0 ? { fuzzyOn: fuzzyColumns, } : {}),
|
|
271
|
-
...(fuzzyDistance ? { fuzzyDistance, } : {}),
|
|
272
|
-
...(fuzzyThreshold !== undefined ? { fuzzyThreshold, } : {}),
|
|
273
|
-
fuzzyNormalize: f["normalize"] === true,
|
|
274
|
-
projectKey: pk,
|
|
275
|
-
};
|
|
273
|
+
const payload = recipeCreateOptionsFromFlags(f);
|
|
274
|
+
const name = payload.name;
|
|
275
|
+
const pk = payload.projectKey;
|
|
276
276
|
const zoneId = await resolveFlowZoneIdFromFlags(c, f, pk);
|
|
277
277
|
const zoneMove = zoneId && name
|
|
278
278
|
? [{ objectId: name, objectType: "RECIPE", },]
|
|
@@ -312,7 +312,6 @@ export const recipeCommands = {
|
|
|
312
312
|
},], pk);
|
|
313
313
|
return { created: createdName, resource: "recipe", ...created, ...moved, };
|
|
314
314
|
},
|
|
315
|
-
usage: "dss recipe create --type TYPE [--input DS[,DS2]] (--output DS | --output-folder FOLDER_ID) [--name NAME] [--output-connection CONN] [--zone ZONE|--zone-id ID] [--if-not-exists] [--dry-run] [--join-on COL|LEFT=RIGHT[,...]] [--join-type LEFT|INNER|RIGHT|FULL] [--fuzzy-on COL|LEFT=RIGHT[,...]] [--fuzzy-distance DAMERAU_LEVENSHTEIN|HAMMING|JACCARD|COSINE|EUCLIDEAN] [--fuzzy-threshold N] [--normalize] [--project-key KEY]",
|
|
316
315
|
description: "Create a recipe with optional inputs and a dataset or managed-folder output.",
|
|
317
316
|
examples: [
|
|
318
317
|
"dss recipe create --type python --input raw_orders,lookup --output orders_clean",
|
|
@@ -322,7 +321,7 @@ export const recipeCommands = {
|
|
|
322
321
|
},
|
|
323
322
|
clone: {
|
|
324
323
|
handler: async (c, a, f) => {
|
|
325
|
-
const usage = "
|
|
324
|
+
const usage = commandUsage("recipe", "clone");
|
|
326
325
|
const fromFlag = typeof f["from"] === "string" ? f["from"].trim() : "";
|
|
327
326
|
const sourceName = a[0] ?? fromFlag;
|
|
328
327
|
if (!sourceName) {
|
|
@@ -390,7 +389,6 @@ export const recipeCommands = {
|
|
|
390
389
|
const moved = await moveCreatedItemsToZone(c, f, [{ objectId: name, objectType: "RECIPE", },], pk);
|
|
391
390
|
return { ...cloned, resource: "recipe", ...moved, };
|
|
392
391
|
},
|
|
393
|
-
usage: "dss recipe clone (source|--from SOURCE) (--name NAME|--to NAME) [--replace-input FROM=TO] [--replace-output FROM=TO] [--replace-payload-text FROM=TO] [--output DATASET] [--copy-output-settings] [--path PATH] [--metastore-table TABLE] [--zone ZONE|--zone-id ID] [--dry-run] [--project-key KEY]",
|
|
394
392
|
description: "Clone a recipe graph/settings/payload into a separate experiment recipe.",
|
|
395
393
|
examples: [
|
|
396
394
|
"dss recipe clone compute_orders --name compute_orders_opt --output orders_opt --copy-output-settings --dry-run",
|
|
@@ -399,10 +397,10 @@ export const recipeCommands = {
|
|
|
399
397
|
},
|
|
400
398
|
diff: {
|
|
401
399
|
handler: async (c, a, f) => {
|
|
402
|
-
requireArgs(a, 1, "
|
|
400
|
+
requireArgs(a, 1, commandUsage("recipe", "diff"));
|
|
403
401
|
const filePath = f["file"];
|
|
404
402
|
if (!filePath) {
|
|
405
|
-
throw new UsageError(
|
|
403
|
+
throw new UsageError(`--file is required. Usage: ${commandUsage("recipe", "diff")}`);
|
|
406
404
|
}
|
|
407
405
|
// Read and validate the local file before any DSS request.
|
|
408
406
|
const localContent = readRecipeFile(filePath, "--file");
|
|
@@ -411,20 +409,19 @@ export const recipeCommands = {
|
|
|
411
409
|
projectKey: f["project-key"],
|
|
412
410
|
});
|
|
413
411
|
if (!result.payload) {
|
|
414
|
-
throw new
|
|
412
|
+
throw new ClientValidationError(`Recipe "${a[0]}" has no code payload to diff.`, "validation_failed");
|
|
415
413
|
}
|
|
416
414
|
return formatLineDiff(a[0], filePath, result.payload, localContent);
|
|
417
415
|
},
|
|
418
|
-
usage: "dss recipe diff <name> --file PATH [--project-key KEY]",
|
|
419
416
|
description: "Show differences between local file and remote recipe code.",
|
|
420
417
|
examples: ["dss recipe diff compute_orders --file code.py",],
|
|
421
418
|
},
|
|
422
419
|
update: {
|
|
423
420
|
handler: async (c, a, f) => {
|
|
424
|
-
requireArgs(a, 1, "
|
|
421
|
+
requireArgs(a, 1, commandUsage("recipe", "update"));
|
|
425
422
|
const data = jsonInput(f);
|
|
426
423
|
if (!data) {
|
|
427
|
-
throw new UsageError(
|
|
424
|
+
throw new UsageError(`--data, --data-file, or --stdin is required. Usage: ${commandUsage("recipe", "update")}`);
|
|
428
425
|
}
|
|
429
426
|
const pk = f["project-key"];
|
|
430
427
|
if (executionMode(f).dryRun) {
|
|
@@ -442,7 +439,6 @@ export const recipeCommands = {
|
|
|
442
439
|
await c.recipes.update(a[0], data, pk);
|
|
443
440
|
return { updated: a[0], resource: "recipe", };
|
|
444
441
|
},
|
|
445
|
-
usage: "dss recipe update <name> (--data '{...}' | --data-file PATH | --stdin) [--dry-run] [--project-key KEY]",
|
|
446
442
|
description: "Update recipe settings via JSON merge. Recipe definition fields must be nested under a top-level recipe key.",
|
|
447
443
|
examples: [
|
|
448
444
|
"dss recipe update compute_orders --data-file settings.json --dry-run",
|
|
@@ -452,7 +448,7 @@ export const recipeCommands = {
|
|
|
452
448
|
},
|
|
453
449
|
"add-input": {
|
|
454
450
|
handler: async (c, a, f) => {
|
|
455
|
-
requireArgs(a, 2, "
|
|
451
|
+
requireArgs(a, 2, commandUsage("recipe", "add-input"));
|
|
456
452
|
const role = f["role"] ?? "main";
|
|
457
453
|
const pk = f["project-key"];
|
|
458
454
|
const { recipe, } = await c.recipes.get(a[0], { projectKey: pk, });
|
|
@@ -480,7 +476,6 @@ export const recipeCommands = {
|
|
|
480
476
|
await c.recipes.update(a[0], { recipe: { inputs: { [role]: { items: nextItems, }, }, }, }, pk);
|
|
481
477
|
return { updated: a[0], resource: "recipe", action: "add-input", role, dataset: a[1], inputs, };
|
|
482
478
|
},
|
|
483
|
-
usage: "dss recipe add-input <recipe> <dataset> [--role ROLE] [--if-not-exists] [--dry-run] [--project-key KEY]",
|
|
484
479
|
description: "Add a dataset as a recipe input by appending one item to the current inputs (no need to resend the whole list).",
|
|
485
480
|
examples: [
|
|
486
481
|
"dss recipe add-input compute_orders extra_lookup",
|
|
@@ -489,7 +484,7 @@ export const recipeCommands = {
|
|
|
489
484
|
},
|
|
490
485
|
"remove-input": {
|
|
491
486
|
handler: async (c, a, f) => {
|
|
492
|
-
requireArgs(a, 2, "
|
|
487
|
+
requireArgs(a, 2, commandUsage("recipe", "remove-input"));
|
|
493
488
|
const role = f["role"] ?? "main";
|
|
494
489
|
const pk = f["project-key"];
|
|
495
490
|
const { recipe, } = await c.recipes.get(a[0], { projectKey: pk, });
|
|
@@ -524,7 +519,6 @@ export const recipeCommands = {
|
|
|
524
519
|
inputs,
|
|
525
520
|
};
|
|
526
521
|
},
|
|
527
|
-
usage: "dss recipe remove-input <recipe> <dataset> [--role ROLE] [--if-exists] [--dry-run] [--project-key KEY]",
|
|
528
522
|
description: "Remove a dataset from a recipe's inputs by dropping one item from the current inputs.",
|
|
529
523
|
examples: [
|
|
530
524
|
"dss recipe remove-input compute_orders stale_lookup",
|
|
@@ -533,7 +527,7 @@ export const recipeCommands = {
|
|
|
533
527
|
},
|
|
534
528
|
"get-payload": {
|
|
535
529
|
handler: async (c, a, f) => {
|
|
536
|
-
requireArgs(a, 1, "
|
|
530
|
+
requireArgs(a, 1, commandUsage("recipe", "get-payload"));
|
|
537
531
|
const payload = await c.recipes.getPayload(a[0], {
|
|
538
532
|
projectKey: f["project-key"],
|
|
539
533
|
});
|
|
@@ -543,7 +537,6 @@ export const recipeCommands = {
|
|
|
543
537
|
}
|
|
544
538
|
return payload;
|
|
545
539
|
},
|
|
546
|
-
usage: "dss recipe get-payload <name> [--output PATH] [--project-key KEY]",
|
|
547
540
|
description: "Print the recipe code payload as a JSON string, or write it to a file with --output.",
|
|
548
541
|
examples: [
|
|
549
542
|
"dss recipe get-payload compute_orders",
|
|
@@ -552,18 +545,17 @@ export const recipeCommands = {
|
|
|
552
545
|
},
|
|
553
546
|
cat: {
|
|
554
547
|
handler: (c, a, f) => {
|
|
555
|
-
requireArgs(a, 1, "
|
|
548
|
+
requireArgs(a, 1, commandUsage("recipe", "cat"));
|
|
556
549
|
return c.recipes.getPayload(a[0], {
|
|
557
550
|
projectKey: f["project-key"],
|
|
558
551
|
});
|
|
559
552
|
},
|
|
560
|
-
usage: "dss recipe cat <name> [--project-key KEY]",
|
|
561
553
|
description: "Print the recipe code payload as a JSON string.",
|
|
562
554
|
examples: ["dss recipe cat compute_orders",],
|
|
563
555
|
},
|
|
564
556
|
"set-payload": {
|
|
565
557
|
handler: async (c, a, f) => {
|
|
566
|
-
requireArgs(a, 1, "
|
|
558
|
+
requireArgs(a, 1, commandUsage("recipe", "set-payload"));
|
|
567
559
|
const filePath = f["file"];
|
|
568
560
|
if (!filePath)
|
|
569
561
|
throw new UsageError("--file is required.");
|
|
@@ -603,7 +595,6 @@ export const recipeCommands = {
|
|
|
603
595
|
...(backupPath ? { backupPath, } : {}),
|
|
604
596
|
};
|
|
605
597
|
},
|
|
606
|
-
usage: "dss recipe set-payload <name> --file PATH [--backup-dir DIR|--no-backup] [--dry-run] [--project-key KEY]",
|
|
607
598
|
description: "Upload recipe code from a local file, backing up payload, graph, settings, and version metadata by default.",
|
|
608
599
|
examples: [
|
|
609
600
|
"dss recipe set-payload compute_orders --file code.py --dry-run",
|
|
@@ -613,7 +604,7 @@ export const recipeCommands = {
|
|
|
613
604
|
},
|
|
614
605
|
restore: {
|
|
615
606
|
handler: async (c, a, f) => {
|
|
616
|
-
const usage = "
|
|
607
|
+
const usage = commandUsage("recipe", "restore");
|
|
617
608
|
requireArgs(a, 1, usage);
|
|
618
609
|
const backupPath = requiredStringFlag(f, "backup", usage);
|
|
619
610
|
const backup = readRecipeBackupFile(backupPath);
|
|
@@ -648,7 +639,6 @@ export const recipeCommands = {
|
|
|
648
639
|
payloadOnly: f["payload-only"] === true,
|
|
649
640
|
};
|
|
650
641
|
},
|
|
651
|
-
usage: "dss recipe restore <name> --backup FILE [--payload-only] [--dry-run] [--project-key KEY]",
|
|
652
642
|
description: "Restore a recipe from a set-payload backup.",
|
|
653
643
|
examples: [
|
|
654
644
|
"dss recipe restore compute_orders --backup .dss-backups/recipes/backup.recipe-backup.json --dry-run",
|
|
@@ -656,7 +646,7 @@ export const recipeCommands = {
|
|
|
656
646
|
},
|
|
657
647
|
"assert-unchanged": {
|
|
658
648
|
handler: async (c, a, f) => {
|
|
659
|
-
const usage = "
|
|
649
|
+
const usage = commandUsage("recipe", "assert-unchanged");
|
|
660
650
|
requireArgs(a, 1, usage);
|
|
661
651
|
const backupPath = requiredStringFlag(f, "since", usage);
|
|
662
652
|
const backup = readRecipeBackupFile(backupPath);
|
|
@@ -708,10 +698,9 @@ export const recipeCommands = {
|
|
|
708
698
|
failures,
|
|
709
699
|
};
|
|
710
700
|
},
|
|
711
|
-
usage: "dss recipe assert-unchanged <name> --since BACKUP [--project-key KEY]",
|
|
712
701
|
description: "Compare current recipe payload, graph, and code env against a backup.",
|
|
713
702
|
examples: [
|
|
714
703
|
"dss recipe assert-unchanged compute_orders --since .dss-backups/recipes/backup.recipe-backup.json",
|
|
715
704
|
],
|
|
716
705
|
},
|
|
717
|
-
};
|
|
706
|
+
});
|