windmill-client 1.770.0 → 1.771.1
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/dist/client.d.ts +42 -6
- package/dist/client.mjs +66 -12
- package/dist/core/OpenAPI.mjs +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +181 -16
- package/dist/index.mjs +3 -2
- package/dist/services.gen.d.ts +58 -3
- package/dist/services.gen.mjs +113 -4
- package/dist/types.gen.d.ts +299 -12
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -448,7 +448,11 @@ export declare let _workflowCtx: WorkflowCtx | null;
|
|
|
448
448
|
export declare function setWorkflowCtx(ctx: WorkflowCtx | null): void;
|
|
449
449
|
export declare class WorkflowCtx {
|
|
450
450
|
private completed;
|
|
451
|
+
/** Null-prototype: step keys are caller-supplied, and a plain object would
|
|
452
|
+
* resolve `toString`/`constructor`/`__proto__` off `Object.prototype`. */
|
|
451
453
|
private counters;
|
|
454
|
+
/** Every key handed out by `_allocKey`, so distinct names can't alias one key. */
|
|
455
|
+
private _usedKeys;
|
|
452
456
|
private pending;
|
|
453
457
|
private _suspended;
|
|
454
458
|
/** When set, the task matching this key executes its inner function directly */
|
|
@@ -464,7 +468,10 @@ export declare class WorkflowCtx {
|
|
|
464
468
|
* `completed_steps[key]`. Initialized to a resolved promise. */
|
|
465
469
|
private _inlineChain;
|
|
466
470
|
constructor(checkpoint?: Record<string, any>);
|
|
467
|
-
/** Name-based key: `double` for first call, `double_2`, `double_3` for subsequent.
|
|
471
|
+
/** Name-based key: `double` for first call, `double_2`, `double_3` for subsequent.
|
|
472
|
+
* Suffixing alone can alias — a second `step("x")` and a first `step("x_2")` both
|
|
473
|
+
* want `x_2` — so keep bumping past keys already handed out. Allocation order is
|
|
474
|
+
* fixed by the workflow body, so replays reproduce the same keys. */
|
|
468
475
|
_allocKey(name: string): string;
|
|
469
476
|
_nextStep(name: string, script: string, args?: Record<string, any>, dispatch_type?: string, options?: TaskOptions): PromiseLike<any>;
|
|
470
477
|
/** Return and clear any pending (unawaited) steps. */
|
|
@@ -479,6 +486,7 @@ export declare class WorkflowCtx {
|
|
|
479
486
|
timeout?: number;
|
|
480
487
|
form?: object;
|
|
481
488
|
selfApproval?: boolean;
|
|
489
|
+
key?: string;
|
|
482
490
|
}): PromiseLike<{
|
|
483
491
|
value: any;
|
|
484
492
|
approver: string;
|
|
@@ -529,23 +537,51 @@ export declare function workflow<T>(fn: (...args: any[]) => Promise<T>): (...arg
|
|
|
529
537
|
/**
|
|
530
538
|
* Suspend the workflow and wait for an external approval.
|
|
531
539
|
*
|
|
532
|
-
*
|
|
533
|
-
*
|
|
540
|
+
* Pass `key` to name the step, then `getApprovalUrls(key)` yields the URLs that
|
|
541
|
+
* resume exactly this approval — route them through your own channel. Without a
|
|
542
|
+
* key the steps are named `approval`, `approval_2`, ...
|
|
534
543
|
*
|
|
535
544
|
* @example
|
|
536
|
-
* const urls = await step("urls", () =>
|
|
537
|
-
* await step("notify", () => sendEmail(urls.
|
|
538
|
-
* const { value, approver } = await waitForApproval({ timeout: 3600 });
|
|
545
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
546
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
547
|
+
* const { value, approver } = await waitForApproval({ key: "manager", timeout: 3600 });
|
|
539
548
|
*/
|
|
540
549
|
export declare function waitForApproval(options?: {
|
|
541
550
|
timeout?: number;
|
|
542
551
|
form?: object;
|
|
543
552
|
selfApproval?: boolean;
|
|
553
|
+
key?: string;
|
|
544
554
|
}): PromiseLike<{
|
|
545
555
|
value: any;
|
|
546
556
|
approver: string;
|
|
547
557
|
approved: boolean;
|
|
548
558
|
}>;
|
|
559
|
+
/**
|
|
560
|
+
* Resume/cancel/approval-page URLs bound to one `waitForApproval` step.
|
|
561
|
+
*
|
|
562
|
+
* Unlike `getResumeUrls()`, which signs a random nonce, these address the very
|
|
563
|
+
* `resume_job` record the step's built-in approval buttons use, so they are
|
|
564
|
+
* stable across replays and safe to embed in a custom notification.
|
|
565
|
+
*
|
|
566
|
+
* `stepKey` must match the `key` given to `waitForApproval`. Keys must be unique
|
|
567
|
+
* within a workflow; reusing one throws rather than silently renaming it. The URL
|
|
568
|
+
* only resumes while that step is awaiting approval; used at any other moment it is
|
|
569
|
+
* rejected rather than banking a row a different approval would consume. Send it
|
|
570
|
+
* ahead of time — approvers just cannot act before the workflow reaches the step.
|
|
571
|
+
*
|
|
572
|
+
* `resume` and `cancel` are step-bound; `approvalPage` is not — it opens the job's
|
|
573
|
+
* approval page, which acts on whichever approval is pending when it is used.
|
|
574
|
+
*
|
|
575
|
+
* @example
|
|
576
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
577
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
578
|
+
* await waitForApproval({ key: "manager" });
|
|
579
|
+
*/
|
|
580
|
+
export declare function getApprovalUrls(stepKey?: string, approver?: string): Promise<{
|
|
581
|
+
approvalPage: string;
|
|
582
|
+
resume: string;
|
|
583
|
+
cancel: string;
|
|
584
|
+
}>;
|
|
549
585
|
/**
|
|
550
586
|
* Process items in parallel with optional concurrency control.
|
|
551
587
|
*
|
package/dist/client.mjs
CHANGED
|
@@ -958,6 +958,13 @@ var StepSuspend = class extends Error {
|
|
|
958
958
|
this.name = "StepSuspend";
|
|
959
959
|
}
|
|
960
960
|
};
|
|
961
|
+
/** A step key travels as one path segment when its URLs are minted, so it must be
|
|
962
|
+
* non-empty and free of `/` and dot segments — otherwise `waitForApproval` would
|
|
963
|
+
* accept a key `getApprovalUrls` can never address. */
|
|
964
|
+
function assertUsableStepKey(key, what) {
|
|
965
|
+
const k = key.trim();
|
|
966
|
+
if (k === "" || k === "." || k === ".." || key.includes("/") || key.includes("\\")) throw new Error(`${what} must be a non-empty step name without \`/\` or dot segments`);
|
|
967
|
+
}
|
|
961
968
|
let _workflowCtx = null;
|
|
962
969
|
function setWorkflowCtx(ctx) {
|
|
963
970
|
_workflowCtx = ctx;
|
|
@@ -965,7 +972,11 @@ function setWorkflowCtx(ctx) {
|
|
|
965
972
|
}
|
|
966
973
|
var WorkflowCtx = class {
|
|
967
974
|
completed;
|
|
968
|
-
|
|
975
|
+
/** Null-prototype: step keys are caller-supplied, and a plain object would
|
|
976
|
+
* resolve `toString`/`constructor`/`__proto__` off `Object.prototype`. */
|
|
977
|
+
counters = Object.create(null);
|
|
978
|
+
/** Every key handed out by `_allocKey`, so distinct names can't alias one key. */
|
|
979
|
+
_usedKeys = new Set();
|
|
969
980
|
pending = [];
|
|
970
981
|
_suspended = false;
|
|
971
982
|
/** When set, the task matching this key executes its inner function directly */
|
|
@@ -981,14 +992,23 @@ var WorkflowCtx = class {
|
|
|
981
992
|
* `completed_steps[key]`. Initialized to a resolved promise. */
|
|
982
993
|
_inlineChain = Promise.resolve();
|
|
983
994
|
constructor(checkpoint = {}) {
|
|
984
|
-
this.completed = checkpoint?.completed_steps ?? {};
|
|
995
|
+
this.completed = Object.assign(Object.create(null), checkpoint?.completed_steps ?? {});
|
|
985
996
|
this._executingKey = checkpoint?._executing_key ?? null;
|
|
986
997
|
}
|
|
987
|
-
/** Name-based key: `double` for first call, `double_2`, `double_3` for subsequent.
|
|
998
|
+
/** Name-based key: `double` for first call, `double_2`, `double_3` for subsequent.
|
|
999
|
+
* Suffixing alone can alias — a second `step("x")` and a first `step("x_2")` both
|
|
1000
|
+
* want `x_2` — so keep bumping past keys already handed out. Allocation order is
|
|
1001
|
+
* fixed by the workflow body, so replays reproduce the same keys. */
|
|
988
1002
|
_allocKey(name) {
|
|
989
|
-
|
|
1003
|
+
let n = (this.counters[name] ?? 0) + 1;
|
|
1004
|
+
let key = n === 1 ? name : `${name}_${n}`;
|
|
1005
|
+
while (this._usedKeys.has(key)) {
|
|
1006
|
+
n++;
|
|
1007
|
+
key = `${name}_${n}`;
|
|
1008
|
+
}
|
|
990
1009
|
this.counters[name] = n;
|
|
991
|
-
|
|
1010
|
+
this._usedKeys.add(key);
|
|
1011
|
+
return key;
|
|
992
1012
|
}
|
|
993
1013
|
_nextStep(name, script, args = {}, dispatch_type = "inline", options) {
|
|
994
1014
|
const key = this._allocKey(name || script || "step");
|
|
@@ -1048,7 +1068,9 @@ var WorkflowCtx = class {
|
|
|
1048
1068
|
return steps;
|
|
1049
1069
|
}
|
|
1050
1070
|
_waitForApproval(options) {
|
|
1051
|
-
|
|
1071
|
+
if (options?.key !== void 0) assertUsableStepKey(options.key, "waitForApproval key");
|
|
1072
|
+
const key = this._allocKey(options?.key || "approval");
|
|
1073
|
+
if (options?.key && key !== options.key) throw new Error(`WAC step key "${options.key}" is already used in this workflow. Give each waitForApproval() its own key so getApprovalUrls() can address it.`);
|
|
1052
1074
|
if (key in this.completed) {
|
|
1053
1075
|
const value = this.completed[key];
|
|
1054
1076
|
return { then: (resolve) => resolve(value) };
|
|
@@ -1287,13 +1309,14 @@ function workflow(fn) {
|
|
|
1287
1309
|
/**
|
|
1288
1310
|
* Suspend the workflow and wait for an external approval.
|
|
1289
1311
|
*
|
|
1290
|
-
*
|
|
1291
|
-
*
|
|
1312
|
+
* Pass `key` to name the step, then `getApprovalUrls(key)` yields the URLs that
|
|
1313
|
+
* resume exactly this approval — route them through your own channel. Without a
|
|
1314
|
+
* key the steps are named `approval`, `approval_2`, ...
|
|
1292
1315
|
*
|
|
1293
1316
|
* @example
|
|
1294
|
-
* const urls = await step("urls", () =>
|
|
1295
|
-
* await step("notify", () => sendEmail(urls.
|
|
1296
|
-
* const { value, approver } = await waitForApproval({ timeout: 3600 });
|
|
1317
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
1318
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
1319
|
+
* const { value, approver } = await waitForApproval({ key: "manager", timeout: 3600 });
|
|
1297
1320
|
*/
|
|
1298
1321
|
function waitForApproval(options) {
|
|
1299
1322
|
const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
|
|
@@ -1301,6 +1324,37 @@ function waitForApproval(options) {
|
|
|
1301
1324
|
return ctx._waitForApproval(options);
|
|
1302
1325
|
}
|
|
1303
1326
|
/**
|
|
1327
|
+
* Resume/cancel/approval-page URLs bound to one `waitForApproval` step.
|
|
1328
|
+
*
|
|
1329
|
+
* Unlike `getResumeUrls()`, which signs a random nonce, these address the very
|
|
1330
|
+
* `resume_job` record the step's built-in approval buttons use, so they are
|
|
1331
|
+
* stable across replays and safe to embed in a custom notification.
|
|
1332
|
+
*
|
|
1333
|
+
* `stepKey` must match the `key` given to `waitForApproval`. Keys must be unique
|
|
1334
|
+
* within a workflow; reusing one throws rather than silently renaming it. The URL
|
|
1335
|
+
* only resumes while that step is awaiting approval; used at any other moment it is
|
|
1336
|
+
* rejected rather than banking a row a different approval would consume. Send it
|
|
1337
|
+
* ahead of time — approvers just cannot act before the workflow reaches the step.
|
|
1338
|
+
*
|
|
1339
|
+
* `resume` and `cancel` are step-bound; `approvalPage` is not — it opens the job's
|
|
1340
|
+
* approval page, which acts on whichever approval is pending when it is used.
|
|
1341
|
+
*
|
|
1342
|
+
* @example
|
|
1343
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
1344
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
1345
|
+
* await waitForApproval({ key: "manager" });
|
|
1346
|
+
*/
|
|
1347
|
+
async function getApprovalUrls(stepKey = "approval", approver) {
|
|
1348
|
+
assertUsableStepKey(stepKey, "getApprovalUrls stepKey");
|
|
1349
|
+
const workspace = getWorkspace();
|
|
1350
|
+
return await JobService.getWacApprovalUrls({
|
|
1351
|
+
workspace,
|
|
1352
|
+
stepKey,
|
|
1353
|
+
approver,
|
|
1354
|
+
id: getEnv("WM_JOB_ID") ?? "NO_JOB_ID"
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1357
|
+
/**
|
|
1304
1358
|
* Process items in parallel with optional concurrency control.
|
|
1305
1359
|
*
|
|
1306
1360
|
* Each item is processed by calling `fn(item)`, which should be a task().
|
|
@@ -1342,4 +1396,4 @@ async function commitKafkaOffsets(triggerPath, topic, partition, offset) {
|
|
|
1342
1396
|
}
|
|
1343
1397
|
|
|
1344
1398
|
//#endregion
|
|
1345
|
-
export { SHARED_FOLDER, StepSuspend, WorkflowCtx, _workflowCtx, appendToResultStream, base64ToUint8Array, commitKafkaOffsets, databaseUrlFromResource, deleteS3File, denoS3LightClientSettings, getEnv, getFlowUserState, getIdToken, getInternalState, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResult, getResultMaybe, getResumeEndpoints, getResumeUrls, getRootJobId, getState, getStatePath, getVariable, getWorkspace, loadS3File, loadS3FileStream, parallel, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, resolveDefaultResource, runFlow, runFlowAsync, runScript, runScriptAsync, runScriptByHash, runScriptByHashAsync, runScriptByPath, runScriptByPathAsync, setClient, setFlowUserState, setInternalState, setProgress, setResource, setState, setVariable, setWorkflowCtx, signS3Object, signS3Objects, sleep, step, streamResult, task, taskFlow, taskScript, uint8ArrayToBase64, usernameToEmail, waitForApproval, waitJob, workerHasInternalServer, workflow, writeS3File };
|
|
1399
|
+
export { SHARED_FOLDER, StepSuspend, WorkflowCtx, _workflowCtx, appendToResultStream, base64ToUint8Array, commitKafkaOffsets, databaseUrlFromResource, deleteS3File, denoS3LightClientSettings, getApprovalUrls, getEnv, getFlowUserState, getIdToken, getInternalState, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResult, getResultMaybe, getResumeEndpoints, getResumeUrls, getRootJobId, getState, getStatePath, getVariable, getWorkspace, loadS3File, loadS3FileStream, parallel, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, resolveDefaultResource, runFlow, runFlowAsync, runScript, runScriptAsync, runScriptByHash, runScriptByHashAsync, runScriptByPath, runScriptByPathAsync, setClient, setFlowUserState, setInternalState, setProgress, setResource, setState, setVariable, setWorkflowCtx, signS3Object, signS3Objects, sleep, step, streamResult, task, taskFlow, taskScript, uint8ArrayToBase64, usernameToEmail, waitForApproval, waitJob, workerHasInternalServer, workflow, writeS3File };
|
package/dist/core/OpenAPI.mjs
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ export { OpenAPI, type OpenAPIConfig } from './core/OpenAPI';
|
|
|
4
4
|
export * from './services.gen';
|
|
5
5
|
export * from './types.gen';
|
|
6
6
|
export type { DenoS3LightClientSettings } from "./s3Types";
|
|
7
|
-
export { type Base64, setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, deleteS3File, signS3Objects, signS3Object, getPresignedS3PublicUrls, getPresignedS3PublicUrl, task, taskScript, taskFlow, workflow, step, sleep, parallel, waitForApproval, type TaskOptions, WorkflowCtx, _workflowCtx, setWorkflowCtx, StepSuspend, runScript, runScriptAsync, runScriptByPath, runScriptByHash, runScriptByPathAsync, runScriptByHashAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, type Sql, requestInteractiveTeamsApproval, appendToResultStream, streamResult, datatable, ducklake, upsertPartition, appendPartition, type DucklakeMaterializeOptions, type SqlStatement, type DatatableSqlTemplateFunction, type SqlTemplateFunction, type S3Object, type S3ObjectRecord, type S3ObjectURI, commitKafkaOffsets } from "./client";
|
|
8
|
-
import { setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, deleteS3File, signS3Objects, signS3Object, getPresignedS3PublicUrls, getPresignedS3PublicUrl, task, taskScript, taskFlow, workflow, step, sleep, parallel, waitForApproval, WorkflowCtx, setWorkflowCtx, StepSuspend, runScript, runScriptAsync, runScriptByPath, runScriptByHash, runScriptByPathAsync, runScriptByHashAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, appendToResultStream, streamResult, datatable, ducklake, upsertPartition, appendPartition, getWorkspace, getStatePath, getInternalState, setInternalState, getResumeEndpoints, getResult, getResultMaybe, resolveDefaultResource, databaseUrlFromResource, base64ToUint8Array, uint8ArrayToBase64, parseS3Object, commitKafkaOffsets } from "./client";
|
|
7
|
+
export { type Base64, setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, deleteS3File, signS3Objects, signS3Object, getPresignedS3PublicUrls, getPresignedS3PublicUrl, task, taskScript, taskFlow, workflow, step, sleep, parallel, waitForApproval, getApprovalUrls, type TaskOptions, WorkflowCtx, _workflowCtx, setWorkflowCtx, StepSuspend, runScript, runScriptAsync, runScriptByPath, runScriptByHash, runScriptByPathAsync, runScriptByHashAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, type Sql, requestInteractiveTeamsApproval, appendToResultStream, streamResult, datatable, ducklake, upsertPartition, appendPartition, type DucklakeMaterializeOptions, type SqlStatement, type DatatableSqlTemplateFunction, type SqlTemplateFunction, type S3Object, type S3ObjectRecord, type S3ObjectURI, commitKafkaOffsets } from "./client";
|
|
8
|
+
import { setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, deleteS3File, signS3Objects, signS3Object, getPresignedS3PublicUrls, getPresignedS3PublicUrl, task, taskScript, taskFlow, workflow, step, sleep, parallel, waitForApproval, getApprovalUrls, WorkflowCtx, setWorkflowCtx, StepSuspend, runScript, runScriptAsync, runScriptByPath, runScriptByHash, runScriptByPathAsync, runScriptByHashAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, appendToResultStream, streamResult, datatable, ducklake, upsertPartition, appendPartition, getWorkspace, getStatePath, getInternalState, setInternalState, getResumeEndpoints, getResult, getResultMaybe, resolveDefaultResource, databaseUrlFromResource, base64ToUint8Array, uint8ArrayToBase64, parseS3Object, commitKafkaOffsets } from "./client";
|
|
9
9
|
import { AdminService, AuditService, FlowService, GranularAclService, GroupService, JobService, ResourceService, VariableService, ScriptService, ScheduleService, SettingsService, UserService, WorkspaceService, TeamsService } from "./services.gen";
|
|
10
10
|
declare const wmill: {
|
|
11
11
|
setClient: typeof setClient;
|
|
@@ -36,6 +36,7 @@ declare const wmill: {
|
|
|
36
36
|
sleep: typeof sleep;
|
|
37
37
|
parallel: typeof parallel;
|
|
38
38
|
waitForApproval: typeof waitForApproval;
|
|
39
|
+
getApprovalUrls: typeof getApprovalUrls;
|
|
39
40
|
WorkflowCtx: typeof WorkflowCtx;
|
|
40
41
|
_workflowCtx: WorkflowCtx | null;
|
|
41
42
|
setWorkflowCtx: typeof setWorkflowCtx;
|
package/dist/index.js
CHANGED
|
@@ -126,7 +126,7 @@ const OpenAPI = {
|
|
|
126
126
|
PASSWORD: void 0,
|
|
127
127
|
TOKEN: getEnv$1("WM_TOKEN"),
|
|
128
128
|
USERNAME: void 0,
|
|
129
|
-
VERSION: "1.
|
|
129
|
+
VERSION: "1.771.1",
|
|
130
130
|
WITH_CREDENTIALS: true,
|
|
131
131
|
interceptors: {
|
|
132
132
|
request: new Interceptors(),
|
|
@@ -7445,6 +7445,42 @@ var ScriptService = class {
|
|
|
7445
7445
|
mediaType: "application/json"
|
|
7446
7446
|
});
|
|
7447
7447
|
}
|
|
7448
|
+
/**
|
|
7449
|
+
* list runnables (scripts, flows, apps) merged, ordered and keyset-paginated
|
|
7450
|
+
* @param data The data for the request.
|
|
7451
|
+
* @param data.workspace
|
|
7452
|
+
* @param data.orderBy sort key: 'updated' (default) or 'name'
|
|
7453
|
+
* @param data.orderDesc order by desc order (default true)
|
|
7454
|
+
* @param data.kinds comma-separated subset of script,flow,app (default all)
|
|
7455
|
+
* @param data.showArchived
|
|
7456
|
+
* @param data.includeWithoutMain include library scripts (no runnable main)
|
|
7457
|
+
* @param data.pathStart restrict to paths under this prefix
|
|
7458
|
+
* @param data.label
|
|
7459
|
+
* @param data.search case-insensitive substring match on summary or path
|
|
7460
|
+
* @param data.perPage number of items to return for a given page (default 30, max 100)
|
|
7461
|
+
* @param data.cursor opaque keyset cursor from a previous page's next_cursor
|
|
7462
|
+
* @returns unknown a page of merged, ordered runnables
|
|
7463
|
+
* @throws ApiError
|
|
7464
|
+
*/
|
|
7465
|
+
static listRunnables(data) {
|
|
7466
|
+
return request(OpenAPI, {
|
|
7467
|
+
method: "GET",
|
|
7468
|
+
url: "/w/{workspace}/runnables/list",
|
|
7469
|
+
path: { workspace: data.workspace },
|
|
7470
|
+
query: {
|
|
7471
|
+
order_by: data.orderBy,
|
|
7472
|
+
order_desc: data.orderDesc,
|
|
7473
|
+
kinds: data.kinds,
|
|
7474
|
+
show_archived: data.showArchived,
|
|
7475
|
+
include_without_main: data.includeWithoutMain,
|
|
7476
|
+
path_start: data.pathStart,
|
|
7477
|
+
label: data.label,
|
|
7478
|
+
search: data.search,
|
|
7479
|
+
per_page: data.perPage,
|
|
7480
|
+
cursor: data.cursor
|
|
7481
|
+
}
|
|
7482
|
+
});
|
|
7483
|
+
}
|
|
7448
7484
|
};
|
|
7449
7485
|
var DraftService = class {
|
|
7450
7486
|
/**
|
|
@@ -8975,6 +9011,7 @@ var JobService = class {
|
|
|
8975
9011
|
* @param data.page which page to return (start at 1, default 1)
|
|
8976
9012
|
* @param data.perPage number of items to return for a given page (default 30, max 100)
|
|
8977
9013
|
* @param data.isSkipped is the job skipped
|
|
9014
|
+
* @param data.resolved filter on whether a failure has been marked as handled. true keeps only resolved failures, false hides them
|
|
8978
9015
|
* @param data.isFlowStep is the job a flow step
|
|
8979
9016
|
* @param data.hasNullParent has null parent
|
|
8980
9017
|
* @param data.success filter on successful jobs
|
|
@@ -9016,6 +9053,7 @@ var JobService = class {
|
|
|
9016
9053
|
page: data.page,
|
|
9017
9054
|
per_page: data.perPage,
|
|
9018
9055
|
is_skipped: data.isSkipped,
|
|
9056
|
+
resolved: data.resolved,
|
|
9019
9057
|
is_flow_step: data.isFlowStep,
|
|
9020
9058
|
has_null_parent: data.hasNullParent,
|
|
9021
9059
|
success: data.success,
|
|
@@ -9153,6 +9191,7 @@ var JobService = class {
|
|
|
9153
9191
|
* @param data.page which page to return (start at 1, default 1)
|
|
9154
9192
|
* @param data.perPage number of items to return for a given page (default 30, max 100)
|
|
9155
9193
|
* @param data.isSkipped is the job skipped
|
|
9194
|
+
* @param data.resolved filter on whether a failure has been marked as handled. true keeps only resolved failures, false hides them
|
|
9156
9195
|
* @param data.isFlowStep is the job a flow step
|
|
9157
9196
|
* @param data.hasNullParent has null parent
|
|
9158
9197
|
* @param data.isNotSchedule is not a scheduled job
|
|
@@ -9186,6 +9225,7 @@ var JobService = class {
|
|
|
9186
9225
|
page: data.page,
|
|
9187
9226
|
per_page: data.perPage,
|
|
9188
9227
|
is_skipped: data.isSkipped,
|
|
9228
|
+
resolved: data.resolved,
|
|
9189
9229
|
is_flow_step: data.isFlowStep,
|
|
9190
9230
|
has_null_parent: data.hasNullParent,
|
|
9191
9231
|
is_not_schedule: data.isNotSchedule
|
|
@@ -9314,6 +9354,7 @@ var JobService = class {
|
|
|
9314
9354
|
* @param data.perPage number of items to return for a given page (default 30, max 100)
|
|
9315
9355
|
* @param data.triggerKind filter by trigger kind. Supports comma-separated list (e.g. 'schedule,webhook') and negation by prefixing all values with '!' (e.g. '!schedule,!webhook')
|
|
9316
9356
|
* @param data.isSkipped is the job skipped
|
|
9357
|
+
* @param data.resolved filter on whether a failure has been marked as handled. true keeps only resolved failures, false hides them
|
|
9317
9358
|
* @param data.isFlowStep is the job a flow step
|
|
9318
9359
|
* @param data.hasNullParent has null parent
|
|
9319
9360
|
* @param data.success filter on successful jobs
|
|
@@ -9358,6 +9399,7 @@ var JobService = class {
|
|
|
9358
9399
|
per_page: data.perPage,
|
|
9359
9400
|
trigger_kind: data.triggerKind,
|
|
9360
9401
|
is_skipped: data.isSkipped,
|
|
9402
|
+
resolved: data.resolved,
|
|
9361
9403
|
is_flow_step: data.isFlowStep,
|
|
9362
9404
|
has_null_parent: data.hasNullParent,
|
|
9363
9405
|
success: data.success,
|
|
@@ -9796,6 +9838,41 @@ var JobService = class {
|
|
|
9796
9838
|
});
|
|
9797
9839
|
}
|
|
9798
9840
|
/**
|
|
9841
|
+
* mark failed jobs as resolved
|
|
9842
|
+
* Marks failed jobs as handled so triage surfaces stop showing them as failures. The job status itself is unchanged. Returns the ids actually resolved: ids that are not visible to the caller or did not fail are silently skipped.
|
|
9843
|
+
* @param data The data for the request.
|
|
9844
|
+
* @param data.workspace
|
|
9845
|
+
* @param data.requestBody
|
|
9846
|
+
* @returns string ids of the jobs that were resolved
|
|
9847
|
+
* @throws ApiError
|
|
9848
|
+
*/
|
|
9849
|
+
static resolveCompletedJobs(data) {
|
|
9850
|
+
return request(OpenAPI, {
|
|
9851
|
+
method: "POST",
|
|
9852
|
+
url: "/w/{workspace}/jobs/completed/resolve",
|
|
9853
|
+
path: { workspace: data.workspace },
|
|
9854
|
+
body: data.requestBody,
|
|
9855
|
+
mediaType: "application/json"
|
|
9856
|
+
});
|
|
9857
|
+
}
|
|
9858
|
+
/**
|
|
9859
|
+
* remove the resolution of failed jobs
|
|
9860
|
+
* @param data The data for the request.
|
|
9861
|
+
* @param data.workspace
|
|
9862
|
+
* @param data.requestBody
|
|
9863
|
+
* @returns string ids of the jobs that were unresolved
|
|
9864
|
+
* @throws ApiError
|
|
9865
|
+
*/
|
|
9866
|
+
static unresolveCompletedJobs(data) {
|
|
9867
|
+
return request(OpenAPI, {
|
|
9868
|
+
method: "POST",
|
|
9869
|
+
url: "/w/{workspace}/jobs/completed/unresolve",
|
|
9870
|
+
path: { workspace: data.workspace },
|
|
9871
|
+
body: data.requestBody,
|
|
9872
|
+
mediaType: "application/json"
|
|
9873
|
+
});
|
|
9874
|
+
}
|
|
9875
|
+
/**
|
|
9799
9876
|
* cancel queued or running job
|
|
9800
9877
|
* @param data The data for the request.
|
|
9801
9878
|
* @param data.workspace
|
|
@@ -9943,6 +10020,28 @@ var JobService = class {
|
|
|
9943
10020
|
});
|
|
9944
10021
|
}
|
|
9945
10022
|
/**
|
|
10023
|
+
* get the resume urls bound to a specific wait_for_approval step of a workflow-as-code job
|
|
10024
|
+
* @param data The data for the request.
|
|
10025
|
+
* @param data.workspace
|
|
10026
|
+
* @param data.id
|
|
10027
|
+
* @param data.stepKey checkpoint key of the wait_for_approval step, as passed to `wait_for_approval(key=...)`
|
|
10028
|
+
* @param data.approver
|
|
10029
|
+
* @returns unknown url endpoints
|
|
10030
|
+
* @throws ApiError
|
|
10031
|
+
*/
|
|
10032
|
+
static getWacApprovalUrls(data) {
|
|
10033
|
+
return request(OpenAPI, {
|
|
10034
|
+
method: "GET",
|
|
10035
|
+
url: "/w/{workspace}/jobs/wac_approval_urls/{id}/{step_key}",
|
|
10036
|
+
path: {
|
|
10037
|
+
workspace: data.workspace,
|
|
10038
|
+
id: data.id,
|
|
10039
|
+
step_key: data.stepKey
|
|
10040
|
+
},
|
|
10041
|
+
query: { approver: data.approver }
|
|
10042
|
+
});
|
|
10043
|
+
}
|
|
10044
|
+
/**
|
|
9946
10045
|
* generate interactive slack approval for suspended job
|
|
9947
10046
|
* @param data The data for the request.
|
|
9948
10047
|
* @param data.workspace
|
|
@@ -10289,6 +10388,7 @@ var JobService = class {
|
|
|
10289
10388
|
* @param data.perPage number of items to return for a given page (default 30, max 100)
|
|
10290
10389
|
* @param data.triggerKind filter by trigger kind. Supports comma-separated list (e.g. 'schedule,webhook') and negation by prefixing all values with '!' (e.g. '!schedule,!webhook')
|
|
10291
10390
|
* @param data.isSkipped is the job skipped
|
|
10391
|
+
* @param data.resolved filter on whether a failure has been marked as handled. true keeps only resolved failures, false hides them
|
|
10292
10392
|
* @param data.isFlowStep is the job a flow step
|
|
10293
10393
|
* @param data.hasNullParent has null parent
|
|
10294
10394
|
* @param data.success filter on successful jobs
|
|
@@ -10330,6 +10430,7 @@ var JobService = class {
|
|
|
10330
10430
|
per_page: data.perPage,
|
|
10331
10431
|
trigger_kind: data.triggerKind,
|
|
10332
10432
|
is_skipped: data.isSkipped,
|
|
10433
|
+
resolved: data.resolved,
|
|
10333
10434
|
is_flow_step: data.isFlowStep,
|
|
10334
10435
|
has_null_parent: data.hasNullParent,
|
|
10335
10436
|
success: data.success,
|
|
@@ -13857,6 +13958,8 @@ var FolderService = class {
|
|
|
13857
13958
|
* list folder names
|
|
13858
13959
|
* @param data The data for the request.
|
|
13859
13960
|
* @param data.workspace
|
|
13961
|
+
* @param data.page which page to return (start at 1, default 1)
|
|
13962
|
+
* @param data.perPage number of items to return for a given page (default 30, max 100)
|
|
13860
13963
|
* @param data.onlyMemberOf only list the folders the user is member of (default false)
|
|
13861
13964
|
* @returns string folder list
|
|
13862
13965
|
* @throws ApiError
|
|
@@ -13866,7 +13969,11 @@ var FolderService = class {
|
|
|
13866
13969
|
method: "GET",
|
|
13867
13970
|
url: "/w/{workspace}/folders/listnames",
|
|
13868
13971
|
path: { workspace: data.workspace },
|
|
13869
|
-
query: {
|
|
13972
|
+
query: {
|
|
13973
|
+
page: data.page,
|
|
13974
|
+
per_page: data.perPage,
|
|
13975
|
+
only_member_of: data.onlyMemberOf
|
|
13976
|
+
}
|
|
13870
13977
|
});
|
|
13871
13978
|
}
|
|
13872
13979
|
/**
|
|
@@ -15366,6 +15473,7 @@ var ConcurrencyGroupsService = class {
|
|
|
15366
15473
|
* @param data.perPage number of items to return for a given page (default 30, max 100)
|
|
15367
15474
|
* @param data.triggerKind filter by trigger kind. Supports comma-separated list (e.g. 'schedule,webhook') and negation by prefixing all values with '!' (e.g. '!schedule,!webhook')
|
|
15368
15475
|
* @param data.isSkipped is the job skipped
|
|
15476
|
+
* @param data.resolved filter on whether a failure has been marked as handled. true keeps only resolved failures, false hides them
|
|
15369
15477
|
* @param data.isFlowStep is the job a flow step
|
|
15370
15478
|
* @param data.hasNullParent has null parent
|
|
15371
15479
|
* @param data.success filter on successful jobs
|
|
@@ -15407,6 +15515,7 @@ var ConcurrencyGroupsService = class {
|
|
|
15407
15515
|
per_page: data.perPage,
|
|
15408
15516
|
trigger_kind: data.triggerKind,
|
|
15409
15517
|
is_skipped: data.isSkipped,
|
|
15518
|
+
resolved: data.resolved,
|
|
15410
15519
|
is_flow_step: data.isFlowStep,
|
|
15411
15520
|
has_null_parent: data.hasNullParent,
|
|
15412
15521
|
success: data.success,
|
|
@@ -15969,7 +16078,7 @@ var HubPublishService = class {
|
|
|
15969
16078
|
});
|
|
15970
16079
|
}
|
|
15971
16080
|
/**
|
|
15972
|
-
*
|
|
16081
|
+
* attach a recorded session to a hub raw app
|
|
15973
16082
|
* Requires the caller to be a workspace admin. Forwards the request to the
|
|
15974
16083
|
* configured Hub scoped to the `{workspace}:{folder}` source and returns
|
|
15975
16084
|
* the Hub's status code and raw response body.
|
|
@@ -15985,10 +16094,10 @@ var HubPublishService = class {
|
|
|
15985
16094
|
* @returns string raw Hub response body (status code is passed through from the Hub)
|
|
15986
16095
|
* @throws ApiError
|
|
15987
16096
|
*/
|
|
15988
|
-
static
|
|
16097
|
+
static publishHubRawAppRecording(data) {
|
|
15989
16098
|
return request(OpenAPI, {
|
|
15990
16099
|
method: "POST",
|
|
15991
|
-
url: "/w/{workspace}/hub/raw_apps/{id}/
|
|
16100
|
+
url: "/w/{workspace}/hub/raw_apps/{id}/recording",
|
|
15992
16101
|
path: {
|
|
15993
16102
|
workspace: data.workspace,
|
|
15994
16103
|
id: data.id
|
|
@@ -17636,6 +17745,13 @@ var StepSuspend = class extends Error {
|
|
|
17636
17745
|
this.name = "StepSuspend";
|
|
17637
17746
|
}
|
|
17638
17747
|
};
|
|
17748
|
+
/** A step key travels as one path segment when its URLs are minted, so it must be
|
|
17749
|
+
* non-empty and free of `/` and dot segments — otherwise `waitForApproval` would
|
|
17750
|
+
* accept a key `getApprovalUrls` can never address. */
|
|
17751
|
+
function assertUsableStepKey(key, what) {
|
|
17752
|
+
const k = key.trim();
|
|
17753
|
+
if (k === "" || k === "." || k === ".." || key.includes("/") || key.includes("\\")) throw new Error(`${what} must be a non-empty step name without \`/\` or dot segments`);
|
|
17754
|
+
}
|
|
17639
17755
|
let _workflowCtx = null;
|
|
17640
17756
|
function setWorkflowCtx(ctx) {
|
|
17641
17757
|
_workflowCtx = ctx;
|
|
@@ -17643,7 +17759,11 @@ function setWorkflowCtx(ctx) {
|
|
|
17643
17759
|
}
|
|
17644
17760
|
var WorkflowCtx = class {
|
|
17645
17761
|
completed;
|
|
17646
|
-
|
|
17762
|
+
/** Null-prototype: step keys are caller-supplied, and a plain object would
|
|
17763
|
+
* resolve `toString`/`constructor`/`__proto__` off `Object.prototype`. */
|
|
17764
|
+
counters = Object.create(null);
|
|
17765
|
+
/** Every key handed out by `_allocKey`, so distinct names can't alias one key. */
|
|
17766
|
+
_usedKeys = new Set();
|
|
17647
17767
|
pending = [];
|
|
17648
17768
|
_suspended = false;
|
|
17649
17769
|
/** When set, the task matching this key executes its inner function directly */
|
|
@@ -17659,14 +17779,23 @@ var WorkflowCtx = class {
|
|
|
17659
17779
|
* `completed_steps[key]`. Initialized to a resolved promise. */
|
|
17660
17780
|
_inlineChain = Promise.resolve();
|
|
17661
17781
|
constructor(checkpoint = {}) {
|
|
17662
|
-
this.completed = checkpoint?.completed_steps ?? {};
|
|
17782
|
+
this.completed = Object.assign(Object.create(null), checkpoint?.completed_steps ?? {});
|
|
17663
17783
|
this._executingKey = checkpoint?._executing_key ?? null;
|
|
17664
17784
|
}
|
|
17665
|
-
/** Name-based key: `double` for first call, `double_2`, `double_3` for subsequent.
|
|
17785
|
+
/** Name-based key: `double` for first call, `double_2`, `double_3` for subsequent.
|
|
17786
|
+
* Suffixing alone can alias — a second `step("x")` and a first `step("x_2")` both
|
|
17787
|
+
* want `x_2` — so keep bumping past keys already handed out. Allocation order is
|
|
17788
|
+
* fixed by the workflow body, so replays reproduce the same keys. */
|
|
17666
17789
|
_allocKey(name) {
|
|
17667
|
-
|
|
17790
|
+
let n = (this.counters[name] ?? 0) + 1;
|
|
17791
|
+
let key = n === 1 ? name : `${name}_${n}`;
|
|
17792
|
+
while (this._usedKeys.has(key)) {
|
|
17793
|
+
n++;
|
|
17794
|
+
key = `${name}_${n}`;
|
|
17795
|
+
}
|
|
17668
17796
|
this.counters[name] = n;
|
|
17669
|
-
|
|
17797
|
+
this._usedKeys.add(key);
|
|
17798
|
+
return key;
|
|
17670
17799
|
}
|
|
17671
17800
|
_nextStep(name, script, args = {}, dispatch_type = "inline", options) {
|
|
17672
17801
|
const key = this._allocKey(name || script || "step");
|
|
@@ -17726,7 +17855,9 @@ var WorkflowCtx = class {
|
|
|
17726
17855
|
return steps;
|
|
17727
17856
|
}
|
|
17728
17857
|
_waitForApproval(options) {
|
|
17729
|
-
|
|
17858
|
+
if (options?.key !== void 0) assertUsableStepKey(options.key, "waitForApproval key");
|
|
17859
|
+
const key = this._allocKey(options?.key || "approval");
|
|
17860
|
+
if (options?.key && key !== options.key) throw new Error(`WAC step key "${options.key}" is already used in this workflow. Give each waitForApproval() its own key so getApprovalUrls() can address it.`);
|
|
17730
17861
|
if (key in this.completed) {
|
|
17731
17862
|
const value = this.completed[key];
|
|
17732
17863
|
return { then: (resolve$1) => resolve$1(value) };
|
|
@@ -17965,13 +18096,14 @@ function workflow(fn) {
|
|
|
17965
18096
|
/**
|
|
17966
18097
|
* Suspend the workflow and wait for an external approval.
|
|
17967
18098
|
*
|
|
17968
|
-
*
|
|
17969
|
-
*
|
|
18099
|
+
* Pass `key` to name the step, then `getApprovalUrls(key)` yields the URLs that
|
|
18100
|
+
* resume exactly this approval — route them through your own channel. Without a
|
|
18101
|
+
* key the steps are named `approval`, `approval_2`, ...
|
|
17970
18102
|
*
|
|
17971
18103
|
* @example
|
|
17972
|
-
* const urls = await step("urls", () =>
|
|
17973
|
-
* await step("notify", () => sendEmail(urls.
|
|
17974
|
-
* const { value, approver } = await waitForApproval({ timeout: 3600 });
|
|
18104
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
18105
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
18106
|
+
* const { value, approver } = await waitForApproval({ key: "manager", timeout: 3600 });
|
|
17975
18107
|
*/
|
|
17976
18108
|
function waitForApproval(options) {
|
|
17977
18109
|
const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
|
|
@@ -17979,6 +18111,37 @@ function waitForApproval(options) {
|
|
|
17979
18111
|
return ctx._waitForApproval(options);
|
|
17980
18112
|
}
|
|
17981
18113
|
/**
|
|
18114
|
+
* Resume/cancel/approval-page URLs bound to one `waitForApproval` step.
|
|
18115
|
+
*
|
|
18116
|
+
* Unlike `getResumeUrls()`, which signs a random nonce, these address the very
|
|
18117
|
+
* `resume_job` record the step's built-in approval buttons use, so they are
|
|
18118
|
+
* stable across replays and safe to embed in a custom notification.
|
|
18119
|
+
*
|
|
18120
|
+
* `stepKey` must match the `key` given to `waitForApproval`. Keys must be unique
|
|
18121
|
+
* within a workflow; reusing one throws rather than silently renaming it. The URL
|
|
18122
|
+
* only resumes while that step is awaiting approval; used at any other moment it is
|
|
18123
|
+
* rejected rather than banking a row a different approval would consume. Send it
|
|
18124
|
+
* ahead of time — approvers just cannot act before the workflow reaches the step.
|
|
18125
|
+
*
|
|
18126
|
+
* `resume` and `cancel` are step-bound; `approvalPage` is not — it opens the job's
|
|
18127
|
+
* approval page, which acts on whichever approval is pending when it is used.
|
|
18128
|
+
*
|
|
18129
|
+
* @example
|
|
18130
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
18131
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
18132
|
+
* await waitForApproval({ key: "manager" });
|
|
18133
|
+
*/
|
|
18134
|
+
async function getApprovalUrls(stepKey = "approval", approver) {
|
|
18135
|
+
assertUsableStepKey(stepKey, "getApprovalUrls stepKey");
|
|
18136
|
+
const workspace = getWorkspace();
|
|
18137
|
+
return await JobService.getWacApprovalUrls({
|
|
18138
|
+
workspace,
|
|
18139
|
+
stepKey,
|
|
18140
|
+
approver,
|
|
18141
|
+
id: getEnv("WM_JOB_ID") ?? "NO_JOB_ID"
|
|
18142
|
+
});
|
|
18143
|
+
}
|
|
18144
|
+
/**
|
|
17982
18145
|
* Process items in parallel with optional concurrency control.
|
|
17983
18146
|
*
|
|
17984
18147
|
* Each item is processed by calling `fn(item)`, which should be a task().
|
|
@@ -18050,6 +18213,7 @@ const wmill = {
|
|
|
18050
18213
|
sleep,
|
|
18051
18214
|
parallel,
|
|
18052
18215
|
waitForApproval,
|
|
18216
|
+
getApprovalUrls,
|
|
18053
18217
|
WorkflowCtx,
|
|
18054
18218
|
_workflowCtx,
|
|
18055
18219
|
setWorkflowCtx,
|
|
@@ -18189,6 +18353,7 @@ exports.default = src_default;
|
|
|
18189
18353
|
exports.deleteS3File = deleteS3File;
|
|
18190
18354
|
exports.denoS3LightClientSettings = denoS3LightClientSettings;
|
|
18191
18355
|
exports.ducklake = ducklake;
|
|
18356
|
+
exports.getApprovalUrls = getApprovalUrls;
|
|
18192
18357
|
exports.getFlowUserState = getFlowUserState;
|
|
18193
18358
|
exports.getIdToken = getIdToken;
|
|
18194
18359
|
exports.getPresignedS3PublicUrl = getPresignedS3PublicUrl;
|