@upstash/workflow 0.2.0 → 0.2.2

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/astro.d.mts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { APIContext, APIRoute } from 'astro';
2
- import { b as WorkflowContext, W as WorkflowServeOptions } from './types-Cki_MHrh.mjs';
2
+ import { b as WorkflowContext, j as PublicServeOptions } from './types-APRap-aV.mjs';
3
3
  import '@upstash/qstash';
4
4
 
5
- declare function serve<TInitialPayload = unknown>(routeFunction: (workflowContext: WorkflowContext<TInitialPayload>, apiContext: APIContext) => Promise<void>, options?: Omit<WorkflowServeOptions<Response, TInitialPayload>, "onStepFinish">): {
5
+ declare function serve<TInitialPayload = unknown>(routeFunction: (workflowContext: WorkflowContext<TInitialPayload>, apiContext: APIContext) => Promise<void>, options?: PublicServeOptions<TInitialPayload>): {
6
6
  POST: APIRoute;
7
7
  };
8
8
 
package/astro.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { APIContext, APIRoute } from 'astro';
2
- import { b as WorkflowContext, W as WorkflowServeOptions } from './types-Cki_MHrh.js';
2
+ import { b as WorkflowContext, j as PublicServeOptions } from './types-APRap-aV.js';
3
3
  import '@upstash/qstash';
4
4
 
5
- declare function serve<TInitialPayload = unknown>(routeFunction: (workflowContext: WorkflowContext<TInitialPayload>, apiContext: APIContext) => Promise<void>, options?: Omit<WorkflowServeOptions<Response, TInitialPayload>, "onStepFinish">): {
5
+ declare function serve<TInitialPayload = unknown>(routeFunction: (workflowContext: WorkflowContext<TInitialPayload>, apiContext: APIContext) => Promise<void>, options?: PublicServeOptions<TInitialPayload>): {
6
6
  POST: APIRoute;
7
7
  };
8
8
 
package/astro.js CHANGED
@@ -20,52 +20,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // platforms/astro.ts
21
21
  var astro_exports = {};
22
22
  __export(astro_exports, {
23
- serve: () => serve2
23
+ serve: () => serve
24
24
  });
25
25
  module.exports = __toCommonJS(astro_exports);
26
26
 
27
- // src/error.ts
28
- var import_qstash = require("@upstash/qstash");
29
- var WorkflowError = class extends import_qstash.QstashError {
30
- constructor(message) {
31
- super(message);
32
- this.name = "WorkflowError";
33
- }
34
- };
35
- var WorkflowAbort = class extends Error {
36
- stepInfo;
37
- stepName;
38
- /**
39
- * whether workflow is to be canceled on abort
40
- */
41
- cancelWorkflow;
42
- /**
43
- *
44
- * @param stepName name of the aborting step
45
- * @param stepInfo step information
46
- * @param cancelWorkflow
47
- */
48
- constructor(stepName, stepInfo, cancelWorkflow = false) {
49
- super(
50
- `This is an Upstash Workflow error thrown after a step executes. It is expected to be raised. Make sure that you await for each step. Also, if you are using try/catch blocks, you should not wrap context.run/sleep/sleepUntil/call methods with try/catch. Aborting workflow after executing step '${stepName}'.`
51
- );
52
- this.name = "WorkflowAbort";
53
- this.stepName = stepName;
54
- this.stepInfo = stepInfo;
55
- this.cancelWorkflow = cancelWorkflow;
56
- }
57
- };
58
- var formatWorkflowError = (error) => {
59
- return error instanceof Error ? {
60
- error: error.name,
61
- message: error.message
62
- } : {
63
- error: "Error",
64
- message: "An error occured while executing workflow."
65
- };
66
- };
67
-
68
27
  // src/client/utils.ts
28
+ var import_qstash = require("@upstash/qstash");
69
29
  var makeNotifyRequest = async (requester, eventId, eventData) => {
70
30
  const result = await requester.request({
71
31
  path: ["v2", "notify", eventId],
@@ -92,32 +52,82 @@ var getSteps = async (requester, workflowRunId, messageId, debug) => {
92
52
  await debug?.log("INFO", "ENDPOINT_START", {
93
53
  message: `Pulled ${steps.length} steps from QStashand returned them without filtering with messageId.`
94
54
  });
95
- return steps;
55
+ return { steps, workflowRunEnded: false };
96
56
  } else {
97
57
  const index = steps.findIndex((item) => item.messageId === messageId);
98
58
  if (index === -1) {
99
- return [];
59
+ return { steps: [], workflowRunEnded: false };
100
60
  }
101
61
  const filteredSteps = steps.slice(0, index + 1);
102
62
  await debug?.log("INFO", "ENDPOINT_START", {
103
63
  message: `Pulled ${steps.length} steps from QStash and filtered them to ${filteredSteps.length} using messageId.`
104
64
  });
105
- return filteredSteps;
65
+ return { steps: filteredSteps, workflowRunEnded: false };
106
66
  }
107
67
  } catch (error) {
108
- await debug?.log("ERROR", "ERROR", {
109
- message: "failed while fetching steps.",
110
- error
111
- });
112
- throw new WorkflowError(`Failed while pulling steps. ${error}`);
68
+ if (error instanceof import_qstash.QstashError && error.status === 404) {
69
+ await debug?.log("WARN", "ENDPOINT_START", {
70
+ message: "Couldn't fetch workflow run steps. This can happen if the workflow run succesfully ends before some callback is executed.",
71
+ error
72
+ });
73
+ return { steps: void 0, workflowRunEnded: true };
74
+ } else {
75
+ throw error;
76
+ }
113
77
  }
114
78
  };
115
79
 
80
+ // src/error.ts
81
+ var import_qstash2 = require("@upstash/qstash");
82
+ var WorkflowError = class extends import_qstash2.QstashError {
83
+ constructor(message) {
84
+ super(message);
85
+ this.name = "WorkflowError";
86
+ }
87
+ };
88
+ var WorkflowAbort = class extends Error {
89
+ stepInfo;
90
+ stepName;
91
+ /**
92
+ * whether workflow is to be canceled on abort
93
+ */
94
+ cancelWorkflow;
95
+ /**
96
+ *
97
+ * @param stepName name of the aborting step
98
+ * @param stepInfo step information
99
+ * @param cancelWorkflow
100
+ */
101
+ constructor(stepName, stepInfo, cancelWorkflow = false) {
102
+ super(
103
+ `This is an Upstash Workflow error thrown after a step executes. It is expected to be raised. Make sure that you await for each step. Also, if you are using try/catch blocks, you should not wrap context.run/sleep/sleepUntil/call methods with try/catch. Aborting workflow after executing step '${stepName}'.`
104
+ );
105
+ this.name = "WorkflowAbort";
106
+ this.stepName = stepName;
107
+ this.stepInfo = stepInfo;
108
+ this.cancelWorkflow = cancelWorkflow;
109
+ }
110
+ };
111
+ var formatWorkflowError = (error) => {
112
+ return error instanceof Error ? {
113
+ error: error.name,
114
+ message: error.message
115
+ } : {
116
+ error: "Error",
117
+ message: "An error occured while executing workflow."
118
+ };
119
+ };
120
+
116
121
  // src/context/steps.ts
117
122
  var BaseLazyStep = class {
118
123
  stepName;
119
124
  // will be set in the subclasses
120
125
  constructor(stepName) {
126
+ if (!stepName) {
127
+ throw new WorkflowError(
128
+ "A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
129
+ );
130
+ }
121
131
  this.stepName = stepName;
122
132
  }
123
133
  };
@@ -210,15 +220,17 @@ var LazyCallStep = class extends BaseLazyStep {
210
220
  method;
211
221
  body;
212
222
  headers;
213
- stepType = "Call";
214
223
  retries;
215
- constructor(stepName, url, method, body, headers, retries) {
224
+ timeout;
225
+ stepType = "Call";
226
+ constructor(stepName, url, method, body, headers, retries, timeout) {
216
227
  super(stepName);
217
228
  this.url = url;
218
229
  this.method = method;
219
230
  this.body = body;
220
231
  this.headers = headers;
221
232
  this.retries = retries;
233
+ this.timeout = timeout;
222
234
  }
223
235
  getPlanStep(concurrent, targetStep) {
224
236
  return {
@@ -726,8 +738,8 @@ var StepTypes = [
726
738
  ];
727
739
 
728
740
  // src/workflow-requests.ts
729
- var import_qstash2 = require("@upstash/qstash");
730
- var triggerFirstInvocation = async (workflowContext, retries, debug) => {
741
+ var import_qstash3 = require("@upstash/qstash");
742
+ var triggerFirstInvocation = async (workflowContext, retries, useJSONContent, debug) => {
731
743
  const { headers } = getHeaders(
732
744
  "true",
733
745
  workflowContext.workflowRunId,
@@ -737,6 +749,9 @@ var triggerFirstInvocation = async (workflowContext, retries, debug) => {
737
749
  workflowContext.failureUrl,
738
750
  retries
739
751
  );
752
+ if (useJSONContent) {
753
+ headers["content-type"] = "application/json";
754
+ }
740
755
  try {
741
756
  const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
742
757
  const result = await workflowContext.qstashClient.publish({
@@ -780,7 +795,7 @@ var triggerRouteFunction = async ({
780
795
  return ok("workflow-finished");
781
796
  } catch (error) {
782
797
  const error_ = error;
783
- if (error instanceof import_qstash2.QstashError && error.status === 400) {
798
+ if (error instanceof import_qstash3.QstashError && error.status === 400) {
784
799
  await debug?.log("WARN", "RESPONSE_WORKFLOW", {
785
800
  message: `tried to append to a cancelled workflow. exiting without publishing.`,
786
801
  name: error.name,
@@ -814,7 +829,7 @@ var triggerWorkflowDelete = async (workflowContext, debug, cancel = false) => {
814
829
  );
815
830
  return { deleted: true };
816
831
  } catch (error) {
817
- if (error instanceof import_qstash2.QstashError && error.status === 404) {
832
+ if (error instanceof import_qstash3.QstashError && error.status === 404) {
818
833
  await debug?.log("WARN", "SUBMIT_CLEANUP", {
819
834
  message: `Failed to remove workflow run ${workflowContext.workflowRunId} as it doesn't exist.`,
820
835
  name: error.name,
@@ -830,7 +845,10 @@ var recreateUserHeaders = (headers) => {
830
845
  const pairs = headers.entries();
831
846
  for (const [header, value] of pairs) {
832
847
  const headerLowerCase = header.toLowerCase();
833
- if (!headerLowerCase.startsWith("upstash-workflow-") && !headerLowerCase.startsWith("x-vercel-") && !headerLowerCase.startsWith("x-forwarded-") && headerLowerCase !== "cf-connecting-ip") {
848
+ if (!headerLowerCase.startsWith("upstash-workflow-") && // https://vercel.com/docs/edge-network/headers/request-headers#x-vercel-id
849
+ !headerLowerCase.startsWith("x-vercel-") && !headerLowerCase.startsWith("x-forwarded-") && // https://blog.cloudflare.com/preventing-request-loops-using-cdn-loop/
850
+ headerLowerCase !== "cf-connecting-ip" && headerLowerCase !== "cdn-loop" && headerLowerCase !== "cf-ew-via" && headerLowerCase !== "cf-ray" && // For Render https://render.com
851
+ headerLowerCase !== "render-proxy-ttl") {
834
852
  filteredHeaders.append(header, value);
835
853
  }
836
854
  }
@@ -848,11 +866,19 @@ var handleThirdPartyCallResult = async (request, requestPayload, client, workflo
848
866
  if (!workflowRunId2)
849
867
  throw new WorkflowError("workflow run id missing in context.call lazy fetch.");
850
868
  if (!messageId) throw new WorkflowError("message id missing in context.call lazy fetch.");
851
- const steps = await getSteps(client.http, workflowRunId2, messageId, debug);
869
+ const { steps, workflowRunEnded } = await getSteps(
870
+ client.http,
871
+ workflowRunId2,
872
+ messageId,
873
+ debug
874
+ );
875
+ if (workflowRunEnded) {
876
+ return ok("workflow-ended");
877
+ }
852
878
  const failingStep = steps.find((step) => step.messageId === messageId);
853
879
  if (!failingStep)
854
880
  throw new WorkflowError(
855
- "Failed to submit the context.call." + (steps.length === 0 ? "No steps found." : `No step was found with matching messageId ${messageId} out of ${steps.length} steps.`)
881
+ "Failed to submit the context.call. " + (steps.length === 0 ? "No steps found." : `No step was found with matching messageId ${messageId} out of ${steps.length} steps.`)
856
882
  );
857
883
  callbackPayload = atob(failingStep.body);
858
884
  }
@@ -933,7 +959,7 @@ ${atob(callbackMessage.body ?? "")}`
933
959
  );
934
960
  }
935
961
  };
936
- var getHeaders = (initHeaderValue, workflowRunId, workflowUrl, userHeaders, step, failureUrl, retries, callRetries) => {
962
+ var getHeaders = (initHeaderValue, workflowRunId, workflowUrl, userHeaders, step, failureUrl, retries, callRetries, callTimeout) => {
937
963
  const baseHeaders = {
938
964
  [WORKFLOW_INIT_HEADER]: initHeaderValue,
939
965
  [WORKFLOW_ID_HEADER]: workflowRunId,
@@ -943,6 +969,9 @@ var getHeaders = (initHeaderValue, workflowRunId, workflowUrl, userHeaders, step
943
969
  if (!step?.callUrl) {
944
970
  baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
945
971
  }
972
+ if (callTimeout) {
973
+ baseHeaders[`Upstash-Timeout`] = callTimeout.toString();
974
+ }
946
975
  if (failureUrl) {
947
976
  baseHeaders[`Upstash-Failure-Callback-Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
948
977
  if (!step?.callUrl) {
@@ -1318,7 +1347,8 @@ var AutoExecutor = class _AutoExecutor {
1318
1347
  singleStep,
1319
1348
  this.context.failureUrl,
1320
1349
  this.context.retries,
1321
- lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0
1350
+ lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
1351
+ lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0
1322
1352
  );
1323
1353
  const willWait = singleStep.concurrent === NO_CONCURRENCY || singleStep.stepId === 0;
1324
1354
  singleStep.out = JSON.stringify(singleStep.out);
@@ -1668,6 +1698,7 @@ var WorkflowContext = class {
1668
1698
  * @param body call body
1669
1699
  * @param headers call headers
1670
1700
  * @param retries number of call retries. 0 by default
1701
+ * @param timeout max duration to wait for the endpoint to respond. in seconds.
1671
1702
  * @returns call result as {
1672
1703
  * status: number;
1673
1704
  * body: unknown;
@@ -1675,9 +1706,17 @@ var WorkflowContext = class {
1675
1706
  * }
1676
1707
  */
1677
1708
  async call(stepName, settings) {
1678
- const { url, method = "GET", body, headers = {}, retries = 0 } = settings;
1709
+ const { url, method = "GET", body, headers = {}, retries = 0, timeout } = settings;
1679
1710
  const result = await this.addStep(
1680
- new LazyCallStep(stepName, url, method, body, headers, retries)
1711
+ new LazyCallStep(
1712
+ stepName,
1713
+ url,
1714
+ method,
1715
+ body,
1716
+ headers,
1717
+ retries,
1718
+ timeout
1719
+ )
1681
1720
  );
1682
1721
  if (typeof result === "string") {
1683
1722
  try {
@@ -1878,7 +1917,7 @@ function decodeBase64(base64) {
1878
1917
  }
1879
1918
 
1880
1919
  // src/serve/authorization.ts
1881
- var import_qstash3 = require("@upstash/qstash");
1920
+ var import_qstash4 = require("@upstash/qstash");
1882
1921
  var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowContext {
1883
1922
  static disabledMessage = "disabled-qstash-worklfow-run";
1884
1923
  /**
@@ -1909,7 +1948,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
1909
1948
  */
1910
1949
  static async tryAuthentication(routeFunction, context) {
1911
1950
  const disabledContext = new _DisabledWorkflowContext({
1912
- qstashClient: new import_qstash3.Client({
1951
+ qstashClient: new import_qstash4.Client({
1913
1952
  baseUrl: "disabled-client",
1914
1953
  token: "disabled-client"
1915
1954
  }),
@@ -2033,7 +2072,8 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
2033
2072
  return {
2034
2073
  rawInitialPayload: requestPayload ?? "",
2035
2074
  steps: [],
2036
- isLastDuplicate: false
2075
+ isLastDuplicate: false,
2076
+ workflowRunEnded: false
2037
2077
  };
2038
2078
  } else {
2039
2079
  let rawSteps;
@@ -2043,7 +2083,21 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
2043
2083
  "ENDPOINT_START",
2044
2084
  "request payload is empty, steps will be fetched from QStash."
2045
2085
  );
2046
- rawSteps = await getSteps(requester, workflowRunId, messageId, debug);
2086
+ const { steps: fetchedSteps, workflowRunEnded } = await getSteps(
2087
+ requester,
2088
+ workflowRunId,
2089
+ messageId,
2090
+ debug
2091
+ );
2092
+ if (workflowRunEnded) {
2093
+ return {
2094
+ rawInitialPayload: void 0,
2095
+ steps: void 0,
2096
+ isLastDuplicate: void 0,
2097
+ workflowRunEnded: true
2098
+ };
2099
+ }
2100
+ rawSteps = fetchedSteps;
2047
2101
  } else {
2048
2102
  rawSteps = JSON.parse(requestPayload);
2049
2103
  }
@@ -2053,7 +2107,8 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
2053
2107
  return {
2054
2108
  rawInitialPayload,
2055
2109
  steps: deduplicatedSteps,
2056
- isLastDuplicate
2110
+ isLastDuplicate,
2111
+ workflowRunEnded: false
2057
2112
  };
2058
2113
  }
2059
2114
  };
@@ -2077,7 +2132,7 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
2077
2132
  const workflowContext = new WorkflowContext({
2078
2133
  qstashClient,
2079
2134
  workflowRunId,
2080
- initialPayload: initialPayloadParser(decodeBase64(sourceBody)),
2135
+ initialPayload: sourceBody ? initialPayloadParser(decodeBase64(sourceBody)) : void 0,
2081
2136
  headers: recreateUserHeaders(new Headers(sourceHeader)),
2082
2137
  steps: [],
2083
2138
  url,
@@ -2107,22 +2162,35 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
2107
2162
  };
2108
2163
 
2109
2164
  // src/serve/options.ts
2110
- var import_qstash4 = require("@upstash/qstash");
2111
2165
  var import_qstash5 = require("@upstash/qstash");
2166
+ var import_qstash6 = require("@upstash/qstash");
2112
2167
  var processOptions = (options) => {
2113
2168
  const environment = options?.env ?? (typeof process === "undefined" ? {} : process.env);
2114
2169
  const receiverEnvironmentVariablesSet = Boolean(
2115
2170
  environment.QSTASH_CURRENT_SIGNING_KEY && environment.QSTASH_NEXT_SIGNING_KEY
2116
2171
  );
2117
2172
  return {
2118
- qstashClient: new import_qstash5.Client({
2173
+ qstashClient: new import_qstash6.Client({
2119
2174
  baseUrl: environment.QSTASH_URL,
2120
2175
  token: environment.QSTASH_TOKEN
2121
2176
  }),
2122
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2123
- onStepFinish: (workflowRunId, _finishCondition) => new Response(JSON.stringify({ workflowRunId }), {
2124
- status: 200
2125
- }),
2177
+ onStepFinish: (workflowRunId, finishCondition) => {
2178
+ if (finishCondition === "auth-fail") {
2179
+ console.error(AUTH_FAIL_MESSAGE);
2180
+ return new Response(
2181
+ JSON.stringify({
2182
+ message: AUTH_FAIL_MESSAGE,
2183
+ workflowRunId
2184
+ }),
2185
+ {
2186
+ status: 400
2187
+ }
2188
+ );
2189
+ }
2190
+ return new Response(JSON.stringify({ workflowRunId }), {
2191
+ status: 200
2192
+ });
2193
+ },
2126
2194
  initialPayloadParser: (initialRequest) => {
2127
2195
  if (!initialRequest) {
2128
2196
  return void 0;
@@ -2136,13 +2204,14 @@ var processOptions = (options) => {
2136
2204
  throw error;
2137
2205
  }
2138
2206
  },
2139
- receiver: receiverEnvironmentVariablesSet ? new import_qstash4.Receiver({
2207
+ receiver: receiverEnvironmentVariablesSet ? new import_qstash5.Receiver({
2140
2208
  currentSigningKey: environment.QSTASH_CURRENT_SIGNING_KEY,
2141
2209
  nextSigningKey: environment.QSTASH_NEXT_SIGNING_KEY
2142
2210
  }) : void 0,
2143
2211
  baseUrl: environment.UPSTASH_WORKFLOW_URL,
2144
2212
  env: environment,
2145
2213
  retries: DEFAULT_RETRIES,
2214
+ useJSONContent: false,
2146
2215
  ...options
2147
2216
  };
2148
2217
  };
@@ -2159,14 +2228,25 @@ var determineUrls = async (request, url, baseUrl, failureFunction, failureUrl, d
2159
2228
  });
2160
2229
  }
2161
2230
  const workflowFailureUrl = failureFunction ? workflowUrl : failureUrl;
2231
+ if (workflowUrl.includes("localhost")) {
2232
+ await debug?.log("WARN", "ENDPOINT_START", {
2233
+ message: `Workflow URL contains localhost. This can happen in local development, but shouldn't happen in production unless you have a route which contains localhost. Received: ${workflowUrl}`
2234
+ });
2235
+ }
2236
+ if (!(workflowUrl.startsWith("http://") || workflowUrl.startsWith("https://"))) {
2237
+ throw new WorkflowError(
2238
+ `Workflow URL should start with 'http://' or 'https://'. Recevied is '${workflowUrl}'`
2239
+ );
2240
+ }
2162
2241
  return {
2163
2242
  workflowUrl,
2164
2243
  workflowFailureUrl
2165
2244
  };
2166
2245
  };
2246
+ 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`;
2167
2247
 
2168
2248
  // src/serve/index.ts
2169
- var serve = (routeFunction, options) => {
2249
+ var serveBase = (routeFunction, options) => {
2170
2250
  const {
2171
2251
  qstashClient,
2172
2252
  onStepFinish,
@@ -2178,7 +2258,8 @@ var serve = (routeFunction, options) => {
2178
2258
  failureFunction,
2179
2259
  baseUrl,
2180
2260
  env,
2181
- retries
2261
+ retries,
2262
+ useJSONContent
2182
2263
  } = processOptions(options);
2183
2264
  const debug = WorkflowLogger.getLogger(verbose);
2184
2265
  const handler = async (request) => {
@@ -2195,7 +2276,7 @@ var serve = (routeFunction, options) => {
2195
2276
  await verifyRequest(requestPayload, request.headers.get("upstash-signature"), receiver);
2196
2277
  const { isFirstInvocation, workflowRunId } = validateRequest(request);
2197
2278
  debug?.setWorkflowRunId(workflowRunId);
2198
- const { rawInitialPayload, steps, isLastDuplicate } = await parseRequest(
2279
+ const { rawInitialPayload, steps, isLastDuplicate, workflowRunEnded } = await parseRequest(
2199
2280
  requestPayload,
2200
2281
  isFirstInvocation,
2201
2282
  workflowRunId,
@@ -2203,8 +2284,11 @@ var serve = (routeFunction, options) => {
2203
2284
  request.headers.get("upstash-message-id"),
2204
2285
  debug
2205
2286
  );
2287
+ if (workflowRunEnded) {
2288
+ return onStepFinish(workflowRunId, "workflow-already-ended");
2289
+ }
2206
2290
  if (isLastDuplicate) {
2207
- return onStepFinish("no-workflow-id", "duplicate-step");
2291
+ return onStepFinish(workflowRunId, "duplicate-step");
2208
2292
  }
2209
2293
  const failureCheck = await handleFailure(
2210
2294
  request,
@@ -2218,7 +2302,7 @@ var serve = (routeFunction, options) => {
2218
2302
  throw failureCheck.error;
2219
2303
  } else if (failureCheck.value === "is-failure-callback") {
2220
2304
  await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
2221
- return onStepFinish("no-workflow-id", "failure-callback");
2305
+ return onStepFinish(workflowRunId, "failure-callback");
2222
2306
  }
2223
2307
  const workflowContext = new WorkflowContext({
2224
2308
  qstashClient,
@@ -2240,7 +2324,11 @@ var serve = (routeFunction, options) => {
2240
2324
  await debug?.log("ERROR", "ERROR", { error: authCheck.error.message });
2241
2325
  throw authCheck.error;
2242
2326
  } else if (authCheck.value === "run-ended") {
2243
- return onStepFinish("no-workflow-id", "auth-fail");
2327
+ await debug?.log("ERROR", "ERROR", { error: AUTH_FAIL_MESSAGE });
2328
+ return onStepFinish(
2329
+ isFirstInvocation ? "no-workflow-id" : workflowContext.workflowRunId,
2330
+ "auth-fail"
2331
+ );
2244
2332
  }
2245
2333
  const callReturnCheck = await handleThirdPartyCallResult(
2246
2334
  request,
@@ -2257,7 +2345,7 @@ var serve = (routeFunction, options) => {
2257
2345
  });
2258
2346
  throw callReturnCheck.error;
2259
2347
  } else if (callReturnCheck.value === "continue-workflow") {
2260
- const result = isFirstInvocation ? await triggerFirstInvocation(workflowContext, retries, debug) : await triggerRouteFunction({
2348
+ const result = isFirstInvocation ? await triggerFirstInvocation(workflowContext, retries, useJSONContent, debug) : await triggerRouteFunction({
2261
2349
  onStep: async () => routeFunction(workflowContext),
2262
2350
  onCleanup: async () => {
2263
2351
  await triggerWorkflowDelete(workflowContext, debug);
@@ -2273,6 +2361,8 @@ var serve = (routeFunction, options) => {
2273
2361
  }
2274
2362
  await debug?.log("INFO", "RESPONSE_WORKFLOW");
2275
2363
  return onStepFinish(workflowContext.workflowRunId, "success");
2364
+ } else if (callReturnCheck.value === "workflow-ended") {
2365
+ return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended");
2276
2366
  }
2277
2367
  await debug?.log("INFO", "RESPONSE_DEFAULT");
2278
2368
  return onStepFinish("no-workflow-id", "fromCallback");
@@ -2290,13 +2380,10 @@ var serve = (routeFunction, options) => {
2290
2380
  return { handler: safeHandler };
2291
2381
  };
2292
2382
 
2293
- // src/client/index.ts
2294
- var import_qstash6 = require("@upstash/qstash");
2295
-
2296
2383
  // platforms/astro.ts
2297
- function serve2(routeFunction, options) {
2384
+ function serve(routeFunction, options) {
2298
2385
  const POST = (apiContext) => {
2299
- const { handler } = serve(
2386
+ const { handler } = serveBase(
2300
2387
  (workflowContext) => routeFunction(workflowContext, apiContext),
2301
2388
  options
2302
2389
  );
package/astro.mjs CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
- serve
3
- } from "./chunk-5R2BFC3N.mjs";
2
+ serveBase
3
+ } from "./chunk-Z7WS5XIR.mjs";
4
4
 
5
5
  // platforms/astro.ts
6
- function serve2(routeFunction, options) {
6
+ function serve(routeFunction, options) {
7
7
  const POST = (apiContext) => {
8
- const { handler } = serve(
8
+ const { handler } = serveBase(
9
9
  (workflowContext) => routeFunction(workflowContext, apiContext),
10
10
  options
11
11
  );
@@ -14,5 +14,5 @@ function serve2(routeFunction, options) {
14
14
  return { POST };
15
15
  }
16
16
  export {
17
- serve2 as serve
17
+ serve
18
18
  };