windmill-cli 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/esm/main.js +290 -55
- package/package.json +1 -1
package/esm/main.js
CHANGED
|
@@ -16784,7 +16784,7 @@ var init_OpenAPI = __esm(() => {
|
|
|
16784
16784
|
PASSWORD: undefined,
|
|
16785
16785
|
TOKEN: getEnv3("WM_TOKEN"),
|
|
16786
16786
|
USERNAME: undefined,
|
|
16787
|
-
VERSION: "1.
|
|
16787
|
+
VERSION: "1.771.1",
|
|
16788
16788
|
WITH_CREDENTIALS: true,
|
|
16789
16789
|
interceptors: {
|
|
16790
16790
|
request: new Interceptors,
|
|
@@ -17103,6 +17103,7 @@ __export(exports_services_gen, {
|
|
|
17103
17103
|
updateApp: () => updateApp,
|
|
17104
17104
|
updateAmqpTrigger: () => updateAmqpTrigger,
|
|
17105
17105
|
unstar: () => unstar,
|
|
17106
|
+
unresolveCompletedJobs: () => unresolveCompletedJobs,
|
|
17106
17107
|
unassignGhesInstallation: () => unassignGhesInstallation,
|
|
17107
17108
|
unarchiveWorkspace: () => unarchiveWorkspace,
|
|
17108
17109
|
toggleWorkspaceErrorHandlerForScript: () => toggleWorkspaceErrorHandlerForScript,
|
|
@@ -17209,6 +17210,7 @@ __export(exports_services_gen, {
|
|
|
17209
17210
|
restartWorkerGroup: () => restartWorkerGroup,
|
|
17210
17211
|
restartFlowAtStep: () => restartFlowAtStep,
|
|
17211
17212
|
resolveNpmPackageVersion: () => resolveNpmPackageVersion,
|
|
17213
|
+
resolveCompletedJobs: () => resolveCompletedJobs,
|
|
17212
17214
|
resetPassword: () => resetPassword,
|
|
17213
17215
|
resetKafkaOffsets: () => resetKafkaOffsets,
|
|
17214
17216
|
resetDiffTally: () => resetDiffTally,
|
|
@@ -17234,7 +17236,7 @@ __export(exports_services_gen, {
|
|
|
17234
17236
|
publishHubScript: () => publishHubScript,
|
|
17235
17237
|
publishHubResources: () => publishHubResources,
|
|
17236
17238
|
publishHubResourceType: () => publishHubResourceType,
|
|
17237
|
-
|
|
17239
|
+
publishHubRawAppRecording: () => publishHubRawAppRecording,
|
|
17238
17240
|
publishHubRawApp: () => publishHubRawApp,
|
|
17239
17241
|
publishHubProjectLogo: () => publishHubProjectLogo,
|
|
17240
17242
|
publishHubPipelineRecording: () => publishHubPipelineRecording,
|
|
@@ -17310,6 +17312,7 @@ __export(exports_services_gen, {
|
|
|
17310
17312
|
listScriptPaths: () => listScriptPaths,
|
|
17311
17313
|
listSchedulesWithJobs: () => listSchedulesWithJobs,
|
|
17312
17314
|
listSchedules: () => listSchedules,
|
|
17315
|
+
listRunnables: () => listRunnables,
|
|
17313
17316
|
listResourceTypeNames: () => listResourceTypeNames,
|
|
17314
17317
|
listResourceType: () => listResourceType,
|
|
17315
17318
|
listResourceNames: () => listResourceNames,
|
|
@@ -17438,6 +17441,7 @@ __export(exports_services_gen, {
|
|
|
17438
17441
|
getWorkspaceDefaultApp: () => getWorkspaceDefaultApp,
|
|
17439
17442
|
getWorkspaceAsSuperAdmin: () => getWorkspaceAsSuperAdmin,
|
|
17440
17443
|
getWebsocketTrigger: () => getWebsocketTrigger,
|
|
17444
|
+
getWacApprovalUrls: () => getWacApprovalUrls,
|
|
17441
17445
|
getVolumeStorage: () => getVolumeStorage,
|
|
17442
17446
|
getVariableValue: () => getVariableValue,
|
|
17443
17447
|
getVariable: () => getVariable,
|
|
@@ -21329,6 +21333,26 @@ var backendVersion = () => {
|
|
|
21329
21333
|
workspace: data3.workspace
|
|
21330
21334
|
}
|
|
21331
21335
|
});
|
|
21336
|
+
}, listRunnables = (data3) => {
|
|
21337
|
+
return request(OpenAPI, {
|
|
21338
|
+
method: "GET",
|
|
21339
|
+
url: "/w/{workspace}/runnables/list",
|
|
21340
|
+
path: {
|
|
21341
|
+
workspace: data3.workspace
|
|
21342
|
+
},
|
|
21343
|
+
query: {
|
|
21344
|
+
order_by: data3.orderBy,
|
|
21345
|
+
order_desc: data3.orderDesc,
|
|
21346
|
+
kinds: data3.kinds,
|
|
21347
|
+
show_archived: data3.showArchived,
|
|
21348
|
+
include_without_main: data3.includeWithoutMain,
|
|
21349
|
+
path_start: data3.pathStart,
|
|
21350
|
+
label: data3.label,
|
|
21351
|
+
search: data3.search,
|
|
21352
|
+
per_page: data3.perPage,
|
|
21353
|
+
cursor: data3.cursor
|
|
21354
|
+
}
|
|
21355
|
+
});
|
|
21332
21356
|
}, listFlows = (data3) => {
|
|
21333
21357
|
return request(OpenAPI, {
|
|
21334
21358
|
method: "GET",
|
|
@@ -22375,6 +22399,7 @@ var backendVersion = () => {
|
|
|
22375
22399
|
page: data3.page,
|
|
22376
22400
|
per_page: data3.perPage,
|
|
22377
22401
|
is_skipped: data3.isSkipped,
|
|
22402
|
+
resolved: data3.resolved,
|
|
22378
22403
|
is_flow_step: data3.isFlowStep,
|
|
22379
22404
|
has_null_parent: data3.hasNullParent,
|
|
22380
22405
|
success: data3.success,
|
|
@@ -22492,6 +22517,7 @@ var backendVersion = () => {
|
|
|
22492
22517
|
page: data3.page,
|
|
22493
22518
|
per_page: data3.perPage,
|
|
22494
22519
|
is_skipped: data3.isSkipped,
|
|
22520
|
+
resolved: data3.resolved,
|
|
22495
22521
|
is_flow_step: data3.isFlowStep,
|
|
22496
22522
|
has_null_parent: data3.hasNullParent,
|
|
22497
22523
|
is_not_schedule: data3.isNotSchedule
|
|
@@ -22586,6 +22612,7 @@ var backendVersion = () => {
|
|
|
22586
22612
|
per_page: data3.perPage,
|
|
22587
22613
|
trigger_kind: data3.triggerKind,
|
|
22588
22614
|
is_skipped: data3.isSkipped,
|
|
22615
|
+
resolved: data3.resolved,
|
|
22589
22616
|
is_flow_step: data3.isFlowStep,
|
|
22590
22617
|
has_null_parent: data3.hasNullParent,
|
|
22591
22618
|
success: data3.success,
|
|
@@ -22818,6 +22845,26 @@ var backendVersion = () => {
|
|
|
22818
22845
|
id: data3.id
|
|
22819
22846
|
}
|
|
22820
22847
|
});
|
|
22848
|
+
}, resolveCompletedJobs = (data3) => {
|
|
22849
|
+
return request(OpenAPI, {
|
|
22850
|
+
method: "POST",
|
|
22851
|
+
url: "/w/{workspace}/jobs/completed/resolve",
|
|
22852
|
+
path: {
|
|
22853
|
+
workspace: data3.workspace
|
|
22854
|
+
},
|
|
22855
|
+
body: data3.requestBody,
|
|
22856
|
+
mediaType: "application/json"
|
|
22857
|
+
});
|
|
22858
|
+
}, unresolveCompletedJobs = (data3) => {
|
|
22859
|
+
return request(OpenAPI, {
|
|
22860
|
+
method: "POST",
|
|
22861
|
+
url: "/w/{workspace}/jobs/completed/unresolve",
|
|
22862
|
+
path: {
|
|
22863
|
+
workspace: data3.workspace
|
|
22864
|
+
},
|
|
22865
|
+
body: data3.requestBody,
|
|
22866
|
+
mediaType: "application/json"
|
|
22867
|
+
});
|
|
22821
22868
|
}, cancelQueuedJob = (data3) => {
|
|
22822
22869
|
return request(OpenAPI, {
|
|
22823
22870
|
method: "POST",
|
|
@@ -22896,6 +22943,19 @@ var backendVersion = () => {
|
|
|
22896
22943
|
flow_level: data3.flowLevel
|
|
22897
22944
|
}
|
|
22898
22945
|
});
|
|
22946
|
+
}, getWacApprovalUrls = (data3) => {
|
|
22947
|
+
return request(OpenAPI, {
|
|
22948
|
+
method: "GET",
|
|
22949
|
+
url: "/w/{workspace}/jobs/wac_approval_urls/{id}/{step_key}",
|
|
22950
|
+
path: {
|
|
22951
|
+
workspace: data3.workspace,
|
|
22952
|
+
id: data3.id,
|
|
22953
|
+
step_key: data3.stepKey
|
|
22954
|
+
},
|
|
22955
|
+
query: {
|
|
22956
|
+
approver: data3.approver
|
|
22957
|
+
}
|
|
22958
|
+
});
|
|
22899
22959
|
}, getSlackApprovalPayload = (data3) => {
|
|
22900
22960
|
return request(OpenAPI, {
|
|
22901
22961
|
method: "GET",
|
|
@@ -24819,6 +24879,8 @@ var backendVersion = () => {
|
|
|
24819
24879
|
workspace: data3.workspace
|
|
24820
24880
|
},
|
|
24821
24881
|
query: {
|
|
24882
|
+
page: data3.page,
|
|
24883
|
+
per_page: data3.perPage,
|
|
24822
24884
|
only_member_of: data3.onlyMemberOf
|
|
24823
24885
|
}
|
|
24824
24886
|
});
|
|
@@ -25687,6 +25749,7 @@ var backendVersion = () => {
|
|
|
25687
25749
|
per_page: data3.perPage,
|
|
25688
25750
|
trigger_kind: data3.triggerKind,
|
|
25689
25751
|
is_skipped: data3.isSkipped,
|
|
25752
|
+
resolved: data3.resolved,
|
|
25690
25753
|
is_flow_step: data3.isFlowStep,
|
|
25691
25754
|
has_null_parent: data3.hasNullParent,
|
|
25692
25755
|
success: data3.success,
|
|
@@ -25989,10 +26052,10 @@ var backendVersion = () => {
|
|
|
25989
26052
|
body: data3.requestBody,
|
|
25990
26053
|
mediaType: "application/json"
|
|
25991
26054
|
});
|
|
25992
|
-
},
|
|
26055
|
+
}, publishHubRawAppRecording = (data3) => {
|
|
25993
26056
|
return request(OpenAPI, {
|
|
25994
26057
|
method: "POST",
|
|
25995
|
-
url: "/w/{workspace}/hub/raw_apps/{id}/
|
|
26058
|
+
url: "/w/{workspace}/hub/raw_apps/{id}/recording",
|
|
25996
26059
|
path: {
|
|
25997
26060
|
workspace: data3.workspace,
|
|
25998
26061
|
id: data3.id
|
|
@@ -26202,6 +26265,7 @@ __export(exports_gen, {
|
|
|
26202
26265
|
updateApp: () => updateApp,
|
|
26203
26266
|
updateAmqpTrigger: () => updateAmqpTrigger,
|
|
26204
26267
|
unstar: () => unstar,
|
|
26268
|
+
unresolveCompletedJobs: () => unresolveCompletedJobs,
|
|
26205
26269
|
unassignGhesInstallation: () => unassignGhesInstallation,
|
|
26206
26270
|
unarchiveWorkspace: () => unarchiveWorkspace,
|
|
26207
26271
|
toggleWorkspaceErrorHandlerForScript: () => toggleWorkspaceErrorHandlerForScript,
|
|
@@ -26308,6 +26372,7 @@ __export(exports_gen, {
|
|
|
26308
26372
|
restartWorkerGroup: () => restartWorkerGroup,
|
|
26309
26373
|
restartFlowAtStep: () => restartFlowAtStep,
|
|
26310
26374
|
resolveNpmPackageVersion: () => resolveNpmPackageVersion,
|
|
26375
|
+
resolveCompletedJobs: () => resolveCompletedJobs,
|
|
26311
26376
|
resetPassword: () => resetPassword,
|
|
26312
26377
|
resetKafkaOffsets: () => resetKafkaOffsets,
|
|
26313
26378
|
resetDiffTally: () => resetDiffTally,
|
|
@@ -26333,7 +26398,7 @@ __export(exports_gen, {
|
|
|
26333
26398
|
publishHubScript: () => publishHubScript,
|
|
26334
26399
|
publishHubResources: () => publishHubResources,
|
|
26335
26400
|
publishHubResourceType: () => publishHubResourceType,
|
|
26336
|
-
|
|
26401
|
+
publishHubRawAppRecording: () => publishHubRawAppRecording,
|
|
26337
26402
|
publishHubRawApp: () => publishHubRawApp,
|
|
26338
26403
|
publishHubProjectLogo: () => publishHubProjectLogo,
|
|
26339
26404
|
publishHubPipelineRecording: () => publishHubPipelineRecording,
|
|
@@ -26409,6 +26474,7 @@ __export(exports_gen, {
|
|
|
26409
26474
|
listScriptPaths: () => listScriptPaths,
|
|
26410
26475
|
listSchedulesWithJobs: () => listSchedulesWithJobs,
|
|
26411
26476
|
listSchedules: () => listSchedules,
|
|
26477
|
+
listRunnables: () => listRunnables,
|
|
26412
26478
|
listResourceTypeNames: () => listResourceTypeNames,
|
|
26413
26479
|
listResourceType: () => listResourceType,
|
|
26414
26480
|
listResourceNames: () => listResourceNames,
|
|
@@ -26537,6 +26603,7 @@ __export(exports_gen, {
|
|
|
26537
26603
|
getWorkspaceDefaultApp: () => getWorkspaceDefaultApp,
|
|
26538
26604
|
getWorkspaceAsSuperAdmin: () => getWorkspaceAsSuperAdmin,
|
|
26539
26605
|
getWebsocketTrigger: () => getWebsocketTrigger,
|
|
26606
|
+
getWacApprovalUrls: () => getWacApprovalUrls,
|
|
26540
26607
|
getVolumeStorage: () => getVolumeStorage,
|
|
26541
26608
|
getVariableValue: () => getVariableValue,
|
|
26542
26609
|
getVariable: () => getVariable,
|
|
@@ -27066,7 +27133,7 @@ var init_auth = __esm(async () => {
|
|
|
27066
27133
|
});
|
|
27067
27134
|
|
|
27068
27135
|
// src/core/constants.ts
|
|
27069
|
-
var WM_FORK_PREFIX = "wm-fork", VERSION = "1.
|
|
27136
|
+
var WM_FORK_PREFIX = "wm-fork", VERSION = "1.771.1";
|
|
27070
27137
|
|
|
27071
27138
|
// src/utils/git.ts
|
|
27072
27139
|
var exports_git = {};
|
|
@@ -82088,15 +82155,43 @@ workflow<T>(fn: (...args: any[]) => Promise<T>): void
|
|
|
82088
82155
|
/**
|
|
82089
82156
|
* Suspend the workflow and wait for an external approval.
|
|
82090
82157
|
*
|
|
82091
|
-
*
|
|
82092
|
-
*
|
|
82158
|
+
* Pass \`key\` to name the step, then \`getApprovalUrls(key)\` yields the URLs that
|
|
82159
|
+
* resume exactly this approval — route them through your own channel. Without a
|
|
82160
|
+
* key the steps are named \`approval\`, \`approval_2\`, ...
|
|
82161
|
+
*
|
|
82162
|
+
* @example
|
|
82163
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
82164
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
82165
|
+
* const { value, approver } = await waitForApproval({ key: "manager", timeout: 3600 });
|
|
82166
|
+
*/
|
|
82167
|
+
waitForApproval(options?: { timeout?: number; form?: object; selfApproval?: boolean; key?: string; }): PromiseLike<{ value: any; approver: string; approved: boolean }>
|
|
82168
|
+
|
|
82169
|
+
/**
|
|
82170
|
+
* Resume/cancel/approval-page URLs bound to one \`waitForApproval\` step.
|
|
82171
|
+
*
|
|
82172
|
+
* Unlike \`getResumeUrls()\`, which signs a random nonce, these address the very
|
|
82173
|
+
* \`resume_job\` record the step's built-in approval buttons use, so they are
|
|
82174
|
+
* stable across replays and safe to embed in a custom notification.
|
|
82175
|
+
*
|
|
82176
|
+
* \`stepKey\` must match the \`key\` given to \`waitForApproval\`. Keys must be unique
|
|
82177
|
+
* within a workflow; reusing one throws rather than silently renaming it. The URL
|
|
82178
|
+
* only resumes while that step is awaiting approval; used at any other moment it is
|
|
82179
|
+
* rejected rather than banking a row a different approval would consume. Send it
|
|
82180
|
+
* ahead of time — approvers just cannot act before the workflow reaches the step.
|
|
82181
|
+
*
|
|
82182
|
+
* \`resume\` and \`cancel\` are step-bound; \`approvalPage\` is not — it opens the job's
|
|
82183
|
+
* approval page, which acts on whichever approval is pending when it is used.
|
|
82093
82184
|
*
|
|
82094
82185
|
* @example
|
|
82095
|
-
* const urls = await step("urls", () =>
|
|
82096
|
-
* await step("notify", () => sendEmail(urls.
|
|
82097
|
-
*
|
|
82186
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
82187
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
82188
|
+
* await waitForApproval({ key: "manager" });
|
|
82098
82189
|
*/
|
|
82099
|
-
|
|
82190
|
+
async getApprovalUrls(stepKey: string = "approval", approver?: string): Promise<{
|
|
82191
|
+
approvalPage: string;
|
|
82192
|
+
resume: string;
|
|
82193
|
+
cancel: string;
|
|
82194
|
+
}>
|
|
82100
82195
|
|
|
82101
82196
|
/**
|
|
82102
82197
|
* Process items in parallel with optional concurrency control.
|
|
@@ -82852,15 +82947,43 @@ workflow<T>(fn: (...args: any[]) => Promise<T>): void
|
|
|
82852
82947
|
/**
|
|
82853
82948
|
* Suspend the workflow and wait for an external approval.
|
|
82854
82949
|
*
|
|
82855
|
-
*
|
|
82856
|
-
*
|
|
82950
|
+
* Pass \`key\` to name the step, then \`getApprovalUrls(key)\` yields the URLs that
|
|
82951
|
+
* resume exactly this approval — route them through your own channel. Without a
|
|
82952
|
+
* key the steps are named \`approval\`, \`approval_2\`, ...
|
|
82857
82953
|
*
|
|
82858
82954
|
* @example
|
|
82859
|
-
* const urls = await step("urls", () =>
|
|
82860
|
-
* await step("notify", () => sendEmail(urls.
|
|
82861
|
-
* const { value, approver } = await waitForApproval({ timeout: 3600 });
|
|
82955
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
82956
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
82957
|
+
* const { value, approver } = await waitForApproval({ key: "manager", timeout: 3600 });
|
|
82862
82958
|
*/
|
|
82863
|
-
waitForApproval(options?: { timeout?: number; form?: object; selfApproval?: boolean; }): PromiseLike<{ value: any; approver: string; approved: boolean }>
|
|
82959
|
+
waitForApproval(options?: { timeout?: number; form?: object; selfApproval?: boolean; key?: string; }): PromiseLike<{ value: any; approver: string; approved: boolean }>
|
|
82960
|
+
|
|
82961
|
+
/**
|
|
82962
|
+
* Resume/cancel/approval-page URLs bound to one \`waitForApproval\` step.
|
|
82963
|
+
*
|
|
82964
|
+
* Unlike \`getResumeUrls()\`, which signs a random nonce, these address the very
|
|
82965
|
+
* \`resume_job\` record the step's built-in approval buttons use, so they are
|
|
82966
|
+
* stable across replays and safe to embed in a custom notification.
|
|
82967
|
+
*
|
|
82968
|
+
* \`stepKey\` must match the \`key\` given to \`waitForApproval\`. Keys must be unique
|
|
82969
|
+
* within a workflow; reusing one throws rather than silently renaming it. The URL
|
|
82970
|
+
* only resumes while that step is awaiting approval; used at any other moment it is
|
|
82971
|
+
* rejected rather than banking a row a different approval would consume. Send it
|
|
82972
|
+
* ahead of time — approvers just cannot act before the workflow reaches the step.
|
|
82973
|
+
*
|
|
82974
|
+
* \`resume\` and \`cancel\` are step-bound; \`approvalPage\` is not — it opens the job's
|
|
82975
|
+
* approval page, which acts on whichever approval is pending when it is used.
|
|
82976
|
+
*
|
|
82977
|
+
* @example
|
|
82978
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
82979
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
82980
|
+
* await waitForApproval({ key: "manager" });
|
|
82981
|
+
*/
|
|
82982
|
+
async getApprovalUrls(stepKey: string = "approval", approver?: string): Promise<{
|
|
82983
|
+
approvalPage: string;
|
|
82984
|
+
resume: string;
|
|
82985
|
+
cancel: string;
|
|
82986
|
+
}>
|
|
82864
82987
|
|
|
82865
82988
|
/**
|
|
82866
82989
|
* Process items in parallel with optional concurrency control.
|
|
@@ -83710,15 +83833,43 @@ workflow<T>(fn: (...args: any[]) => Promise<T>): void
|
|
|
83710
83833
|
/**
|
|
83711
83834
|
* Suspend the workflow and wait for an external approval.
|
|
83712
83835
|
*
|
|
83713
|
-
*
|
|
83714
|
-
*
|
|
83836
|
+
* Pass \`key\` to name the step, then \`getApprovalUrls(key)\` yields the URLs that
|
|
83837
|
+
* resume exactly this approval — route them through your own channel. Without a
|
|
83838
|
+
* key the steps are named \`approval\`, \`approval_2\`, ...
|
|
83839
|
+
*
|
|
83840
|
+
* @example
|
|
83841
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
83842
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
83843
|
+
* const { value, approver } = await waitForApproval({ key: "manager", timeout: 3600 });
|
|
83844
|
+
*/
|
|
83845
|
+
waitForApproval(options?: { timeout?: number; form?: object; selfApproval?: boolean; key?: string; }): PromiseLike<{ value: any; approver: string; approved: boolean }>
|
|
83846
|
+
|
|
83847
|
+
/**
|
|
83848
|
+
* Resume/cancel/approval-page URLs bound to one \`waitForApproval\` step.
|
|
83849
|
+
*
|
|
83850
|
+
* Unlike \`getResumeUrls()\`, which signs a random nonce, these address the very
|
|
83851
|
+
* \`resume_job\` record the step's built-in approval buttons use, so they are
|
|
83852
|
+
* stable across replays and safe to embed in a custom notification.
|
|
83853
|
+
*
|
|
83854
|
+
* \`stepKey\` must match the \`key\` given to \`waitForApproval\`. Keys must be unique
|
|
83855
|
+
* within a workflow; reusing one throws rather than silently renaming it. The URL
|
|
83856
|
+
* only resumes while that step is awaiting approval; used at any other moment it is
|
|
83857
|
+
* rejected rather than banking a row a different approval would consume. Send it
|
|
83858
|
+
* ahead of time — approvers just cannot act before the workflow reaches the step.
|
|
83859
|
+
*
|
|
83860
|
+
* \`resume\` and \`cancel\` are step-bound; \`approvalPage\` is not — it opens the job's
|
|
83861
|
+
* approval page, which acts on whichever approval is pending when it is used.
|
|
83715
83862
|
*
|
|
83716
83863
|
* @example
|
|
83717
|
-
* const urls = await step("urls", () =>
|
|
83718
|
-
* await step("notify", () => sendEmail(urls.
|
|
83719
|
-
*
|
|
83864
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
83865
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
83866
|
+
* await waitForApproval({ key: "manager" });
|
|
83720
83867
|
*/
|
|
83721
|
-
|
|
83868
|
+
async getApprovalUrls(stepKey: string = "approval", approver?: string): Promise<{
|
|
83869
|
+
approvalPage: string;
|
|
83870
|
+
resume: string;
|
|
83871
|
+
cancel: string;
|
|
83872
|
+
}>
|
|
83722
83873
|
|
|
83723
83874
|
/**
|
|
83724
83875
|
* Process items in parallel with optional concurrency control.
|
|
@@ -85304,6 +85455,17 @@ def get_shared_state(path: str = 'state.json') -> None
|
|
|
85304
85455
|
# Dictionary with approvalPage, resume, and cancel URLs
|
|
85305
85456
|
def get_resume_urls(approver: str = None, flow_level: bool = None) -> dict
|
|
85306
85457
|
|
|
85458
|
+
# Get the resume URLs bound to one \`\`wait_for_approval\`\` step of this workflow.
|
|
85459
|
+
#
|
|
85460
|
+
# Args:
|
|
85461
|
+
# step_key: Checkpoint key of the approval step, as passed to
|
|
85462
|
+
# \`\`wait_for_approval(key=...)\`\`
|
|
85463
|
+
# approver: Optional approver name
|
|
85464
|
+
#
|
|
85465
|
+
# Returns:
|
|
85466
|
+
# Dictionary with approvalPage, resume, and cancel URLs
|
|
85467
|
+
def get_approval_urls(step_key: str = 'approval', approver: str = None) -> dict
|
|
85468
|
+
|
|
85307
85469
|
# Sends an interactive approval request via Slack, allowing optional customization of the message, approver, and form fields.
|
|
85308
85470
|
#
|
|
85309
85471
|
# **[Enterprise Edition Only]** To include form fields in the Slack approval request, use the "Advanced -> Suspend -> Form" functionality.
|
|
@@ -85580,8 +85742,9 @@ async def sleep(seconds: int)
|
|
|
85580
85742
|
|
|
85581
85743
|
# Suspend the workflow and wait for an external approval.
|
|
85582
85744
|
#
|
|
85583
|
-
#
|
|
85584
|
-
# resume
|
|
85745
|
+
# Pass \`\`key\`\` to name the step, then \`\`get_approval_urls(key)\`\` yields the URLs
|
|
85746
|
+
# that resume exactly this approval — route them through your own channel.
|
|
85747
|
+
# Without a key the steps are named \`\`approval\`\`, \`\`approval_2\`\`, ...
|
|
85585
85748
|
#
|
|
85586
85749
|
# Returns a dict with \`\`value\`\` (form data), \`\`approver\`\`, and \`\`approved\`\`.
|
|
85587
85750
|
#
|
|
@@ -85589,13 +85752,14 @@ async def sleep(seconds: int)
|
|
|
85589
85752
|
# timeout: Approval timeout in seconds (default 1800).
|
|
85590
85753
|
# form: Optional form schema for the approval page.
|
|
85591
85754
|
# self_approval: Whether the user who triggered the flow can approve it (default True).
|
|
85755
|
+
# key: Optional checkpoint key naming this approval step.
|
|
85592
85756
|
#
|
|
85593
85757
|
# Example::
|
|
85594
85758
|
#
|
|
85595
|
-
# urls = await step("urls", lambda:
|
|
85596
|
-
# await step("notify", lambda: send_email(urls["
|
|
85597
|
-
# result = await wait_for_approval(timeout=3600)
|
|
85598
|
-
async def wait_for_approval(timeout: int = 1800, form: dict | None = None, self_approval: bool = True) -> dict
|
|
85759
|
+
# urls = await step("urls", lambda: get_approval_urls("manager"))
|
|
85760
|
+
# await step("notify", lambda: send_email(urls["resume"], urls["cancel"]))
|
|
85761
|
+
# result = await wait_for_approval(key="manager", timeout=3600)
|
|
85762
|
+
async def wait_for_approval(timeout: int = 1800, form: dict | None = None, self_approval: bool = True, key: str | None = None) -> dict
|
|
85599
85763
|
|
|
85600
85764
|
# Process items in parallel with optional concurrency control.
|
|
85601
85765
|
#
|
|
@@ -86672,6 +86836,18 @@ const user = await backend.get_user({ user_id: '123' });
|
|
|
86672
86836
|
|
|
86673
86837
|
The frontend cannot reach datatables, workspace items, or external services on its own — it goes through \`backend.<key>(args)\` for everything server-side.
|
|
86674
86838
|
|
|
86839
|
+
### Keeping data out of recorded demos
|
|
86840
|
+
|
|
86841
|
+
An app can be demoed by recording a session: every interaction becomes a step carrying a snapshot of the page, replayed publicly or on the Hub. Password inputs are masked automatically. Mark anything else that must not appear with \`data-wm-no-record\` — the whole marked subtree is dropped from every snapshot, along with its values and the step's own metadata:
|
|
86842
|
+
|
|
86843
|
+
\`\`\`tsx
|
|
86844
|
+
<label data-wm-no-record>
|
|
86845
|
+
Customer SSN <input value={ssn} onChange={onSsn} />
|
|
86846
|
+
</label>
|
|
86847
|
+
\`\`\`
|
|
86848
|
+
|
|
86849
|
+
Apply it to customer data, internal notes and anything else a viewer of the demo should not see. It costs nothing when the app is never recorded.
|
|
86850
|
+
|
|
86675
86851
|
## Backend runnables
|
|
86676
86852
|
|
|
86677
86853
|
Each runnable has a unique key (used to call it from the frontend) and one of four types:
|
|
@@ -86774,6 +86950,7 @@ def main(user_id: str):
|
|
|
86774
86950
|
3. **Keep runnables focused** — one function per runnable; small surface area.
|
|
86775
86951
|
4. **Use descriptive keys** — \`get_user\`, not \`a\`.
|
|
86776
86952
|
5. **Always whitelist tables** — adding a runnable that queries a new table requires the table to be in \`data.tables\` first.
|
|
86953
|
+
6. **Mark sensitive UI with \`data-wm-no-record\`** — it is what keeps that data out of a recorded demo; passwords are handled for you.
|
|
86777
86954
|
`,
|
|
86778
86955
|
triggers: `---
|
|
86779
86956
|
name: triggers
|
|
@@ -87227,7 +87404,7 @@ import {
|
|
|
87227
87404
|
step,
|
|
87228
87405
|
sleep,
|
|
87229
87406
|
waitForApproval,
|
|
87230
|
-
|
|
87407
|
+
getApprovalUrls,
|
|
87231
87408
|
parallel,
|
|
87232
87409
|
workflow,
|
|
87233
87410
|
} from "windmill-client";
|
|
@@ -87245,7 +87422,7 @@ export const main = workflow(async (x: string) => {
|
|
|
87245
87422
|
Python:
|
|
87246
87423
|
|
|
87247
87424
|
\`\`\`python
|
|
87248
|
-
from wmill import task, task_script, task_flow, step, sleep, wait_for_approval,
|
|
87425
|
+
from wmill import task, task_script, task_flow, step, sleep, wait_for_approval, get_approval_urls, parallel, workflow
|
|
87249
87426
|
|
|
87250
87427
|
@task()
|
|
87251
87428
|
async def process(x: str) -> str:
|
|
@@ -87329,12 +87506,13 @@ output = await pipeline(input=data)
|
|
|
87329
87506
|
Use \`step()\` for lightweight inline values that must not change during replay:
|
|
87330
87507
|
|
|
87331
87508
|
\`\`\`typescript
|
|
87332
|
-
const urls = await step("get_urls", () => getResumeUrls());
|
|
87333
87509
|
const startedAt = await step("started_at", () => new Date().toISOString());
|
|
87334
87510
|
\`\`\`
|
|
87335
87511
|
|
|
87336
87512
|
\`\`\`python
|
|
87337
|
-
|
|
87513
|
+
from datetime import datetime
|
|
87514
|
+
|
|
87515
|
+
started_at = await step("started_at", lambda: datetime.now().isoformat())
|
|
87338
87516
|
\`\`\`
|
|
87339
87517
|
|
|
87340
87518
|
Use stable, descriptive step names. Do not generate step names dynamically.
|
|
@@ -87359,20 +87537,28 @@ Only parallelize independent steps. Do not read the result of a task before it i
|
|
|
87359
87537
|
|
|
87360
87538
|
## Approvals
|
|
87361
87539
|
|
|
87362
|
-
|
|
87540
|
+
Name the approval step and generate its URLs inside \`step()\` before sending them.
|
|
87541
|
+
\`getApprovalUrls\` / \`get_approval_urls\` returns the URLs bound to that step, the same
|
|
87542
|
+
ones its built-in approve/reject buttons use:
|
|
87363
87543
|
|
|
87364
87544
|
\`\`\`typescript
|
|
87365
|
-
const urls = await step("
|
|
87366
|
-
await step("notify", () => sendApprovalEmail(urls.
|
|
87367
|
-
const approval = await waitForApproval({ timeout: 3600 });
|
|
87545
|
+
const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
87546
|
+
await step("notify", () => sendApprovalEmail(urls.resume, urls.cancel));
|
|
87547
|
+
const approval = await waitForApproval({ key: "manager", timeout: 3600 });
|
|
87368
87548
|
\`\`\`
|
|
87369
87549
|
|
|
87370
87550
|
\`\`\`python
|
|
87371
|
-
urls = await step("
|
|
87372
|
-
await step("notify", lambda: send_approval_email(urls["
|
|
87373
|
-
approval = await wait_for_approval(timeout=3600)
|
|
87551
|
+
urls = await step("urls", lambda: get_approval_urls("manager"))
|
|
87552
|
+
await step("notify", lambda: send_approval_email(urls["resume"], urls["cancel"]))
|
|
87553
|
+
approval = await wait_for_approval(key="manager", timeout=3600)
|
|
87374
87554
|
\`\`\`
|
|
87375
87555
|
|
|
87556
|
+
With several approvals in one workflow, give each its own key so each notification
|
|
87557
|
+
resumes its own step. Keys must be unique — reusing one raises an error rather than
|
|
87558
|
+
silently renaming the step. A minted URL only resumes while its own step is awaiting
|
|
87559
|
+
approval; used at any other moment it is rejected rather than resuming the wrong one. \`getResumeUrls()\` / \`get_resume_urls()\` still works but signs a
|
|
87560
|
+
random nonce, so its URLs are not tied to any particular approval step.
|
|
87561
|
+
|
|
87376
87562
|
\`selfApproval: false\` and \`self_approval=False\` are Enterprise-only approval behavior. Do not use them unless the user asks for that behavior.
|
|
87377
87563
|
|
|
87378
87564
|
## Error Handling
|
|
@@ -87386,7 +87572,7 @@ TypeScript: avoid broad \`try/catch\` around WAC SDK calls. The SDK uses an inte
|
|
|
87386
87572
|
|
|
87387
87573
|
## TypeScript Workflow-as-Code API (windmill-client)
|
|
87388
87574
|
|
|
87389
|
-
Import: \`import { workflow, task, taskScript, taskFlow, step, sleep, waitForApproval, getResumeUrls, parallel } from "windmill-client"\`
|
|
87575
|
+
Import: \`import { workflow, task, taskScript, taskFlow, step, sleep, waitForApproval, getApprovalUrls, getResumeUrls, parallel } from "windmill-client"\`
|
|
87390
87576
|
|
|
87391
87577
|
\`\`\`typescript
|
|
87392
87578
|
export interface TaskOptions {
|
|
@@ -87456,15 +87642,39 @@ export async function sleep(seconds: number): Promise<void>
|
|
|
87456
87642
|
/**
|
|
87457
87643
|
* Suspend the workflow and wait for an external approval.
|
|
87458
87644
|
*
|
|
87459
|
-
*
|
|
87460
|
-
*
|
|
87645
|
+
* Pass \`key\` to name the step, then \`getApprovalUrls(key)\` yields the URLs that
|
|
87646
|
+
* resume exactly this approval — route them through your own channel. Without a
|
|
87647
|
+
* key the steps are named \`approval\`, \`approval_2\`, ...
|
|
87648
|
+
*
|
|
87649
|
+
* @example
|
|
87650
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
87651
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
87652
|
+
* const { value, approver } = await waitForApproval({ key: "manager", timeout: 3600 });
|
|
87653
|
+
*/
|
|
87654
|
+
export function waitForApproval(options?: { timeout?: number; form?: object; selfApproval?: boolean; key?: string; }): PromiseLike<{ value: any; approver: string; approved: boolean }>
|
|
87655
|
+
|
|
87656
|
+
/**
|
|
87657
|
+
* Resume/cancel/approval-page URLs bound to one \`waitForApproval\` step.
|
|
87658
|
+
*
|
|
87659
|
+
* Unlike \`getResumeUrls()\`, which signs a random nonce, these address the very
|
|
87660
|
+
* \`resume_job\` record the step's built-in approval buttons use, so they are
|
|
87661
|
+
* stable across replays and safe to embed in a custom notification.
|
|
87662
|
+
*
|
|
87663
|
+
* \`stepKey\` must match the \`key\` given to \`waitForApproval\`. Keys must be unique
|
|
87664
|
+
* within a workflow; reusing one throws rather than silently renaming it. The URL
|
|
87665
|
+
* only resumes while that step is awaiting approval; used at any other moment it is
|
|
87666
|
+
* rejected rather than banking a row a different approval would consume. Send it
|
|
87667
|
+
* ahead of time — approvers just cannot act before the workflow reaches the step.
|
|
87668
|
+
*
|
|
87669
|
+
* \`resume\` and \`cancel\` are step-bound; \`approvalPage\` is not — it opens the job's
|
|
87670
|
+
* approval page, which acts on whichever approval is pending when it is used.
|
|
87461
87671
|
*
|
|
87462
87672
|
* @example
|
|
87463
|
-
* const urls = await step("urls", () =>
|
|
87464
|
-
* await step("notify", () => sendEmail(urls.
|
|
87465
|
-
*
|
|
87673
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
87674
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
87675
|
+
* await waitForApproval({ key: "manager" });
|
|
87466
87676
|
*/
|
|
87467
|
-
export function
|
|
87677
|
+
export async function getApprovalUrls(stepKey: string = "approval", approver?: string): Promise<{ approvalPage: string; resume: string; cancel: string; }>
|
|
87468
87678
|
|
|
87469
87679
|
/**
|
|
87470
87680
|
* Process items in parallel with optional concurrency control.
|
|
@@ -87482,7 +87692,7 @@ export async function parallel<T, R>(items: T[], fn: (item: T) => PromiseLike<R>
|
|
|
87482
87692
|
|
|
87483
87693
|
## Python Workflow-as-Code API (wmill)
|
|
87484
87694
|
|
|
87485
|
-
Import: \`from wmill import workflow, task, task_script, task_flow, step, sleep, wait_for_approval, get_resume_urls, parallel, TaskError\`
|
|
87695
|
+
Import: \`from wmill import workflow, task, task_script, task_flow, step, sleep, wait_for_approval, get_approval_urls, get_resume_urls, parallel, TaskError\`
|
|
87486
87696
|
|
|
87487
87697
|
\`\`\`python
|
|
87488
87698
|
# Raised when a WAC task step failed.
|
|
@@ -87570,8 +87780,9 @@ async def sleep(seconds: int)
|
|
|
87570
87780
|
|
|
87571
87781
|
# Suspend the workflow and wait for an external approval.
|
|
87572
87782
|
#
|
|
87573
|
-
#
|
|
87574
|
-
# resume
|
|
87783
|
+
# Pass \`\`key\`\` to name the step, then \`\`get_approval_urls(key)\`\` yields the URLs
|
|
87784
|
+
# that resume exactly this approval — route them through your own channel.
|
|
87785
|
+
# Without a key the steps are named \`\`approval\`\`, \`\`approval_2\`\`, ...
|
|
87575
87786
|
#
|
|
87576
87787
|
# Returns a dict with \`\`value\`\` (form data), \`\`approver\`\`, and \`\`approved\`\`.
|
|
87577
87788
|
#
|
|
@@ -87579,13 +87790,37 @@ async def sleep(seconds: int)
|
|
|
87579
87790
|
# timeout: Approval timeout in seconds (default 1800).
|
|
87580
87791
|
# form: Optional form schema for the approval page.
|
|
87581
87792
|
# self_approval: Whether the user who triggered the flow can approve it (default True).
|
|
87793
|
+
# key: Optional checkpoint key naming this approval step.
|
|
87582
87794
|
#
|
|
87583
87795
|
# Example::
|
|
87584
87796
|
#
|
|
87585
|
-
# urls = await step("urls", lambda:
|
|
87586
|
-
# await step("notify", lambda: send_email(urls["
|
|
87587
|
-
# result = await wait_for_approval(timeout=3600)
|
|
87588
|
-
async def wait_for_approval(timeout: int = 1800, form: dict | None = None, self_approval: bool = True) -> dict
|
|
87797
|
+
# urls = await step("urls", lambda: get_approval_urls("manager"))
|
|
87798
|
+
# await step("notify", lambda: send_email(urls["resume"], urls["cancel"]))
|
|
87799
|
+
# result = await wait_for_approval(key="manager", timeout=3600)
|
|
87800
|
+
async def wait_for_approval(timeout: int = 1800, form: dict | None = None, self_approval: bool = True, key: str | None = None) -> dict
|
|
87801
|
+
|
|
87802
|
+
# Get the resume/cancel/approval-page URLs bound to one \`\`wait_for_approval\`\` step.
|
|
87803
|
+
#
|
|
87804
|
+
# Unlike :func:\`get_resume_urls\`, which signs a random nonce, these address the
|
|
87805
|
+
# very \`\`resume_job\`\` record the step's built-in approval buttons use, so they
|
|
87806
|
+
# are stable across replays and safe to embed in a custom notification.
|
|
87807
|
+
#
|
|
87808
|
+
# Args:
|
|
87809
|
+
# step_key: Checkpoint key of the approval step, as passed to
|
|
87810
|
+
# \`\`wait_for_approval(key=...)\`\`. Keys must be unique within a workflow;
|
|
87811
|
+
# reusing one raises rather than silently renaming it. The URL only
|
|
87812
|
+
# resumes while that step is awaiting approval; used at any other moment
|
|
87813
|
+
# it is rejected rather than banking a row a different approval would
|
|
87814
|
+
# consume. Send it ahead of time — approvers just cannot act before the
|
|
87815
|
+
# workflow reaches the step.
|
|
87816
|
+
# \`\`resume\`\` and \`\`cancel\`\` are step-bound; \`\`approvalPage\`\` is not — it
|
|
87817
|
+
# opens the job's approval page, which acts on whichever approval is
|
|
87818
|
+
# pending when it is used.
|
|
87819
|
+
# approver: Optional approver name
|
|
87820
|
+
#
|
|
87821
|
+
# Returns:
|
|
87822
|
+
# Dictionary with approvalPage, resume, and cancel URLs
|
|
87823
|
+
def get_approval_urls(step_key: str = 'approval', approver: str = None) -> dict
|
|
87589
87824
|
|
|
87590
87825
|
# Process items in parallel with optional concurrency control.
|
|
87591
87826
|
#
|