dataiku-sdk 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -0
- package/bin/dss.js +39 -13
- package/dist/src/cli.js +800 -504
- package/dist/src/client.d.ts +18 -17
- package/dist/src/client.js +49 -36
- package/dist/src/config.d.ts +0 -2
- package/dist/src/config.js +1 -16
- package/dist/src/errors.d.ts +2 -1
- package/dist/src/errors.js +3 -1
- package/dist/src/index.d.ts +4 -4
- package/dist/src/index.js +2 -2
- package/dist/src/resources/datasets.d.ts +21 -7
- package/dist/src/resources/datasets.js +62 -69
- package/dist/src/resources/jobs.d.ts +1 -0
- package/dist/src/resources/jobs.js +1 -1
- package/dist/src/resources/recipes.js +20 -4
- package/dist/src/resources/scenarios.d.ts +24 -0
- package/dist/src/resources/scenarios.js +161 -0
- package/dist/src/skill.d.ts +5 -0
- package/dist/src/skill.js +93 -100
- package/dist/src/utils/cleanup-ledger.js +22 -1
- package/package.json +2 -1
package/dist/src/client.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export interface DataikuClientConfig {
|
|
|
35
35
|
caCertPath?: string;
|
|
36
36
|
/**
|
|
37
37
|
* Called when an API response fails schema validation but data is still usable.
|
|
38
|
-
* Default:
|
|
38
|
+
* Default: ignored. Set to a recording or throwing function for strict mode.
|
|
39
39
|
* @param method - resource method that triggered the warning (e.g. "datasets.list")
|
|
40
40
|
* @param errors - human-readable validation error strings
|
|
41
41
|
*/
|
|
@@ -50,23 +50,23 @@ export declare class DataikuClient {
|
|
|
50
50
|
private readonly verbose;
|
|
51
51
|
private readonly tlsOptions;
|
|
52
52
|
private readonly onValidationWarning;
|
|
53
|
-
private
|
|
54
|
-
private
|
|
55
|
-
private
|
|
56
|
-
private
|
|
57
|
-
private
|
|
58
|
-
private
|
|
53
|
+
private projectsResource?;
|
|
54
|
+
private datasetsResource?;
|
|
55
|
+
private recipesResource?;
|
|
56
|
+
private dashboardsResource?;
|
|
57
|
+
private dataQualityResource?;
|
|
58
|
+
private jobsResource?;
|
|
59
59
|
private futuresResource?;
|
|
60
|
-
private
|
|
61
|
-
private
|
|
62
|
-
private
|
|
63
|
-
private
|
|
64
|
-
private
|
|
65
|
-
private
|
|
66
|
-
private
|
|
67
|
-
private
|
|
68
|
-
private
|
|
69
|
-
private
|
|
60
|
+
private scenariosResource?;
|
|
61
|
+
private foldersResource?;
|
|
62
|
+
private flowZonesResource?;
|
|
63
|
+
private variablesResource?;
|
|
64
|
+
private connectionsResource?;
|
|
65
|
+
private codeEnvsResource?;
|
|
66
|
+
private insightsResource?;
|
|
67
|
+
private sqlResource?;
|
|
68
|
+
private notebooksResource?;
|
|
69
|
+
private wikiResource?;
|
|
70
70
|
get projects(): ProjectsResource;
|
|
71
71
|
get datasets(): DatasetsResource;
|
|
72
72
|
get dashboards(): DashboardsResource;
|
|
@@ -113,6 +113,7 @@ export declare class DataikuClient {
|
|
|
113
113
|
safeParse<S extends TSchema>(schema: S, data: unknown, method: string): Static<S>;
|
|
114
114
|
/** Emit a validation warning via the configured callback. */
|
|
115
115
|
warn(method: string, errors: string[]): void;
|
|
116
|
+
private requestIdFromHeaders;
|
|
116
117
|
private parseJsonResponse;
|
|
117
118
|
private fetchWithRetry;
|
|
118
119
|
}
|
package/dist/src/client.js
CHANGED
|
@@ -31,8 +31,7 @@ const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
|
|
|
31
31
|
/* ------------------------------------------------------------------ */
|
|
32
32
|
/* Helpers */
|
|
33
33
|
/* ------------------------------------------------------------------ */
|
|
34
|
-
function defaultValidationWarning(
|
|
35
|
-
process.stderr.write(`[dataiku-sdk] Schema validation warning in ${method}:\n ${errors.join("\n ")}\n`);
|
|
34
|
+
function defaultValidationWarning(_method, _errors) {
|
|
36
35
|
}
|
|
37
36
|
function sleep(ms) {
|
|
38
37
|
return new Promise((r) => setTimeout(r, ms));
|
|
@@ -92,73 +91,73 @@ export class DataikuClient {
|
|
|
92
91
|
tlsOptions;
|
|
93
92
|
onValidationWarning;
|
|
94
93
|
/* Resource namespaces — lazily initialized to break circular imports */
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
94
|
+
projectsResource;
|
|
95
|
+
datasetsResource;
|
|
96
|
+
recipesResource;
|
|
97
|
+
dashboardsResource;
|
|
98
|
+
dataQualityResource;
|
|
99
|
+
jobsResource;
|
|
101
100
|
futuresResource;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
101
|
+
scenariosResource;
|
|
102
|
+
foldersResource;
|
|
103
|
+
flowZonesResource;
|
|
104
|
+
variablesResource;
|
|
105
|
+
connectionsResource;
|
|
106
|
+
codeEnvsResource;
|
|
107
|
+
insightsResource;
|
|
108
|
+
sqlResource;
|
|
109
|
+
notebooksResource;
|
|
110
|
+
wikiResource;
|
|
112
111
|
get projects() {
|
|
113
|
-
return (this.
|
|
112
|
+
return (this.projectsResource ??= new ProjectsResource(this));
|
|
114
113
|
}
|
|
115
114
|
get datasets() {
|
|
116
|
-
return (this.
|
|
115
|
+
return (this.datasetsResource ??= new DatasetsResource(this));
|
|
117
116
|
}
|
|
118
117
|
get dashboards() {
|
|
119
|
-
return (this.
|
|
118
|
+
return (this.dashboardsResource ??= new DashboardsResource(this));
|
|
120
119
|
}
|
|
121
120
|
get dataQuality() {
|
|
122
|
-
return (this.
|
|
121
|
+
return (this.dataQualityResource ??= new DataQualityResource(this));
|
|
123
122
|
}
|
|
124
123
|
get recipes() {
|
|
125
|
-
return (this.
|
|
124
|
+
return (this.recipesResource ??= new RecipesResource(this));
|
|
126
125
|
}
|
|
127
126
|
get jobs() {
|
|
128
|
-
return (this.
|
|
127
|
+
return (this.jobsResource ??= new JobsResource(this));
|
|
129
128
|
}
|
|
130
129
|
get futures() {
|
|
131
130
|
return (this.futuresResource ??= new FuturesResource(this));
|
|
132
131
|
}
|
|
133
132
|
get scenarios() {
|
|
134
|
-
return (this.
|
|
133
|
+
return (this.scenariosResource ??= new ScenariosResource(this));
|
|
135
134
|
}
|
|
136
135
|
get folders() {
|
|
137
|
-
return (this.
|
|
136
|
+
return (this.foldersResource ??= new FoldersResource(this));
|
|
138
137
|
}
|
|
139
138
|
get flowZones() {
|
|
140
|
-
return (this.
|
|
139
|
+
return (this.flowZonesResource ??= new FlowZonesResource(this));
|
|
141
140
|
}
|
|
142
141
|
get variables() {
|
|
143
|
-
return (this.
|
|
142
|
+
return (this.variablesResource ??= new VariablesResource(this));
|
|
144
143
|
}
|
|
145
144
|
get connections() {
|
|
146
|
-
return (this.
|
|
145
|
+
return (this.connectionsResource ??= new ConnectionsResource(this));
|
|
147
146
|
}
|
|
148
147
|
get codeEnvs() {
|
|
149
|
-
return (this.
|
|
148
|
+
return (this.codeEnvsResource ??= new CodeEnvsResource(this));
|
|
150
149
|
}
|
|
151
150
|
get insights() {
|
|
152
|
-
return (this.
|
|
151
|
+
return (this.insightsResource ??= new InsightsResource(this));
|
|
153
152
|
}
|
|
154
153
|
get sql() {
|
|
155
|
-
return (this.
|
|
154
|
+
return (this.sqlResource ??= new SqlResource(this));
|
|
156
155
|
}
|
|
157
156
|
get notebooks() {
|
|
158
|
-
return (this.
|
|
157
|
+
return (this.notebooksResource ??= new NotebooksResource(this));
|
|
159
158
|
}
|
|
160
159
|
get wiki() {
|
|
161
|
-
return (this.
|
|
160
|
+
return (this.wikiResource ??= new WikiResource(this));
|
|
162
161
|
}
|
|
163
162
|
constructor(config) {
|
|
164
163
|
const url = config.url?.trim();
|
|
@@ -298,6 +297,20 @@ export class DataikuClient {
|
|
|
298
297
|
this.onValidationWarning(method, errors);
|
|
299
298
|
}
|
|
300
299
|
/* ---- private: JSON parsing ---- */
|
|
300
|
+
requestIdFromHeaders(headers) {
|
|
301
|
+
for (const name of [
|
|
302
|
+
"x-request-id",
|
|
303
|
+
"x-dku-request-id",
|
|
304
|
+
"x-dataiku-request-id",
|
|
305
|
+
"x-correlation-id",
|
|
306
|
+
"x-amzn-requestid",
|
|
307
|
+
]) {
|
|
308
|
+
const value = headers.get(name);
|
|
309
|
+
if (value)
|
|
310
|
+
return value;
|
|
311
|
+
}
|
|
312
|
+
return undefined;
|
|
313
|
+
}
|
|
301
314
|
async parseJsonResponse(res) {
|
|
302
315
|
const text = await res.text();
|
|
303
316
|
// SAFETY: Empty 2xx responses from DSS are surfaced to callers as undefined
|
|
@@ -310,7 +323,7 @@ export class DataikuClient {
|
|
|
310
323
|
}
|
|
311
324
|
catch {
|
|
312
325
|
const summary = text.length > 300 ? `${text.slice(0, 300)}…` : text;
|
|
313
|
-
throw new DataikuError(res.status, res.statusText || "Invalid JSON response", `Expected JSON response body but got non-JSON content: ${summary}
|
|
326
|
+
throw new DataikuError(res.status, res.statusText || "Invalid JSON response", `Expected JSON response body but got non-JSON content: ${summary}`, undefined, this.requestIdFromHeaders(res.headers));
|
|
314
327
|
}
|
|
315
328
|
}
|
|
316
329
|
/* ---- private: retry loop ---- */
|
|
@@ -347,7 +360,7 @@ export class DataikuClient {
|
|
|
347
360
|
await sleep(delayMs);
|
|
348
361
|
continue;
|
|
349
362
|
}
|
|
350
|
-
throw new DataikuError(res.status, res.statusText, text, buildRetryMetadata(method, retryEnabled, maxAttempts, attempt, delaysMs, false));
|
|
363
|
+
throw new DataikuError(res.status, res.statusText, text, buildRetryMetadata(method, retryEnabled, maxAttempts, attempt, delaysMs, false), this.requestIdFromHeaders(res.headers));
|
|
351
364
|
}
|
|
352
365
|
return res;
|
|
353
366
|
}
|
package/dist/src/config.d.ts
CHANGED
|
@@ -9,5 +9,3 @@ export declare function getConfigDir(): string;
|
|
|
9
9
|
export declare function getCredentialsPath(): string;
|
|
10
10
|
export declare function loadCredentials(): DssCredentials | null;
|
|
11
11
|
export declare function saveCredentials(creds: DssCredentials): void;
|
|
12
|
-
export declare function deleteCredentials(): void;
|
|
13
|
-
export declare function maskApiKey(apiKey: string): string;
|
package/dist/src/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { chmodSync, mkdirSync, readFileSync,
|
|
1
|
+
import { chmodSync, mkdirSync, readFileSync, writeFileSync, } from "node:fs";
|
|
2
2
|
import { homedir, } from "node:os";
|
|
3
3
|
import { dirname, join, resolve, } from "node:path";
|
|
4
4
|
export function getConfigDir() {
|
|
@@ -56,18 +56,3 @@ export function saveCredentials(creds) {
|
|
|
56
56
|
writeFileSync(path, `${JSON.stringify(data, null, 2)}\n`, "utf-8");
|
|
57
57
|
chmodSync(path, 0o600);
|
|
58
58
|
}
|
|
59
|
-
export function deleteCredentials() {
|
|
60
|
-
try {
|
|
61
|
-
unlinkSync(getCredentialsPath());
|
|
62
|
-
}
|
|
63
|
-
catch (err) {
|
|
64
|
-
if (err.code === "ENOENT")
|
|
65
|
-
return;
|
|
66
|
-
throw err;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
export function maskApiKey(apiKey) {
|
|
70
|
-
if (apiKey.length <= 12)
|
|
71
|
-
return "***";
|
|
72
|
-
return `${apiKey.slice(0, 6)}...${apiKey.slice(-6)}`;
|
|
73
|
-
}
|
package/dist/src/errors.d.ts
CHANGED
|
@@ -24,7 +24,8 @@ export declare class DataikuError extends Error {
|
|
|
24
24
|
retryable: boolean;
|
|
25
25
|
retryHint: string;
|
|
26
26
|
retry?: DataikuRetryMetadata;
|
|
27
|
-
|
|
27
|
+
requestId?: string;
|
|
28
|
+
constructor(status: number, statusText: string, body: string, retry?: DataikuRetryMetadata, requestId?: string);
|
|
28
29
|
private static extractSummary;
|
|
29
30
|
private static formatRetryMetadata;
|
|
30
31
|
private static buildDetails;
|
package/dist/src/errors.js
CHANGED
|
@@ -152,7 +152,8 @@ export class DataikuError extends Error {
|
|
|
152
152
|
retryable;
|
|
153
153
|
retryHint;
|
|
154
154
|
retry;
|
|
155
|
-
|
|
155
|
+
requestId;
|
|
156
|
+
constructor(status, statusText, body, retry, requestId) {
|
|
156
157
|
const details = DataikuError.buildDetails(status, statusText, body, retry);
|
|
157
158
|
super(details.message);
|
|
158
159
|
this.status = status;
|
|
@@ -163,6 +164,7 @@ export class DataikuError extends Error {
|
|
|
163
164
|
this.retryable = details.retryable;
|
|
164
165
|
this.retryHint = details.retryHint;
|
|
165
166
|
this.retry = retry;
|
|
167
|
+
this.requestId = requestId;
|
|
166
168
|
}
|
|
167
169
|
static extractSummary(_status, _statusText, body) {
|
|
168
170
|
try {
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { DataikuClient, type DataikuClientConfig, } from "./client.js";
|
|
2
2
|
export { type CredentialValidationOptions, type CredentialValidationResult, validateCredentials, } from "./auth.js";
|
|
3
|
-
export {
|
|
3
|
+
export { type DssCredentials, getConfigDir, getCredentialsPath, loadCredentials, saveCredentials, } from "./config.js";
|
|
4
4
|
export { DataikuError, type DataikuErrorCategory, type DataikuErrorTaxonomy, type DataikuRetryMetadata, } from "./errors.js";
|
|
5
5
|
export { CodeEnvsResource, } from "./resources/code-envs.js";
|
|
6
6
|
export { type ConnectionSchemaListOptions, ConnectionsResource, type ConnectionTableListOptions, } from "./resources/connections.js";
|
|
@@ -15,13 +15,13 @@ export { computeNextPollDelayMs, type JobBuildAndWaitOptions, type JobBuildOptio
|
|
|
15
15
|
export { NotebooksResource, } from "./resources/notebooks.js";
|
|
16
16
|
export { type FlowMapResult, ProjectsResource, } from "./resources/projects.js";
|
|
17
17
|
export { type RecipeCloneOptions, type RecipeCloneResult, type RecipeGraphReference, type RecipeGraphValidationResult, type RecipeRunOptions, type RecipeRunOutput, type RecipeRunResult, RecipesResource, } from "./resources/recipes.js";
|
|
18
|
-
export { normalizeScenarioUpdateData, SCENARIO_CANONICAL_EDITABLE_FIELDS, type ScenarioFieldChange, type ScenarioFieldMismatch, ScenariosResource, type ScenarioUpdateNormalization, type ScenarioUpdatePreview, scenarioUpdatePreview, type ScenarioUpdateResult, } from "./resources/scenarios.js";
|
|
18
|
+
export { normalizeScenarioUpdateData, SCENARIO_CANONICAL_EDITABLE_FIELDS, type ScenarioFieldChange, type ScenarioFieldMismatch, type ScenarioScriptRunResult, ScenariosResource, type ScenarioUpdateNormalization, type ScenarioUpdatePreview, scenarioUpdatePreview, type ScenarioUpdateResult, } from "./resources/scenarios.js";
|
|
19
19
|
export { SqlResource, } from "./resources/sql.js";
|
|
20
20
|
export { VariablesResource, } from "./resources/variables.js";
|
|
21
21
|
export { WikiResource, } from "./resources/wiki.js";
|
|
22
|
-
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, ProjectMetadataSchema, ProjectSummaryArraySchema, ProjectSummarySchema, ProjectVariablesSchema, RecipeCreateOptionsSchema, RecipeCreateResultSchema, RecipeDetailsSchema, RecipeSummaryArraySchema, RecipeSummarySchema, safeParseSchema, ScenarioDetailsSchema, ScenarioStatusSchema, ScenarioSummaryArraySchema, ScenarioSummarySchema, SqlNotebookCellSchema, SqlNotebookContentSchema, SqlNotebookSummaryArraySchema, SqlNotebookSummarySchema, SqlQueryResponseSchema, SqlQueryResultSchema, SqlQuerySchemaSchema, WikiArticleDataArraySchema, WikiArticleDataSchema, WikiArticleMetadataSchema, WikiSettingsSchema, WikiTaxonomyNodeSchema, } from "./schemas.js";
|
|
22
|
+
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, ProjectMetadataSchema, ProjectSummaryArraySchema, ProjectSummarySchema, ProjectVariablesSchema, RecipeCreateOptionsSchema, RecipeCreateResultSchema, RecipeDetailsSchema, RecipeSummaryArraySchema, RecipeSummarySchema, safeParseSchema, ScenarioDetailsSchema, ScenarioStatusSchema, ScenarioSummaryArraySchema, ScenarioSummarySchema, ScenarioWaitResultSchema, SqlNotebookCellSchema, SqlNotebookContentSchema, SqlNotebookSummaryArraySchema, SqlNotebookSummarySchema, SqlQueryResponseSchema, SqlQueryResultSchema, SqlQuerySchemaSchema, WikiArticleDataArraySchema, WikiArticleDataSchema, WikiArticleMetadataSchema, WikiSettingsSchema, WikiTaxonomyNodeSchema, } from "./schemas.js";
|
|
23
23
|
export type { SafeParseResult, } from "./schemas.js";
|
|
24
|
-
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, ProjectMetadata, ProjectSummary, ProjectVariables, RecipeCreateOptions, RecipeCreateResult, RecipeDetails, RecipeSummary, ScenarioDetails, ScenarioStatus, ScenarioSummary, SqlNotebookCell, SqlNotebookContent, SqlNotebookSummary, SqlQueryResponse, SqlQueryResult, SqlQuerySchema, WikiArticleData, WikiArticleMetadata, WikiSettings, WikiTaxonomyNode, } from "./schemas.js";
|
|
24
|
+
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, ProjectMetadata, ProjectSummary, ProjectVariables, RecipeCreateOptions, RecipeCreateResult, RecipeDetails, RecipeSummary, ScenarioDetails, ScenarioStatus, ScenarioSummary, ScenarioWaitResult, SqlNotebookCell, SqlNotebookContent, SqlNotebookSummary, SqlQueryResponse, SqlQueryResult, SqlQuerySchema, WikiArticleData, WikiArticleMetadata, WikiSettings, WikiTaxonomyNode, } from "./schemas.js";
|
|
25
25
|
export { deepMerge, } from "./utils/deep-merge.js";
|
|
26
26
|
export { type NormalizedFlowEdge, type NormalizedFlowMap, type NormalizedFlowNode, normalizeFlowGraph, } from "./utils/flow-map.js";
|
|
27
27
|
export { sanitizeFileName, } from "./utils/sanitize.js";
|
package/dist/src/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export { DataikuClient, } from "./client.js";
|
|
3
3
|
// Auth & Config
|
|
4
4
|
export { validateCredentials, } from "./auth.js";
|
|
5
|
-
export {
|
|
5
|
+
export { getConfigDir, getCredentialsPath, loadCredentials, saveCredentials, } from "./config.js";
|
|
6
6
|
// Errors
|
|
7
7
|
export { DataikuError, } from "./errors.js";
|
|
8
8
|
// Resources (for advanced use / extension)
|
|
@@ -24,7 +24,7 @@ export { SqlResource, } from "./resources/sql.js";
|
|
|
24
24
|
export { VariablesResource, } from "./resources/variables.js";
|
|
25
25
|
export { WikiResource, } from "./resources/wiki.js";
|
|
26
26
|
// Schemas (TypeBox schema objects for runtime validation)
|
|
27
|
-
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, ProjectMetadataSchema, ProjectSummaryArraySchema, ProjectSummarySchema, ProjectVariablesSchema, RecipeCreateOptionsSchema, RecipeCreateResultSchema, RecipeDetailsSchema, RecipeSummaryArraySchema, RecipeSummarySchema, safeParseSchema, ScenarioDetailsSchema, ScenarioStatusSchema, ScenarioSummaryArraySchema, ScenarioSummarySchema, SqlNotebookCellSchema, SqlNotebookContentSchema, SqlNotebookSummaryArraySchema, SqlNotebookSummarySchema, SqlQueryResponseSchema, SqlQueryResultSchema, SqlQuerySchemaSchema, WikiArticleDataArraySchema, WikiArticleDataSchema, WikiArticleMetadataSchema, WikiSettingsSchema, WikiTaxonomyNodeSchema, } from "./schemas.js";
|
|
27
|
+
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, ProjectMetadataSchema, ProjectSummaryArraySchema, ProjectSummarySchema, ProjectVariablesSchema, RecipeCreateOptionsSchema, RecipeCreateResultSchema, RecipeDetailsSchema, RecipeSummaryArraySchema, RecipeSummarySchema, safeParseSchema, ScenarioDetailsSchema, ScenarioStatusSchema, ScenarioSummaryArraySchema, ScenarioSummarySchema, ScenarioWaitResultSchema, SqlNotebookCellSchema, SqlNotebookContentSchema, SqlNotebookSummaryArraySchema, SqlNotebookSummarySchema, SqlQueryResponseSchema, SqlQueryResultSchema, SqlQuerySchemaSchema, WikiArticleDataArraySchema, WikiArticleDataSchema, WikiArticleMetadataSchema, WikiSettingsSchema, WikiTaxonomyNodeSchema, } from "./schemas.js";
|
|
28
28
|
// Utilities
|
|
29
29
|
export { deepMerge, } from "./utils/deep-merge.js";
|
|
30
30
|
export { normalizeFlowGraph, } from "./utils/flow-map.js";
|
|
@@ -47,9 +47,9 @@ export declare class DatasetsResource extends BaseResource {
|
|
|
47
47
|
/** Replace dataset schema columns directly through the schema endpoint. */
|
|
48
48
|
updateSchema(datasetName: string, columns: DatasetSchemaColumnInput[], projectKey?: string): Promise<void>;
|
|
49
49
|
/**
|
|
50
|
-
* Preview dataset
|
|
51
|
-
*
|
|
52
|
-
* data rows
|
|
50
|
+
* Preview dataset rows as structured data: column names plus row arrays,
|
|
51
|
+
* mirroring the sql query shape ({ columns, rows, rowCount }). Streams TSV
|
|
52
|
+
* from the API and returns up to `maxRows` data rows.
|
|
53
53
|
*
|
|
54
54
|
* If `validateColumns` is provided, the first TSV row (header) is checked
|
|
55
55
|
* against the column names. Mismatches emit a warning via onValidationWarning.
|
|
@@ -61,12 +61,20 @@ export declare class DatasetsResource extends BaseResource {
|
|
|
61
61
|
name: string;
|
|
62
62
|
}[];
|
|
63
63
|
timeoutMs?: number;
|
|
64
|
-
}): Promise<
|
|
64
|
+
}): Promise<{
|
|
65
|
+
columns: Array<{
|
|
66
|
+
name: string;
|
|
67
|
+
}>;
|
|
68
|
+
rows: string[][];
|
|
69
|
+
rowCount: number;
|
|
70
|
+
}>;
|
|
65
71
|
/** Get dataset metadata (tags, custom fields, checklists). */
|
|
66
72
|
metadata(datasetName: string, projectKey?: string): Promise<Record<string, unknown>>;
|
|
67
73
|
/**
|
|
68
|
-
* Download dataset
|
|
69
|
-
* Returns the
|
|
74
|
+
* Download dataset rows as a gzipped (or .csv) file, capped at `limit` rows
|
|
75
|
+
* (default 100k). Returns the written path, the number of data rows written,
|
|
76
|
+
* whether the dataset had more rows than the cap (truncated), and the limit
|
|
77
|
+
* used — so callers can detect truncation instead of silently getting a sample.
|
|
70
78
|
*/
|
|
71
79
|
download(datasetName: string, opts?: {
|
|
72
80
|
outputPath?: string;
|
|
@@ -74,7 +82,13 @@ export declare class DatasetsResource extends BaseResource {
|
|
|
74
82
|
validateColumns?: {
|
|
75
83
|
name: string;
|
|
76
84
|
}[];
|
|
77
|
-
|
|
85
|
+
limit?: number;
|
|
86
|
+
}): Promise<{
|
|
87
|
+
path: string;
|
|
88
|
+
rows: number;
|
|
89
|
+
truncated: boolean;
|
|
90
|
+
limit: number;
|
|
91
|
+
}>;
|
|
78
92
|
/**
|
|
79
93
|
* Create a new dataset.
|
|
80
94
|
*
|
|
@@ -133,22 +133,6 @@ export function validateStreamColumns(headerRow, expectedColumns) {
|
|
|
133
133
|
}
|
|
134
134
|
return warnings;
|
|
135
135
|
}
|
|
136
|
-
function emitCsvLineWithLimit(row, maxDataRows, emittedRows, onLine, onHeader) {
|
|
137
|
-
if (isBlankRow(row))
|
|
138
|
-
return false;
|
|
139
|
-
const isHeader = emittedRows.value === 0;
|
|
140
|
-
if (isHeader && onHeader)
|
|
141
|
-
onHeader(row);
|
|
142
|
-
if (!isHeader && emittedRows.value - 1 >= maxDataRows) {
|
|
143
|
-
return true;
|
|
144
|
-
}
|
|
145
|
-
onLine(rowToCsv(row));
|
|
146
|
-
emittedRows.value += 1;
|
|
147
|
-
if (!isHeader && emittedRows.value - 1 >= maxDataRows) {
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
return false;
|
|
151
|
-
}
|
|
152
136
|
function buildPreviewTimeoutError(timeoutMs) {
|
|
153
137
|
return new DataikuError(0, "Request Timeout", `Dataset preview timed out after ${timeoutMs}ms while waiting for rows.`);
|
|
154
138
|
}
|
|
@@ -167,13 +151,29 @@ async function readChunkWithTimeout(reader, remainingMs, timeoutMs) {
|
|
|
167
151
|
});
|
|
168
152
|
});
|
|
169
153
|
}
|
|
170
|
-
async function
|
|
154
|
+
async function collectPreviewRows(body, maxDataRows, timeoutMs, onHeader) {
|
|
171
155
|
const state = createTsvStreamState();
|
|
172
|
-
|
|
173
|
-
const
|
|
156
|
+
let columns;
|
|
157
|
+
const rows = [];
|
|
174
158
|
let done = false;
|
|
175
159
|
const startedAt = Date.now();
|
|
176
160
|
const reader = body.getReader();
|
|
161
|
+
const handleRow = (row) => {
|
|
162
|
+
if (done || isBlankRow(row))
|
|
163
|
+
return;
|
|
164
|
+
if (columns === undefined) {
|
|
165
|
+
columns = row;
|
|
166
|
+
onHeader?.(row);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (rows.length >= maxDataRows) {
|
|
170
|
+
done = true;
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
rows.push(row);
|
|
174
|
+
if (rows.length >= maxDataRows)
|
|
175
|
+
done = true;
|
|
176
|
+
};
|
|
177
177
|
try {
|
|
178
178
|
while (true) {
|
|
179
179
|
if (done) {
|
|
@@ -186,64 +186,53 @@ async function collectPreviewCsv(body, maxDataRows, timeoutMs, onHeader) {
|
|
|
186
186
|
const result = await readChunkWithTimeout(reader, remainingMs, timeoutMs);
|
|
187
187
|
if (result.done)
|
|
188
188
|
break;
|
|
189
|
-
consumeTsvChunk(Buffer.from(result.value).toString("utf-8"), state,
|
|
190
|
-
if (done)
|
|
191
|
-
return;
|
|
192
|
-
done = emitCsvLineWithLimit(row, maxDataRows, emittedRows, (line) => {
|
|
193
|
-
lines.push(line);
|
|
194
|
-
}, onHeader);
|
|
195
|
-
});
|
|
189
|
+
consumeTsvChunk(Buffer.from(result.value).toString("utf-8"), state, handleRow);
|
|
196
190
|
}
|
|
197
|
-
if (!done)
|
|
198
|
-
flushTsvStream(state,
|
|
199
|
-
|
|
200
|
-
return;
|
|
201
|
-
done = emitCsvLineWithLimit(row, maxDataRows, emittedRows, (line) => {
|
|
202
|
-
lines.push(line);
|
|
203
|
-
}, onHeader);
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
return lines.join("\n");
|
|
191
|
+
if (!done)
|
|
192
|
+
flushTsvStream(state, handleRow);
|
|
193
|
+
return { columns: columns ?? [], rows, };
|
|
207
194
|
}
|
|
208
195
|
finally {
|
|
209
196
|
reader.releaseLock();
|
|
210
197
|
}
|
|
211
198
|
}
|
|
212
|
-
function tsvToCsvTransform(maxDataRows, onHeader) {
|
|
199
|
+
function tsvToCsvTransform(maxDataRows, stats, onHeader) {
|
|
213
200
|
const state = createTsvStreamState();
|
|
214
|
-
const emittedRows = { value: 0, };
|
|
215
|
-
let done = false;
|
|
216
201
|
const maxRows = Math.max(1, maxDataRows);
|
|
202
|
+
let headerSeen = false;
|
|
203
|
+
let done = false;
|
|
204
|
+
const handleRow = (row, push) => {
|
|
205
|
+
if (done || isBlankRow(row))
|
|
206
|
+
return;
|
|
207
|
+
if (!headerSeen) {
|
|
208
|
+
headerSeen = true;
|
|
209
|
+
onHeader?.(row);
|
|
210
|
+
push(`${rowToCsv(row)}\n`);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (stats.rows >= maxRows) {
|
|
214
|
+
stats.truncated = true;
|
|
215
|
+
done = true;
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
push(`${rowToCsv(row)}\n`);
|
|
219
|
+
stats.rows += 1;
|
|
220
|
+
};
|
|
217
221
|
return new Transform({
|
|
218
222
|
transform(chunk, _encoding, callback) {
|
|
219
223
|
if (done) {
|
|
220
224
|
callback();
|
|
221
225
|
return;
|
|
222
226
|
}
|
|
223
|
-
consumeTsvChunk(chunk.toString("utf-8"), state, (row) =>
|
|
224
|
-
|
|
225
|
-
return;
|
|
226
|
-
done = emitCsvLineWithLimit(row, maxRows, emittedRows, (line) => {
|
|
227
|
-
this.push(`${line}\n`);
|
|
228
|
-
}, onHeader);
|
|
229
|
-
});
|
|
230
|
-
if (done) {
|
|
227
|
+
consumeTsvChunk(chunk.toString("utf-8"), state, (row) => handleRow(row, (line) => this.push(line)));
|
|
228
|
+
if (done)
|
|
231
229
|
this.push(null);
|
|
232
|
-
}
|
|
233
230
|
callback();
|
|
234
231
|
},
|
|
235
232
|
flush(callback) {
|
|
236
|
-
if (done) {
|
|
237
|
-
|
|
238
|
-
return;
|
|
233
|
+
if (!done) {
|
|
234
|
+
flushTsvStream(state, (row) => handleRow(row, (line) => this.push(line)));
|
|
239
235
|
}
|
|
240
|
-
flushTsvStream(state, (row) => {
|
|
241
|
-
if (done)
|
|
242
|
-
return;
|
|
243
|
-
done = emitCsvLineWithLimit(row, maxRows, emittedRows, (line) => {
|
|
244
|
-
this.push(`${line}\n`);
|
|
245
|
-
}, onHeader);
|
|
246
|
-
});
|
|
247
236
|
callback();
|
|
248
237
|
},
|
|
249
238
|
});
|
|
@@ -387,9 +376,9 @@ export class DatasetsResource extends BaseResource {
|
|
|
387
376
|
await this.client.put(`/public/api/projects/${this.enc(projectKey)}/datasets/${dsEnc}/schema`, { columns, });
|
|
388
377
|
}
|
|
389
378
|
/**
|
|
390
|
-
* Preview dataset
|
|
391
|
-
*
|
|
392
|
-
* data rows
|
|
379
|
+
* Preview dataset rows as structured data: column names plus row arrays,
|
|
380
|
+
* mirroring the sql query shape ({ columns, rows, rowCount }). Streams TSV
|
|
381
|
+
* from the API and returns up to `maxRows` data rows.
|
|
393
382
|
*
|
|
394
383
|
* If `validateColumns` is provided, the first TSV row (header) is checked
|
|
395
384
|
* against the column names. Mismatches emit a warning via onValidationWarning.
|
|
@@ -408,8 +397,9 @@ export class DatasetsResource extends BaseResource {
|
|
|
408
397
|
}
|
|
409
398
|
: undefined;
|
|
410
399
|
if (!res.body)
|
|
411
|
-
return
|
|
412
|
-
|
|
400
|
+
return { columns: [], rows: [], rowCount: 0, };
|
|
401
|
+
const { columns, rows, } = await collectPreviewRows(res.body, maxRows, timeoutMs, onHeader);
|
|
402
|
+
return { columns: columns.map((name) => ({ name, })), rows, rowCount: rows.length, };
|
|
413
403
|
}
|
|
414
404
|
/** Get dataset metadata (tags, custom fields, checklists). */
|
|
415
405
|
async metadata(datasetName, projectKey) {
|
|
@@ -417,13 +407,15 @@ export class DatasetsResource extends BaseResource {
|
|
|
417
407
|
return this.client.get(`/public/api/projects/${this.enc(projectKey)}/datasets/${dsEnc}/metadata`);
|
|
418
408
|
}
|
|
419
409
|
/**
|
|
420
|
-
* Download dataset
|
|
421
|
-
* Returns the
|
|
410
|
+
* Download dataset rows as a gzipped (or .csv) file, capped at `limit` rows
|
|
411
|
+
* (default 100k). Returns the written path, the number of data rows written,
|
|
412
|
+
* whether the dataset had more rows than the cap (truncated), and the limit
|
|
413
|
+
* used — so callers can detect truncation instead of silently getting a sample.
|
|
422
414
|
*/
|
|
423
415
|
async download(datasetName, opts) {
|
|
424
|
-
const
|
|
416
|
+
const limit = Math.max(1, opts?.limit ?? 100_000);
|
|
425
417
|
const dsEnc = encodeURIComponent(datasetName);
|
|
426
|
-
const res = await this.client.stream(`/public/api/projects/${this.enc(opts?.projectKey)}/datasets/${dsEnc}/data/?format=tsv-excel-header&limit=${
|
|
418
|
+
const res = await this.client.stream(`/public/api/projects/${this.enc(opts?.projectKey)}/datasets/${dsEnc}/data/?format=tsv-excel-header&limit=${limit + 1}`);
|
|
427
419
|
const safeDatasetName = sanitizeFileName(datasetName, "dataset");
|
|
428
420
|
const filePath = opts?.outputPath?.endsWith(".gz") || opts?.outputPath?.endsWith(".csv")
|
|
429
421
|
? resolve(opts.outputPath)
|
|
@@ -437,8 +429,9 @@ export class DatasetsResource extends BaseResource {
|
|
|
437
429
|
}
|
|
438
430
|
: undefined;
|
|
439
431
|
const shouldGzip = filePath.endsWith(".gz");
|
|
432
|
+
const stats = { rows: 0, truncated: false, };
|
|
440
433
|
const nodeStream = Readable.fromWeb(res.body);
|
|
441
|
-
const csvTransform = tsvToCsvTransform(
|
|
434
|
+
const csvTransform = tsvToCsvTransform(limit, stats, onHeader);
|
|
442
435
|
const fileOut = createWriteStream(filePath);
|
|
443
436
|
if (shouldGzip) {
|
|
444
437
|
const gzip = createGzip();
|
|
@@ -447,7 +440,7 @@ export class DatasetsResource extends BaseResource {
|
|
|
447
440
|
else {
|
|
448
441
|
await pipeline(nodeStream, csvTransform, fileOut);
|
|
449
442
|
}
|
|
450
|
-
return filePath;
|
|
443
|
+
return { path: filePath, rows: stats.rows, truncated: stats.truncated, limit, };
|
|
451
444
|
}
|
|
452
445
|
/**
|
|
453
446
|
* Create a new dataset.
|
|
@@ -181,7 +181,7 @@ export class JobsResource extends BaseResource {
|
|
|
181
181
|
// DSS cat-activity-log URLs require a browser session; API-key callers must use the public log endpoint.
|
|
182
182
|
const path = `/public/api/projects/${this.enc(opts?.projectKey)}/jobs/${jobEnc}/log/${query}`;
|
|
183
183
|
const log = await this.client.getText(path);
|
|
184
|
-
return limitJobLog(log, opts?.maxLogLines);
|
|
184
|
+
return limitJobLog(filterJobLog(log, opts?.logFilter), opts?.maxLogLines);
|
|
185
185
|
}
|
|
186
186
|
async logFromUrl(logUrl, opts) {
|
|
187
187
|
const parsed = new URL(logUrl, "http://dss.local");
|