dataiku-sdk 3.6.0 → 3.7.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 +14 -6
- package/bin/bun-version.js +14 -0
- package/bin/dss.js +23 -12
- package/dist/build-metadata.json +1 -1
- package/dist/packages/types/src/index.d.ts +74 -1
- package/dist/packages/types/src/index.js +53 -1
- package/dist/src/cli/coerce.d.ts +1 -0
- package/dist/src/cli/coerce.js +19 -15
- package/dist/src/cli/command-syntax.json +3521 -416
- package/dist/src/cli/commands/analysis.js +19 -1
- package/dist/src/cli/commands/bundle.js +22 -0
- package/dist/src/cli/commands/connection.js +26 -2
- package/dist/src/cli/commands/data-quality.js +33 -1
- package/dist/src/cli/commands/dataset.js +35 -4
- package/dist/src/cli/commands/discussion.js +15 -0
- package/dist/src/cli/commands/doctor.js +1 -1
- package/dist/src/cli/commands/flow.d.ts +5 -0
- package/dist/src/cli/commands/flow.js +57 -0
- package/dist/src/cli/commands/future.js +8 -0
- package/dist/src/cli/commands/index.js +6 -0
- package/dist/src/cli/commands/job.js +29 -6
- package/dist/src/cli/commands/metrics.js +21 -1
- package/dist/src/cli/commands/ml-task.d.ts +5 -0
- package/dist/src/cli/commands/ml-task.js +86 -16
- package/dist/src/cli/commands/mlflow.d.ts +11 -0
- package/dist/src/cli/commands/mlflow.js +121 -0
- package/dist/src/cli/commands/plugin.js +5 -11
- package/dist/src/cli/commands/project-deployer.js +70 -0
- package/dist/src/cli/commands/project-library.js +2 -5
- package/dist/src/cli/commands/project.js +8 -0
- package/dist/src/cli/commands/recipe.d.ts +9 -0
- package/dist/src/cli/commands/recipe.js +93 -7
- package/dist/src/cli/commands/saved-model.d.ts +1 -1
- package/dist/src/cli/commands/saved-model.js +9 -76
- package/dist/src/cli/commands/streaming-endpoint.js +30 -1
- package/dist/src/cli/commands/webapp.js +8 -0
- package/dist/src/cli/commands/wiki.js +22 -0
- package/dist/src/cli/commands/workspace.js +8 -0
- package/dist/src/cli/contract.d.ts +16 -15
- package/dist/src/cli/contract.js +139 -3404
- package/dist/src/cli/doctor.d.ts +13 -0
- package/dist/src/cli/doctor.js +41 -1
- package/dist/src/cli/flags.d.ts +7 -1
- package/dist/src/cli/flags.js +78 -6
- package/dist/src/cli/helpers/app-successor.js +1 -2
- package/dist/src/cli/helpers/documentation.d.ts +21 -0
- package/dist/src/cli/helpers/documentation.js +53 -0
- package/dist/src/cli/helpers/trained-model.d.ts +26 -0
- package/dist/src/cli/helpers/trained-model.js +144 -0
- package/dist/src/cli/list-output.d.ts +7 -0
- package/dist/src/cli/list-output.js +77 -0
- package/dist/src/cli/list-shapes.d.ts +21 -0
- package/dist/src/cli/list-shapes.js +111 -0
- package/dist/src/cli/output-schemas.d.ts +0 -14
- package/dist/src/cli/output-schemas.js +4 -7
- package/dist/src/cli/output.d.ts +0 -1
- package/dist/src/cli/output.js +27 -19
- package/dist/src/cli/plans.d.ts +14 -0
- package/dist/src/cli/plans.js +3684 -0
- package/dist/src/cli/usage.d.ts +7 -0
- package/dist/src/cli/usage.js +20 -1
- package/dist/src/cli/version.d.ts +2 -2
- package/dist/src/cli/version.js +2 -2
- package/dist/src/cli.js +127 -113
- package/dist/src/client.d.ts +52 -43
- package/dist/src/client.js +267 -96
- package/dist/src/errors.d.ts +11 -1
- package/dist/src/errors.js +31 -47
- package/dist/src/generated/action-output-schemas.json +345 -89
- package/dist/src/index.d.ts +5 -1
- package/dist/src/index.js +3 -0
- package/dist/src/resources/analyses.d.ts +8 -0
- package/dist/src/resources/analyses.js +13 -1
- package/dist/src/resources/bundles.d.ts +34 -0
- package/dist/src/resources/bundles.js +67 -0
- package/dist/src/resources/connections.d.ts +9 -0
- package/dist/src/resources/connections.js +15 -0
- package/dist/src/resources/data-quality.d.ts +20 -0
- package/dist/src/resources/data-quality.js +30 -0
- package/dist/src/resources/dataset-create.d.ts +19 -0
- package/dist/src/resources/dataset-create.js +66 -0
- package/dist/src/resources/datasets.d.ts +25 -15
- package/dist/src/resources/datasets.js +59 -111
- package/dist/src/resources/discussions.d.ts +5 -0
- package/dist/src/resources/discussions.js +7 -0
- package/dist/src/resources/documentation.d.ts +25 -0
- package/dist/src/resources/documentation.js +16 -0
- package/dist/src/resources/flow.d.ts +48 -0
- package/dist/src/resources/flow.js +65 -0
- package/dist/src/resources/futures.d.ts +23 -0
- package/dist/src/resources/futures.js +32 -0
- package/dist/src/resources/jobs.js +102 -2
- package/dist/src/resources/metrics.d.ts +10 -0
- package/dist/src/resources/metrics.js +10 -0
- package/dist/src/resources/ml-tasks.d.ts +65 -2
- package/dist/src/resources/ml-tasks.js +102 -28
- package/dist/src/resources/mlflow-extension.d.ts +73 -0
- package/dist/src/resources/mlflow-extension.js +105 -0
- package/dist/src/resources/projects.d.ts +6 -0
- package/dist/src/resources/projects.js +8 -0
- package/dist/src/resources/recipe-create.d.ts +65 -0
- package/dist/src/resources/recipe-create.js +338 -0
- package/dist/src/resources/recipes.d.ts +28 -29
- package/dist/src/resources/recipes.js +126 -245
- package/dist/src/resources/saved-models.d.ts +10 -6
- package/dist/src/resources/saved-models.js +16 -14
- package/dist/src/resources/scenarios.js +8 -14
- package/dist/src/resources/streaming-endpoints.d.ts +12 -0
- package/dist/src/resources/streaming-endpoints.js +15 -0
- package/dist/src/resources/trained-model.d.ts +60 -0
- package/dist/src/resources/trained-model.js +98 -0
- package/dist/src/resources/webapps.d.ts +8 -0
- package/dist/src/resources/webapps.js +10 -0
- package/dist/src/resources/wiki.d.ts +5 -0
- package/dist/src/resources/wiki.js +7 -0
- package/dist/src/resources/workspaces.d.ts +2 -0
- package/dist/src/resources/workspaces.js +4 -0
- package/dist/src/utils/response-file.js +20 -9
- package/dist/src/utils/secret-sanitize.d.ts +7 -0
- package/dist/src/utils/secret-sanitize.js +46 -0
- package/package.json +25 -26
- package/plugin.json +1 -1
- package/skills/dataiku-dss/SKILL.md +1 -1
- package/skills/dataiku-dss/references/authentication.md +3 -1
- package/skills/dataiku-dss/references/coding.md +1 -0
- package/skills/dataiku-dss/references/discovery.md +4 -6
- package/skills/dataiku-dss/references/troubleshooting.md +3 -2
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { num, parseBooleanOption, splitCsvFlag, } from "../coerce.js";
|
|
2
|
+
import { executionMode, } from "../flags.js";
|
|
3
|
+
import { withUsage, } from "../syntax.js";
|
|
4
|
+
import { UsageError, } from "../usage.js";
|
|
5
|
+
/** `dss mlflow set-inference-info` flags → SDK inference info (shared with --plan). */
|
|
6
|
+
export function inferenceInfoFromFlags(runId, f) {
|
|
7
|
+
const predictionType = f["prediction-type"];
|
|
8
|
+
if (typeof predictionType !== "string") {
|
|
9
|
+
throw new UsageError("--prediction-type is required.", "missing_required_flag");
|
|
10
|
+
}
|
|
11
|
+
const classes = splitCsvFlag(f["classes"]);
|
|
12
|
+
return {
|
|
13
|
+
runId,
|
|
14
|
+
predictionType: predictionType.toUpperCase(),
|
|
15
|
+
...(classes.length > 0 ? { classes, } : {}),
|
|
16
|
+
...(typeof f["code-env"] === "string" ? { codeEnvName: f["code-env"], } : {}),
|
|
17
|
+
...(typeof f["target"] === "string" ? { target: f["target"], } : {}),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/** `dss mlflow deploy-run` flags → SDK deploy options (shared with --plan). */
|
|
21
|
+
export function deployRunOptionsFromFlags(runId, savedModelId, f) {
|
|
22
|
+
const classLabels = splitCsvFlag(f["classes"]);
|
|
23
|
+
const setActive = f["set-active"];
|
|
24
|
+
const threshold = f["binary-classification-threshold"];
|
|
25
|
+
const optimal = f["use-optimal-threshold"];
|
|
26
|
+
const skipReports = f["skip-expensive-reports"];
|
|
27
|
+
return {
|
|
28
|
+
runId,
|
|
29
|
+
savedModelId,
|
|
30
|
+
...(typeof f["version-id"] === "string" ? { versionId: f["version-id"], } : {}),
|
|
31
|
+
...(typeof f["model-name"] === "string" ? { modelName: f["model-name"], } : {}),
|
|
32
|
+
...(typeof f["evaluation-dataset"] === "string"
|
|
33
|
+
? { evaluationDataset: f["evaluation-dataset"], }
|
|
34
|
+
: {}),
|
|
35
|
+
...(typeof f["target"] === "string" ? { targetColumnName: f["target"], } : {}),
|
|
36
|
+
...(classLabels.length > 0 ? { classLabels, } : {}),
|
|
37
|
+
...(typeof f["code-env"] === "string" ? { codeEnvName: f["code-env"], } : {}),
|
|
38
|
+
...(setActive !== undefined ? { activate: parseBooleanOption(setActive, "--set-active"), } : {}),
|
|
39
|
+
...(threshold !== undefined
|
|
40
|
+
? { binaryClassificationThreshold: num(threshold, "--binary-classification-threshold"), }
|
|
41
|
+
: {}),
|
|
42
|
+
...(optimal !== undefined
|
|
43
|
+
? { useOptimalThreshold: parseBooleanOption(optimal, "--use-optimal-threshold"), }
|
|
44
|
+
: {}),
|
|
45
|
+
...(skipReports !== undefined
|
|
46
|
+
? { skipExpensiveReports: parseBooleanOption(skipReports, "--skip-expensive-reports"), }
|
|
47
|
+
: {}),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** `dss mlflow create-experiments-dataset` flags → SDK options (shared with --plan). */
|
|
51
|
+
export function experimentsDatasetOptionsFromFlags(datasetName, f) {
|
|
52
|
+
const experimentIds = splitCsvFlag(f["experiments"]);
|
|
53
|
+
const viewType = f["view-type"];
|
|
54
|
+
const format = f["format"];
|
|
55
|
+
return {
|
|
56
|
+
datasetName,
|
|
57
|
+
...(experimentIds.length > 0 ? { experimentIds, } : {}),
|
|
58
|
+
...(typeof viewType === "string"
|
|
59
|
+
? {
|
|
60
|
+
viewType: viewType.toUpperCase(),
|
|
61
|
+
}
|
|
62
|
+
: {}),
|
|
63
|
+
...(typeof f["filter"] === "string" ? { filter: f["filter"], } : {}),
|
|
64
|
+
...(typeof format === "string"
|
|
65
|
+
? { format: format.toUpperCase(), }
|
|
66
|
+
: {}),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export const mlflowCommands = withUsage("mlflow", {
|
|
70
|
+
"list-models": {
|
|
71
|
+
handler: (c, a, f) => c.mlflowExtension.listModels(a[0], f["project-key"]),
|
|
72
|
+
description: "List the models an MLflow experiment-tracking run logged ({runId, artifactPath}).",
|
|
73
|
+
examples: ["dss mlflow list-models RUN_ID",],
|
|
74
|
+
},
|
|
75
|
+
"set-inference-info": {
|
|
76
|
+
handler: async (c, a, f) => {
|
|
77
|
+
await c.mlflowExtension.setRunInferenceInfo(inferenceInfoFromFlags(a[0], f), f["project-key"]);
|
|
78
|
+
return { updated: a[0], resource: "mlflow", };
|
|
79
|
+
},
|
|
80
|
+
description: "Record an MLflow run's prediction type, classes, code env, and target so deploy-run can use them.",
|
|
81
|
+
examples: [
|
|
82
|
+
"dss mlflow set-inference-info RUN_ID --prediction-type MULTICLASS --classes a,b,c --target species",
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
"deploy-run": {
|
|
86
|
+
handler: (c, a, f) => c.mlflowExtension.deployRun(deployRunOptionsFromFlags(a[0], a[1], f), f["project-key"]),
|
|
87
|
+
description: "Deploy an MLflow run's model as a version of an existing saved model (default version id: timestamp); --evaluation-dataset evaluates it. Synchronous: DSS loads the model in its code env, often past 30 s, so raise --request-timeout.",
|
|
88
|
+
examples: [
|
|
89
|
+
"dss mlflow deploy-run RUN_ID SAVED_MODEL_ID --version-id v2 --code-env py311_mlflow --request-timeout 300000",
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
"create-experiments-dataset": {
|
|
93
|
+
handler: async (c, a, f) => {
|
|
94
|
+
await c.mlflowExtension.createExperimentsDataset(experimentsDatasetOptionsFromFlags(a[0], f), f["project-key"]);
|
|
95
|
+
return { created: a[0], resource: "mlflow", };
|
|
96
|
+
},
|
|
97
|
+
description: "Create a virtual dataset exposing the project's MLflow experiment-tracking runs.",
|
|
98
|
+
examples: ["dss mlflow create-experiments-dataset mlflow_runs --experiments FGXlefMU",],
|
|
99
|
+
},
|
|
100
|
+
"garbage-collect": {
|
|
101
|
+
handler: async (c, _a, f) => {
|
|
102
|
+
if (executionMode(f).dryRun) {
|
|
103
|
+
return { dryRun: true, action: "garbage-collect", resource: "mlflow", };
|
|
104
|
+
}
|
|
105
|
+
await c.mlflowExtension.garbageCollect(f["project-key"]);
|
|
106
|
+
return { garbageCollected: true, resource: "mlflow", };
|
|
107
|
+
},
|
|
108
|
+
description: "Permanently delete the project's MLflow experiments and runs marked as deleted.",
|
|
109
|
+
examples: ["dss mlflow garbage-collect --dry-run",],
|
|
110
|
+
},
|
|
111
|
+
"clean-db": {
|
|
112
|
+
handler: async (c, _a, f) => {
|
|
113
|
+
if (executionMode(f).dryRun)
|
|
114
|
+
return { dryRun: true, action: "clean-db", resource: "mlflow", };
|
|
115
|
+
await c.mlflowExtension.cleanDb(f["project-key"]);
|
|
116
|
+
return { cleaned: true, resource: "mlflow", };
|
|
117
|
+
},
|
|
118
|
+
description: "Admin: delete ALL MLflow experiment-tracking data of the project (experiments, runs, params, metrics, tags). Irreversible.",
|
|
119
|
+
examples: ["dss mlflow clean-db --plan",],
|
|
120
|
+
},
|
|
121
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import { validatedPluginGitUrl, validatePluginDestinationPath, validatePluginId, validatePluginName, validatePluginPath, } from "../../resources/plugins.js";
|
|
3
|
-
import {
|
|
3
|
+
import { writeResponseToFile, } from "../../utils/response-file.js";
|
|
4
|
+
import { num, readStdinText, sha256Hex, } from "../coerce.js";
|
|
4
5
|
import { executionMode, } from "../flags.js";
|
|
5
6
|
import { planResult, } from "../output.js";
|
|
6
7
|
import { commandUsage, withUsage, } from "../syntax.js";
|
|
@@ -188,7 +189,7 @@ export const pluginCommands = withUsage("plugin", {
|
|
|
188
189
|
}
|
|
189
190
|
const pluginId = validatePluginId(a[0]);
|
|
190
191
|
const res = await c.plugins.download(pluginId);
|
|
191
|
-
const bytes = await
|
|
192
|
+
const bytes = await writeResponseToFile(out, res);
|
|
192
193
|
return { path: out, bytes, };
|
|
193
194
|
},
|
|
194
195
|
description: "Download a development plugin as a zip archive to a local file.",
|
|
@@ -598,7 +599,7 @@ export const pluginCommands = withUsage("plugin", {
|
|
|
598
599
|
const out = f["output"];
|
|
599
600
|
if (typeof out === "string" && out.trim() !== "") {
|
|
600
601
|
const res = await c.plugins.downloadFile(pluginId, path);
|
|
601
|
-
const bytes = await
|
|
602
|
+
const bytes = await writeResponseToFile(out, res);
|
|
602
603
|
return { path: out, bytes, };
|
|
603
604
|
}
|
|
604
605
|
return { data: await c.plugins.getFile(pluginId, path), };
|
|
@@ -634,10 +635,7 @@ export const pluginCommands = withUsage("plugin", {
|
|
|
634
635
|
: await readStdinText();
|
|
635
636
|
await c.plugins.putFile(pluginId, path, content);
|
|
636
637
|
const bytes = typeof content === "string" ? Buffer.byteLength(content, "utf8") : content.length;
|
|
637
|
-
|
|
638
|
-
hasher.update(typeof content === "string" ? content : new Uint8Array(content));
|
|
639
|
-
const sha256 = hasher.digest("hex");
|
|
640
|
-
return { written: path, pluginId, bytes, sha256, };
|
|
638
|
+
return { written: path, pluginId, bytes, sha256: sha256Hex(content), };
|
|
641
639
|
},
|
|
642
640
|
description: "Create or replace a development plugin file with text or binary content; reports the written byte count and sha256.",
|
|
643
641
|
examples: [
|
|
@@ -760,7 +758,3 @@ function readSettingsInput(flags) {
|
|
|
760
758
|
}
|
|
761
759
|
return parsed;
|
|
762
760
|
}
|
|
763
|
-
async function writeResponseToFileForPlugin(path, res) {
|
|
764
|
-
const { writeResponseToFile, } = await import("../../utils/response-file.js");
|
|
765
|
-
return writeResponseToFile(path, res);
|
|
766
|
-
}
|
|
@@ -103,4 +103,74 @@ export const projectDeployerCommands = withUsage("project-deployer", {
|
|
|
103
103
|
description: "Create a Project Deployer infrastructure.",
|
|
104
104
|
examples: ["dss project-deployer create-infra --data-file infra.json",],
|
|
105
105
|
},
|
|
106
|
+
"list-stages": {
|
|
107
|
+
handler: (c) => c.projectDeployer.listStages(),
|
|
108
|
+
description: "List the Project Deployer stages (e.g. Development, Test, Production).",
|
|
109
|
+
examples: ["dss project-deployer list-stages",],
|
|
110
|
+
},
|
|
111
|
+
"get-infra": {
|
|
112
|
+
handler: (c, a) => c.projectDeployer.getInfra(a[0]),
|
|
113
|
+
description: "Get a Project Deployer infrastructure (stage, automation node, deployments).",
|
|
114
|
+
examples: ["dss project-deployer get-infra prod-infra",],
|
|
115
|
+
},
|
|
116
|
+
"infra-settings": {
|
|
117
|
+
handler: (c, a) => c.projectDeployer.getInfraSettings(a[0]),
|
|
118
|
+
description: "Get an infrastructure's settings (permissions, automation node URL, connection remappings).",
|
|
119
|
+
examples: ["dss project-deployer infra-settings prod-infra",],
|
|
120
|
+
},
|
|
121
|
+
"save-infra-settings": {
|
|
122
|
+
handler: async (c, a, f) => {
|
|
123
|
+
await c.projectDeployer.saveInfraSettings(a[0], requiredJsonInput(f, "--data, --data-file, or --stdin is required (settings from infra-settings)."));
|
|
124
|
+
return { updated: a[0], resource: "project-deployer", };
|
|
125
|
+
},
|
|
126
|
+
description: "Save infrastructure settings obtained from infra-settings, edited.",
|
|
127
|
+
examples: ["dss project-deployer save-infra-settings prod-infra --data-file infra.json",],
|
|
128
|
+
},
|
|
129
|
+
"delete-infra": {
|
|
130
|
+
handler: async (c, a) => {
|
|
131
|
+
await c.projectDeployer.deleteInfra(a[0]);
|
|
132
|
+
return { deleted: a[0], resource: "project-deployer", };
|
|
133
|
+
},
|
|
134
|
+
description: "Delete an infrastructure that no deployment uses.",
|
|
135
|
+
examples: ["dss project-deployer delete-infra old-infra --plan",],
|
|
136
|
+
},
|
|
137
|
+
"deployment-settings": {
|
|
138
|
+
handler: (c, a) => c.projectDeployer.getDeploymentSettings(a[0]),
|
|
139
|
+
description: "Get a deployment's settings (infra, bundle, remappings); edit and send to save-deployment-settings.",
|
|
140
|
+
examples: ["dss project-deployer deployment-settings v1-on-prod",],
|
|
141
|
+
},
|
|
142
|
+
"governance-status": {
|
|
143
|
+
handler: (c, a, f) => c.projectDeployer.getGovernanceStatus(a[0], f["bundle-id"]),
|
|
144
|
+
description: "Governance status of a deployment's bundle (or --bundle-id): messages on whether it may be deployed.",
|
|
145
|
+
examples: ["dss project-deployer governance-status v1-on-prod",],
|
|
146
|
+
},
|
|
147
|
+
"delete-project": {
|
|
148
|
+
handler: async (c, a) => {
|
|
149
|
+
await c.projectDeployer.deleteProject(a[0]);
|
|
150
|
+
return { deleted: a[0], resource: "project-deployer", };
|
|
151
|
+
},
|
|
152
|
+
description: "Delete a published project that no deployment uses.",
|
|
153
|
+
examples: ["dss project-deployer delete-project MYPROJECT --plan",],
|
|
154
|
+
},
|
|
155
|
+
"project-settings": {
|
|
156
|
+
handler: (c, a) => c.projectDeployer.getProjectSettings(a[0]),
|
|
157
|
+
description: "Get a published project's settings (owner, permissions).",
|
|
158
|
+
examples: ["dss project-deployer project-settings MYPROJECT",],
|
|
159
|
+
},
|
|
160
|
+
"save-project-settings": {
|
|
161
|
+
handler: async (c, a, f) => {
|
|
162
|
+
await c.projectDeployer.saveProjectSettings(a[0], requiredJsonInput(f, "--data, --data-file, or --stdin is required (settings from project-settings)."));
|
|
163
|
+
return { updated: a[0], resource: "project-deployer", };
|
|
164
|
+
},
|
|
165
|
+
description: "Save published project settings obtained from project-settings, edited.",
|
|
166
|
+
examples: ["dss project-deployer save-project-settings MYPROJECT --data-file published.json",],
|
|
167
|
+
},
|
|
168
|
+
"delete-bundle": {
|
|
169
|
+
handler: async (c, a) => {
|
|
170
|
+
await c.projectDeployer.deleteBundle(a[0], a[1]);
|
|
171
|
+
return { deleted: a[1], resource: "project-deployer", project: a[0], };
|
|
172
|
+
},
|
|
173
|
+
description: "Delete a bundle of a published project that no deployment uses.",
|
|
174
|
+
examples: ["dss project-deployer delete-bundle MYPROJECT v1 --plan",],
|
|
175
|
+
},
|
|
106
176
|
});
|
|
@@ -8,9 +8,6 @@ import { commandUsage, withUsage, } from "../syntax.js";
|
|
|
8
8
|
import { requireArgs, UsageError, } from "../usage.js";
|
|
9
9
|
const PROJECT_LIBRARY_EXIT_CODES = { usage: 1, error: 2, transient: 3, };
|
|
10
10
|
const PUT_FLAG_ERROR_HINT = "Pass a 64-character SHA-256 hex digest (lowercase or uppercase).";
|
|
11
|
-
function sha256BytesHex(bytes) {
|
|
12
|
-
return new Bun.CryptoHasher("sha256").update(bytes).digest("hex");
|
|
13
|
-
}
|
|
14
11
|
function projectLibraryContentsEndpoint(client, projectKey, path) {
|
|
15
12
|
return encodedProjectEndpoint(client, projectKey, `/libraries/contents/${encodeLibraryPath(path)}`);
|
|
16
13
|
}
|
|
@@ -43,7 +40,7 @@ export function projectLibraryPutPayload(flags) {
|
|
|
43
40
|
contentSource: "file",
|
|
44
41
|
file: flags["file"],
|
|
45
42
|
bytes: bytes.length,
|
|
46
|
-
sha256:
|
|
43
|
+
sha256: sha256Hex(bytes),
|
|
47
44
|
...(expectSha256 ? { expectSha256, } : {}),
|
|
48
45
|
};
|
|
49
46
|
}
|
|
@@ -90,7 +87,7 @@ export const projectLibraryCommands = withUsage("project-library", {
|
|
|
90
87
|
throw new UsageError("--output PATH is required.", "missing_required_flag");
|
|
91
88
|
const bytes = await c.projectLibrary.getFileBytes(a[0], f["project-key"]);
|
|
92
89
|
const written = await Bun.write(out, bytes, { createPath: false, });
|
|
93
|
-
return { path: out, bytes: written, sha256:
|
|
90
|
+
return { path: out, bytes: written, sha256: sha256Hex(bytes), };
|
|
94
91
|
},
|
|
95
92
|
description: "Download a project library file's raw bytes to a local file.",
|
|
96
93
|
examples: ["dss project-library get-bytes static/logo.png --output ./logo.png",],
|
|
@@ -278,4 +278,12 @@ export const projectCommands = withUsage("project", {
|
|
|
278
278
|
description: "Update a project's settings via JSON merge.",
|
|
279
279
|
examples: ["dss project settings-set --data-file settings.json --project-key MY_PROJ",],
|
|
280
280
|
},
|
|
281
|
+
"push-to-git-remote": {
|
|
282
|
+
handler: async (c, a, f) => {
|
|
283
|
+
await c.projects.pushToGitRemote(a[0], f["project-key"]);
|
|
284
|
+
return { pushed: a[0], resource: "project", };
|
|
285
|
+
},
|
|
286
|
+
description: "Push the project to a Git remote already declared in DSS (per-project Git mode). Branches, commits, pulls, and remotes: dss project-git.",
|
|
287
|
+
examples: ["dss project push-to-git-remote origin --plan",],
|
|
288
|
+
},
|
|
281
289
|
});
|
|
@@ -13,6 +13,15 @@ export declare function recipeCreateOptionsFromFlags(f: Record<string, string |
|
|
|
13
13
|
fuzzyDistance?: string | undefined;
|
|
14
14
|
fuzzyThreshold?: number | undefined;
|
|
15
15
|
fuzzyNormalize: boolean;
|
|
16
|
+
orderBy?: string | undefined;
|
|
17
|
+
formula?: string | undefined;
|
|
18
|
+
filter?: string | undefined;
|
|
16
19
|
projectKey: string | undefined;
|
|
20
|
+
aggregate?: string[] | undefined;
|
|
21
|
+
dropColumns?: string[] | undefined;
|
|
22
|
+
fillEmpty?: string[] | undefined;
|
|
23
|
+
groupBy?: string[] | undefined;
|
|
24
|
+
keepColumns?: string[] | undefined;
|
|
25
|
+
rename?: string[] | undefined;
|
|
17
26
|
};
|
|
18
27
|
export declare const recipeCommands: Record<string, CommandMeta>;
|
|
@@ -1,13 +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
|
+
import { ClientValidationError, DataikuError, } from "../../errors.js";
|
|
5
|
+
import { recipeOutputSchemaIsComputable, schemaUpdateComputableId, schemaUpdateIsPending, } from "../../resources/recipe-create.js";
|
|
5
6
|
import { deepMerge, } from "../../utils/deep-merge.js";
|
|
6
7
|
import { jobLogFilterFromFlag, jsonInput, maxLogLinesFromFlags, normalizeLineEndings, num, recipeInputDatasetsFromFlags, requiredJsonInput, requiredStringFlag, rewritePairsFromFlags, sha256Hex, splitCsvFlag, stableHash, } from "../coerce.js";
|
|
7
8
|
import { executionMode, } from "../flags.js";
|
|
8
9
|
import { moveCreatedItemsToZone, resolveFlowZoneIdFromFlags, } from "../helpers/flow-zone.js";
|
|
9
10
|
import { ensureRecipeBackupDir, readRecipeBackup, recipeBackupDocument, recipeBackupPath, recipeCodeEnv, recipeGraph, recipeInputItemRef, recipeRoleInputItems, recipeRunShouldWait, writeRecipeBackup, } from "../helpers/recipe.js";
|
|
10
|
-
import { encodedProjectEndpoint, readIfExists, skipResult, } from "../output.js";
|
|
11
|
+
import { encodedProjectEndpoint, enqueueCliWarning, readIfExists, skipResult, } from "../output.js";
|
|
11
12
|
import { commandUsage, withUsage, } from "../syntax.js";
|
|
12
13
|
import { requireArgs, UsageError, } from "../usage.js";
|
|
13
14
|
/** Read a local recipe file before any DSS request, mapping read failures to usage validation. */
|
|
@@ -30,6 +31,51 @@ function readRecipeBackupFile(backupPath) {
|
|
|
30
31
|
throw new UsageError(`Could not read --backup ${backupPath}: ${reason}.`, "not_found", "Verify the backup file path and that it is readable.");
|
|
31
32
|
}
|
|
32
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* DSS does not recompute visual-recipe output schemas when the recipe is
|
|
36
|
+
* saved, and a build against a stale or empty output schema "succeeds" with
|
|
37
|
+
* the wrong columns. Around a payload write: outputs whose schema matched the
|
|
38
|
+
* DSS-computed one before the write (DSS-derived) or is empty get the newly
|
|
39
|
+
* computed schema; outputs whose schema had been hand-edited are left alone
|
|
40
|
+
* and reported in a warning.
|
|
41
|
+
*/
|
|
42
|
+
async function writeKeepingDerivedOutputSchemas(c, recipeName, recipeType, projectKey, write) {
|
|
43
|
+
if (typeof recipeType !== "string" || !recipeOutputSchemaIsComputable(recipeType)) {
|
|
44
|
+
await write();
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
const derivedOutputs = await c.recipes.computeSchemaUpdates(recipeName, projectKey).then((before) => before.computables.filter((computable) => !schemaUpdateIsPending(computable)).map(schemaUpdateComputableId),
|
|
48
|
+
// Unknown before-state: only empty schemas are safe to fill.
|
|
49
|
+
(error) => {
|
|
50
|
+
if (error instanceof DataikuError)
|
|
51
|
+
return [];
|
|
52
|
+
throw error;
|
|
53
|
+
});
|
|
54
|
+
await write();
|
|
55
|
+
try {
|
|
56
|
+
const result = await c.recipes.updateSchema(recipeName, { projectKey, derivedOutputs, });
|
|
57
|
+
if (result.pending.length > 0) {
|
|
58
|
+
enqueueCliWarning({
|
|
59
|
+
code: "recipe_output_schema_outdated",
|
|
60
|
+
recipe: recipeName,
|
|
61
|
+
outputs: result.pending,
|
|
62
|
+
hint: `These outputs have an edited schema that differs from the DSS-computed one. Run dss recipe update-schema ${recipeName} to replace it, or build with --auto-update-schema.`,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return result.updated.length > 0 ? { outputSchemaUpdated: result.updated, } : {};
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (!(error instanceof DataikuError))
|
|
69
|
+
throw error;
|
|
70
|
+
enqueueCliWarning({
|
|
71
|
+
code: "recipe_output_schema_not_computed",
|
|
72
|
+
recipe: recipeName,
|
|
73
|
+
error: error.message.split("\n")[0],
|
|
74
|
+
hint: `Fix the recipe settings, then run dss recipe update-schema ${recipeName}.`,
|
|
75
|
+
});
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
33
79
|
function formatLineDiff(remoteName, localPath, remoteContent, localContent) {
|
|
34
80
|
// Line-ending differences are not content differences: compare and split on
|
|
35
81
|
// CRLF-normalized text, mirroring assert-unchanged's normalized payload hash.
|
|
@@ -112,10 +158,23 @@ export function recipeCreateOptionsFromFlags(f) {
|
|
|
112
158
|
...(fuzzyDistance ? { fuzzyDistance, } : {}),
|
|
113
159
|
...(fuzzyThreshold !== undefined ? { fuzzyThreshold, } : {}),
|
|
114
160
|
fuzzyNormalize: f["normalize"] === true,
|
|
161
|
+
...csvOption("groupBy", f["group-by"]),
|
|
162
|
+
...csvOption("aggregate", f["aggregate"]),
|
|
163
|
+
...(typeof f["order-by"] === "string" ? { orderBy: f["order-by"], } : {}),
|
|
164
|
+
...csvOption("rename", f["rename"]),
|
|
165
|
+
...csvOption("fillEmpty", f["fill-empty"]),
|
|
166
|
+
...(typeof f["formula"] === "string" ? { formula: f["formula"], } : {}),
|
|
167
|
+
...(typeof f["filter"] === "string" ? { filter: f["filter"], } : {}),
|
|
168
|
+
...csvOption("dropColumns", f["drop-columns"]),
|
|
169
|
+
...csvOption("keepColumns", f["keep-columns"]),
|
|
115
170
|
projectKey: pk,
|
|
116
171
|
};
|
|
117
172
|
return payload;
|
|
118
173
|
}
|
|
174
|
+
function csvOption(key, value) {
|
|
175
|
+
const items = splitCsvFlag(value);
|
|
176
|
+
return items.length > 0 ? { [key]: items, } : {};
|
|
177
|
+
}
|
|
119
178
|
export const recipeCommands = withUsage("recipe", {
|
|
120
179
|
list: {
|
|
121
180
|
handler: (c, _a, f) => c.recipes.list(f["project-key"]),
|
|
@@ -310,13 +369,21 @@ export const recipeCommands = withUsage("recipe", {
|
|
|
310
369
|
objectId: createdName,
|
|
311
370
|
objectType: "RECIPE",
|
|
312
371
|
},], pk);
|
|
372
|
+
if (created.outputSchemaUpdateError) {
|
|
373
|
+
enqueueCliWarning({
|
|
374
|
+
code: "recipe_output_schema_not_computed",
|
|
375
|
+
recipe: createdName,
|
|
376
|
+
error: created.outputSchemaUpdateError,
|
|
377
|
+
hint: `Fix the recipe settings, then run dss recipe update-schema ${createdName}.`,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
313
380
|
return { created: createdName, resource: "recipe", ...created, ...moved, };
|
|
314
381
|
},
|
|
315
|
-
description: "Create a recipe with optional inputs and a dataset or managed-folder output.",
|
|
382
|
+
description: "Create a recipe with optional inputs and a dataset or managed-folder output. Missing outputs are created on --output-connection as DSS managed datasets. Join, grouping (--group-by/--aggregate) and prepare (--rename/--formula/--filter/...) payloads come from flags. Visual recipe outputs get the DSS-computed schema (outputSchemaUpdated).",
|
|
316
383
|
examples: [
|
|
317
384
|
"dss recipe create --type python --input raw_orders,lookup --output orders_clean",
|
|
318
|
-
"dss recipe create --type
|
|
319
|
-
"dss recipe create --type
|
|
385
|
+
"dss recipe create --type grouping --input orders --output orders_by_cat --group-by category --aggregate amount:sum+avg,name:first --order-by day",
|
|
386
|
+
"dss recipe create --type prepare --input orders --output orders_prep --rename name=label --formula 'total=amount * 2' --filter 'amount > 0'",
|
|
320
387
|
],
|
|
321
388
|
},
|
|
322
389
|
clone: {
|
|
@@ -586,22 +653,41 @@ export const recipeCommands = withUsage("recipe", {
|
|
|
586
653
|
ensureRecipeBackupDir(backupDir);
|
|
587
654
|
writeRecipeBackup(backupPath, `${JSON.stringify(recipeBackupDocument(a[0], pk, current), null, 2)}\n`);
|
|
588
655
|
}
|
|
589
|
-
await c.recipes.replace(a[0], { ...current, payload: content, }, pk);
|
|
656
|
+
const schema = await writeKeepingDerivedOutputSchemas(c, a[0], current.recipe.type, pk, () => c.recipes.replace(a[0], { ...current, payload: content, }, pk));
|
|
590
657
|
return {
|
|
591
658
|
updated: a[0],
|
|
592
659
|
resource: "recipe",
|
|
593
660
|
file: filePath,
|
|
594
661
|
backupCreated: backupPath !== undefined,
|
|
595
662
|
...(backupPath ? { backupPath, } : {}),
|
|
663
|
+
...schema,
|
|
596
664
|
};
|
|
597
665
|
},
|
|
598
|
-
description: "Upload recipe code from a local file, backing up payload, graph, settings, and version metadata by default.",
|
|
666
|
+
description: "Upload recipe code from a local file, backing up payload, graph, settings, and version metadata by default. For visual and SQL query recipes, outputs whose schema was empty or matched the DSS-computed one before the upload get the newly computed schema (outputSchemaUpdated); hand-edited output schemas are kept and reported in a recipe_output_schema_outdated warning.",
|
|
599
667
|
examples: [
|
|
600
668
|
"dss recipe set-payload compute_orders --file code.py --dry-run",
|
|
601
669
|
"dss recipe set-payload compute_orders --file code.py --backup-dir ./backups",
|
|
602
670
|
"dss recipe set-payload compute_orders --file code.py --no-backup",
|
|
603
671
|
],
|
|
604
672
|
},
|
|
673
|
+
"update-schema": {
|
|
674
|
+
handler: async (c, a, f) => {
|
|
675
|
+
requireArgs(a, 1, commandUsage("recipe", "update-schema"));
|
|
676
|
+
const dryRun = executionMode(f).dryRun;
|
|
677
|
+
const result = await c.recipes.updateSchema(a[0], {
|
|
678
|
+
projectKey: f["project-key"],
|
|
679
|
+
dryRun,
|
|
680
|
+
});
|
|
681
|
+
return dryRun
|
|
682
|
+
? { dryRun: true, action: "update-schema", resource: "recipe", name: a[0], ...result, }
|
|
683
|
+
: result;
|
|
684
|
+
},
|
|
685
|
+
description: "Propagate schema changes: write the output schemas DSS computes from a visual or SQL query recipe (the UI's Update schema; dataikuapi compute_schema_updates().apply()) to every output whose schema differs. --dry-run lists them under pending. Code recipes are rejected: their code sets the schema when it runs.",
|
|
686
|
+
examples: [
|
|
687
|
+
"dss recipe update-schema compute_orders_joined --dry-run",
|
|
688
|
+
"dss recipe update-schema compute_orders_joined",
|
|
689
|
+
],
|
|
690
|
+
},
|
|
605
691
|
restore: {
|
|
606
692
|
handler: async (c, a, f) => {
|
|
607
693
|
const usage = commandUsage("recipe", "restore");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CommandMeta } from "../types.js";
|
|
2
2
|
/**
|
|
3
|
-
* Mutating actions accept --plan (buildMutationPlan in
|
|
3
|
+
* Mutating actions accept --plan (buildMutationPlan in plans.ts owns the
|
|
4
4
|
* --plan path centrally); the handlers below keep --dry-run support with a
|
|
5
5
|
* zero-request planned payload, mirroring set-active/delete.
|
|
6
6
|
*/
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { unexpectedResponseError, } from "../../errors.js";
|
|
2
|
-
import { writeResponseToFile, } from "../../utils/response-file.js";
|
|
3
1
|
import { json, jsonInput, parseBooleanOption, requiredJsonInput, } from "../coerce.js";
|
|
4
2
|
import { executionMode, } from "../flags.js";
|
|
3
|
+
import { trainedModelCommands, } from "../helpers/trained-model.js";
|
|
5
4
|
import { readIfExists, skipResult, } from "../output.js";
|
|
6
5
|
import { commandUsage, withUsage, } from "../syntax.js";
|
|
7
6
|
import { requireArgs, UsageError, } from "../usage.js";
|
|
8
7
|
/**
|
|
9
|
-
* Mutating actions accept --plan (buildMutationPlan in
|
|
8
|
+
* Mutating actions accept --plan (buildMutationPlan in plans.ts owns the
|
|
10
9
|
* --plan path centrally); the handlers below keep --dry-run support with a
|
|
11
10
|
* zero-request planned payload, mirroring set-active/delete.
|
|
12
11
|
*/
|
|
@@ -361,79 +360,13 @@ export const savedModelCommands = withUsage("saved-model", {
|
|
|
361
360
|
"dss saved-model evaluate-version MODEL_ID VERSION_ID --dataset ds --skip-expensive-reports true --project-key PROJECT",
|
|
362
361
|
],
|
|
363
362
|
},
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
const fullClassName = f["full-class-name"];
|
|
372
|
-
const jarOptions = {
|
|
373
|
-
...(fullClassName !== undefined ? { fullClassName, } : {}),
|
|
374
|
-
...(f["include-libs"] !== undefined
|
|
375
|
-
? { includeLibs: parseBooleanOption(f["include-libs"], "--include-libs"), }
|
|
376
|
-
: {}),
|
|
377
|
-
};
|
|
378
|
-
const res = await c.savedModels.downloadScoringJar(jarOptions, a[0], a[1], f["project-key"]);
|
|
379
|
-
if (!res.body) {
|
|
380
|
-
throw unexpectedResponseError("savedModels.downloadScoringJar response did not include a body");
|
|
381
|
-
}
|
|
382
|
-
const bytes = await writeResponseToFile(out, res);
|
|
383
|
-
return { path: out, bytes, };
|
|
384
|
-
},
|
|
385
|
-
description: "Download the optimized scoring JAR of a version (license-gated server side). --full-class-name forwards the documented fullClassName query parameter; --include-libs toggles including scoring libraries.",
|
|
386
|
-
examples: [
|
|
387
|
-
"dss saved-model download-scoring-jar MODEL_ID VERSION_ID --output ./scoring.jar --project-key PROJECT",
|
|
388
|
-
"dss saved-model download-scoring-jar MODEL_ID VERSION_ID --output ./scoring.jar --full-class-name model.Model --include-libs false --project-key PROJECT",
|
|
389
|
-
],
|
|
390
|
-
},
|
|
391
|
-
"download-scoring-pmml": {
|
|
392
|
-
handler: async (c, a, f) => {
|
|
393
|
-
requireArgs(a, 2, commandUsage("saved-model", "download-scoring-pmml"));
|
|
394
|
-
const out = f["output"];
|
|
395
|
-
if (!out)
|
|
396
|
-
throw new UsageError("--output PATH is required.", "missing_required_flag");
|
|
397
|
-
const res = await c.savedModels.downloadScoringPmml(a[0], a[1], f["project-key"]);
|
|
398
|
-
if (!res.body) {
|
|
399
|
-
throw unexpectedResponseError("savedModels.downloadScoringPmml response did not include a body");
|
|
400
|
-
}
|
|
401
|
-
const bytes = await writeResponseToFile(out, res);
|
|
402
|
-
return { path: out, bytes, };
|
|
403
|
-
},
|
|
404
|
-
description: "Download the PMML scoring file of a version (license-gated server side).",
|
|
405
|
-
examples: [
|
|
406
|
-
"dss saved-model download-scoring-pmml MODEL_ID VERSION_ID --output ./model.pmml --project-key PROJECT",
|
|
407
|
-
],
|
|
408
|
-
},
|
|
409
|
-
"set-user-meta": {
|
|
410
|
-
handler: async (c, a, f) => {
|
|
411
|
-
const usage = commandUsage("saved-model", "set-user-meta");
|
|
412
|
-
requireArgs(a, 2, usage);
|
|
413
|
-
const userMeta = requiredJsonInput(f, "User-meta JSON is required via --data, --data-file, or --stdin.");
|
|
414
|
-
const projectKey = f["project-key"];
|
|
415
|
-
if (executionMode(f).dryRun) {
|
|
416
|
-
return {
|
|
417
|
-
dryRun: true,
|
|
418
|
-
action: "set-user-meta",
|
|
419
|
-
resource: "saved-model",
|
|
420
|
-
id: a[0],
|
|
421
|
-
versionId: a[1],
|
|
422
|
-
projectKey,
|
|
423
|
-
payload: userMeta,
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
return c.savedModels.setUserMeta(a[0], a[1], userMeta, projectKey).then(() => ({
|
|
427
|
-
updated: a[0],
|
|
428
|
-
versionId: a[1],
|
|
429
|
-
resource: "saved-model",
|
|
430
|
-
}));
|
|
431
|
-
},
|
|
432
|
-
description: 'Update the user metadata of a model version. Send only the "userMeta" field of a previously-retrieved version-details object.',
|
|
433
|
-
examples: [
|
|
434
|
-
'dss saved-model set-user-meta MODEL_ID VERSION_ID --data \'{"name":"Churn model","description":"v2"}\' --project-key PROJECT',
|
|
435
|
-
],
|
|
436
|
-
},
|
|
363
|
+
...trainedModelCommands({
|
|
364
|
+
resource: "saved-model",
|
|
365
|
+
ids: "MODEL_ID VERSION_ID",
|
|
366
|
+
noun: "saved-model version",
|
|
367
|
+
model: (c, a, pk) => c.savedModels.version(a[0], a[1], pk),
|
|
368
|
+
downloadDocumentation: (c, exportId, pk) => c.savedModels.downloadDocumentation(exportId, pk),
|
|
369
|
+
}),
|
|
437
370
|
});
|
|
438
371
|
function mlflowImportOptions(f) {
|
|
439
372
|
const codeEnvName = f["code-env"];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsonInput, requiredJsonInput, } from "../coerce.js";
|
|
2
2
|
import { commandUsage, withUsage, } from "../syntax.js";
|
|
3
|
-
import { requireArgs, } from "../usage.js";
|
|
3
|
+
import { requireArgs, UsageError, } from "../usage.js";
|
|
4
4
|
export const streamingEndpointCommands = withUsage("streaming-endpoint", {
|
|
5
5
|
list: {
|
|
6
6
|
handler: (c, _a, f) => c.streamingEndpoints.list(f["project-key"]),
|
|
@@ -43,4 +43,33 @@ export const streamingEndpointCommands = withUsage("streaming-endpoint", {
|
|
|
43
43
|
description: "Delete a streaming endpoint.",
|
|
44
44
|
examples: ["dss streaming-endpoint delete my-stream",],
|
|
45
45
|
},
|
|
46
|
+
"create-managed": {
|
|
47
|
+
handler: async (c, a, f) => {
|
|
48
|
+
const connectionId = f["connection"];
|
|
49
|
+
if (typeof connectionId !== "string") {
|
|
50
|
+
throw new UsageError("--connection CONN is required.", "missing_required_flag");
|
|
51
|
+
}
|
|
52
|
+
const formatOptionId = f["format-option"];
|
|
53
|
+
await c.streamingEndpoints.createManaged(a[0], {
|
|
54
|
+
connectionId,
|
|
55
|
+
...(typeof formatOptionId === "string" ? { formatOptionId, } : {}),
|
|
56
|
+
}, f["project-key"]);
|
|
57
|
+
return { created: a[0], resource: "streaming-endpoint", };
|
|
58
|
+
},
|
|
59
|
+
description: "Create a managed streaming endpoint on a connection; DSS picks type and params from the connection (--format-option for the message format).",
|
|
60
|
+
examples: ["dss streaming-endpoint create-managed orders_stream --connection kafka_main",],
|
|
61
|
+
},
|
|
62
|
+
schema: {
|
|
63
|
+
handler: (c, a, f) => c.streamingEndpoints.getSchema(a[0], f["project-key"]),
|
|
64
|
+
description: "Get a streaming endpoint's schema ({columns: [{name, type}]}).",
|
|
65
|
+
examples: ["dss streaming-endpoint schema orders_stream",],
|
|
66
|
+
},
|
|
67
|
+
"set-schema": {
|
|
68
|
+
handler: async (c, a, f) => {
|
|
69
|
+
await c.streamingEndpoints.setSchema(a[0], requiredJsonInput(f, '--data, --data-file, or --stdin is required ({"columns": [...]}).'), f["project-key"]);
|
|
70
|
+
return { updated: a[0], resource: "streaming-endpoint", };
|
|
71
|
+
},
|
|
72
|
+
description: "Replace a streaming endpoint's schema with an object from the schema action, edited.",
|
|
73
|
+
examples: ["dss streaming-endpoint set-schema orders_stream --data-file schema.json",],
|
|
74
|
+
},
|
|
46
75
|
});
|
|
@@ -113,4 +113,12 @@ export const webappCommands = withUsage("webapp", {
|
|
|
113
113
|
description: "Get a webapp backend's runtime state.",
|
|
114
114
|
examples: ["dss webapp backend-state WEBAPP_ID",],
|
|
115
115
|
},
|
|
116
|
+
trust: {
|
|
117
|
+
handler: (c, a, f) => c.webapps.trust(a[0], {
|
|
118
|
+
projectKey: f["project-key"],
|
|
119
|
+
...(f["for-everybody"] === true ? { trustForEverybody: true, } : {}),
|
|
120
|
+
}),
|
|
121
|
+
description: "Trust a webapp's code so it can run for you, or for every user with --for-everybody (admin). Returns canAccess and trustedCodeStatus.",
|
|
122
|
+
examples: ["dss webapp trust VCMN2ra", "dss webapp trust VCMN2ra --for-everybody",],
|
|
123
|
+
},
|
|
116
124
|
});
|