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.
Files changed (79) hide show
  1. package/README.md +132 -17
  2. package/dist/build-metadata.json +1 -1
  3. package/dist/packages/types/src/index.d.ts +39 -4
  4. package/dist/packages/types/src/index.js +31 -2
  5. package/dist/src/cli/commands/api-service.js +62 -16
  6. package/dist/src/cli/commands/bundle.js +49 -15
  7. package/dist/src/cli/commands/code-env.js +210 -49
  8. package/dist/src/cli/commands/code.d.ts +19 -0
  9. package/dist/src/cli/commands/code.js +87 -15
  10. package/dist/src/cli/commands/dataset.js +8 -3
  11. package/dist/src/cli/commands/flow-zone.js +33 -5
  12. package/dist/src/cli/commands/notebook.js +72 -41
  13. package/dist/src/cli/commands/project-git.js +8 -5
  14. package/dist/src/cli/commands/project-library.d.ts +21 -0
  15. package/dist/src/cli/commands/project-library.js +121 -50
  16. package/dist/src/cli/commands/project.js +16 -2
  17. package/dist/src/cli/commands/recipe.js +37 -12
  18. package/dist/src/cli/commands/sql.d.ts +10 -0
  19. package/dist/src/cli/commands/sql.js +39 -17
  20. package/dist/src/cli/commands/webapp.js +67 -13
  21. package/dist/src/cli/contract.d.ts +15 -0
  22. package/dist/src/cli/contract.js +870 -107
  23. package/dist/src/cli/env.d.ts +9 -0
  24. package/dist/src/cli/env.js +20 -2
  25. package/dist/src/cli/flags.js +9 -0
  26. package/dist/src/cli/helpers/cleanup.js +104 -3
  27. package/dist/src/cli/helpers/flow-zone.d.ts +3 -0
  28. package/dist/src/cli/helpers/flow-zone.js +33 -3
  29. package/dist/src/cli/helpers/recipe.d.ts +20 -0
  30. package/dist/src/cli/helpers/recipe.js +158 -3
  31. package/dist/src/cli/output.d.ts +2 -0
  32. package/dist/src/cli/output.js +33 -6
  33. package/dist/src/cli/runtime.d.ts +35 -1
  34. package/dist/src/cli/runtime.js +125 -18
  35. package/dist/src/cli/types.d.ts +7 -0
  36. package/dist/src/cli.js +135 -28
  37. package/dist/src/client.d.ts +60 -0
  38. package/dist/src/client.js +237 -42
  39. package/dist/src/errors.d.ts +8 -2
  40. package/dist/src/errors.js +40 -0
  41. package/dist/src/index.d.ts +4 -3
  42. package/dist/src/index.js +2 -1
  43. package/dist/src/resources/api-services.d.ts +48 -6
  44. package/dist/src/resources/api-services.js +54 -8
  45. package/dist/src/resources/bundles.d.ts +51 -6
  46. package/dist/src/resources/bundles.js +39 -9
  47. package/dist/src/resources/code-envs.d.ts +25 -3
  48. package/dist/src/resources/code-envs.js +104 -2
  49. package/dist/src/resources/datasets.d.ts +20 -0
  50. package/dist/src/resources/datasets.js +232 -52
  51. package/dist/src/resources/jobs.d.ts +35 -10
  52. package/dist/src/resources/jobs.js +92 -17
  53. package/dist/src/resources/notebooks.d.ts +77 -7
  54. package/dist/src/resources/notebooks.js +143 -19
  55. package/dist/src/resources/project-git.d.ts +12 -0
  56. package/dist/src/resources/project-git.js +39 -8
  57. package/dist/src/resources/project-library.d.ts +122 -7
  58. package/dist/src/resources/project-library.js +494 -25
  59. package/dist/src/resources/projects.d.ts +5 -2
  60. package/dist/src/resources/projects.js +18 -2
  61. package/dist/src/resources/scenarios.d.ts +30 -0
  62. package/dist/src/resources/scenarios.js +73 -27
  63. package/dist/src/resources/sql.d.ts +6 -0
  64. package/dist/src/resources/sql.js +22 -2
  65. package/dist/src/resources/webapps.d.ts +35 -4
  66. package/dist/src/resources/webapps.js +54 -5
  67. package/dist/src/schemas.d.ts +2 -2
  68. package/dist/src/schemas.js +1 -1
  69. package/dist/src/skill.d.ts +9 -0
  70. package/dist/src/skill.js +37 -4
  71. package/dist/src/utils/flow-analysis.d.ts +53 -0
  72. package/dist/src/utils/flow-analysis.js +382 -0
  73. package/dist/src/utils/project-archive.d.ts +41 -2
  74. package/dist/src/utils/project-archive.js +159 -16
  75. package/package.json +4 -4
  76. package/packages/types/dist/index.d.ts +39 -4
  77. package/packages/types/dist/index.js +31 -2
  78. package/plugin.json +1 -1
  79. package/skills/dataiku-dss/SKILL.md +74 -47
@@ -1,4 +1,21 @@
1
+ import { ClientValidationError, } from "../errors.js";
2
+ import { stableHash, } from "../utils/stable-hash.js";
1
3
  import { BaseResource, } from "./base.js";
4
+ const EXPECT_HASH_PATTERN = /^[0-9a-fA-F]{64}$/;
5
+ function assertExpectedSettingsHash(serviceId, expectHash, current, projectKey) {
6
+ if (!EXPECT_HASH_PATTERN.test(expectHash)) {
7
+ throw new ClientValidationError("Expected API service settings hash must be a 64-character SHA-256 hex digest.", "validation_failed", "Use the hash value returned by a previous read.", { projectKey, serviceId, });
8
+ }
9
+ const actual = stableHash(current);
10
+ if (actual !== expectHash.toLowerCase()) {
11
+ throw new ClientValidationError(`The API service ${JSON.stringify(serviceId)} changed since it was read.`, "validation_failed", "Re-read the service settings and retry with the current hash value.", {
12
+ projectKey,
13
+ serviceId,
14
+ expectedHash: expectHash.toLowerCase(),
15
+ actualHash: actual,
16
+ });
17
+ }
18
+ }
2
19
  export class ApiServicesResource extends BaseResource {
3
20
  /** List API services in a project. */
4
21
  async list(projectKey) {
@@ -12,8 +29,17 @@ export class ApiServicesResource extends BaseResource {
12
29
  async getSettings(serviceId, projectKey) {
13
30
  return this.client.get(`${this.servicePath(serviceId, projectKey)}/settings`);
14
31
  }
15
- /** Save API service settings. */
16
- async saveSettings(serviceId, body, projectKey) {
32
+ /**
33
+ * Save API service settings with explicit replacement semantics: the body
34
+ * is the complete settings object (fetched via get-settings) and is PUT
35
+ * as-is. With `expectHash` armed, the settings are read first and their
36
+ * stable hash must match, or the write is refused before any PUT.
37
+ */
38
+ async saveSettings(serviceId, body, projectKey, options = {}) {
39
+ if (options.expectHash !== undefined) {
40
+ const current = await this.getSettings(serviceId, projectKey);
41
+ assertExpectedSettingsHash(serviceId, options.expectHash, current, projectKey);
42
+ }
17
43
  return this.client.put(`${this.servicePath(serviceId, projectKey)}/settings`, body);
18
44
  }
19
45
  /** Add a standard prediction endpoint backed by a saved model. */
@@ -35,9 +61,17 @@ export class ApiServicesResource extends BaseResource {
35
61
  async getPackageSummary(serviceId, packageId, projectKey) {
36
62
  return this.client.get(`${this.packagePath(serviceId, packageId, projectKey)}/summary`);
37
63
  }
38
- /** Create a deployable package from the current service state. */
39
- async createPackage(serviceId, packageId, projectKey) {
40
- const message = await this.client.postText(this.packagePath(serviceId, packageId, projectKey), {});
64
+ /**
65
+ * Create a deployable package from the current service state. The
66
+ * documented optional `releaseNotes` parameter is forwarded as the
67
+ * `releaseNotes` query parameter when provided.
68
+ */
69
+ async createPackage(serviceId, packageId, projectKey, options = {}) {
70
+ const params = new URLSearchParams();
71
+ if (options.releaseNotes !== undefined)
72
+ params.set("releaseNotes", options.releaseNotes);
73
+ const query = params.size > 0 ? `?${params.toString()}` : "";
74
+ const message = await this.client.postText(`${this.packagePath(serviceId, packageId, projectKey)}${query}`, {});
41
75
  return { message, };
42
76
  }
43
77
  /** Delete an API service package. */
@@ -48,9 +82,21 @@ export class ApiServicesResource extends BaseResource {
48
82
  async downloadPackageArchive(serviceId, packageId, projectKey) {
49
83
  return this.client.stream(`${this.packagePath(serviceId, packageId, projectKey)}/archive`);
50
84
  }
51
- /** Publish an API service package to the API Deployer. */
52
- async publishPackage(serviceId, packageId, projectKey) {
53
- return this.client.post(`${this.packagePath(serviceId, packageId, projectKey)}/publish`, {});
85
+ /**
86
+ * Publish an API service package to the API Deployer. The documented
87
+ * optional `publishedServiceId` parameter selects the published service
88
+ * the package is deployed to (a new published service is created when no
89
+ * match exists; when omitted, the server falls back to the service's own
90
+ * id). It is forwarded as the `publishedServiceId` query parameter when
91
+ * provided.
92
+ */
93
+ async publishPackage(serviceId, packageId, projectKey, options = {}) {
94
+ const params = new URLSearchParams();
95
+ if (options.publishedServiceId !== undefined) {
96
+ params.set("publishedServiceId", options.publishedServiceId);
97
+ }
98
+ const query = params.size > 0 ? `?${params.toString()}` : "";
99
+ return this.client.post(`${this.packagePath(serviceId, packageId, projectKey)}/publish${query}`, {});
54
100
  }
55
101
  servicePath(serviceId, projectKey) {
56
102
  return `/public/api/projects/${this.enc(projectKey)}/apiservices/${encodeURIComponent(serviceId)}`;
@@ -1,23 +1,68 @@
1
1
  import { BaseResource } from "./base.js";
2
+ /**
3
+ * Optional, documented parameters of the bundle-export endpoint:
4
+ * - `releaseNotes`: important changes introduced in the bundle;
5
+ * - `evaluateProjectStandardsChecks`: whether the Project Standards Checks
6
+ * applying to the project should run (defaults to true server-side, and the
7
+ * official client always sends it).
8
+ */
9
+ export interface BundleExportOptions {
10
+ releaseNotes?: string;
11
+ evaluateProjectStandardsChecks?: boolean;
12
+ }
13
+ /**
14
+ * Optional, documented parameter of the bundle-publish endpoint: the key of
15
+ * the published project on the Project Deployer where the bundle is deployed
16
+ * (a new published project is created when no match exists; when omitted, the
17
+ * server falls back to the source project's key).
18
+ */
19
+ export interface BundlePublishOptions {
20
+ publishedProjectKey?: string;
21
+ }
22
+ /**
23
+ * Optional, documented parameter of the bundle-activation endpoint: scenario
24
+ * IDs mapped to whether each scenario should be enabled or disabled upon
25
+ * activation.
26
+ */
27
+ export interface BundleActivateOptions {
28
+ scenariosToEnable?: Record<string, boolean>;
29
+ }
2
30
  export declare class BundlesResource extends BaseResource {
3
31
  /** List bundles exported from a project on the Design node. */
4
32
  listExported(projectKey?: string): Promise<Record<string, unknown>[]>;
5
- /** Create or overwrite an exported Design-node bundle. */
6
- exportBundle(bundleId: string, projectKey?: string): Promise<void>;
33
+ /**
34
+ * Create or overwrite an exported Design-node bundle. The documented
35
+ * optional parameters are forwarded as query parameters:
36
+ * `releaseNotes` when provided, and `evaluateProjectStandardsChecks`
37
+ * (defaults to true, matching the official client which always sends it).
38
+ */
39
+ exportBundle(bundleId: string, projectKey?: string, options?: BundleExportOptions): Promise<void>;
7
40
  /** Delete an exported Design-node bundle. */
8
41
  deleteExported(bundleId: string, projectKey?: string): Promise<void>;
9
42
  /** Download an exported Design-node bundle archive. */
10
43
  downloadExportedArchive(bundleId: string, projectKey?: string): Promise<Response>;
11
- /** Publish a Design-node bundle to the Project Deployer. */
12
- publish(bundleId: string, projectKey?: string): Promise<Record<string, unknown>>;
44
+ /**
45
+ * Publish a Design-node bundle to the Project Deployer. The documented
46
+ * optional `publishedProjectKey` parameter selects the published project
47
+ * the bundle is deployed to (a new published project is created when no
48
+ * match exists; when omitted, the server falls back to the source
49
+ * project's key). It is forwarded as the `publishedProjectKey` query
50
+ * parameter when provided.
51
+ */
52
+ publish(bundleId: string, projectKey?: string, options?: BundlePublishOptions): Promise<Record<string, unknown>>;
13
53
  /** List bundles imported into a project on the Automation node. */
14
54
  listImported(projectKey?: string): Promise<Record<string, unknown>[]>;
15
55
  /** Import a server-side bundle archive into an Automation-node project. */
16
56
  importFromArchive(archivePath: string, projectKey?: string): Promise<Record<string, unknown>>;
17
57
  /** Import a local bundle archive stream into an Automation-node project. */
18
58
  importFromStream(filePath: string, projectKey?: string): Promise<void>;
19
- /** Activate an imported Automation-node bundle. */
20
- activate(bundleId: string, projectKey?: string): Promise<Record<string, unknown>>;
59
+ /**
60
+ * Activate an imported Automation-node bundle. The documented optional
61
+ * `scenariosToEnable` dict (scenario ID → enabled/disabled upon
62
+ * activation) is forwarded as the `scenariosActiveOnActivation` request
63
+ * body when provided.
64
+ */
65
+ activate(bundleId: string, projectKey?: string, options?: BundleActivateOptions): Promise<Record<string, unknown>>;
21
66
  /** Preload an imported Automation-node bundle. */
22
67
  preload(bundleId: string, projectKey?: string): Promise<Record<string, unknown>>;
23
68
  /** Delete an imported Automation-node bundle. */
@@ -5,9 +5,18 @@ export class BundlesResource extends BaseResource {
5
5
  const res = await this.client.get(`/public/api/projects/${this.enc(projectKey)}/bundles/exported`);
6
6
  return res.bundles ?? [];
7
7
  }
8
- /** Create or overwrite an exported Design-node bundle. */
9
- async exportBundle(bundleId, projectKey) {
10
- await this.client.putVoid(`/public/api/projects/${this.enc(projectKey)}/bundles/exported/${encodeURIComponent(bundleId)}`, {});
8
+ /**
9
+ * Create or overwrite an exported Design-node bundle. The documented
10
+ * optional parameters are forwarded as query parameters:
11
+ * `releaseNotes` when provided, and `evaluateProjectStandardsChecks`
12
+ * (defaults to true, matching the official client which always sends it).
13
+ */
14
+ async exportBundle(bundleId, projectKey, options = {}) {
15
+ const params = new URLSearchParams();
16
+ if (options.releaseNotes !== undefined)
17
+ params.set("releaseNotes", options.releaseNotes);
18
+ params.set("evaluateProjectStandardsChecks", String(options.evaluateProjectStandardsChecks ?? true));
19
+ await this.client.putVoid(`/public/api/projects/${this.enc(projectKey)}/bundles/exported/${encodeURIComponent(bundleId)}?${params.toString()}`, {});
11
20
  }
12
21
  /** Delete an exported Design-node bundle. */
13
22
  async deleteExported(bundleId, projectKey) {
@@ -17,9 +26,21 @@ export class BundlesResource extends BaseResource {
17
26
  async downloadExportedArchive(bundleId, projectKey) {
18
27
  return this.client.stream(`/public/api/projects/${this.enc(projectKey)}/bundles/exported/${encodeURIComponent(bundleId)}/archive`);
19
28
  }
20
- /** Publish a Design-node bundle to the Project Deployer. */
21
- async publish(bundleId, projectKey) {
22
- return this.client.post(`/public/api/projects/${this.enc(projectKey)}/bundles/${encodeURIComponent(bundleId)}/publish`, {});
29
+ /**
30
+ * Publish a Design-node bundle to the Project Deployer. The documented
31
+ * optional `publishedProjectKey` parameter selects the published project
32
+ * the bundle is deployed to (a new published project is created when no
33
+ * match exists; when omitted, the server falls back to the source
34
+ * project's key). It is forwarded as the `publishedProjectKey` query
35
+ * parameter when provided.
36
+ */
37
+ async publish(bundleId, projectKey, options = {}) {
38
+ const params = new URLSearchParams();
39
+ if (options.publishedProjectKey !== undefined) {
40
+ params.set("publishedProjectKey", options.publishedProjectKey);
41
+ }
42
+ const query = params.size > 0 ? `?${params.toString()}` : "";
43
+ return this.client.post(`/public/api/projects/${this.enc(projectKey)}/bundles/${encodeURIComponent(bundleId)}/publish${query}`, {});
23
44
  }
24
45
  /** List bundles imported into a project on the Automation node. */
25
46
  async listImported(projectKey) {
@@ -34,9 +55,18 @@ export class BundlesResource extends BaseResource {
34
55
  async importFromStream(filePath, projectKey) {
35
56
  await this.client.upload(`/public/api/projects/${this.enc(projectKey)}/bundles/imported/actions/importFromStream`, filePath);
36
57
  }
37
- /** Activate an imported Automation-node bundle. */
38
- async activate(bundleId, projectKey) {
39
- return this.client.post(`/public/api/projects/${this.enc(projectKey)}/bundles/imported/${encodeURIComponent(bundleId)}/actions/activate`, {});
58
+ /**
59
+ * Activate an imported Automation-node bundle. The documented optional
60
+ * `scenariosToEnable` dict (scenario ID → enabled/disabled upon
61
+ * activation) is forwarded as the `scenariosActiveOnActivation` request
62
+ * body when provided.
63
+ */
64
+ async activate(bundleId, projectKey, options = {}) {
65
+ const body = options.scenariosToEnable !== undefined
66
+ && Object.keys(options.scenariosToEnable).length > 0
67
+ ? { scenariosActiveOnActivation: options.scenariosToEnable, }
68
+ : {};
69
+ return this.client.post(`/public/api/projects/${this.enc(projectKey)}/bundles/imported/${encodeURIComponent(bundleId)}/actions/activate`, body);
40
70
  }
41
71
  /** Preload an imported Automation-node bundle. */
42
72
  async preload(bundleId, projectKey) {
@@ -1,4 +1,4 @@
1
- import type { CodeEnvActionResult, CodeEnvCreateOptions, CodeEnvDetails, CodeEnvPackageList, CodeEnvSetPackagesOptions, CodeEnvSummary, CodeEnvUpdatePackagesOptions, CodeEnvWaitOptions } from "../schemas.js";
1
+ import type { CodeEnvActionResult, CodeEnvCreateOptions, CodeEnvDetails, CodeEnvGetLogOptions, CodeEnvLogResult, CodeEnvLogSummary, CodeEnvPackageList, CodeEnvSetPackagesOptions, CodeEnvSummary, CodeEnvUpdateImagesOptions, CodeEnvUpdatePackagesOptions, CodeEnvVersionForProject, CodeEnvWaitOptions } from "../schemas.js";
2
2
  import { BaseResource } from "./base.js";
3
3
  export declare class CodeEnvsResource extends BaseResource {
4
4
  list(opts?: {
@@ -6,9 +6,31 @@ export declare class CodeEnvsResource extends BaseResource {
6
6
  }): Promise<CodeEnvSummary[]>;
7
7
  get(envLang: string, envName: string): Promise<CodeEnvDetails>;
8
8
  getDefinition(envLang: string, envName: string): Promise<Record<string, unknown>>;
9
+ /** List the build log files DSS keeps for this code environment. */
10
+ listLogs(envLang: string, envName: string): Promise<CodeEnvLogSummary[]>;
11
+ /**
12
+ * Fetch one code-env build log, bounded by default: at most
13
+ * `maxBytes` bytes (default 10 MiB, 0 disables the cap) and the last
14
+ * `maxLines` lines (default 500, 0 disables the tail). Returns what was
15
+ * kept plus the truncation flags so callers can warn instead of
16
+ * silently losing output.
17
+ */
18
+ getLog(envLang: string, envName: string, logName: string, opts?: CodeEnvGetLogOptions): Promise<CodeEnvLogResult>;
19
+ /**
20
+ * Rebuild the Docker image(s) of the code environment to match its
21
+ * settings. `wait: false` returns the raw DSS future payload.
22
+ */
23
+ updateImages(envLang: string, envName: string, opts?: CodeEnvUpdateImagesOptions): Promise<CodeEnvActionResult>;
24
+ /**
25
+ * Resolve the code-env version a project uses (versioned environments on
26
+ * automation nodes); empty `version` for unversioned environments.
27
+ */
28
+ getVersionForProject(envLang: string, envName: string, projectKey: string): Promise<CodeEnvVersionForProject>;
9
29
  create(opts: CodeEnvCreateOptions): Promise<CodeEnvActionResult>;
10
- setDefinition(envLang: string, envName: string, definition: Record<string, unknown>): Promise<CodeEnvActionResult>;
11
- setPackages(envLang: string, envName: string, packages: CodeEnvPackageList, opts?: Pick<CodeEnvSetPackagesOptions, "installCorePackages">): Promise<CodeEnvActionResult>;
30
+ setDefinition(envLang: string, envName: string, definition: Record<string, unknown>, opts?: {
31
+ expectHash?: string;
32
+ }): Promise<CodeEnvActionResult>;
33
+ setPackages(envLang: string, envName: string, packages: CodeEnvPackageList, opts?: Pick<CodeEnvSetPackagesOptions, "installCorePackages" | "expectHash">): Promise<CodeEnvActionResult>;
12
34
  updatePackages(envLang: string, envName: string, opts?: CodeEnvUpdatePackagesOptions): Promise<CodeEnvActionResult>;
13
35
  setJupyterSupport(envLang: string, envName: string, active: boolean, opts?: CodeEnvWaitOptions): Promise<CodeEnvActionResult>;
14
36
  delete(envLang: string, envName: string, opts?: CodeEnvWaitOptions): Promise<CodeEnvActionResult>;
@@ -1,5 +1,11 @@
1
- import { CodeEnvSummaryArraySchema, CodeEnvUsageArraySchema, } from "../schemas.js";
1
+ import { ClientValidationError, } from "../errors.js";
2
+ import { CodeEnvLogSummaryArraySchema, CodeEnvSummaryArraySchema, CodeEnvUsageArraySchema, CodeEnvVersionForProjectSchema, } from "../schemas.js";
3
+ import { stableHash, } from "../utils/stable-hash.js";
2
4
  import { BaseResource, } from "./base.js";
5
+ /** Byte cap applied to fetched code-env logs so stdout/JSON stays bounded. */
6
+ const DEFAULT_LOG_MAX_BYTES = 10 * 1024 * 1024;
7
+ /** Default number of tail lines returned by getLog (0 disables). */
8
+ const DEFAULT_LOG_MAX_LINES = 500;
3
9
  export class CodeEnvsResource extends BaseResource {
4
10
  async list(opts) {
5
11
  const raw = await this.client.get("/public/api/admin/code-envs/");
@@ -21,8 +27,12 @@ export class CodeEnvsResource extends BaseResource {
21
27
  envName: raw.envName ?? envName,
22
28
  envLang: raw.envLang ?? envLang,
23
29
  pythonInterpreter: desc.pythonInterpreter,
30
+ deploymentMode: typeof raw.deploymentMode === "string"
31
+ ? raw.deploymentMode
32
+ : undefined,
24
33
  requestedPackages,
25
34
  installedPackages,
35
+ definitionHash: stableHash(raw),
26
36
  };
27
37
  }
28
38
  async getDefinition(envLang, envName) {
@@ -30,6 +40,61 @@ export class CodeEnvsResource extends BaseResource {
30
40
  const nameEnc = encodeURIComponent(envName);
31
41
  return this.client.get(`/public/api/admin/code-envs/${langEnc}/${nameEnc}`);
32
42
  }
43
+ /** List the build log files DSS keeps for this code environment. */
44
+ async listLogs(envLang, envName) {
45
+ const langEnc = encodeURIComponent(envLang);
46
+ const nameEnc = encodeURIComponent(envName);
47
+ const raw = await this.client.get(`/public/api/admin/code-envs/${langEnc}/${nameEnc}/logs`);
48
+ return this.client.safeParse(CodeEnvLogSummaryArraySchema, raw, "codeEnvs.listLogs");
49
+ }
50
+ /**
51
+ * Fetch one code-env build log, bounded by default: at most
52
+ * `maxBytes` bytes (default 10 MiB, 0 disables the cap) and the last
53
+ * `maxLines` lines (default 500, 0 disables the tail). Returns what was
54
+ * kept plus the truncation flags so callers can warn instead of
55
+ * silently losing output.
56
+ */
57
+ async getLog(envLang, envName, logName, opts) {
58
+ const langEnc = encodeURIComponent(envLang);
59
+ const nameEnc = encodeURIComponent(envName);
60
+ const logEnc = encodeURIComponent(logName);
61
+ const path = `/public/api/admin/code-envs/${langEnc}/${nameEnc}/logs/${logEnc}`;
62
+ const maxBytes = opts?.maxBytes ?? DEFAULT_LOG_MAX_BYTES;
63
+ const fetched = maxBytes > 0
64
+ ? await this.client.getTextLimited(path, maxBytes)
65
+ : { text: await this.client.getText(path), truncated: false, };
66
+ const tailed = tailLog(fetched.text, opts?.maxLines ?? DEFAULT_LOG_MAX_LINES);
67
+ return {
68
+ log: tailed.log,
69
+ bytes: Buffer.byteLength(fetched.text, "utf-8"),
70
+ truncated: fetched.truncated,
71
+ tailed: tailed.tailed,
72
+ };
73
+ }
74
+ /**
75
+ * Rebuild the Docker image(s) of the code environment to match its
76
+ * settings. `wait: false` returns the raw DSS future payload.
77
+ */
78
+ async updateImages(envLang, envName, opts) {
79
+ const langEnc = encodeURIComponent(envLang);
80
+ const nameEnc = encodeURIComponent(envName);
81
+ const query = new URLSearchParams();
82
+ if (opts?.envVersion !== undefined)
83
+ query.set("envVersion", opts.envVersion);
84
+ query.set("wait", String(opts?.wait !== false));
85
+ return this.client.post(`/public/api/admin/code-envs/${langEnc}/${nameEnc}/images?${query.toString()}`);
86
+ }
87
+ /**
88
+ * Resolve the code-env version a project uses (versioned environments on
89
+ * automation nodes); empty `version` for unversioned environments.
90
+ */
91
+ async getVersionForProject(envLang, envName, projectKey) {
92
+ const langEnc = encodeURIComponent(envLang);
93
+ const nameEnc = encodeURIComponent(envName);
94
+ const pkEnc = encodeURIComponent(projectKey);
95
+ const raw = await this.client.get(`/public/api/admin/code-envs/${langEnc}/${nameEnc}/${pkEnc}/version`);
96
+ return this.client.safeParse(CodeEnvVersionForProjectSchema, raw, "codeEnvs.getVersionForProject");
97
+ }
33
98
  async create(opts) {
34
99
  const langEnc = encodeURIComponent(opts.envLang);
35
100
  const nameEnc = encodeURIComponent(opts.envName);
@@ -39,13 +104,20 @@ export class CodeEnvsResource extends BaseResource {
39
104
  };
40
105
  return this.client.post(`/public/api/admin/code-envs/${langEnc}/${nameEnc}?wait=${opts.wait !== false}`, body);
41
106
  }
42
- async setDefinition(envLang, envName, definition) {
107
+ async setDefinition(envLang, envName, definition, opts) {
108
+ if (opts?.expectHash !== undefined) {
109
+ const current = await this.getDefinition(envLang, envName);
110
+ assertDefinitionHash(envLang, envName, current, opts.expectHash);
111
+ }
43
112
  const langEnc = encodeURIComponent(envLang);
44
113
  const nameEnc = encodeURIComponent(envName);
45
114
  return this.client.put(`/public/api/admin/code-envs/${langEnc}/${nameEnc}`, definition);
46
115
  }
47
116
  async setPackages(envLang, envName, packages, opts) {
48
117
  const current = await this.getDefinition(envLang, envName);
118
+ if (opts?.expectHash !== undefined) {
119
+ assertDefinitionHash(envLang, envName, current, opts.expectHash);
120
+ }
49
121
  const next = {
50
122
  ...current,
51
123
  specPackageList: normalizePackageList(packages),
@@ -98,6 +170,36 @@ export class CodeEnvsResource extends BaseResource {
98
170
  return this.client.safeParse(CodeEnvUsageArraySchema, raw, "codeEnvs.listUsages");
99
171
  }
100
172
  }
173
+ /**
174
+ * Keep only the last `maxLines` lines of a log (0 disables the tail).
175
+ * Returns whether any leading lines were dropped.
176
+ */
177
+ function tailLog(log, maxLines) {
178
+ if (!log)
179
+ return { log, tailed: false, };
180
+ if (maxLines <= 0)
181
+ return { log, tailed: false, };
182
+ const lines = log.split(/\r\n|\n/);
183
+ if (lines.length <= maxLines)
184
+ return { log, tailed: false, };
185
+ return { log: lines.slice(lines.length - maxLines).join("\n"), tailed: true, };
186
+ }
187
+ /**
188
+ * Provenance guard for full-definition writes: DSS requires the PUT body to
189
+ * come from a prior GET, so refuse the write when the definition no longer
190
+ * hashes to the hash the caller captured.
191
+ */
192
+ function assertDefinitionHash(envLang, envName, current, expected) {
193
+ const currentHash = stableHash(current);
194
+ if (currentHash === expected)
195
+ return;
196
+ throw new ClientValidationError(`Code env ${envLang}/${envName} changed since the expected definition hash was captured; refusing to overwrite it.`, "validation_failed", "Re-read the definition with dss code-env get-definition (definitionHash comes from code-env get), review the diff, and retry with the fresh hash.", {
197
+ envLang,
198
+ envName,
199
+ expectedDefinitionHash: expected,
200
+ currentDefinitionHash: currentHash,
201
+ });
202
+ }
101
203
  function splitPackageList(raw) {
102
204
  if (!raw)
103
205
  return [];
@@ -80,6 +80,10 @@ export declare class DatasetsResource extends BaseResource {
80
80
  *
81
81
  * If `validateColumns` is provided, the first TSV row (header) is checked
82
82
  * against the column names. Mismatches emit a warning via onValidationWarning.
83
+ *
84
+ * The stream is byte-bounded (16 MiB per field, 64 MiB per row, 16 GiB per
85
+ * response): an oversized field or unterminated quoted row aborts the
86
+ * preview, cancels the response, and fails with a DataikuError.
83
87
  */
84
88
  preview(datasetName: string, opts?: {
85
89
  maxRows?: number;
@@ -103,6 +107,10 @@ export declare class DatasetsResource extends BaseResource {
103
107
  * fully scanned. Returns the observed count together with `exact` (false when
104
108
  * the probe cap was reached, i.e. the count is a lower bound) and whether the
105
109
  * count satisfies the assertion.
110
+ *
111
+ * Streaming is byte-bounded (16 MiB per field, 64 MiB per row, 16 GiB per
112
+ * response); oversized fields abort the count, cancel the response, and
113
+ * fail with a DataikuError.
106
114
  */
107
115
  assertRowCount(datasetName: string, expected: number, projectKey?: string): Promise<{
108
116
  expected: number;
@@ -117,6 +125,16 @@ export declare class DatasetsResource extends BaseResource {
117
125
  * (default 100k). Returns the written path, the number of data rows written,
118
126
  * whether the dataset had more rows than the cap (truncated), and the limit
119
127
  * used — so callers can detect truncation instead of silently getting a sample.
128
+ *
129
+ * Exported cells are spreadsheet-safe by default: headers/values whose
130
+ * first effective character is a spreadsheet formula sigil (`=`, `+`, `-`,
131
+ * `@`, including leading whitespace/control variants) are neutralized with
132
+ * a leading apostrophe so the file never executes formulas on open. Pass
133
+ * `rawData: true` to preserve exact bytes.
134
+ *
135
+ * Streaming is byte-bounded (16 MiB per field, 64 MiB per row, 16 GiB per
136
+ * response); on overflow the response is cancelled, the error is thrown,
137
+ * and any partially written download file is removed.
120
138
  */
121
139
  download(datasetName: string, opts?: {
122
140
  outputPath?: string;
@@ -125,6 +143,8 @@ export declare class DatasetsResource extends BaseResource {
125
143
  name: string;
126
144
  }[];
127
145
  limit?: number;
146
+ /** Preserve exact cell bytes (no spreadsheet-safe formula neutralization), default false. */
147
+ rawData?: boolean;
128
148
  }): Promise<{
129
149
  path: string;
130
150
  rows: number;