windmill-cli 1.769.1 → 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/esm/main.js +333 -60
- 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.0",
|
|
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,8 +17236,10 @@ __export(exports_services_gen, {
|
|
|
17234
17236
|
publishHubScript: () => publishHubScript,
|
|
17235
17237
|
publishHubResources: () => publishHubResources,
|
|
17236
17238
|
publishHubResourceType: () => publishHubResourceType,
|
|
17239
|
+
publishHubRawAppRecording: () => publishHubRawAppRecording,
|
|
17237
17240
|
publishHubRawAppEmbed: () => publishHubRawAppEmbed,
|
|
17238
17241
|
publishHubRawApp: () => publishHubRawApp,
|
|
17242
|
+
publishHubProjectLogo: () => publishHubProjectLogo,
|
|
17239
17243
|
publishHubPipelineRecording: () => publishHubPipelineRecording,
|
|
17240
17244
|
publishHubMigrations: () => publishHubMigrations,
|
|
17241
17245
|
publishHubFlowRecording: () => publishHubFlowRecording,
|
|
@@ -17309,6 +17313,7 @@ __export(exports_services_gen, {
|
|
|
17309
17313
|
listScriptPaths: () => listScriptPaths,
|
|
17310
17314
|
listSchedulesWithJobs: () => listSchedulesWithJobs,
|
|
17311
17315
|
listSchedules: () => listSchedules,
|
|
17316
|
+
listRunnables: () => listRunnables,
|
|
17312
17317
|
listResourceTypeNames: () => listResourceTypeNames,
|
|
17313
17318
|
listResourceType: () => listResourceType,
|
|
17314
17319
|
listResourceNames: () => listResourceNames,
|
|
@@ -17437,6 +17442,7 @@ __export(exports_services_gen, {
|
|
|
17437
17442
|
getWorkspaceDefaultApp: () => getWorkspaceDefaultApp,
|
|
17438
17443
|
getWorkspaceAsSuperAdmin: () => getWorkspaceAsSuperAdmin,
|
|
17439
17444
|
getWebsocketTrigger: () => getWebsocketTrigger,
|
|
17445
|
+
getWacApprovalUrls: () => getWacApprovalUrls,
|
|
17440
17446
|
getVolumeStorage: () => getVolumeStorage,
|
|
17441
17447
|
getVariableValue: () => getVariableValue,
|
|
17442
17448
|
getVariable: () => getVariable,
|
|
@@ -21328,6 +21334,26 @@ var backendVersion = () => {
|
|
|
21328
21334
|
workspace: data3.workspace
|
|
21329
21335
|
}
|
|
21330
21336
|
});
|
|
21337
|
+
}, listRunnables = (data3) => {
|
|
21338
|
+
return request(OpenAPI, {
|
|
21339
|
+
method: "GET",
|
|
21340
|
+
url: "/w/{workspace}/runnables/list",
|
|
21341
|
+
path: {
|
|
21342
|
+
workspace: data3.workspace
|
|
21343
|
+
},
|
|
21344
|
+
query: {
|
|
21345
|
+
order_by: data3.orderBy,
|
|
21346
|
+
order_desc: data3.orderDesc,
|
|
21347
|
+
kinds: data3.kinds,
|
|
21348
|
+
show_archived: data3.showArchived,
|
|
21349
|
+
include_without_main: data3.includeWithoutMain,
|
|
21350
|
+
path_start: data3.pathStart,
|
|
21351
|
+
label: data3.label,
|
|
21352
|
+
search: data3.search,
|
|
21353
|
+
per_page: data3.perPage,
|
|
21354
|
+
cursor: data3.cursor
|
|
21355
|
+
}
|
|
21356
|
+
});
|
|
21331
21357
|
}, listFlows = (data3) => {
|
|
21332
21358
|
return request(OpenAPI, {
|
|
21333
21359
|
method: "GET",
|
|
@@ -22374,6 +22400,7 @@ var backendVersion = () => {
|
|
|
22374
22400
|
page: data3.page,
|
|
22375
22401
|
per_page: data3.perPage,
|
|
22376
22402
|
is_skipped: data3.isSkipped,
|
|
22403
|
+
resolved: data3.resolved,
|
|
22377
22404
|
is_flow_step: data3.isFlowStep,
|
|
22378
22405
|
has_null_parent: data3.hasNullParent,
|
|
22379
22406
|
success: data3.success,
|
|
@@ -22491,6 +22518,7 @@ var backendVersion = () => {
|
|
|
22491
22518
|
page: data3.page,
|
|
22492
22519
|
per_page: data3.perPage,
|
|
22493
22520
|
is_skipped: data3.isSkipped,
|
|
22521
|
+
resolved: data3.resolved,
|
|
22494
22522
|
is_flow_step: data3.isFlowStep,
|
|
22495
22523
|
has_null_parent: data3.hasNullParent,
|
|
22496
22524
|
is_not_schedule: data3.isNotSchedule
|
|
@@ -22585,6 +22613,7 @@ var backendVersion = () => {
|
|
|
22585
22613
|
per_page: data3.perPage,
|
|
22586
22614
|
trigger_kind: data3.triggerKind,
|
|
22587
22615
|
is_skipped: data3.isSkipped,
|
|
22616
|
+
resolved: data3.resolved,
|
|
22588
22617
|
is_flow_step: data3.isFlowStep,
|
|
22589
22618
|
has_null_parent: data3.hasNullParent,
|
|
22590
22619
|
success: data3.success,
|
|
@@ -22817,6 +22846,26 @@ var backendVersion = () => {
|
|
|
22817
22846
|
id: data3.id
|
|
22818
22847
|
}
|
|
22819
22848
|
});
|
|
22849
|
+
}, resolveCompletedJobs = (data3) => {
|
|
22850
|
+
return request(OpenAPI, {
|
|
22851
|
+
method: "POST",
|
|
22852
|
+
url: "/w/{workspace}/jobs/completed/resolve",
|
|
22853
|
+
path: {
|
|
22854
|
+
workspace: data3.workspace
|
|
22855
|
+
},
|
|
22856
|
+
body: data3.requestBody,
|
|
22857
|
+
mediaType: "application/json"
|
|
22858
|
+
});
|
|
22859
|
+
}, unresolveCompletedJobs = (data3) => {
|
|
22860
|
+
return request(OpenAPI, {
|
|
22861
|
+
method: "POST",
|
|
22862
|
+
url: "/w/{workspace}/jobs/completed/unresolve",
|
|
22863
|
+
path: {
|
|
22864
|
+
workspace: data3.workspace
|
|
22865
|
+
},
|
|
22866
|
+
body: data3.requestBody,
|
|
22867
|
+
mediaType: "application/json"
|
|
22868
|
+
});
|
|
22820
22869
|
}, cancelQueuedJob = (data3) => {
|
|
22821
22870
|
return request(OpenAPI, {
|
|
22822
22871
|
method: "POST",
|
|
@@ -22895,6 +22944,19 @@ var backendVersion = () => {
|
|
|
22895
22944
|
flow_level: data3.flowLevel
|
|
22896
22945
|
}
|
|
22897
22946
|
});
|
|
22947
|
+
}, getWacApprovalUrls = (data3) => {
|
|
22948
|
+
return request(OpenAPI, {
|
|
22949
|
+
method: "GET",
|
|
22950
|
+
url: "/w/{workspace}/jobs/wac_approval_urls/{id}/{step_key}",
|
|
22951
|
+
path: {
|
|
22952
|
+
workspace: data3.workspace,
|
|
22953
|
+
id: data3.id,
|
|
22954
|
+
step_key: data3.stepKey
|
|
22955
|
+
},
|
|
22956
|
+
query: {
|
|
22957
|
+
approver: data3.approver
|
|
22958
|
+
}
|
|
22959
|
+
});
|
|
22898
22960
|
}, getSlackApprovalPayload = (data3) => {
|
|
22899
22961
|
return request(OpenAPI, {
|
|
22900
22962
|
method: "GET",
|
|
@@ -24818,6 +24880,8 @@ var backendVersion = () => {
|
|
|
24818
24880
|
workspace: data3.workspace
|
|
24819
24881
|
},
|
|
24820
24882
|
query: {
|
|
24883
|
+
page: data3.page,
|
|
24884
|
+
per_page: data3.perPage,
|
|
24821
24885
|
only_member_of: data3.onlyMemberOf
|
|
24822
24886
|
}
|
|
24823
24887
|
});
|
|
@@ -25321,7 +25385,8 @@ var backendVersion = () => {
|
|
|
25321
25385
|
workspace: data3.workspace
|
|
25322
25386
|
},
|
|
25323
25387
|
query: {
|
|
25324
|
-
storage: data3.storage
|
|
25388
|
+
storage: data3.storage,
|
|
25389
|
+
s3_resource_path: data3.s3ResourcePath
|
|
25325
25390
|
}
|
|
25326
25391
|
});
|
|
25327
25392
|
}, getStorageUsage = (data3) => {
|
|
@@ -25346,7 +25411,8 @@ var backendVersion = () => {
|
|
|
25346
25411
|
max_keys: data3.maxKeys,
|
|
25347
25412
|
marker: data3.marker,
|
|
25348
25413
|
prefix: data3.prefix,
|
|
25349
|
-
storage: data3.storage
|
|
25414
|
+
storage: data3.storage,
|
|
25415
|
+
s3_resource_path: data3.s3ResourcePath
|
|
25350
25416
|
}
|
|
25351
25417
|
});
|
|
25352
25418
|
}, loadFileMetadata = (data3) => {
|
|
@@ -25358,7 +25424,8 @@ var backendVersion = () => {
|
|
|
25358
25424
|
},
|
|
25359
25425
|
query: {
|
|
25360
25426
|
file_key: data3.fileKey,
|
|
25361
|
-
storage: data3.storage
|
|
25427
|
+
storage: data3.storage,
|
|
25428
|
+
s3_resource_path: data3.s3ResourcePath
|
|
25362
25429
|
}
|
|
25363
25430
|
});
|
|
25364
25431
|
}, loadFilePreview = (data3) => {
|
|
@@ -25376,7 +25443,8 @@ var backendVersion = () => {
|
|
|
25376
25443
|
csv_has_header: data3.csvHasHeader,
|
|
25377
25444
|
read_bytes_from: data3.readBytesFrom,
|
|
25378
25445
|
read_bytes_length: data3.readBytesLength,
|
|
25379
|
-
storage: data3.storage
|
|
25446
|
+
storage: data3.storage,
|
|
25447
|
+
s3_resource_path: data3.s3ResourcePath
|
|
25380
25448
|
}
|
|
25381
25449
|
});
|
|
25382
25450
|
}, listGitRepoFiles = (data3) => {
|
|
@@ -25495,7 +25563,8 @@ var backendVersion = () => {
|
|
|
25495
25563
|
},
|
|
25496
25564
|
query: {
|
|
25497
25565
|
file_key: data3.fileKey,
|
|
25498
|
-
storage: data3.storage
|
|
25566
|
+
storage: data3.storage,
|
|
25567
|
+
s3_resource_path: data3.s3ResourcePath
|
|
25499
25568
|
}
|
|
25500
25569
|
});
|
|
25501
25570
|
}, moveS3File = (data3) => {
|
|
@@ -25508,7 +25577,8 @@ var backendVersion = () => {
|
|
|
25508
25577
|
query: {
|
|
25509
25578
|
src_file_key: data3.srcFileKey,
|
|
25510
25579
|
dest_file_key: data3.destFileKey,
|
|
25511
|
-
storage: data3.storage
|
|
25580
|
+
storage: data3.storage,
|
|
25581
|
+
s3_resource_path: data3.s3ResourcePath
|
|
25512
25582
|
}
|
|
25513
25583
|
});
|
|
25514
25584
|
}, fileUpload = (data3) => {
|
|
@@ -25680,6 +25750,7 @@ var backendVersion = () => {
|
|
|
25680
25750
|
per_page: data3.perPage,
|
|
25681
25751
|
trigger_kind: data3.triggerKind,
|
|
25682
25752
|
is_skipped: data3.isSkipped,
|
|
25753
|
+
resolved: data3.resolved,
|
|
25683
25754
|
is_flow_step: data3.isFlowStep,
|
|
25684
25755
|
has_null_parent: data3.hasNullParent,
|
|
25685
25756
|
success: data3.success,
|
|
@@ -25996,6 +26067,20 @@ var backendVersion = () => {
|
|
|
25996
26067
|
body: data3.requestBody,
|
|
25997
26068
|
mediaType: "application/json"
|
|
25998
26069
|
});
|
|
26070
|
+
}, publishHubRawAppRecording = (data3) => {
|
|
26071
|
+
return request(OpenAPI, {
|
|
26072
|
+
method: "POST",
|
|
26073
|
+
url: "/w/{workspace}/hub/raw_apps/{id}/recording",
|
|
26074
|
+
path: {
|
|
26075
|
+
workspace: data3.workspace,
|
|
26076
|
+
id: data3.id
|
|
26077
|
+
},
|
|
26078
|
+
query: {
|
|
26079
|
+
folder: data3.folder
|
|
26080
|
+
},
|
|
26081
|
+
body: data3.requestBody,
|
|
26082
|
+
mediaType: "application/json"
|
|
26083
|
+
});
|
|
25999
26084
|
}, publishHubScriptRecording = (data3) => {
|
|
26000
26085
|
return request(OpenAPI, {
|
|
26001
26086
|
method: "POST",
|
|
@@ -26102,6 +26187,20 @@ var backendVersion = () => {
|
|
|
26102
26187
|
folder: data3.folder
|
|
26103
26188
|
}
|
|
26104
26189
|
});
|
|
26190
|
+
}, publishHubProjectLogo = (data3) => {
|
|
26191
|
+
return request(OpenAPI, {
|
|
26192
|
+
method: "POST",
|
|
26193
|
+
url: "/w/{workspace}/hub/projects/{slug}/logo",
|
|
26194
|
+
path: {
|
|
26195
|
+
workspace: data3.workspace,
|
|
26196
|
+
slug: data3.slug
|
|
26197
|
+
},
|
|
26198
|
+
query: {
|
|
26199
|
+
folder: data3.folder
|
|
26200
|
+
},
|
|
26201
|
+
body: data3.requestBody,
|
|
26202
|
+
mediaType: "application/json"
|
|
26203
|
+
});
|
|
26105
26204
|
}, submitHubProject = (data3) => {
|
|
26106
26205
|
return request(OpenAPI, {
|
|
26107
26206
|
method: "POST",
|
|
@@ -26181,6 +26280,7 @@ __export(exports_gen, {
|
|
|
26181
26280
|
updateApp: () => updateApp,
|
|
26182
26281
|
updateAmqpTrigger: () => updateAmqpTrigger,
|
|
26183
26282
|
unstar: () => unstar,
|
|
26283
|
+
unresolveCompletedJobs: () => unresolveCompletedJobs,
|
|
26184
26284
|
unassignGhesInstallation: () => unassignGhesInstallation,
|
|
26185
26285
|
unarchiveWorkspace: () => unarchiveWorkspace,
|
|
26186
26286
|
toggleWorkspaceErrorHandlerForScript: () => toggleWorkspaceErrorHandlerForScript,
|
|
@@ -26287,6 +26387,7 @@ __export(exports_gen, {
|
|
|
26287
26387
|
restartWorkerGroup: () => restartWorkerGroup,
|
|
26288
26388
|
restartFlowAtStep: () => restartFlowAtStep,
|
|
26289
26389
|
resolveNpmPackageVersion: () => resolveNpmPackageVersion,
|
|
26390
|
+
resolveCompletedJobs: () => resolveCompletedJobs,
|
|
26290
26391
|
resetPassword: () => resetPassword,
|
|
26291
26392
|
resetKafkaOffsets: () => resetKafkaOffsets,
|
|
26292
26393
|
resetDiffTally: () => resetDiffTally,
|
|
@@ -26312,8 +26413,10 @@ __export(exports_gen, {
|
|
|
26312
26413
|
publishHubScript: () => publishHubScript,
|
|
26313
26414
|
publishHubResources: () => publishHubResources,
|
|
26314
26415
|
publishHubResourceType: () => publishHubResourceType,
|
|
26416
|
+
publishHubRawAppRecording: () => publishHubRawAppRecording,
|
|
26315
26417
|
publishHubRawAppEmbed: () => publishHubRawAppEmbed,
|
|
26316
26418
|
publishHubRawApp: () => publishHubRawApp,
|
|
26419
|
+
publishHubProjectLogo: () => publishHubProjectLogo,
|
|
26317
26420
|
publishHubPipelineRecording: () => publishHubPipelineRecording,
|
|
26318
26421
|
publishHubMigrations: () => publishHubMigrations,
|
|
26319
26422
|
publishHubFlowRecording: () => publishHubFlowRecording,
|
|
@@ -26387,6 +26490,7 @@ __export(exports_gen, {
|
|
|
26387
26490
|
listScriptPaths: () => listScriptPaths,
|
|
26388
26491
|
listSchedulesWithJobs: () => listSchedulesWithJobs,
|
|
26389
26492
|
listSchedules: () => listSchedules,
|
|
26493
|
+
listRunnables: () => listRunnables,
|
|
26390
26494
|
listResourceTypeNames: () => listResourceTypeNames,
|
|
26391
26495
|
listResourceType: () => listResourceType,
|
|
26392
26496
|
listResourceNames: () => listResourceNames,
|
|
@@ -26515,6 +26619,7 @@ __export(exports_gen, {
|
|
|
26515
26619
|
getWorkspaceDefaultApp: () => getWorkspaceDefaultApp,
|
|
26516
26620
|
getWorkspaceAsSuperAdmin: () => getWorkspaceAsSuperAdmin,
|
|
26517
26621
|
getWebsocketTrigger: () => getWebsocketTrigger,
|
|
26622
|
+
getWacApprovalUrls: () => getWacApprovalUrls,
|
|
26518
26623
|
getVolumeStorage: () => getVolumeStorage,
|
|
26519
26624
|
getVariableValue: () => getVariableValue,
|
|
26520
26625
|
getVariable: () => getVariable,
|
|
@@ -27044,7 +27149,7 @@ var init_auth = __esm(async () => {
|
|
|
27044
27149
|
});
|
|
27045
27150
|
|
|
27046
27151
|
// src/core/constants.ts
|
|
27047
|
-
var WM_FORK_PREFIX = "wm-fork", VERSION = "1.
|
|
27152
|
+
var WM_FORK_PREFIX = "wm-fork", VERSION = "1.771.0";
|
|
27048
27153
|
|
|
27049
27154
|
// src/utils/git.ts
|
|
27050
27155
|
var exports_git = {};
|
|
@@ -49576,7 +49681,7 @@ var require_zipEntries = __commonJS((exports, module) => {
|
|
|
49576
49681
|
if (this.centralDirRecords !== this.files.length) {
|
|
49577
49682
|
if (this.centralDirRecords !== 0 && this.files.length === 0) {
|
|
49578
49683
|
throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length);
|
|
49579
|
-
}
|
|
49684
|
+
}
|
|
49580
49685
|
}
|
|
49581
49686
|
},
|
|
49582
49687
|
readEndOfCentral: function() {
|
|
@@ -58010,7 +58115,7 @@ var require_loader = __commonJS((exports, module) => {
|
|
|
58010
58115
|
var error2 = generateError(state, message);
|
|
58011
58116
|
if (state.onWarning) {
|
|
58012
58117
|
state.onWarning.call(null, error2);
|
|
58013
|
-
}
|
|
58118
|
+
}
|
|
58014
58119
|
}
|
|
58015
58120
|
var directiveHandlers = {
|
|
58016
58121
|
YAML: function handleYamlDirective(state, name, args) {
|
|
@@ -58548,7 +58653,7 @@ var require_loader = __commonJS((exports, module) => {
|
|
|
58548
58653
|
} else if (detectedIndent) {
|
|
58549
58654
|
sc.value += common3.repeat(`
|
|
58550
58655
|
`, emptyLines + 1);
|
|
58551
|
-
}
|
|
58656
|
+
}
|
|
58552
58657
|
detectedIndent = true;
|
|
58553
58658
|
emptyLines = 0;
|
|
58554
58659
|
captureStart = state.position;
|
|
@@ -82066,15 +82171,43 @@ workflow<T>(fn: (...args: any[]) => Promise<T>): void
|
|
|
82066
82171
|
/**
|
|
82067
82172
|
* Suspend the workflow and wait for an external approval.
|
|
82068
82173
|
*
|
|
82069
|
-
*
|
|
82070
|
-
*
|
|
82174
|
+
* Pass \`key\` to name the step, then \`getApprovalUrls(key)\` yields the URLs that
|
|
82175
|
+
* resume exactly this approval — route them through your own channel. Without a
|
|
82176
|
+
* key the steps are named \`approval\`, \`approval_2\`, ...
|
|
82071
82177
|
*
|
|
82072
82178
|
* @example
|
|
82073
|
-
* const urls = await step("urls", () =>
|
|
82074
|
-
* await step("notify", () => sendEmail(urls.
|
|
82075
|
-
* const { value, approver } = await waitForApproval({ timeout: 3600 });
|
|
82179
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
82180
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
82181
|
+
* const { value, approver } = await waitForApproval({ key: "manager", timeout: 3600 });
|
|
82076
82182
|
*/
|
|
82077
|
-
waitForApproval(options?: { timeout?: number; form?: object; selfApproval?: boolean; }): PromiseLike<{ value: any; approver: string; approved: boolean }>
|
|
82183
|
+
waitForApproval(options?: { timeout?: number; form?: object; selfApproval?: boolean; key?: string; }): PromiseLike<{ value: any; approver: string; approved: boolean }>
|
|
82184
|
+
|
|
82185
|
+
/**
|
|
82186
|
+
* Resume/cancel/approval-page URLs bound to one \`waitForApproval\` step.
|
|
82187
|
+
*
|
|
82188
|
+
* Unlike \`getResumeUrls()\`, which signs a random nonce, these address the very
|
|
82189
|
+
* \`resume_job\` record the step's built-in approval buttons use, so they are
|
|
82190
|
+
* stable across replays and safe to embed in a custom notification.
|
|
82191
|
+
*
|
|
82192
|
+
* \`stepKey\` must match the \`key\` given to \`waitForApproval\`. Keys must be unique
|
|
82193
|
+
* within a workflow; reusing one throws rather than silently renaming it. The URL
|
|
82194
|
+
* only resumes while that step is awaiting approval; used at any other moment it is
|
|
82195
|
+
* rejected rather than banking a row a different approval would consume. Send it
|
|
82196
|
+
* ahead of time — approvers just cannot act before the workflow reaches the step.
|
|
82197
|
+
*
|
|
82198
|
+
* \`resume\` and \`cancel\` are step-bound; \`approvalPage\` is not — it opens the job's
|
|
82199
|
+
* approval page, which acts on whichever approval is pending when it is used.
|
|
82200
|
+
*
|
|
82201
|
+
* @example
|
|
82202
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
82203
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
82204
|
+
* await waitForApproval({ key: "manager" });
|
|
82205
|
+
*/
|
|
82206
|
+
async getApprovalUrls(stepKey: string = "approval", approver?: string): Promise<{
|
|
82207
|
+
approvalPage: string;
|
|
82208
|
+
resume: string;
|
|
82209
|
+
cancel: string;
|
|
82210
|
+
}>
|
|
82078
82211
|
|
|
82079
82212
|
/**
|
|
82080
82213
|
* Process items in parallel with optional concurrency control.
|
|
@@ -82830,15 +82963,43 @@ workflow<T>(fn: (...args: any[]) => Promise<T>): void
|
|
|
82830
82963
|
/**
|
|
82831
82964
|
* Suspend the workflow and wait for an external approval.
|
|
82832
82965
|
*
|
|
82833
|
-
*
|
|
82834
|
-
*
|
|
82966
|
+
* Pass \`key\` to name the step, then \`getApprovalUrls(key)\` yields the URLs that
|
|
82967
|
+
* resume exactly this approval — route them through your own channel. Without a
|
|
82968
|
+
* key the steps are named \`approval\`, \`approval_2\`, ...
|
|
82835
82969
|
*
|
|
82836
82970
|
* @example
|
|
82837
|
-
* const urls = await step("urls", () =>
|
|
82838
|
-
* await step("notify", () => sendEmail(urls.
|
|
82839
|
-
* const { value, approver } = await waitForApproval({ timeout: 3600 });
|
|
82971
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
82972
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
82973
|
+
* const { value, approver } = await waitForApproval({ key: "manager", timeout: 3600 });
|
|
82840
82974
|
*/
|
|
82841
|
-
waitForApproval(options?: { timeout?: number; form?: object; selfApproval?: boolean; }): PromiseLike<{ value: any; approver: string; approved: boolean }>
|
|
82975
|
+
waitForApproval(options?: { timeout?: number; form?: object; selfApproval?: boolean; key?: string; }): PromiseLike<{ value: any; approver: string; approved: boolean }>
|
|
82976
|
+
|
|
82977
|
+
/**
|
|
82978
|
+
* Resume/cancel/approval-page URLs bound to one \`waitForApproval\` step.
|
|
82979
|
+
*
|
|
82980
|
+
* Unlike \`getResumeUrls()\`, which signs a random nonce, these address the very
|
|
82981
|
+
* \`resume_job\` record the step's built-in approval buttons use, so they are
|
|
82982
|
+
* stable across replays and safe to embed in a custom notification.
|
|
82983
|
+
*
|
|
82984
|
+
* \`stepKey\` must match the \`key\` given to \`waitForApproval\`. Keys must be unique
|
|
82985
|
+
* within a workflow; reusing one throws rather than silently renaming it. The URL
|
|
82986
|
+
* only resumes while that step is awaiting approval; used at any other moment it is
|
|
82987
|
+
* rejected rather than banking a row a different approval would consume. Send it
|
|
82988
|
+
* ahead of time — approvers just cannot act before the workflow reaches the step.
|
|
82989
|
+
*
|
|
82990
|
+
* \`resume\` and \`cancel\` are step-bound; \`approvalPage\` is not — it opens the job's
|
|
82991
|
+
* approval page, which acts on whichever approval is pending when it is used.
|
|
82992
|
+
*
|
|
82993
|
+
* @example
|
|
82994
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
82995
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
82996
|
+
* await waitForApproval({ key: "manager" });
|
|
82997
|
+
*/
|
|
82998
|
+
async getApprovalUrls(stepKey: string = "approval", approver?: string): Promise<{
|
|
82999
|
+
approvalPage: string;
|
|
83000
|
+
resume: string;
|
|
83001
|
+
cancel: string;
|
|
83002
|
+
}>
|
|
82842
83003
|
|
|
82843
83004
|
/**
|
|
82844
83005
|
* Process items in parallel with optional concurrency control.
|
|
@@ -83688,15 +83849,43 @@ workflow<T>(fn: (...args: any[]) => Promise<T>): void
|
|
|
83688
83849
|
/**
|
|
83689
83850
|
* Suspend the workflow and wait for an external approval.
|
|
83690
83851
|
*
|
|
83691
|
-
*
|
|
83692
|
-
*
|
|
83852
|
+
* Pass \`key\` to name the step, then \`getApprovalUrls(key)\` yields the URLs that
|
|
83853
|
+
* resume exactly this approval — route them through your own channel. Without a
|
|
83854
|
+
* key the steps are named \`approval\`, \`approval_2\`, ...
|
|
83693
83855
|
*
|
|
83694
83856
|
* @example
|
|
83695
|
-
* const urls = await step("urls", () =>
|
|
83696
|
-
* await step("notify", () => sendEmail(urls.
|
|
83697
|
-
* const { value, approver } = await waitForApproval({ timeout: 3600 });
|
|
83857
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
83858
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
83859
|
+
* const { value, approver } = await waitForApproval({ key: "manager", timeout: 3600 });
|
|
83698
83860
|
*/
|
|
83699
|
-
waitForApproval(options?: { timeout?: number; form?: object; selfApproval?: boolean; }): PromiseLike<{ value: any; approver: string; approved: boolean }>
|
|
83861
|
+
waitForApproval(options?: { timeout?: number; form?: object; selfApproval?: boolean; key?: string; }): PromiseLike<{ value: any; approver: string; approved: boolean }>
|
|
83862
|
+
|
|
83863
|
+
/**
|
|
83864
|
+
* Resume/cancel/approval-page URLs bound to one \`waitForApproval\` step.
|
|
83865
|
+
*
|
|
83866
|
+
* Unlike \`getResumeUrls()\`, which signs a random nonce, these address the very
|
|
83867
|
+
* \`resume_job\` record the step's built-in approval buttons use, so they are
|
|
83868
|
+
* stable across replays and safe to embed in a custom notification.
|
|
83869
|
+
*
|
|
83870
|
+
* \`stepKey\` must match the \`key\` given to \`waitForApproval\`. Keys must be unique
|
|
83871
|
+
* within a workflow; reusing one throws rather than silently renaming it. The URL
|
|
83872
|
+
* only resumes while that step is awaiting approval; used at any other moment it is
|
|
83873
|
+
* rejected rather than banking a row a different approval would consume. Send it
|
|
83874
|
+
* ahead of time — approvers just cannot act before the workflow reaches the step.
|
|
83875
|
+
*
|
|
83876
|
+
* \`resume\` and \`cancel\` are step-bound; \`approvalPage\` is not — it opens the job's
|
|
83877
|
+
* approval page, which acts on whichever approval is pending when it is used.
|
|
83878
|
+
*
|
|
83879
|
+
* @example
|
|
83880
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
83881
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
83882
|
+
* await waitForApproval({ key: "manager" });
|
|
83883
|
+
*/
|
|
83884
|
+
async getApprovalUrls(stepKey: string = "approval", approver?: string): Promise<{
|
|
83885
|
+
approvalPage: string;
|
|
83886
|
+
resume: string;
|
|
83887
|
+
cancel: string;
|
|
83888
|
+
}>
|
|
83700
83889
|
|
|
83701
83890
|
/**
|
|
83702
83891
|
* Process items in parallel with optional concurrency control.
|
|
@@ -85282,6 +85471,17 @@ def get_shared_state(path: str = 'state.json') -> None
|
|
|
85282
85471
|
# Dictionary with approvalPage, resume, and cancel URLs
|
|
85283
85472
|
def get_resume_urls(approver: str = None, flow_level: bool = None) -> dict
|
|
85284
85473
|
|
|
85474
|
+
# Get the resume URLs bound to one \`\`wait_for_approval\`\` step of this workflow.
|
|
85475
|
+
#
|
|
85476
|
+
# Args:
|
|
85477
|
+
# step_key: Checkpoint key of the approval step, as passed to
|
|
85478
|
+
# \`\`wait_for_approval(key=...)\`\`
|
|
85479
|
+
# approver: Optional approver name
|
|
85480
|
+
#
|
|
85481
|
+
# Returns:
|
|
85482
|
+
# Dictionary with approvalPage, resume, and cancel URLs
|
|
85483
|
+
def get_approval_urls(step_key: str = 'approval', approver: str = None) -> dict
|
|
85484
|
+
|
|
85285
85485
|
# Sends an interactive approval request via Slack, allowing optional customization of the message, approver, and form fields.
|
|
85286
85486
|
#
|
|
85287
85487
|
# **[Enterprise Edition Only]** To include form fields in the Slack approval request, use the "Advanced -> Suspend -> Form" functionality.
|
|
@@ -85558,8 +85758,9 @@ async def sleep(seconds: int)
|
|
|
85558
85758
|
|
|
85559
85759
|
# Suspend the workflow and wait for an external approval.
|
|
85560
85760
|
#
|
|
85561
|
-
#
|
|
85562
|
-
# resume
|
|
85761
|
+
# Pass \`\`key\`\` to name the step, then \`\`get_approval_urls(key)\`\` yields the URLs
|
|
85762
|
+
# that resume exactly this approval — route them through your own channel.
|
|
85763
|
+
# Without a key the steps are named \`\`approval\`\`, \`\`approval_2\`\`, ...
|
|
85563
85764
|
#
|
|
85564
85765
|
# Returns a dict with \`\`value\`\` (form data), \`\`approver\`\`, and \`\`approved\`\`.
|
|
85565
85766
|
#
|
|
@@ -85567,13 +85768,14 @@ async def sleep(seconds: int)
|
|
|
85567
85768
|
# timeout: Approval timeout in seconds (default 1800).
|
|
85568
85769
|
# form: Optional form schema for the approval page.
|
|
85569
85770
|
# self_approval: Whether the user who triggered the flow can approve it (default True).
|
|
85771
|
+
# key: Optional checkpoint key naming this approval step.
|
|
85570
85772
|
#
|
|
85571
85773
|
# Example::
|
|
85572
85774
|
#
|
|
85573
|
-
# urls = await step("urls", lambda:
|
|
85574
|
-
# await step("notify", lambda: send_email(urls["
|
|
85575
|
-
# result = await wait_for_approval(timeout=3600)
|
|
85576
|
-
async def wait_for_approval(timeout: int = 1800, form: dict | None = None, self_approval: bool = True) -> dict
|
|
85775
|
+
# urls = await step("urls", lambda: get_approval_urls("manager"))
|
|
85776
|
+
# await step("notify", lambda: send_email(urls["resume"], urls["cancel"]))
|
|
85777
|
+
# result = await wait_for_approval(key="manager", timeout=3600)
|
|
85778
|
+
async def wait_for_approval(timeout: int = 1800, form: dict | None = None, self_approval: bool = True, key: str | None = None) -> dict
|
|
85577
85779
|
|
|
85578
85780
|
# Process items in parallel with optional concurrency control.
|
|
85579
85781
|
#
|
|
@@ -86650,6 +86852,18 @@ const user = await backend.get_user({ user_id: '123' });
|
|
|
86650
86852
|
|
|
86651
86853
|
The frontend cannot reach datatables, workspace items, or external services on its own — it goes through \`backend.<key>(args)\` for everything server-side.
|
|
86652
86854
|
|
|
86855
|
+
### Keeping data out of recorded demos
|
|
86856
|
+
|
|
86857
|
+
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:
|
|
86858
|
+
|
|
86859
|
+
\`\`\`tsx
|
|
86860
|
+
<label data-wm-no-record>
|
|
86861
|
+
Customer SSN <input value={ssn} onChange={onSsn} />
|
|
86862
|
+
</label>
|
|
86863
|
+
\`\`\`
|
|
86864
|
+
|
|
86865
|
+
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.
|
|
86866
|
+
|
|
86653
86867
|
## Backend runnables
|
|
86654
86868
|
|
|
86655
86869
|
Each runnable has a unique key (used to call it from the frontend) and one of four types:
|
|
@@ -86752,6 +86966,7 @@ def main(user_id: str):
|
|
|
86752
86966
|
3. **Keep runnables focused** — one function per runnable; small surface area.
|
|
86753
86967
|
4. **Use descriptive keys** — \`get_user\`, not \`a\`.
|
|
86754
86968
|
5. **Always whitelist tables** — adding a runnable that queries a new table requires the table to be in \`data.tables\` first.
|
|
86969
|
+
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.
|
|
86755
86970
|
`,
|
|
86756
86971
|
triggers: `---
|
|
86757
86972
|
name: triggers
|
|
@@ -87205,7 +87420,7 @@ import {
|
|
|
87205
87420
|
step,
|
|
87206
87421
|
sleep,
|
|
87207
87422
|
waitForApproval,
|
|
87208
|
-
|
|
87423
|
+
getApprovalUrls,
|
|
87209
87424
|
parallel,
|
|
87210
87425
|
workflow,
|
|
87211
87426
|
} from "windmill-client";
|
|
@@ -87223,7 +87438,7 @@ export const main = workflow(async (x: string) => {
|
|
|
87223
87438
|
Python:
|
|
87224
87439
|
|
|
87225
87440
|
\`\`\`python
|
|
87226
|
-
from wmill import task, task_script, task_flow, step, sleep, wait_for_approval,
|
|
87441
|
+
from wmill import task, task_script, task_flow, step, sleep, wait_for_approval, get_approval_urls, parallel, workflow
|
|
87227
87442
|
|
|
87228
87443
|
@task()
|
|
87229
87444
|
async def process(x: str) -> str:
|
|
@@ -87307,12 +87522,13 @@ output = await pipeline(input=data)
|
|
|
87307
87522
|
Use \`step()\` for lightweight inline values that must not change during replay:
|
|
87308
87523
|
|
|
87309
87524
|
\`\`\`typescript
|
|
87310
|
-
const urls = await step("get_urls", () => getResumeUrls());
|
|
87311
87525
|
const startedAt = await step("started_at", () => new Date().toISOString());
|
|
87312
87526
|
\`\`\`
|
|
87313
87527
|
|
|
87314
87528
|
\`\`\`python
|
|
87315
|
-
|
|
87529
|
+
from datetime import datetime
|
|
87530
|
+
|
|
87531
|
+
started_at = await step("started_at", lambda: datetime.now().isoformat())
|
|
87316
87532
|
\`\`\`
|
|
87317
87533
|
|
|
87318
87534
|
Use stable, descriptive step names. Do not generate step names dynamically.
|
|
@@ -87337,20 +87553,28 @@ Only parallelize independent steps. Do not read the result of a task before it i
|
|
|
87337
87553
|
|
|
87338
87554
|
## Approvals
|
|
87339
87555
|
|
|
87340
|
-
|
|
87556
|
+
Name the approval step and generate its URLs inside \`step()\` before sending them.
|
|
87557
|
+
\`getApprovalUrls\` / \`get_approval_urls\` returns the URLs bound to that step, the same
|
|
87558
|
+
ones its built-in approve/reject buttons use:
|
|
87341
87559
|
|
|
87342
87560
|
\`\`\`typescript
|
|
87343
|
-
const urls = await step("
|
|
87344
|
-
await step("notify", () => sendApprovalEmail(urls.
|
|
87345
|
-
const approval = await waitForApproval({ timeout: 3600 });
|
|
87561
|
+
const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
87562
|
+
await step("notify", () => sendApprovalEmail(urls.resume, urls.cancel));
|
|
87563
|
+
const approval = await waitForApproval({ key: "manager", timeout: 3600 });
|
|
87346
87564
|
\`\`\`
|
|
87347
87565
|
|
|
87348
87566
|
\`\`\`python
|
|
87349
|
-
urls = await step("
|
|
87350
|
-
await step("notify", lambda: send_approval_email(urls["
|
|
87351
|
-
approval = await wait_for_approval(timeout=3600)
|
|
87567
|
+
urls = await step("urls", lambda: get_approval_urls("manager"))
|
|
87568
|
+
await step("notify", lambda: send_approval_email(urls["resume"], urls["cancel"]))
|
|
87569
|
+
approval = await wait_for_approval(key="manager", timeout=3600)
|
|
87352
87570
|
\`\`\`
|
|
87353
87571
|
|
|
87572
|
+
With several approvals in one workflow, give each its own key so each notification
|
|
87573
|
+
resumes its own step. Keys must be unique — reusing one raises an error rather than
|
|
87574
|
+
silently renaming the step. A minted URL only resumes while its own step is awaiting
|
|
87575
|
+
approval; used at any other moment it is rejected rather than resuming the wrong one. \`getResumeUrls()\` / \`get_resume_urls()\` still works but signs a
|
|
87576
|
+
random nonce, so its URLs are not tied to any particular approval step.
|
|
87577
|
+
|
|
87354
87578
|
\`selfApproval: false\` and \`self_approval=False\` are Enterprise-only approval behavior. Do not use them unless the user asks for that behavior.
|
|
87355
87579
|
|
|
87356
87580
|
## Error Handling
|
|
@@ -87364,7 +87588,7 @@ TypeScript: avoid broad \`try/catch\` around WAC SDK calls. The SDK uses an inte
|
|
|
87364
87588
|
|
|
87365
87589
|
## TypeScript Workflow-as-Code API (windmill-client)
|
|
87366
87590
|
|
|
87367
|
-
Import: \`import { workflow, task, taskScript, taskFlow, step, sleep, waitForApproval, getResumeUrls, parallel } from "windmill-client"\`
|
|
87591
|
+
Import: \`import { workflow, task, taskScript, taskFlow, step, sleep, waitForApproval, getApprovalUrls, getResumeUrls, parallel } from "windmill-client"\`
|
|
87368
87592
|
|
|
87369
87593
|
\`\`\`typescript
|
|
87370
87594
|
export interface TaskOptions {
|
|
@@ -87434,15 +87658,39 @@ export async function sleep(seconds: number): Promise<void>
|
|
|
87434
87658
|
/**
|
|
87435
87659
|
* Suspend the workflow and wait for an external approval.
|
|
87436
87660
|
*
|
|
87437
|
-
*
|
|
87438
|
-
*
|
|
87661
|
+
* Pass \`key\` to name the step, then \`getApprovalUrls(key)\` yields the URLs that
|
|
87662
|
+
* resume exactly this approval — route them through your own channel. Without a
|
|
87663
|
+
* key the steps are named \`approval\`, \`approval_2\`, ...
|
|
87664
|
+
*
|
|
87665
|
+
* @example
|
|
87666
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
87667
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
87668
|
+
* const { value, approver } = await waitForApproval({ key: "manager", timeout: 3600 });
|
|
87669
|
+
*/
|
|
87670
|
+
export function waitForApproval(options?: { timeout?: number; form?: object; selfApproval?: boolean; key?: string; }): PromiseLike<{ value: any; approver: string; approved: boolean }>
|
|
87671
|
+
|
|
87672
|
+
/**
|
|
87673
|
+
* Resume/cancel/approval-page URLs bound to one \`waitForApproval\` step.
|
|
87674
|
+
*
|
|
87675
|
+
* Unlike \`getResumeUrls()\`, which signs a random nonce, these address the very
|
|
87676
|
+
* \`resume_job\` record the step's built-in approval buttons use, so they are
|
|
87677
|
+
* stable across replays and safe to embed in a custom notification.
|
|
87678
|
+
*
|
|
87679
|
+
* \`stepKey\` must match the \`key\` given to \`waitForApproval\`. Keys must be unique
|
|
87680
|
+
* within a workflow; reusing one throws rather than silently renaming it. The URL
|
|
87681
|
+
* only resumes while that step is awaiting approval; used at any other moment it is
|
|
87682
|
+
* rejected rather than banking a row a different approval would consume. Send it
|
|
87683
|
+
* ahead of time — approvers just cannot act before the workflow reaches the step.
|
|
87684
|
+
*
|
|
87685
|
+
* \`resume\` and \`cancel\` are step-bound; \`approvalPage\` is not — it opens the job's
|
|
87686
|
+
* approval page, which acts on whichever approval is pending when it is used.
|
|
87439
87687
|
*
|
|
87440
87688
|
* @example
|
|
87441
|
-
* const urls = await step("urls", () =>
|
|
87442
|
-
* await step("notify", () => sendEmail(urls.
|
|
87443
|
-
*
|
|
87689
|
+
* const urls = await step("urls", () => getApprovalUrls("manager"));
|
|
87690
|
+
* await step("notify", () => sendEmail(urls.resume, urls.cancel));
|
|
87691
|
+
* await waitForApproval({ key: "manager" });
|
|
87444
87692
|
*/
|
|
87445
|
-
export function
|
|
87693
|
+
export async function getApprovalUrls(stepKey: string = "approval", approver?: string): Promise<{ approvalPage: string; resume: string; cancel: string; }>
|
|
87446
87694
|
|
|
87447
87695
|
/**
|
|
87448
87696
|
* Process items in parallel with optional concurrency control.
|
|
@@ -87460,7 +87708,7 @@ export async function parallel<T, R>(items: T[], fn: (item: T) => PromiseLike<R>
|
|
|
87460
87708
|
|
|
87461
87709
|
## Python Workflow-as-Code API (wmill)
|
|
87462
87710
|
|
|
87463
|
-
Import: \`from wmill import workflow, task, task_script, task_flow, step, sleep, wait_for_approval, get_resume_urls, parallel, TaskError\`
|
|
87711
|
+
Import: \`from wmill import workflow, task, task_script, task_flow, step, sleep, wait_for_approval, get_approval_urls, get_resume_urls, parallel, TaskError\`
|
|
87464
87712
|
|
|
87465
87713
|
\`\`\`python
|
|
87466
87714
|
# Raised when a WAC task step failed.
|
|
@@ -87548,8 +87796,9 @@ async def sleep(seconds: int)
|
|
|
87548
87796
|
|
|
87549
87797
|
# Suspend the workflow and wait for an external approval.
|
|
87550
87798
|
#
|
|
87551
|
-
#
|
|
87552
|
-
# resume
|
|
87799
|
+
# Pass \`\`key\`\` to name the step, then \`\`get_approval_urls(key)\`\` yields the URLs
|
|
87800
|
+
# that resume exactly this approval — route them through your own channel.
|
|
87801
|
+
# Without a key the steps are named \`\`approval\`\`, \`\`approval_2\`\`, ...
|
|
87553
87802
|
#
|
|
87554
87803
|
# Returns a dict with \`\`value\`\` (form data), \`\`approver\`\`, and \`\`approved\`\`.
|
|
87555
87804
|
#
|
|
@@ -87557,13 +87806,37 @@ async def sleep(seconds: int)
|
|
|
87557
87806
|
# timeout: Approval timeout in seconds (default 1800).
|
|
87558
87807
|
# form: Optional form schema for the approval page.
|
|
87559
87808
|
# self_approval: Whether the user who triggered the flow can approve it (default True).
|
|
87809
|
+
# key: Optional checkpoint key naming this approval step.
|
|
87560
87810
|
#
|
|
87561
87811
|
# Example::
|
|
87562
87812
|
#
|
|
87563
|
-
# urls = await step("urls", lambda:
|
|
87564
|
-
# await step("notify", lambda: send_email(urls["
|
|
87565
|
-
# result = await wait_for_approval(timeout=3600)
|
|
87566
|
-
async def wait_for_approval(timeout: int = 1800, form: dict | None = None, self_approval: bool = True) -> dict
|
|
87813
|
+
# urls = await step("urls", lambda: get_approval_urls("manager"))
|
|
87814
|
+
# await step("notify", lambda: send_email(urls["resume"], urls["cancel"]))
|
|
87815
|
+
# result = await wait_for_approval(key="manager", timeout=3600)
|
|
87816
|
+
async def wait_for_approval(timeout: int = 1800, form: dict | None = None, self_approval: bool = True, key: str | None = None) -> dict
|
|
87817
|
+
|
|
87818
|
+
# Get the resume/cancel/approval-page URLs bound to one \`\`wait_for_approval\`\` step.
|
|
87819
|
+
#
|
|
87820
|
+
# Unlike :func:\`get_resume_urls\`, which signs a random nonce, these address the
|
|
87821
|
+
# very \`\`resume_job\`\` record the step's built-in approval buttons use, so they
|
|
87822
|
+
# are stable across replays and safe to embed in a custom notification.
|
|
87823
|
+
#
|
|
87824
|
+
# Args:
|
|
87825
|
+
# step_key: Checkpoint key of the approval step, as passed to
|
|
87826
|
+
# \`\`wait_for_approval(key=...)\`\`. Keys must be unique within a workflow;
|
|
87827
|
+
# reusing one raises rather than silently renaming it. The URL only
|
|
87828
|
+
# resumes while that step is awaiting approval; used at any other moment
|
|
87829
|
+
# it is rejected rather than banking a row a different approval would
|
|
87830
|
+
# consume. Send it ahead of time — approvers just cannot act before the
|
|
87831
|
+
# workflow reaches the step.
|
|
87832
|
+
# \`\`resume\`\` and \`\`cancel\`\` are step-bound; \`\`approvalPage\`\` is not — it
|
|
87833
|
+
# opens the job's approval page, which acts on whichever approval is
|
|
87834
|
+
# pending when it is used.
|
|
87835
|
+
# approver: Optional approver name
|
|
87836
|
+
#
|
|
87837
|
+
# Returns:
|
|
87838
|
+
# Dictionary with approvalPage, resume, and cancel URLs
|
|
87839
|
+
def get_approval_urls(step_key: str = 'approval', approver: str = None) -> dict
|
|
87567
87840
|
|
|
87568
87841
|
# Process items in parallel with optional concurrency control.
|
|
87569
87842
|
#
|