@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.
package/nextjs.js CHANGED
@@ -154,22 +154,21 @@ function getWorkflowRunId(id) {
154
154
  return `wfr_${id ?? nanoid()}`;
155
155
  }
156
156
  function decodeBase64(base64) {
157
+ const binString = atob(base64);
157
158
  try {
158
- const binString = atob(base64);
159
159
  const intArray = Uint8Array.from(binString, (m) => m.codePointAt(0));
160
160
  return new TextDecoder().decode(intArray);
161
161
  } catch (error) {
162
162
  console.warn(
163
163
  `Upstash Qstash: Failed while decoding base64 "${base64}". Decoding with atob and returning it instead. ${error}`
164
164
  );
165
- return atob(base64);
165
+ return binString;
166
166
  }
167
167
  }
168
168
 
169
169
  // src/context/steps.ts
170
- var BaseLazyStep = class {
170
+ var BaseLazyStep = class _BaseLazyStep {
171
171
  stepName;
172
- // will be set in the subclasses
173
172
  constructor(stepName) {
174
173
  if (!stepName) {
175
174
  throw new WorkflowError(
@@ -178,10 +177,58 @@ var BaseLazyStep = class {
178
177
  }
179
178
  this.stepName = stepName;
180
179
  }
180
+ /**
181
+ * parse the out field of a step result.
182
+ *
183
+ * will be called when returning the steps to the context from auto executor
184
+ *
185
+ * @param out field of the step
186
+ * @returns parsed out field
187
+ */
188
+ parseOut(out) {
189
+ if (out === void 0) {
190
+ if (this.allowUndefinedOut) {
191
+ return void 0;
192
+ } else {
193
+ throw new WorkflowError(
194
+ `Error while parsing output of ${this.stepType} step. Expected a string, but got: undefined`
195
+ );
196
+ }
197
+ }
198
+ if (typeof out === "object") {
199
+ if (this.stepType !== "Wait") {
200
+ console.warn(
201
+ `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
202
+ );
203
+ return out;
204
+ }
205
+ return {
206
+ ...out,
207
+ eventData: _BaseLazyStep.tryParsing(out.eventData)
208
+ };
209
+ }
210
+ if (typeof out !== "string") {
211
+ throw new WorkflowError(
212
+ `Error while parsing output of ${this.stepType} step. Expected a string or undefined, but got: ${typeof out}`
213
+ );
214
+ }
215
+ return this.safeParseOut(out);
216
+ }
217
+ safeParseOut(out) {
218
+ return _BaseLazyStep.tryParsing(out);
219
+ }
220
+ static tryParsing(stepOut) {
221
+ try {
222
+ return JSON.parse(stepOut);
223
+ } catch {
224
+ return stepOut;
225
+ }
226
+ }
181
227
  };
182
228
  var LazyFunctionStep = class extends BaseLazyStep {
183
229
  stepFunction;
184
230
  stepType = "Run";
231
+ allowUndefinedOut = true;
185
232
  constructor(stepName, stepFunction) {
186
233
  super(stepName);
187
234
  this.stepFunction = stepFunction;
@@ -212,6 +259,7 @@ var LazyFunctionStep = class extends BaseLazyStep {
212
259
  var LazySleepStep = class extends BaseLazyStep {
213
260
  sleep;
214
261
  stepType = "SleepFor";
262
+ allowUndefinedOut = true;
215
263
  constructor(stepName, sleep) {
216
264
  super(stepName);
217
265
  this.sleep = sleep;
@@ -239,6 +287,7 @@ var LazySleepStep = class extends BaseLazyStep {
239
287
  var LazySleepUntilStep = class extends BaseLazyStep {
240
288
  sleepUntil;
241
289
  stepType = "SleepUntil";
290
+ allowUndefinedOut = true;
242
291
  constructor(stepName, sleepUntil) {
243
292
  super(stepName);
244
293
  this.sleepUntil = sleepUntil;
@@ -262,8 +311,11 @@ var LazySleepUntilStep = class extends BaseLazyStep {
262
311
  concurrent
263
312
  });
264
313
  }
314
+ safeParseOut() {
315
+ return void 0;
316
+ }
265
317
  };
266
- var LazyCallStep = class extends BaseLazyStep {
318
+ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
267
319
  url;
268
320
  method;
269
321
  body;
@@ -272,6 +324,7 @@ var LazyCallStep = class extends BaseLazyStep {
272
324
  timeout;
273
325
  flowControl;
274
326
  stepType = "Call";
327
+ allowUndefinedOut = false;
275
328
  constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
276
329
  super(stepName);
277
330
  this.url = url;
@@ -303,11 +356,53 @@ var LazyCallStep = class extends BaseLazyStep {
303
356
  callHeaders: this.headers
304
357
  });
305
358
  }
359
+ safeParseOut(out) {
360
+ const { header, status, body } = JSON.parse(out);
361
+ const responseHeaders = new Headers(header);
362
+ if (_LazyCallStep.isText(responseHeaders.get("content-type"))) {
363
+ const bytes = new Uint8Array(out.length);
364
+ for (let i = 0; i < out.length; i++) {
365
+ bytes[i] = out.charCodeAt(i);
366
+ }
367
+ const processedResult = new TextDecoder().decode(bytes);
368
+ const newBody = JSON.parse(processedResult).body;
369
+ return {
370
+ status,
371
+ header,
372
+ body: BaseLazyStep.tryParsing(newBody)
373
+ };
374
+ } else {
375
+ return { header, status, body };
376
+ }
377
+ }
378
+ static applicationHeaders = /* @__PURE__ */ new Set([
379
+ "application/json",
380
+ "application/xml",
381
+ "application/javascript",
382
+ "application/x-www-form-urlencoded",
383
+ "application/xhtml+xml",
384
+ "application/ld+json",
385
+ "application/rss+xml",
386
+ "application/atom+xml"
387
+ ]);
388
+ static isText = (contentTypeHeader) => {
389
+ if (!contentTypeHeader) {
390
+ return false;
391
+ }
392
+ if (_LazyCallStep.applicationHeaders.has(contentTypeHeader)) {
393
+ return true;
394
+ }
395
+ if (contentTypeHeader.startsWith("text/")) {
396
+ return true;
397
+ }
398
+ return false;
399
+ };
306
400
  };
307
401
  var LazyWaitForEventStep = class extends BaseLazyStep {
308
402
  eventId;
309
403
  timeout;
310
404
  stepType = "Wait";
405
+ allowUndefinedOut = false;
311
406
  constructor(stepName, eventId, timeout) {
312
407
  super(stepName);
313
408
  this.eventId = eventId;
@@ -334,6 +429,13 @@ var LazyWaitForEventStep = class extends BaseLazyStep {
334
429
  concurrent
335
430
  });
336
431
  }
432
+ safeParseOut(out) {
433
+ const result = JSON.parse(out);
434
+ return {
435
+ ...result,
436
+ eventData: BaseLazyStep.tryParsing(result.eventData)
437
+ };
438
+ }
337
439
  };
338
440
  var LazyNotifyStep = class extends LazyFunctionStep {
339
441
  stepType = "Notify";
@@ -347,10 +449,18 @@ var LazyNotifyStep = class extends LazyFunctionStep {
347
449
  };
348
450
  });
349
451
  }
452
+ safeParseOut(out) {
453
+ const result = JSON.parse(out);
454
+ return {
455
+ ...result,
456
+ eventData: BaseLazyStep.tryParsing(result.eventData)
457
+ };
458
+ }
350
459
  };
351
460
  var LazyInvokeStep = class extends BaseLazyStep {
352
461
  stepType = "Invoke";
353
462
  params;
463
+ allowUndefinedOut = false;
354
464
  constructor(stepName, {
355
465
  workflow,
356
466
  body,
@@ -390,6 +500,13 @@ var LazyInvokeStep = class extends BaseLazyStep {
390
500
  concurrent
391
501
  });
392
502
  }
503
+ safeParseOut(out) {
504
+ const result = JSON.parse(out);
505
+ return {
506
+ ...result,
507
+ body: BaseLazyStep.tryParsing(result.body)
508
+ };
509
+ }
393
510
  };
394
511
 
395
512
  // node_modules/neverthrow/dist/index.es.js
@@ -1075,7 +1192,8 @@ var getHeaders = ({
1075
1192
  flowControl,
1076
1193
  callFlowControl
1077
1194
  }) => {
1078
- const contentType = (userHeaders ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
1195
+ const callHeaders = new Headers(step?.callHeaders);
1196
+ const contentType = (callHeaders.get("content-type") ? callHeaders.get("content-type") : userHeaders?.get("Content-Type") ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
1079
1197
  const baseHeaders = {
1080
1198
  [WORKFLOW_INIT_HEADER]: initHeaderValue,
1081
1199
  [WORKFLOW_ID_HEADER]: workflowRunId,
@@ -1486,7 +1604,7 @@ var AutoExecutor = class _AutoExecutor {
1486
1604
  step,
1487
1605
  stepCount: this.stepCount
1488
1606
  });
1489
- return step.out;
1607
+ return lazyStep.parseOut(step.out);
1490
1608
  }
1491
1609
  const resultStep = await lazyStep.getResultStep(NO_CONCURRENCY, this.stepCount);
1492
1610
  await this.debug?.log("INFO", "RUN_SINGLE", {
@@ -1561,7 +1679,9 @@ var AutoExecutor = class _AutoExecutor {
1561
1679
  case "last": {
1562
1680
  const parallelResultSteps = sortedSteps.filter((step) => step.stepId >= initialStepCount).slice(0, parallelSteps.length);
1563
1681
  validateParallelSteps(parallelSteps, parallelResultSteps);
1564
- return parallelResultSteps.map((step) => step.out);
1682
+ return parallelResultSteps.map(
1683
+ (step, index) => parallelSteps[index].parseOut(step.out)
1684
+ );
1565
1685
  }
1566
1686
  }
1567
1687
  const fillValue = void 0;
@@ -1664,7 +1784,7 @@ var AutoExecutor = class _AutoExecutor {
1664
1784
  });
1665
1785
  throw new WorkflowAbort(invokeStep.stepName, invokeStep);
1666
1786
  }
1667
- const result = await this.context.qstashClient.batchJSON(
1787
+ const result = await this.context.qstashClient.batch(
1668
1788
  steps.map((singleStep, index) => {
1669
1789
  const lazyStep = lazySteps[index];
1670
1790
  const { headers } = getHeaders({
@@ -1694,7 +1814,7 @@ var AutoExecutor = class _AutoExecutor {
1694
1814
  {
1695
1815
  headers,
1696
1816
  method: singleStep.callMethod,
1697
- body: singleStep.callBody,
1817
+ body: JSON.stringify(singleStep.callBody),
1698
1818
  url: singleStep.callUrl
1699
1819
  }
1700
1820
  ) : (
@@ -1704,7 +1824,7 @@ var AutoExecutor = class _AutoExecutor {
1704
1824
  {
1705
1825
  headers,
1706
1826
  method: "POST",
1707
- body: singleStep,
1827
+ body: JSON.stringify(singleStep),
1708
1828
  url: this.context.url,
1709
1829
  notBefore: willWait ? singleStep.sleepUntil : void 0,
1710
1830
  delay: willWait ? singleStep.sleepFor : void 0
@@ -1712,8 +1832,9 @@ var AutoExecutor = class _AutoExecutor {
1712
1832
  );
1713
1833
  })
1714
1834
  );
1835
+ const _result = result;
1715
1836
  await this.debug?.log("INFO", "SUBMIT_STEP", {
1716
- messageIds: result.map((message) => {
1837
+ messageIds: _result.map((message) => {
1717
1838
  return {
1718
1839
  message: message.messageId
1719
1840
  };
@@ -2402,7 +2523,7 @@ var WorkflowContext = class {
2402
2523
  */
2403
2524
  async run(stepName, stepFunction) {
2404
2525
  const wrappedStepFunction = () => this.executor.wrapStep(stepName, stepFunction);
2405
- return this.addStep(new LazyFunctionStep(stepName, wrappedStepFunction));
2526
+ return await this.addStep(new LazyFunctionStep(stepName, wrappedStepFunction));
2406
2527
  }
2407
2528
  /**
2408
2529
  * Stops the execution for the duration provided.
@@ -2473,43 +2594,27 @@ var WorkflowContext = class {
2473
2594
  * }
2474
2595
  */
2475
2596
  async call(stepName, settings) {
2476
- const { url, method = "GET", body, headers = {}, retries = 0, timeout, flowControl } = settings;
2477
- const result = await this.addStep(
2597
+ const {
2598
+ url,
2599
+ method = "GET",
2600
+ body: requestBody,
2601
+ headers = {},
2602
+ retries = 0,
2603
+ timeout,
2604
+ flowControl
2605
+ } = settings;
2606
+ return await this.addStep(
2478
2607
  new LazyCallStep(
2479
2608
  stepName,
2480
2609
  url,
2481
2610
  method,
2482
- body,
2611
+ requestBody,
2483
2612
  headers,
2484
2613
  retries,
2485
2614
  timeout,
2486
2615
  flowControl
2487
2616
  )
2488
2617
  );
2489
- if (typeof result === "string") {
2490
- try {
2491
- const body2 = JSON.parse(result);
2492
- return {
2493
- status: 200,
2494
- header: {},
2495
- body: body2
2496
- };
2497
- } catch {
2498
- return {
2499
- status: 200,
2500
- header: {},
2501
- body: result
2502
- };
2503
- }
2504
- }
2505
- try {
2506
- return {
2507
- ...result,
2508
- body: JSON.parse(result.body)
2509
- };
2510
- } catch {
2511
- return result;
2512
- }
2513
2618
  }
2514
2619
  /**
2515
2620
  * Pauses workflow execution until a specific event occurs or a timeout is reached.
@@ -2548,15 +2653,7 @@ var WorkflowContext = class {
2548
2653
  async waitForEvent(stepName, eventId, options = {}) {
2549
2654
  const { timeout = "7d" } = options;
2550
2655
  const timeoutStr = typeof timeout === "string" ? timeout : `${timeout}s`;
2551
- const result = await this.addStep(new LazyWaitForEventStep(stepName, eventId, timeoutStr));
2552
- try {
2553
- return {
2554
- ...result,
2555
- eventData: JSON.parse(result.eventData)
2556
- };
2557
- } catch {
2558
- return result;
2559
- }
2656
+ return await this.addStep(new LazyWaitForEventStep(stepName, eventId, timeoutStr));
2560
2657
  }
2561
2658
  /**
2562
2659
  * Notify workflow runs waiting for an event
@@ -2580,24 +2677,12 @@ var WorkflowContext = class {
2580
2677
  * @returns notify response which has event id, event data and list of waiters which were notified
2581
2678
  */
2582
2679
  async notify(stepName, eventId, eventData) {
2583
- const result = await this.addStep(
2680
+ return await this.addStep(
2584
2681
  new LazyNotifyStep(stepName, eventId, eventData, this.qstashClient.http)
2585
2682
  );
2586
- try {
2587
- return {
2588
- ...result,
2589
- eventData: JSON.parse(result.eventData)
2590
- };
2591
- } catch {
2592
- return result;
2593
- }
2594
2683
  }
2595
2684
  async invoke(stepName, settings) {
2596
- const result = await this.addStep(new LazyInvokeStep(stepName, settings));
2597
- return {
2598
- ...result,
2599
- body: result.body ? JSON.parse(result.body) : void 0
2600
- };
2685
+ return await this.addStep(new LazyInvokeStep(stepName, settings));
2601
2686
  }
2602
2687
  /**
2603
2688
  * Cancel the current workflow run
@@ -2756,10 +2841,6 @@ var processRawSteps = (rawSteps) => {
2756
2841
  const stepsToDecode = encodedSteps.filter((step) => step.callType === "step");
2757
2842
  const otherSteps = stepsToDecode.map((rawStep) => {
2758
2843
  const step = JSON.parse(decodeBase64(rawStep.body));
2759
- try {
2760
- step.out = JSON.parse(step.out);
2761
- } catch {
2762
- }
2763
2844
  if (step.waitEventId) {
2764
2845
  const newOut = {
2765
2846
  eventData: step.out ? decodeBase64(step.out) : void 0,
package/nextjs.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  SDK_TELEMETRY,
3
3
  serveBase,
4
4
  serveManyBase
5
- } from "./chunk-GFNR743S.mjs";
5
+ } from "./chunk-WQAJ2RSZ.mjs";
6
6
 
7
7
  // platforms/nextjs.ts
8
8
  var appTelemetry = {
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@upstash/workflow","version":"v0.2.10","description":"Durable, Reliable and Performant Serverless Functions","main":"./index.js","module":"./index.mjs","types":"./index.d.ts","files":["./*"],"exports":{".":{"import":"./index.mjs","require":"./index.js"},"./dist/nextjs":{"import":"./nextjs.mjs","require":"./nextjs.js"},"./nextjs":{"import":"./nextjs.mjs","require":"./nextjs.js"},"./h3":{"import":"./h3.mjs","require":"./h3.js"},"./svelte":{"import":"./svelte.mjs","require":"./svelte.js"},"./solidjs":{"import":"./solidjs.mjs","require":"./solidjs.js"},"./workflow":{"import":"./workflow.mjs","require":"./workflow.js"},"./hono":{"import":"./hono.mjs","require":"./hono.js"},"./cloudflare":{"import":"./cloudflare.mjs","require":"./cloudflare.js"},"./astro":{"import":"./astro.mjs","require":"./astro.js"},"./express":{"import":"./express.mjs","require":"./express.js"}},"scripts":{"build":"tsup && cp README.md ./dist/ && cp package.json ./dist/ && cp LICENSE ./dist/","test":"bun test src","fmt":"prettier --write .","lint":"tsc && eslint \"{src,platforms}/**/*.{js,ts,tsx}\" --quiet --fix","check-exports":"bun run build && cd dist && attw -P"},"repository":{"type":"git","url":"git+https://github.com/upstash/workflow-ts.git"},"keywords":["upstash","qstash","workflow","serverless"],"author":"Cahid Arda Oz","license":"MIT","bugs":{"url":"https://github.com/upstash/workflow-ts/issues"},"homepage":"https://github.com/upstash/workflow-ts#readme","devDependencies":{"@commitlint/cli":"^19.5.0","@commitlint/config-conventional":"^19.5.0","@eslint/js":"^9.11.1","@solidjs/start":"^1.0.8","@sveltejs/kit":"^2.6.1","@types/bun":"^1.1.10","@types/express":"^5.0.0","astro":"^4.16.7","eslint":"^9.11.1","eslint-plugin-unicorn":"^55.0.0","express":"^4.21.1","globals":"^15.10.0","h3":"^1.12.0","hono":"^4.6.20","husky":"^9.1.6","next":"^14.2.14","prettier":"3.3.3","tsup":"^8.3.0","typescript":"^5.7.2","typescript-eslint":"^8.18.0"},"dependencies":{"@ai-sdk/openai":"^1.0.15","@upstash/qstash":"^2.7.22","ai":"^4.0.30","zod":"^3.24.1"},"directories":{"example":"examples"}}
1
+ {"name":"@upstash/workflow","version":"v0.2.11","description":"Durable, Reliable and Performant Serverless Functions","main":"./index.js","module":"./index.mjs","types":"./index.d.ts","files":["./*"],"exports":{".":{"import":"./index.mjs","require":"./index.js"},"./dist/nextjs":{"import":"./nextjs.mjs","require":"./nextjs.js"},"./nextjs":{"import":"./nextjs.mjs","require":"./nextjs.js"},"./h3":{"import":"./h3.mjs","require":"./h3.js"},"./svelte":{"import":"./svelte.mjs","require":"./svelte.js"},"./solidjs":{"import":"./solidjs.mjs","require":"./solidjs.js"},"./workflow":{"import":"./workflow.mjs","require":"./workflow.js"},"./hono":{"import":"./hono.mjs","require":"./hono.js"},"./cloudflare":{"import":"./cloudflare.mjs","require":"./cloudflare.js"},"./astro":{"import":"./astro.mjs","require":"./astro.js"},"./express":{"import":"./express.mjs","require":"./express.js"}},"scripts":{"build":"tsup && cp README.md ./dist/ && cp package.json ./dist/ && cp LICENSE ./dist/","test":"bun test src","fmt":"prettier --write .","lint":"tsc && eslint \"{src,platforms}/**/*.{js,ts,tsx}\" --quiet --fix","check-exports":"bun run build && cd dist && attw -P"},"repository":{"type":"git","url":"git+https://github.com/upstash/workflow-ts.git"},"keywords":["upstash","qstash","workflow","serverless"],"author":"Cahid Arda Oz","license":"MIT","bugs":{"url":"https://github.com/upstash/workflow-ts/issues"},"homepage":"https://github.com/upstash/workflow-ts#readme","devDependencies":{"@commitlint/cli":"^19.5.0","@commitlint/config-conventional":"^19.5.0","@eslint/js":"^9.11.1","@solidjs/start":"^1.0.8","@sveltejs/kit":"^2.6.1","@types/bun":"^1.1.10","@types/express":"^5.0.0","astro":"^4.16.7","eslint":"^9.11.1","eslint-plugin-unicorn":"^55.0.0","express":"^4.21.1","globals":"^15.10.0","h3":"^1.12.0","hono":"^4.6.20","husky":"^9.1.6","next":"^14.2.14","prettier":"3.3.3","tsup":"^8.3.0","typescript":"^5.7.2","typescript-eslint":"^8.18.0"},"dependencies":{"@ai-sdk/openai":"^1.0.15","@upstash/qstash":"^2.7.22","ai":"^4.0.30","zod":"^3.24.1"},"directories":{"example":"examples"}}
@@ -1,4 +1,4 @@
1
- import { k as PublicServeOptions, R as RouteFunction, t as InvokableWorkflow } from './types-CYhDXnf8.js';
1
+ import { k as PublicServeOptions, R as RouteFunction, t as InvokableWorkflow } from './types-DS9q8FyV.js';
2
2
 
3
3
  type OmitOptionsInServeMany<TOptions> = Omit<TOptions, "env" | "url" | "schema" | "initialPayloadParser">;
4
4
  declare const serveManyBase: <THandler extends (...params: any[]) => any, TOptions extends OmitOptionsInServeMany<PublicServeOptions> = OmitOptionsInServeMany<PublicServeOptions>, TServeParams extends [routeFunction: RouteFunction<any, any>, options: TOptions] = [routeFunction: RouteFunction<any, any>, options: TOptions]>({ workflows, getUrl, serveMethod, options, }: {
@@ -1,4 +1,4 @@
1
- import { k as PublicServeOptions, R as RouteFunction, t as InvokableWorkflow } from './types-CYhDXnf8.mjs';
1
+ import { k as PublicServeOptions, R as RouteFunction, t as InvokableWorkflow } from './types-DS9q8FyV.mjs';
2
2
 
3
3
  type OmitOptionsInServeMany<TOptions> = Omit<TOptions, "env" | "url" | "schema" | "initialPayloadParser">;
4
4
  declare const serveManyBase: <THandler extends (...params: any[]) => any, TOptions extends OmitOptionsInServeMany<PublicServeOptions> = OmitOptionsInServeMany<PublicServeOptions>, TServeParams extends [routeFunction: RouteFunction<any, any>, options: TOptions] = [routeFunction: RouteFunction<any, any>, options: TOptions]>({ workflows, getUrl, serveMethod, options, }: {
package/solidjs.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { APIEvent } from '@solidjs/start/server';
2
- import { R as RouteFunction, k as PublicServeOptions } from './types-CYhDXnf8.mjs';
2
+ import { R as RouteFunction, k as PublicServeOptions } from './types-DS9q8FyV.mjs';
3
3
  import '@upstash/qstash';
4
4
  import 'zod';
5
5
  import 'ai';
package/solidjs.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { APIEvent } from '@solidjs/start/server';
2
- import { R as RouteFunction, k as PublicServeOptions } from './types-CYhDXnf8.js';
2
+ import { R as RouteFunction, k as PublicServeOptions } from './types-DS9q8FyV.js';
3
3
  import '@upstash/qstash';
4
4
  import 'zod';
5
5
  import 'ai';