@upstash/workflow 0.2.6 → 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/express.js CHANGED
@@ -23692,7 +23692,9 @@ var require_express2 = __commonJS({
23692
23692
  // platforms/express.ts
23693
23693
  var express_exports = {};
23694
23694
  __export(express_exports, {
23695
- serve: () => serve
23695
+ createWorkflow: () => createWorkflow,
23696
+ serve: () => serve,
23697
+ serveMany: () => serveMany
23696
23698
  });
23697
23699
  module.exports = __toCommonJS(express_exports);
23698
23700
 
@@ -23707,7 +23709,7 @@ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
23707
23709
  var DEFAULT_CONTENT_TYPE = "application/json";
23708
23710
  var NO_CONCURRENCY = 1;
23709
23711
  var DEFAULT_RETRIES = 3;
23710
- var VERSION = "v0.2.3";
23712
+ var VERSION = "v0.2.7";
23711
23713
  var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
23712
23714
  var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
23713
23715
  var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
@@ -23807,6 +23809,31 @@ var formatWorkflowError = (error) => {
23807
23809
  };
23808
23810
  };
23809
23811
 
23812
+ // src/utils.ts
23813
+ var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
23814
+ var NANOID_LENGTH = 21;
23815
+ function getRandomInt() {
23816
+ return Math.floor(Math.random() * NANOID_CHARS.length);
23817
+ }
23818
+ function nanoid() {
23819
+ return Array.from({ length: NANOID_LENGTH }).map(() => NANOID_CHARS[getRandomInt()]).join("");
23820
+ }
23821
+ function getWorkflowRunId(id) {
23822
+ return `wfr_${id ?? nanoid()}`;
23823
+ }
23824
+ function decodeBase64(base64) {
23825
+ try {
23826
+ const binString = atob(base64);
23827
+ const intArray = Uint8Array.from(binString, (m) => m.codePointAt(0));
23828
+ return new TextDecoder().decode(intArray);
23829
+ } catch (error) {
23830
+ console.warn(
23831
+ `Upstash Qstash: Failed while decoding base64 "${base64}". Decoding with atob and returning it instead. ${error}`
23832
+ );
23833
+ return atob(base64);
23834
+ }
23835
+ }
23836
+
23810
23837
  // src/context/steps.ts
23811
23838
  var BaseLazyStep = class {
23812
23839
  stepName;
@@ -23987,6 +24014,41 @@ var LazyNotifyStep = class extends LazyFunctionStep {
23987
24014
  });
23988
24015
  }
23989
24016
  };
24017
+ var LazyInvokeStep = class extends BaseLazyStep {
24018
+ stepType = "Invoke";
24019
+ params;
24020
+ constructor(stepName, { workflow, body, headers = {}, workflowRunId, retries }) {
24021
+ super(stepName);
24022
+ this.params = {
24023
+ workflow,
24024
+ body,
24025
+ headers,
24026
+ workflowRunId: getWorkflowRunId(workflowRunId),
24027
+ retries
24028
+ };
24029
+ }
24030
+ getPlanStep(concurrent, targetStep) {
24031
+ return {
24032
+ stepId: 0,
24033
+ stepName: this.stepName,
24034
+ stepType: this.stepType,
24035
+ concurrent,
24036
+ targetStep
24037
+ };
24038
+ }
24039
+ /**
24040
+ * won't be used as it's the server who will add the result step
24041
+ * in Invoke step.
24042
+ */
24043
+ getResultStep(concurrent, stepId) {
24044
+ return Promise.resolve({
24045
+ stepId,
24046
+ stepName: this.stepName,
24047
+ stepType: this.stepType,
24048
+ concurrent
24049
+ });
24050
+ }
24051
+ };
23990
24052
 
23991
24053
  // node_modules/neverthrow/dist/index.es.js
23992
24054
  var defaultErrorConfig = {
@@ -24411,7 +24473,8 @@ var StepTypes = [
24411
24473
  "SleepUntil",
24412
24474
  "Call",
24413
24475
  "Wait",
24414
- "Notify"
24476
+ "Notify",
24477
+ "Invoke"
24415
24478
  ];
24416
24479
 
24417
24480
  // src/workflow-requests.ts
@@ -24419,7 +24482,7 @@ var import_qstash3 = require("@upstash/qstash");
24419
24482
  var triggerFirstInvocation = async ({
24420
24483
  workflowContext,
24421
24484
  useJSONContent,
24422
- telemetry,
24485
+ telemetry: telemetry2,
24423
24486
  debug
24424
24487
  }) => {
24425
24488
  const { headers } = getHeaders({
@@ -24429,8 +24492,11 @@ var triggerFirstInvocation = async ({
24429
24492
  userHeaders: workflowContext.headers,
24430
24493
  failureUrl: workflowContext.failureUrl,
24431
24494
  retries: workflowContext.retries,
24432
- telemetry
24495
+ telemetry: telemetry2
24433
24496
  });
24497
+ if (workflowContext.headers.get("content-type")) {
24498
+ headers["content-type"] = workflowContext.headers.get("content-type");
24499
+ }
24434
24500
  if (useJSONContent) {
24435
24501
  headers["content-type"] = "application/json";
24436
24502
  }
@@ -24472,8 +24538,8 @@ var triggerRouteFunction = async ({
24472
24538
  debug
24473
24539
  }) => {
24474
24540
  try {
24475
- await onStep();
24476
- await onCleanup();
24541
+ const result = await onStep();
24542
+ await onCleanup(result);
24477
24543
  return ok("workflow-finished");
24478
24544
  } catch (error) {
24479
24545
  const error_ = error;
@@ -24494,14 +24560,15 @@ var triggerRouteFunction = async ({
24494
24560
  }
24495
24561
  }
24496
24562
  };
24497
- var triggerWorkflowDelete = async (workflowContext, debug, cancel = false) => {
24563
+ var triggerWorkflowDelete = async (workflowContext, result, debug, cancel = false) => {
24498
24564
  await debug?.log("SUBMIT", "SUBMIT_CLEANUP", {
24499
24565
  deletedWorkflowRunId: workflowContext.workflowRunId
24500
24566
  });
24501
24567
  await workflowContext.qstashClient.http.request({
24502
24568
  path: ["v2", "workflows", "runs", `${workflowContext.workflowRunId}?cancel=${cancel}`],
24503
24569
  method: "DELETE",
24504
- parseResponseAsJson: false
24570
+ parseResponseAsJson: false,
24571
+ body: JSON.stringify(result)
24505
24572
  });
24506
24573
  await debug?.log(
24507
24574
  "SUBMIT",
@@ -24530,7 +24597,7 @@ var handleThirdPartyCallResult = async ({
24530
24597
  workflowUrl,
24531
24598
  failureUrl,
24532
24599
  retries,
24533
- telemetry,
24600
+ telemetry: telemetry2,
24534
24601
  debug
24535
24602
  }) => {
24536
24603
  try {
@@ -24598,7 +24665,7 @@ ${atob(callbackMessage.body ?? "")}`
24598
24665
  userHeaders,
24599
24666
  failureUrl,
24600
24667
  retries,
24601
- telemetry
24668
+ telemetry: telemetry2
24602
24669
  });
24603
24670
  const callResponse = {
24604
24671
  status: callbackMessage.status,
@@ -24637,11 +24704,11 @@ ${atob(callbackMessage.body ?? "")}`
24637
24704
  );
24638
24705
  }
24639
24706
  };
24640
- var getTelemetryHeaders = (telemetry) => {
24707
+ var getTelemetryHeaders = (telemetry2) => {
24641
24708
  return {
24642
- [TELEMETRY_HEADER_SDK]: telemetry.sdk,
24643
- [TELEMETRY_HEADER_FRAMEWORK]: telemetry.framework,
24644
- [TELEMETRY_HEADER_RUNTIME]: telemetry.runtime ?? "unknown"
24709
+ [TELEMETRY_HEADER_SDK]: telemetry2.sdk,
24710
+ [TELEMETRY_HEADER_FRAMEWORK]: telemetry2.framework,
24711
+ [TELEMETRY_HEADER_RUNTIME]: telemetry2.runtime ?? "unknown"
24645
24712
  };
24646
24713
  };
24647
24714
  var getHeaders = ({
@@ -24654,14 +24721,17 @@ var getHeaders = ({
24654
24721
  step,
24655
24722
  callRetries,
24656
24723
  callTimeout,
24657
- telemetry
24724
+ telemetry: telemetry2
24658
24725
  }) => {
24726
+ const contentType = (userHeaders ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
24659
24727
  const baseHeaders = {
24660
24728
  [WORKFLOW_INIT_HEADER]: initHeaderValue,
24661
24729
  [WORKFLOW_ID_HEADER]: workflowRunId,
24662
24730
  [WORKFLOW_URL_HEADER]: workflowUrl,
24663
24731
  [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
24664
- ...telemetry ? getTelemetryHeaders(telemetry) : {}
24732
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
24733
+ "content-type": contentType,
24734
+ ...telemetry2 ? getTelemetryHeaders(telemetry2) : {}
24665
24735
  };
24666
24736
  if (!step?.callUrl) {
24667
24737
  baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
@@ -24675,6 +24745,9 @@ var getHeaders = ({
24675
24745
  baseHeaders["Upstash-Failure-Callback"] = failureUrl;
24676
24746
  }
24677
24747
  }
24748
+ if (step?.stepType === "Invoke") {
24749
+ baseHeaders["upstash-workflow-invoke"] = "true";
24750
+ }
24678
24751
  if (step?.callUrl) {
24679
24752
  baseHeaders["Upstash-Retries"] = callRetries?.toString() ?? "0";
24680
24753
  baseHeaders[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
@@ -24696,7 +24769,6 @@ var getHeaders = ({
24696
24769
  baseHeaders[`Upstash-Failure-Callback-Forward-${header}`] = userHeaders.get(header);
24697
24770
  }
24698
24771
  }
24699
- const contentType = (userHeaders ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
24700
24772
  if (step?.callHeaders) {
24701
24773
  const forwardedHeaders = Object.fromEntries(
24702
24774
  Object.entries(step.callHeaders).map(([header, value]) => [
@@ -24736,8 +24808,8 @@ var getHeaders = ({
24736
24808
  Object.entries(baseHeaders).map(([header, value]) => [header, [value]])
24737
24809
  ),
24738
24810
  // to include telemetry headers:
24739
- ...telemetry ? Object.fromEntries(
24740
- Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
24811
+ ...telemetry2 ? Object.fromEntries(
24812
+ Object.entries(getTelemetryHeaders(telemetry2)).map(([header, value]) => [
24741
24813
  header,
24742
24814
  [value]
24743
24815
  ])
@@ -24746,8 +24818,7 @@ var getHeaders = ({
24746
24818
  "Upstash-Workflow-Runid": [workflowRunId],
24747
24819
  [WORKFLOW_INIT_HEADER]: ["false"],
24748
24820
  [WORKFLOW_URL_HEADER]: [workflowUrl],
24749
- "Upstash-Workflow-CallType": ["step"],
24750
- "Content-Type": [contentType]
24821
+ "Upstash-Workflow-CallType": ["step"]
24751
24822
  }
24752
24823
  };
24753
24824
  }
@@ -24793,10 +24864,10 @@ var AutoExecutor = class _AutoExecutor {
24793
24864
  stepCount = 0;
24794
24865
  planStepCount = 0;
24795
24866
  executingStep = false;
24796
- constructor(context, steps, telemetry, debug) {
24867
+ constructor(context, steps, telemetry2, debug) {
24797
24868
  this.context = context;
24798
24869
  this.steps = steps;
24799
- this.telemetry = telemetry;
24870
+ this.telemetry = telemetry2;
24800
24871
  this.debug = debug;
24801
24872
  this.nonPlanStepCount = this.steps.filter((step) => !step.targetStep).length;
24802
24873
  }
@@ -25042,7 +25113,23 @@ var AutoExecutor = class _AutoExecutor {
25042
25113
  method: "POST",
25043
25114
  parseResponseAsJson: false
25044
25115
  });
25045
- throw new WorkflowAbort(steps[0].stepName, steps[0]);
25116
+ throw new WorkflowAbort(waitStep.stepName, waitStep);
25117
+ }
25118
+ if (steps.length === 1 && lazySteps[0] instanceof LazyInvokeStep) {
25119
+ const invokeStep = steps[0];
25120
+ const lazyInvokeStep = lazySteps[0];
25121
+ await lazyInvokeStep.params.workflow.callback(
25122
+ {
25123
+ body: lazyInvokeStep.params.body,
25124
+ headers: lazyInvokeStep.params.headers,
25125
+ workflowRunId: lazyInvokeStep.params.workflowRunId,
25126
+ workflow: lazyInvokeStep.params.workflow,
25127
+ retries: lazyInvokeStep.params.retries
25128
+ },
25129
+ invokeStep,
25130
+ this.context
25131
+ );
25132
+ throw new WorkflowAbort(invokeStep.stepName, invokeStep);
25046
25133
  }
25047
25134
  const result = await this.context.qstashClient.batchJSON(
25048
25135
  steps.map((singleStep, index) => {
@@ -25728,7 +25815,7 @@ var WorkflowContext = class {
25728
25815
  initialPayload,
25729
25816
  env,
25730
25817
  retries,
25731
- telemetry
25818
+ telemetry: telemetry2
25732
25819
  }) {
25733
25820
  this.qstashClient = qstashClient;
25734
25821
  this.workflowRunId = workflowRunId;
@@ -25739,7 +25826,7 @@ var WorkflowContext = class {
25739
25826
  this.requestPayload = initialPayload;
25740
25827
  this.env = env ?? {};
25741
25828
  this.retries = retries ?? DEFAULT_RETRIES;
25742
- this.executor = new AutoExecutor(this, this.steps, telemetry, debug);
25829
+ this.executor = new AutoExecutor(this, this.steps, telemetry2, debug);
25743
25830
  }
25744
25831
  /**
25745
25832
  * Executes a workflow step
@@ -25959,6 +26046,13 @@ var WorkflowContext = class {
25959
26046
  return result;
25960
26047
  }
25961
26048
  }
26049
+ async invoke(stepName, settings) {
26050
+ const result = await this.addStep(new LazyInvokeStep(stepName, settings));
26051
+ return {
26052
+ ...result,
26053
+ body: result.body ? JSON.parse(result.body) : void 0
26054
+ };
26055
+ }
25962
26056
  /**
25963
26057
  * Cancel the current workflow run
25964
26058
  *
@@ -26036,31 +26130,6 @@ var WorkflowLogger = class _WorkflowLogger {
26036
26130
  }
26037
26131
  };
26038
26132
 
26039
- // src/utils.ts
26040
- var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
26041
- var NANOID_LENGTH = 21;
26042
- function getRandomInt() {
26043
- return Math.floor(Math.random() * NANOID_CHARS.length);
26044
- }
26045
- function nanoid() {
26046
- return Array.from({ length: NANOID_LENGTH }).map(() => NANOID_CHARS[getRandomInt()]).join("");
26047
- }
26048
- function getWorkflowRunId(id) {
26049
- return `wfr_${id ?? nanoid()}`;
26050
- }
26051
- function decodeBase64(base64) {
26052
- try {
26053
- const binString = atob(base64);
26054
- const intArray = Uint8Array.from(binString, (m) => m.codePointAt(0));
26055
- return new TextDecoder().decode(intArray);
26056
- } catch (error) {
26057
- console.warn(
26058
- `Upstash Qstash: Failed while decoding base64 "${base64}". Decoding with atob and returning it instead. ${error}`
26059
- );
26060
- return atob(base64);
26061
- }
26062
- }
26063
-
26064
26133
  // src/serve/authorization.ts
26065
26134
  var import_qstash8 = require("@upstash/qstash");
26066
26135
  var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowContext {
@@ -26398,7 +26467,7 @@ var determineUrls = async (request, url, baseUrl, failureFunction, failureUrl, d
26398
26467
  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`;
26399
26468
 
26400
26469
  // src/serve/index.ts
26401
- var serveBase = (routeFunction, telemetry, options) => {
26470
+ var serveBase = (routeFunction, telemetry2, options) => {
26402
26471
  const {
26403
26472
  qstashClient,
26404
26473
  onStepFinish,
@@ -26414,7 +26483,7 @@ var serveBase = (routeFunction, telemetry, options) => {
26414
26483
  useJSONContent,
26415
26484
  disableTelemetry
26416
26485
  } = processOptions(options);
26417
- telemetry = disableTelemetry ? void 0 : telemetry;
26486
+ telemetry2 = disableTelemetry ? void 0 : telemetry2;
26418
26487
  const debug = WorkflowLogger.getLogger(verbose);
26419
26488
  const handler = async (request) => {
26420
26489
  await debug?.log("INFO", "ENDPOINT_START");
@@ -26472,7 +26541,7 @@ var serveBase = (routeFunction, telemetry, options) => {
26472
26541
  debug,
26473
26542
  env,
26474
26543
  retries,
26475
- telemetry
26544
+ telemetry: telemetry2
26476
26545
  });
26477
26546
  const authCheck = await DisabledWorkflowContext.tryAuthentication(
26478
26547
  routeFunction,
@@ -26495,7 +26564,7 @@ var serveBase = (routeFunction, telemetry, options) => {
26495
26564
  workflowUrl,
26496
26565
  failureUrl: workflowFailureUrl,
26497
26566
  retries,
26498
- telemetry,
26567
+ telemetry: telemetry2,
26499
26568
  debug
26500
26569
  });
26501
26570
  if (callReturnCheck.isErr()) {
@@ -26504,10 +26573,10 @@ var serveBase = (routeFunction, telemetry, options) => {
26504
26573
  });
26505
26574
  throw callReturnCheck.error;
26506
26575
  } else if (callReturnCheck.value === "continue-workflow") {
26507
- const result = isFirstInvocation ? await triggerFirstInvocation({ workflowContext, useJSONContent, telemetry, debug }) : await triggerRouteFunction({
26576
+ const result = isFirstInvocation ? await triggerFirstInvocation({ workflowContext, useJSONContent, telemetry: telemetry2, debug }) : await triggerRouteFunction({
26508
26577
  onStep: async () => routeFunction(workflowContext),
26509
- onCleanup: async () => {
26510
- await triggerWorkflowDelete(workflowContext, debug);
26578
+ onCleanup: async (result2) => {
26579
+ await triggerWorkflowDelete(workflowContext, result2, debug);
26511
26580
  },
26512
26581
  onCancel: async () => {
26513
26582
  await makeCancelRequest(workflowContext.qstashClient.http, workflowRunId);
@@ -26541,15 +26610,112 @@ var serveBase = (routeFunction, telemetry, options) => {
26541
26610
 
26542
26611
  // platforms/express.ts
26543
26612
  var import_express = __toESM(require_express2());
26544
- function serve(routeFunction, options) {
26545
- const router = (0, import_express.Router)();
26546
- const handler = async (request_, res) => {
26613
+
26614
+ // src/serve/serve-many.ts
26615
+ var serveManyBase = ({
26616
+ workflows,
26617
+ getWorkflowId
26618
+ }) => {
26619
+ const workflowIds = [];
26620
+ const workflowMap = Object.fromEntries(
26621
+ Object.entries(workflows).map((workflow) => {
26622
+ const workflowId = workflow[0];
26623
+ if (workflowIds.includes(workflowId)) {
26624
+ throw new WorkflowError(
26625
+ `Duplicate workflow name found: '${workflowId}'. Please set different workflow names in serveMany.`
26626
+ );
26627
+ }
26628
+ if (workflowId.includes("/")) {
26629
+ throw new WorkflowError(
26630
+ `Invalid workflow name found: '${workflowId}'. Workflow name cannot contain '/'.`
26631
+ );
26632
+ }
26633
+ workflowIds.push(workflowId);
26634
+ workflow[1].workflowId = workflowId;
26635
+ return [workflowId, workflow[1].handler];
26636
+ })
26637
+ );
26638
+ return {
26639
+ handler: async (...params) => {
26640
+ const pickedWorkflowId = getWorkflowId(...params);
26641
+ if (!pickedWorkflowId) {
26642
+ throw new WorkflowError(`Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`);
26643
+ }
26644
+ const workflow = workflowMap[pickedWorkflowId];
26645
+ if (!workflow) {
26646
+ throw new WorkflowError(`No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`);
26647
+ }
26648
+ return await workflow(...params);
26649
+ }
26650
+ };
26651
+ };
26652
+ var createInvokeCallback = (telemetry2) => {
26653
+ const invokeCallback = async (settings, invokeStep, context) => {
26654
+ const { body, workflow, headers = {}, workflowRunId = getWorkflowRunId(), retries } = settings;
26655
+ const { workflowId } = workflow;
26656
+ if (!workflowId) {
26657
+ throw new WorkflowError("You can only invoke workflow which has a workflowId");
26658
+ }
26659
+ const { headers: invokerHeaders } = getHeaders({
26660
+ initHeaderValue: "false",
26661
+ workflowRunId: context.workflowRunId,
26662
+ workflowUrl: context.url,
26663
+ userHeaders: context.headers,
26664
+ failureUrl: context.failureUrl,
26665
+ retries: context.retries,
26666
+ telemetry: telemetry2
26667
+ });
26668
+ invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
26669
+ const newUrl = context.url.replace(/[^/]+$/, workflowId);
26670
+ const { headers: triggerHeaders } = getHeaders({
26671
+ initHeaderValue: "true",
26672
+ workflowRunId,
26673
+ workflowUrl: newUrl,
26674
+ userHeaders: new Headers(headers),
26675
+ retries,
26676
+ telemetry: telemetry2
26677
+ });
26678
+ triggerHeaders["Upstash-Workflow-Invoke"] = "true";
26679
+ const request = {
26680
+ body: JSON.stringify(body),
26681
+ headers: Object.fromEntries(
26682
+ Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
26683
+ ),
26684
+ workflowRunId,
26685
+ workflowUrl: context.url,
26686
+ step: invokeStep
26687
+ };
26688
+ await context.qstashClient.publish({
26689
+ headers: triggerHeaders,
26690
+ method: "POST",
26691
+ body: JSON.stringify(request),
26692
+ url: newUrl
26693
+ });
26694
+ return void 0;
26695
+ };
26696
+ return invokeCallback;
26697
+ };
26698
+
26699
+ // platforms/express.ts
26700
+ var isEmptyRequest = (req) => {
26701
+ return req.headers["content-type"] === "application/json" && req.headers["content-length"] === "0";
26702
+ };
26703
+ var telemetry = {
26704
+ sdk: SDK_TELEMETRY,
26705
+ framework: "express",
26706
+ runtime: process.versions.bun ? `bun@${process.versions.bun}/node@${process.version}` : `node@${process.version}`
26707
+ };
26708
+ function createExpressHandler(params) {
26709
+ const [routeFunction, options] = params;
26710
+ return async (request_, res) => {
26547
26711
  if (request_.method.toUpperCase() !== "POST") {
26548
26712
  res.status(405).json("Only POST requests are allowed in workflows");
26549
26713
  return;
26550
26714
  }
26551
26715
  let requestBody;
26552
- if (request_.headers["content-type"]?.includes("text/plain")) {
26716
+ if (isEmptyRequest(request_)) {
26717
+ requestBody = "";
26718
+ } else if (request_.headers["content-type"]?.includes("text/plain")) {
26553
26719
  requestBody = request_.body;
26554
26720
  } else if (request_.headers["content-type"]?.includes("application/json")) {
26555
26721
  requestBody = JSON.stringify(request_.body);
@@ -26566,11 +26732,7 @@ function serve(routeFunction, options) {
26566
26732
  });
26567
26733
  const { handler: serveHandler } = serveBase(
26568
26734
  routeFunction,
26569
- {
26570
- sdk: SDK_TELEMETRY,
26571
- framework: "express",
26572
- runtime: process.versions.bun ? `bun@${process.versions.bun}/node@${process.version}` : `node@${process.version}`
26573
- },
26735
+ telemetry,
26574
26736
  {
26575
26737
  ...options,
26576
26738
  useJSONContent: true
@@ -26579,12 +26741,38 @@ function serve(routeFunction, options) {
26579
26741
  const response = await serveHandler(webRequest);
26580
26742
  res.status(response.status).json(await response.json());
26581
26743
  };
26744
+ }
26745
+ function serve(routeFunction, options) {
26746
+ const router = (0, import_express.Router)();
26747
+ const handler = createExpressHandler([routeFunction, options]);
26582
26748
  router.all("*", handler);
26583
26749
  return router;
26584
26750
  }
26751
+ var createWorkflow = (...params) => {
26752
+ const handler = createExpressHandler(params);
26753
+ return {
26754
+ callback: createInvokeCallback(telemetry),
26755
+ handler,
26756
+ workflowId: void 0
26757
+ };
26758
+ };
26759
+ var serveMany = (workflows) => {
26760
+ const router = (0, import_express.Router)();
26761
+ const { handler } = serveManyBase({
26762
+ workflows,
26763
+ getWorkflowId(...params) {
26764
+ const components = params[0].url.split("/");
26765
+ return components[components.length - 1];
26766
+ }
26767
+ });
26768
+ router.all("*", handler);
26769
+ return router;
26770
+ };
26585
26771
  // Annotate the CommonJS export names for ESM import in node:
26586
26772
  0 && (module.exports = {
26587
- serve
26773
+ createWorkflow,
26774
+ serve,
26775
+ serveMany
26588
26776
  });
26589
26777
  /*! Bundled license information:
26590
26778
 
package/express.mjs CHANGED
@@ -1,10 +1,14 @@
1
+ import {
2
+ createInvokeCallback,
3
+ serveManyBase
4
+ } from "./chunk-LCZMBGEM.mjs";
1
5
  import {
2
6
  SDK_TELEMETRY,
3
7
  __commonJS,
4
8
  __require,
5
9
  __toESM,
6
10
  serveBase
7
- } from "./chunk-OLNSY3BB.mjs";
11
+ } from "./chunk-IWAW7GIG.mjs";
8
12
 
9
13
  // node_modules/depd/index.js
10
14
  var require_depd = __commonJS({
@@ -23667,15 +23671,25 @@ var require_express2 = __commonJS({
23667
23671
 
23668
23672
  // platforms/express.ts
23669
23673
  var import_express = __toESM(require_express2());
23670
- function serve(routeFunction, options) {
23671
- const router = (0, import_express.Router)();
23672
- const handler = async (request_, res) => {
23674
+ var isEmptyRequest = (req) => {
23675
+ return req.headers["content-type"] === "application/json" && req.headers["content-length"] === "0";
23676
+ };
23677
+ var telemetry = {
23678
+ sdk: SDK_TELEMETRY,
23679
+ framework: "express",
23680
+ runtime: process.versions.bun ? `bun@${process.versions.bun}/node@${process.version}` : `node@${process.version}`
23681
+ };
23682
+ function createExpressHandler(params) {
23683
+ const [routeFunction, options] = params;
23684
+ return async (request_, res) => {
23673
23685
  if (request_.method.toUpperCase() !== "POST") {
23674
23686
  res.status(405).json("Only POST requests are allowed in workflows");
23675
23687
  return;
23676
23688
  }
23677
23689
  let requestBody;
23678
- if (request_.headers["content-type"]?.includes("text/plain")) {
23690
+ if (isEmptyRequest(request_)) {
23691
+ requestBody = "";
23692
+ } else if (request_.headers["content-type"]?.includes("text/plain")) {
23679
23693
  requestBody = request_.body;
23680
23694
  } else if (request_.headers["content-type"]?.includes("application/json")) {
23681
23695
  requestBody = JSON.stringify(request_.body);
@@ -23692,11 +23706,7 @@ function serve(routeFunction, options) {
23692
23706
  });
23693
23707
  const { handler: serveHandler } = serveBase(
23694
23708
  routeFunction,
23695
- {
23696
- sdk: SDK_TELEMETRY,
23697
- framework: "express",
23698
- runtime: process.versions.bun ? `bun@${process.versions.bun}/node@${process.version}` : `node@${process.version}`
23699
- },
23709
+ telemetry,
23700
23710
  {
23701
23711
  ...options,
23702
23712
  useJSONContent: true
@@ -23705,11 +23715,37 @@ function serve(routeFunction, options) {
23705
23715
  const response = await serveHandler(webRequest);
23706
23716
  res.status(response.status).json(await response.json());
23707
23717
  };
23718
+ }
23719
+ function serve(routeFunction, options) {
23720
+ const router = (0, import_express.Router)();
23721
+ const handler = createExpressHandler([routeFunction, options]);
23708
23722
  router.all("*", handler);
23709
23723
  return router;
23710
23724
  }
23725
+ var createWorkflow = (...params) => {
23726
+ const handler = createExpressHandler(params);
23727
+ return {
23728
+ callback: createInvokeCallback(telemetry),
23729
+ handler,
23730
+ workflowId: void 0
23731
+ };
23732
+ };
23733
+ var serveMany = (workflows) => {
23734
+ const router = (0, import_express.Router)();
23735
+ const { handler } = serveManyBase({
23736
+ workflows,
23737
+ getWorkflowId(...params) {
23738
+ const components = params[0].url.split("/");
23739
+ return components[components.length - 1];
23740
+ }
23741
+ });
23742
+ router.all("*", handler);
23743
+ return router;
23744
+ };
23711
23745
  export {
23712
- serve
23746
+ createWorkflow,
23747
+ serve,
23748
+ serveMany
23713
23749
  };
23714
23750
  /*! Bundled license information:
23715
23751
 
package/h3.d.mts CHANGED
@@ -1,15 +1,17 @@
1
1
  import * as h3 from 'h3';
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
+ import { s as serveManyBase } from './serve-many-BlBvXfBS.mjs';
3
4
  import '@upstash/qstash';
4
5
  import 'zod';
5
6
  import 'ai';
6
7
  import '@ai-sdk/openai';
7
8
 
8
- declare const serve: <TInitialPayload = unknown>(routeFunction: RouteFunction<TInitialPayload>, options?: PublicServeOptions<TInitialPayload>) => {
9
- handler: h3.EventHandler<h3.EventHandlerRequest, Promise<Response | {
10
- status: number;
11
- body: string;
12
- }>>;
9
+ declare const serve: <TInitialPayload = unknown, TResult = unknown>(routeFunction: RouteFunction<TInitialPayload, TResult>, options?: PublicServeOptions<TInitialPayload>) => {
10
+ handler: h3.EventHandler<h3.EventHandlerRequest, Promise<Response>>;
11
+ };
12
+ declare const createWorkflow: <TInitialPayload, TResult>(routeFunction: RouteFunction<TInitialPayload, TResult>, options?: PublicServeOptions<TInitialPayload> | undefined) => InvokableWorkflow<TInitialPayload, TResult, Parameters<ReturnType<typeof serve<TInitialPayload, TResult>>["handler"]>>;
13
+ declare const serveMany: (workflows: Parameters<typeof serveManyBase>[0]["workflows"]) => {
14
+ handler: (event: h3.H3Event<h3.EventHandlerRequest>) => Promise<any>;
13
15
  };
14
16
 
15
- export { serve };
17
+ export { createWorkflow, serve, serveMany };