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.js
CHANGED
|
@@ -5,10 +5,10 @@ import { resolve, } from "node:path";
|
|
|
5
5
|
import { num, seenJsonInputCredentials, unknownJsonInput, } from "./cli/coerce.js";
|
|
6
6
|
import { commands, } from "./cli/commands/index.js";
|
|
7
7
|
import { ambientProjectKey, loadEnvFile, } from "./cli/env.js";
|
|
8
|
-
import { executionMode, FLAG_ALIASES,
|
|
8
|
+
import { executionMode, FLAG_ALIASES, isFlagValueToken, parseArgs, rawPositionals, } from "./cli/flags.js";
|
|
9
9
|
import { cleanupLedgerEntry, } from "./cli/helpers/cleanup.js";
|
|
10
|
-
import { shapeListResult, } from "./cli/list-output.js";
|
|
11
10
|
import { commandFailureExitCode, CommandResultFailure, enqueueCliWarning, flushCliWarnings, isFailedWaitResult, planResult, projectResultFields, setOutputFieldProjection, writeCommandResult, } from "./cli/output.js";
|
|
11
|
+
import { shapeCommandResult, } from "./cli/result-shapes.js";
|
|
12
12
|
import { currentCommandContext, resolveCredentials, resolveLoginCredentials, } from "./cli/runtime.js";
|
|
13
13
|
import { commandSyntaxTree, commandUsage, } from "./cli/syntax.js";
|
|
14
14
|
import { COMMANDS_RUN_HINT, inferRequiresProject, missingActionError, noCommandError, requireArgs, RESOURCE_NAMES, unknownActionError, unknownFlagError, unknownResourceError, UsageError, } from "./cli/usage.js";
|
|
@@ -533,8 +533,7 @@ function redactArgv(argv) {
|
|
|
533
533
|
else {
|
|
534
534
|
redacted.push(arg);
|
|
535
535
|
const next = argv[index + 1];
|
|
536
|
-
if (next !== undefined
|
|
537
|
-
&& (next === "-" || !next.startsWith("-") || isNegativeNumberToken(next))) {
|
|
536
|
+
if (next !== undefined && isFlagValueToken(next)) {
|
|
538
537
|
redacted.push("***");
|
|
539
538
|
index++;
|
|
540
539
|
}
|
|
@@ -1023,8 +1022,7 @@ async function runBatch(flags) {
|
|
|
1023
1022
|
await preflightCleanupLedgerForFlags(client, stepFlags);
|
|
1024
1023
|
const stepArgs = positional.slice(2);
|
|
1025
1024
|
result = await meta.handler(client, stepArgs, stepFlags);
|
|
1026
|
-
|
|
1027
|
-
result = shapeListResult(resource, result, stepFlags);
|
|
1025
|
+
result = shapeCommandResult(resource, action, result, stepFlags);
|
|
1028
1026
|
await recordCleanupLedgerEntry(client, resource, action, stepArgs, stepFlags, result, projectKey);
|
|
1029
1027
|
}
|
|
1030
1028
|
const failureExitCode = commandFailureExitCode(result);
|
|
@@ -1247,6 +1245,10 @@ function dssDiagnosticDetails(err) {
|
|
|
1247
1245
|
function isAmbiguousMutationFailure(err, context) {
|
|
1248
1246
|
if (!(err instanceof DataikuError))
|
|
1249
1247
|
return false;
|
|
1248
|
+
// DSS definitively refused the operation (e.g. the database rejected the SQL):
|
|
1249
|
+
// nothing took effect, so there is no outcome to verify.
|
|
1250
|
+
if (err.definiteFailure)
|
|
1251
|
+
return false;
|
|
1250
1252
|
const method = err.retry?.method.toUpperCase();
|
|
1251
1253
|
if (!method || method === "GET" || method === "HEAD")
|
|
1252
1254
|
return false;
|
|
@@ -1298,13 +1300,14 @@ function errorExitCode(err) {
|
|
|
1298
1300
|
}
|
|
1299
1301
|
function buildErrorReport(err, contextOverride) {
|
|
1300
1302
|
const context = contextOverride ?? rawCommandContext();
|
|
1303
|
+
// The envelope echoes only the resolved project; resource/action are known to the caller.
|
|
1304
|
+
const scope = context.projectKey ? { projectKey: context.projectKey, } : {};
|
|
1301
1305
|
const exitCode = errorExitCode(err);
|
|
1302
1306
|
if (err instanceof ClientValidationError
|
|
1303
1307
|
&& (err.code === "ambiguous_outcome" || err.code === "assertion_failed"
|
|
1304
1308
|
|| err.code === "long_running_failure")) {
|
|
1305
1309
|
return {
|
|
1306
1310
|
type: "error",
|
|
1307
|
-
ok: false,
|
|
1308
1311
|
error: err.message,
|
|
1309
1312
|
code: err.code,
|
|
1310
1313
|
category: "dss",
|
|
@@ -1312,13 +1315,12 @@ function buildErrorReport(err, contextOverride) {
|
|
|
1312
1315
|
retryable: false,
|
|
1313
1316
|
...(err.hint ? { hint: err.hint, } : {}),
|
|
1314
1317
|
...(err.details ? { details: err.details, } : {}),
|
|
1315
|
-
...
|
|
1318
|
+
...scope,
|
|
1316
1319
|
};
|
|
1317
1320
|
}
|
|
1318
1321
|
if (err instanceof UsageError || err instanceof ClientValidationError) {
|
|
1319
1322
|
return {
|
|
1320
1323
|
type: "error",
|
|
1321
|
-
ok: false,
|
|
1322
1324
|
error: err.message,
|
|
1323
1325
|
code: err.code,
|
|
1324
1326
|
category: err.code === "target_absence_unverifiable"
|
|
@@ -1330,26 +1332,24 @@ function buildErrorReport(err, contextOverride) {
|
|
|
1330
1332
|
...(err.code === "target_absence_unverifiable" ? { retryable: false, } : {}),
|
|
1331
1333
|
...(err.hint ? { hint: err.hint, } : {}),
|
|
1332
1334
|
...(err.details ? { details: err.details, } : {}),
|
|
1333
|
-
...
|
|
1335
|
+
...scope,
|
|
1334
1336
|
};
|
|
1335
1337
|
}
|
|
1336
1338
|
if (err instanceof CommandResultFailure) {
|
|
1337
1339
|
return {
|
|
1338
1340
|
type: "error",
|
|
1339
|
-
ok: false,
|
|
1340
1341
|
error: err.message,
|
|
1341
1342
|
code: err.code,
|
|
1342
1343
|
category: "dss",
|
|
1343
1344
|
exitCode: err.exitCode,
|
|
1344
1345
|
details: boundedFailureResult(err.result),
|
|
1345
|
-
...
|
|
1346
|
+
...scope,
|
|
1346
1347
|
};
|
|
1347
1348
|
}
|
|
1348
1349
|
if (isAmbiguousMutationFailure(err, context)) {
|
|
1349
1350
|
const method = err.retry?.method.toUpperCase() ?? "mutation";
|
|
1350
1351
|
return {
|
|
1351
1352
|
type: "error",
|
|
1352
|
-
ok: false,
|
|
1353
1353
|
error: `The ${method} request failed after dispatch; the mutation outcome is unknown.`,
|
|
1354
1354
|
code: "ambiguous_outcome",
|
|
1355
1355
|
category: "dss",
|
|
@@ -1363,14 +1363,19 @@ function buildErrorReport(err, contextOverride) {
|
|
|
1363
1363
|
idempotency: "none",
|
|
1364
1364
|
...dssErrorDetails(err),
|
|
1365
1365
|
...dssDiagnosticDetails(err),
|
|
1366
|
+
...err.details,
|
|
1366
1367
|
...(err.retry ? { retry: err.retry, } : {}),
|
|
1367
1368
|
},
|
|
1368
|
-
...
|
|
1369
|
+
...scope,
|
|
1369
1370
|
};
|
|
1370
1371
|
}
|
|
1371
1372
|
if (err instanceof DataikuError) {
|
|
1372
1373
|
const { dssMessage, dssErrorType, } = dssDiagnosticDetails(err);
|
|
1373
|
-
const details = {
|
|
1374
|
+
const details = {
|
|
1375
|
+
...dssErrorDetails(err),
|
|
1376
|
+
...(dssErrorType ? { dssErrorType, } : {}),
|
|
1377
|
+
...err.details,
|
|
1378
|
+
};
|
|
1374
1379
|
// Generic hints name what the command targeted. DSS answers 403 (not
|
|
1375
1380
|
// 404) for a project that does not exist: "Failed to read project
|
|
1376
1381
|
// permissions". A 403 about something else keeps the generic hint.
|
|
@@ -1383,7 +1388,6 @@ function buildErrorReport(err, contextOverride) {
|
|
|
1383
1388
|
: err.retryHint;
|
|
1384
1389
|
return {
|
|
1385
1390
|
type: "error",
|
|
1386
|
-
ok: false,
|
|
1387
1391
|
error: dssMessage ? `${err.safeMessage}: ${dssMessage}` : err.safeMessage,
|
|
1388
1392
|
code: dataikuErrorCode(err.category),
|
|
1389
1393
|
category: "dss",
|
|
@@ -1393,18 +1397,17 @@ function buildErrorReport(err, contextOverride) {
|
|
|
1393
1397
|
retryable: err.retryable,
|
|
1394
1398
|
requestId: err.requestId ?? requestIdFromBody(err.body),
|
|
1395
1399
|
...(Object.keys(details).length > 0 ? { details, } : {}),
|
|
1396
|
-
...
|
|
1400
|
+
...scope,
|
|
1397
1401
|
};
|
|
1398
1402
|
}
|
|
1399
1403
|
const message = err instanceof Error ? err.message : String(err);
|
|
1400
1404
|
return {
|
|
1401
1405
|
type: "error",
|
|
1402
|
-
ok: false,
|
|
1403
1406
|
error: message,
|
|
1404
1407
|
code: "internal_error",
|
|
1405
1408
|
category: "internal",
|
|
1406
1409
|
exitCode,
|
|
1407
|
-
...
|
|
1410
|
+
...scope,
|
|
1408
1411
|
};
|
|
1409
1412
|
}
|
|
1410
1413
|
function writeErrorReport(err) {
|
|
@@ -1516,7 +1519,7 @@ async function main() {
|
|
|
1516
1519
|
assertCleanupLedgerSupported(resource, action, flags);
|
|
1517
1520
|
await preflightCleanupLedgerForFlags(client, flags);
|
|
1518
1521
|
const handled = await actionMeta.handler(client, args, flags);
|
|
1519
|
-
const result =
|
|
1522
|
+
const result = shapeCommandResult(resource, action, handled, flags);
|
|
1520
1523
|
await recordCleanupLedgerEntry(client, resource, action, args, flags, result, projectKey);
|
|
1521
1524
|
const failureExitCode = commandFailureExitCode(result);
|
|
1522
1525
|
if (failureExitCode !== undefined)
|
package/dist/src/errors.d.ts
CHANGED
|
@@ -20,12 +20,18 @@ export interface DataikuErrorTrustedMetadata {
|
|
|
20
20
|
elapsedMs?: number;
|
|
21
21
|
/** Set by the transport when the retained response body is only a bounded prefix. */
|
|
22
22
|
bodyTruncated?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Set by a resource that recognized DSS's answer as a definite failure of the
|
|
25
|
+
* whole operation: nothing took effect, so a non-idempotent mutation is not
|
|
26
|
+
* ambiguous.
|
|
27
|
+
*/
|
|
28
|
+
definiteFailure?: boolean;
|
|
23
29
|
}
|
|
24
30
|
export declare function canonicalStatusText(status: number): string;
|
|
25
31
|
export declare class ClientValidationError extends Error {
|
|
26
32
|
readonly code: StableErrorCode;
|
|
27
33
|
readonly hint?: string;
|
|
28
|
-
|
|
34
|
+
details?: Record<string, unknown>;
|
|
29
35
|
constructor(message: string, code?: StableErrorCode, hint?: string, details?: Record<string, unknown>, options?: ErrorOptions);
|
|
30
36
|
}
|
|
31
37
|
/**
|
|
@@ -62,6 +68,10 @@ export declare class DataikuError extends Error {
|
|
|
62
68
|
readonly trustedTarget?: string;
|
|
63
69
|
readonly trustedElapsedMs?: number;
|
|
64
70
|
readonly bodyTruncated?: boolean;
|
|
71
|
+
/** DSS definitively failed the whole operation; see `DataikuErrorTrustedMetadata.definiteFailure`. */
|
|
72
|
+
readonly definiteFailure?: boolean;
|
|
73
|
+
/** Client-side outcome context (e.g. rollback of partial mutations), surfaced in CLI `details`. */
|
|
74
|
+
details?: Record<string, unknown>;
|
|
65
75
|
constructor(status: number, statusText: string, body: string, retry?: DataikuRetryMetadata, requestId?: string, trustedMetadata?: DataikuErrorTrustedMetadata);
|
|
66
76
|
/** Status line only: never echoes response body text. */
|
|
67
77
|
get safeMessage(): string;
|
package/dist/src/errors.js
CHANGED
|
@@ -74,6 +74,8 @@ export const UNEXPECTED_RESPONSE_MARKER = "Unexpected DSS response";
|
|
|
74
74
|
export function unexpectedResponseError(detail, status = 200) {
|
|
75
75
|
return new DataikuError(status, "Unexpected Response", `${UNEXPECTED_RESPONSE_MARKER}: ${detail}`);
|
|
76
76
|
}
|
|
77
|
+
/** Hint for a DSS answer that definitively failed the request (e.g. the database rejected the SQL). */
|
|
78
|
+
const DEFINITE_FAILURE_HINT = "DSS reported that the request failed (for SQL: syntax error, missing object, or missing privileges of the connection's role). Fix the request or grants; do not retry unchanged.";
|
|
77
79
|
/** Prefix for a SQL query failure reported by DSS on a 2xx finish-streaming response. */
|
|
78
80
|
export const SQL_QUERY_FAILED_MARKER = "SQL query failed in DSS";
|
|
79
81
|
const TLS_CERTIFICATE_HINT = "TLS certificate verification failed. Trust the DSS/corporate CA with --ca-cert PATH or NODE_EXTRA_CA_CERTS, or save it for every process and directory with `dss auth login --ca-cert PATH` (a project .env applies only when dss runs in that directory); use --insecure only for temporary troubleshooting.";
|
|
@@ -140,6 +142,8 @@ function isCertificateTrustFailure(lowerBody) {
|
|
|
140
142
|
|| lowerBody.includes("unable to get local issuer certificate")
|
|
141
143
|
|| lowerBody.includes("unable to verify leaf signature")
|
|
142
144
|
|| lowerBody.includes("self-signed certificate")
|
|
145
|
+
|| lowerBody.includes("self signed certificate")
|
|
146
|
+
|| lowerBody.includes("depth_zero_self_signed_cert")
|
|
143
147
|
|| lowerBody.includes("certificate has expired")
|
|
144
148
|
|| lowerBody.includes("cert_has_expired")
|
|
145
149
|
|| lowerBody.includes("self_signed_cert_in_chain")
|
|
@@ -372,6 +376,10 @@ export class DataikuError extends Error {
|
|
|
372
376
|
trustedTarget;
|
|
373
377
|
trustedElapsedMs;
|
|
374
378
|
bodyTruncated;
|
|
379
|
+
/** DSS definitively failed the whole operation; see `DataikuErrorTrustedMetadata.definiteFailure`. */
|
|
380
|
+
definiteFailure;
|
|
381
|
+
/** Client-side outcome context (e.g. rollback of partial mutations), surfaced in CLI `details`. */
|
|
382
|
+
details;
|
|
375
383
|
constructor(status, statusText, body, retry, requestId, trustedMetadata) {
|
|
376
384
|
const details = DataikuError.buildDetails(status, body);
|
|
377
385
|
super(details.message);
|
|
@@ -379,14 +387,21 @@ export class DataikuError extends Error {
|
|
|
379
387
|
this.statusText = statusText;
|
|
380
388
|
this.body = body;
|
|
381
389
|
this.name = "DataikuError";
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
390
|
+
const definite = trustedMetadata?.definiteFailure === true;
|
|
391
|
+
// A definite DSS refusal is not a transport/server fault: replaying it
|
|
392
|
+
// unchanged cannot succeed. Keep a more specific forbidden/not_found class.
|
|
393
|
+
const reclassify = definite
|
|
394
|
+
&& (details.category === "transient" || details.category === "unknown"
|
|
395
|
+
|| details.category === "unexpected_response");
|
|
396
|
+
this.category = reclassify ? "validation" : details.category;
|
|
397
|
+
this.retryable = reclassify ? false : details.retryable;
|
|
398
|
+
this.retryHint = reclassify ? DEFINITE_FAILURE_HINT : details.retryHint;
|
|
385
399
|
this.retry = retry;
|
|
386
400
|
this.requestId = requestId;
|
|
387
401
|
this.trustedTarget = trustedMetadata?.target;
|
|
388
402
|
this.trustedElapsedMs = trustedMetadata?.elapsedMs;
|
|
389
403
|
this.bodyTruncated = trustedMetadata?.bodyTruncated === true ? true : undefined;
|
|
404
|
+
this.definiteFailure = definite ? true : undefined;
|
|
390
405
|
}
|
|
391
406
|
/** Status line only: never echoes response body text. */
|
|
392
407
|
get safeMessage() {
|
|
@@ -363,6 +363,107 @@
|
|
|
363
363
|
}
|
|
364
364
|
}
|
|
365
365
|
},
|
|
366
|
+
"dataset.info": {
|
|
367
|
+
"type": "object",
|
|
368
|
+
"additionalProperties": false,
|
|
369
|
+
"required": [
|
|
370
|
+
"name"
|
|
371
|
+
],
|
|
372
|
+
"properties": {
|
|
373
|
+
"name": {
|
|
374
|
+
"type": "string"
|
|
375
|
+
},
|
|
376
|
+
"type": {
|
|
377
|
+
"type": "string"
|
|
378
|
+
},
|
|
379
|
+
"managed": {
|
|
380
|
+
"type": "boolean"
|
|
381
|
+
},
|
|
382
|
+
"connection": {
|
|
383
|
+
"type": "string"
|
|
384
|
+
},
|
|
385
|
+
"formatType": {
|
|
386
|
+
"type": "string"
|
|
387
|
+
},
|
|
388
|
+
"partitioned": {
|
|
389
|
+
"type": "boolean"
|
|
390
|
+
},
|
|
391
|
+
"schema": {
|
|
392
|
+
"type": "array",
|
|
393
|
+
"items": {
|
|
394
|
+
"type": "object",
|
|
395
|
+
"additionalProperties": false,
|
|
396
|
+
"required": [
|
|
397
|
+
"name",
|
|
398
|
+
"type"
|
|
399
|
+
],
|
|
400
|
+
"properties": {
|
|
401
|
+
"name": {
|
|
402
|
+
"type": "string"
|
|
403
|
+
},
|
|
404
|
+
"type": {
|
|
405
|
+
"type": "string"
|
|
406
|
+
},
|
|
407
|
+
"meaning": {
|
|
408
|
+
"type": "string"
|
|
409
|
+
},
|
|
410
|
+
"comment": {
|
|
411
|
+
"type": "string"
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
"recipes": {
|
|
417
|
+
"type": "array",
|
|
418
|
+
"items": {
|
|
419
|
+
"type": "string"
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
"buildable": {
|
|
423
|
+
"type": "boolean"
|
|
424
|
+
},
|
|
425
|
+
"upstreamBuildable": {
|
|
426
|
+
"type": "boolean"
|
|
427
|
+
},
|
|
428
|
+
"downstreamBuildable": {
|
|
429
|
+
"type": "boolean"
|
|
430
|
+
},
|
|
431
|
+
"tags": {
|
|
432
|
+
"type": "array",
|
|
433
|
+
"items": {
|
|
434
|
+
"type": "string"
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
"dataQuality": {
|
|
438
|
+
"type": "object",
|
|
439
|
+
"additionalProperties": true
|
|
440
|
+
},
|
|
441
|
+
"lastBuild": {
|
|
442
|
+
"type": "object",
|
|
443
|
+
"additionalProperties": false,
|
|
444
|
+
"properties": {
|
|
445
|
+
"jobId": {
|
|
446
|
+
"type": "string"
|
|
447
|
+
},
|
|
448
|
+
"success": {
|
|
449
|
+
"type": "boolean"
|
|
450
|
+
},
|
|
451
|
+
"startTime": {
|
|
452
|
+
"type": "number"
|
|
453
|
+
},
|
|
454
|
+
"endTime": {
|
|
455
|
+
"type": "number"
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
"lastModifiedOn": {
|
|
460
|
+
"type": "number"
|
|
461
|
+
},
|
|
462
|
+
"lastModifiedBy": {
|
|
463
|
+
"type": "string"
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
},
|
|
366
467
|
"dataset.list": {
|
|
367
468
|
"type": "array",
|
|
368
469
|
"items": {
|
|
@@ -825,6 +926,121 @@
|
|
|
825
926
|
}
|
|
826
927
|
}
|
|
827
928
|
},
|
|
929
|
+
"job.get": {
|
|
930
|
+
"type": "object",
|
|
931
|
+
"additionalProperties": false,
|
|
932
|
+
"required": [
|
|
933
|
+
"id",
|
|
934
|
+
"state"
|
|
935
|
+
],
|
|
936
|
+
"properties": {
|
|
937
|
+
"id": {
|
|
938
|
+
"type": "string"
|
|
939
|
+
},
|
|
940
|
+
"name": {
|
|
941
|
+
"type": "string"
|
|
942
|
+
},
|
|
943
|
+
"type": {
|
|
944
|
+
"type": "string"
|
|
945
|
+
},
|
|
946
|
+
"state": {
|
|
947
|
+
"type": "string"
|
|
948
|
+
},
|
|
949
|
+
"initiator": {
|
|
950
|
+
"type": "string"
|
|
951
|
+
},
|
|
952
|
+
"triggeredFrom": {
|
|
953
|
+
"type": "string"
|
|
954
|
+
},
|
|
955
|
+
"startTime": {
|
|
956
|
+
"type": "number"
|
|
957
|
+
},
|
|
958
|
+
"endTime": {
|
|
959
|
+
"type": "number"
|
|
960
|
+
},
|
|
961
|
+
"outputs": {
|
|
962
|
+
"type": "array",
|
|
963
|
+
"items": {
|
|
964
|
+
"type": "object",
|
|
965
|
+
"additionalProperties": false,
|
|
966
|
+
"properties": {
|
|
967
|
+
"type": {
|
|
968
|
+
"type": "string"
|
|
969
|
+
},
|
|
970
|
+
"id": {
|
|
971
|
+
"type": "string"
|
|
972
|
+
},
|
|
973
|
+
"projectKey": {
|
|
974
|
+
"type": "string"
|
|
975
|
+
},
|
|
976
|
+
"partition": {
|
|
977
|
+
"type": "string"
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
},
|
|
982
|
+
"progress": {
|
|
983
|
+
"type": "object",
|
|
984
|
+
"additionalProperties": {
|
|
985
|
+
"type": "number"
|
|
986
|
+
}
|
|
987
|
+
},
|
|
988
|
+
"error": {
|
|
989
|
+
"type": "object",
|
|
990
|
+
"additionalProperties": false,
|
|
991
|
+
"properties": {
|
|
992
|
+
"type": {
|
|
993
|
+
"type": "string"
|
|
994
|
+
},
|
|
995
|
+
"message": {
|
|
996
|
+
"type": "string"
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
},
|
|
1000
|
+
"activities": {
|
|
1001
|
+
"type": "array",
|
|
1002
|
+
"items": {
|
|
1003
|
+
"type": "object",
|
|
1004
|
+
"additionalProperties": false,
|
|
1005
|
+
"properties": {
|
|
1006
|
+
"id": {
|
|
1007
|
+
"type": "string"
|
|
1008
|
+
},
|
|
1009
|
+
"recipe": {
|
|
1010
|
+
"type": "string"
|
|
1011
|
+
},
|
|
1012
|
+
"recipeType": {
|
|
1013
|
+
"type": "string"
|
|
1014
|
+
},
|
|
1015
|
+
"state": {
|
|
1016
|
+
"type": "string"
|
|
1017
|
+
},
|
|
1018
|
+
"totalTime": {
|
|
1019
|
+
"type": "number"
|
|
1020
|
+
},
|
|
1021
|
+
"warnings": {
|
|
1022
|
+
"type": "number"
|
|
1023
|
+
},
|
|
1024
|
+
"error": {
|
|
1025
|
+
"type": "object",
|
|
1026
|
+
"additionalProperties": false,
|
|
1027
|
+
"properties": {
|
|
1028
|
+
"type": {
|
|
1029
|
+
"type": "string"
|
|
1030
|
+
},
|
|
1031
|
+
"message": {
|
|
1032
|
+
"type": "string"
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
},
|
|
1036
|
+
"message": {
|
|
1037
|
+
"type": "string"
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
},
|
|
828
1044
|
"job.list": {
|
|
829
1045
|
"type": "array",
|
|
830
1046
|
"items": {
|
|
@@ -1519,7 +1735,8 @@
|
|
|
1519
1735
|
"type": "object",
|
|
1520
1736
|
"required": [
|
|
1521
1737
|
"projectKey",
|
|
1522
|
-
"name"
|
|
1738
|
+
"name",
|
|
1739
|
+
"deniedPermissions"
|
|
1523
1740
|
],
|
|
1524
1741
|
"properties": {
|
|
1525
1742
|
"projectKey": {
|
|
@@ -1537,25 +1754,6 @@
|
|
|
1537
1754
|
"projectAppType": {
|
|
1538
1755
|
"type": "string"
|
|
1539
1756
|
},
|
|
1540
|
-
"creationTag": {
|
|
1541
|
-
"additionalProperties": true,
|
|
1542
|
-
"type": "object",
|
|
1543
|
-
"properties": {
|
|
1544
|
-
"versionNumber": {
|
|
1545
|
-
"type": "number"
|
|
1546
|
-
},
|
|
1547
|
-
"lastModifiedOn": {
|
|
1548
|
-
"anyOf": [
|
|
1549
|
-
{
|
|
1550
|
-
"type": "number"
|
|
1551
|
-
},
|
|
1552
|
-
{
|
|
1553
|
-
"type": "string"
|
|
1554
|
-
}
|
|
1555
|
-
]
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
1558
|
-
},
|
|
1559
1757
|
"ownerLogin": {
|
|
1560
1758
|
"type": "string"
|
|
1561
1759
|
},
|
|
@@ -1565,21 +1763,12 @@
|
|
|
1565
1763
|
"type": "string"
|
|
1566
1764
|
}
|
|
1567
1765
|
},
|
|
1568
|
-
"
|
|
1569
|
-
"
|
|
1570
|
-
"
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
],
|
|
1575
|
-
"properties": {
|
|
1576
|
-
"versionNumber": {
|
|
1577
|
-
"type": "number"
|
|
1578
|
-
},
|
|
1579
|
-
"lastModifiedOn": {
|
|
1580
|
-
"type": "number"
|
|
1581
|
-
}
|
|
1582
|
-
}
|
|
1766
|
+
"deniedPermissions": {
|
|
1767
|
+
"type": "array",
|
|
1768
|
+
"items": {
|
|
1769
|
+
"type": "string"
|
|
1770
|
+
},
|
|
1771
|
+
"description": "Permission flags DSS reports as false; absent flags are granted."
|
|
1583
1772
|
}
|
|
1584
1773
|
}
|
|
1585
1774
|
},
|
|
@@ -4,6 +4,24 @@
|
|
|
4
4
|
* public endpoint writes; without it every downstream build fails.
|
|
5
5
|
*/
|
|
6
6
|
export declare function assertDatasetTypeCreatable(dsType: string): void;
|
|
7
|
+
/**
|
|
8
|
+
* Dataset types that read from a SQL connection. These are the types DSS
|
|
9
|
+
* detects schemas for through `testAndDetectSettings/externalSQL` (the list
|
|
10
|
+
* dataikuapi's `DSSDataset.autodetect_settings` uses).
|
|
11
|
+
*/
|
|
12
|
+
export declare const SQL_DATASET_TYPES: readonly ["JDBC", "PostgreSQL", "MySQL", "Vertica", "Snowflake", "Redshift", "Greenplum", "Teradata", "Oracle", "SQLServer", "SAPHANA", "Netezza", "BigQuery", "Athena", "hiveserver2", "Synapse", "FabricWarehouse", "Databricks", "DatabricksLakebase"];
|
|
13
|
+
export declare function isSqlDatasetType(dsType: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Validate the SQL source options (`table`/`dbSchema`/`catalog`/`query`) of a
|
|
16
|
+
* dataset creation against its type. Shared by `dataset create`, its plan, and
|
|
17
|
+
* the SDK so every entry point rejects the same combinations.
|
|
18
|
+
*/
|
|
19
|
+
export declare function assertSqlDatasetSource(dsType: string, source: {
|
|
20
|
+
table?: string;
|
|
21
|
+
dbSchema?: string;
|
|
22
|
+
catalog?: string;
|
|
23
|
+
query?: string;
|
|
24
|
+
}): void;
|
|
7
25
|
/** Wire body for POST /datasets/; shared with `dataset create --plan` so the plan matches the request. */
|
|
8
26
|
export declare function buildDatasetCreateBody(opts: {
|
|
9
27
|
projectKey: string;
|
|
@@ -13,6 +31,7 @@ export declare function buildDatasetCreateBody(opts: {
|
|
|
13
31
|
table?: string;
|
|
14
32
|
dbSchema?: string;
|
|
15
33
|
catalog?: string;
|
|
34
|
+
query?: string;
|
|
16
35
|
formatType?: string;
|
|
17
36
|
formatParams?: Record<string, unknown>;
|
|
18
37
|
managed?: boolean;
|
|
@@ -9,6 +9,60 @@ export function assertDatasetTypeCreatable(dsType) {
|
|
|
9
9
|
return;
|
|
10
10
|
throw new ClientValidationError("Inline (editable) datasets cannot be created here: the DSS public API cannot write their rows, and an Inline dataset without rows fails every downstream build (SourceDatasetNotReadyException). For a small static table, create an UploadedFiles dataset and upload a CSV with dss dataset upload-file, or write the rows from a python recipe into a managed dataset.", "validation_failed");
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Dataset types that read from a SQL connection. These are the types DSS
|
|
14
|
+
* detects schemas for through `testAndDetectSettings/externalSQL` (the list
|
|
15
|
+
* dataikuapi's `DSSDataset.autodetect_settings` uses).
|
|
16
|
+
*/
|
|
17
|
+
export const SQL_DATASET_TYPES = [
|
|
18
|
+
"JDBC",
|
|
19
|
+
"PostgreSQL",
|
|
20
|
+
"MySQL",
|
|
21
|
+
"Vertica",
|
|
22
|
+
"Snowflake",
|
|
23
|
+
"Redshift",
|
|
24
|
+
"Greenplum",
|
|
25
|
+
"Teradata",
|
|
26
|
+
"Oracle",
|
|
27
|
+
"SQLServer",
|
|
28
|
+
"SAPHANA",
|
|
29
|
+
"Netezza",
|
|
30
|
+
"BigQuery",
|
|
31
|
+
"Athena",
|
|
32
|
+
"hiveserver2",
|
|
33
|
+
"Synapse",
|
|
34
|
+
"FabricWarehouse",
|
|
35
|
+
"Databricks",
|
|
36
|
+
"DatabricksLakebase",
|
|
37
|
+
];
|
|
38
|
+
export function isSqlDatasetType(dsType) {
|
|
39
|
+
const lower = dsType.toLowerCase();
|
|
40
|
+
return SQL_DATASET_TYPES.some((type) => type.toLowerCase() === lower);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Validate the SQL source options (`table`/`dbSchema`/`catalog`/`query`) of a
|
|
44
|
+
* dataset creation against its type. Shared by `dataset create`, its plan, and
|
|
45
|
+
* the SDK so every entry point rejects the same combinations.
|
|
46
|
+
*/
|
|
47
|
+
export function assertSqlDatasetSource(dsType, source) {
|
|
48
|
+
const hasTable = source.table !== undefined;
|
|
49
|
+
const hasQuery = source.query !== undefined;
|
|
50
|
+
if (hasTable && hasQuery) {
|
|
51
|
+
throw new ClientValidationError("Pass either a table or a query for a SQL dataset, not both.", "conflicting_input_sources");
|
|
52
|
+
}
|
|
53
|
+
if (!hasTable && (source.dbSchema !== undefined || source.catalog !== undefined)) {
|
|
54
|
+
throw new ClientValidationError("A schema or catalog only applies together with a table.", "validation_failed", "Add --table, or drop --schema/--catalog (a query names its own tables).");
|
|
55
|
+
}
|
|
56
|
+
if (hasTable && source.table.trim() === "") {
|
|
57
|
+
throw new ClientValidationError("table must be a non-empty table name.", "invalid_flag_value");
|
|
58
|
+
}
|
|
59
|
+
if (hasQuery && source.query.trim() === "") {
|
|
60
|
+
throw new ClientValidationError("query must be a non-empty SQL query.", "invalid_flag_value");
|
|
61
|
+
}
|
|
62
|
+
if ((hasTable || hasQuery) && !isSqlDatasetType(dsType)) {
|
|
63
|
+
throw new ClientValidationError(`A table or query only applies to SQL dataset types, not "${dsType}".`, "validation_failed", `SQL types: ${SQL_DATASET_TYPES.join(", ")}.`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
12
66
|
/** Wire body for POST /datasets/; shared with `dataset create --plan` so the plan matches the request. */
|
|
13
67
|
export function buildDatasetCreateBody(opts) {
|
|
14
68
|
assertDatasetTypeCreatable(opts.dsType);
|
|
@@ -23,6 +77,21 @@ export function buildDatasetCreateBody(opts) {
|
|
|
23
77
|
if (!opts.connection) {
|
|
24
78
|
throw new ClientValidationError("connection is required unless dsType is UploadedFiles.");
|
|
25
79
|
}
|
|
80
|
+
if (opts.query !== undefined) {
|
|
81
|
+
if (opts.table !== undefined) {
|
|
82
|
+
throw new ClientValidationError("Pass either a table or a query for a SQL dataset, not both.", "conflicting_input_sources");
|
|
83
|
+
}
|
|
84
|
+
if (opts.query.trim() === "") {
|
|
85
|
+
throw new ClientValidationError("query must be a non-empty SQL query.", "invalid_flag_value");
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
projectKey: opts.projectKey,
|
|
89
|
+
name: opts.datasetName,
|
|
90
|
+
type: opts.dsType,
|
|
91
|
+
params: { connection: opts.connection, mode: "query", query: opts.query, },
|
|
92
|
+
managed: opts.managed ?? false,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
26
95
|
if (opts.table) {
|
|
27
96
|
const params = {
|
|
28
97
|
connection: opts.connection,
|