@upstash/workflow 0.2.22 → 0.2.23

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.
@@ -113,7 +113,9 @@ var StepTypes = [
113
113
  "Call",
114
114
  "Wait",
115
115
  "Notify",
116
- "Invoke"
116
+ "Invoke",
117
+ "CreateWebhook",
118
+ "WaitForWebhook"
117
119
  ];
118
120
 
119
121
  // src/agents/adapters.ts
@@ -394,8 +396,8 @@ var NANOID_LENGTH = 21;
394
396
  function getRandomInt() {
395
397
  return Math.floor(Math.random() * NANOID_CHARS.length);
396
398
  }
397
- function nanoid() {
398
- return Array.from({ length: NANOID_LENGTH }).map(() => NANOID_CHARS[getRandomInt()]).join("");
399
+ function nanoid(length = NANOID_LENGTH) {
400
+ return Array.from({ length }).map(() => NANOID_CHARS[getRandomInt()]).join("");
399
401
  }
400
402
  function getWorkflowRunId(id) {
401
403
  return `wfr_${id ?? nanoid()}`;
@@ -412,6 +414,37 @@ function decodeBase64(base64) {
412
414
  return binString;
413
415
  }
414
416
  }
417
+ function getUserIdFromToken(qstashClient) {
418
+ try {
419
+ const token = qstashClient.token;
420
+ const decodedToken = decodeBase64(token);
421
+ const tokenPayload = JSON.parse(decodedToken);
422
+ const userId = tokenPayload.UserID;
423
+ if (!userId) {
424
+ throw new WorkflowError("QStash token payload does not contain userId");
425
+ }
426
+ return userId;
427
+ } catch (error) {
428
+ throw new WorkflowError(
429
+ `Failed to decode QStash token while running create webhook step: ${error.message}`
430
+ );
431
+ }
432
+ }
433
+ function getQStashUrl(qstashClient) {
434
+ try {
435
+ const requester = qstashClient.http;
436
+ const baseUrl = requester.baseUrl;
437
+ if (!baseUrl) {
438
+ throw new WorkflowError("QStash client does not have a baseUrl");
439
+ }
440
+ return baseUrl;
441
+ } catch (error) {
442
+ throw new WorkflowError(`Failed to get QStash URL from client: ${error.message}`);
443
+ }
444
+ }
445
+ function getEventId() {
446
+ return `evt_${nanoid(15)}`;
447
+ }
415
448
 
416
449
  // node_modules/neverthrow/dist/index.es.js
417
450
  var defaultErrorConfig = {
@@ -1137,7 +1170,9 @@ If you want to disable QStash Verification, you should clear env variables QSTAS
1137
1170
  // src/context/steps.ts
1138
1171
  var BaseLazyStep = class _BaseLazyStep {
1139
1172
  stepName;
1140
- constructor(stepName) {
1173
+ context;
1174
+ constructor(context, stepName) {
1175
+ this.context = context;
1141
1176
  if (!stepName) {
1142
1177
  throw new WorkflowError(
1143
1178
  "A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
@@ -1155,13 +1190,14 @@ var BaseLazyStep = class _BaseLazyStep {
1155
1190
  *
1156
1191
  * will be called when returning the steps to the context from auto executor
1157
1192
  *
1158
- * @param out field of the step
1193
+ * @param step step
1159
1194
  * @returns parsed out field
1160
1195
  */
1161
- parseOut(out) {
1196
+ parseOut(step) {
1197
+ const out = step.out;
1162
1198
  if (out === void 0) {
1163
1199
  if (this.allowUndefinedOut) {
1164
- return void 0;
1200
+ return this.handleUndefinedOut(step);
1165
1201
  } else {
1166
1202
  throw new WorkflowError(
1167
1203
  `Error while parsing output of ${this.stepType} step. Expected a string, but got: undefined`
@@ -1169,27 +1205,26 @@ var BaseLazyStep = class _BaseLazyStep {
1169
1205
  }
1170
1206
  }
1171
1207
  if (typeof out === "object") {
1172
- if (this.stepType !== "Wait") {
1173
- console.warn(
1174
- `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
1175
- );
1176
- return out;
1177
- }
1178
- return {
1179
- ...out,
1180
- eventData: _BaseLazyStep.tryParsing(out.eventData)
1181
- };
1208
+ console.warn(
1209
+ `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
1210
+ );
1211
+ return out;
1182
1212
  }
1183
1213
  if (typeof out !== "string") {
1184
1214
  throw new WorkflowError(
1185
1215
  `Error while parsing output of ${this.stepType} step. Expected a string or undefined, but got: ${typeof out}`
1186
1216
  );
1187
1217
  }
1188
- return this.safeParseOut(out);
1218
+ return this.safeParseOut(out, step);
1189
1219
  }
1190
- safeParseOut(out) {
1220
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1221
+ safeParseOut(out, step) {
1191
1222
  return _BaseLazyStep.tryParsing(out);
1192
1223
  }
1224
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1225
+ handleUndefinedOut(step) {
1226
+ return void 0;
1227
+ }
1193
1228
  static tryParsing(stepOut) {
1194
1229
  try {
1195
1230
  return JSON.parse(stepOut);
@@ -1240,8 +1275,8 @@ var LazyFunctionStep = class extends BaseLazyStep {
1240
1275
  stepFunction;
1241
1276
  stepType = "Run";
1242
1277
  allowUndefinedOut = true;
1243
- constructor(stepName, stepFunction) {
1244
- super(stepName);
1278
+ constructor(context, stepName, stepFunction) {
1279
+ super(context, stepName);
1245
1280
  this.stepFunction = stepFunction;
1246
1281
  }
1247
1282
  getPlanStep(concurrent, targetStep) {
@@ -1271,8 +1306,8 @@ var LazySleepStep = class extends BaseLazyStep {
1271
1306
  sleep;
1272
1307
  stepType = "SleepFor";
1273
1308
  allowUndefinedOut = true;
1274
- constructor(stepName, sleep) {
1275
- super(stepName);
1309
+ constructor(context, stepName, sleep) {
1310
+ super(context, stepName);
1276
1311
  this.sleep = sleep;
1277
1312
  }
1278
1313
  getPlanStep(concurrent, targetStep) {
@@ -1313,8 +1348,8 @@ var LazySleepUntilStep = class extends BaseLazyStep {
1313
1348
  sleepUntil;
1314
1349
  stepType = "SleepUntil";
1315
1350
  allowUndefinedOut = true;
1316
- constructor(stepName, sleepUntil) {
1317
- super(stepName);
1351
+ constructor(context, stepName, sleepUntil) {
1352
+ super(context, stepName);
1318
1353
  this.sleepUntil = sleepUntil;
1319
1354
  }
1320
1355
  getPlanStep(concurrent, targetStep) {
@@ -1366,8 +1401,8 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1366
1401
  stringifyBody;
1367
1402
  stepType = "Call";
1368
1403
  allowUndefinedOut = false;
1369
- constructor(stepName, url, method, body, headers, retries, retryDelay, timeout, flowControl, stringifyBody) {
1370
- super(stepName);
1404
+ constructor(context, stepName, url, method, body, headers, retries, retryDelay, timeout, flowControl, stringifyBody) {
1405
+ super(context, stepName);
1371
1406
  this.url = url;
1372
1407
  this.method = method;
1373
1408
  this.body = body;
@@ -1511,13 +1546,12 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1511
1546
  ]);
1512
1547
  }
1513
1548
  };
1514
- var LazyWaitForEventStep = class extends BaseLazyStep {
1549
+ var LazyWaitEventStep = class extends BaseLazyStep {
1515
1550
  eventId;
1516
1551
  timeout;
1517
- stepType = "Wait";
1518
1552
  allowUndefinedOut = false;
1519
- constructor(stepName, eventId, timeout) {
1520
- super(stepName);
1553
+ constructor(context, stepName, eventId, timeout) {
1554
+ super(context, stepName);
1521
1555
  this.eventId = eventId;
1522
1556
  this.timeout = timeout;
1523
1557
  }
@@ -1542,13 +1576,6 @@ var LazyWaitForEventStep = class extends BaseLazyStep {
1542
1576
  concurrent
1543
1577
  });
1544
1578
  }
1545
- safeParseOut(out) {
1546
- const result = JSON.parse(out);
1547
- return {
1548
- ...result,
1549
- eventData: BaseLazyStep.tryParsing(result.eventData)
1550
- };
1551
- }
1552
1579
  getHeaders({ context, telemetry, invokeCount, step }) {
1553
1580
  const headers = super.getHeaders({ context, telemetry, invokeCount, step });
1554
1581
  headers.headers["Upstash-Workflow-CallType"] = "step";
@@ -1582,7 +1609,7 @@ var LazyWaitForEventStep = class extends BaseLazyStep {
1582
1609
  timeoutHeaders,
1583
1610
  step: {
1584
1611
  stepId: step.stepId,
1585
- stepType: "Wait",
1612
+ stepType: this.stepType,
1586
1613
  stepName: step.stepName,
1587
1614
  concurrent: step.concurrent,
1588
1615
  targetStep: step.targetStep
@@ -1603,8 +1630,8 @@ var LazyWaitForEventStep = class extends BaseLazyStep {
1603
1630
  };
1604
1631
  var LazyNotifyStep = class extends LazyFunctionStep {
1605
1632
  stepType = "Notify";
1606
- constructor(stepName, eventId, eventData, requester) {
1607
- super(stepName, async () => {
1633
+ constructor(context, stepName, eventId, eventData, requester) {
1634
+ super(context, stepName, async () => {
1608
1635
  const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
1609
1636
  return {
1610
1637
  eventId,
@@ -1629,7 +1656,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
1629
1656
  * workflow id of the invoked workflow
1630
1657
  */
1631
1658
  workflowId;
1632
- constructor(stepName, {
1659
+ constructor(context, stepName, {
1633
1660
  workflow,
1634
1661
  body,
1635
1662
  headers = {},
@@ -1639,7 +1666,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
1639
1666
  flowControl,
1640
1667
  stringifyBody = true
1641
1668
  }) {
1642
- super(stepName);
1669
+ super(context, stepName);
1643
1670
  this.params = {
1644
1671
  workflow,
1645
1672
  body,
@@ -1700,6 +1727,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
1700
1727
  userHeaders: context.headers,
1701
1728
  invokeCount
1702
1729
  });
1730
+ context.qstashClient.http.headers?.forEach((value, key) => {
1731
+ invokerHeaders[key] = value;
1732
+ });
1703
1733
  invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
1704
1734
  let invokeBody;
1705
1735
  if (this.params.stringifyBody) {
@@ -1771,6 +1801,88 @@ var LazyInvokeStep = class extends BaseLazyStep {
1771
1801
  return [result];
1772
1802
  }
1773
1803
  };
1804
+ var LazyCreateWebhookStep = class extends BaseLazyStep {
1805
+ stepType = "CreateWebhook";
1806
+ allowUndefinedOut = false;
1807
+ getPlanStep(concurrent, targetStep) {
1808
+ return {
1809
+ stepId: 0,
1810
+ stepName: this.stepName,
1811
+ stepType: this.stepType,
1812
+ concurrent,
1813
+ targetStep
1814
+ };
1815
+ }
1816
+ async getResultStep(concurrent, stepId) {
1817
+ return {
1818
+ stepId,
1819
+ stepName: this.stepName,
1820
+ stepType: this.stepType,
1821
+ out: void 0,
1822
+ concurrent
1823
+ };
1824
+ }
1825
+ getBody({ step, context }) {
1826
+ const userId = getUserIdFromToken(context.qstashClient);
1827
+ const workflowRunId = context.workflowRunId;
1828
+ const eventId = getEventId();
1829
+ const qstashUrl = getQStashUrl(this.context.qstashClient);
1830
+ return JSON.stringify({
1831
+ ...step,
1832
+ out: JSON.stringify({
1833
+ webhookUrl: `${qstashUrl}/v2/workflows/hooks/${userId}/${workflowRunId}/${eventId}`,
1834
+ eventId
1835
+ })
1836
+ });
1837
+ }
1838
+ };
1839
+ var LazyWaitForWebhookStep = class extends LazyWaitEventStep {
1840
+ stepType = "WaitForWebhook";
1841
+ allowUndefinedOut = true;
1842
+ constructor(context, stepName, webhook, timeout) {
1843
+ super(context, stepName, webhook.eventId, timeout);
1844
+ }
1845
+ safeParseOut(out) {
1846
+ const eventData = decodeBase64(out);
1847
+ const parsedEventData = BaseLazyStep.tryParsing(eventData);
1848
+ const body = parsedEventData.body;
1849
+ const parsedBody = typeof body === "string" ? decodeBase64(body) : void 0;
1850
+ const request = new Request(
1851
+ `${parsedEventData.proto}://${parsedEventData.host}${parsedEventData.url}`,
1852
+ {
1853
+ method: parsedEventData.method,
1854
+ headers: parsedEventData.header,
1855
+ body: parsedBody
1856
+ }
1857
+ );
1858
+ return {
1859
+ request,
1860
+ timeout: false
1861
+ };
1862
+ }
1863
+ handleUndefinedOut() {
1864
+ return {
1865
+ timeout: true,
1866
+ request: void 0
1867
+ };
1868
+ }
1869
+ };
1870
+ var LazyWaitForEventStep = class extends LazyWaitEventStep {
1871
+ stepType = "Wait";
1872
+ allowUndefinedOut = true;
1873
+ parseWaitForEventOut(out, waitTimeout) {
1874
+ return {
1875
+ eventData: out ? BaseLazyStep.tryParsing(decodeBase64(out)) : void 0,
1876
+ timeout: waitTimeout ?? false
1877
+ };
1878
+ }
1879
+ safeParseOut(out, step) {
1880
+ return this.parseWaitForEventOut(out, step.waitTimeout);
1881
+ }
1882
+ handleUndefinedOut(step) {
1883
+ return this.parseWaitForEventOut(void 0, step.waitTimeout);
1884
+ }
1885
+ };
1774
1886
 
1775
1887
  // src/qstash/headers.ts
1776
1888
  var WorkflowHeaders = class {
@@ -2161,7 +2273,7 @@ var AutoExecutor = class _AutoExecutor {
2161
2273
  step,
2162
2274
  stepCount: this.stepCount
2163
2275
  });
2164
- return lazyStep.parseOut(step.out);
2276
+ return lazyStep.parseOut(step);
2165
2277
  }
2166
2278
  const resultStep = await submitSingleStep({
2167
2279
  context: this.context,
@@ -2248,7 +2360,7 @@ var AutoExecutor = class _AutoExecutor {
2248
2360
  const parallelResultSteps = sortedSteps.filter((step) => step.stepId >= initialStepCount).slice(0, parallelSteps.length);
2249
2361
  validateParallelSteps(parallelSteps, parallelResultSteps);
2250
2362
  return parallelResultSteps.map(
2251
- (step, index) => parallelSteps[index].parseOut(step.out)
2363
+ (step, index) => parallelSteps[index].parseOut(step)
2252
2364
  );
2253
2365
  }
2254
2366
  }
@@ -2304,7 +2416,6 @@ var AutoExecutor = class _AutoExecutor {
2304
2416
  * @param index index of the current step
2305
2417
  * @returns result[index] if lazyStepList > 1, otherwise result
2306
2418
  */
2307
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
2308
2419
  static getResult(lazyStepList, result, index) {
2309
2420
  if (lazyStepList.length === 1) {
2310
2421
  return result;
@@ -2937,7 +3048,7 @@ var WorkflowContext = class {
2937
3048
  */
2938
3049
  async run(stepName, stepFunction) {
2939
3050
  const wrappedStepFunction = () => this.executor.wrapStep(stepName, stepFunction);
2940
- return await this.addStep(new LazyFunctionStep(stepName, wrappedStepFunction));
3051
+ return await this.addStep(new LazyFunctionStep(this, stepName, wrappedStepFunction));
2941
3052
  }
2942
3053
  /**
2943
3054
  * Stops the execution for the duration provided.
@@ -2951,7 +3062,7 @@ var WorkflowContext = class {
2951
3062
  * @returns undefined
2952
3063
  */
2953
3064
  async sleep(stepName, duration) {
2954
- await this.addStep(new LazySleepStep(stepName, duration));
3065
+ await this.addStep(new LazySleepStep(this, stepName, duration));
2955
3066
  }
2956
3067
  /**
2957
3068
  * Stops the execution until the date time provided.
@@ -2973,13 +3084,14 @@ var WorkflowContext = class {
2973
3084
  datetime = typeof datetime === "string" ? new Date(datetime) : datetime;
2974
3085
  time = Math.round(datetime.getTime() / 1e3);
2975
3086
  }
2976
- await this.addStep(new LazySleepUntilStep(stepName, time));
3087
+ await this.addStep(new LazySleepUntilStep(this, stepName, time));
2977
3088
  }
2978
3089
  async call(stepName, settings) {
2979
3090
  let callStep;
2980
3091
  if ("workflow" in settings) {
2981
3092
  const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
2982
3093
  callStep = new LazyCallStep(
3094
+ this,
2983
3095
  stepName,
2984
3096
  url,
2985
3097
  "POST",
@@ -3004,6 +3116,7 @@ var WorkflowContext = class {
3004
3116
  stringifyBody = true
3005
3117
  } = settings;
3006
3118
  callStep = new LazyCallStep(
3119
+ this,
3007
3120
  stepName,
3008
3121
  url,
3009
3122
  method,
@@ -3055,7 +3168,9 @@ var WorkflowContext = class {
3055
3168
  async waitForEvent(stepName, eventId, options = {}) {
3056
3169
  const { timeout = "7d" } = options;
3057
3170
  const timeoutStr = typeof timeout === "string" ? timeout : `${timeout}s`;
3058
- return await this.addStep(new LazyWaitForEventStep(stepName, eventId, timeoutStr));
3171
+ return await this.addStep(
3172
+ new LazyWaitForEventStep(this, stepName, eventId, timeoutStr)
3173
+ );
3059
3174
  }
3060
3175
  /**
3061
3176
  * Notify workflow runs waiting for an event
@@ -3080,11 +3195,19 @@ var WorkflowContext = class {
3080
3195
  */
3081
3196
  async notify(stepName, eventId, eventData) {
3082
3197
  return await this.addStep(
3083
- new LazyNotifyStep(stepName, eventId, eventData, this.qstashClient.http)
3198
+ new LazyNotifyStep(this, stepName, eventId, eventData, this.qstashClient.http)
3084
3199
  );
3085
3200
  }
3086
3201
  async invoke(stepName, settings) {
3087
- return await this.addStep(new LazyInvokeStep(stepName, settings));
3202
+ return await this.addStep(
3203
+ new LazyInvokeStep(this, stepName, settings)
3204
+ );
3205
+ }
3206
+ async createWebhook(stepName) {
3207
+ return await this.addStep(new LazyCreateWebhookStep(this, stepName));
3208
+ }
3209
+ async waitForWebhook(stepName, webhook, timeout) {
3210
+ return await this.addStep(new LazyWaitForWebhookStep(this, stepName, webhook, timeout));
3088
3211
  }
3089
3212
  /**
3090
3213
  * Cancel the current workflow run
@@ -3248,13 +3371,6 @@ var processRawSteps = (rawSteps) => {
3248
3371
  const stepsToDecode = encodedSteps.filter((step) => step.callType === "step");
3249
3372
  const otherSteps = stepsToDecode.map((rawStep) => {
3250
3373
  const step = JSON.parse(decodeBase64(rawStep.body));
3251
- if (step.waitEventId) {
3252
- const newOut = {
3253
- eventData: step.out ? decodeBase64(step.out) : void 0,
3254
- timeout: step.waitTimeout ?? false
3255
- };
3256
- step.out = newOut;
3257
- }
3258
3374
  return step;
3259
3375
  });
3260
3376
  const steps = [initialStep, ...otherSteps];
package/cloudflare.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as RouteFunction, o as PublicServeOptions, z as InvokableWorkflow } from './types-9nCq6bRP.mjs';
2
- import { s as serveManyBase } from './serve-many-CctdYIfB.mjs';
1
+ import { R as RouteFunction, o as PublicServeOptions, z as InvokableWorkflow } from './types-BD06btU6.mjs';
2
+ import { s as serveManyBase } from './serve-many-B5Vbacm6.mjs';
3
3
  import '@upstash/qstash';
4
4
  import 'zod';
5
5
  import 'ai';
package/cloudflare.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as RouteFunction, o as PublicServeOptions, z as InvokableWorkflow } from './types-9nCq6bRP.js';
2
- import { s as serveManyBase } from './serve-many-BXDr30rl.js';
1
+ import { R as RouteFunction, o as PublicServeOptions, z as InvokableWorkflow } from './types-BD06btU6.js';
2
+ import { s as serveManyBase } from './serve-many-BCV7INWe.js';
3
3
  import '@upstash/qstash';
4
4
  import 'zod';
5
5
  import 'ai';