windmill-client 1.769.0 → 1.771.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/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 +261 -19
- package/dist/index.mjs +3 -2
- package/dist/services.gen.d.ts +101 -1
- package/dist/services.gen.mjs +193 -7
- package/dist/types.gen.d.ts +436 -0
- 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;
|