@upstash/workflow 0.2.10 → 0.2.11

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.
@@ -114,15 +114,15 @@ function getWorkflowRunId(id) {
114
114
  return `wfr_${id ?? nanoid()}`;
115
115
  }
116
116
  function decodeBase64(base64) {
117
+ const binString = atob(base64);
117
118
  try {
118
- const binString = atob(base64);
119
119
  const intArray = Uint8Array.from(binString, (m) => m.codePointAt(0));
120
120
  return new TextDecoder().decode(intArray);
121
121
  } catch (error) {
122
122
  console.warn(
123
123
  `Upstash Qstash: Failed while decoding base64 "${base64}". Decoding with atob and returning it instead. ${error}`
124
124
  );
125
- return atob(base64);
125
+ return binString;
126
126
  }
127
127
  }
128
128
 
@@ -859,7 +859,8 @@ var getHeaders = ({
859
859
  flowControl,
860
860
  callFlowControl
861
861
  }) => {
862
- const contentType = (userHeaders ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
862
+ const callHeaders = new Headers(step?.callHeaders);
863
+ const contentType = (callHeaders.get("content-type") ? callHeaders.get("content-type") : userHeaders?.get("Content-Type") ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
863
864
  const baseHeaders = {
864
865
  [WORKFLOW_INIT_HEADER]: initHeaderValue,
865
866
  [WORKFLOW_ID_HEADER]: workflowRunId,
@@ -1290,9 +1291,8 @@ var WorkflowTool = class {
1290
1291
  };
1291
1292
 
1292
1293
  // src/context/steps.ts
1293
- var BaseLazyStep = class {
1294
+ var BaseLazyStep = class _BaseLazyStep {
1294
1295
  stepName;
1295
- // will be set in the subclasses
1296
1296
  constructor(stepName) {
1297
1297
  if (!stepName) {
1298
1298
  throw new WorkflowError(
@@ -1301,10 +1301,58 @@ var BaseLazyStep = class {
1301
1301
  }
1302
1302
  this.stepName = stepName;
1303
1303
  }
1304
+ /**
1305
+ * parse the out field of a step result.
1306
+ *
1307
+ * will be called when returning the steps to the context from auto executor
1308
+ *
1309
+ * @param out field of the step
1310
+ * @returns parsed out field
1311
+ */
1312
+ parseOut(out) {
1313
+ if (out === void 0) {
1314
+ if (this.allowUndefinedOut) {
1315
+ return void 0;
1316
+ } else {
1317
+ throw new WorkflowError(
1318
+ `Error while parsing output of ${this.stepType} step. Expected a string, but got: undefined`
1319
+ );
1320
+ }
1321
+ }
1322
+ if (typeof out === "object") {
1323
+ if (this.stepType !== "Wait") {
1324
+ console.warn(
1325
+ `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
1326
+ );
1327
+ return out;
1328
+ }
1329
+ return {
1330
+ ...out,
1331
+ eventData: _BaseLazyStep.tryParsing(out.eventData)
1332
+ };
1333
+ }
1334
+ if (typeof out !== "string") {
1335
+ throw new WorkflowError(
1336
+ `Error while parsing output of ${this.stepType} step. Expected a string or undefined, but got: ${typeof out}`
1337
+ );
1338
+ }
1339
+ return this.safeParseOut(out);
1340
+ }
1341
+ safeParseOut(out) {
1342
+ return _BaseLazyStep.tryParsing(out);
1343
+ }
1344
+ static tryParsing(stepOut) {
1345
+ try {
1346
+ return JSON.parse(stepOut);
1347
+ } catch {
1348
+ return stepOut;
1349
+ }
1350
+ }
1304
1351
  };
1305
1352
  var LazyFunctionStep = class extends BaseLazyStep {
1306
1353
  stepFunction;
1307
1354
  stepType = "Run";
1355
+ allowUndefinedOut = true;
1308
1356
  constructor(stepName, stepFunction) {
1309
1357
  super(stepName);
1310
1358
  this.stepFunction = stepFunction;
@@ -1335,6 +1383,7 @@ var LazyFunctionStep = class extends BaseLazyStep {
1335
1383
  var LazySleepStep = class extends BaseLazyStep {
1336
1384
  sleep;
1337
1385
  stepType = "SleepFor";
1386
+ allowUndefinedOut = true;
1338
1387
  constructor(stepName, sleep) {
1339
1388
  super(stepName);
1340
1389
  this.sleep = sleep;
@@ -1362,6 +1411,7 @@ var LazySleepStep = class extends BaseLazyStep {
1362
1411
  var LazySleepUntilStep = class extends BaseLazyStep {
1363
1412
  sleepUntil;
1364
1413
  stepType = "SleepUntil";
1414
+ allowUndefinedOut = true;
1365
1415
  constructor(stepName, sleepUntil) {
1366
1416
  super(stepName);
1367
1417
  this.sleepUntil = sleepUntil;
@@ -1385,8 +1435,11 @@ var LazySleepUntilStep = class extends BaseLazyStep {
1385
1435
  concurrent
1386
1436
  });
1387
1437
  }
1438
+ safeParseOut() {
1439
+ return void 0;
1440
+ }
1388
1441
  };
1389
- var LazyCallStep = class extends BaseLazyStep {
1442
+ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1390
1443
  url;
1391
1444
  method;
1392
1445
  body;
@@ -1395,6 +1448,7 @@ var LazyCallStep = class extends BaseLazyStep {
1395
1448
  timeout;
1396
1449
  flowControl;
1397
1450
  stepType = "Call";
1451
+ allowUndefinedOut = false;
1398
1452
  constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
1399
1453
  super(stepName);
1400
1454
  this.url = url;
@@ -1426,11 +1480,53 @@ var LazyCallStep = class extends BaseLazyStep {
1426
1480
  callHeaders: this.headers
1427
1481
  });
1428
1482
  }
1483
+ safeParseOut(out) {
1484
+ const { header, status, body } = JSON.parse(out);
1485
+ const responseHeaders = new Headers(header);
1486
+ if (_LazyCallStep.isText(responseHeaders.get("content-type"))) {
1487
+ const bytes = new Uint8Array(out.length);
1488
+ for (let i = 0; i < out.length; i++) {
1489
+ bytes[i] = out.charCodeAt(i);
1490
+ }
1491
+ const processedResult = new TextDecoder().decode(bytes);
1492
+ const newBody = JSON.parse(processedResult).body;
1493
+ return {
1494
+ status,
1495
+ header,
1496
+ body: BaseLazyStep.tryParsing(newBody)
1497
+ };
1498
+ } else {
1499
+ return { header, status, body };
1500
+ }
1501
+ }
1502
+ static applicationHeaders = /* @__PURE__ */ new Set([
1503
+ "application/json",
1504
+ "application/xml",
1505
+ "application/javascript",
1506
+ "application/x-www-form-urlencoded",
1507
+ "application/xhtml+xml",
1508
+ "application/ld+json",
1509
+ "application/rss+xml",
1510
+ "application/atom+xml"
1511
+ ]);
1512
+ static isText = (contentTypeHeader) => {
1513
+ if (!contentTypeHeader) {
1514
+ return false;
1515
+ }
1516
+ if (_LazyCallStep.applicationHeaders.has(contentTypeHeader)) {
1517
+ return true;
1518
+ }
1519
+ if (contentTypeHeader.startsWith("text/")) {
1520
+ return true;
1521
+ }
1522
+ return false;
1523
+ };
1429
1524
  };
1430
1525
  var LazyWaitForEventStep = class extends BaseLazyStep {
1431
1526
  eventId;
1432
1527
  timeout;
1433
1528
  stepType = "Wait";
1529
+ allowUndefinedOut = false;
1434
1530
  constructor(stepName, eventId, timeout) {
1435
1531
  super(stepName);
1436
1532
  this.eventId = eventId;
@@ -1457,6 +1553,13 @@ var LazyWaitForEventStep = class extends BaseLazyStep {
1457
1553
  concurrent
1458
1554
  });
1459
1555
  }
1556
+ safeParseOut(out) {
1557
+ const result = JSON.parse(out);
1558
+ return {
1559
+ ...result,
1560
+ eventData: BaseLazyStep.tryParsing(result.eventData)
1561
+ };
1562
+ }
1460
1563
  };
1461
1564
  var LazyNotifyStep = class extends LazyFunctionStep {
1462
1565
  stepType = "Notify";
@@ -1470,10 +1573,18 @@ var LazyNotifyStep = class extends LazyFunctionStep {
1470
1573
  };
1471
1574
  });
1472
1575
  }
1576
+ safeParseOut(out) {
1577
+ const result = JSON.parse(out);
1578
+ return {
1579
+ ...result,
1580
+ eventData: BaseLazyStep.tryParsing(result.eventData)
1581
+ };
1582
+ }
1473
1583
  };
1474
1584
  var LazyInvokeStep = class extends BaseLazyStep {
1475
1585
  stepType = "Invoke";
1476
1586
  params;
1587
+ allowUndefinedOut = false;
1477
1588
  constructor(stepName, {
1478
1589
  workflow,
1479
1590
  body,
@@ -1513,6 +1624,13 @@ var LazyInvokeStep = class extends BaseLazyStep {
1513
1624
  concurrent
1514
1625
  });
1515
1626
  }
1627
+ safeParseOut(out) {
1628
+ const result = JSON.parse(out);
1629
+ return {
1630
+ ...result,
1631
+ body: BaseLazyStep.tryParsing(result.body)
1632
+ };
1633
+ }
1516
1634
  };
1517
1635
 
1518
1636
  // src/context/auto-executor.ts
@@ -1618,7 +1736,7 @@ var AutoExecutor = class _AutoExecutor {
1618
1736
  step,
1619
1737
  stepCount: this.stepCount
1620
1738
  });
1621
- return step.out;
1739
+ return lazyStep.parseOut(step.out);
1622
1740
  }
1623
1741
  const resultStep = await lazyStep.getResultStep(NO_CONCURRENCY, this.stepCount);
1624
1742
  await this.debug?.log("INFO", "RUN_SINGLE", {
@@ -1693,7 +1811,9 @@ var AutoExecutor = class _AutoExecutor {
1693
1811
  case "last": {
1694
1812
  const parallelResultSteps = sortedSteps.filter((step) => step.stepId >= initialStepCount).slice(0, parallelSteps.length);
1695
1813
  validateParallelSteps(parallelSteps, parallelResultSteps);
1696
- return parallelResultSteps.map((step) => step.out);
1814
+ return parallelResultSteps.map(
1815
+ (step, index) => parallelSteps[index].parseOut(step.out)
1816
+ );
1697
1817
  }
1698
1818
  }
1699
1819
  const fillValue = void 0;
@@ -1796,7 +1916,7 @@ var AutoExecutor = class _AutoExecutor {
1796
1916
  });
1797
1917
  throw new WorkflowAbort(invokeStep.stepName, invokeStep);
1798
1918
  }
1799
- const result = await this.context.qstashClient.batchJSON(
1919
+ const result = await this.context.qstashClient.batch(
1800
1920
  steps.map((singleStep, index) => {
1801
1921
  const lazyStep = lazySteps[index];
1802
1922
  const { headers } = getHeaders({
@@ -1826,7 +1946,7 @@ var AutoExecutor = class _AutoExecutor {
1826
1946
  {
1827
1947
  headers,
1828
1948
  method: singleStep.callMethod,
1829
- body: singleStep.callBody,
1949
+ body: JSON.stringify(singleStep.callBody),
1830
1950
  url: singleStep.callUrl
1831
1951
  }
1832
1952
  ) : (
@@ -1836,7 +1956,7 @@ var AutoExecutor = class _AutoExecutor {
1836
1956
  {
1837
1957
  headers,
1838
1958
  method: "POST",
1839
- body: singleStep,
1959
+ body: JSON.stringify(singleStep),
1840
1960
  url: this.context.url,
1841
1961
  notBefore: willWait ? singleStep.sleepUntil : void 0,
1842
1962
  delay: willWait ? singleStep.sleepFor : void 0
@@ -1844,8 +1964,9 @@ var AutoExecutor = class _AutoExecutor {
1844
1964
  );
1845
1965
  })
1846
1966
  );
1967
+ const _result = result;
1847
1968
  await this.debug?.log("INFO", "SUBMIT_STEP", {
1848
- messageIds: result.map((message) => {
1969
+ messageIds: _result.map((message) => {
1849
1970
  return {
1850
1971
  message: message.messageId
1851
1972
  };
@@ -2441,7 +2562,7 @@ var WorkflowContext = class {
2441
2562
  */
2442
2563
  async run(stepName, stepFunction) {
2443
2564
  const wrappedStepFunction = () => this.executor.wrapStep(stepName, stepFunction);
2444
- return this.addStep(new LazyFunctionStep(stepName, wrappedStepFunction));
2565
+ return await this.addStep(new LazyFunctionStep(stepName, wrappedStepFunction));
2445
2566
  }
2446
2567
  /**
2447
2568
  * Stops the execution for the duration provided.
@@ -2512,43 +2633,27 @@ var WorkflowContext = class {
2512
2633
  * }
2513
2634
  */
2514
2635
  async call(stepName, settings) {
2515
- const { url, method = "GET", body, headers = {}, retries = 0, timeout, flowControl } = settings;
2516
- const result = await this.addStep(
2636
+ const {
2637
+ url,
2638
+ method = "GET",
2639
+ body: requestBody,
2640
+ headers = {},
2641
+ retries = 0,
2642
+ timeout,
2643
+ flowControl
2644
+ } = settings;
2645
+ return await this.addStep(
2517
2646
  new LazyCallStep(
2518
2647
  stepName,
2519
2648
  url,
2520
2649
  method,
2521
- body,
2650
+ requestBody,
2522
2651
  headers,
2523
2652
  retries,
2524
2653
  timeout,
2525
2654
  flowControl
2526
2655
  )
2527
2656
  );
2528
- if (typeof result === "string") {
2529
- try {
2530
- const body2 = JSON.parse(result);
2531
- return {
2532
- status: 200,
2533
- header: {},
2534
- body: body2
2535
- };
2536
- } catch {
2537
- return {
2538
- status: 200,
2539
- header: {},
2540
- body: result
2541
- };
2542
- }
2543
- }
2544
- try {
2545
- return {
2546
- ...result,
2547
- body: JSON.parse(result.body)
2548
- };
2549
- } catch {
2550
- return result;
2551
- }
2552
2657
  }
2553
2658
  /**
2554
2659
  * Pauses workflow execution until a specific event occurs or a timeout is reached.
@@ -2587,15 +2692,7 @@ var WorkflowContext = class {
2587
2692
  async waitForEvent(stepName, eventId, options = {}) {
2588
2693
  const { timeout = "7d" } = options;
2589
2694
  const timeoutStr = typeof timeout === "string" ? timeout : `${timeout}s`;
2590
- const result = await this.addStep(new LazyWaitForEventStep(stepName, eventId, timeoutStr));
2591
- try {
2592
- return {
2593
- ...result,
2594
- eventData: JSON.parse(result.eventData)
2595
- };
2596
- } catch {
2597
- return result;
2598
- }
2695
+ return await this.addStep(new LazyWaitForEventStep(stepName, eventId, timeoutStr));
2599
2696
  }
2600
2697
  /**
2601
2698
  * Notify workflow runs waiting for an event
@@ -2619,24 +2716,12 @@ var WorkflowContext = class {
2619
2716
  * @returns notify response which has event id, event data and list of waiters which were notified
2620
2717
  */
2621
2718
  async notify(stepName, eventId, eventData) {
2622
- const result = await this.addStep(
2719
+ return await this.addStep(
2623
2720
  new LazyNotifyStep(stepName, eventId, eventData, this.qstashClient.http)
2624
2721
  );
2625
- try {
2626
- return {
2627
- ...result,
2628
- eventData: JSON.parse(result.eventData)
2629
- };
2630
- } catch {
2631
- return result;
2632
- }
2633
2722
  }
2634
2723
  async invoke(stepName, settings) {
2635
- const result = await this.addStep(new LazyInvokeStep(stepName, settings));
2636
- return {
2637
- ...result,
2638
- body: result.body ? JSON.parse(result.body) : void 0
2639
- };
2724
+ return await this.addStep(new LazyInvokeStep(stepName, settings));
2640
2725
  }
2641
2726
  /**
2642
2727
  * Cancel the current workflow run
@@ -2795,10 +2880,6 @@ var processRawSteps = (rawSteps) => {
2795
2880
  const stepsToDecode = encodedSteps.filter((step) => step.callType === "step");
2796
2881
  const otherSteps = stepsToDecode.map((rawStep) => {
2797
2882
  const step = JSON.parse(decodeBase64(rawStep.body));
2798
- try {
2799
- step.out = JSON.parse(step.out);
2800
- } catch {
2801
- }
2802
2883
  if (step.waitEventId) {
2803
2884
  const newOut = {
2804
2885
  eventData: step.out ? decodeBase64(step.out) : void 0,
package/cloudflare.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as RouteFunction, k as PublicServeOptions, t as InvokableWorkflow } from './types-CYhDXnf8.mjs';
2
- import { s as serveManyBase } from './serve-many-BVDpPsF-.mjs';
1
+ import { R as RouteFunction, k as PublicServeOptions, t as InvokableWorkflow } from './types-DS9q8FyV.mjs';
2
+ import { s as serveManyBase } from './serve-many-Fuovl7gl.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, k as PublicServeOptions, t as InvokableWorkflow } from './types-CYhDXnf8.js';
2
- import { s as serveManyBase } from './serve-many-e4zufyXN.js';
1
+ import { R as RouteFunction, k as PublicServeOptions, t as InvokableWorkflow } from './types-DS9q8FyV.js';
2
+ import { s as serveManyBase } from './serve-many-DNnLsDIp.js';
3
3
  import '@upstash/qstash';
4
4
  import 'zod';
5
5
  import 'ai';