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