@upstash/qstash 2.7.0-workflow-alpha.3 → 2.7.0-workflow-alpha.4

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.
@@ -0,0 +1,81 @@
1
+ import {
2
+ Receiver,
3
+ serve
4
+ } from "./chunk-ORKD27UW.mjs";
5
+
6
+ // platforms/h3.ts
7
+ import { defineEventHandler, getHeader, readRawBody } from "h3";
8
+ var verifySignatureH3 = (handler, config) => {
9
+ const currentSigningKey = config?.currentSigningKey ?? process.env.QSTASH_CURRENT_SIGNING_KEY;
10
+ if (!currentSigningKey) {
11
+ throw new Error(
12
+ "currentSigningKey is required, either in the config or as env variable QSTASH_CURRENT_SIGNING_KEY"
13
+ );
14
+ }
15
+ const nextSigningKey = config?.nextSigningKey ?? process.env.QSTASH_NEXT_SIGNING_KEY;
16
+ if (!nextSigningKey) {
17
+ throw new Error(
18
+ "nextSigningKey is required, either in the config or as env variable QSTASH_NEXT_SIGNING_KEY"
19
+ );
20
+ }
21
+ const receiver = new Receiver({
22
+ currentSigningKey,
23
+ nextSigningKey
24
+ });
25
+ return defineEventHandler(async (event) => {
26
+ const signature = getHeader(event, "upstash-signature");
27
+ if (!signature) {
28
+ return { status: 403, body: "`Upstash-Signature` header is missing" };
29
+ }
30
+ if (typeof signature !== "string") {
31
+ throw new TypeError("`Upstash-Signature` header is not a string");
32
+ }
33
+ const body = await readRawBody(event);
34
+ const isValid = await receiver.verify({
35
+ signature,
36
+ body: JSON.stringify(body),
37
+ clockTolerance: config?.clockTolerance
38
+ });
39
+ if (!isValid) {
40
+ return { status: 403, body: "invalid signature" };
41
+ }
42
+ event._requestBody = body;
43
+ return handler(event);
44
+ });
45
+ };
46
+ function transformHeaders(headers) {
47
+ const formattedHeaders = Object.entries(headers).map(([key, value]) => [
48
+ key,
49
+ Array.isArray(value) ? value.join(", ") : value ?? ""
50
+ ]);
51
+ return formattedHeaders;
52
+ }
53
+ var serve2 = (routeFunction, options) => {
54
+ const handler = defineEventHandler(async (event) => {
55
+ const method = event.node.req.method;
56
+ if (method?.toUpperCase() !== "POST") {
57
+ return {
58
+ status: 405,
59
+ body: "Only POST requests are allowed in worklfows"
60
+ };
61
+ }
62
+ const request_ = event.node.req;
63
+ const protocol = request_.headers["x-forwarded-proto"];
64
+ const host = request_.headers.host;
65
+ const url = `${protocol}://${host}${event.path}`;
66
+ const headers = transformHeaders(request_.headers);
67
+ const request = new Request(url, {
68
+ headers,
69
+ body: await readRawBody(event),
70
+ method: "POST"
71
+ });
72
+ const serveHandler = serve(routeFunction, options);
73
+ return await serveHandler(request);
74
+ });
75
+ return handler;
76
+ };
77
+
78
+ export {
79
+ verifySignatureH3,
80
+ serve2 as serve
81
+ };
@@ -0,0 +1,81 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+ var _chunkHK2I6V52js = require('./chunk-HK2I6V52.js');
5
+
6
+ // platforms/h3.ts
7
+ var _h3 = require('h3');
8
+ var verifySignatureH3 = (handler, config) => {
9
+ const currentSigningKey = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _ => _.currentSigningKey]), () => ( process.env.QSTASH_CURRENT_SIGNING_KEY));
10
+ if (!currentSigningKey) {
11
+ throw new Error(
12
+ "currentSigningKey is required, either in the config or as env variable QSTASH_CURRENT_SIGNING_KEY"
13
+ );
14
+ }
15
+ const nextSigningKey = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _2 => _2.nextSigningKey]), () => ( process.env.QSTASH_NEXT_SIGNING_KEY));
16
+ if (!nextSigningKey) {
17
+ throw new Error(
18
+ "nextSigningKey is required, either in the config or as env variable QSTASH_NEXT_SIGNING_KEY"
19
+ );
20
+ }
21
+ const receiver = new (0, _chunkHK2I6V52js.Receiver)({
22
+ currentSigningKey,
23
+ nextSigningKey
24
+ });
25
+ return _h3.defineEventHandler.call(void 0, async (event) => {
26
+ const signature = _h3.getHeader.call(void 0, event, "upstash-signature");
27
+ if (!signature) {
28
+ return { status: 403, body: "`Upstash-Signature` header is missing" };
29
+ }
30
+ if (typeof signature !== "string") {
31
+ throw new TypeError("`Upstash-Signature` header is not a string");
32
+ }
33
+ const body = await _h3.readRawBody.call(void 0, event);
34
+ const isValid = await receiver.verify({
35
+ signature,
36
+ body: JSON.stringify(body),
37
+ clockTolerance: _optionalChain([config, 'optionalAccess', _3 => _3.clockTolerance])
38
+ });
39
+ if (!isValid) {
40
+ return { status: 403, body: "invalid signature" };
41
+ }
42
+ event._requestBody = body;
43
+ return handler(event);
44
+ });
45
+ };
46
+ function transformHeaders(headers) {
47
+ const formattedHeaders = Object.entries(headers).map(([key, value]) => [
48
+ key,
49
+ Array.isArray(value) ? value.join(", ") : _nullishCoalesce(value, () => ( ""))
50
+ ]);
51
+ return formattedHeaders;
52
+ }
53
+ var serve2 = (routeFunction, options) => {
54
+ const handler = _h3.defineEventHandler.call(void 0, async (event) => {
55
+ const method = event.node.req.method;
56
+ if (_optionalChain([method, 'optionalAccess', _4 => _4.toUpperCase, 'call', _5 => _5()]) !== "POST") {
57
+ return {
58
+ status: 405,
59
+ body: "Only POST requests are allowed in worklfows"
60
+ };
61
+ }
62
+ const request_ = event.node.req;
63
+ const protocol = request_.headers["x-forwarded-proto"];
64
+ const host = request_.headers.host;
65
+ const url = `${protocol}://${host}${event.path}`;
66
+ const headers = transformHeaders(request_.headers);
67
+ const request = new Request(url, {
68
+ headers,
69
+ body: await _h3.readRawBody.call(void 0, event),
70
+ method: "POST"
71
+ });
72
+ const serveHandler = _chunkHK2I6V52js.serve.call(void 0, routeFunction, options);
73
+ return await serveHandler(request);
74
+ });
75
+ return handler;
76
+ };
77
+
78
+
79
+
80
+
81
+ exports.verifySignatureH3 = verifySignatureH3; exports.serve = serve2;
@@ -657,6 +657,11 @@ function processHeaders(request) {
657
657
  function getRequestPath(request) {
658
658
  return _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(request.url, () => ( request.urlGroup)), () => ( request.topic)), () => ( `api/${_optionalChain([request, 'access', _28 => _28.api, 'optionalAccess', _29 => _29.name])}`));
659
659
  }
660
+ var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
661
+ var NANOID_LENGTH = 21;
662
+ function nanoid() {
663
+ return [...crypto.getRandomValues(new Uint8Array(NANOID_LENGTH))].map((x) => NANOID_CHARS[x % NANOID_CHARS.length]).join("");
664
+ }
660
665
 
661
666
  // src/client/queue.ts
662
667
  var Queue = class {
@@ -1668,9 +1673,10 @@ var getHeaders = (initHeaderValue, workflowRunId, workflowUrl, userHeaders, step
1668
1673
  };
1669
1674
  if (userHeaders) {
1670
1675
  for (const header of userHeaders.keys()) {
1671
- baseHeaders[`Upstash-Forward-${header}`] = userHeaders.get(header);
1672
1676
  if (_optionalChain([step, 'optionalAccess', _45 => _45.callHeaders])) {
1673
1677
  baseHeaders[`Upstash-Callback-Forward-${header}`] = userHeaders.get(header);
1678
+ } else {
1679
+ baseHeaders[`Upstash-Forward-${header}`] = userHeaders.get(header);
1674
1680
  }
1675
1681
  }
1676
1682
  }
@@ -1801,9 +1807,9 @@ var AutoExecutor = (_class3 = class _AutoExecutor {
1801
1807
  * @param stepFunction step function to wrap
1802
1808
  * @returns wrapped step function
1803
1809
  */
1804
- async wrapStep(stepName, stepFunction) {
1810
+ wrapStep(stepName, stepFunction) {
1805
1811
  this.executingStep = stepName;
1806
- const result = await stepFunction();
1812
+ const result = stepFunction();
1807
1813
  this.executingStep = false;
1808
1814
  return result;
1809
1815
  }
@@ -1956,7 +1962,7 @@ var AutoExecutor = (_class3 = class _AutoExecutor {
1956
1962
  "false",
1957
1963
  this.context.workflowRunId,
1958
1964
  this.context.url,
1959
- singleStep.callUrl ? void 0 : this.context.headers,
1965
+ this.context.headers,
1960
1966
  singleStep,
1961
1967
  this.context.failureUrl
1962
1968
  );
@@ -2096,7 +2102,10 @@ var LazyFunctionStep = (_class4 = class extends BaseLazyStep {
2096
2102
  }
2097
2103
  }
2098
2104
  async getResultStep(concurrent, stepId) {
2099
- const result = await this.stepFunction();
2105
+ let result = this.stepFunction();
2106
+ if (result instanceof Promise) {
2107
+ result = await result;
2108
+ }
2100
2109
  return {
2101
2110
  stepId,
2102
2111
  stepName: this.stepName,
@@ -2303,6 +2312,27 @@ var WorkflowContext = class {
2303
2312
  * initial payload as a raw string
2304
2313
  */
2305
2314
 
2315
+ /**
2316
+ * Map of environment variables and their values.
2317
+ *
2318
+ * Can be set using the `env` option of serve:
2319
+ *
2320
+ * ```ts
2321
+ * export const POST = serve<MyPayload>(
2322
+ * async (context) => {
2323
+ * const key = context.env["API_KEY"];
2324
+ * },
2325
+ * {
2326
+ * env: {
2327
+ * "API_KEY": "*****";
2328
+ * }
2329
+ * }
2330
+ * )
2331
+ * ```
2332
+ *
2333
+ * Default value is set to `process.env`.
2334
+ */
2335
+
2306
2336
  constructor({
2307
2337
  qstashClient,
2308
2338
  workflowRunId,
@@ -2312,7 +2342,8 @@ var WorkflowContext = class {
2312
2342
  failureUrl,
2313
2343
  debug,
2314
2344
  initialPayload,
2315
- rawInitialPayload
2345
+ rawInitialPayload,
2346
+ env
2316
2347
  }) {
2317
2348
  this.qstashClient = qstashClient;
2318
2349
  this.workflowRunId = workflowRunId;
@@ -2322,14 +2353,15 @@ var WorkflowContext = class {
2322
2353
  this.headers = headers;
2323
2354
  this.requestPayload = initialPayload;
2324
2355
  this.rawInitialPayload = _nullishCoalesce(rawInitialPayload, () => ( JSON.stringify(this.requestPayload)));
2356
+ this.env = _nullishCoalesce(env, () => ( {}));
2325
2357
  this.executor = new AutoExecutor(this, this.steps, debug);
2326
2358
  }
2327
2359
  /**
2328
2360
  * Executes a workflow step
2329
2361
  *
2330
2362
  * ```typescript
2331
- * const result = await context.run("step 1", async () => {
2332
- * return await Promise.resolve("result")
2363
+ * const result = await context.run("step 1", () => {
2364
+ * return "result"
2333
2365
  * })
2334
2366
  * ```
2335
2367
  *
@@ -2338,11 +2370,11 @@ var WorkflowContext = class {
2338
2370
  *
2339
2371
  * ```typescript
2340
2372
  * const [result1, result2] = await Promise.all([
2341
- * context.run("step 1", async () => {
2342
- * return await Promise.resolve("result1")
2373
+ * context.run("step 1", () => {
2374
+ * return "result1"
2343
2375
  * })
2344
2376
  * context.run("step 2", async () => {
2345
- * return await Promise.resolve("result2")
2377
+ * return await fetchResults()
2346
2378
  * })
2347
2379
  * ])
2348
2380
  * ```
@@ -2352,7 +2384,7 @@ var WorkflowContext = class {
2352
2384
  * @returns result of the step function
2353
2385
  */
2354
2386
  async run(stepName, stepFunction) {
2355
- const wrappedStepFunction = async () => this.executor.wrapStep(stepName, stepFunction);
2387
+ const wrappedStepFunction = () => this.executor.wrapStep(stepName, stepFunction);
2356
2388
  return this.addStep(new LazyFunctionStep(stepName, wrappedStepFunction));
2357
2389
  }
2358
2390
  /**
@@ -2448,7 +2480,8 @@ var DisabledWorkflowContext = (_class8 = class _DisabledWorkflowContext extends
2448
2480
  url: context.url,
2449
2481
  failureUrl: context.failureUrl,
2450
2482
  initialPayload: context.requestPayload,
2451
- rawInitialPayload: context.rawInitialPayload
2483
+ rawInitialPayload: context.rawInitialPayload,
2484
+ env: context.env
2452
2485
  });
2453
2486
  try {
2454
2487
  await routeFunction(disabledContext);
@@ -2510,36 +2543,6 @@ var WorkflowLogger = (_class9 = class _WorkflowLogger {
2510
2543
  }
2511
2544
  }, _class9);
2512
2545
 
2513
- // node_modules/nanoid/index.js
2514
- var _crypto = require('crypto'); var _crypto2 = _interopRequireDefault(_crypto);
2515
-
2516
- // node_modules/nanoid/url-alphabet/index.js
2517
- var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
2518
-
2519
- // node_modules/nanoid/index.js
2520
- var POOL_SIZE_MULTIPLIER = 128;
2521
- var pool;
2522
- var poolOffset;
2523
- var fillPool = (bytes) => {
2524
- if (!pool || pool.length < bytes) {
2525
- pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
2526
- _crypto2.default.randomFillSync(pool);
2527
- poolOffset = 0;
2528
- } else if (poolOffset + bytes > pool.length) {
2529
- _crypto2.default.randomFillSync(pool);
2530
- poolOffset = 0;
2531
- }
2532
- poolOffset += bytes;
2533
- };
2534
- var nanoid = (size = 21) => {
2535
- fillPool(size -= 0);
2536
- let id = "";
2537
- for (let i = poolOffset - size; i < poolOffset; i++) {
2538
- id += urlAlphabet[pool[i] & 63];
2539
- }
2540
- return id;
2541
- };
2542
-
2543
2546
  // src/client/workflow/workflow-parser.ts
2544
2547
  var getPayload = async (request) => {
2545
2548
  try {
@@ -2548,12 +2551,9 @@ var getPayload = async (request) => {
2548
2551
  return;
2549
2552
  }
2550
2553
  };
2551
- var decodeBase64 = (encodedString) => {
2552
- return Buffer.from(encodedString, "base64").toString();
2553
- };
2554
2554
  var parsePayload = (rawPayload) => {
2555
2555
  const [encodedInitialPayload, ...encodedSteps] = JSON.parse(rawPayload);
2556
- const rawInitialPayload = decodeBase64(encodedInitialPayload.body);
2556
+ const rawInitialPayload = atob(encodedInitialPayload.body);
2557
2557
  const initialStep = {
2558
2558
  stepId: 0,
2559
2559
  stepName: "init",
@@ -2563,7 +2563,7 @@ var parsePayload = (rawPayload) => {
2563
2563
  };
2564
2564
  const stepsToDecode = encodedSteps.filter((step) => step.callType === "step");
2565
2565
  const otherSteps = stepsToDecode.map((rawStep) => {
2566
- return JSON.parse(decodeBase64(rawStep.body));
2566
+ return JSON.parse(atob(rawStep.body));
2567
2567
  });
2568
2568
  const steps = [initialStep, ...otherSteps];
2569
2569
  return {
@@ -2688,13 +2688,14 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
2688
2688
 
2689
2689
  // src/client/workflow/serve.ts
2690
2690
  var processOptions = (options) => {
2691
+ const environment = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _69 => _69.env]), () => ( (typeof process === "undefined" ? {} : process.env)));
2691
2692
  const receiverEnvironmentVariablesSet = Boolean(
2692
- process.env.QSTASH_CURRENT_SIGNING_KEY && process.env.QSTASH_NEXT_SIGNING_KEY
2693
+ environment.QSTASH_CURRENT_SIGNING_KEY && environment.QSTASH_NEXT_SIGNING_KEY
2693
2694
  );
2694
2695
  return {
2695
2696
  qstashClient: new Client({
2696
- baseUrl: process.env.QSTASH_URL,
2697
- token: process.env.QSTASH_TOKEN
2697
+ baseUrl: environment.QSTASH_URL,
2698
+ token: environment.QSTASH_TOKEN
2698
2699
  }),
2699
2700
  onStepFinish: (workflowRunId, finishCondition) => new Response(JSON.stringify({ workflowRunId, finishCondition }), {
2700
2701
  status: 200
@@ -2713,10 +2714,11 @@ var processOptions = (options) => {
2713
2714
  }
2714
2715
  },
2715
2716
  receiver: receiverEnvironmentVariablesSet ? new Receiver({
2716
- currentSigningKey: process.env.QSTASH_CURRENT_SIGNING_KEY,
2717
- nextSigningKey: process.env.QSTASH_NEXT_SIGNING_KEY
2717
+ currentSigningKey: environment.QSTASH_CURRENT_SIGNING_KEY,
2718
+ nextSigningKey: environment.QSTASH_NEXT_SIGNING_KEY
2718
2719
  }) : void 0,
2719
- baseUrl: process.env.UPSTASH_WORKFLOW_URL,
2720
+ baseUrl: environment.UPSTASH_WORKFLOW_URL,
2721
+ env: environment,
2720
2722
  ...options
2721
2723
  };
2722
2724
  };
@@ -2730,16 +2732,17 @@ var serve = (routeFunction, options) => {
2730
2732
  receiver,
2731
2733
  failureUrl,
2732
2734
  failureFunction,
2733
- baseUrl
2735
+ baseUrl,
2736
+ env
2734
2737
  } = processOptions(options);
2735
2738
  const debug = WorkflowLogger.getLogger(verbose);
2736
- return async (request) => {
2739
+ const handler = async (request) => {
2737
2740
  const initialWorkflowUrl = _nullishCoalesce(url, () => ( request.url));
2738
2741
  const workflowUrl = baseUrl ? initialWorkflowUrl.replace(/^(https?:\/\/[^/]+)(\/.*)?$/, (_, matchedBaseUrl, path) => {
2739
2742
  return baseUrl + (path || "");
2740
2743
  }) : initialWorkflowUrl;
2741
2744
  if (workflowUrl !== initialWorkflowUrl) {
2742
- await _optionalChain([debug, 'optionalAccess', _69 => _69.log, 'call', _70 => _70("WARN", "ENDPOINT_START", {
2745
+ await _optionalChain([debug, 'optionalAccess', _70 => _70.log, 'call', _71 => _71("WARN", "ENDPOINT_START", {
2743
2746
  warning: `QStash Workflow: replacing the base of the url with "${baseUrl}" and using it as workflow endpoint.`,
2744
2747
  originalURL: initialWorkflowUrl,
2745
2748
  updatedURL: workflowUrl
@@ -2748,7 +2751,7 @@ var serve = (routeFunction, options) => {
2748
2751
  const workflowFailureUrl = failureFunction ? workflowUrl : failureUrl;
2749
2752
  const requestPayload = await _asyncNullishCoalesce(await getPayload(request), async () => ( ""));
2750
2753
  await verifyRequest(requestPayload, request.headers.get("upstash-signature"), receiver);
2751
- await _optionalChain([debug, 'optionalAccess', _71 => _71.log, 'call', _72 => _72("INFO", "ENDPOINT_START")]);
2754
+ await _optionalChain([debug, 'optionalAccess', _72 => _72.log, 'call', _73 => _73("INFO", "ENDPOINT_START")]);
2752
2755
  const failureCheck = await handleFailure(
2753
2756
  request,
2754
2757
  requestPayload,
@@ -2759,11 +2762,11 @@ var serve = (routeFunction, options) => {
2759
2762
  if (failureCheck.isErr()) {
2760
2763
  throw failureCheck.error;
2761
2764
  } else if (failureCheck.value === "is-failure-callback") {
2762
- await _optionalChain([debug, 'optionalAccess', _73 => _73.log, 'call', _74 => _74("WARN", "RESPONSE_DEFAULT", "failureFunction executed")]);
2765
+ await _optionalChain([debug, 'optionalAccess', _74 => _74.log, 'call', _75 => _75("WARN", "RESPONSE_DEFAULT", "failureFunction executed")]);
2763
2766
  return onStepFinish("no-workflow-id", "failure-callback");
2764
2767
  }
2765
2768
  const { isFirstInvocation, workflowRunId } = validateRequest(request);
2766
- _optionalChain([debug, 'optionalAccess', _75 => _75.setWorkflowRunId, 'call', _76 => _76(workflowRunId)]);
2769
+ _optionalChain([debug, 'optionalAccess', _76 => _76.setWorkflowRunId, 'call', _77 => _77(workflowRunId)]);
2767
2770
  const { rawInitialPayload, steps, isLastDuplicate } = await parseRequest(
2768
2771
  requestPayload,
2769
2772
  isFirstInvocation,
@@ -2781,14 +2784,15 @@ var serve = (routeFunction, options) => {
2781
2784
  steps,
2782
2785
  url: workflowUrl,
2783
2786
  failureUrl: workflowFailureUrl,
2784
- debug
2787
+ debug,
2788
+ env
2785
2789
  });
2786
2790
  const authCheck = await DisabledWorkflowContext.tryAuthentication(
2787
2791
  routeFunction,
2788
2792
  workflowContext
2789
2793
  );
2790
2794
  if (authCheck.isErr()) {
2791
- await _optionalChain([debug, 'optionalAccess', _77 => _77.log, 'call', _78 => _78("ERROR", "ERROR", { error: authCheck.error.message })]);
2795
+ await _optionalChain([debug, 'optionalAccess', _78 => _78.log, 'call', _79 => _79("ERROR", "ERROR", { error: authCheck.error.message })]);
2792
2796
  throw authCheck.error;
2793
2797
  } else if (authCheck.value === "run-ended") {
2794
2798
  return onStepFinish("no-workflow-id", "auth-fail");
@@ -2802,7 +2806,7 @@ var serve = (routeFunction, options) => {
2802
2806
  debug
2803
2807
  );
2804
2808
  if (callReturnCheck.isErr()) {
2805
- await _optionalChain([debug, 'optionalAccess', _79 => _79.log, 'call', _80 => _80("ERROR", "SUBMIT_THIRD_PARTY_RESULT", {
2809
+ await _optionalChain([debug, 'optionalAccess', _80 => _80.log, 'call', _81 => _81("ERROR", "SUBMIT_THIRD_PARTY_RESULT", {
2806
2810
  error: callReturnCheck.error.message
2807
2811
  })]);
2808
2812
  throw callReturnCheck.error;
@@ -2814,15 +2818,23 @@ var serve = (routeFunction, options) => {
2814
2818
  }
2815
2819
  });
2816
2820
  if (result.isErr()) {
2817
- await _optionalChain([debug, 'optionalAccess', _81 => _81.log, 'call', _82 => _82("ERROR", "ERROR", { error: result.error.message })]);
2821
+ await _optionalChain([debug, 'optionalAccess', _82 => _82.log, 'call', _83 => _83("ERROR", "ERROR", { error: result.error.message })]);
2818
2822
  throw result.error;
2819
2823
  }
2820
- await _optionalChain([debug, 'optionalAccess', _83 => _83.log, 'call', _84 => _84("INFO", "RESPONSE_WORKFLOW")]);
2824
+ await _optionalChain([debug, 'optionalAccess', _84 => _84.log, 'call', _85 => _85("INFO", "RESPONSE_WORKFLOW")]);
2821
2825
  return onStepFinish(workflowContext.workflowRunId, "success");
2822
2826
  }
2823
- await _optionalChain([debug, 'optionalAccess', _85 => _85.log, 'call', _86 => _86("INFO", "RESPONSE_DEFAULT")]);
2827
+ await _optionalChain([debug, 'optionalAccess', _86 => _86.log, 'call', _87 => _87("INFO", "RESPONSE_DEFAULT")]);
2824
2828
  return onStepFinish("no-workflow-id", "fromCallback");
2825
2829
  };
2830
+ return async (request) => {
2831
+ try {
2832
+ return await handler(request);
2833
+ } catch (error) {
2834
+ console.error(error);
2835
+ return new Response(JSON.stringify(formatWorkflowError(error)), { status: 500 });
2836
+ }
2837
+ };
2826
2838
  };
2827
2839
 
2828
2840
  // src/client/workflow/index.ts