windmill-client 1.651.1 → 1.653.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.d.ts CHANGED
@@ -87,12 +87,6 @@ export declare function getResult(jobId: string): Promise<any>;
87
87
  * @returns Object with started, completed, success, and result properties
88
88
  */
89
89
  export declare function getResultMaybe(jobId: string): Promise<any>;
90
- /**
91
- * Wrap a function to execute as a Windmill task within a flow context
92
- * @param f - Function to wrap as a task
93
- * @returns Async wrapper function that executes as a Windmill job
94
- */
95
- export declare function task<P, T>(f: (_: P) => T): (_: P) => Promise<T>;
96
90
  /**
97
91
  * @deprecated Use runScriptByPathAsync or runScriptByHashAsync instead
98
92
  */
@@ -417,3 +411,119 @@ export declare function requestInteractiveTeamsApproval({ teamName, channelName,
417
411
  * @returns S3 object record with storage and s3 key
418
412
  */
419
413
  export declare function parseS3Object(s3Object: S3Object): S3ObjectRecord;
414
+ export declare class StepSuspend extends Error {
415
+ dispatchInfo: Record<string, any>;
416
+ constructor(dispatchInfo: Record<string, any>);
417
+ }
418
+ export interface TaskOptions {
419
+ timeout?: number;
420
+ tag?: string;
421
+ cache_ttl?: number;
422
+ priority?: number;
423
+ concurrency_limit?: number;
424
+ concurrency_key?: string;
425
+ concurrency_time_window_s?: number;
426
+ }
427
+ export declare let _workflowCtx: WorkflowCtx | null;
428
+ export declare function setWorkflowCtx(ctx: WorkflowCtx | null): void;
429
+ export declare class WorkflowCtx {
430
+ private completed;
431
+ private counters;
432
+ private pending;
433
+ private _suspended;
434
+ /** When set, the task matching this key executes its inner function directly */
435
+ _executingKey: string | null;
436
+ constructor(checkpoint?: Record<string, any>);
437
+ /** Name-based key: `double` for first call, `double_2`, `double_3` for subsequent. */
438
+ _allocKey(name: string): string;
439
+ _nextStep(name: string, script: string, args?: Record<string, any>, dispatch_type?: string, options?: TaskOptions): PromiseLike<any>;
440
+ /** Return and clear any pending (unawaited) steps. */
441
+ _flushPending(): Array<{
442
+ name: string;
443
+ script: string;
444
+ args: Record<string, any>;
445
+ key: string;
446
+ dispatch_type: string;
447
+ }>;
448
+ _waitForApproval(options?: {
449
+ timeout?: number;
450
+ form?: object;
451
+ }): PromiseLike<{
452
+ value: any;
453
+ approver: string;
454
+ approved: boolean;
455
+ }>;
456
+ _sleep(seconds: number): PromiseLike<void>;
457
+ _runInlineStep<T>(name: string, fn: () => T | Promise<T>): Promise<T>;
458
+ }
459
+ export declare function sleep(seconds: number): Promise<void>;
460
+ export declare function step<T>(name: string, fn: () => T | Promise<T>): Promise<T>;
461
+ /**
462
+ * Wrap an async function as a workflow task.
463
+ *
464
+ * @example
465
+ * const extract_data = task(async (url: string) => { ... });
466
+ * const run_external = task("f/external_script", async (x: number) => { ... });
467
+ *
468
+ * Inside a `workflow()`, calling a task dispatches it as a step.
469
+ * Outside a workflow, the function body executes directly.
470
+ */
471
+ export declare function task<T extends (...args: any[]) => Promise<any>>(fnOrPath: T | string, maybeFnOrOptions?: T | TaskOptions, maybeOptions?: TaskOptions): T;
472
+ /**
473
+ * Create a task that dispatches to a separate Windmill script.
474
+ *
475
+ * @example
476
+ * const extract = taskScript("f/data/extract");
477
+ * // inside workflow: await extract({ url: "https://..." })
478
+ */
479
+ export declare function taskScript(path: string, options?: TaskOptions): (...args: any[]) => PromiseLike<any>;
480
+ /**
481
+ * Create a task that dispatches to a separate Windmill flow.
482
+ *
483
+ * @example
484
+ * const pipeline = taskFlow("f/etl/pipeline");
485
+ * // inside workflow: await pipeline({ input: data })
486
+ */
487
+ export declare function taskFlow(path: string, options?: TaskOptions): (...args: any[]) => PromiseLike<any>;
488
+ /**
489
+ * Mark an async function as a workflow-as-code entry point.
490
+ *
491
+ * The function must be **deterministic**: given the same inputs it must call
492
+ * tasks in the same order on every replay. Branching on task results is fine
493
+ * (results are replayed from checkpoint), but branching on external state
494
+ * (current time, random values, external API calls) must use `step()` to
495
+ * checkpoint the value so replays see the same result.
496
+ */
497
+ export declare function workflow<T>(fn: (...args: any[]) => Promise<T>): (...args: any[]) => Promise<T>;
498
+ /**
499
+ * Suspend the workflow and wait for an external approval.
500
+ *
501
+ * Use `getResumeUrls()` (wrapped in `step()`) to obtain resume/cancel/approvalPage
502
+ * URLs before calling this function.
503
+ *
504
+ * @example
505
+ * const urls = await step("urls", () => getResumeUrls());
506
+ * await step("notify", () => sendEmail(urls.approvalPage));
507
+ * const { value, approver } = await waitForApproval({ timeout: 3600 });
508
+ */
509
+ export declare function waitForApproval(options?: {
510
+ timeout?: number;
511
+ form?: object;
512
+ }): PromiseLike<{
513
+ value: any;
514
+ approver: string;
515
+ approved: boolean;
516
+ }>;
517
+ /**
518
+ * Process items in parallel with optional concurrency control.
519
+ *
520
+ * Each item is processed by calling `fn(item)`, which should be a task().
521
+ * Items are dispatched in batches of `concurrency` (default: all at once).
522
+ *
523
+ * @example
524
+ * const process = task(async (item: string) => { ... });
525
+ * const results = await parallel(items, process, { concurrency: 5 });
526
+ */
527
+ export declare function parallel<T, R>(items: T[], fn: (item: T) => PromiseLike<R> | R, options?: {
528
+ concurrency?: number;
529
+ }): Promise<R[]>;
package/dist/client.mjs CHANGED
@@ -181,37 +181,35 @@ async function getResultMaybe(jobId) {
181
181
  });
182
182
  }
183
183
  const STRIP_COMMENTS = /(\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s*=[^,\)]*(('(?:\\'|[^'\r\n])*')|("(?:\\"|[^"\r\n])*"))|(\s*=[^,\)]*))/gm;
184
- const ARGUMENT_NAMES = /([^\s,]+)/g;
185
184
  function getParamNames(func) {
186
185
  const fnStr = func.toString().replace(STRIP_COMMENTS, "");
187
- let result = fnStr.slice(fnStr.indexOf("(") + 1, fnStr.indexOf(")")).match(ARGUMENT_NAMES);
188
- if (result === null) result = [];
189
- return result;
190
- }
191
- /**
192
- * Wrap a function to execute as a Windmill task within a flow context
193
- * @param f - Function to wrap as a task
194
- * @returns Async wrapper function that executes as a Windmill job
195
- */
196
- function task(f) {
197
- return async (...y) => {
198
- const args = {};
199
- const paramNames = getParamNames(f);
200
- y.forEach((x, i) => args[paramNames[i]] = x);
201
- let req = await fetch(`${OpenAPI.BASE}/w/${getWorkspace()}/jobs/run/workflow_as_code/${getEnv("WM_JOB_ID")}/${f.name}`, {
202
- method: "POST",
203
- headers: {
204
- "Content-Type": "application/json",
205
- Authorization: `Bearer ${getEnv("WM_TOKEN")}`
206
- },
207
- body: JSON.stringify({ args })
208
- });
209
- let jobId = await req.text();
210
- console.log(`Started task ${f.name} as job ${jobId}`);
211
- let r = await waitJob(jobId);
212
- console.log(`Task ${f.name} (${jobId}) completed`);
213
- return r;
214
- };
186
+ const openIdx = fnStr.indexOf("(");
187
+ if (openIdx === -1) return [];
188
+ let depth = 1;
189
+ let closeIdx = openIdx + 1;
190
+ for (; closeIdx < fnStr.length && depth > 0; closeIdx++) if (fnStr[closeIdx] === "(") depth++;
191
+ else if (fnStr[closeIdx] === ")") depth--;
192
+ const paramStr = fnStr.slice(openIdx + 1, closeIdx - 1).trim();
193
+ if (!paramStr) return [];
194
+ const params = [];
195
+ let current = "";
196
+ let d = 0;
197
+ for (const ch of paramStr) {
198
+ if ("(<{".includes(ch)) d++;
199
+ else if (")>}".includes(ch)) d--;
200
+ if (ch === "," && d === 0) {
201
+ params.push(current.trim());
202
+ current = "";
203
+ } else current += ch;
204
+ }
205
+ if (current.trim()) params.push(current.trim());
206
+ return params.map((p) => {
207
+ p = p.replace(/^\.\.\./, "");
208
+ if (p.startsWith("{") || p.startsWith("[")) return "";
209
+ const colonIdx = p.indexOf(":");
210
+ if (colonIdx !== -1) p = p.slice(0, colonIdx);
211
+ return p.replace(/\?$/, "").trim();
212
+ }).filter(Boolean);
215
213
  }
216
214
  /**
217
215
  * @deprecated Use runScriptByPathAsync or runScriptByHashAsync instead
@@ -928,6 +926,315 @@ function parseS3Object(s3Object) {
928
926
  function parseVariableSyntax(s) {
929
927
  if (s.startsWith("var://")) return s.substring(6);
930
928
  }
929
+ var StepSuspend = class extends Error {
930
+ constructor(dispatchInfo) {
931
+ super("__step_suspend__");
932
+ this.dispatchInfo = dispatchInfo;
933
+ this.name = "StepSuspend";
934
+ }
935
+ };
936
+ let _workflowCtx = null;
937
+ function setWorkflowCtx(ctx) {
938
+ _workflowCtx = ctx;
939
+ Reflect.set(globalThis, "__wmill_wf_ctx", ctx);
940
+ }
941
+ var WorkflowCtx = class {
942
+ completed;
943
+ counters = {};
944
+ pending = [];
945
+ _suspended = false;
946
+ /** When set, the task matching this key executes its inner function directly */
947
+ _executingKey;
948
+ constructor(checkpoint = {}) {
949
+ this.completed = checkpoint?.completed_steps ?? {};
950
+ this._executingKey = checkpoint?._executing_key ?? null;
951
+ }
952
+ /** Name-based key: `double` for first call, `double_2`, `double_3` for subsequent. */
953
+ _allocKey(name) {
954
+ const n = (this.counters[name] ?? 0) + 1;
955
+ this.counters[name] = n;
956
+ return n === 1 ? name : `${name}_${n}`;
957
+ }
958
+ _nextStep(name, script, args = {}, dispatch_type = "inline", options) {
959
+ const key = this._allocKey(name || script || "step");
960
+ if (key in this.completed) {
961
+ const value = this.completed[key];
962
+ if (value && typeof value === "object" && value.__wmill_error) {
963
+ const err = new Error(value.message || `Task '${name}' failed`);
964
+ err.result = value.result;
965
+ err.step_key = value.step_key;
966
+ err.child_job_id = value.child_job_id;
967
+ return { then: (_resolve, reject) => {
968
+ if (reject) reject(err);
969
+ else throw err;
970
+ } };
971
+ }
972
+ return { then: (resolve) => resolve(value) };
973
+ }
974
+ if (this._executingKey === key) return {
975
+ then: (resolve) => resolve(null),
976
+ _execute_directly: true
977
+ };
978
+ if (this._executingKey !== null) return { then: () => new Promise(() => {}) };
979
+ const stepInfo = {
980
+ name: name || key,
981
+ script: script || key,
982
+ args,
983
+ key,
984
+ dispatch_type
985
+ };
986
+ if (options) {
987
+ if (options.timeout !== void 0) stepInfo.timeout = options.timeout;
988
+ if (options.tag !== void 0) stepInfo.tag = options.tag;
989
+ if (options.cache_ttl !== void 0) stepInfo.cache_ttl = options.cache_ttl;
990
+ if (options.priority !== void 0) stepInfo.priority = options.priority;
991
+ if (options.concurrency_limit !== void 0) stepInfo.concurrent_limit = options.concurrency_limit;
992
+ if (options.concurrency_key !== void 0) stepInfo.concurrency_key = options.concurrency_key;
993
+ if (options.concurrency_time_window_s !== void 0) stepInfo.concurrency_time_window_s = options.concurrency_time_window_s;
994
+ }
995
+ this.pending.push(stepInfo);
996
+ return { then: () => {
997
+ if (this._suspended) return new Promise(() => {});
998
+ this._suspended = true;
999
+ const steps = [...this.pending];
1000
+ this.pending = [];
1001
+ throw new StepSuspend({
1002
+ mode: steps.length > 1 ? "parallel" : "sequential",
1003
+ steps
1004
+ });
1005
+ } };
1006
+ }
1007
+ /** Return and clear any pending (unawaited) steps. */
1008
+ _flushPending() {
1009
+ const steps = [...this.pending];
1010
+ this.pending = [];
1011
+ return steps;
1012
+ }
1013
+ _waitForApproval(options) {
1014
+ const key = this._allocKey("approval");
1015
+ if (key in this.completed) {
1016
+ const value = this.completed[key];
1017
+ return { then: (resolve) => resolve(value) };
1018
+ }
1019
+ if (this._executingKey !== null) return { then: () => new Promise(() => {}) };
1020
+ throw new StepSuspend({
1021
+ mode: "approval",
1022
+ key,
1023
+ timeout: options?.timeout ?? 1800,
1024
+ form: options?.form,
1025
+ steps: []
1026
+ });
1027
+ }
1028
+ _sleep(seconds) {
1029
+ const key = this._allocKey("sleep");
1030
+ if (key in this.completed) return { then: (resolve) => resolve(void 0) };
1031
+ if (this._executingKey !== null) return { then: () => new Promise(() => {}) };
1032
+ throw new StepSuspend({
1033
+ mode: "sleep",
1034
+ key,
1035
+ seconds: Math.max(1, Math.round(seconds)),
1036
+ steps: []
1037
+ });
1038
+ }
1039
+ async _runInlineStep(name, fn) {
1040
+ const key = this._allocKey(name || "step");
1041
+ if (key in this.completed) {
1042
+ const value = this.completed[key];
1043
+ if (value && typeof value === "object" && value.__wmill_error) {
1044
+ const err = new Error(value.message || `Step '${name}' failed`);
1045
+ err.result = value.result;
1046
+ err.step_key = value.step_key;
1047
+ err.child_job_id = value.child_job_id;
1048
+ throw err;
1049
+ }
1050
+ return value;
1051
+ }
1052
+ if (this._executingKey !== null) return new Promise(() => {});
1053
+ const result = await fn();
1054
+ throw new StepSuspend({
1055
+ mode: "inline_checkpoint",
1056
+ steps: [],
1057
+ key,
1058
+ result
1059
+ });
1060
+ }
1061
+ };
1062
+ async function sleep(seconds) {
1063
+ const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
1064
+ if (ctx) return ctx._sleep(seconds);
1065
+ await new Promise((r) => setTimeout(r, seconds * 1e3));
1066
+ }
1067
+ async function step(name, fn) {
1068
+ const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
1069
+ if (ctx) return ctx._runInlineStep(name, fn);
1070
+ return fn();
1071
+ }
1072
+ /**
1073
+ * Wrap an async function as a workflow task.
1074
+ *
1075
+ * @example
1076
+ * const extract_data = task(async (url: string) => { ... });
1077
+ * const run_external = task("f/external_script", async (x: number) => { ... });
1078
+ *
1079
+ * Inside a `workflow()`, calling a task dispatches it as a step.
1080
+ * Outside a workflow, the function body executes directly.
1081
+ */
1082
+ function task(fnOrPath, maybeFnOrOptions, maybeOptions) {
1083
+ let fn;
1084
+ let taskPath;
1085
+ let taskOptions;
1086
+ if (typeof fnOrPath === "string") {
1087
+ taskPath = fnOrPath;
1088
+ fn = maybeFnOrOptions;
1089
+ taskOptions = maybeOptions;
1090
+ } else {
1091
+ fn = fnOrPath;
1092
+ taskOptions = maybeFnOrOptions;
1093
+ }
1094
+ const taskName = fn.name || taskPath || "";
1095
+ const wrapper = function(...args) {
1096
+ const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
1097
+ if (ctx) {
1098
+ const script = taskPath ?? taskName;
1099
+ const paramNames = getParamNames(fn);
1100
+ const kwargs = {};
1101
+ for (let i = 0; i < args.length; i++) if (paramNames[i]) kwargs[paramNames[i]] = args[i];
1102
+ else kwargs[`arg${i}`] = args[i];
1103
+ const stepResult = ctx._nextStep(taskName, script, kwargs, "inline", taskOptions);
1104
+ if (stepResult?._execute_directly) return (async () => {
1105
+ const result = await fn(...args);
1106
+ throw new StepSuspend({
1107
+ mode: "step_complete",
1108
+ steps: [],
1109
+ result
1110
+ });
1111
+ })();
1112
+ return stepResult;
1113
+ } else if (getEnv("WM_JOB_ID") && !getEnv("WM_FLOW_JOB_ID")) return (async () => {
1114
+ const paramNames = getParamNames(fn);
1115
+ const kwargs = {};
1116
+ args.forEach((x, i) => kwargs[paramNames[i]] = x);
1117
+ let req = await fetch(`${OpenAPI.BASE}/w/${getWorkspace()}/jobs/run/workflow_as_code/${getEnv("WM_JOB_ID")}/${taskName}`, {
1118
+ method: "POST",
1119
+ headers: {
1120
+ "Content-Type": "application/json",
1121
+ Authorization: `Bearer ${getEnv("WM_TOKEN")}`
1122
+ },
1123
+ body: JSON.stringify({ args: kwargs })
1124
+ });
1125
+ let jobId = await req.text();
1126
+ console.log(`Started task ${taskName} as job ${jobId}`);
1127
+ let r = await waitJob(jobId);
1128
+ console.log(`Task ${taskName} (${jobId}) completed`);
1129
+ return r;
1130
+ })();
1131
+ else return fn(...args);
1132
+ };
1133
+ Object.defineProperty(wrapper, "name", { value: taskName });
1134
+ wrapper._is_task = true;
1135
+ wrapper._task_path = taskPath;
1136
+ return wrapper;
1137
+ }
1138
+ /**
1139
+ * Create a task that dispatches to a separate Windmill script.
1140
+ *
1141
+ * @example
1142
+ * const extract = taskScript("f/data/extract");
1143
+ * // inside workflow: await extract({ url: "https://..." })
1144
+ */
1145
+ function taskScript(path, options) {
1146
+ const name = path.split("/").pop() || path;
1147
+ const wrapper = function(...args) {
1148
+ const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
1149
+ if (ctx) {
1150
+ const kwargs = args.length === 1 && typeof args[0] === "object" && args[0] !== null ? args[0] : args.reduce((acc, v, i) => {
1151
+ acc[`arg${i}`] = v;
1152
+ return acc;
1153
+ }, {});
1154
+ return ctx._nextStep(name, path, kwargs, "script", options);
1155
+ }
1156
+ throw new Error(`taskScript("${path}") can only be called inside a workflow()`);
1157
+ };
1158
+ Object.defineProperty(wrapper, "name", { value: name });
1159
+ wrapper._is_task = true;
1160
+ wrapper._task_path = path;
1161
+ return wrapper;
1162
+ }
1163
+ /**
1164
+ * Create a task that dispatches to a separate Windmill flow.
1165
+ *
1166
+ * @example
1167
+ * const pipeline = taskFlow("f/etl/pipeline");
1168
+ * // inside workflow: await pipeline({ input: data })
1169
+ */
1170
+ function taskFlow(path, options) {
1171
+ const name = path.split("/").pop() || path;
1172
+ const wrapper = function(...args) {
1173
+ const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
1174
+ if (ctx) {
1175
+ const kwargs = args.length === 1 && typeof args[0] === "object" && args[0] !== null ? args[0] : args.reduce((acc, v, i) => {
1176
+ acc[`arg${i}`] = v;
1177
+ return acc;
1178
+ }, {});
1179
+ return ctx._nextStep(name, path, kwargs, "flow", options);
1180
+ }
1181
+ throw new Error(`taskFlow("${path}") can only be called inside a workflow()`);
1182
+ };
1183
+ Object.defineProperty(wrapper, "name", { value: name });
1184
+ wrapper._is_task = true;
1185
+ wrapper._task_path = path;
1186
+ return wrapper;
1187
+ }
1188
+ /**
1189
+ * Mark an async function as a workflow-as-code entry point.
1190
+ *
1191
+ * The function must be **deterministic**: given the same inputs it must call
1192
+ * tasks in the same order on every replay. Branching on task results is fine
1193
+ * (results are replayed from checkpoint), but branching on external state
1194
+ * (current time, random values, external API calls) must use `step()` to
1195
+ * checkpoint the value so replays see the same result.
1196
+ */
1197
+ function workflow(fn) {
1198
+ fn._is_workflow = true;
1199
+ return fn;
1200
+ }
1201
+ /**
1202
+ * Suspend the workflow and wait for an external approval.
1203
+ *
1204
+ * Use `getResumeUrls()` (wrapped in `step()`) to obtain resume/cancel/approvalPage
1205
+ * URLs before calling this function.
1206
+ *
1207
+ * @example
1208
+ * const urls = await step("urls", () => getResumeUrls());
1209
+ * await step("notify", () => sendEmail(urls.approvalPage));
1210
+ * const { value, approver } = await waitForApproval({ timeout: 3600 });
1211
+ */
1212
+ function waitForApproval(options) {
1213
+ const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
1214
+ if (!ctx) throw new Error("waitForApproval can only be called inside a workflow()");
1215
+ return ctx._waitForApproval(options);
1216
+ }
1217
+ /**
1218
+ * Process items in parallel with optional concurrency control.
1219
+ *
1220
+ * Each item is processed by calling `fn(item)`, which should be a task().
1221
+ * Items are dispatched in batches of `concurrency` (default: all at once).
1222
+ *
1223
+ * @example
1224
+ * const process = task(async (item: string) => { ... });
1225
+ * const results = await parallel(items, process, { concurrency: 5 });
1226
+ */
1227
+ async function parallel(items, fn, options) {
1228
+ const concurrency = options?.concurrency ?? items.length;
1229
+ if (concurrency <= 0 || items.length === 0) return [];
1230
+ const results = [];
1231
+ for (let i = 0; i < items.length; i += concurrency) {
1232
+ const batch = items.slice(i, i + concurrency);
1233
+ const batchResults = await Promise.all(batch.map((item) => fn(item)));
1234
+ results.push(...batchResults);
1235
+ }
1236
+ return results;
1237
+ }
931
1238
 
932
1239
  //#endregion
933
- export { SHARED_FOLDER, appendToResultStream, base64ToUint8Array, databaseUrlFromResource, denoS3LightClientSettings, getFlowUserState, getIdToken, getInternalState, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResult, getResultMaybe, getResumeEndpoints, getResumeUrls, getRootJobId, getState, getStatePath, getVariable, getWorkspace, loadS3File, loadS3FileStream, parseS3Object, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, resolveDefaultResource, runFlow, runFlowAsync, runScript, runScriptAsync, runScriptByHash, runScriptByHashAsync, runScriptByPath, runScriptByPathAsync, setClient, setFlowUserState, setInternalState, setProgress, setResource, setState, setVariable, signS3Object, signS3Objects, streamResult, task, uint8ArrayToBase64, usernameToEmail, waitJob, writeS3File };
1240
+ export { SHARED_FOLDER, StepSuspend, WorkflowCtx, _workflowCtx, appendToResultStream, base64ToUint8Array, databaseUrlFromResource, denoS3LightClientSettings, getFlowUserState, getIdToken, getInternalState, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResult, getResultMaybe, getResumeEndpoints, getResumeUrls, getRootJobId, getState, getStatePath, getVariable, getWorkspace, loadS3File, loadS3FileStream, parallel, parseS3Object, 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 };
@@ -29,7 +29,7 @@ const OpenAPI = {
29
29
  PASSWORD: void 0,
30
30
  TOKEN: getEnv("WM_TOKEN"),
31
31
  USERNAME: void 0,
32
- VERSION: "1.651.1",
32
+ VERSION: "1.653.0",
33
33
  WITH_CREDENTIALS: true,
34
34
  interceptors: {
35
35
  request: new Interceptors(),
package/dist/index.d.ts CHANGED
@@ -4,8 +4,8 @@ export { OpenAPI, type OpenAPIConfig } from './core/OpenAPI';
4
4
  export * from './services.gen';
5
5
  export * from './types.gen';
6
6
  export type { DenoS3LightClientSettings } from "./s3Types";
7
- export { type Base64, setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, signS3Objects, signS3Object, getPresignedS3PublicUrls, getPresignedS3PublicUrl, task, runScript, runScriptAsync, runScriptByPath, runScriptByHash, runScriptByPathAsync, runScriptByHashAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, type Sql, requestInteractiveTeamsApproval, appendToResultStream, streamResult, datatable, ducklake, type DatatableSqlTemplateFunction, type SqlTemplateFunction, type S3Object, type S3ObjectRecord, type S3ObjectURI } from "./client";
8
- import { setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, signS3Objects, signS3Object, getPresignedS3PublicUrls, getPresignedS3PublicUrl, task, runScript, runScriptAsync, runScriptByPath, runScriptByHash, runScriptByPathAsync, runScriptByHashAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, appendToResultStream, streamResult, datatable, ducklake, getWorkspace, getStatePath, getInternalState, setInternalState, getResumeEndpoints, getResult, getResultMaybe, resolveDefaultResource, databaseUrlFromResource, base64ToUint8Array, uint8ArrayToBase64, parseS3Object } from "./client";
7
+ export { type Base64, setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, signS3Objects, signS3Object, getPresignedS3PublicUrls, getPresignedS3PublicUrl, task, taskScript, taskFlow, workflow, step, sleep, parallel, waitForApproval, type TaskOptions, WorkflowCtx, _workflowCtx, setWorkflowCtx, StepSuspend, runScript, runScriptAsync, runScriptByPath, runScriptByHash, runScriptByPathAsync, runScriptByHashAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, type Sql, requestInteractiveTeamsApproval, appendToResultStream, streamResult, datatable, ducklake, type DatatableSqlTemplateFunction, type SqlTemplateFunction, type S3Object, type S3ObjectRecord, type S3ObjectURI } from "./client";
8
+ import { setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, signS3Objects, signS3Object, getPresignedS3PublicUrls, getPresignedS3PublicUrl, task, taskScript, taskFlow, workflow, step, sleep, parallel, waitForApproval, WorkflowCtx, setWorkflowCtx, StepSuspend, runScript, runScriptAsync, runScriptByPath, runScriptByHash, runScriptByPathAsync, runScriptByHashAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, appendToResultStream, streamResult, datatable, ducklake, getWorkspace, getStatePath, getInternalState, setInternalState, getResumeEndpoints, getResult, getResultMaybe, resolveDefaultResource, databaseUrlFromResource, base64ToUint8Array, uint8ArrayToBase64, parseS3Object } from "./client";
9
9
  import { AdminService, AuditService, FlowService, GranularAclService, GroupService, JobService, ResourceService, VariableService, ScriptService, ScheduleService, SettingsService, UserService, WorkspaceService, TeamsService } from "./services.gen";
10
10
  declare const wmill: {
11
11
  setClient: typeof setClient;
@@ -28,6 +28,17 @@ declare const wmill: {
28
28
  getPresignedS3PublicUrls: typeof getPresignedS3PublicUrls;
29
29
  getPresignedS3PublicUrl: typeof getPresignedS3PublicUrl;
30
30
  task: typeof task;
31
+ taskScript: typeof taskScript;
32
+ taskFlow: typeof taskFlow;
33
+ workflow: typeof workflow;
34
+ step: typeof step;
35
+ sleep: typeof sleep;
36
+ parallel: typeof parallel;
37
+ waitForApproval: typeof waitForApproval;
38
+ WorkflowCtx: typeof WorkflowCtx;
39
+ _workflowCtx: WorkflowCtx | null;
40
+ setWorkflowCtx: typeof setWorkflowCtx;
41
+ StepSuspend: typeof StepSuspend;
31
42
  runScript: typeof runScript;
32
43
  runScriptAsync: typeof runScriptAsync;
33
44
  runScriptByPath: typeof runScriptByPath;
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.651.1",
129
+ VERSION: "1.653.0",
130
130
  WITH_CREDENTIALS: true,
131
131
  interceptors: {
132
132
  request: new Interceptors(),
@@ -13261,37 +13261,35 @@ async function getResultMaybe(jobId) {
13261
13261
  });
13262
13262
  }
13263
13263
  const STRIP_COMMENTS = /(\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s*=[^,\)]*(('(?:\\'|[^'\r\n])*')|("(?:\\"|[^"\r\n])*"))|(\s*=[^,\)]*))/gm;
13264
- const ARGUMENT_NAMES = /([^\s,]+)/g;
13265
13264
  function getParamNames(func) {
13266
13265
  const fnStr = func.toString().replace(STRIP_COMMENTS, "");
13267
- let result = fnStr.slice(fnStr.indexOf("(") + 1, fnStr.indexOf(")")).match(ARGUMENT_NAMES);
13268
- if (result === null) result = [];
13269
- return result;
13270
- }
13271
- /**
13272
- * Wrap a function to execute as a Windmill task within a flow context
13273
- * @param f - Function to wrap as a task
13274
- * @returns Async wrapper function that executes as a Windmill job
13275
- */
13276
- function task(f) {
13277
- return async (...y) => {
13278
- const args = {};
13279
- const paramNames = getParamNames(f);
13280
- y.forEach((x, i) => args[paramNames[i]] = x);
13281
- let req = await fetch(`${OpenAPI.BASE}/w/${getWorkspace()}/jobs/run/workflow_as_code/${getEnv("WM_JOB_ID")}/${f.name}`, {
13282
- method: "POST",
13283
- headers: {
13284
- "Content-Type": "application/json",
13285
- Authorization: `Bearer ${getEnv("WM_TOKEN")}`
13286
- },
13287
- body: JSON.stringify({ args })
13288
- });
13289
- let jobId = await req.text();
13290
- console.log(`Started task ${f.name} as job ${jobId}`);
13291
- let r = await waitJob(jobId);
13292
- console.log(`Task ${f.name} (${jobId}) completed`);
13293
- return r;
13294
- };
13266
+ const openIdx = fnStr.indexOf("(");
13267
+ if (openIdx === -1) return [];
13268
+ let depth = 1;
13269
+ let closeIdx = openIdx + 1;
13270
+ for (; closeIdx < fnStr.length && depth > 0; closeIdx++) if (fnStr[closeIdx] === "(") depth++;
13271
+ else if (fnStr[closeIdx] === ")") depth--;
13272
+ const paramStr = fnStr.slice(openIdx + 1, closeIdx - 1).trim();
13273
+ if (!paramStr) return [];
13274
+ const params = [];
13275
+ let current = "";
13276
+ let d = 0;
13277
+ for (const ch of paramStr) {
13278
+ if ("(<{".includes(ch)) d++;
13279
+ else if (")>}".includes(ch)) d--;
13280
+ if (ch === "," && d === 0) {
13281
+ params.push(current.trim());
13282
+ current = "";
13283
+ } else current += ch;
13284
+ }
13285
+ if (current.trim()) params.push(current.trim());
13286
+ return params.map((p) => {
13287
+ p = p.replace(/^\.\.\./, "");
13288
+ if (p.startsWith("{") || p.startsWith("[")) return "";
13289
+ const colonIdx = p.indexOf(":");
13290
+ if (colonIdx !== -1) p = p.slice(0, colonIdx);
13291
+ return p.replace(/\?$/, "").trim();
13292
+ }).filter(Boolean);
13295
13293
  }
13296
13294
  /**
13297
13295
  * @deprecated Use runScriptByPathAsync or runScriptByHashAsync instead
@@ -14008,6 +14006,315 @@ function parseS3Object(s3Object) {
14008
14006
  function parseVariableSyntax(s) {
14009
14007
  if (s.startsWith("var://")) return s.substring(6);
14010
14008
  }
14009
+ var StepSuspend = class extends Error {
14010
+ constructor(dispatchInfo) {
14011
+ super("__step_suspend__");
14012
+ this.dispatchInfo = dispatchInfo;
14013
+ this.name = "StepSuspend";
14014
+ }
14015
+ };
14016
+ let _workflowCtx = null;
14017
+ function setWorkflowCtx(ctx) {
14018
+ _workflowCtx = ctx;
14019
+ Reflect.set(globalThis, "__wmill_wf_ctx", ctx);
14020
+ }
14021
+ var WorkflowCtx = class {
14022
+ completed;
14023
+ counters = {};
14024
+ pending = [];
14025
+ _suspended = false;
14026
+ /** When set, the task matching this key executes its inner function directly */
14027
+ _executingKey;
14028
+ constructor(checkpoint = {}) {
14029
+ this.completed = checkpoint?.completed_steps ?? {};
14030
+ this._executingKey = checkpoint?._executing_key ?? null;
14031
+ }
14032
+ /** Name-based key: `double` for first call, `double_2`, `double_3` for subsequent. */
14033
+ _allocKey(name) {
14034
+ const n = (this.counters[name] ?? 0) + 1;
14035
+ this.counters[name] = n;
14036
+ return n === 1 ? name : `${name}_${n}`;
14037
+ }
14038
+ _nextStep(name, script, args = {}, dispatch_type = "inline", options) {
14039
+ const key = this._allocKey(name || script || "step");
14040
+ if (key in this.completed) {
14041
+ const value = this.completed[key];
14042
+ if (value && typeof value === "object" && value.__wmill_error) {
14043
+ const err = new Error(value.message || `Task '${name}' failed`);
14044
+ err.result = value.result;
14045
+ err.step_key = value.step_key;
14046
+ err.child_job_id = value.child_job_id;
14047
+ return { then: (_resolve, reject) => {
14048
+ if (reject) reject(err);
14049
+ else throw err;
14050
+ } };
14051
+ }
14052
+ return { then: (resolve$1) => resolve$1(value) };
14053
+ }
14054
+ if (this._executingKey === key) return {
14055
+ then: (resolve$1) => resolve$1(null),
14056
+ _execute_directly: true
14057
+ };
14058
+ if (this._executingKey !== null) return { then: () => new Promise(() => {}) };
14059
+ const stepInfo = {
14060
+ name: name || key,
14061
+ script: script || key,
14062
+ args,
14063
+ key,
14064
+ dispatch_type
14065
+ };
14066
+ if (options) {
14067
+ if (options.timeout !== void 0) stepInfo.timeout = options.timeout;
14068
+ if (options.tag !== void 0) stepInfo.tag = options.tag;
14069
+ if (options.cache_ttl !== void 0) stepInfo.cache_ttl = options.cache_ttl;
14070
+ if (options.priority !== void 0) stepInfo.priority = options.priority;
14071
+ if (options.concurrency_limit !== void 0) stepInfo.concurrent_limit = options.concurrency_limit;
14072
+ if (options.concurrency_key !== void 0) stepInfo.concurrency_key = options.concurrency_key;
14073
+ if (options.concurrency_time_window_s !== void 0) stepInfo.concurrency_time_window_s = options.concurrency_time_window_s;
14074
+ }
14075
+ this.pending.push(stepInfo);
14076
+ return { then: () => {
14077
+ if (this._suspended) return new Promise(() => {});
14078
+ this._suspended = true;
14079
+ const steps = [...this.pending];
14080
+ this.pending = [];
14081
+ throw new StepSuspend({
14082
+ mode: steps.length > 1 ? "parallel" : "sequential",
14083
+ steps
14084
+ });
14085
+ } };
14086
+ }
14087
+ /** Return and clear any pending (unawaited) steps. */
14088
+ _flushPending() {
14089
+ const steps = [...this.pending];
14090
+ this.pending = [];
14091
+ return steps;
14092
+ }
14093
+ _waitForApproval(options) {
14094
+ const key = this._allocKey("approval");
14095
+ if (key in this.completed) {
14096
+ const value = this.completed[key];
14097
+ return { then: (resolve$1) => resolve$1(value) };
14098
+ }
14099
+ if (this._executingKey !== null) return { then: () => new Promise(() => {}) };
14100
+ throw new StepSuspend({
14101
+ mode: "approval",
14102
+ key,
14103
+ timeout: options?.timeout ?? 1800,
14104
+ form: options?.form,
14105
+ steps: []
14106
+ });
14107
+ }
14108
+ _sleep(seconds) {
14109
+ const key = this._allocKey("sleep");
14110
+ if (key in this.completed) return { then: (resolve$1) => resolve$1(void 0) };
14111
+ if (this._executingKey !== null) return { then: () => new Promise(() => {}) };
14112
+ throw new StepSuspend({
14113
+ mode: "sleep",
14114
+ key,
14115
+ seconds: Math.max(1, Math.round(seconds)),
14116
+ steps: []
14117
+ });
14118
+ }
14119
+ async _runInlineStep(name, fn) {
14120
+ const key = this._allocKey(name || "step");
14121
+ if (key in this.completed) {
14122
+ const value = this.completed[key];
14123
+ if (value && typeof value === "object" && value.__wmill_error) {
14124
+ const err = new Error(value.message || `Step '${name}' failed`);
14125
+ err.result = value.result;
14126
+ err.step_key = value.step_key;
14127
+ err.child_job_id = value.child_job_id;
14128
+ throw err;
14129
+ }
14130
+ return value;
14131
+ }
14132
+ if (this._executingKey !== null) return new Promise(() => {});
14133
+ const result = await fn();
14134
+ throw new StepSuspend({
14135
+ mode: "inline_checkpoint",
14136
+ steps: [],
14137
+ key,
14138
+ result
14139
+ });
14140
+ }
14141
+ };
14142
+ async function sleep(seconds) {
14143
+ const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
14144
+ if (ctx) return ctx._sleep(seconds);
14145
+ await new Promise((r) => setTimeout(r, seconds * 1e3));
14146
+ }
14147
+ async function step(name, fn) {
14148
+ const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
14149
+ if (ctx) return ctx._runInlineStep(name, fn);
14150
+ return fn();
14151
+ }
14152
+ /**
14153
+ * Wrap an async function as a workflow task.
14154
+ *
14155
+ * @example
14156
+ * const extract_data = task(async (url: string) => { ... });
14157
+ * const run_external = task("f/external_script", async (x: number) => { ... });
14158
+ *
14159
+ * Inside a `workflow()`, calling a task dispatches it as a step.
14160
+ * Outside a workflow, the function body executes directly.
14161
+ */
14162
+ function task(fnOrPath, maybeFnOrOptions, maybeOptions) {
14163
+ let fn;
14164
+ let taskPath;
14165
+ let taskOptions;
14166
+ if (typeof fnOrPath === "string") {
14167
+ taskPath = fnOrPath;
14168
+ fn = maybeFnOrOptions;
14169
+ taskOptions = maybeOptions;
14170
+ } else {
14171
+ fn = fnOrPath;
14172
+ taskOptions = maybeFnOrOptions;
14173
+ }
14174
+ const taskName = fn.name || taskPath || "";
14175
+ const wrapper = function(...args) {
14176
+ const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
14177
+ if (ctx) {
14178
+ const script = taskPath ?? taskName;
14179
+ const paramNames = getParamNames(fn);
14180
+ const kwargs = {};
14181
+ for (let i = 0; i < args.length; i++) if (paramNames[i]) kwargs[paramNames[i]] = args[i];
14182
+ else kwargs[`arg${i}`] = args[i];
14183
+ const stepResult = ctx._nextStep(taskName, script, kwargs, "inline", taskOptions);
14184
+ if (stepResult?._execute_directly) return (async () => {
14185
+ const result = await fn(...args);
14186
+ throw new StepSuspend({
14187
+ mode: "step_complete",
14188
+ steps: [],
14189
+ result
14190
+ });
14191
+ })();
14192
+ return stepResult;
14193
+ } else if (getEnv("WM_JOB_ID") && !getEnv("WM_FLOW_JOB_ID")) return (async () => {
14194
+ const paramNames = getParamNames(fn);
14195
+ const kwargs = {};
14196
+ args.forEach((x, i) => kwargs[paramNames[i]] = x);
14197
+ let req = await fetch(`${OpenAPI.BASE}/w/${getWorkspace()}/jobs/run/workflow_as_code/${getEnv("WM_JOB_ID")}/${taskName}`, {
14198
+ method: "POST",
14199
+ headers: {
14200
+ "Content-Type": "application/json",
14201
+ Authorization: `Bearer ${getEnv("WM_TOKEN")}`
14202
+ },
14203
+ body: JSON.stringify({ args: kwargs })
14204
+ });
14205
+ let jobId = await req.text();
14206
+ console.log(`Started task ${taskName} as job ${jobId}`);
14207
+ let r = await waitJob(jobId);
14208
+ console.log(`Task ${taskName} (${jobId}) completed`);
14209
+ return r;
14210
+ })();
14211
+ else return fn(...args);
14212
+ };
14213
+ Object.defineProperty(wrapper, "name", { value: taskName });
14214
+ wrapper._is_task = true;
14215
+ wrapper._task_path = taskPath;
14216
+ return wrapper;
14217
+ }
14218
+ /**
14219
+ * Create a task that dispatches to a separate Windmill script.
14220
+ *
14221
+ * @example
14222
+ * const extract = taskScript("f/data/extract");
14223
+ * // inside workflow: await extract({ url: "https://..." })
14224
+ */
14225
+ function taskScript(path, options) {
14226
+ const name = path.split("/").pop() || path;
14227
+ const wrapper = function(...args) {
14228
+ const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
14229
+ if (ctx) {
14230
+ const kwargs = args.length === 1 && typeof args[0] === "object" && args[0] !== null ? args[0] : args.reduce((acc, v, i) => {
14231
+ acc[`arg${i}`] = v;
14232
+ return acc;
14233
+ }, {});
14234
+ return ctx._nextStep(name, path, kwargs, "script", options);
14235
+ }
14236
+ throw new Error(`taskScript("${path}") can only be called inside a workflow()`);
14237
+ };
14238
+ Object.defineProperty(wrapper, "name", { value: name });
14239
+ wrapper._is_task = true;
14240
+ wrapper._task_path = path;
14241
+ return wrapper;
14242
+ }
14243
+ /**
14244
+ * Create a task that dispatches to a separate Windmill flow.
14245
+ *
14246
+ * @example
14247
+ * const pipeline = taskFlow("f/etl/pipeline");
14248
+ * // inside workflow: await pipeline({ input: data })
14249
+ */
14250
+ function taskFlow(path, options) {
14251
+ const name = path.split("/").pop() || path;
14252
+ const wrapper = function(...args) {
14253
+ const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
14254
+ if (ctx) {
14255
+ const kwargs = args.length === 1 && typeof args[0] === "object" && args[0] !== null ? args[0] : args.reduce((acc, v, i) => {
14256
+ acc[`arg${i}`] = v;
14257
+ return acc;
14258
+ }, {});
14259
+ return ctx._nextStep(name, path, kwargs, "flow", options);
14260
+ }
14261
+ throw new Error(`taskFlow("${path}") can only be called inside a workflow()`);
14262
+ };
14263
+ Object.defineProperty(wrapper, "name", { value: name });
14264
+ wrapper._is_task = true;
14265
+ wrapper._task_path = path;
14266
+ return wrapper;
14267
+ }
14268
+ /**
14269
+ * Mark an async function as a workflow-as-code entry point.
14270
+ *
14271
+ * The function must be **deterministic**: given the same inputs it must call
14272
+ * tasks in the same order on every replay. Branching on task results is fine
14273
+ * (results are replayed from checkpoint), but branching on external state
14274
+ * (current time, random values, external API calls) must use `step()` to
14275
+ * checkpoint the value so replays see the same result.
14276
+ */
14277
+ function workflow(fn) {
14278
+ fn._is_workflow = true;
14279
+ return fn;
14280
+ }
14281
+ /**
14282
+ * Suspend the workflow and wait for an external approval.
14283
+ *
14284
+ * Use `getResumeUrls()` (wrapped in `step()`) to obtain resume/cancel/approvalPage
14285
+ * URLs before calling this function.
14286
+ *
14287
+ * @example
14288
+ * const urls = await step("urls", () => getResumeUrls());
14289
+ * await step("notify", () => sendEmail(urls.approvalPage));
14290
+ * const { value, approver } = await waitForApproval({ timeout: 3600 });
14291
+ */
14292
+ function waitForApproval(options) {
14293
+ const ctx = _workflowCtx ?? Reflect.get(globalThis, "__wmill_wf_ctx");
14294
+ if (!ctx) throw new Error("waitForApproval can only be called inside a workflow()");
14295
+ return ctx._waitForApproval(options);
14296
+ }
14297
+ /**
14298
+ * Process items in parallel with optional concurrency control.
14299
+ *
14300
+ * Each item is processed by calling `fn(item)`, which should be a task().
14301
+ * Items are dispatched in batches of `concurrency` (default: all at once).
14302
+ *
14303
+ * @example
14304
+ * const process = task(async (item: string) => { ... });
14305
+ * const results = await parallel(items, process, { concurrency: 5 });
14306
+ */
14307
+ async function parallel(items, fn, options) {
14308
+ const concurrency = options?.concurrency ?? items.length;
14309
+ if (concurrency <= 0 || items.length === 0) return [];
14310
+ const results = [];
14311
+ for (let i = 0; i < items.length; i += concurrency) {
14312
+ const batch = items.slice(i, i + concurrency);
14313
+ const batchResults = await Promise.all(batch.map((item) => fn(item)));
14314
+ results.push(...batchResults);
14315
+ }
14316
+ return results;
14317
+ }
14011
14318
 
14012
14319
  //#endregion
14013
14320
  //#region src/index.ts
@@ -14032,6 +14339,17 @@ const wmill = {
14032
14339
  getPresignedS3PublicUrls,
14033
14340
  getPresignedS3PublicUrl,
14034
14341
  task,
14342
+ taskScript,
14343
+ taskFlow,
14344
+ workflow,
14345
+ step,
14346
+ sleep,
14347
+ parallel,
14348
+ waitForApproval,
14349
+ WorkflowCtx,
14350
+ _workflowCtx,
14351
+ setWorkflowCtx,
14352
+ StepSuspend,
14035
14353
  runScript,
14036
14354
  runScriptAsync,
14037
14355
  runScriptByPath,
@@ -14132,6 +14450,7 @@ exports.ServiceLogsService = ServiceLogsService;
14132
14450
  exports.SettingService = SettingService;
14133
14451
  exports.SettingsService = SettingsService;
14134
14452
  exports.SqsTriggerService = SqsTriggerService;
14453
+ exports.StepSuspend = StepSuspend;
14135
14454
  exports.TeamsService = TeamsService;
14136
14455
  exports.TokenService = TokenService;
14137
14456
  exports.TriggerService = TriggerService;
@@ -14140,9 +14459,16 @@ exports.VariableService = VariableService;
14140
14459
  exports.VolumeService = VolumeService;
14141
14460
  exports.WebsocketTriggerService = WebsocketTriggerService;
14142
14461
  exports.WorkerService = WorkerService;
14462
+ exports.WorkflowCtx = WorkflowCtx;
14143
14463
  exports.WorkspaceDependenciesService = WorkspaceDependenciesService;
14144
14464
  exports.WorkspaceIntegrationService = WorkspaceIntegrationService;
14145
14465
  exports.WorkspaceService = WorkspaceService;
14466
+ Object.defineProperty(exports, '_workflowCtx', {
14467
+ enumerable: true,
14468
+ get: function () {
14469
+ return _workflowCtx;
14470
+ }
14471
+ });
14146
14472
  exports.appendToResultStream = appendToResultStream;
14147
14473
  exports.datatable = datatable;
14148
14474
  exports.default = src_default;
@@ -14160,6 +14486,7 @@ exports.getState = getState;
14160
14486
  exports.getVariable = getVariable;
14161
14487
  exports.loadS3File = loadS3File;
14162
14488
  exports.loadS3FileStream = loadS3FileStream;
14489
+ exports.parallel = parallel;
14163
14490
  exports.requestInteractiveSlackApproval = requestInteractiveSlackApproval;
14164
14491
  exports.requestInteractiveTeamsApproval = requestInteractiveTeamsApproval;
14165
14492
  exports.runFlow = runFlow;
@@ -14176,10 +14503,17 @@ exports.setProgress = setProgress;
14176
14503
  exports.setResource = setResource;
14177
14504
  exports.setState = setState;
14178
14505
  exports.setVariable = setVariable;
14506
+ exports.setWorkflowCtx = setWorkflowCtx;
14179
14507
  exports.signS3Object = signS3Object;
14180
14508
  exports.signS3Objects = signS3Objects;
14509
+ exports.sleep = sleep;
14510
+ exports.step = step;
14181
14511
  exports.streamResult = streamResult;
14182
14512
  exports.task = task;
14513
+ exports.taskFlow = taskFlow;
14514
+ exports.taskScript = taskScript;
14183
14515
  exports.usernameToEmail = usernameToEmail;
14516
+ exports.waitForApproval = waitForApproval;
14184
14517
  exports.waitJob = waitJob;
14518
+ exports.workflow = workflow;
14185
14519
  exports.writeS3File = writeS3File;
package/dist/index.mjs CHANGED
@@ -3,7 +3,7 @@ import { CancelError, CancelablePromise } from "./core/CancelablePromise.mjs";
3
3
  import { OpenAPI } from "./core/OpenAPI.mjs";
4
4
  import { AdminService, AgentWorkersService, AppService, AssetService, AuditService, CaptureService, ConcurrencyGroupsService, ConfigService, DocumentationService, DraftService, EmailTriggerService, FavoriteService, FlowConversationService, FlowService, FolderService, GcpTriggerService, GitSyncService, GranularAclService, GroupService, HealthService, HelpersService, HttpTriggerService, IndexSearchService, InputService, IntegrationService, JobService, KafkaTriggerService, McpOauthService, McpService, MetricsService, MqttTriggerService, NativeTriggerService, NatsTriggerService, NpmProxyService, OauthService, OidcService, OpenapiService, 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 { datatable, ducklake } from "./sqlUtils.mjs";
6
- import { SHARED_FOLDER, appendToResultStream, base64ToUint8Array, databaseUrlFromResource, denoS3LightClientSettings, getFlowUserState, getIdToken, getInternalState, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResult, getResultMaybe, getResumeEndpoints, getResumeUrls, getRootJobId, getState, getStatePath, getVariable, getWorkspace, loadS3File, loadS3FileStream, parseS3Object, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, resolveDefaultResource, runFlow, runFlowAsync, runScript, runScriptAsync, runScriptByHash, runScriptByHashAsync, runScriptByPath, runScriptByPathAsync, setClient, setFlowUserState, setInternalState, setProgress, setResource, setState, setVariable, signS3Object, signS3Objects, streamResult, task, uint8ArrayToBase64, usernameToEmail, waitJob, writeS3File } from "./client.mjs";
6
+ import { SHARED_FOLDER, StepSuspend, WorkflowCtx, _workflowCtx, appendToResultStream, base64ToUint8Array, databaseUrlFromResource, denoS3LightClientSettings, getFlowUserState, getIdToken, getInternalState, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResult, getResultMaybe, getResumeEndpoints, getResumeUrls, getRootJobId, getState, getStatePath, getVariable, getWorkspace, loadS3File, loadS3FileStream, parallel, parseS3Object, 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
7
 
8
8
  //#region src/index.ts
9
9
  const wmill = {
@@ -27,6 +27,17 @@ const wmill = {
27
27
  getPresignedS3PublicUrls,
28
28
  getPresignedS3PublicUrl,
29
29
  task,
30
+ taskScript,
31
+ taskFlow,
32
+ workflow,
33
+ step,
34
+ sleep,
35
+ parallel,
36
+ waitForApproval,
37
+ WorkflowCtx,
38
+ _workflowCtx,
39
+ setWorkflowCtx,
40
+ StepSuspend,
30
41
  runScript,
31
42
  runScriptAsync,
32
43
  runScriptByPath,
@@ -77,4 +88,4 @@ const wmill = {
77
88
  var src_default = wmill;
78
89
 
79
90
  //#endregion
80
- export { AdminService, AgentWorkersService, ApiError, AppService, AssetService, AuditService, CancelError, CancelablePromise, CaptureService, ConcurrencyGroupsService, ConfigService, DocumentationService, DraftService, EmailTriggerService, FavoriteService, FlowConversationService, FlowService, FolderService, GcpTriggerService, GitSyncService, GranularAclService, GroupService, HealthService, HelpersService, HttpTriggerService, IndexSearchService, InputService, IntegrationService, JobService, KafkaTriggerService, McpOauthService, McpService, MetricsService, MqttTriggerService, NativeTriggerService, NatsTriggerService, NpmProxyService, OauthService, OidcService, OpenAPI, OpenapiService, PostgresTriggerService, RawAppService, ResourceService, ScheduleService, ScriptService, ServiceLogsService, SettingService, SettingsService, SqsTriggerService, TeamsService, TokenService, TriggerService, UserService, VariableService, VolumeService, WebsocketTriggerService, WorkerService, WorkspaceDependenciesService, WorkspaceIntegrationService, WorkspaceService, appendToResultStream, datatable, src_default as default, denoS3LightClientSettings, ducklake, getFlowUserState, getIdToken, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResumeUrls, getRootJobId, getState, getVariable, loadS3File, loadS3FileStream, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, runFlow, runFlowAsync, runScript, runScriptAsync, runScriptByHash, runScriptByHashAsync, runScriptByPath, runScriptByPathAsync, setClient, setFlowUserState, setProgress, setResource, setState, setVariable, signS3Object, signS3Objects, streamResult, task, usernameToEmail, waitJob, writeS3File };
91
+ export { AdminService, AgentWorkersService, ApiError, AppService, AssetService, AuditService, CancelError, CancelablePromise, CaptureService, ConcurrencyGroupsService, ConfigService, DocumentationService, DraftService, EmailTriggerService, FavoriteService, FlowConversationService, FlowService, FolderService, GcpTriggerService, GitSyncService, GranularAclService, GroupService, HealthService, HelpersService, HttpTriggerService, IndexSearchService, InputService, IntegrationService, JobService, KafkaTriggerService, McpOauthService, McpService, MetricsService, MqttTriggerService, NativeTriggerService, NatsTriggerService, NpmProxyService, OauthService, OidcService, OpenAPI, OpenapiService, PostgresTriggerService, RawAppService, ResourceService, ScheduleService, ScriptService, ServiceLogsService, SettingService, SettingsService, SqsTriggerService, StepSuspend, TeamsService, TokenService, TriggerService, UserService, VariableService, VolumeService, WebsocketTriggerService, WorkerService, WorkflowCtx, WorkspaceDependenciesService, WorkspaceIntegrationService, WorkspaceService, _workflowCtx, appendToResultStream, datatable, src_default as default, 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, usernameToEmail, waitForApproval, waitJob, workflow, writeS3File };
@@ -1315,7 +1315,7 @@ export type NewScript = {
1315
1315
  path: string;
1316
1316
  parent_hash?: string;
1317
1317
  summary: string;
1318
- description: string;
1318
+ description?: string;
1319
1319
  content: string;
1320
1320
  schema?: {
1321
1321
  [key: string]: unknown;
@@ -11981,6 +11981,10 @@ export type SearchJobsIndexResponse = {
11981
11981
  * Is the current indexer service being replaced
11982
11982
  */
11983
11983
  lost_lock_ownership?: boolean;
11984
+ /**
11985
+ * Maximum time window in seconds for indexing
11986
+ */
11987
+ max_index_time_window_secs?: number;
11984
11988
  };
11985
11989
  };
11986
11990
  export type SearchLogsIndexData = {
@@ -24774,6 +24778,10 @@ export type $OpenApiTs = {
24774
24778
  * Is the current indexer service being replaced
24775
24779
  */
24776
24780
  lost_lock_ownership?: boolean;
24781
+ /**
24782
+ * Maximum time window in seconds for indexing
24783
+ */
24784
+ max_index_time_window_secs?: number;
24777
24785
  };
24778
24786
  };
24779
24787
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "windmill-client",
3
3
  "description": "Windmill SDK client for browsers and Node.js",
4
- "version": "1.651.1",
4
+ "version": "1.653.0",
5
5
  "author": "Ruben Fiszel",
6
6
  "license": "Apache 2.0",
7
7
  "sideEffects": false,