dataiku-sdk 3.7.0 → 3.9.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 +4 -2
- package/dist/build-metadata.json +1 -1
- package/dist/packages/types/src/index.d.ts +40 -4
- package/dist/packages/types/src/index.js +22 -1
- package/dist/src/cli/coerce.d.ts +1 -0
- package/dist/src/cli/coerce.js +1 -1
- package/dist/src/cli/command-syntax.json +156 -0
- package/dist/src/cli/commands/dataset.js +44 -8
- package/dist/src/cli/commands/flow-zone.js +241 -46
- package/dist/src/cli/commands/job.js +52 -9
- package/dist/src/cli/commands/project.js +4 -3
- package/dist/src/cli/commands/recipe.d.ts +4 -0
- package/dist/src/cli/commands/recipe.js +38 -1
- package/dist/src/cli/commands/wiki.js +56 -0
- package/dist/src/cli/contract.js +13 -8
- package/dist/src/cli/doctor.js +2 -0
- package/dist/src/cli/flags.d.ts +7 -0
- package/dist/src/cli/flags.js +28 -2
- package/dist/src/cli/helpers/dataset.d.ts +12 -0
- package/dist/src/cli/helpers/dataset.js +36 -0
- package/dist/src/cli/helpers/flow-zone.d.ts +21 -0
- package/dist/src/cli/helpers/flow-zone.js +144 -4
- package/dist/src/cli/output-schemas.js +27 -3
- package/dist/src/cli/output.js +6 -0
- package/dist/src/cli/plans.js +58 -2
- package/dist/src/cli/project-map-output.d.ts +24 -0
- package/dist/src/cli/project-map-output.js +21 -0
- package/dist/src/cli/read-shapes.d.ts +14 -0
- package/dist/src/cli/read-shapes.js +114 -0
- package/dist/src/cli/result-shapes.d.ts +6 -0
- package/dist/src/cli/result-shapes.js +235 -0
- package/dist/src/cli/types.d.ts +2 -0
- package/dist/src/cli/version.d.ts +2 -2
- package/dist/src/cli/version.js +2 -2
- package/dist/src/cli.js +23 -20
- package/dist/src/errors.d.ts +11 -1
- package/dist/src/errors.js +18 -3
- package/dist/src/generated/action-output-schemas.json +224 -35
- package/dist/src/resources/dataset-create.d.ts +19 -0
- package/dist/src/resources/dataset-create.js +69 -0
- package/dist/src/resources/datasets.d.ts +21 -0
- package/dist/src/resources/datasets.js +61 -1
- package/dist/src/resources/flow-zones.d.ts +29 -3
- package/dist/src/resources/flow-zones.js +53 -3
- package/dist/src/resources/jobs.d.ts +36 -1
- package/dist/src/resources/jobs.js +111 -5
- package/dist/src/resources/projects.d.ts +9 -0
- package/dist/src/resources/projects.js +10 -3
- package/dist/src/resources/recipe-create.d.ts +17 -3
- package/dist/src/resources/recipe-create.js +149 -33
- package/dist/src/resources/recipes.js +76 -23
- package/dist/src/resources/sql.js +52 -13
- package/dist/src/resources/wiki.d.ts +47 -1
- package/dist/src/resources/wiki.js +89 -0
- package/dist/src/utils/flow-analysis.js +4 -0
- package/dist/src/utils/secret-sanitize.d.ts +11 -2
- package/dist/src/utils/secret-sanitize.js +23 -6
- package/package.json +4 -4
- package/plugin.json +1 -1
- package/skills/dataiku-dss/references/discovery.md +2 -2
- package/skills/dataiku-dss/references/flow-maps.md +2 -2
- package/skills/dataiku-dss/references/troubleshooting.md +3 -3
package/dist/src/cli/plans.js
CHANGED
|
@@ -16,11 +16,12 @@ import { schemaPropagationOptionsFromFlags, } from "./commands/flow.js";
|
|
|
16
16
|
import { mlTaskFieldsFromFlags, mlTaskReguessOptionsFromFlags, } from "./commands/ml-task.js";
|
|
17
17
|
import { deployRunOptionsFromFlags, experimentsDatasetOptionsFromFlags, inferenceInfoFromFlags, } from "./commands/mlflow.js";
|
|
18
18
|
import { projectLibraryPutPayload, } from "./commands/project-library.js";
|
|
19
|
-
import { recipeCreateOptionsFromFlags, } from "./commands/recipe.js";
|
|
19
|
+
import { enqueueRecipeCreateWarnings, recipeCreateOptionsFromFlags, } from "./commands/recipe.js";
|
|
20
20
|
import { resolveSqlQueryInvocation, } from "./commands/sql.js";
|
|
21
21
|
import { buildRegistryEntry, splitPackageSpec, } from "./contract.js";
|
|
22
22
|
import { ambientProjectKey, } from "./env.js";
|
|
23
23
|
import { executionMode, } from "./flags.js";
|
|
24
|
+
import { datasetSqlSourceFromFlags, } from "./helpers/dataset.js";
|
|
24
25
|
import { flowZoneColor, flowZoneMoveItems, flowZoneName, } from "./helpers/flow-zone.js";
|
|
25
26
|
import { recipeBackupPath, recipeRunShouldWait, } from "./helpers/recipe.js";
|
|
26
27
|
import { diagnosticsComputationFromFlags, } from "./helpers/trained-model.js";
|
|
@@ -419,6 +420,50 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
419
420
|
endpoint: projectEndpoint(`/wiki/${encodeURIComponent(id)}`),
|
|
420
421
|
identifiers: { article: id, },
|
|
421
422
|
};
|
|
423
|
+
case "wiki.attach": {
|
|
424
|
+
const articleEndpoint = projectEndpoint(`/wiki/${encodeURIComponent(id)}`);
|
|
425
|
+
const upload = {
|
|
426
|
+
method: "POST",
|
|
427
|
+
endpoint: `${articleEndpoint}/upload`,
|
|
428
|
+
payload: uploadPayload(args[1]),
|
|
429
|
+
};
|
|
430
|
+
return {
|
|
431
|
+
...upload,
|
|
432
|
+
identifiers: { article: id, localPath: args[1], },
|
|
433
|
+
requests: [
|
|
434
|
+
{
|
|
435
|
+
sequence: 1,
|
|
436
|
+
method: "GET",
|
|
437
|
+
endpoint: articleEndpoint,
|
|
438
|
+
purpose: "read current attachments",
|
|
439
|
+
},
|
|
440
|
+
{ sequence: 2, ...upload, },
|
|
441
|
+
{
|
|
442
|
+
sequence: 3,
|
|
443
|
+
method: "GET",
|
|
444
|
+
endpoint: articleEndpoint,
|
|
445
|
+
assert: { newAttachments: 1, },
|
|
446
|
+
},
|
|
447
|
+
],
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
case "wiki.detach": {
|
|
451
|
+
const articleEndpoint = projectEndpoint(`/wiki/${encodeURIComponent(id)}`);
|
|
452
|
+
return {
|
|
453
|
+
method: "PUT",
|
|
454
|
+
endpoint: articleEndpoint,
|
|
455
|
+
identifiers: { article: id, smartId: args[1], },
|
|
456
|
+
requests: [
|
|
457
|
+
{ sequence: 1, method: "GET", endpoint: articleEndpoint, },
|
|
458
|
+
{
|
|
459
|
+
sequence: 2,
|
|
460
|
+
method: "PUT",
|
|
461
|
+
endpoint: articleEndpoint,
|
|
462
|
+
payload: "<article data without the attachment with the given smartId>",
|
|
463
|
+
},
|
|
464
|
+
],
|
|
465
|
+
};
|
|
466
|
+
}
|
|
422
467
|
case "dashboard.create": {
|
|
423
468
|
const data = jsonInput(flags);
|
|
424
469
|
const flagName = flags["name"];
|
|
@@ -730,8 +775,16 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
730
775
|
if (!connection && dsType.toLowerCase() !== "uploadedfiles") {
|
|
731
776
|
throw new UsageError("--connection is required unless --type is UploadedFiles.");
|
|
732
777
|
}
|
|
778
|
+
const sqlSource = datasetSqlSourceFromFlags(flags, dsType);
|
|
779
|
+
const hasSqlSource = sqlSource.table !== undefined || sqlSource.query !== undefined;
|
|
733
780
|
const endpoint = projectEndpoint("/datasets/"); // throws without a project key
|
|
734
781
|
return {
|
|
782
|
+
...(hasSqlSource
|
|
783
|
+
? {
|
|
784
|
+
exact: false,
|
|
785
|
+
reason: "The POST is exact; apply then detects the schema (POST /actions/testAndDetectSettings/externalSQL) and stores it (PUT /schema).",
|
|
786
|
+
}
|
|
787
|
+
: {}),
|
|
735
788
|
method: "POST",
|
|
736
789
|
endpoint,
|
|
737
790
|
identifiers: { name, },
|
|
@@ -740,6 +793,7 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
740
793
|
datasetName: name,
|
|
741
794
|
connection,
|
|
742
795
|
dsType,
|
|
796
|
+
...sqlSource,
|
|
743
797
|
}),
|
|
744
798
|
};
|
|
745
799
|
}
|
|
@@ -924,7 +978,9 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
924
978
|
}
|
|
925
979
|
const endpoint = projectEndpoint("/recipes/"); // throws without a project key
|
|
926
980
|
// Same flag mapping and body construction as the handler and RecipesResource.create.
|
|
927
|
-
const
|
|
981
|
+
const createOptions = recipeCreateOptionsFromFlags(flags);
|
|
982
|
+
enqueueRecipeCreateWarnings(createOptions);
|
|
983
|
+
const { recipePrototype, creationSettings, grouping, prepareSteps, } = buildRecipeCreateRequest(createOptions, projectKey);
|
|
928
984
|
const edits = grouping
|
|
929
985
|
? { grouping, }
|
|
930
986
|
: prepareSteps.length > 0
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { FlowMapResult } from "../resources/projects.js";
|
|
2
|
+
import type { AnalyzedFlowMap, AnalyzedFlowNode, FlowMapComponent, FlowMapZone } from "../utils/flow-analysis.js";
|
|
3
|
+
/**
|
|
4
|
+
* `dss project map` output: the SDK `FlowMapResult` with derivable duplicates
|
|
5
|
+
* removed at the CLI boundary. Lossless — every dropped field can be rebuilt:
|
|
6
|
+
* node `name` defaults to `id`, `zoneName` comes from `zones[]`, zone/component
|
|
7
|
+
* membership comes from each node's `zoneId`/`componentId`, an absent
|
|
8
|
+
* `warnings` means none, and an absent `truncation` means nothing was cut.
|
|
9
|
+
* `topologyFingerprint` is passed through untouched.
|
|
10
|
+
*/
|
|
11
|
+
export type CompactFlowMapNode = Omit<AnalyzedFlowNode, "zoneName">;
|
|
12
|
+
export type CompactFlowMapZone = Omit<FlowMapZone, "nodeIds">;
|
|
13
|
+
export type CompactFlowMapComponent = Omit<FlowMapComponent, "nodeIds">;
|
|
14
|
+
export interface CompactFlowMap extends Omit<AnalyzedFlowMap, "nodes" | "zones" | "components" | "warnings"> {
|
|
15
|
+
nodes: CompactFlowMapNode[];
|
|
16
|
+
zones: CompactFlowMapZone[];
|
|
17
|
+
components: CompactFlowMapComponent[];
|
|
18
|
+
warnings?: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface CompactFlowMapResult extends Omit<FlowMapResult, "map" | "truncation"> {
|
|
21
|
+
map: CompactFlowMap;
|
|
22
|
+
truncation?: FlowMapResult["truncation"];
|
|
23
|
+
}
|
|
24
|
+
export declare function compactProjectMapOutput(result: FlowMapResult): CompactFlowMapResult;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function compactNode(node) {
|
|
2
|
+
const { zoneName: _zoneName, name, ...rest } = node;
|
|
3
|
+
return name === undefined || name === node.id ? rest : { ...rest, name, };
|
|
4
|
+
}
|
|
5
|
+
export function compactProjectMapOutput(result) {
|
|
6
|
+
const { nodes, zones, components, warnings, ...mapRest } = result.map;
|
|
7
|
+
const map = {
|
|
8
|
+
...mapRest,
|
|
9
|
+
nodes: nodes.map(compactNode),
|
|
10
|
+
zones: zones.map(({ nodeIds: _nodeIds, ...zone }) => zone),
|
|
11
|
+
components: components.map(({ nodeIds: _nodeIds, ...component }) => component),
|
|
12
|
+
};
|
|
13
|
+
if (warnings.length > 0)
|
|
14
|
+
map.warnings = warnings;
|
|
15
|
+
const { map: _map, truncation, ...resultRest } = result;
|
|
16
|
+
return {
|
|
17
|
+
map,
|
|
18
|
+
...(truncation.truncated ? { truncation, } : {}),
|
|
19
|
+
...resultRest,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain data shared by the compact read shapers (src/cli/result-shapes.ts) and
|
|
3
|
+
* the discovery output schemas (src/cli/output-schemas.ts), so the advertised
|
|
4
|
+
* schema is the emitted shape. Imports nothing: the schema generator loads it
|
|
5
|
+
* without the CLI runtime.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Settings-object noise `dataset get` / `project get` drop: metrics and check
|
|
9
|
+
* configuration, version stamps and checklists that agents never edit.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DATASET_GET_DROPPED_KEYS: readonly ["metrics", "metricsChecks", "versionTag", "creationTag", "checklists"];
|
|
12
|
+
export declare const PROJECT_GET_DROPPED_KEYS: readonly ["metrics", "metricsChecks", "versionTag", "creationTag", "checklists", "objectImgHash", "isProjectImg", "defaultImgColor", "imgPattern"];
|
|
13
|
+
/** Discovery output schemas of the `job get` and `dataset info` compact defaults. */
|
|
14
|
+
export declare function compactReadOutputSchemas(): Record<string, Record<string, unknown>>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain data shared by the compact read shapers (src/cli/result-shapes.ts) and
|
|
3
|
+
* the discovery output schemas (src/cli/output-schemas.ts), so the advertised
|
|
4
|
+
* schema is the emitted shape. Imports nothing: the schema generator loads it
|
|
5
|
+
* without the CLI runtime.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Settings-object noise `dataset get` / `project get` drop: metrics and check
|
|
9
|
+
* configuration, version stamps and checklists that agents never edit.
|
|
10
|
+
*/
|
|
11
|
+
export const DATASET_GET_DROPPED_KEYS = [
|
|
12
|
+
"metrics",
|
|
13
|
+
"metricsChecks",
|
|
14
|
+
"versionTag",
|
|
15
|
+
"creationTag",
|
|
16
|
+
"checklists",
|
|
17
|
+
];
|
|
18
|
+
export const PROJECT_GET_DROPPED_KEYS = [
|
|
19
|
+
...DATASET_GET_DROPPED_KEYS,
|
|
20
|
+
"objectImgHash",
|
|
21
|
+
"isProjectImg",
|
|
22
|
+
"defaultImgColor",
|
|
23
|
+
"imgPattern",
|
|
24
|
+
];
|
|
25
|
+
const STRING = { type: "string", };
|
|
26
|
+
const NUMBER = { type: "number", };
|
|
27
|
+
const BOOLEAN = { type: "boolean", };
|
|
28
|
+
/** Discovery output schemas of the `job get` and `dataset info` compact defaults. */
|
|
29
|
+
export function compactReadOutputSchemas() {
|
|
30
|
+
const errorSchema = {
|
|
31
|
+
type: "object",
|
|
32
|
+
additionalProperties: false,
|
|
33
|
+
properties: { type: STRING, message: STRING, },
|
|
34
|
+
};
|
|
35
|
+
return {
|
|
36
|
+
"job.get": {
|
|
37
|
+
type: "object",
|
|
38
|
+
additionalProperties: false,
|
|
39
|
+
required: ["id", "state",],
|
|
40
|
+
properties: {
|
|
41
|
+
id: STRING,
|
|
42
|
+
name: STRING,
|
|
43
|
+
type: STRING,
|
|
44
|
+
state: STRING,
|
|
45
|
+
initiator: STRING,
|
|
46
|
+
triggeredFrom: STRING,
|
|
47
|
+
startTime: NUMBER,
|
|
48
|
+
endTime: NUMBER,
|
|
49
|
+
outputs: {
|
|
50
|
+
type: "array",
|
|
51
|
+
items: {
|
|
52
|
+
type: "object",
|
|
53
|
+
additionalProperties: false,
|
|
54
|
+
properties: { type: STRING, id: STRING, projectKey: STRING, partition: STRING, },
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
progress: { type: "object", additionalProperties: NUMBER, },
|
|
58
|
+
error: errorSchema,
|
|
59
|
+
activities: {
|
|
60
|
+
type: "array",
|
|
61
|
+
items: {
|
|
62
|
+
type: "object",
|
|
63
|
+
additionalProperties: false,
|
|
64
|
+
properties: {
|
|
65
|
+
id: STRING,
|
|
66
|
+
recipe: STRING,
|
|
67
|
+
recipeType: STRING,
|
|
68
|
+
state: STRING,
|
|
69
|
+
totalTime: NUMBER,
|
|
70
|
+
warnings: NUMBER,
|
|
71
|
+
error: errorSchema,
|
|
72
|
+
message: STRING,
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
"dataset.info": {
|
|
79
|
+
type: "object",
|
|
80
|
+
additionalProperties: false,
|
|
81
|
+
required: ["name",],
|
|
82
|
+
properties: {
|
|
83
|
+
name: STRING,
|
|
84
|
+
type: STRING,
|
|
85
|
+
managed: BOOLEAN,
|
|
86
|
+
connection: STRING,
|
|
87
|
+
formatType: STRING,
|
|
88
|
+
partitioned: BOOLEAN,
|
|
89
|
+
schema: {
|
|
90
|
+
type: "array",
|
|
91
|
+
items: {
|
|
92
|
+
type: "object",
|
|
93
|
+
additionalProperties: false,
|
|
94
|
+
required: ["name", "type",],
|
|
95
|
+
properties: { name: STRING, type: STRING, meaning: STRING, comment: STRING, },
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
recipes: { type: "array", items: STRING, },
|
|
99
|
+
buildable: BOOLEAN,
|
|
100
|
+
upstreamBuildable: BOOLEAN,
|
|
101
|
+
downstreamBuildable: BOOLEAN,
|
|
102
|
+
tags: { type: "array", items: STRING, },
|
|
103
|
+
dataQuality: { type: "object", additionalProperties: true, },
|
|
104
|
+
lastBuild: {
|
|
105
|
+
type: "object",
|
|
106
|
+
additionalProperties: false,
|
|
107
|
+
properties: { jobId: STRING, success: BOOLEAN, startTime: NUMBER, endTime: NUMBER, },
|
|
108
|
+
},
|
|
109
|
+
lastModifiedOn: NUMBER,
|
|
110
|
+
lastModifiedBy: STRING,
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compact a command result for agents: `*.list` items (filter, cap, compact
|
|
3
|
+
* fields) and the four large read commands. `--full` and `--fields` bypass
|
|
4
|
+
* the read shapers so the DSS object (or a projection of it) is returned.
|
|
5
|
+
*/
|
|
6
|
+
export declare function shapeCommandResult(resource: string, action: string, result: unknown, flags: Record<string, string | boolean>): unknown;
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compact default results of the four large read commands (`job get`,
|
|
3
|
+
* `dataset info`, `dataset get`, `project get`), plus the single dispatch
|
|
4
|
+
* point for compacting command results (`shapeCommandResult`).
|
|
5
|
+
*
|
|
6
|
+
* The SDK resources keep returning the raw DSS objects; only the CLI compacts.
|
|
7
|
+
* `--full` returns the DSS object unchanged, and `--fields` projects DSS paths
|
|
8
|
+
* out of it (exactly like the compact `*.list` shapes in list-output.ts).
|
|
9
|
+
*
|
|
10
|
+
* Imports no schema graph: the discovery schemas below are plain data.
|
|
11
|
+
*/
|
|
12
|
+
import { isRecord, } from "../utils/records.js";
|
|
13
|
+
import { shapeListResult, } from "./list-output.js";
|
|
14
|
+
import { DATASET_GET_DROPPED_KEYS, PROJECT_GET_DROPPED_KEYS, } from "./read-shapes.js";
|
|
15
|
+
function record(value) {
|
|
16
|
+
return isRecord(value) ? value : {};
|
|
17
|
+
}
|
|
18
|
+
function nonEmptyString(value) {
|
|
19
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
20
|
+
}
|
|
21
|
+
/** Drop `undefined` members so absent optional fields are omitted, never null. */
|
|
22
|
+
function defined(fields) {
|
|
23
|
+
return Object.fromEntries(Object.entries(fields).filter(([, value,]) => value !== undefined));
|
|
24
|
+
}
|
|
25
|
+
/** `{ type, message }` of a DSS error object (`error`, `firstFailure`); undefined when empty. */
|
|
26
|
+
function errorSummary(value) {
|
|
27
|
+
if (!isRecord(value))
|
|
28
|
+
return undefined;
|
|
29
|
+
const shaped = defined({
|
|
30
|
+
type: nonEmptyString(value["errorType"]),
|
|
31
|
+
message: nonEmptyString(value["detailedMessage"]) ?? nonEmptyString(value["message"]),
|
|
32
|
+
});
|
|
33
|
+
return Object.keys(shaped).length > 0 ? shaped : undefined;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Output id/project of a job output across DSS shapes: `targetDataset` +
|
|
37
|
+
* `targetDatasetProjectKey`, `targetManagedFolder`, `targetSavedModel`, ...
|
|
38
|
+
* and the plain `{ id, projectKey }` form.
|
|
39
|
+
*/
|
|
40
|
+
function outputTarget(output) {
|
|
41
|
+
const targetKey = Object.keys(output).find((key) => /^target[A-Z]/.test(key) && !key.endsWith("ProjectKey") && key !== "targetPartition"
|
|
42
|
+
&& typeof output[key] === "string");
|
|
43
|
+
return {
|
|
44
|
+
id: targetKey === undefined ? output["id"] : output[targetKey],
|
|
45
|
+
projectKey: targetKey === undefined ? output["projectKey"] : output[`${targetKey}ProjectKey`],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function shapeJobOutput(output, jobProjectKey) {
|
|
49
|
+
const fields = record(output);
|
|
50
|
+
const { id, projectKey, } = outputTarget(fields);
|
|
51
|
+
const partition = fields["targetPartition"] ?? fields["partition"];
|
|
52
|
+
return defined({
|
|
53
|
+
type: fields["type"],
|
|
54
|
+
id,
|
|
55
|
+
projectKey: typeof projectKey === "string" && projectKey !== jobProjectKey
|
|
56
|
+
? projectKey
|
|
57
|
+
: undefined,
|
|
58
|
+
partition: typeof partition === "string" && partition !== "NP" ? partition : undefined,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function shapeJobActivity(activity) {
|
|
62
|
+
const fields = record(activity);
|
|
63
|
+
return defined({
|
|
64
|
+
id: fields["activityId"],
|
|
65
|
+
recipe: fields["recipeName"],
|
|
66
|
+
recipeType: fields["recipeType"],
|
|
67
|
+
state: fields["state"],
|
|
68
|
+
totalTime: fields["totalTime"],
|
|
69
|
+
warnings: record(fields["warnings"])["totalCount"],
|
|
70
|
+
error: errorSummary(fields["firstFailure"]),
|
|
71
|
+
message: nonEmptyString(fields["message"]),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/** `job get`: state, outputs, progress, and the failure; never the log tail. */
|
|
75
|
+
function shapeJobGet(result) {
|
|
76
|
+
if (!isRecord(result))
|
|
77
|
+
return result;
|
|
78
|
+
const base = record(result["baseStatus"]);
|
|
79
|
+
const def = record(base["def"]);
|
|
80
|
+
const activities = record(base["activities"]);
|
|
81
|
+
return defined({
|
|
82
|
+
id: def["id"],
|
|
83
|
+
name: def["name"],
|
|
84
|
+
type: def["type"],
|
|
85
|
+
state: base["state"],
|
|
86
|
+
initiator: nonEmptyString(def["initiator"])
|
|
87
|
+
?? nonEmptyString(record(result["initiator"])["login"]),
|
|
88
|
+
triggeredFrom: def["triggeredFrom"],
|
|
89
|
+
startTime: base["jobStartTime"],
|
|
90
|
+
endTime: base["jobEndTime"],
|
|
91
|
+
outputs: Array.isArray(def["outputs"])
|
|
92
|
+
? def["outputs"].map((output) => shapeJobOutput(output, def["projectKey"]))
|
|
93
|
+
: undefined,
|
|
94
|
+
progress: result["globalState"],
|
|
95
|
+
error: errorSummary(result["error"]),
|
|
96
|
+
activities: Object.values(activities).map(shapeJobActivity),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/** Extra column keys worth keeping when set (DSS sends most as ""/defaults). */
|
|
100
|
+
const COLUMN_EXTRA_KEYS = ["meaning", "comment",];
|
|
101
|
+
function shapeColumn(column) {
|
|
102
|
+
const fields = record(column);
|
|
103
|
+
const shaped = { name: fields["name"], type: fields["type"], };
|
|
104
|
+
for (const key of COLUMN_EXTRA_KEYS) {
|
|
105
|
+
const value = nonEmptyString(fields[key]);
|
|
106
|
+
if (value !== undefined)
|
|
107
|
+
shaped[key] = value;
|
|
108
|
+
}
|
|
109
|
+
return shaped;
|
|
110
|
+
}
|
|
111
|
+
function shapeLastBuild(value) {
|
|
112
|
+
if (!isRecord(value))
|
|
113
|
+
return undefined;
|
|
114
|
+
const shaped = defined({
|
|
115
|
+
jobId: value["jobId"],
|
|
116
|
+
success: value["buildSuccess"],
|
|
117
|
+
startTime: value["buildStartTime"],
|
|
118
|
+
endTime: value["buildEndTime"],
|
|
119
|
+
});
|
|
120
|
+
return Object.keys(shaped).length > 0 ? shaped : undefined;
|
|
121
|
+
}
|
|
122
|
+
/** `dataset info`: what the dataset is, its schema, flow neighbours, and freshness. */
|
|
123
|
+
function shapeDatasetInfo(result) {
|
|
124
|
+
if (!isRecord(result))
|
|
125
|
+
return result;
|
|
126
|
+
const dataset = record(result["dataset"]);
|
|
127
|
+
const params = record(dataset["params"]);
|
|
128
|
+
const columns = record(dataset["schema"])["columns"];
|
|
129
|
+
const tags = dataset["tags"];
|
|
130
|
+
const quality = record(result["dataQualityStatus"]);
|
|
131
|
+
const versioning = record(result["versioning"]);
|
|
132
|
+
const timeline = record(result["timeline"]);
|
|
133
|
+
return defined({
|
|
134
|
+
name: result["name"] ?? dataset["name"],
|
|
135
|
+
type: result["type"] ?? dataset["type"],
|
|
136
|
+
managed: dataset["managed"],
|
|
137
|
+
connection: params["connection"] ?? params["uploadConnection"],
|
|
138
|
+
formatType: dataset["formatType"],
|
|
139
|
+
partitioned: result["partitioned"],
|
|
140
|
+
schema: Array.isArray(columns) ? columns.map(shapeColumn) : undefined,
|
|
141
|
+
recipes: Array.isArray(result["recipes"])
|
|
142
|
+
? result["recipes"].map((recipe) => record(recipe)["name"])
|
|
143
|
+
: undefined,
|
|
144
|
+
buildable: result["buildable"],
|
|
145
|
+
upstreamBuildable: result["upstreamBuildable"],
|
|
146
|
+
downstreamBuildable: result["downstreamBuildable"],
|
|
147
|
+
tags: Array.isArray(tags) && tags.length > 0 ? tags : undefined,
|
|
148
|
+
dataQuality: Object.keys(quality).length > 0 && quality["numberItems"] !== 0
|
|
149
|
+
? result["dataQualityStatus"]
|
|
150
|
+
: undefined,
|
|
151
|
+
lastBuild: shapeLastBuild(result["lastBuild"]),
|
|
152
|
+
lastModifiedOn: versioning["lastModifiedOn"] ?? timeline["lastModifiedOn"],
|
|
153
|
+
lastModifiedBy: record(versioning["lastModifiedBy"] ?? timeline["lastModifiedBy"])["login"],
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Recursively remove empty strings, arrays and objects (including objects that
|
|
158
|
+
* become empty). `false`, `0` and `null` are kept. Array positions are
|
|
159
|
+
* preserved: an element that empties out stays as its empty value.
|
|
160
|
+
*/
|
|
161
|
+
function pruneEmpty(value) {
|
|
162
|
+
if (typeof value === "string")
|
|
163
|
+
return value.length === 0 ? undefined : value;
|
|
164
|
+
if (Array.isArray(value)) {
|
|
165
|
+
if (value.length === 0)
|
|
166
|
+
return undefined;
|
|
167
|
+
return value.map((item) => pruneEmpty(item) ?? (typeof item === "string" ? "" : Array.isArray(item) ? [] : {}));
|
|
168
|
+
}
|
|
169
|
+
if (isRecord(value)) {
|
|
170
|
+
const pruned = {};
|
|
171
|
+
for (const [key, member,] of Object.entries(value)) {
|
|
172
|
+
const kept = pruneEmpty(member);
|
|
173
|
+
if (kept !== undefined)
|
|
174
|
+
pruned[key] = kept;
|
|
175
|
+
}
|
|
176
|
+
return Object.keys(pruned).length === 0 ? undefined : pruned;
|
|
177
|
+
}
|
|
178
|
+
return value;
|
|
179
|
+
}
|
|
180
|
+
function withoutKeys(source, keys) {
|
|
181
|
+
return Object.fromEntries(Object.entries(source).filter(([key,]) => !keys.includes(key)));
|
|
182
|
+
}
|
|
183
|
+
/** `dataset get`: the settings object minus metadata and empty/default noise. */
|
|
184
|
+
function shapeDatasetGet(result) {
|
|
185
|
+
if (!isRecord(result))
|
|
186
|
+
return result;
|
|
187
|
+
const settings = withoutKeys(result, DATASET_GET_DROPPED_KEYS);
|
|
188
|
+
const formatParams = settings["formatParams"];
|
|
189
|
+
if (isRecord(formatParams)) {
|
|
190
|
+
settings["formatParams"] = withoutKeys(formatParams, ["hiveSeparators",]);
|
|
191
|
+
}
|
|
192
|
+
return pruneEmpty(settings) ?? {};
|
|
193
|
+
}
|
|
194
|
+
const PERMISSION_KEY = /^can[A-Z]/;
|
|
195
|
+
/**
|
|
196
|
+
* `project get`: as `dataset get`, with the boolean permission flags
|
|
197
|
+
* (`can*`, `isProjectAdmin`) collapsed to the denied ones. Absent from the
|
|
198
|
+
* list means granted, so nothing is lost.
|
|
199
|
+
*/
|
|
200
|
+
function shapeProjectGet(result) {
|
|
201
|
+
if (!isRecord(result))
|
|
202
|
+
return result;
|
|
203
|
+
const settings = withoutKeys(result, PROJECT_GET_DROPPED_KEYS);
|
|
204
|
+
const deniedPermissions = [];
|
|
205
|
+
for (const [key, value,] of Object.entries(settings)) {
|
|
206
|
+
if (typeof value !== "boolean" || !(PERMISSION_KEY.test(key) || key === "isProjectAdmin")) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
if (!value)
|
|
210
|
+
deniedPermissions.push(key);
|
|
211
|
+
delete settings[key];
|
|
212
|
+
}
|
|
213
|
+
const pruned = record(pruneEmpty(settings));
|
|
214
|
+
return { ...pruned, deniedPermissions, };
|
|
215
|
+
}
|
|
216
|
+
/** Compact read shapers by `resource.action`. */
|
|
217
|
+
const READ_SHAPERS = {
|
|
218
|
+
"job.get": shapeJobGet,
|
|
219
|
+
"dataset.info": shapeDatasetInfo,
|
|
220
|
+
"dataset.get": shapeDatasetGet,
|
|
221
|
+
"project.get": shapeProjectGet,
|
|
222
|
+
};
|
|
223
|
+
/**
|
|
224
|
+
* Compact a command result for agents: `*.list` items (filter, cap, compact
|
|
225
|
+
* fields) and the four large read commands. `--full` and `--fields` bypass
|
|
226
|
+
* the read shapers so the DSS object (or a projection of it) is returned.
|
|
227
|
+
*/
|
|
228
|
+
export function shapeCommandResult(resource, action, result, flags) {
|
|
229
|
+
if (action === "list")
|
|
230
|
+
return shapeListResult(resource, result, flags);
|
|
231
|
+
const shaper = READ_SHAPERS[`${resource}.${action}`];
|
|
232
|
+
if (!shaper || flags["full"] === true || typeof flags["fields"] === "string")
|
|
233
|
+
return result;
|
|
234
|
+
return shaper(result);
|
|
235
|
+
}
|
package/dist/src/cli/types.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface CommandPayloadSchema {
|
|
|
7
7
|
dataFileFlag?: boolean;
|
|
8
8
|
contentType?: "application/json" | "text/plain";
|
|
9
9
|
jsonShape?: "object" | "array";
|
|
10
|
+
/** Precise JSON Schema of the payload, published as the contract's `schemas.input`. */
|
|
11
|
+
jsonSchema?: Record<string, unknown>;
|
|
10
12
|
}
|
|
11
13
|
export interface CommandFlagChoice {
|
|
12
14
|
oneOf: string[][];
|
|
@@ -49,7 +49,7 @@ export declare function buildVersionPayload(input: {
|
|
|
49
49
|
export declare const PACKAGE_ROOT: string | undefined;
|
|
50
50
|
export declare const CLI_VERSION: string;
|
|
51
51
|
export declare const CLI_GIT_REVISION: string | undefined;
|
|
52
|
-
export declare const AGENT_CONTRACT_VERSION =
|
|
52
|
+
export declare const AGENT_CONTRACT_VERSION = 4;
|
|
53
53
|
export declare const JSON_SCHEMA_DRAFT = "https://json-schema.org/draft/2020-12/schema";
|
|
54
|
-
export declare const AGENT_CONTRACT_SCHEMA_ID = "https://clssck.github.io/dataiku-sdk/schemas/agent-contract-
|
|
54
|
+
export declare const AGENT_CONTRACT_SCHEMA_ID = "https://clssck.github.io/dataiku-sdk/schemas/agent-contract-v4.json";
|
|
55
55
|
export declare function cliVersionResult(): CliVersionPayload;
|
package/dist/src/cli/version.js
CHANGED
|
@@ -204,9 +204,9 @@ export function buildVersionPayload(input) {
|
|
|
204
204
|
export const PACKAGE_ROOT = findPackageRoot();
|
|
205
205
|
export const CLI_VERSION = packageVersion(PACKAGE_ROOT);
|
|
206
206
|
export const CLI_GIT_REVISION = gitRevision(PACKAGE_ROOT);
|
|
207
|
-
export const AGENT_CONTRACT_VERSION =
|
|
207
|
+
export const AGENT_CONTRACT_VERSION = 4;
|
|
208
208
|
export const JSON_SCHEMA_DRAFT = "https://json-schema.org/draft/2020-12/schema";
|
|
209
|
-
export const AGENT_CONTRACT_SCHEMA_ID = "https://clssck.github.io/dataiku-sdk/schemas/agent-contract-
|
|
209
|
+
export const AGENT_CONTRACT_SCHEMA_ID = "https://clssck.github.io/dataiku-sdk/schemas/agent-contract-v4.json";
|
|
210
210
|
export function cliVersionResult() {
|
|
211
211
|
// Only code actually loaded from dist/ may report dist provenance; an
|
|
212
212
|
// inherited DSS_LOAD_SOURCE on a source run is ignored.
|