@upstash/workflow 0.2.22 → 0.2.23-rc

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/h3.js CHANGED
@@ -511,8 +511,8 @@ var NANOID_LENGTH = 21;
511
511
  function getRandomInt() {
512
512
  return Math.floor(Math.random() * NANOID_CHARS.length);
513
513
  }
514
- function nanoid() {
515
- return Array.from({ length: NANOID_LENGTH }).map(() => NANOID_CHARS[getRandomInt()]).join("");
514
+ function nanoid(length = NANOID_LENGTH) {
515
+ return Array.from({ length }).map(() => NANOID_CHARS[getRandomInt()]).join("");
516
516
  }
517
517
  function getWorkflowRunId(id) {
518
518
  return `wfr_${id ?? nanoid()}`;
@@ -529,6 +529,37 @@ function decodeBase64(base64) {
529
529
  return binString;
530
530
  }
531
531
  }
532
+ function getUserIdFromToken(qstashClient) {
533
+ try {
534
+ const token = qstashClient.token;
535
+ const decodedToken = decodeBase64(token);
536
+ const tokenPayload = JSON.parse(decodedToken);
537
+ const userId = tokenPayload.UserID;
538
+ if (!userId) {
539
+ throw new WorkflowError("QStash token payload does not contain userId");
540
+ }
541
+ return userId;
542
+ } catch (error) {
543
+ throw new WorkflowError(
544
+ `Failed to decode QStash token while running create webhook step: ${error.message}`
545
+ );
546
+ }
547
+ }
548
+ function getQStashUrl(qstashClient) {
549
+ try {
550
+ const requester = qstashClient.http;
551
+ const baseUrl = requester.baseUrl;
552
+ if (!baseUrl) {
553
+ throw new WorkflowError("QStash client does not have a baseUrl");
554
+ }
555
+ return baseUrl;
556
+ } catch (error) {
557
+ throw new WorkflowError(`Failed to get QStash URL from client: ${error.message}`);
558
+ }
559
+ }
560
+ function getEventId() {
561
+ return `evt_${nanoid(15)}`;
562
+ }
532
563
 
533
564
  // node_modules/neverthrow/dist/index.es.js
534
565
  var defaultErrorConfig = {
@@ -954,7 +985,9 @@ var StepTypes = [
954
985
  "Call",
955
986
  "Wait",
956
987
  "Notify",
957
- "Invoke"
988
+ "Invoke",
989
+ "CreateWebhook",
990
+ "WaitForWebhook"
958
991
  ];
959
992
 
960
993
  // src/workflow-requests.ts
@@ -1266,7 +1299,9 @@ If you want to disable QStash Verification, you should clear env variables QSTAS
1266
1299
  // src/context/steps.ts
1267
1300
  var BaseLazyStep = class _BaseLazyStep {
1268
1301
  stepName;
1269
- constructor(stepName) {
1302
+ context;
1303
+ constructor(context, stepName) {
1304
+ this.context = context;
1270
1305
  if (!stepName) {
1271
1306
  throw new WorkflowError(
1272
1307
  "A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
@@ -1284,13 +1319,14 @@ var BaseLazyStep = class _BaseLazyStep {
1284
1319
  *
1285
1320
  * will be called when returning the steps to the context from auto executor
1286
1321
  *
1287
- * @param out field of the step
1322
+ * @param step step
1288
1323
  * @returns parsed out field
1289
1324
  */
1290
- parseOut(out) {
1325
+ parseOut(step) {
1326
+ const out = step.out;
1291
1327
  if (out === void 0) {
1292
1328
  if (this.allowUndefinedOut) {
1293
- return void 0;
1329
+ return this.handleUndefinedOut(step);
1294
1330
  } else {
1295
1331
  throw new WorkflowError(
1296
1332
  `Error while parsing output of ${this.stepType} step. Expected a string, but got: undefined`
@@ -1298,27 +1334,26 @@ var BaseLazyStep = class _BaseLazyStep {
1298
1334
  }
1299
1335
  }
1300
1336
  if (typeof out === "object") {
1301
- if (this.stepType !== "Wait") {
1302
- console.warn(
1303
- `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
1304
- );
1305
- return out;
1306
- }
1307
- return {
1308
- ...out,
1309
- eventData: _BaseLazyStep.tryParsing(out.eventData)
1310
- };
1337
+ console.warn(
1338
+ `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
1339
+ );
1340
+ return out;
1311
1341
  }
1312
1342
  if (typeof out !== "string") {
1313
1343
  throw new WorkflowError(
1314
1344
  `Error while parsing output of ${this.stepType} step. Expected a string or undefined, but got: ${typeof out}`
1315
1345
  );
1316
1346
  }
1317
- return this.safeParseOut(out);
1347
+ return this.safeParseOut(out, step);
1318
1348
  }
1319
- safeParseOut(out) {
1349
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1350
+ safeParseOut(out, step) {
1320
1351
  return _BaseLazyStep.tryParsing(out);
1321
1352
  }
1353
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1354
+ handleUndefinedOut(step) {
1355
+ return void 0;
1356
+ }
1322
1357
  static tryParsing(stepOut) {
1323
1358
  try {
1324
1359
  return JSON.parse(stepOut);
@@ -1369,8 +1404,8 @@ var LazyFunctionStep = class extends BaseLazyStep {
1369
1404
  stepFunction;
1370
1405
  stepType = "Run";
1371
1406
  allowUndefinedOut = true;
1372
- constructor(stepName, stepFunction) {
1373
- super(stepName);
1407
+ constructor(context, stepName, stepFunction) {
1408
+ super(context, stepName);
1374
1409
  this.stepFunction = stepFunction;
1375
1410
  }
1376
1411
  getPlanStep(concurrent, targetStep) {
@@ -1400,8 +1435,8 @@ var LazySleepStep = class extends BaseLazyStep {
1400
1435
  sleep;
1401
1436
  stepType = "SleepFor";
1402
1437
  allowUndefinedOut = true;
1403
- constructor(stepName, sleep) {
1404
- super(stepName);
1438
+ constructor(context, stepName, sleep) {
1439
+ super(context, stepName);
1405
1440
  this.sleep = sleep;
1406
1441
  }
1407
1442
  getPlanStep(concurrent, targetStep) {
@@ -1442,8 +1477,8 @@ var LazySleepUntilStep = class extends BaseLazyStep {
1442
1477
  sleepUntil;
1443
1478
  stepType = "SleepUntil";
1444
1479
  allowUndefinedOut = true;
1445
- constructor(stepName, sleepUntil) {
1446
- super(stepName);
1480
+ constructor(context, stepName, sleepUntil) {
1481
+ super(context, stepName);
1447
1482
  this.sleepUntil = sleepUntil;
1448
1483
  }
1449
1484
  getPlanStep(concurrent, targetStep) {
@@ -1495,8 +1530,8 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1495
1530
  stringifyBody;
1496
1531
  stepType = "Call";
1497
1532
  allowUndefinedOut = false;
1498
- constructor(stepName, url, method, body, headers, retries, retryDelay, timeout, flowControl, stringifyBody) {
1499
- super(stepName);
1533
+ constructor(context, stepName, url, method, body, headers, retries, retryDelay, timeout, flowControl, stringifyBody) {
1534
+ super(context, stepName);
1500
1535
  this.url = url;
1501
1536
  this.method = method;
1502
1537
  this.body = body;
@@ -1640,13 +1675,12 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1640
1675
  ]);
1641
1676
  }
1642
1677
  };
1643
- var LazyWaitForEventStep = class extends BaseLazyStep {
1678
+ var LazyWaitEventStep = class extends BaseLazyStep {
1644
1679
  eventId;
1645
1680
  timeout;
1646
- stepType = "Wait";
1647
1681
  allowUndefinedOut = false;
1648
- constructor(stepName, eventId, timeout) {
1649
- super(stepName);
1682
+ constructor(context, stepName, eventId, timeout) {
1683
+ super(context, stepName);
1650
1684
  this.eventId = eventId;
1651
1685
  this.timeout = timeout;
1652
1686
  }
@@ -1671,13 +1705,6 @@ var LazyWaitForEventStep = class extends BaseLazyStep {
1671
1705
  concurrent
1672
1706
  });
1673
1707
  }
1674
- safeParseOut(out) {
1675
- const result = JSON.parse(out);
1676
- return {
1677
- ...result,
1678
- eventData: BaseLazyStep.tryParsing(result.eventData)
1679
- };
1680
- }
1681
1708
  getHeaders({ context, telemetry: telemetry2, invokeCount, step }) {
1682
1709
  const headers = super.getHeaders({ context, telemetry: telemetry2, invokeCount, step });
1683
1710
  headers.headers["Upstash-Workflow-CallType"] = "step";
@@ -1711,7 +1738,7 @@ var LazyWaitForEventStep = class extends BaseLazyStep {
1711
1738
  timeoutHeaders,
1712
1739
  step: {
1713
1740
  stepId: step.stepId,
1714
- stepType: "Wait",
1741
+ stepType: this.stepType,
1715
1742
  stepName: step.stepName,
1716
1743
  concurrent: step.concurrent,
1717
1744
  targetStep: step.targetStep
@@ -1732,8 +1759,8 @@ var LazyWaitForEventStep = class extends BaseLazyStep {
1732
1759
  };
1733
1760
  var LazyNotifyStep = class extends LazyFunctionStep {
1734
1761
  stepType = "Notify";
1735
- constructor(stepName, eventId, eventData, requester) {
1736
- super(stepName, async () => {
1762
+ constructor(context, stepName, eventId, eventData, requester) {
1763
+ super(context, stepName, async () => {
1737
1764
  const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
1738
1765
  return {
1739
1766
  eventId,
@@ -1758,7 +1785,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
1758
1785
  * workflow id of the invoked workflow
1759
1786
  */
1760
1787
  workflowId;
1761
- constructor(stepName, {
1788
+ constructor(context, stepName, {
1762
1789
  workflow,
1763
1790
  body,
1764
1791
  headers = {},
@@ -1768,7 +1795,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
1768
1795
  flowControl,
1769
1796
  stringifyBody = true
1770
1797
  }) {
1771
- super(stepName);
1798
+ super(context, stepName);
1772
1799
  this.params = {
1773
1800
  workflow,
1774
1801
  body,
@@ -1829,6 +1856,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
1829
1856
  userHeaders: context.headers,
1830
1857
  invokeCount
1831
1858
  });
1859
+ context.qstashClient.http.headers?.forEach((value, key) => {
1860
+ invokerHeaders[key] = value;
1861
+ });
1832
1862
  invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
1833
1863
  let invokeBody;
1834
1864
  if (this.params.stringifyBody) {
@@ -1900,6 +1930,91 @@ var LazyInvokeStep = class extends BaseLazyStep {
1900
1930
  return [result];
1901
1931
  }
1902
1932
  };
1933
+ var LazyCreateWebhookStep = class extends BaseLazyStep {
1934
+ stepType = "CreateWebhook";
1935
+ allowUndefinedOut = false;
1936
+ getPlanStep(concurrent, targetStep) {
1937
+ return {
1938
+ stepId: 0,
1939
+ stepName: this.stepName,
1940
+ stepType: this.stepType,
1941
+ concurrent,
1942
+ targetStep
1943
+ };
1944
+ }
1945
+ async getResultStep(concurrent, stepId) {
1946
+ return {
1947
+ stepId,
1948
+ stepName: this.stepName,
1949
+ stepType: this.stepType,
1950
+ out: void 0,
1951
+ concurrent
1952
+ };
1953
+ }
1954
+ getBody({ step, context }) {
1955
+ const userId = getUserIdFromToken(context.qstashClient);
1956
+ const out = [userId, context.workflowRunId, getEventId()].join("/");
1957
+ return JSON.stringify({
1958
+ ...step,
1959
+ out
1960
+ });
1961
+ }
1962
+ safeParseOut(out) {
1963
+ const [userId, workflowRunId, eventId] = out.split("/");
1964
+ const qstashUrl = getQStashUrl(this.context.qstashClient);
1965
+ return {
1966
+ webhookUrl: `${qstashUrl}/v2/workflows/hooks/${userId}/${workflowRunId}/${eventId}`,
1967
+ eventId
1968
+ };
1969
+ }
1970
+ };
1971
+ var LazyWaitForWebhookStep = class extends LazyWaitEventStep {
1972
+ stepType = "WaitForWebhook";
1973
+ allowUndefinedOut = true;
1974
+ constructor(context, stepName, webhook, timeout) {
1975
+ super(context, stepName, webhook.eventId, timeout);
1976
+ }
1977
+ safeParseOut(out) {
1978
+ const eventData = decodeBase64(out);
1979
+ const parsedEventData = BaseLazyStep.tryParsing(eventData);
1980
+ const body = parsedEventData.body;
1981
+ const parsedBody = typeof body === "string" ? decodeBase64(body) : void 0;
1982
+ const request = new Request(
1983
+ `${parsedEventData.proto}://${parsedEventData.host}${parsedEventData.url}`,
1984
+ {
1985
+ method: parsedEventData.method,
1986
+ headers: parsedEventData.header,
1987
+ body: parsedBody
1988
+ }
1989
+ );
1990
+ return {
1991
+ request,
1992
+ timeout: false
1993
+ };
1994
+ }
1995
+ handleUndefinedOut() {
1996
+ return {
1997
+ timeout: true,
1998
+ request: void 0
1999
+ };
2000
+ }
2001
+ };
2002
+ var LazyWaitForEventStep = class extends LazyWaitEventStep {
2003
+ stepType = "Wait";
2004
+ allowUndefinedOut = true;
2005
+ parseWaitForEventOut(out, waitTimeout) {
2006
+ return {
2007
+ eventData: out ? BaseLazyStep.tryParsing(decodeBase64(out)) : void 0,
2008
+ timeout: waitTimeout ?? false
2009
+ };
2010
+ }
2011
+ safeParseOut(out, step) {
2012
+ return this.parseWaitForEventOut(out, step.waitTimeout);
2013
+ }
2014
+ handleUndefinedOut(step) {
2015
+ return this.parseWaitForEventOut(void 0, step.waitTimeout);
2016
+ }
2017
+ };
1903
2018
 
1904
2019
  // src/agents/constants.ts
1905
2020
  var AGENT_NAME_HEADER = "upstash-agent-name";
@@ -2304,7 +2419,7 @@ var AutoExecutor = class _AutoExecutor {
2304
2419
  step,
2305
2420
  stepCount: this.stepCount
2306
2421
  });
2307
- return lazyStep.parseOut(step.out);
2422
+ return lazyStep.parseOut(step);
2308
2423
  }
2309
2424
  const resultStep = await submitSingleStep({
2310
2425
  context: this.context,
@@ -2391,7 +2506,7 @@ var AutoExecutor = class _AutoExecutor {
2391
2506
  const parallelResultSteps = sortedSteps.filter((step) => step.stepId >= initialStepCount).slice(0, parallelSteps.length);
2392
2507
  validateParallelSteps(parallelSteps, parallelResultSteps);
2393
2508
  return parallelResultSteps.map(
2394
- (step, index) => parallelSteps[index].parseOut(step.out)
2509
+ (step, index) => parallelSteps[index].parseOut(step)
2395
2510
  );
2396
2511
  }
2397
2512
  }
@@ -2447,7 +2562,6 @@ var AutoExecutor = class _AutoExecutor {
2447
2562
  * @param index index of the current step
2448
2563
  * @returns result[index] if lazyStepList > 1, otherwise result
2449
2564
  */
2450
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
2451
2565
  static getResult(lazyStepList, result, index) {
2452
2566
  if (lazyStepList.length === 1) {
2453
2567
  return result;
@@ -3239,7 +3353,7 @@ var WorkflowContext = class {
3239
3353
  */
3240
3354
  async run(stepName, stepFunction) {
3241
3355
  const wrappedStepFunction = () => this.executor.wrapStep(stepName, stepFunction);
3242
- return await this.addStep(new LazyFunctionStep(stepName, wrappedStepFunction));
3356
+ return await this.addStep(new LazyFunctionStep(this, stepName, wrappedStepFunction));
3243
3357
  }
3244
3358
  /**
3245
3359
  * Stops the execution for the duration provided.
@@ -3253,7 +3367,7 @@ var WorkflowContext = class {
3253
3367
  * @returns undefined
3254
3368
  */
3255
3369
  async sleep(stepName, duration) {
3256
- await this.addStep(new LazySleepStep(stepName, duration));
3370
+ await this.addStep(new LazySleepStep(this, stepName, duration));
3257
3371
  }
3258
3372
  /**
3259
3373
  * Stops the execution until the date time provided.
@@ -3275,13 +3389,14 @@ var WorkflowContext = class {
3275
3389
  datetime = typeof datetime === "string" ? new Date(datetime) : datetime;
3276
3390
  time = Math.round(datetime.getTime() / 1e3);
3277
3391
  }
3278
- await this.addStep(new LazySleepUntilStep(stepName, time));
3392
+ await this.addStep(new LazySleepUntilStep(this, stepName, time));
3279
3393
  }
3280
3394
  async call(stepName, settings) {
3281
3395
  let callStep;
3282
3396
  if ("workflow" in settings) {
3283
3397
  const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
3284
3398
  callStep = new LazyCallStep(
3399
+ this,
3285
3400
  stepName,
3286
3401
  url,
3287
3402
  "POST",
@@ -3306,6 +3421,7 @@ var WorkflowContext = class {
3306
3421
  stringifyBody = true
3307
3422
  } = settings;
3308
3423
  callStep = new LazyCallStep(
3424
+ this,
3309
3425
  stepName,
3310
3426
  url,
3311
3427
  method,
@@ -3357,7 +3473,9 @@ var WorkflowContext = class {
3357
3473
  async waitForEvent(stepName, eventId, options = {}) {
3358
3474
  const { timeout = "7d" } = options;
3359
3475
  const timeoutStr = typeof timeout === "string" ? timeout : `${timeout}s`;
3360
- return await this.addStep(new LazyWaitForEventStep(stepName, eventId, timeoutStr));
3476
+ return await this.addStep(
3477
+ new LazyWaitForEventStep(this, stepName, eventId, timeoutStr)
3478
+ );
3361
3479
  }
3362
3480
  /**
3363
3481
  * Notify workflow runs waiting for an event
@@ -3382,11 +3500,19 @@ var WorkflowContext = class {
3382
3500
  */
3383
3501
  async notify(stepName, eventId, eventData) {
3384
3502
  return await this.addStep(
3385
- new LazyNotifyStep(stepName, eventId, eventData, this.qstashClient.http)
3503
+ new LazyNotifyStep(this, stepName, eventId, eventData, this.qstashClient.http)
3386
3504
  );
3387
3505
  }
3388
3506
  async invoke(stepName, settings) {
3389
- return await this.addStep(new LazyInvokeStep(stepName, settings));
3507
+ return await this.addStep(
3508
+ new LazyInvokeStep(this, stepName, settings)
3509
+ );
3510
+ }
3511
+ async createWebhook(stepName) {
3512
+ return await this.addStep(new LazyCreateWebhookStep(this, stepName));
3513
+ }
3514
+ async waitForWebhook(stepName, webhook, timeout) {
3515
+ return await this.addStep(new LazyWaitForWebhookStep(this, stepName, webhook, timeout));
3390
3516
  }
3391
3517
  /**
3392
3518
  * Cancel the current workflow run
@@ -3550,13 +3676,6 @@ var processRawSteps = (rawSteps) => {
3550
3676
  const stepsToDecode = encodedSteps.filter((step) => step.callType === "step");
3551
3677
  const otherSteps = stepsToDecode.map((rawStep) => {
3552
3678
  const step = JSON.parse(decodeBase64(rawStep.body));
3553
- if (step.waitEventId) {
3554
- const newOut = {
3555
- eventData: step.out ? decodeBase64(step.out) : void 0,
3556
- timeout: step.waitTimeout ?? false
3557
- };
3558
- step.out = newOut;
3559
- }
3560
3679
  return step;
3561
3680
  });
3562
3681
  const steps = [initialStep, ...otherSteps];
package/h3.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  SDK_TELEMETRY,
3
3
  serveBase,
4
4
  serveManyBase
5
- } from "./chunk-BON2RKOR.mjs";
5
+ } from "./chunk-KAGTWBLF.mjs";
6
6
 
7
7
  // node_modules/defu/dist/defu.mjs
8
8
  function isPlainObject(value) {
package/hono.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Context } from 'hono';
2
- import { R as RouteFunction, o as PublicServeOptions, z as InvokableWorkflow } from './types-9nCq6bRP.mjs';
2
+ import { R as RouteFunction, o as PublicServeOptions, z as InvokableWorkflow } from './types-BD06btU6.mjs';
3
3
  import { Variables } from 'hono/types';
4
- import { s as serveManyBase } from './serve-many-CctdYIfB.mjs';
4
+ import { s as serveManyBase } from './serve-many-B5Vbacm6.mjs';
5
5
  import '@upstash/qstash';
6
6
  import 'zod';
7
7
  import 'ai';
package/hono.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Context } from 'hono';
2
- import { R as RouteFunction, o as PublicServeOptions, z as InvokableWorkflow } from './types-9nCq6bRP.js';
2
+ import { R as RouteFunction, o as PublicServeOptions, z as InvokableWorkflow } from './types-BD06btU6.js';
3
3
  import { Variables } from 'hono/types';
4
- import { s as serveManyBase } from './serve-many-BXDr30rl.js';
4
+ import { s as serveManyBase } from './serve-many-BCV7INWe.js';
5
5
  import '@upstash/qstash';
6
6
  import 'zod';
7
7
  import 'ai';