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/index.js CHANGED
@@ -126,7 +126,7 @@ const OpenAPI = {
126
126
  PASSWORD: void 0,
127
127
  TOKEN: getEnv$1("WM_TOKEN"),
128
128
  USERNAME: void 0,
129
- VERSION: "1.769.0",
129
+ VERSION: "1.771.0",
130
130
  WITH_CREDENTIALS: true,
131
131
  interceptors: {
132
132
  request: new Interceptors(),
@@ -7445,6 +7445,42 @@ var ScriptService = class {
7445
7445
  mediaType: "application/json"
7446
7446
  });
7447
7447
  }
7448
+ /**
7449
+ * list runnables (scripts, flows, apps) merged, ordered and keyset-paginated
7450
+ * @param data The data for the request.
7451
+ * @param data.workspace
7452
+ * @param data.orderBy sort key: 'updated' (default) or 'name'
7453
+ * @param data.orderDesc order by desc order (default true)
7454
+ * @param data.kinds comma-separated subset of script,flow,app (default all)
7455
+ * @param data.showArchived
7456
+ * @param data.includeWithoutMain include library scripts (no runnable main)
7457
+ * @param data.pathStart restrict to paths under this prefix
7458
+ * @param data.label
7459
+ * @param data.search case-insensitive substring match on summary or path
7460
+ * @param data.perPage number of items to return for a given page (default 30, max 100)
7461
+ * @param data.cursor opaque keyset cursor from a previous page's next_cursor
7462
+ * @returns unknown a page of merged, ordered runnables
7463
+ * @throws ApiError
7464
+ */
7465
+ static listRunnables(data) {
7466
+ return request(OpenAPI, {
7467
+ method: "GET",
7468
+ url: "/w/{workspace}/runnables/list",
7469
+ path: { workspace: data.workspace },
7470
+ query: {
7471
+ order_by: data.orderBy,
7472
+ order_desc: data.orderDesc,
7473
+ kinds: data.kinds,
7474
+ show_archived: data.showArchived,
7475
+ include_without_main: data.includeWithoutMain,
7476
+ path_start: data.pathStart,
7477
+ label: data.label,
7478
+ search: data.search,
7479
+ per_page: data.perPage,
7480
+ cursor: data.cursor
7481
+ }
7482
+ });
7483
+ }
7448
7484
  };
7449
7485
  var DraftService = class {
7450
7486
  /**
@@ -8975,6 +9011,7 @@ var JobService = class {
8975
9011
  * @param data.page which page to return (start at 1, default 1)
8976
9012
  * @param data.perPage number of items to return for a given page (default 30, max 100)
8977
9013
  * @param data.isSkipped is the job skipped
9014
+ * @param data.resolved filter on whether a failure has been marked as handled. true keeps only resolved failures, false hides them
8978
9015
  * @param data.isFlowStep is the job a flow step
8979
9016
  * @param data.hasNullParent has null parent
8980
9017
  * @param data.success filter on successful jobs
@@ -9016,6 +9053,7 @@ var JobService = class {
9016
9053
  page: data.page,
9017
9054
  per_page: data.perPage,
9018
9055
  is_skipped: data.isSkipped,
9056
+ resolved: data.resolved,
9019
9057
  is_flow_step: data.isFlowStep,
9020
9058
  has_null_parent: data.hasNullParent,
9021
9059
  success: data.success,
@@ -9153,6 +9191,7 @@ var JobService = class {
9153
9191
  * @param data.page which page to return (start at 1, default 1)
9154
9192
  * @param data.perPage number of items to return for a given page (default 30, max 100)
9155
9193
  * @param data.isSkipped is the job skipped
9194
+ * @param data.resolved filter on whether a failure has been marked as handled. true keeps only resolved failures, false hides them
9156
9195
  * @param data.isFlowStep is the job a flow step
9157
9196
  * @param data.hasNullParent has null parent
9158
9197
  * @param data.isNotSchedule is not a scheduled job
@@ -9186,6 +9225,7 @@ var JobService = class {
9186
9225
  page: data.page,
9187
9226
  per_page: data.perPage,
9188
9227
  is_skipped: data.isSkipped,
9228
+ resolved: data.resolved,
9189
9229
  is_flow_step: data.isFlowStep,
9190
9230
  has_null_parent: data.hasNullParent,
9191
9231
  is_not_schedule: data.isNotSchedule
@@ -9314,6 +9354,7 @@ var JobService = class {
9314
9354
  * @param data.perPage number of items to return for a given page (default 30, max 100)
9315
9355
  * @param data.triggerKind filter by trigger kind. Supports comma-separated list (e.g. 'schedule,webhook') and negation by prefixing all values with '!' (e.g. '!schedule,!webhook')
9316
9356
  * @param data.isSkipped is the job skipped
9357
+ * @param data.resolved filter on whether a failure has been marked as handled. true keeps only resolved failures, false hides them
9317
9358
  * @param data.isFlowStep is the job a flow step
9318
9359
  * @param data.hasNullParent has null parent
9319
9360
  * @param data.success filter on successful jobs
@@ -9358,6 +9399,7 @@ var JobService = class {
9358
9399
  per_page: data.perPage,
9359
9400
  trigger_kind: data.triggerKind,
9360
9401
  is_skipped: data.isSkipped,
9402
+ resolved: data.resolved,
9361
9403
  is_flow_step: data.isFlowStep,
9362
9404
  has_null_parent: data.hasNullParent,
9363
9405
  success: data.success,
@@ -9796,6 +9838,41 @@ var JobService = class {
9796
9838
  });
9797
9839
  }
9798
9840
  /**
9841
+ * mark failed jobs as resolved
9842
+ * Marks failed jobs as handled so triage surfaces stop showing them as failures. The job status itself is unchanged. Returns the ids actually resolved: ids that are not visible to the caller or did not fail are silently skipped.
9843
+ * @param data The data for the request.
9844
+ * @param data.workspace
9845
+ * @param data.requestBody
9846
+ * @returns string ids of the jobs that were resolved
9847
+ * @throws ApiError
9848
+ */
9849
+ static resolveCompletedJobs(data) {
9850
+ return request(OpenAPI, {
9851
+ method: "POST",
9852
+ url: "/w/{workspace}/jobs/completed/resolve",
9853
+ path: { workspace: data.workspace },
9854
+ body: data.requestBody,
9855
+ mediaType: "application/json"
9856
+ });
9857
+ }
9858
+ /**
9859
+ * remove the resolution of failed jobs
9860
+ * @param data The data for the request.
9861
+ * @param data.workspace
9862
+ * @param data.requestBody
9863
+ * @returns string ids of the jobs that were unresolved
9864
+ * @throws ApiError
9865
+ */
9866
+ static unresolveCompletedJobs(data) {
9867
+ return request(OpenAPI, {
9868
+ method: "POST",
9869
+ url: "/w/{workspace}/jobs/completed/unresolve",
9870
+ path: { workspace: data.workspace },
9871
+ body: data.requestBody,
9872
+ mediaType: "application/json"
9873
+ });
9874
+ }
9875
+ /**
9799
9876
  * cancel queued or running job
9800
9877
  * @param data The data for the request.
9801
9878
  * @param data.workspace
@@ -9943,6 +10020,28 @@ var JobService = class {
9943
10020
  });
9944
10021
  }
9945
10022
  /**
10023
+ * get the resume urls bound to a specific wait_for_approval step of a workflow-as-code job
10024
+ * @param data The data for the request.
10025
+ * @param data.workspace
10026
+ * @param data.id
10027
+ * @param data.stepKey checkpoint key of the wait_for_approval step, as passed to `wait_for_approval(key=...)`
10028
+ * @param data.approver
10029
+ * @returns unknown url endpoints
10030
+ * @throws ApiError
10031
+ */
10032
+ static getWacApprovalUrls(data) {
10033
+ return request(OpenAPI, {
10034
+ method: "GET",
10035
+ url: "/w/{workspace}/jobs/wac_approval_urls/{id}/{step_key}",
10036
+ path: {
10037
+ workspace: data.workspace,
10038
+ id: data.id,
10039
+ step_key: data.stepKey
10040
+ },
10041
+ query: { approver: data.approver }
10042
+ });
10043
+ }
10044
+ /**
9946
10045
  * generate interactive slack approval for suspended job
9947
10046
  * @param data The data for the request.
9948
10047
  * @param data.workspace
@@ -10289,6 +10388,7 @@ var JobService = class {
10289
10388
  * @param data.perPage number of items to return for a given page (default 30, max 100)
10290
10389
  * @param data.triggerKind filter by trigger kind. Supports comma-separated list (e.g. 'schedule,webhook') and negation by prefixing all values with '!' (e.g. '!schedule,!webhook')
10291
10390
  * @param data.isSkipped is the job skipped
10391
+ * @param data.resolved filter on whether a failure has been marked as handled. true keeps only resolved failures, false hides them
10292
10392
  * @param data.isFlowStep is the job a flow step
10293
10393
  * @param data.hasNullParent has null parent
10294
10394
  * @param data.success filter on successful jobs
@@ -10330,6 +10430,7 @@ var JobService = class {
10330
10430
  per_page: data.perPage,
10331
10431
  trigger_kind: data.triggerKind,
10332
10432
  is_skipped: data.isSkipped,
10433
+ resolved: data.resolved,
10333
10434
  is_flow_step: data.isFlowStep,
10334
10435
  has_null_parent: data.hasNullParent,
10335
10436
  success: data.success,
@@ -13857,6 +13958,8 @@ var FolderService = class {
13857
13958
  * list folder names
13858
13959
  * @param data The data for the request.
13859
13960
  * @param data.workspace
13961
+ * @param data.page which page to return (start at 1, default 1)
13962
+ * @param data.perPage number of items to return for a given page (default 30, max 100)
13860
13963
  * @param data.onlyMemberOf only list the folders the user is member of (default false)
13861
13964
  * @returns string folder list
13862
13965
  * @throws ApiError
@@ -13866,7 +13969,11 @@ var FolderService = class {
13866
13969
  method: "GET",
13867
13970
  url: "/w/{workspace}/folders/listnames",
13868
13971
  path: { workspace: data.workspace },
13869
- query: { only_member_of: data.onlyMemberOf }
13972
+ query: {
13973
+ page: data.page,
13974
+ per_page: data.perPage,
13975
+ only_member_of: data.onlyMemberOf
13976
+ }
13870
13977
  });
13871
13978
  }
13872
13979
  /**
@@ -14731,6 +14838,7 @@ var HelpersService = class {
14731
14838
  * @param data The data for the request.
14732
14839
  * @param data.workspace
14733
14840
  * @param data.storage
14841
+ * @param data.s3ResourcePath When set, test the connection of this object storage resource instead of the workspace storage
14734
14842
  * @returns unknown Connection settings
14735
14843
  * @throws ApiError
14736
14844
  */
@@ -14739,7 +14847,10 @@ var HelpersService = class {
14739
14847
  method: "GET",
14740
14848
  url: "/w/{workspace}/job_helpers/test_connection",
14741
14849
  path: { workspace: data.workspace },
14742
- query: { storage: data.storage }
14850
+ query: {
14851
+ storage: data.storage,
14852
+ s3_resource_path: data.s3ResourcePath
14853
+ }
14743
14854
  });
14744
14855
  }
14745
14856
  /**
@@ -14766,6 +14877,7 @@ var HelpersService = class {
14766
14877
  * @param data.marker
14767
14878
  * @param data.prefix
14768
14879
  * @param data.storage
14880
+ * @param data.s3ResourcePath When set, list the files of this object storage resource instead of the workspace storage
14769
14881
  * @returns unknown List of file keys
14770
14882
  * @throws ApiError
14771
14883
  */
@@ -14778,7 +14890,8 @@ var HelpersService = class {
14778
14890
  max_keys: data.maxKeys,
14779
14891
  marker: data.marker,
14780
14892
  prefix: data.prefix,
14781
- storage: data.storage
14893
+ storage: data.storage,
14894
+ s3_resource_path: data.s3ResourcePath
14782
14895
  }
14783
14896
  });
14784
14897
  }
@@ -14788,6 +14901,7 @@ var HelpersService = class {
14788
14901
  * @param data.workspace
14789
14902
  * @param data.fileKey
14790
14903
  * @param data.storage
14904
+ * @param data.s3ResourcePath When set, load the file metadata from this object storage resource instead of the workspace storage
14791
14905
  * @returns WindmillFileMetadata FileMetadata
14792
14906
  * @throws ApiError
14793
14907
  */
@@ -14798,7 +14912,8 @@ var HelpersService = class {
14798
14912
  path: { workspace: data.workspace },
14799
14913
  query: {
14800
14914
  file_key: data.fileKey,
14801
- storage: data.storage
14915
+ storage: data.storage,
14916
+ s3_resource_path: data.s3ResourcePath
14802
14917
  }
14803
14918
  });
14804
14919
  }
@@ -14814,6 +14929,7 @@ var HelpersService = class {
14814
14929
  * @param data.readBytesFrom
14815
14930
  * @param data.readBytesLength
14816
14931
  * @param data.storage
14932
+ * @param data.s3ResourcePath When set, load the file preview from this object storage resource instead of the workspace storage
14817
14933
  * @returns WindmillFilePreview FilePreview
14818
14934
  * @throws ApiError
14819
14935
  */
@@ -14830,7 +14946,8 @@ var HelpersService = class {
14830
14946
  csv_has_header: data.csvHasHeader,
14831
14947
  read_bytes_from: data.readBytesFrom,
14832
14948
  read_bytes_length: data.readBytesLength,
14833
- storage: data.storage
14949
+ storage: data.storage,
14950
+ s3_resource_path: data.s3ResourcePath
14834
14951
  }
14835
14952
  });
14836
14953
  }
@@ -15035,6 +15152,7 @@ var HelpersService = class {
15035
15152
  * @param data.workspace
15036
15153
  * @param data.fileKey
15037
15154
  * @param data.storage
15155
+ * @param data.s3ResourcePath When set, delete the file from this object storage resource instead of the workspace storage
15038
15156
  * @returns unknown Confirmation
15039
15157
  * @throws ApiError
15040
15158
  */
@@ -15045,7 +15163,8 @@ var HelpersService = class {
15045
15163
  path: { workspace: data.workspace },
15046
15164
  query: {
15047
15165
  file_key: data.fileKey,
15048
- storage: data.storage
15166
+ storage: data.storage,
15167
+ s3_resource_path: data.s3ResourcePath
15049
15168
  }
15050
15169
  });
15051
15170
  }
@@ -15056,6 +15175,7 @@ var HelpersService = class {
15056
15175
  * @param data.srcFileKey
15057
15176
  * @param data.destFileKey
15058
15177
  * @param data.storage
15178
+ * @param data.s3ResourcePath When set, move the file within this object storage resource instead of the workspace storage
15059
15179
  * @returns unknown Confirmation
15060
15180
  * @throws ApiError
15061
15181
  */
@@ -15067,7 +15187,8 @@ var HelpersService = class {
15067
15187
  query: {
15068
15188
  src_file_key: data.srcFileKey,
15069
15189
  dest_file_key: data.destFileKey,
15070
- storage: data.storage
15190
+ storage: data.storage,
15191
+ s3_resource_path: data.s3ResourcePath
15071
15192
  }
15072
15193
  });
15073
15194
  }
@@ -15352,6 +15473,7 @@ var ConcurrencyGroupsService = class {
15352
15473
  * @param data.perPage number of items to return for a given page (default 30, max 100)
15353
15474
  * @param data.triggerKind filter by trigger kind. Supports comma-separated list (e.g. 'schedule,webhook') and negation by prefixing all values with '!' (e.g. '!schedule,!webhook')
15354
15475
  * @param data.isSkipped is the job skipped
15476
+ * @param data.resolved filter on whether a failure has been marked as handled. true keeps only resolved failures, false hides them
15355
15477
  * @param data.isFlowStep is the job a flow step
15356
15478
  * @param data.hasNullParent has null parent
15357
15479
  * @param data.success filter on successful jobs
@@ -15393,6 +15515,7 @@ var ConcurrencyGroupsService = class {
15393
15515
  per_page: data.perPage,
15394
15516
  trigger_kind: data.triggerKind,
15395
15517
  is_skipped: data.isSkipped,
15518
+ resolved: data.resolved,
15396
15519
  is_flow_step: data.isFlowStep,
15397
15520
  has_null_parent: data.hasNullParent,
15398
15521
  success: data.success,
@@ -15985,6 +16108,36 @@ var HubPublishService = class {
15985
16108
  });
15986
16109
  }
15987
16110
  /**
16111
+ * attach a recorded session to a hub raw app
16112
+ * Requires the caller to be a workspace admin. Forwards the request to the
16113
+ * configured Hub scoped to the `{workspace}:{folder}` source and returns
16114
+ * the Hub's status code and raw response body.
16115
+ *
16116
+ * @param data The data for the request.
16117
+ * @param data.workspace
16118
+ * @param data.id hub id of the raw app
16119
+ * @param data.folder workspace folder scoping the Hub publication: a workspace can publish
16120
+ * one Hub project per folder and the Hub-side source key is
16121
+ * `{workspace}:{folder}`
16122
+ *
16123
+ * @param data.requestBody
16124
+ * @returns string raw Hub response body (status code is passed through from the Hub)
16125
+ * @throws ApiError
16126
+ */
16127
+ static publishHubRawAppRecording(data) {
16128
+ return request(OpenAPI, {
16129
+ method: "POST",
16130
+ url: "/w/{workspace}/hub/raw_apps/{id}/recording",
16131
+ path: {
16132
+ workspace: data.workspace,
16133
+ id: data.id
16134
+ },
16135
+ query: { folder: data.folder },
16136
+ body: data.requestBody,
16137
+ mediaType: "application/json"
16138
+ });
16139
+ }
16140
+ /**
15988
16141
  * attach a recording to a hub script
15989
16142
  * Requires the caller to be a workspace admin. Forwards the request to the
15990
16143
  * configured Hub scoped to the `{workspace}:{folder}` source and returns
@@ -16205,6 +16358,39 @@ var HubPublishService = class {
16205
16358
  });
16206
16359
  }
16207
16360
  /**
16361
+ * set or clear a hub project's custom logo
16362
+ * Requires the caller to be a workspace admin. Sets the project's custom
16363
+ * logo (base64 png/svg, decoded size max 512KB) or clears it when `logo`
16364
+ * is null; the `logo` field itself is required so an empty body cannot
16365
+ * clear the logo by accident. Forwards the request to the configured Hub
16366
+ * scoped to the `{workspace}:{folder}` source and returns the Hub's
16367
+ * status code and raw response body.
16368
+ *
16369
+ * @param data The data for the request.
16370
+ * @param data.workspace
16371
+ * @param data.slug hub project slug
16372
+ * @param data.folder workspace folder scoping the Hub publication: a workspace can publish
16373
+ * one Hub project per folder and the Hub-side source key is
16374
+ * `{workspace}:{folder}`
16375
+ *
16376
+ * @param data.requestBody
16377
+ * @returns string raw Hub response body (status code is passed through from the Hub)
16378
+ * @throws ApiError
16379
+ */
16380
+ static publishHubProjectLogo(data) {
16381
+ return request(OpenAPI, {
16382
+ method: "POST",
16383
+ url: "/w/{workspace}/hub/projects/{slug}/logo",
16384
+ path: {
16385
+ workspace: data.workspace,
16386
+ slug: data.slug
16387
+ },
16388
+ query: { folder: data.folder },
16389
+ body: data.requestBody,
16390
+ mediaType: "application/json"
16391
+ });
16392
+ }
16393
+ /**
16208
16394
  * submit a hub project draft for review
16209
16395
  * Requires the caller to be a workspace admin. Forwards the request to the
16210
16396
  * configured Hub scoped to the `{workspace}:{folder}` source and returns
@@ -17589,6 +17775,13 @@ var StepSuspend = class extends Error {
17589
17775
  this.name = "StepSuspend";
17590
17776
  }
17591
17777
  };
17778
+ /** A step key travels as one path segment when its URLs are minted, so it must be
17779
+ * non-empty and free of `/` and dot segments — otherwise `waitForApproval` would
17780
+ * accept a key `getApprovalUrls` can never address. */
17781
+ function assertUsableStepKey(key, what) {
17782
+ const k = key.trim();
17783
+ if (k === "" || k === "." || k === ".." || key.includes("/") || key.includes("\\")) throw new Error(`${what} must be a non-empty step name without \`/\` or dot segments`);
17784
+ }
17592
17785
  let _workflowCtx = null;
17593
17786
  function setWorkflowCtx(ctx) {
17594
17787
  _workflowCtx = ctx;
@@ -17596,7 +17789,11 @@ function setWorkflowCtx(ctx) {
17596
17789
  }
17597
17790
  var WorkflowCtx = class {
17598
17791
  completed;
17599
- counters = {};
17792
+ /** Null-prototype: step keys are caller-supplied, and a plain object would
17793
+ * resolve `toString`/`constructor`/`__proto__` off `Object.prototype`. */
17794
+ counters = Object.create(null);
17795
+ /** Every key handed out by `_allocKey`, so distinct names can't alias one key. */
17796
+ _usedKeys = new Set();
17600
17797
  pending = [];
17601
17798
  _suspended = false;
17602
17799
  /** When set, the task matching this key executes its inner function directly */
@@ -17612,14 +17809,23 @@ var WorkflowCtx = class {
17612
17809
  * `completed_steps[key]`. Initialized to a resolved promise. */
17613
17810
  _inlineChain = Promise.resolve();
17614
17811
  constructor(checkpoint = {}) {
17615
- this.completed = checkpoint?.completed_steps ?? {};
17812
+ this.completed = Object.assign(Object.create(null), checkpoint?.completed_steps ?? {});
17616
17813
  this._executingKey = checkpoint?._executing_key ?? null;
17617
17814
  }
17618
- /** Name-based key: `double` for first call, `double_2`, `double_3` for subsequent. */
17815
+ /** Name-based key: `double` for first call, `double_2`, `double_3` for subsequent.
17816
+ * Suffixing alone can alias — a second `step("x")` and a first `step("x_2")` both
17817
+ * want `x_2` — so keep bumping past keys already handed out. Allocation order is
17818
+ * fixed by the workflow body, so replays reproduce the same keys. */
17619
17819
  _allocKey(name) {
17620
- const n = (this.counters[name] ?? 0) + 1;
17820
+ let n = (this.counters[name] ?? 0) + 1;
17821
+ let key = n === 1 ? name : `${name}_${n}`;
17822
+ while (this._usedKeys.has(key)) {
17823
+ n++;
17824
+ key = `${name}_${n}`;
17825
+ }
17621
17826
  this.counters[name] = n;
17622
- return n === 1 ? name : `${name}_${n}`;
17827
+ this._usedKeys.add(key);
17828
+ return key;
17623
17829
  }
17624
17830
  _nextStep(name, script, args = {}, dispatch_type = "inline", options) {
17625
17831
  const key = this._allocKey(name || script || "step");
@@ -17679,7 +17885,9 @@ var WorkflowCtx = class {
17679
17885
  return steps;
17680
17886
  }
17681
17887
  _waitForApproval(options) {
17682
- const key = this._allocKey("approval");
17888
+ if (options?.key !== void 0) assertUsableStepKey(options.key, "waitForApproval key");
17889
+ const key = this._allocKey(options?.key || "approval");
17890
+ 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.`);
17683
17891
  if (key in this.completed) {
17684
17892
  const value = this.completed[key];
17685
17893
  return { then: (resolve$1) => resolve$1(value) };
@@ -17918,13 +18126,14 @@ function workflow(fn) {
17918
18126
  /**
17919
18127
  * Suspend the workflow and wait for an external approval.
17920
18128
  *
17921
- * Use `getResumeUrls()` (wrapped in `step()`) to obtain resume/cancel/approvalPage
17922
- * URLs before calling this function.
18129
+ * Pass `key` to name the step, then `getApprovalUrls(key)` yields the URLs that
18130
+ * resume exactly this approval — route them through your own channel. Without a
18131
+ * key the steps are named `approval`, `approval_2`, ...
17923
18132
  *
17924
18133
  * @example
17925
- * const urls = await step("urls", () => getResumeUrls());
17926
- * await step("notify", () => sendEmail(urls.approvalPage));
17927
- * const { value, approver } = await waitForApproval({ timeout: 3600 });
18134
+ * const urls = await step("urls", () => getApprovalUrls("manager"));
18135
+ * await step("notify", () => sendEmail(urls.resume, urls.cancel));
18136
+ * const { value, approver } = await waitForApproval({ key: "manager", timeout: 3600 });
17928
18137
  */
17929
18138
  function waitForApproval(options) {
17930
18139
  const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
@@ -17932,6 +18141,37 @@ function waitForApproval(options) {
17932
18141
  return ctx._waitForApproval(options);
17933
18142
  }
17934
18143
  /**
18144
+ * Resume/cancel/approval-page URLs bound to one `waitForApproval` step.
18145
+ *
18146
+ * Unlike `getResumeUrls()`, which signs a random nonce, these address the very
18147
+ * `resume_job` record the step's built-in approval buttons use, so they are
18148
+ * stable across replays and safe to embed in a custom notification.
18149
+ *
18150
+ * `stepKey` must match the `key` given to `waitForApproval`. Keys must be unique
18151
+ * within a workflow; reusing one throws rather than silently renaming it. The URL
18152
+ * only resumes while that step is awaiting approval; used at any other moment it is
18153
+ * rejected rather than banking a row a different approval would consume. Send it
18154
+ * ahead of time — approvers just cannot act before the workflow reaches the step.
18155
+ *
18156
+ * `resume` and `cancel` are step-bound; `approvalPage` is not — it opens the job's
18157
+ * approval page, which acts on whichever approval is pending when it is used.
18158
+ *
18159
+ * @example
18160
+ * const urls = await step("urls", () => getApprovalUrls("manager"));
18161
+ * await step("notify", () => sendEmail(urls.resume, urls.cancel));
18162
+ * await waitForApproval({ key: "manager" });
18163
+ */
18164
+ async function getApprovalUrls(stepKey = "approval", approver) {
18165
+ assertUsableStepKey(stepKey, "getApprovalUrls stepKey");
18166
+ const workspace = getWorkspace();
18167
+ return await JobService.getWacApprovalUrls({
18168
+ workspace,
18169
+ stepKey,
18170
+ approver,
18171
+ id: getEnv("WM_JOB_ID") ?? "NO_JOB_ID"
18172
+ });
18173
+ }
18174
+ /**
17935
18175
  * Process items in parallel with optional concurrency control.
17936
18176
  *
17937
18177
  * Each item is processed by calling `fn(item)`, which should be a task().
@@ -18003,6 +18243,7 @@ const wmill = {
18003
18243
  sleep,
18004
18244
  parallel,
18005
18245
  waitForApproval,
18246
+ getApprovalUrls,
18006
18247
  WorkflowCtx,
18007
18248
  _workflowCtx,
18008
18249
  setWorkflowCtx,
@@ -18142,6 +18383,7 @@ exports.default = src_default;
18142
18383
  exports.deleteS3File = deleteS3File;
18143
18384
  exports.denoS3LightClientSettings = denoS3LightClientSettings;
18144
18385
  exports.ducklake = ducklake;
18386
+ exports.getApprovalUrls = getApprovalUrls;
18145
18387
  exports.getFlowUserState = getFlowUserState;
18146
18388
  exports.getIdToken = getIdToken;
18147
18389
  exports.getPresignedS3PublicUrl = getPresignedS3PublicUrl;
package/dist/index.mjs CHANGED
@@ -4,7 +4,7 @@ import { OpenAPI } from "./core/OpenAPI.mjs";
4
4
  import { AdminService, AgentWorkersService, AmqpTriggerService, AppService, AssetService, AuditService, AzureTriggerService, CaptureService, ConcurrencyGroupsService, ConfigService, DataMetricService, DocumentationService, DraftService, EmailTriggerService, FavoriteService, FlowConversationsService, FlowService, FolderService, GcpTriggerService, GitSyncService, GranularAclService, GroupService, HealthService, HelpersService, HttpTriggerService, HubPublishService, IndexSearchService, InputService, IntegrationService, JobService, KafkaTriggerService, McpOauthService, McpService, MetricsService, MqttTriggerService, NativeTriggerService, NatsTriggerService, NpmProxyService, OauthService, OidcService, OpenapiService, PathAutocompleteService, PostgresTriggerService, RawAppService, ResourceService, ScheduleService, ScriptService, ServiceLogsService, SettingService, SettingsService, SqsTriggerService, TeamsService, TokenService, TriggerService, UserService, VariableService, VolumeService, WebsocketTriggerService, WorkerService, WorkspaceDependenciesService, WorkspaceIntegrationService, WorkspaceService } from "./services.gen.mjs";
5
5
  import { parseS3Object } from "./s3Types.mjs";
6
6
  import { appendPartition, datatable, ducklake, upsertPartition } from "./sqlUtils.mjs";
7
- import { SHARED_FOLDER, StepSuspend, WorkflowCtx, _workflowCtx, appendToResultStream, base64ToUint8Array, commitKafkaOffsets, databaseUrlFromResource, deleteS3File, denoS3LightClientSettings, 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, workflow, writeS3File } from "./client.mjs";
7
+ import { SHARED_FOLDER, StepSuspend, WorkflowCtx, _workflowCtx, appendToResultStream, base64ToUint8Array, commitKafkaOffsets, databaseUrlFromResource, deleteS3File, denoS3LightClientSettings, getApprovalUrls, 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, workflow, writeS3File } from "./client.mjs";
8
8
 
9
9
  //#region src/index.ts
10
10
  const wmill = {
@@ -36,6 +36,7 @@ const wmill = {
36
36
  sleep,
37
37
  parallel,
38
38
  waitForApproval,
39
+ getApprovalUrls,
39
40
  WorkflowCtx,
40
41
  _workflowCtx,
41
42
  setWorkflowCtx,
@@ -93,4 +94,4 @@ const wmill = {
93
94
  var src_default = wmill;
94
95
 
95
96
  //#endregion
96
- export { AdminService, AgentWorkersService, AmqpTriggerService, ApiError, AppService, AssetService, AuditService, AzureTriggerService, CancelError, CancelablePromise, CaptureService, ConcurrencyGroupsService, ConfigService, DataMetricService, DocumentationService, DraftService, EmailTriggerService, FavoriteService, FlowConversationsService, FlowService, FolderService, GcpTriggerService, GitSyncService, GranularAclService, GroupService, HealthService, HelpersService, HttpTriggerService, HubPublishService, IndexSearchService, InputService, IntegrationService, JobService, KafkaTriggerService, McpOauthService, McpService, MetricsService, MqttTriggerService, NativeTriggerService, NatsTriggerService, NpmProxyService, OauthService, OidcService, OpenAPI, OpenapiService, PathAutocompleteService, PostgresTriggerService, RawAppService, ResourceService, ScheduleService, ScriptService, ServiceLogsService, SettingService, SettingsService, SqsTriggerService, StepSuspend, TeamsService, TokenService, TriggerService, UserService, VariableService, VolumeService, WebsocketTriggerService, WorkerService, WorkflowCtx, WorkspaceDependenciesService, WorkspaceIntegrationService, WorkspaceService, _workflowCtx, appendPartition, appendToResultStream, commitKafkaOffsets, datatable, src_default as default, deleteS3File, denoS3LightClientSettings, ducklake, getFlowUserState, getIdToken, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResumeUrls, getRootJobId, getState, getVariable, loadS3File, loadS3FileStream, parallel, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, runFlow, runFlowAsync, runScript, runScriptAsync, runScriptByHash, runScriptByHashAsync, runScriptByPath, runScriptByPathAsync, setClient, setFlowUserState, setProgress, setResource, setState, setVariable, setWorkflowCtx, signS3Object, signS3Objects, sleep, step, streamResult, task, taskFlow, taskScript, upsertPartition, usernameToEmail, waitForApproval, waitJob, workflow, writeS3File };
97
+ export { AdminService, AgentWorkersService, AmqpTriggerService, ApiError, AppService, AssetService, AuditService, AzureTriggerService, CancelError, CancelablePromise, CaptureService, ConcurrencyGroupsService, ConfigService, DataMetricService, DocumentationService, DraftService, EmailTriggerService, FavoriteService, FlowConversationsService, FlowService, FolderService, GcpTriggerService, GitSyncService, GranularAclService, GroupService, HealthService, HelpersService, HttpTriggerService, HubPublishService, IndexSearchService, InputService, IntegrationService, JobService, KafkaTriggerService, McpOauthService, McpService, MetricsService, MqttTriggerService, NativeTriggerService, NatsTriggerService, NpmProxyService, OauthService, OidcService, OpenAPI, OpenapiService, PathAutocompleteService, PostgresTriggerService, RawAppService, ResourceService, ScheduleService, ScriptService, ServiceLogsService, SettingService, SettingsService, SqsTriggerService, StepSuspend, TeamsService, TokenService, TriggerService, UserService, VariableService, VolumeService, WebsocketTriggerService, WorkerService, WorkflowCtx, WorkspaceDependenciesService, WorkspaceIntegrationService, WorkspaceService, _workflowCtx, appendPartition, appendToResultStream, commitKafkaOffsets, datatable, src_default as default, deleteS3File, denoS3LightClientSettings, ducklake, getApprovalUrls, getFlowUserState, getIdToken, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResumeUrls, getRootJobId, getState, getVariable, loadS3File, loadS3FileStream, parallel, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, runFlow, runFlowAsync, runScript, runScriptAsync, runScriptByHash, runScriptByHashAsync, runScriptByPath, runScriptByPathAsync, setClient, setFlowUserState, setProgress, setResource, setState, setVariable, setWorkflowCtx, signS3Object, signS3Objects, sleep, step, streamResult, task, taskFlow, taskScript, upsertPartition, usernameToEmail, waitForApproval, waitJob, workflow, writeS3File };