@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 +2 -2
- package/astro.d.ts +2 -2
- package/astro.js +175 -88
- package/astro.mjs +5 -5
- package/{chunk-5R2BFC3N.mjs → chunk-Z7WS5XIR.mjs} +150 -234
- package/cloudflare.d.mts +2 -2
- package/cloudflare.d.ts +2 -2
- package/cloudflare.js +175 -88
- package/cloudflare.mjs +5 -5
- package/express.d.mts +1 -1
- package/express.d.ts +1 -1
- package/express.js +187 -93
- package/express.mjs +17 -10
- package/h3.d.mts +2 -2
- package/h3.d.ts +2 -2
- package/h3.js +175 -88
- package/h3.mjs +5 -5
- package/hono.d.mts +4 -2
- package/hono.d.ts +4 -2
- package/hono.js +175 -88
- package/hono.mjs +5 -5
- package/index.d.mts +3 -3
- package/index.d.ts +3 -3
- package/index.js +179 -86
- package/index.mjs +189 -3
- package/nextjs.d.mts +3 -3
- package/nextjs.d.ts +3 -3
- package/nextjs.js +179 -92
- package/nextjs.mjs +9 -9
- package/package.json +1 -1
- package/solidjs.d.mts +2 -2
- package/solidjs.d.ts +2 -2
- package/solidjs.js +175 -88
- package/solidjs.mjs +5 -5
- package/svelte.d.mts +3 -3
- package/svelte.d.ts +3 -3
- package/svelte.js +178 -88
- package/svelte.mjs +8 -5
- package/{types-Cki_MHrh.d.mts → types-APRap-aV.d.mts} +12 -2
- package/{types-Cki_MHrh.d.ts → types-APRap-aV.d.ts} +12 -2
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: () =>
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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-") &&
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
2174
|
+
qstashClient: new import_qstash6.Client({
|
|
2120
2175
|
baseUrl: environment.QSTASH_URL,
|
|
2121
2176
|
token: environment.QSTASH_TOKEN
|
|
2122
2177
|
}),
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
|
2299
|
-
const { handler: serveHandler } =
|
|
2300
|
-
|
|
2301
|
-
|
|
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 } =
|
|
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
|
-
|
|
3
|
-
} from "./chunk-
|
|
2
|
+
serveBase
|
|
3
|
+
} from "./chunk-Z7WS5XIR.mjs";
|
|
4
4
|
|
|
5
5
|
// platforms/nextjs.ts
|
|
6
|
-
var
|
|
7
|
-
const { handler: serveHandler } =
|
|
8
|
-
|
|
9
|
-
|
|
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 } =
|
|
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
|
-
|
|
40
|
+
serve,
|
|
41
41
|
servePagesRouter
|
|
42
42
|
};
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@upstash/workflow","version":"v0.2.
|
|
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,
|
|
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?:
|
|
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,
|
|
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?:
|
|
14
|
+
declare const serve: <TInitialPayload = unknown>(routeFunction: RouteFunction<TInitialPayload>, options?: PublicServeOptions<TInitialPayload>) => {
|
|
15
15
|
POST: (event: APIEvent) => Promise<Response>;
|
|
16
16
|
};
|
|
17
17
|
|