dataiku-sdk 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -17
- package/dist/build-metadata.json +1 -1
- package/dist/packages/types/src/index.d.ts +39 -4
- package/dist/packages/types/src/index.js +31 -2
- package/dist/src/cli/commands/api-service.js +62 -16
- package/dist/src/cli/commands/bundle.js +49 -15
- package/dist/src/cli/commands/code-env.js +210 -49
- package/dist/src/cli/commands/code.d.ts +19 -0
- package/dist/src/cli/commands/code.js +87 -15
- package/dist/src/cli/commands/dataset.js +8 -3
- package/dist/src/cli/commands/flow-zone.js +33 -5
- package/dist/src/cli/commands/notebook.js +72 -41
- package/dist/src/cli/commands/project-git.js +8 -5
- package/dist/src/cli/commands/project-library.d.ts +21 -0
- package/dist/src/cli/commands/project-library.js +121 -50
- package/dist/src/cli/commands/project.js +16 -2
- package/dist/src/cli/commands/recipe.js +37 -12
- package/dist/src/cli/commands/sql.d.ts +10 -0
- package/dist/src/cli/commands/sql.js +39 -17
- package/dist/src/cli/commands/webapp.js +67 -13
- package/dist/src/cli/contract.d.ts +15 -0
- package/dist/src/cli/contract.js +870 -107
- package/dist/src/cli/env.d.ts +9 -0
- package/dist/src/cli/env.js +20 -2
- package/dist/src/cli/flags.js +9 -0
- package/dist/src/cli/helpers/cleanup.js +104 -3
- package/dist/src/cli/helpers/flow-zone.d.ts +3 -0
- package/dist/src/cli/helpers/flow-zone.js +33 -3
- package/dist/src/cli/helpers/recipe.d.ts +20 -0
- package/dist/src/cli/helpers/recipe.js +158 -3
- package/dist/src/cli/output.d.ts +2 -0
- package/dist/src/cli/output.js +33 -6
- package/dist/src/cli/runtime.d.ts +35 -1
- package/dist/src/cli/runtime.js +125 -18
- package/dist/src/cli/types.d.ts +7 -0
- package/dist/src/cli.js +135 -28
- package/dist/src/client.d.ts +60 -0
- package/dist/src/client.js +237 -42
- package/dist/src/errors.d.ts +8 -2
- package/dist/src/errors.js +40 -0
- package/dist/src/index.d.ts +4 -3
- package/dist/src/index.js +2 -1
- package/dist/src/resources/api-services.d.ts +48 -6
- package/dist/src/resources/api-services.js +54 -8
- package/dist/src/resources/bundles.d.ts +51 -6
- package/dist/src/resources/bundles.js +39 -9
- package/dist/src/resources/code-envs.d.ts +25 -3
- package/dist/src/resources/code-envs.js +104 -2
- package/dist/src/resources/datasets.d.ts +20 -0
- package/dist/src/resources/datasets.js +232 -52
- package/dist/src/resources/jobs.d.ts +35 -10
- package/dist/src/resources/jobs.js +92 -17
- package/dist/src/resources/notebooks.d.ts +77 -7
- package/dist/src/resources/notebooks.js +143 -19
- package/dist/src/resources/project-git.d.ts +12 -0
- package/dist/src/resources/project-git.js +39 -8
- package/dist/src/resources/project-library.d.ts +122 -7
- package/dist/src/resources/project-library.js +494 -25
- package/dist/src/resources/projects.d.ts +5 -2
- package/dist/src/resources/projects.js +18 -2
- package/dist/src/resources/scenarios.d.ts +30 -0
- package/dist/src/resources/scenarios.js +73 -27
- package/dist/src/resources/sql.d.ts +6 -0
- package/dist/src/resources/sql.js +22 -2
- package/dist/src/resources/webapps.d.ts +35 -4
- package/dist/src/resources/webapps.js +54 -5
- package/dist/src/schemas.d.ts +2 -2
- package/dist/src/schemas.js +1 -1
- package/dist/src/skill.d.ts +9 -0
- package/dist/src/skill.js +37 -4
- package/dist/src/utils/flow-analysis.d.ts +53 -0
- package/dist/src/utils/flow-analysis.js +382 -0
- package/dist/src/utils/project-archive.d.ts +41 -2
- package/dist/src/utils/project-archive.js +159 -16
- package/package.json +4 -4
- package/packages/types/dist/index.d.ts +39 -4
- package/packages/types/dist/index.js +31 -2
- package/plugin.json +1 -1
- package/skills/dataiku-dss/SKILL.md +74 -47
package/dist/src/client.js
CHANGED
|
@@ -3,7 +3,7 @@ import { basename, } from "node:path";
|
|
|
3
3
|
import { getCACertificates, } from "node:tls";
|
|
4
4
|
import { Value, } from "@sinclair/typebox/value";
|
|
5
5
|
import { safeParseSchema, } from "./schemas.js";
|
|
6
|
-
import { classifyDataikuError, ClientValidationError, DataikuError, } from "./errors.js";
|
|
6
|
+
import { classifyDataikuError, ClientValidationError, DataikuError, NON_JSON_RESPONSE_MARKER, } from "./errors.js";
|
|
7
7
|
import { AnalysesResource, } from "./resources/analyses.js";
|
|
8
8
|
import { ApiDeployerResource, } from "./resources/api-deployer.js";
|
|
9
9
|
import { ApiServicesResource, } from "./resources/api-services.js";
|
|
@@ -47,6 +47,14 @@ const MAX_RETRY_ATTEMPTS_CAP = 10;
|
|
|
47
47
|
const BASE_DELAY_MS = 2_000;
|
|
48
48
|
const MAX_BACKOFF_DELAY_MS = 30_000;
|
|
49
49
|
const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
|
|
50
|
+
/**
|
|
51
|
+
* Default cap on bytes buffered from a single response body by the text/JSON
|
|
52
|
+
* consumers (getText, postText, parseJsonResponse). Bodies larger than this
|
|
53
|
+
* are rejected with a DataikuError after the stream is cancelled; raw
|
|
54
|
+
* streaming methods (stream, postStream) are unaffected.
|
|
55
|
+
*/
|
|
56
|
+
const DEFAULT_MAX_BUFFERED_BODY_BYTES = 50 * 1024 * 1024;
|
|
57
|
+
const RESPONSE_TOO_LARGE_STATUS_TEXT = "Response Too Large";
|
|
50
58
|
/* ------------------------------------------------------------------ */
|
|
51
59
|
/* Helpers */
|
|
52
60
|
/* ------------------------------------------------------------------ */
|
|
@@ -105,6 +113,43 @@ function trimToUtf8Boundary(bytes) {
|
|
|
105
113
|
return bytes;
|
|
106
114
|
return continuation + 1 < expected ? bytes.subarray(0, i) : bytes;
|
|
107
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Drop leading UTF-8 continuation bytes. A UTF-8 character never *starts*
|
|
118
|
+
* with a continuation byte, so any leading continuation bytes are the remains
|
|
119
|
+
* of a character split by a byte cut at the start of the retained range.
|
|
120
|
+
* Dropping them keeps the decoded text free of replacement characters.
|
|
121
|
+
*/
|
|
122
|
+
function trimFromUtf8BoundaryStart(bytes) {
|
|
123
|
+
let i = 0;
|
|
124
|
+
while (i < bytes.length && (bytes[i] & 0xC0) === 0x80) {
|
|
125
|
+
i++;
|
|
126
|
+
}
|
|
127
|
+
return i > 0 ? bytes.subarray(i) : bytes;
|
|
128
|
+
}
|
|
129
|
+
function buildBodyReadTimeoutError(timeoutMs) {
|
|
130
|
+
return new DataikuError(0, "Request Timeout", `Request timed out after ${timeoutMs}ms while reading the response body.`);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Read the next chunk of a response body under a hard deadline.
|
|
134
|
+
* When `remainingMs` elapses, the stream is cancelled and the caller's
|
|
135
|
+
* promise rejects with a DataikuError, so a stalled body cannot hang the
|
|
136
|
+
* buffered consumers after headers already arrived.
|
|
137
|
+
*/
|
|
138
|
+
async function readChunkWithDeadline(reader, remainingMs, timeoutMs) {
|
|
139
|
+
const { promise, resolve, reject, } = Promise.withResolvers();
|
|
140
|
+
const timer = setTimeout(() => {
|
|
141
|
+
void reader.cancel(buildBodyReadTimeoutError(timeoutMs)).catch(() => { });
|
|
142
|
+
reject(buildBodyReadTimeoutError(timeoutMs));
|
|
143
|
+
}, remainingMs);
|
|
144
|
+
reader.read().then((result) => {
|
|
145
|
+
clearTimeout(timer);
|
|
146
|
+
resolve(result);
|
|
147
|
+
}, (error) => {
|
|
148
|
+
clearTimeout(timer);
|
|
149
|
+
reject(error);
|
|
150
|
+
});
|
|
151
|
+
return promise;
|
|
152
|
+
}
|
|
108
153
|
function buildRetryMetadata(method, enabled, maxAttempts, attempts, delaysMs, timedOut) {
|
|
109
154
|
return {
|
|
110
155
|
method,
|
|
@@ -161,6 +206,7 @@ export class DataikuClient {
|
|
|
161
206
|
apiKey;
|
|
162
207
|
defaultProjectKey;
|
|
163
208
|
requestTimeoutMs;
|
|
209
|
+
maxResponseBodyBytes;
|
|
164
210
|
retryMaxAttempts;
|
|
165
211
|
verbose;
|
|
166
212
|
tlsOptions;
|
|
@@ -326,6 +372,7 @@ export class DataikuClient {
|
|
|
326
372
|
this.apiKey = apiKey;
|
|
327
373
|
this.defaultProjectKey = config?.projectKey?.trim() || undefined;
|
|
328
374
|
this.requestTimeoutMs = config?.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
375
|
+
this.maxResponseBodyBytes = config?.maxResponseBodyBytes ?? DEFAULT_MAX_BUFFERED_BODY_BYTES;
|
|
329
376
|
const rawMax = config?.retryMaxAttempts ?? DEFAULT_RETRY_MAX_ATTEMPTS;
|
|
330
377
|
this.retryMaxAttempts = Math.min(Math.max(1, rawMax), MAX_RETRY_ATTEMPTS_CAP);
|
|
331
378
|
this.verbose = config?.verbose === true;
|
|
@@ -344,6 +391,13 @@ export class DataikuClient {
|
|
|
344
391
|
getRequestTimeoutMs() {
|
|
345
392
|
return this.requestTimeoutMs;
|
|
346
393
|
}
|
|
394
|
+
/**
|
|
395
|
+
* The configured maximum number of bytes buffered from a single response
|
|
396
|
+
* body by the text/JSON consumer methods (default 50 MiB).
|
|
397
|
+
*/
|
|
398
|
+
getMaxResponseBodyBytes() {
|
|
399
|
+
return this.maxResponseBodyBytes;
|
|
400
|
+
}
|
|
347
401
|
/* ---- public: project key resolution ---- */
|
|
348
402
|
resolveProjectKey(paramValue) {
|
|
349
403
|
const pk = paramValue?.trim();
|
|
@@ -374,56 +428,50 @@ export class DataikuClient {
|
|
|
374
428
|
const data = await this.parseJsonResponse(res);
|
|
375
429
|
return { data, meta: this.responseMeta(res.headers), };
|
|
376
430
|
}
|
|
431
|
+
/**
|
|
432
|
+
* GET returning the entire text body. The body is buffered with a hard
|
|
433
|
+
* byte cap (`maxResponseBodyBytes`, default 50 MiB) and read under the
|
|
434
|
+
* request deadline: a response exceeding the cap throws a DataikuError
|
|
435
|
+
* instead of being silently truncated, and a stalled body times out.
|
|
436
|
+
*/
|
|
377
437
|
async getText(path) {
|
|
378
438
|
const res = await this.fetchWithRetry(`${this.baseUrl}${path}`, {
|
|
379
439
|
method: "GET",
|
|
380
440
|
headers: this.getAnyHeaders(),
|
|
381
441
|
});
|
|
382
|
-
|
|
442
|
+
const { text, truncated, } = await this.readBoundedBodyText(res, this.maxResponseBodyBytes);
|
|
443
|
+
if (truncated)
|
|
444
|
+
throw this.buildResponseTooLargeError(res, this.maxResponseBodyBytes);
|
|
445
|
+
return text;
|
|
383
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* GET returning at most the first `maxBytes` bytes of a text body.
|
|
449
|
+
* When the response exceeds the cap the stream is cancelled, only the
|
|
450
|
+
* collected prefix is returned and `truncated` is true. The read runs
|
|
451
|
+
* under the request deadline: a stalled body throws a DataikuError.
|
|
452
|
+
*/
|
|
384
453
|
async getTextLimited(path, maxBytes) {
|
|
385
454
|
const limit = Math.max(0, Math.floor(maxBytes));
|
|
386
455
|
const res = await this.fetchWithRetry(`${this.baseUrl}${path}`, {
|
|
387
456
|
method: "GET",
|
|
388
457
|
headers: this.getAnyHeaders(),
|
|
389
458
|
});
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
break;
|
|
407
|
-
}
|
|
408
|
-
chunks.push(value);
|
|
409
|
-
bytesRead += value.byteLength;
|
|
410
|
-
}
|
|
411
|
-
if (!truncated && bytesRead >= limit) {
|
|
412
|
-
// Buffer filled exactly on a chunk boundary; peek whether more data remains.
|
|
413
|
-
const { done, } = await reader.read();
|
|
414
|
-
if (!done)
|
|
415
|
-
truncated = true;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
finally {
|
|
419
|
-
await reader.cancel();
|
|
420
|
-
}
|
|
421
|
-
const collected = concatBytes(chunks, bytesRead);
|
|
422
|
-
// On truncation, drop any trailing partial UTF-8 character so the decoded
|
|
423
|
-
// text never re-encodes beyond the byte cap (a stream-flush would otherwise
|
|
424
|
-
// emit a 3-byte replacement char for a split multibyte sequence).
|
|
425
|
-
const usable = truncated ? trimToUtf8Boundary(collected) : collected;
|
|
426
|
-
return { text: new TextDecoder().decode(usable), truncated, };
|
|
459
|
+
return this.readBoundedBodyText(res, limit);
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* GET returning at most the last `maxBytes` bytes of a text body.
|
|
463
|
+
* When the response exceeds the cap, earlier bytes are discarded, only
|
|
464
|
+
* the tail is kept and `truncated` is true — so callers that need the end
|
|
465
|
+
* of a large document (e.g. job logs) stay bounded without losing the most
|
|
466
|
+
* recent content. The read runs under the request deadline.
|
|
467
|
+
*/
|
|
468
|
+
async getTextTailLimited(path, maxBytes) {
|
|
469
|
+
const limit = Math.max(0, Math.floor(maxBytes));
|
|
470
|
+
const res = await this.fetchWithRetry(`${this.baseUrl}${path}`, {
|
|
471
|
+
method: "GET",
|
|
472
|
+
headers: this.getAnyHeaders(),
|
|
473
|
+
});
|
|
474
|
+
return this.readBodyTextTail(res, limit);
|
|
427
475
|
}
|
|
428
476
|
/**
|
|
429
477
|
* POST with optional transient retry. Only opt in when repeating the request
|
|
@@ -442,13 +490,20 @@ export class DataikuClient {
|
|
|
442
490
|
}, retryMaxAttempts);
|
|
443
491
|
return this.parseJsonResponse(res);
|
|
444
492
|
}
|
|
493
|
+
/**
|
|
494
|
+
* POST returning the text body, under the same bounded buffering rules as
|
|
495
|
+
* {@link getText} (byte cap `maxResponseBodyBytes`, request deadline).
|
|
496
|
+
*/
|
|
445
497
|
async postText(path, body) {
|
|
446
498
|
const res = await this.fetchWithRetry(`${this.baseUrl}${path}`, {
|
|
447
499
|
method: "POST",
|
|
448
500
|
headers: this.getHeaders(),
|
|
449
501
|
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
450
502
|
});
|
|
451
|
-
|
|
503
|
+
const { text, truncated, } = await this.readBoundedBodyText(res, this.maxResponseBodyBytes);
|
|
504
|
+
if (truncated)
|
|
505
|
+
throw this.buildResponseTooLargeError(res, this.maxResponseBodyBytes);
|
|
506
|
+
return text;
|
|
452
507
|
}
|
|
453
508
|
async postStream(path, body) {
|
|
454
509
|
return this.fetchWithRetry(`${this.baseUrl}${path}`, {
|
|
@@ -571,7 +626,9 @@ export class DataikuClient {
|
|
|
571
626
|
return undefined;
|
|
572
627
|
}
|
|
573
628
|
async parseJsonResponse(res) {
|
|
574
|
-
const text = await res.
|
|
629
|
+
const { text, truncated, } = await this.readBoundedBodyText(res, this.maxResponseBodyBytes);
|
|
630
|
+
if (truncated)
|
|
631
|
+
throw this.buildResponseTooLargeError(res, this.maxResponseBodyBytes);
|
|
575
632
|
// SAFETY: Empty 2xx responses from DSS are surfaced to callers as undefined
|
|
576
633
|
// cast to T. This keeps existing call sites stable, but callers that rely on
|
|
577
634
|
// an object shape must guard explicitly before dereferencing the result.
|
|
@@ -582,9 +639,147 @@ export class DataikuClient {
|
|
|
582
639
|
}
|
|
583
640
|
catch {
|
|
584
641
|
const summary = text.length > 300 ? `${text.slice(0, 300)}…` : text;
|
|
585
|
-
throw new DataikuError(res.status, res.statusText || "Invalid JSON response",
|
|
642
|
+
throw new DataikuError(res.status, res.statusText || "Invalid JSON response", `${NON_JSON_RESPONSE_MARKER}: ${summary}`, undefined, this.requestIdFromHeaders(res.headers));
|
|
586
643
|
}
|
|
587
644
|
}
|
|
645
|
+
/* ---- private: bounded response body reading ---- */
|
|
646
|
+
/**
|
|
647
|
+
* Read at most `maxBytes` of a 2xx response body as UTF-8 text.
|
|
648
|
+
*
|
|
649
|
+
* The body is consumed with the request deadline still active (measured
|
|
650
|
+
* from the first read): a stalled body throws a DataikuError instead of
|
|
651
|
+
* hanging. When the stream yields more than the cap, the reader cancels the
|
|
652
|
+
* body and returns the collected prefix with `truncated: true`; truncated
|
|
653
|
+
* text is trimmed to a UTF-8 character boundary so it never decodes beyond
|
|
654
|
+
* the byte cap.
|
|
655
|
+
*/
|
|
656
|
+
async readBoundedBodyText(res, maxBytes) {
|
|
657
|
+
const limit = Math.max(0, Math.floor(maxBytes));
|
|
658
|
+
if (!res.body)
|
|
659
|
+
return { text: "", truncated: false, };
|
|
660
|
+
const reader = res.body.getReader();
|
|
661
|
+
const chunks = [];
|
|
662
|
+
let bytesRead = 0;
|
|
663
|
+
let truncated = false;
|
|
664
|
+
const startedAt = Date.now();
|
|
665
|
+
try {
|
|
666
|
+
while (bytesRead < limit) {
|
|
667
|
+
const remainingMs = this.requestTimeoutMs - (Date.now() - startedAt);
|
|
668
|
+
if (remainingMs <= 0)
|
|
669
|
+
throw buildBodyReadTimeoutError(this.requestTimeoutMs);
|
|
670
|
+
const { done, value, } = await readChunkWithDeadline(reader, remainingMs, this.requestTimeoutMs);
|
|
671
|
+
if (done)
|
|
672
|
+
break;
|
|
673
|
+
const room = limit - bytesRead;
|
|
674
|
+
if (value.byteLength > room) {
|
|
675
|
+
chunks.push(value.slice(0, room));
|
|
676
|
+
bytesRead += room;
|
|
677
|
+
truncated = true;
|
|
678
|
+
break;
|
|
679
|
+
}
|
|
680
|
+
chunks.push(value);
|
|
681
|
+
bytesRead += value.byteLength;
|
|
682
|
+
}
|
|
683
|
+
if (!truncated && bytesRead >= limit) {
|
|
684
|
+
// Buffer filled exactly on a chunk boundary; peek whether more data remains.
|
|
685
|
+
const remainingMs = this.requestTimeoutMs - (Date.now() - startedAt);
|
|
686
|
+
if (remainingMs <= 0)
|
|
687
|
+
throw buildBodyReadTimeoutError(this.requestTimeoutMs);
|
|
688
|
+
const { done, } = await readChunkWithDeadline(reader, remainingMs, this.requestTimeoutMs);
|
|
689
|
+
if (!done)
|
|
690
|
+
truncated = true;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
finally {
|
|
694
|
+
void reader.cancel().catch(() => { });
|
|
695
|
+
}
|
|
696
|
+
const collected = concatBytes(chunks, bytesRead);
|
|
697
|
+
// On truncation, drop any trailing partial UTF-8 character so the decoded
|
|
698
|
+
// text never re-encodes beyond the byte cap (a stream-flush would otherwise
|
|
699
|
+
// emit a 3-byte replacement char for a split multibyte sequence).
|
|
700
|
+
const usable = truncated ? trimToUtf8Boundary(collected) : collected;
|
|
701
|
+
return { text: new TextDecoder().decode(usable), truncated, };
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Read a 2xx response body keeping only the last `maxBytes` bytes.
|
|
705
|
+
* Earlier bytes are discarded as the stream advances, so memory stays
|
|
706
|
+
* bounded by the cap plus one chunk even for arbitrarily large bodies.
|
|
707
|
+
* Returns `truncated: true` when bytes had to be dropped. Bytes that fall
|
|
708
|
+
* in the middle of a UTF-8 character are dropped from both ends so the
|
|
709
|
+
* decoded text never contains a replacement character.
|
|
710
|
+
*/
|
|
711
|
+
async readBodyTextTail(res, maxBytes) {
|
|
712
|
+
const limit = Math.max(0, Math.floor(maxBytes));
|
|
713
|
+
if (!res.body)
|
|
714
|
+
return { text: "", truncated: false, };
|
|
715
|
+
const reader = res.body.getReader();
|
|
716
|
+
const ring = new Uint8Array(limit);
|
|
717
|
+
let writeOffset = 0;
|
|
718
|
+
let retainedBytes = 0;
|
|
719
|
+
let truncated = false;
|
|
720
|
+
const startedAt = Date.now();
|
|
721
|
+
try {
|
|
722
|
+
while (true) {
|
|
723
|
+
const remainingMs = this.requestTimeoutMs - (Date.now() - startedAt);
|
|
724
|
+
if (remainingMs <= 0)
|
|
725
|
+
throw buildBodyReadTimeoutError(this.requestTimeoutMs);
|
|
726
|
+
const { done, value, } = await readChunkWithDeadline(reader, remainingMs, this.requestTimeoutMs);
|
|
727
|
+
if (done)
|
|
728
|
+
break;
|
|
729
|
+
if (limit === 0) {
|
|
730
|
+
truncated = value.byteLength > 0;
|
|
731
|
+
if (truncated)
|
|
732
|
+
break;
|
|
733
|
+
continue;
|
|
734
|
+
}
|
|
735
|
+
if (value.byteLength >= limit) {
|
|
736
|
+
ring.set(value.subarray(value.byteLength - limit));
|
|
737
|
+
truncated = truncated || retainedBytes > 0 || value.byteLength > limit;
|
|
738
|
+
retainedBytes = limit;
|
|
739
|
+
writeOffset = 0;
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
742
|
+
const firstLength = Math.min(value.byteLength, limit - writeOffset);
|
|
743
|
+
ring.set(value.subarray(0, firstLength), writeOffset);
|
|
744
|
+
const remainingLength = value.byteLength - firstLength;
|
|
745
|
+
if (remainingLength > 0) {
|
|
746
|
+
ring.set(value.subarray(firstLength));
|
|
747
|
+
}
|
|
748
|
+
writeOffset = (writeOffset + value.byteLength) % limit;
|
|
749
|
+
truncated = truncated || retainedBytes + value.byteLength > limit;
|
|
750
|
+
retainedBytes = Math.min(limit, retainedBytes + value.byteLength);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
finally {
|
|
754
|
+
void reader.cancel().catch(() => { });
|
|
755
|
+
}
|
|
756
|
+
let collected;
|
|
757
|
+
if (retainedBytes === 0) {
|
|
758
|
+
collected = new Uint8Array(0);
|
|
759
|
+
}
|
|
760
|
+
else if (retainedBytes < limit) {
|
|
761
|
+
collected = ring.slice(0, retainedBytes);
|
|
762
|
+
}
|
|
763
|
+
else if (writeOffset === 0) {
|
|
764
|
+
collected = ring;
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
collected = new Uint8Array(retainedBytes);
|
|
768
|
+
const suffixLength = limit - writeOffset;
|
|
769
|
+
collected.set(ring.subarray(writeOffset));
|
|
770
|
+
collected.set(ring.subarray(0, writeOffset), suffixLength);
|
|
771
|
+
}
|
|
772
|
+
// A byte cut inside a multi-byte sequence can leave continuation bytes at
|
|
773
|
+
// the start (and possibly the end) of the tail; drop both so the decoded
|
|
774
|
+
// text never starts or ends with a U+FFFD replacement character.
|
|
775
|
+
const usable = truncated
|
|
776
|
+
? trimToUtf8Boundary(trimFromUtf8BoundaryStart(collected))
|
|
777
|
+
: collected;
|
|
778
|
+
return { text: new TextDecoder().decode(usable), truncated, };
|
|
779
|
+
}
|
|
780
|
+
buildResponseTooLargeError(res, limit) {
|
|
781
|
+
return new DataikuError(res.status, RESPONSE_TOO_LARGE_STATUS_TEXT, `Response body exceeded the ${limit}-byte limit; the body was cancelled after ${limit} bytes.`, undefined, this.requestIdFromHeaders(res.headers));
|
|
782
|
+
}
|
|
588
783
|
/* ---- private: retry loop ---- */
|
|
589
784
|
async fetchWithRetry(url, init, retryMaxAttempts) {
|
|
590
785
|
const method = (init.method ?? "GET").toUpperCase();
|
package/dist/src/errors.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export type DataikuErrorCategory = "not_found" | "forbidden" | "validation" | "transient" | "unknown";
|
|
2
|
-
export type StableErrorCode = "usage_error" | "unknown_flag" | "missing_required_arg" | "missing_required_flag" | "invalid_flag_value" | "conflicting_input_sources" | "invalid_enum" | "not_found" | "permission_denied" | "target_absence_unverifiable" | "validation_failed" | "transient" | "long_running_failure" | "command_result_failure" | "assertion_failed" | "ambiguous_outcome" | "internal_error";
|
|
1
|
+
export type DataikuErrorCategory = "not_found" | "forbidden" | "validation" | "transient" | "unexpected_response" | "unknown";
|
|
2
|
+
export type StableErrorCode = "usage_error" | "unknown_flag" | "missing_required_arg" | "missing_required_flag" | "invalid_flag_value" | "conflicting_input_sources" | "invalid_enum" | "not_found" | "permission_denied" | "target_absence_unverifiable" | "validation_failed" | "transient" | "long_running_failure" | "command_result_failure" | "assertion_failed" | "ambiguous_outcome" | "unexpected_response" | "internal_error";
|
|
3
3
|
export declare function dataikuErrorCode(category: DataikuErrorCategory): StableErrorCode;
|
|
4
4
|
export interface DataikuErrorTaxonomy {
|
|
5
5
|
category: DataikuErrorCategory;
|
|
@@ -26,6 +26,12 @@ export declare class ClientValidationError extends Error {
|
|
|
26
26
|
readonly details?: Record<string, unknown>;
|
|
27
27
|
constructor(message: string, code?: StableErrorCode, hint?: string, details?: Record<string, unknown>);
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Message prefix the client stamps on a 2xx body that is not JSON. The
|
|
31
|
+
* classifier recognizes exactly this prefix, so the parse-failure path and the
|
|
32
|
+
* taxonomy stay in sync as one contract.
|
|
33
|
+
*/
|
|
34
|
+
export declare const NON_JSON_RESPONSE_MARKER = "Expected JSON response body but got non-JSON content";
|
|
29
35
|
export declare function classifyDataikuError(status: number, body: string): DataikuErrorTaxonomy;
|
|
30
36
|
export declare class DataikuError extends Error {
|
|
31
37
|
status: number;
|
package/dist/src/errors.js
CHANGED
|
@@ -8,6 +8,8 @@ export function dataikuErrorCode(category) {
|
|
|
8
8
|
return "validation_failed";
|
|
9
9
|
case "transient":
|
|
10
10
|
return "transient";
|
|
11
|
+
case "unexpected_response":
|
|
12
|
+
return "unexpected_response";
|
|
11
13
|
case "unknown":
|
|
12
14
|
return "internal_error";
|
|
13
15
|
}
|
|
@@ -17,11 +19,21 @@ const CANONICAL_STATUS_TEXT = {
|
|
|
17
19
|
401: "Unauthorized",
|
|
18
20
|
403: "Forbidden",
|
|
19
21
|
404: "Not Found",
|
|
22
|
+
405: "Method Not Allowed",
|
|
23
|
+
406: "Not Acceptable",
|
|
20
24
|
408: "Request Timeout",
|
|
21
25
|
409: "Conflict",
|
|
26
|
+
410: "Gone",
|
|
27
|
+
412: "Precondition Failed",
|
|
28
|
+
413: "Payload Too Large",
|
|
29
|
+
415: "Unsupported Media Type",
|
|
30
|
+
416: "Range Not Satisfiable",
|
|
31
|
+
418: "I'm a Teapot",
|
|
22
32
|
422: "Unprocessable Entity",
|
|
23
33
|
425: "Too Early",
|
|
34
|
+
426: "Upgrade Required",
|
|
24
35
|
429: "Too Many Requests",
|
|
36
|
+
451: "Unavailable For Legal Reasons",
|
|
25
37
|
500: "Internal Server Error",
|
|
26
38
|
501: "Not Implemented",
|
|
27
39
|
502: "Bad Gateway",
|
|
@@ -43,6 +55,12 @@ export class ClientValidationError extends Error {
|
|
|
43
55
|
this.details = details;
|
|
44
56
|
}
|
|
45
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Message prefix the client stamps on a 2xx body that is not JSON. The
|
|
60
|
+
* classifier recognizes exactly this prefix, so the parse-failure path and the
|
|
61
|
+
* taxonomy stay in sync as one contract.
|
|
62
|
+
*/
|
|
63
|
+
export const NON_JSON_RESPONSE_MARKER = "Expected JSON response body but got non-JSON content";
|
|
46
64
|
const TLS_CERTIFICATE_HINT = "TLS certificate verification failed. Trust the DSS/corporate CA with --ca-cert PATH or NODE_EXTRA_CA_CERTS; use --insecure only for temporary troubleshooting.";
|
|
47
65
|
const BUSINESS_APPS_API_UNAVAILABLE_HINT = "Business Apps API is not available on this DSS instance. Use classic app commands or check DSS version/feature availability.";
|
|
48
66
|
const MAX_ERROR_SUMMARY_LENGTH = 200;
|
|
@@ -141,6 +159,18 @@ export function classifyDataikuError(status, body) {
|
|
|
141
159
|
retryHint: "Network/transport failure. Retry with backoff and verify DSS URL reachability.",
|
|
142
160
|
};
|
|
143
161
|
}
|
|
162
|
+
// A 2xx response carrying a non-JSON body is a response-contract violation,
|
|
163
|
+
// not a transport fault: HTTP succeeded, but an intermediary (proxy, SSO or
|
|
164
|
+
// login page, HTML gateway) answered in place of the DSS API. Only the client's
|
|
165
|
+
// own parse-failure marker produces this prefix.
|
|
166
|
+
if (status >= 200 && status < 300
|
|
167
|
+
&& lowerBody.startsWith(NON_JSON_RESPONSE_MARKER.toLowerCase())) {
|
|
168
|
+
return {
|
|
169
|
+
category: "unexpected_response",
|
|
170
|
+
retryable: false,
|
|
171
|
+
retryHint: "DSS returned a non-JSON response to a JSON API request (typically a proxy, gateway, or login page). Verify the DSS URL and that no intermediary serves HTML; do not retry unchanged.",
|
|
172
|
+
};
|
|
173
|
+
}
|
|
144
174
|
const isSqlInputConnectionMismatch = (status === 400 || status >= 500)
|
|
145
175
|
&& lowerBody.includes("s3 dataset")
|
|
146
176
|
&& lowerBody.includes("athena connection");
|
|
@@ -280,6 +310,16 @@ export function classifyDataikuError(status, body) {
|
|
|
280
310
|
retryHint: "Retry with exponential backoff. If it persists, check DSS availability and upstream proxies.",
|
|
281
311
|
};
|
|
282
312
|
}
|
|
313
|
+
// Any remaining HTTP error status is an API-contract mismatch: the endpoint,
|
|
314
|
+
// resource, or DSS feature/version does not support this request. It is
|
|
315
|
+
// non-retryable — retrying unchanged cannot succeed.
|
|
316
|
+
if (status >= 400) {
|
|
317
|
+
return {
|
|
318
|
+
category: "unexpected_response",
|
|
319
|
+
retryable: false,
|
|
320
|
+
retryHint: "The DSS API rejected the request with an unrecognized HTTP status. Verify the endpoint, resource, and DSS feature/version availability; do not retry unchanged.",
|
|
321
|
+
};
|
|
322
|
+
}
|
|
283
323
|
return {
|
|
284
324
|
category: "unknown",
|
|
285
325
|
retryable: false,
|
package/dist/src/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export { type FlowZoneItemInput, FlowZonesResource, } from "./resources/flow-zon
|
|
|
18
18
|
export { FoldersResource, } from "./resources/folders.js";
|
|
19
19
|
export { FuturesResource, } from "./resources/futures.js";
|
|
20
20
|
export { InsightsResource, } from "./resources/insights.js";
|
|
21
|
-
export { computeNextPollDelayMs, type JobBuildAndWaitOptions, type JobBuildOptions, type JobBuildTarget, type JobBuildTargetType, type JobLogFilter, type JobLogProgress, type JobLogSummary, JobsResource, parseJobLogProgress, } from "./resources/jobs.js";
|
|
21
|
+
export { computeNextPollDelayMs, type JobBuildAndWaitOptions, type JobBuildOptions, type JobBuildTarget, type JobBuildTargetType, type JobLogFilter, type JobLogProgress, type JobLogSummary, type JobLogUnavailableReason, JobsResource, type JobWaitOutcome, parseJobLogProgress, } from "./resources/jobs.js";
|
|
22
22
|
export { MeaningsResource, } from "./resources/meanings.js";
|
|
23
23
|
export { MetricsResource, } from "./resources/metrics.js";
|
|
24
24
|
export * from "./resources/ml-tasks.js";
|
|
@@ -37,10 +37,11 @@ export { VariablesResource, } from "./resources/variables.js";
|
|
|
37
37
|
export { WebappsResource, } from "./resources/webapps.js";
|
|
38
38
|
export { WikiResource, } from "./resources/wiki.js";
|
|
39
39
|
export { WorkspacesResource, } from "./resources/workspaces.js";
|
|
40
|
-
export { BuildModeSchema, CodeEnvActionResultSchema, CodeEnvCreateOptionsSchema, CodeEnvDetailsSchema, CodeEnvPackageListSchema, CodeEnvSetPackagesOptionsSchema, CodeEnvSummaryArraySchema, CodeEnvSummarySchema, CodeEnvUpdatePackagesOptionsSchema, CodeEnvUsageArraySchema, CodeEnvWaitOptionsSchema, ConnectionSummarySchema, DashboardDetailsSchema, DashboardSummaryArraySchema, DashboardSummarySchema, DataQualityComputeResultSchema, DataQualityProjectStatusSchema, DataQualityRuleArraySchema, DataQualityRuleResultArraySchema, DataQualityRuleResultSchema, DataQualityRuleSchema, DataQualityRulesSchema, DataQualityStatusByPartitionSchema, DataQualityStatusSchema, DataQualityTimelineEntrySchema, DataQualityTimelineSchema, DatasetCreateOptionsSchema, DatasetDetailsSchema, DatasetSchemaSchema, DatasetSummaryArraySchema, DatasetSummarySchema, FlowMapOptionsSchema, FlowZoneArraySchema, FlowZoneCreateOptionsSchema, FlowZoneItemSchema, FlowZoneObjectTypeSchema, FlowZonePositionSchema, FlowZoneSchema, FlowZoneUpdateOptionsSchema, FolderCreateOptionsSchema, FolderDetailsSchema, FolderItemArraySchema, FolderItemSchema, FolderSummaryArraySchema, FolderSummarySchema, FutureStateSchema, FutureWaitResultSchema, InsightDetailsSchema, InsightSummaryArraySchema, InsightSummarySchema, JobSummaryArraySchema, JobSummarySchema, JobWaitResultSchema, JupyterCellSchema, JupyterNotebookContentSchema, JupyterNotebookSummaryArraySchema, JupyterNotebookSummarySchema, NotebookSessionArraySchema, NotebookSessionSchema, parseSchema, ProjectDetailsSchema, ProjectGitActionResultSchema, ProjectGitDiffResultSchema, ProjectGitFutureResponseSchema, ProjectGitFutureStateSchema, ProjectGitLibrariesSchema, ProjectGitLibrarySchema, ProjectGitLogResultSchema, ProjectGitRemoteSchema, ProjectGitStatusSchema, ProjectGitTagSchema, ProjectGitTagsSchema, ProjectMetadataSchema, ProjectSummaryArraySchema, ProjectSummarySchema, ProjectVariablesSchema, RecipeCreateOptionsSchema, RecipeCreateResultSchema, RecipeDetailsSchema, RecipeSummaryArraySchema, RecipeSummarySchema, safeParseSchema, ScenarioDetailsSchema, ScenarioStatusSchema, ScenarioStepRunSchema, ScenarioSummaryArraySchema, ScenarioSummarySchema, ScenarioWaitResultSchema, SqlNotebookCellSchema, SqlNotebookContentSchema, SqlNotebookSummaryArraySchema, SqlNotebookSummarySchema, SqlQueryResponseSchema, SqlQueryResultSchema, SqlQuerySchemaSchema, WikiArticleDataArraySchema, WikiArticleDataSchema, WikiArticleMetadataSchema, WikiSettingsSchema, WikiTaxonomyNodeSchema, } from "./schemas.js";
|
|
40
|
+
export { BuildModeSchema, CodeEnvActionResultSchema, CodeEnvCreateOptionsSchema, CodeEnvDetailsSchema, CodeEnvGetLogOptionsSchema, CodeEnvLogResultSchema, CodeEnvLogSummaryArraySchema, CodeEnvLogSummarySchema, CodeEnvPackageListSchema, CodeEnvSetPackagesOptionsSchema, CodeEnvSummaryArraySchema, CodeEnvSummarySchema, CodeEnvUpdateImagesOptionsSchema, CodeEnvUpdatePackagesOptionsSchema, CodeEnvUsageArraySchema, CodeEnvVersionForProjectSchema, CodeEnvWaitOptionsSchema, ConnectionSummarySchema, DashboardDetailsSchema, DashboardSummaryArraySchema, DashboardSummarySchema, DataQualityComputeResultSchema, DataQualityProjectStatusSchema, DataQualityRuleArraySchema, DataQualityRuleResultArraySchema, DataQualityRuleResultSchema, DataQualityRuleSchema, DataQualityRulesSchema, DataQualityStatusByPartitionSchema, DataQualityStatusSchema, DataQualityTimelineEntrySchema, DataQualityTimelineSchema, DatasetCreateOptionsSchema, DatasetDetailsSchema, DatasetSchemaSchema, DatasetSummaryArraySchema, DatasetSummarySchema, FlowMapOptionsSchema, FlowZoneArraySchema, FlowZoneCreateOptionsSchema, FlowZoneItemSchema, FlowZoneObjectTypeSchema, FlowZonePositionSchema, FlowZoneSchema, FlowZoneUpdateOptionsSchema, FolderCreateOptionsSchema, FolderDetailsSchema, FolderItemArraySchema, FolderItemSchema, FolderSummaryArraySchema, FolderSummarySchema, FutureStateSchema, FutureWaitResultSchema, InsightDetailsSchema, InsightSummaryArraySchema, InsightSummarySchema, JobSummaryArraySchema, JobSummarySchema, JobWaitResultSchema, JupyterCellSchema, JupyterNotebookContentSchema, JupyterNotebookSummaryArraySchema, JupyterNotebookSummarySchema, NotebookSessionArraySchema, NotebookSessionSchema, parseSchema, ProjectDetailsSchema, ProjectGitActionResultSchema, ProjectGitDiffResultSchema, ProjectGitFutureResponseSchema, ProjectGitFutureStateSchema, ProjectGitLibrariesSchema, ProjectGitLibrarySchema, ProjectGitLogResultSchema, ProjectGitRemoteSchema, ProjectGitStatusSchema, ProjectGitTagSchema, ProjectGitTagsSchema, ProjectMetadataSchema, ProjectSummaryArraySchema, ProjectSummarySchema, ProjectVariablesSchema, RecipeCreateOptionsSchema, RecipeCreateResultSchema, RecipeDetailsSchema, RecipeSummaryArraySchema, RecipeSummarySchema, safeParseSchema, ScenarioDetailsSchema, ScenarioStatusSchema, ScenarioStepRunSchema, ScenarioSummaryArraySchema, ScenarioSummarySchema, ScenarioWaitResultSchema, SqlNotebookCellSchema, SqlNotebookContentSchema, SqlNotebookHistorySchema, SqlNotebookSummaryArraySchema, SqlNotebookSummarySchema, SqlQueryResponseSchema, SqlQueryResultSchema, SqlQuerySchemaSchema, WikiArticleDataArraySchema, WikiArticleDataSchema, WikiArticleMetadataSchema, WikiSettingsSchema, WikiTaxonomyNodeSchema, } from "./schemas.js";
|
|
41
41
|
export type { SafeParseResult, } from "./schemas.js";
|
|
42
|
-
export type { BuildMode, CodeEnvActionResult, CodeEnvCreateOptions, CodeEnvDetails, CodeEnvPackageList, CodeEnvSetPackagesOptions, CodeEnvSummary, CodeEnvUpdatePackagesOptions, CodeEnvUsage, CodeEnvWaitOptions, ConnectionSummary, DashboardDetails, DashboardSummary, DataQualityComputeResult, DataQualityProjectStatus, DataQualityRule, DataQualityRuleResult, DataQualityRules, DataQualityStatus, DataQualityStatusByPartition, DataQualityTimeline, DataQualityTimelineEntry, DatasetCreateOptions, DatasetDetails, DatasetSchema, DatasetSummary, FlowMapOptions, FlowZone, FlowZoneCreateOptions, FlowZoneItem, FlowZoneObjectType, FlowZonePosition, FlowZoneUpdateOptions, FolderCreateOptions, FolderDetails, FolderItem, FolderSummary, FutureState, FutureWaitResult, InsightDetails, InsightSummary, JobSummary, JobWaitResult, JupyterCell, JupyterNotebookContent, JupyterNotebookSummary, NotebookSession, ProjectDetails, ProjectGitActionResult, ProjectGitDiffResult, ProjectGitFutureResponse, ProjectGitFutureState, ProjectGitLibraries, ProjectGitLibrary, ProjectGitLogResult, ProjectGitRemote, ProjectGitStatus, ProjectGitTag, ProjectGitTags, ProjectMetadata, ProjectSummary, ProjectVariables, RecipeCreateOptions, RecipeCreateResult, RecipeDetails, RecipeSummary, ScenarioDetails, ScenarioStatus, ScenarioStepRun, ScenarioSummary, ScenarioWaitResult, SqlNotebookCell, SqlNotebookContent, SqlNotebookSummary, SqlQueryResponse, SqlQueryResult, SqlQuerySchema, WikiArticleData, WikiArticleMetadata, WikiSettings, WikiTaxonomyNode, } from "./schemas.js";
|
|
42
|
+
export type { BuildMode, CodeEnvActionResult, CodeEnvCreateOptions, CodeEnvDetails, CodeEnvGetLogOptions, CodeEnvLogResult, CodeEnvLogSummary, CodeEnvPackageList, CodeEnvSetPackagesOptions, CodeEnvSummary, CodeEnvUpdateImagesOptions, CodeEnvUpdatePackagesOptions, CodeEnvUsage, CodeEnvVersionForProject, CodeEnvWaitOptions, ConnectionSummary, DashboardDetails, DashboardSummary, DataQualityComputeResult, DataQualityProjectStatus, DataQualityRule, DataQualityRuleResult, DataQualityRules, DataQualityStatus, DataQualityStatusByPartition, DataQualityTimeline, DataQualityTimelineEntry, DatasetCreateOptions, DatasetDetails, DatasetSchema, DatasetSummary, FlowMapOptions, FlowZone, FlowZoneCreateOptions, FlowZoneItem, FlowZoneObjectType, FlowZonePosition, FlowZoneUpdateOptions, FolderCreateOptions, FolderDetails, FolderItem, FolderSummary, FutureState, FutureWaitResult, InsightDetails, InsightSummary, JobSummary, JobWaitResult, JupyterCell, JupyterNotebookContent, JupyterNotebookSummary, NotebookSession, ProjectDetails, ProjectGitActionResult, ProjectGitDiffResult, ProjectGitFutureResponse, ProjectGitFutureState, ProjectGitLibraries, ProjectGitLibrary, ProjectGitLogResult, ProjectGitRemote, ProjectGitStatus, ProjectGitTag, ProjectGitTags, ProjectMetadata, ProjectSummary, ProjectVariables, RecipeCreateOptions, RecipeCreateResult, RecipeDetails, RecipeSummary, ScenarioDetails, ScenarioStatus, ScenarioStepRun, ScenarioSummary, ScenarioWaitResult, SqlNotebookCell, SqlNotebookContent, SqlNotebookSummary, SqlQueryResponse, SqlQueryResult, SqlQuerySchema, WikiArticleData, WikiArticleMetadata, WikiSettings, WikiTaxonomyNode, } from "./schemas.js";
|
|
43
43
|
export { deepMerge, } from "./utils/deep-merge.js";
|
|
44
|
+
export { type AnalyzedFlowMap, type AnalyzedFlowNode, analyzeFlowMap, type FlowMapComponent, type FlowMapDiagnostic, type FlowMapRendering, type FlowMapZone, type FlowRenderFormat, flowTopologyFingerprint, renderFlowMap, } from "./utils/flow-analysis.js";
|
|
44
45
|
export { type NormalizedFlowEdge, type NormalizedFlowMap, type NormalizedFlowNode, normalizeFlowGraph, } from "./utils/flow-map.js";
|
|
45
46
|
export * from "./utils/project-archive.js";
|
|
46
47
|
export { sanitizeFileName, } from "./utils/sanitize.js";
|
package/dist/src/index.js
CHANGED
|
@@ -42,9 +42,10 @@ export { WebappsResource, } from "./resources/webapps.js";
|
|
|
42
42
|
export { WikiResource, } from "./resources/wiki.js";
|
|
43
43
|
export { WorkspacesResource, } from "./resources/workspaces.js";
|
|
44
44
|
// Schemas (TypeBox schema objects for runtime validation)
|
|
45
|
-
export { BuildModeSchema, CodeEnvActionResultSchema, CodeEnvCreateOptionsSchema, CodeEnvDetailsSchema, CodeEnvPackageListSchema, CodeEnvSetPackagesOptionsSchema, CodeEnvSummaryArraySchema, CodeEnvSummarySchema, CodeEnvUpdatePackagesOptionsSchema, CodeEnvUsageArraySchema, CodeEnvWaitOptionsSchema, ConnectionSummarySchema, DashboardDetailsSchema, DashboardSummaryArraySchema, DashboardSummarySchema, DataQualityComputeResultSchema, DataQualityProjectStatusSchema, DataQualityRuleArraySchema, DataQualityRuleResultArraySchema, DataQualityRuleResultSchema, DataQualityRuleSchema, DataQualityRulesSchema, DataQualityStatusByPartitionSchema, DataQualityStatusSchema, DataQualityTimelineEntrySchema, DataQualityTimelineSchema, DatasetCreateOptionsSchema, DatasetDetailsSchema, DatasetSchemaSchema, DatasetSummaryArraySchema, DatasetSummarySchema, FlowMapOptionsSchema, FlowZoneArraySchema, FlowZoneCreateOptionsSchema, FlowZoneItemSchema, FlowZoneObjectTypeSchema, FlowZonePositionSchema, FlowZoneSchema, FlowZoneUpdateOptionsSchema, FolderCreateOptionsSchema, FolderDetailsSchema, FolderItemArraySchema, FolderItemSchema, FolderSummaryArraySchema, FolderSummarySchema, FutureStateSchema, FutureWaitResultSchema, InsightDetailsSchema, InsightSummaryArraySchema, InsightSummarySchema, JobSummaryArraySchema, JobSummarySchema, JobWaitResultSchema, JupyterCellSchema, JupyterNotebookContentSchema, JupyterNotebookSummaryArraySchema, JupyterNotebookSummarySchema, NotebookSessionArraySchema, NotebookSessionSchema, parseSchema, ProjectDetailsSchema, ProjectGitActionResultSchema, ProjectGitDiffResultSchema, ProjectGitFutureResponseSchema, ProjectGitFutureStateSchema, ProjectGitLibrariesSchema, ProjectGitLibrarySchema, ProjectGitLogResultSchema, ProjectGitRemoteSchema, ProjectGitStatusSchema, ProjectGitTagSchema, ProjectGitTagsSchema, ProjectMetadataSchema, ProjectSummaryArraySchema, ProjectSummarySchema, ProjectVariablesSchema, RecipeCreateOptionsSchema, RecipeCreateResultSchema, RecipeDetailsSchema, RecipeSummaryArraySchema, RecipeSummarySchema, safeParseSchema, ScenarioDetailsSchema, ScenarioStatusSchema, ScenarioStepRunSchema, ScenarioSummaryArraySchema, ScenarioSummarySchema, ScenarioWaitResultSchema, SqlNotebookCellSchema, SqlNotebookContentSchema, SqlNotebookSummaryArraySchema, SqlNotebookSummarySchema, SqlQueryResponseSchema, SqlQueryResultSchema, SqlQuerySchemaSchema, WikiArticleDataArraySchema, WikiArticleDataSchema, WikiArticleMetadataSchema, WikiSettingsSchema, WikiTaxonomyNodeSchema, } from "./schemas.js";
|
|
45
|
+
export { BuildModeSchema, CodeEnvActionResultSchema, CodeEnvCreateOptionsSchema, CodeEnvDetailsSchema, CodeEnvGetLogOptionsSchema, CodeEnvLogResultSchema, CodeEnvLogSummaryArraySchema, CodeEnvLogSummarySchema, CodeEnvPackageListSchema, CodeEnvSetPackagesOptionsSchema, CodeEnvSummaryArraySchema, CodeEnvSummarySchema, CodeEnvUpdateImagesOptionsSchema, CodeEnvUpdatePackagesOptionsSchema, CodeEnvUsageArraySchema, CodeEnvVersionForProjectSchema, CodeEnvWaitOptionsSchema, ConnectionSummarySchema, DashboardDetailsSchema, DashboardSummaryArraySchema, DashboardSummarySchema, DataQualityComputeResultSchema, DataQualityProjectStatusSchema, DataQualityRuleArraySchema, DataQualityRuleResultArraySchema, DataQualityRuleResultSchema, DataQualityRuleSchema, DataQualityRulesSchema, DataQualityStatusByPartitionSchema, DataQualityStatusSchema, DataQualityTimelineEntrySchema, DataQualityTimelineSchema, DatasetCreateOptionsSchema, DatasetDetailsSchema, DatasetSchemaSchema, DatasetSummaryArraySchema, DatasetSummarySchema, FlowMapOptionsSchema, FlowZoneArraySchema, FlowZoneCreateOptionsSchema, FlowZoneItemSchema, FlowZoneObjectTypeSchema, FlowZonePositionSchema, FlowZoneSchema, FlowZoneUpdateOptionsSchema, FolderCreateOptionsSchema, FolderDetailsSchema, FolderItemArraySchema, FolderItemSchema, FolderSummaryArraySchema, FolderSummarySchema, FutureStateSchema, FutureWaitResultSchema, InsightDetailsSchema, InsightSummaryArraySchema, InsightSummarySchema, JobSummaryArraySchema, JobSummarySchema, JobWaitResultSchema, JupyterCellSchema, JupyterNotebookContentSchema, JupyterNotebookSummaryArraySchema, JupyterNotebookSummarySchema, NotebookSessionArraySchema, NotebookSessionSchema, parseSchema, ProjectDetailsSchema, ProjectGitActionResultSchema, ProjectGitDiffResultSchema, ProjectGitFutureResponseSchema, ProjectGitFutureStateSchema, ProjectGitLibrariesSchema, ProjectGitLibrarySchema, ProjectGitLogResultSchema, ProjectGitRemoteSchema, ProjectGitStatusSchema, ProjectGitTagSchema, ProjectGitTagsSchema, ProjectMetadataSchema, ProjectSummaryArraySchema, ProjectSummarySchema, ProjectVariablesSchema, RecipeCreateOptionsSchema, RecipeCreateResultSchema, RecipeDetailsSchema, RecipeSummaryArraySchema, RecipeSummarySchema, safeParseSchema, ScenarioDetailsSchema, ScenarioStatusSchema, ScenarioStepRunSchema, ScenarioSummaryArraySchema, ScenarioSummarySchema, ScenarioWaitResultSchema, SqlNotebookCellSchema, SqlNotebookContentSchema, SqlNotebookHistorySchema, SqlNotebookSummaryArraySchema, SqlNotebookSummarySchema, SqlQueryResponseSchema, SqlQueryResultSchema, SqlQuerySchemaSchema, WikiArticleDataArraySchema, WikiArticleDataSchema, WikiArticleMetadataSchema, WikiSettingsSchema, WikiTaxonomyNodeSchema, } from "./schemas.js";
|
|
46
46
|
// Utilities
|
|
47
47
|
export { deepMerge, } from "./utils/deep-merge.js";
|
|
48
|
+
export { analyzeFlowMap, flowTopologyFingerprint, renderFlowMap, } from "./utils/flow-analysis.js";
|
|
48
49
|
export { normalizeFlowGraph, } from "./utils/flow-map.js";
|
|
49
50
|
export * from "./utils/project-archive.js";
|
|
50
51
|
export { sanitizeFileName, } from "./utils/sanitize.js";
|
|
@@ -9,6 +9,32 @@ export interface ApiServicePackageListItem extends Record<string, unknown> {
|
|
|
9
9
|
packageId?: string;
|
|
10
10
|
serviceId?: string;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* 64-hex SHA-256 hash of the service settings as last fetched, used as a
|
|
14
|
+
* non-atomic stale-read guard: the write is refused when the settings already
|
|
15
|
+
* differ at the verification read. DSS exposes no conditional write, so a
|
|
16
|
+
* writer committing between that read and the PUT is still not detected.
|
|
17
|
+
*/
|
|
18
|
+
export interface ApiServiceSaveOptions {
|
|
19
|
+
expectHash?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Optional, documented parameters of the package-generation endpoint. */
|
|
22
|
+
export interface ApiServiceCreatePackageOptions {
|
|
23
|
+
releaseNotes?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Optional, documented parameter of the package-publish endpoint: the id of
|
|
27
|
+
* the published service on the API Deployer where the package is deployed
|
|
28
|
+
* (defaults to the service's own id server-side).
|
|
29
|
+
*/
|
|
30
|
+
export interface ApiServicePublishOptions {
|
|
31
|
+
publishedServiceId?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface ApiServicePackageListItem extends Record<string, unknown> {
|
|
34
|
+
id?: string;
|
|
35
|
+
packageId?: string;
|
|
36
|
+
serviceId?: string;
|
|
37
|
+
}
|
|
12
38
|
export type ApiServiceActionResult = Record<string, unknown> | undefined;
|
|
13
39
|
export declare class ApiServicesResource extends BaseResource {
|
|
14
40
|
/** List API services in a project. */
|
|
@@ -17,24 +43,40 @@ export declare class ApiServicesResource extends BaseResource {
|
|
|
17
43
|
create(serviceId: string, projectKey?: string): Promise<ApiServiceActionResult>;
|
|
18
44
|
/** Get API service settings, including endpoint definitions. */
|
|
19
45
|
getSettings(serviceId: string, projectKey?: string): Promise<Record<string, unknown>>;
|
|
20
|
-
/**
|
|
21
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Save API service settings with explicit replacement semantics: the body
|
|
48
|
+
* is the complete settings object (fetched via get-settings) and is PUT
|
|
49
|
+
* as-is. With `expectHash` armed, the settings are read first and their
|
|
50
|
+
* stable hash must match, or the write is refused before any PUT.
|
|
51
|
+
*/
|
|
52
|
+
saveSettings(serviceId: string, body: Record<string, unknown>, projectKey?: string, options?: ApiServiceSaveOptions): Promise<ApiServiceActionResult>;
|
|
22
53
|
/** Add a standard prediction endpoint backed by a saved model. */
|
|
23
54
|
addPredictionEndpoint(serviceId: string, endpointId: string, savedModelId: string, projectKey?: string): Promise<ApiServiceActionResult>;
|
|
24
55
|
/** List deployable packages for an API service. */
|
|
25
56
|
listPackages(serviceId: string, projectKey?: string): Promise<ApiServicePackageListItem[]>;
|
|
26
57
|
/** Get an API service package summary. */
|
|
27
58
|
getPackageSummary(serviceId: string, packageId: string, projectKey?: string): Promise<Record<string, unknown>>;
|
|
28
|
-
/**
|
|
29
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Create a deployable package from the current service state. The
|
|
61
|
+
* documented optional `releaseNotes` parameter is forwarded as the
|
|
62
|
+
* `releaseNotes` query parameter when provided.
|
|
63
|
+
*/
|
|
64
|
+
createPackage(serviceId: string, packageId: string, projectKey?: string, options?: ApiServiceCreatePackageOptions): Promise<{
|
|
30
65
|
message: string;
|
|
31
66
|
}>;
|
|
32
67
|
/** Delete an API service package. */
|
|
33
68
|
deletePackage(serviceId: string, packageId: string, projectKey?: string): Promise<void>;
|
|
34
69
|
/** Download an API service package archive. */
|
|
35
70
|
downloadPackageArchive(serviceId: string, packageId: string, projectKey?: string): Promise<Response>;
|
|
36
|
-
/**
|
|
37
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Publish an API service package to the API Deployer. The documented
|
|
73
|
+
* optional `publishedServiceId` parameter selects the published service
|
|
74
|
+
* the package is deployed to (a new published service is created when no
|
|
75
|
+
* match exists; when omitted, the server falls back to the service's own
|
|
76
|
+
* id). It is forwarded as the `publishedServiceId` query parameter when
|
|
77
|
+
* provided.
|
|
78
|
+
*/
|
|
79
|
+
publishPackage(serviceId: string, packageId: string, projectKey?: string, options?: ApiServicePublishOptions): Promise<ApiServiceActionResult>;
|
|
38
80
|
private servicePath;
|
|
39
81
|
private packagePath;
|
|
40
82
|
}
|