@upstash/workflow 0.2.7 → 0.2.8-rc-invoke

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
@@ -20,7 +20,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // platforms/h3.ts
21
21
  var h3_exports = {};
22
22
  __export(h3_exports, {
23
- serve: () => serve
23
+ createWorkflow: () => createWorkflow,
24
+ serve: () => serve,
25
+ serveMany: () => serveMany
24
26
  });
25
27
  module.exports = __toCommonJS(h3_exports);
26
28
 
@@ -400,7 +402,7 @@ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
400
402
  var DEFAULT_CONTENT_TYPE = "application/json";
401
403
  var NO_CONCURRENCY = 1;
402
404
  var DEFAULT_RETRIES = 3;
403
- var VERSION = "v0.2.3";
405
+ var VERSION = "v0.2.7";
404
406
  var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
405
407
  var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
406
408
  var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
@@ -447,6 +449,31 @@ var formatWorkflowError = (error) => {
447
449
  };
448
450
  };
449
451
 
452
+ // src/utils.ts
453
+ var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
454
+ var NANOID_LENGTH = 21;
455
+ function getRandomInt() {
456
+ return Math.floor(Math.random() * NANOID_CHARS.length);
457
+ }
458
+ function nanoid() {
459
+ return Array.from({ length: NANOID_LENGTH }).map(() => NANOID_CHARS[getRandomInt()]).join("");
460
+ }
461
+ function getWorkflowRunId(id) {
462
+ return `wfr_${id ?? nanoid()}`;
463
+ }
464
+ function decodeBase64(base64) {
465
+ try {
466
+ const binString = atob(base64);
467
+ const intArray = Uint8Array.from(binString, (m) => m.codePointAt(0));
468
+ return new TextDecoder().decode(intArray);
469
+ } catch (error) {
470
+ console.warn(
471
+ `Upstash Qstash: Failed while decoding base64 "${base64}". Decoding with atob and returning it instead. ${error}`
472
+ );
473
+ return atob(base64);
474
+ }
475
+ }
476
+
450
477
  // src/context/steps.ts
451
478
  var BaseLazyStep = class {
452
479
  stepName;
@@ -627,6 +654,41 @@ var LazyNotifyStep = class extends LazyFunctionStep {
627
654
  });
628
655
  }
629
656
  };
657
+ var LazyInvokeStep = class extends BaseLazyStep {
658
+ stepType = "Invoke";
659
+ params;
660
+ constructor(stepName, { workflow, body, headers = {}, workflowRunId, retries }) {
661
+ super(stepName);
662
+ this.params = {
663
+ workflow,
664
+ body,
665
+ headers,
666
+ workflowRunId: getWorkflowRunId(workflowRunId),
667
+ retries
668
+ };
669
+ }
670
+ getPlanStep(concurrent, targetStep) {
671
+ return {
672
+ stepId: 0,
673
+ stepName: this.stepName,
674
+ stepType: this.stepType,
675
+ concurrent,
676
+ targetStep
677
+ };
678
+ }
679
+ /**
680
+ * won't be used as it's the server who will add the result step
681
+ * in Invoke step.
682
+ */
683
+ getResultStep(concurrent, stepId) {
684
+ return Promise.resolve({
685
+ stepId,
686
+ stepName: this.stepName,
687
+ stepType: this.stepType,
688
+ concurrent
689
+ });
690
+ }
691
+ };
630
692
 
631
693
  // node_modules/neverthrow/dist/index.es.js
632
694
  var defaultErrorConfig = {
@@ -1051,7 +1113,8 @@ var StepTypes = [
1051
1113
  "SleepUntil",
1052
1114
  "Call",
1053
1115
  "Wait",
1054
- "Notify"
1116
+ "Notify",
1117
+ "Invoke"
1055
1118
  ];
1056
1119
 
1057
1120
  // src/workflow-requests.ts
@@ -1059,7 +1122,7 @@ var import_qstash3 = require("@upstash/qstash");
1059
1122
  var triggerFirstInvocation = async ({
1060
1123
  workflowContext,
1061
1124
  useJSONContent,
1062
- telemetry,
1125
+ telemetry: telemetry2,
1063
1126
  debug
1064
1127
  }) => {
1065
1128
  const { headers } = getHeaders({
@@ -1069,7 +1132,7 @@ var triggerFirstInvocation = async ({
1069
1132
  userHeaders: workflowContext.headers,
1070
1133
  failureUrl: workflowContext.failureUrl,
1071
1134
  retries: workflowContext.retries,
1072
- telemetry
1135
+ telemetry: telemetry2
1073
1136
  });
1074
1137
  if (workflowContext.headers.get("content-type")) {
1075
1138
  headers["content-type"] = workflowContext.headers.get("content-type");
@@ -1115,8 +1178,8 @@ var triggerRouteFunction = async ({
1115
1178
  debug
1116
1179
  }) => {
1117
1180
  try {
1118
- await onStep();
1119
- await onCleanup();
1181
+ const result = await onStep();
1182
+ await onCleanup(result);
1120
1183
  return ok("workflow-finished");
1121
1184
  } catch (error) {
1122
1185
  const error_ = error;
@@ -1137,14 +1200,15 @@ var triggerRouteFunction = async ({
1137
1200
  }
1138
1201
  }
1139
1202
  };
1140
- var triggerWorkflowDelete = async (workflowContext, debug, cancel = false) => {
1203
+ var triggerWorkflowDelete = async (workflowContext, result, debug, cancel = false) => {
1141
1204
  await debug?.log("SUBMIT", "SUBMIT_CLEANUP", {
1142
1205
  deletedWorkflowRunId: workflowContext.workflowRunId
1143
1206
  });
1144
1207
  await workflowContext.qstashClient.http.request({
1145
1208
  path: ["v2", "workflows", "runs", `${workflowContext.workflowRunId}?cancel=${cancel}`],
1146
1209
  method: "DELETE",
1147
- parseResponseAsJson: false
1210
+ parseResponseAsJson: false,
1211
+ body: JSON.stringify(result)
1148
1212
  });
1149
1213
  await debug?.log(
1150
1214
  "SUBMIT",
@@ -1173,7 +1237,7 @@ var handleThirdPartyCallResult = async ({
1173
1237
  workflowUrl,
1174
1238
  failureUrl,
1175
1239
  retries,
1176
- telemetry,
1240
+ telemetry: telemetry2,
1177
1241
  debug
1178
1242
  }) => {
1179
1243
  try {
@@ -1241,7 +1305,7 @@ ${atob(callbackMessage.body ?? "")}`
1241
1305
  userHeaders,
1242
1306
  failureUrl,
1243
1307
  retries,
1244
- telemetry
1308
+ telemetry: telemetry2
1245
1309
  });
1246
1310
  const callResponse = {
1247
1311
  status: callbackMessage.status,
@@ -1280,11 +1344,11 @@ ${atob(callbackMessage.body ?? "")}`
1280
1344
  );
1281
1345
  }
1282
1346
  };
1283
- var getTelemetryHeaders = (telemetry) => {
1347
+ var getTelemetryHeaders = (telemetry2) => {
1284
1348
  return {
1285
- [TELEMETRY_HEADER_SDK]: telemetry.sdk,
1286
- [TELEMETRY_HEADER_FRAMEWORK]: telemetry.framework,
1287
- [TELEMETRY_HEADER_RUNTIME]: telemetry.runtime ?? "unknown"
1349
+ [TELEMETRY_HEADER_SDK]: telemetry2.sdk,
1350
+ [TELEMETRY_HEADER_FRAMEWORK]: telemetry2.framework,
1351
+ [TELEMETRY_HEADER_RUNTIME]: telemetry2.runtime ?? "unknown"
1288
1352
  };
1289
1353
  };
1290
1354
  var getHeaders = ({
@@ -1297,14 +1361,17 @@ var getHeaders = ({
1297
1361
  step,
1298
1362
  callRetries,
1299
1363
  callTimeout,
1300
- telemetry
1364
+ telemetry: telemetry2
1301
1365
  }) => {
1366
+ const contentType = (userHeaders ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
1302
1367
  const baseHeaders = {
1303
1368
  [WORKFLOW_INIT_HEADER]: initHeaderValue,
1304
1369
  [WORKFLOW_ID_HEADER]: workflowRunId,
1305
1370
  [WORKFLOW_URL_HEADER]: workflowUrl,
1306
1371
  [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
1307
- ...telemetry ? getTelemetryHeaders(telemetry) : {}
1372
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
1373
+ "content-type": contentType,
1374
+ ...telemetry2 ? getTelemetryHeaders(telemetry2) : {}
1308
1375
  };
1309
1376
  if (!step?.callUrl) {
1310
1377
  baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
@@ -1318,6 +1385,9 @@ var getHeaders = ({
1318
1385
  baseHeaders["Upstash-Failure-Callback"] = failureUrl;
1319
1386
  }
1320
1387
  }
1388
+ if (step?.stepType === "Invoke") {
1389
+ baseHeaders["upstash-workflow-invoke"] = "true";
1390
+ }
1321
1391
  if (step?.callUrl) {
1322
1392
  baseHeaders["Upstash-Retries"] = callRetries?.toString() ?? "0";
1323
1393
  baseHeaders[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
@@ -1339,7 +1409,6 @@ var getHeaders = ({
1339
1409
  baseHeaders[`Upstash-Failure-Callback-Forward-${header}`] = userHeaders.get(header);
1340
1410
  }
1341
1411
  }
1342
- const contentType = (userHeaders ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
1343
1412
  if (step?.callHeaders) {
1344
1413
  const forwardedHeaders = Object.fromEntries(
1345
1414
  Object.entries(step.callHeaders).map(([header, value]) => [
@@ -1379,8 +1448,8 @@ var getHeaders = ({
1379
1448
  Object.entries(baseHeaders).map(([header, value]) => [header, [value]])
1380
1449
  ),
1381
1450
  // to include telemetry headers:
1382
- ...telemetry ? Object.fromEntries(
1383
- Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
1451
+ ...telemetry2 ? Object.fromEntries(
1452
+ Object.entries(getTelemetryHeaders(telemetry2)).map(([header, value]) => [
1384
1453
  header,
1385
1454
  [value]
1386
1455
  ])
@@ -1389,8 +1458,7 @@ var getHeaders = ({
1389
1458
  "Upstash-Workflow-Runid": [workflowRunId],
1390
1459
  [WORKFLOW_INIT_HEADER]: ["false"],
1391
1460
  [WORKFLOW_URL_HEADER]: [workflowUrl],
1392
- "Upstash-Workflow-CallType": ["step"],
1393
- "Content-Type": [contentType]
1461
+ "Upstash-Workflow-CallType": ["step"]
1394
1462
  }
1395
1463
  };
1396
1464
  }
@@ -1436,10 +1504,10 @@ var AutoExecutor = class _AutoExecutor {
1436
1504
  stepCount = 0;
1437
1505
  planStepCount = 0;
1438
1506
  executingStep = false;
1439
- constructor(context, steps, telemetry, debug) {
1507
+ constructor(context, steps, telemetry2, debug) {
1440
1508
  this.context = context;
1441
1509
  this.steps = steps;
1442
- this.telemetry = telemetry;
1510
+ this.telemetry = telemetry2;
1443
1511
  this.debug = debug;
1444
1512
  this.nonPlanStepCount = this.steps.filter((step) => !step.targetStep).length;
1445
1513
  }
@@ -1685,7 +1753,23 @@ var AutoExecutor = class _AutoExecutor {
1685
1753
  method: "POST",
1686
1754
  parseResponseAsJson: false
1687
1755
  });
1688
- throw new WorkflowAbort(steps[0].stepName, steps[0]);
1756
+ throw new WorkflowAbort(waitStep.stepName, waitStep);
1757
+ }
1758
+ if (steps.length === 1 && lazySteps[0] instanceof LazyInvokeStep) {
1759
+ const invokeStep = steps[0];
1760
+ const lazyInvokeStep = lazySteps[0];
1761
+ await lazyInvokeStep.params.workflow.callback(
1762
+ {
1763
+ body: lazyInvokeStep.params.body,
1764
+ headers: lazyInvokeStep.params.headers,
1765
+ workflowRunId: lazyInvokeStep.params.workflowRunId,
1766
+ workflow: lazyInvokeStep.params.workflow,
1767
+ retries: lazyInvokeStep.params.retries
1768
+ },
1769
+ invokeStep,
1770
+ this.context
1771
+ );
1772
+ throw new WorkflowAbort(invokeStep.stepName, invokeStep);
1689
1773
  }
1690
1774
  const result = await this.context.qstashClient.batchJSON(
1691
1775
  steps.map((singleStep, index) => {
@@ -2371,7 +2455,7 @@ var WorkflowContext = class {
2371
2455
  initialPayload,
2372
2456
  env,
2373
2457
  retries,
2374
- telemetry
2458
+ telemetry: telemetry2
2375
2459
  }) {
2376
2460
  this.qstashClient = qstashClient;
2377
2461
  this.workflowRunId = workflowRunId;
@@ -2382,7 +2466,7 @@ var WorkflowContext = class {
2382
2466
  this.requestPayload = initialPayload;
2383
2467
  this.env = env ?? {};
2384
2468
  this.retries = retries ?? DEFAULT_RETRIES;
2385
- this.executor = new AutoExecutor(this, this.steps, telemetry, debug);
2469
+ this.executor = new AutoExecutor(this, this.steps, telemetry2, debug);
2386
2470
  }
2387
2471
  /**
2388
2472
  * Executes a workflow step
@@ -2602,6 +2686,13 @@ var WorkflowContext = class {
2602
2686
  return result;
2603
2687
  }
2604
2688
  }
2689
+ async invoke(stepName, settings) {
2690
+ const result = await this.addStep(new LazyInvokeStep(stepName, settings));
2691
+ return {
2692
+ ...result,
2693
+ body: result.body ? JSON.parse(result.body) : void 0
2694
+ };
2695
+ }
2605
2696
  /**
2606
2697
  * Cancel the current workflow run
2607
2698
  *
@@ -2679,31 +2770,6 @@ var WorkflowLogger = class _WorkflowLogger {
2679
2770
  }
2680
2771
  };
2681
2772
 
2682
- // src/utils.ts
2683
- var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
2684
- var NANOID_LENGTH = 21;
2685
- function getRandomInt() {
2686
- return Math.floor(Math.random() * NANOID_CHARS.length);
2687
- }
2688
- function nanoid() {
2689
- return Array.from({ length: NANOID_LENGTH }).map(() => NANOID_CHARS[getRandomInt()]).join("");
2690
- }
2691
- function getWorkflowRunId(id) {
2692
- return `wfr_${id ?? nanoid()}`;
2693
- }
2694
- function decodeBase64(base64) {
2695
- try {
2696
- const binString = atob(base64);
2697
- const intArray = Uint8Array.from(binString, (m) => m.codePointAt(0));
2698
- return new TextDecoder().decode(intArray);
2699
- } catch (error) {
2700
- console.warn(
2701
- `Upstash Qstash: Failed while decoding base64 "${base64}". Decoding with atob and returning it instead. ${error}`
2702
- );
2703
- return atob(base64);
2704
- }
2705
- }
2706
-
2707
2773
  // src/serve/authorization.ts
2708
2774
  var import_qstash8 = require("@upstash/qstash");
2709
2775
  var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowContext {
@@ -3041,7 +3107,7 @@ var determineUrls = async (request, url, baseUrl, failureFunction, failureUrl, d
3041
3107
  var AUTH_FAIL_MESSAGE = `Failed to authenticate Workflow request. If this is unexpected, see the caveat https://upstash.com/docs/workflow/basics/caveats#avoid-non-deterministic-code-outside-context-run`;
3042
3108
 
3043
3109
  // src/serve/index.ts
3044
- var serveBase = (routeFunction, telemetry, options) => {
3110
+ var serveBase = (routeFunction, telemetry2, options) => {
3045
3111
  const {
3046
3112
  qstashClient,
3047
3113
  onStepFinish,
@@ -3057,7 +3123,7 @@ var serveBase = (routeFunction, telemetry, options) => {
3057
3123
  useJSONContent,
3058
3124
  disableTelemetry
3059
3125
  } = processOptions(options);
3060
- telemetry = disableTelemetry ? void 0 : telemetry;
3126
+ telemetry2 = disableTelemetry ? void 0 : telemetry2;
3061
3127
  const debug = WorkflowLogger.getLogger(verbose);
3062
3128
  const handler = async (request) => {
3063
3129
  await debug?.log("INFO", "ENDPOINT_START");
@@ -3115,7 +3181,7 @@ var serveBase = (routeFunction, telemetry, options) => {
3115
3181
  debug,
3116
3182
  env,
3117
3183
  retries,
3118
- telemetry
3184
+ telemetry: telemetry2
3119
3185
  });
3120
3186
  const authCheck = await DisabledWorkflowContext.tryAuthentication(
3121
3187
  routeFunction,
@@ -3138,7 +3204,7 @@ var serveBase = (routeFunction, telemetry, options) => {
3138
3204
  workflowUrl,
3139
3205
  failureUrl: workflowFailureUrl,
3140
3206
  retries,
3141
- telemetry,
3207
+ telemetry: telemetry2,
3142
3208
  debug
3143
3209
  });
3144
3210
  if (callReturnCheck.isErr()) {
@@ -3147,10 +3213,10 @@ var serveBase = (routeFunction, telemetry, options) => {
3147
3213
  });
3148
3214
  throw callReturnCheck.error;
3149
3215
  } else if (callReturnCheck.value === "continue-workflow") {
3150
- const result = isFirstInvocation ? await triggerFirstInvocation({ workflowContext, useJSONContent, telemetry, debug }) : await triggerRouteFunction({
3216
+ const result = isFirstInvocation ? await triggerFirstInvocation({ workflowContext, useJSONContent, telemetry: telemetry2, debug }) : await triggerRouteFunction({
3151
3217
  onStep: async () => routeFunction(workflowContext),
3152
- onCleanup: async () => {
3153
- await triggerWorkflowDelete(workflowContext, debug);
3218
+ onCleanup: async (result2) => {
3219
+ await triggerWorkflowDelete(workflowContext, result2, debug);
3154
3220
  },
3155
3221
  onCancel: async () => {
3156
3222
  await makeCancelRequest(workflowContext.qstashClient.http, workflowRunId);
@@ -3182,6 +3248,91 @@ var serveBase = (routeFunction, telemetry, options) => {
3182
3248
  return { handler: safeHandler };
3183
3249
  };
3184
3250
 
3251
+ // src/serve/serve-many.ts
3252
+ var serveManyBase = ({
3253
+ workflows,
3254
+ getWorkflowId
3255
+ }) => {
3256
+ const workflowIds = [];
3257
+ const workflowMap = Object.fromEntries(
3258
+ Object.entries(workflows).map((workflow) => {
3259
+ const workflowId = workflow[0];
3260
+ if (workflowIds.includes(workflowId)) {
3261
+ throw new WorkflowError(
3262
+ `Duplicate workflow name found: '${workflowId}'. Please set different workflow names in serveMany.`
3263
+ );
3264
+ }
3265
+ if (workflowId.includes("/")) {
3266
+ throw new WorkflowError(
3267
+ `Invalid workflow name found: '${workflowId}'. Workflow name cannot contain '/'.`
3268
+ );
3269
+ }
3270
+ workflowIds.push(workflowId);
3271
+ workflow[1].workflowId = workflowId;
3272
+ return [workflowId, workflow[1].handler];
3273
+ })
3274
+ );
3275
+ return {
3276
+ handler: async (...params) => {
3277
+ const pickedWorkflowId = getWorkflowId(...params);
3278
+ if (!pickedWorkflowId) {
3279
+ throw new WorkflowError(`Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`);
3280
+ }
3281
+ const workflow = workflowMap[pickedWorkflowId];
3282
+ if (!workflow) {
3283
+ throw new WorkflowError(`No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`);
3284
+ }
3285
+ return await workflow(...params);
3286
+ }
3287
+ };
3288
+ };
3289
+ var createInvokeCallback = (telemetry2) => {
3290
+ const invokeCallback = async (settings, invokeStep, context) => {
3291
+ const { body, workflow, headers = {}, workflowRunId = getWorkflowRunId(), retries } = settings;
3292
+ const { workflowId } = workflow;
3293
+ if (!workflowId) {
3294
+ throw new WorkflowError("You can only invoke workflow which has a workflowId");
3295
+ }
3296
+ const { headers: invokerHeaders } = getHeaders({
3297
+ initHeaderValue: "false",
3298
+ workflowRunId: context.workflowRunId,
3299
+ workflowUrl: context.url,
3300
+ userHeaders: context.headers,
3301
+ failureUrl: context.failureUrl,
3302
+ retries: context.retries,
3303
+ telemetry: telemetry2
3304
+ });
3305
+ invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
3306
+ const newUrl = context.url.replace(/[^/]+$/, workflowId);
3307
+ const { headers: triggerHeaders } = getHeaders({
3308
+ initHeaderValue: "true",
3309
+ workflowRunId,
3310
+ workflowUrl: newUrl,
3311
+ userHeaders: new Headers(headers),
3312
+ retries,
3313
+ telemetry: telemetry2
3314
+ });
3315
+ triggerHeaders["Upstash-Workflow-Invoke"] = "true";
3316
+ const request = {
3317
+ body: JSON.stringify(body),
3318
+ headers: Object.fromEntries(
3319
+ Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
3320
+ ),
3321
+ workflowRunId,
3322
+ workflowUrl: context.url,
3323
+ step: invokeStep
3324
+ };
3325
+ await context.qstashClient.publish({
3326
+ headers: triggerHeaders,
3327
+ method: "POST",
3328
+ body: JSON.stringify(request),
3329
+ url: newUrl
3330
+ });
3331
+ return void 0;
3332
+ };
3333
+ return invokeCallback;
3334
+ };
3335
+
3185
3336
  // platforms/h3.ts
3186
3337
  function transformHeaders(headers) {
3187
3338
  const formattedHeaders = Object.entries(headers).map(([key, value]) => [
@@ -3190,39 +3341,59 @@ function transformHeaders(headers) {
3190
3341
  ]);
3191
3342
  return formattedHeaders;
3192
3343
  }
3344
+ function getUrl(event) {
3345
+ const request_ = event.node.req;
3346
+ const protocol = request_.headers["x-forwarded-proto"];
3347
+ const host = request_.headers.host;
3348
+ const url = `${protocol}://${host}${event.path}`;
3349
+ return url;
3350
+ }
3351
+ var telemetry = {
3352
+ sdk: SDK_TELEMETRY,
3353
+ framework: "h3",
3354
+ runtime: process.versions.bun ? `bun@${process.versions.bun}/node@${process.version}` : `node@${process.version}`
3355
+ };
3193
3356
  var serve = (routeFunction, options) => {
3194
3357
  const handler = defineEventHandler(async (event) => {
3195
3358
  const method = event.node.req.method;
3196
3359
  if (method?.toUpperCase() !== "POST") {
3197
- return {
3198
- status: 405,
3199
- body: "Only POST requests are allowed in worklfows"
3200
- };
3360
+ return new Response("Only POST requests are allowed in worklfows", {
3361
+ status: 405
3362
+ });
3201
3363
  }
3202
- const request_ = event.node.req;
3203
- const protocol = request_.headers["x-forwarded-proto"];
3204
- const host = request_.headers.host;
3205
- const url = `${protocol}://${host}${event.path}`;
3206
- const headers = transformHeaders(request_.headers);
3364
+ const url = getUrl(event);
3365
+ const headers = transformHeaders(event.node.req.headers);
3207
3366
  const request = new Request(url, {
3208
3367
  headers,
3209
3368
  body: await readRawBody(event),
3210
3369
  method: "POST"
3211
3370
  });
3212
- const { handler: serveHandler } = serveBase(
3213
- routeFunction,
3214
- {
3215
- sdk: SDK_TELEMETRY,
3216
- framework: "h3",
3217
- runtime: process.versions.bun ? `bun@${process.versions.bun}/node@${process.version}` : `node@${process.version}`
3218
- },
3219
- options
3220
- );
3371
+ const { handler: serveHandler } = serveBase(routeFunction, telemetry, options);
3221
3372
  return await serveHandler(request);
3222
3373
  });
3223
3374
  return { handler };
3224
3375
  };
3376
+ var createWorkflow = (...params) => {
3377
+ const { handler } = serve(...params);
3378
+ return {
3379
+ callback: createInvokeCallback(telemetry),
3380
+ handler,
3381
+ workflowId: void 0
3382
+ };
3383
+ };
3384
+ var serveMany = (workflows) => {
3385
+ return serveManyBase({
3386
+ workflows,
3387
+ getWorkflowId(event) {
3388
+ const url = getUrl(event);
3389
+ const components = url.split("/");
3390
+ return components[components.length - 1];
3391
+ }
3392
+ });
3393
+ };
3225
3394
  // Annotate the CommonJS export names for ESM import in node:
3226
3395
  0 && (module.exports = {
3227
- serve
3396
+ createWorkflow,
3397
+ serve,
3398
+ serveMany
3228
3399
  });
package/h3.mjs CHANGED
@@ -1,7 +1,11 @@
1
+ import {
2
+ createInvokeCallback,
3
+ serveManyBase
4
+ } from "./chunk-LCZMBGEM.mjs";
1
5
  import {
2
6
  SDK_TELEMETRY,
3
7
  serveBase
4
- } from "./chunk-U6XFLG7W.mjs";
8
+ } from "./chunk-IWAW7GIG.mjs";
5
9
 
6
10
  // node_modules/defu/dist/defu.mjs
7
11
  function isPlainObject(value) {
@@ -323,38 +327,58 @@ function transformHeaders(headers) {
323
327
  ]);
324
328
  return formattedHeaders;
325
329
  }
330
+ function getUrl(event) {
331
+ const request_ = event.node.req;
332
+ const protocol = request_.headers["x-forwarded-proto"];
333
+ const host = request_.headers.host;
334
+ const url = `${protocol}://${host}${event.path}`;
335
+ return url;
336
+ }
337
+ var telemetry = {
338
+ sdk: SDK_TELEMETRY,
339
+ framework: "h3",
340
+ runtime: process.versions.bun ? `bun@${process.versions.bun}/node@${process.version}` : `node@${process.version}`
341
+ };
326
342
  var serve = (routeFunction, options) => {
327
343
  const handler = defineEventHandler(async (event) => {
328
344
  const method = event.node.req.method;
329
345
  if (method?.toUpperCase() !== "POST") {
330
- return {
331
- status: 405,
332
- body: "Only POST requests are allowed in worklfows"
333
- };
346
+ return new Response("Only POST requests are allowed in worklfows", {
347
+ status: 405
348
+ });
334
349
  }
335
- const request_ = event.node.req;
336
- const protocol = request_.headers["x-forwarded-proto"];
337
- const host = request_.headers.host;
338
- const url = `${protocol}://${host}${event.path}`;
339
- const headers = transformHeaders(request_.headers);
350
+ const url = getUrl(event);
351
+ const headers = transformHeaders(event.node.req.headers);
340
352
  const request = new Request(url, {
341
353
  headers,
342
354
  body: await readRawBody(event),
343
355
  method: "POST"
344
356
  });
345
- const { handler: serveHandler } = serveBase(
346
- routeFunction,
347
- {
348
- sdk: SDK_TELEMETRY,
349
- framework: "h3",
350
- runtime: process.versions.bun ? `bun@${process.versions.bun}/node@${process.version}` : `node@${process.version}`
351
- },
352
- options
353
- );
357
+ const { handler: serveHandler } = serveBase(routeFunction, telemetry, options);
354
358
  return await serveHandler(request);
355
359
  });
356
360
  return { handler };
357
361
  };
362
+ var createWorkflow = (...params) => {
363
+ const { handler } = serve(...params);
364
+ return {
365
+ callback: createInvokeCallback(telemetry),
366
+ handler,
367
+ workflowId: void 0
368
+ };
369
+ };
370
+ var serveMany = (workflows) => {
371
+ return serveManyBase({
372
+ workflows,
373
+ getWorkflowId(event) {
374
+ const url = getUrl(event);
375
+ const components = url.split("/");
376
+ return components[components.length - 1];
377
+ }
378
+ });
379
+ };
358
380
  export {
359
- serve
381
+ createWorkflow,
382
+ serve,
383
+ serveMany
360
384
  };
package/hono.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Context } from 'hono';
2
- import { R as RouteFunction, j as PublicServeOptions } from './types-Cuqlx2Cr.mjs';
2
+ import { R as RouteFunction, j as PublicServeOptions, t as InvokableWorkflow } from './types-C7Y7WUQd.mjs';
3
3
  import { Variables } from 'hono/types';
4
+ import { s as serveManyBase } from './serve-many-BlBvXfBS.mjs';
4
5
  import '@upstash/qstash';
5
6
  import 'zod';
6
7
  import 'ai';
@@ -14,7 +15,7 @@ type WorkflowBindings = {
14
15
  UPSTASH_WORKFLOW_URL?: string;
15
16
  };
16
17
  /**
17
- * Serve method to serve a Upstash Workflow in a Nextjs project
18
+ * Serve method to serve a Upstash Workflow in a Hono project
18
19
  *
19
20
  * See for options https://upstash.com/docs/qstash/workflows/basics/serve
20
21
  *
@@ -22,9 +23,14 @@ type WorkflowBindings = {
22
23
  * @param options workflow options
23
24
  * @returns
24
25
  */
25
- declare const serve: <TInitialPayload = unknown, TBindings extends WorkflowBindings = WorkflowBindings, TVariables extends Variables = object>(routeFunction: RouteFunction<TInitialPayload>, options?: PublicServeOptions<TInitialPayload>) => ((context: Context<{
26
+ declare const serve: <TInitialPayload = unknown, TBindings extends WorkflowBindings = WorkflowBindings, TVariables extends Variables = object, TResult = unknown>(routeFunction: RouteFunction<TInitialPayload, TResult>, options?: PublicServeOptions<TInitialPayload>) => ((context: Context<{
26
27
  Bindings: TBindings;
27
28
  Variables: TVariables;
28
29
  }>) => Promise<Response>);
30
+ declare const createWorkflow: <TInitialPayload, TResult>(routeFunction: RouteFunction<TInitialPayload, TResult>, options?: PublicServeOptions<TInitialPayload> | undefined) => InvokableWorkflow<TInitialPayload, TResult, Parameters<ReturnType<typeof serve<TInitialPayload, WorkflowBindings, Variables, TResult>>>>;
31
+ declare const serveMany: (workflows: Parameters<typeof serveManyBase>[0]["workflows"]) => (context: Context<{
32
+ Bindings: WorkflowBindings;
33
+ Variables: object;
34
+ }, any, {}>) => Promise<any>;
29
35
 
30
- export { type WorkflowBindings, serve };
36
+ export { type WorkflowBindings, createWorkflow, serve, serveMany };