@upstash/workflow 0.2.1 → 0.2.3
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 +248 -76
- package/astro.mjs +5 -5
- package/{chunk-ADOBNR4O.mjs → chunk-QBJ3LQIO.mjs} +222 -221
- package/cloudflare.d.mts +2 -2
- package/cloudflare.d.ts +2 -2
- package/cloudflare.js +248 -76
- package/cloudflare.mjs +5 -5
- package/express.d.mts +1 -1
- package/express.d.ts +1 -1
- package/express.js +1620 -1305
- package/express.mjs +1395 -1252
- package/h3.d.mts +2 -2
- package/h3.d.ts +2 -2
- package/h3.js +248 -76
- package/h3.mjs +5 -5
- package/hono.d.mts +4 -2
- package/hono.d.ts +4 -2
- package/hono.js +248 -76
- package/hono.mjs +5 -5
- package/index.d.mts +3 -3
- package/index.d.ts +3 -3
- package/index.js +252 -74
- package/index.mjs +189 -3
- package/nextjs.d.mts +3 -3
- package/nextjs.d.ts +3 -3
- package/nextjs.js +249 -77
- package/nextjs.mjs +6 -6
- package/package.json +1 -1
- package/solidjs.d.mts +2 -2
- package/solidjs.d.ts +2 -2
- package/solidjs.js +248 -76
- package/solidjs.mjs +5 -5
- package/svelte.d.mts +3 -3
- package/svelte.d.ts +3 -3
- package/svelte.js +251 -76
- package/svelte.mjs +8 -5
- package/{types-Be4hC1mu.d.mts → types-R9q4MUwl.d.mts} +246 -12
- package/{types-Be4hC1mu.d.ts → types-R9q4MUwl.d.ts} +246 -12
|
@@ -71,7 +71,19 @@ var formatWorkflowError = (error) => {
|
|
|
71
71
|
};
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
+
// src/types.ts
|
|
75
|
+
var StepTypes = [
|
|
76
|
+
"Initial",
|
|
77
|
+
"Run",
|
|
78
|
+
"SleepFor",
|
|
79
|
+
"SleepUntil",
|
|
80
|
+
"Call",
|
|
81
|
+
"Wait",
|
|
82
|
+
"Notify"
|
|
83
|
+
];
|
|
84
|
+
|
|
74
85
|
// src/client/utils.ts
|
|
86
|
+
import { QstashError as QstashError2 } from "@upstash/qstash";
|
|
75
87
|
var makeNotifyRequest = async (requester, eventId, eventData) => {
|
|
76
88
|
const result = await requester.request({
|
|
77
89
|
path: ["v2", "notify", eventId],
|
|
@@ -105,24 +117,28 @@ var getSteps = async (requester, workflowRunId, messageId, debug) => {
|
|
|
105
117
|
await debug?.log("INFO", "ENDPOINT_START", {
|
|
106
118
|
message: `Pulled ${steps.length} steps from QStashand returned them without filtering with messageId.`
|
|
107
119
|
});
|
|
108
|
-
return steps;
|
|
120
|
+
return { steps, workflowRunEnded: false };
|
|
109
121
|
} else {
|
|
110
122
|
const index = steps.findIndex((item) => item.messageId === messageId);
|
|
111
123
|
if (index === -1) {
|
|
112
|
-
return [];
|
|
124
|
+
return { steps: [], workflowRunEnded: false };
|
|
113
125
|
}
|
|
114
126
|
const filteredSteps = steps.slice(0, index + 1);
|
|
115
127
|
await debug?.log("INFO", "ENDPOINT_START", {
|
|
116
128
|
message: `Pulled ${steps.length} steps from QStash and filtered them to ${filteredSteps.length} using messageId.`
|
|
117
129
|
});
|
|
118
|
-
return filteredSteps;
|
|
130
|
+
return { steps: filteredSteps, workflowRunEnded: false };
|
|
119
131
|
}
|
|
120
132
|
} catch (error) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
133
|
+
if (error instanceof QstashError2 && error.status === 404) {
|
|
134
|
+
await debug?.log("WARN", "ENDPOINT_START", {
|
|
135
|
+
message: "Couldn't fetch workflow run steps. This can happen if the workflow run succesfully ends before some callback is executed.",
|
|
136
|
+
error
|
|
137
|
+
});
|
|
138
|
+
return { steps: void 0, workflowRunEnded: true };
|
|
139
|
+
} else {
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
126
142
|
}
|
|
127
143
|
};
|
|
128
144
|
|
|
@@ -734,20 +750,9 @@ var DEFAULT_CONTENT_TYPE = "application/json";
|
|
|
734
750
|
var NO_CONCURRENCY = 1;
|
|
735
751
|
var DEFAULT_RETRIES = 3;
|
|
736
752
|
|
|
737
|
-
// src/types.ts
|
|
738
|
-
var StepTypes = [
|
|
739
|
-
"Initial",
|
|
740
|
-
"Run",
|
|
741
|
-
"SleepFor",
|
|
742
|
-
"SleepUntil",
|
|
743
|
-
"Call",
|
|
744
|
-
"Wait",
|
|
745
|
-
"Notify"
|
|
746
|
-
];
|
|
747
|
-
|
|
748
753
|
// src/workflow-requests.ts
|
|
749
|
-
import { QstashError as
|
|
750
|
-
var triggerFirstInvocation = async (workflowContext, retries, debug) => {
|
|
754
|
+
import { QstashError as QstashError3 } from "@upstash/qstash";
|
|
755
|
+
var triggerFirstInvocation = async (workflowContext, retries, useJSONContent, debug) => {
|
|
751
756
|
const { headers } = getHeaders(
|
|
752
757
|
"true",
|
|
753
758
|
workflowContext.workflowRunId,
|
|
@@ -757,6 +762,9 @@ var triggerFirstInvocation = async (workflowContext, retries, debug) => {
|
|
|
757
762
|
workflowContext.failureUrl,
|
|
758
763
|
retries
|
|
759
764
|
);
|
|
765
|
+
if (useJSONContent) {
|
|
766
|
+
headers["content-type"] = "application/json";
|
|
767
|
+
}
|
|
760
768
|
try {
|
|
761
769
|
const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
|
|
762
770
|
const result = await workflowContext.qstashClient.publish({
|
|
@@ -800,7 +808,7 @@ var triggerRouteFunction = async ({
|
|
|
800
808
|
return ok("workflow-finished");
|
|
801
809
|
} catch (error) {
|
|
802
810
|
const error_ = error;
|
|
803
|
-
if (error instanceof
|
|
811
|
+
if (error instanceof QstashError3 && error.status === 400) {
|
|
804
812
|
await debug?.log("WARN", "RESPONSE_WORKFLOW", {
|
|
805
813
|
message: `tried to append to a cancelled workflow. exiting without publishing.`,
|
|
806
814
|
name: error.name,
|
|
@@ -834,7 +842,7 @@ var triggerWorkflowDelete = async (workflowContext, debug, cancel = false) => {
|
|
|
834
842
|
);
|
|
835
843
|
return { deleted: true };
|
|
836
844
|
} catch (error) {
|
|
837
|
-
if (error instanceof
|
|
845
|
+
if (error instanceof QstashError3 && error.status === 404) {
|
|
838
846
|
await debug?.log("WARN", "SUBMIT_CLEANUP", {
|
|
839
847
|
message: `Failed to remove workflow run ${workflowContext.workflowRunId} as it doesn't exist.`,
|
|
840
848
|
name: error.name,
|
|
@@ -871,11 +879,19 @@ var handleThirdPartyCallResult = async (request, requestPayload, client, workflo
|
|
|
871
879
|
if (!workflowRunId2)
|
|
872
880
|
throw new WorkflowError("workflow run id missing in context.call lazy fetch.");
|
|
873
881
|
if (!messageId) throw new WorkflowError("message id missing in context.call lazy fetch.");
|
|
874
|
-
const steps = await getSteps(
|
|
882
|
+
const { steps, workflowRunEnded } = await getSteps(
|
|
883
|
+
client.http,
|
|
884
|
+
workflowRunId2,
|
|
885
|
+
messageId,
|
|
886
|
+
debug
|
|
887
|
+
);
|
|
888
|
+
if (workflowRunEnded) {
|
|
889
|
+
return ok("workflow-ended");
|
|
890
|
+
}
|
|
875
891
|
const failingStep = steps.find((step) => step.messageId === messageId);
|
|
876
892
|
if (!failingStep)
|
|
877
893
|
throw new WorkflowError(
|
|
878
|
-
"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.`)
|
|
894
|
+
"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.`)
|
|
879
895
|
);
|
|
880
896
|
callbackPayload = atob(failingStep.body);
|
|
881
897
|
}
|
|
@@ -1458,6 +1474,127 @@ var sortSteps = (steps) => {
|
|
|
1458
1474
|
return [...steps].sort((step, stepOther) => getStepId(step) - getStepId(stepOther));
|
|
1459
1475
|
};
|
|
1460
1476
|
|
|
1477
|
+
// src/context/api/anthropic.ts
|
|
1478
|
+
import { anthropic } from "@upstash/qstash";
|
|
1479
|
+
|
|
1480
|
+
// src/context/provider.ts
|
|
1481
|
+
var getProviderInfo = (api) => {
|
|
1482
|
+
if (!api.provider) {
|
|
1483
|
+
throw new WorkflowError("A Provider must be provided.");
|
|
1484
|
+
}
|
|
1485
|
+
if (api.provider.owner === "upstash") {
|
|
1486
|
+
throw new WorkflowError("Upstash provider isn't supported.");
|
|
1487
|
+
}
|
|
1488
|
+
const { name, provider, ...parameters } = api;
|
|
1489
|
+
if (!provider.baseUrl) throw new TypeError("baseUrl cannot be empty or undefined!");
|
|
1490
|
+
if (!provider.token) throw new TypeError("token cannot be empty or undefined!");
|
|
1491
|
+
if (provider.apiKind !== name) {
|
|
1492
|
+
throw new TypeError(`Unexpected api name. Expected '${provider.apiKind}', received ${name}`);
|
|
1493
|
+
}
|
|
1494
|
+
const providerInfo = {
|
|
1495
|
+
url: provider.getUrl(),
|
|
1496
|
+
baseUrl: provider.baseUrl,
|
|
1497
|
+
route: provider.getRoute(),
|
|
1498
|
+
appendHeaders: provider.getHeaders(parameters),
|
|
1499
|
+
owner: provider.owner,
|
|
1500
|
+
method: provider.method
|
|
1501
|
+
};
|
|
1502
|
+
return provider.onFinish(providerInfo, parameters);
|
|
1503
|
+
};
|
|
1504
|
+
|
|
1505
|
+
// src/context/api/base.ts
|
|
1506
|
+
var BaseWorkflowApi = class {
|
|
1507
|
+
context;
|
|
1508
|
+
constructor({ context }) {
|
|
1509
|
+
this.context = context;
|
|
1510
|
+
}
|
|
1511
|
+
/**
|
|
1512
|
+
* context.call which uses a QStash API
|
|
1513
|
+
*
|
|
1514
|
+
* @param stepName
|
|
1515
|
+
* @param settings
|
|
1516
|
+
* @returns
|
|
1517
|
+
*/
|
|
1518
|
+
async callApi(stepName, settings) {
|
|
1519
|
+
const { url, appendHeaders, method } = getProviderInfo(settings.api);
|
|
1520
|
+
const { method: userMethod, body, headers = {}, retries = 0, timeout } = settings;
|
|
1521
|
+
return await this.context.call(stepName, {
|
|
1522
|
+
url,
|
|
1523
|
+
method: userMethod ?? method,
|
|
1524
|
+
body,
|
|
1525
|
+
headers: {
|
|
1526
|
+
...appendHeaders,
|
|
1527
|
+
...headers
|
|
1528
|
+
},
|
|
1529
|
+
retries,
|
|
1530
|
+
timeout
|
|
1531
|
+
});
|
|
1532
|
+
}
|
|
1533
|
+
};
|
|
1534
|
+
|
|
1535
|
+
// src/context/api/anthropic.ts
|
|
1536
|
+
var AnthropicAPI = class extends BaseWorkflowApi {
|
|
1537
|
+
async call(stepName, settings) {
|
|
1538
|
+
const { token, operation, ...parameters } = settings;
|
|
1539
|
+
return await this.callApi(stepName, {
|
|
1540
|
+
api: {
|
|
1541
|
+
name: "llm",
|
|
1542
|
+
provider: anthropic({ token })
|
|
1543
|
+
},
|
|
1544
|
+
...parameters
|
|
1545
|
+
});
|
|
1546
|
+
}
|
|
1547
|
+
};
|
|
1548
|
+
|
|
1549
|
+
// src/context/api/openai.ts
|
|
1550
|
+
import { openai } from "@upstash/qstash";
|
|
1551
|
+
var OpenAIAPI = class extends BaseWorkflowApi {
|
|
1552
|
+
async call(stepName, settings) {
|
|
1553
|
+
const { token, organization, operation, ...parameters } = settings;
|
|
1554
|
+
return await this.callApi(stepName, {
|
|
1555
|
+
api: {
|
|
1556
|
+
name: "llm",
|
|
1557
|
+
provider: openai({ token, organization })
|
|
1558
|
+
},
|
|
1559
|
+
...parameters
|
|
1560
|
+
});
|
|
1561
|
+
}
|
|
1562
|
+
};
|
|
1563
|
+
|
|
1564
|
+
// src/context/api/resend.ts
|
|
1565
|
+
import { resend } from "@upstash/qstash";
|
|
1566
|
+
var ResendAPI = class extends BaseWorkflowApi {
|
|
1567
|
+
async call(stepName, settings) {
|
|
1568
|
+
const { token, batch = false, ...parameters } = settings;
|
|
1569
|
+
return await this.callApi(stepName, {
|
|
1570
|
+
api: {
|
|
1571
|
+
name: "email",
|
|
1572
|
+
provider: resend({ token, batch })
|
|
1573
|
+
},
|
|
1574
|
+
...parameters
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
};
|
|
1578
|
+
|
|
1579
|
+
// src/context/api/index.ts
|
|
1580
|
+
var WorkflowApi = class extends BaseWorkflowApi {
|
|
1581
|
+
get openai() {
|
|
1582
|
+
return new OpenAIAPI({
|
|
1583
|
+
context: this.context
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
get resend() {
|
|
1587
|
+
return new ResendAPI({
|
|
1588
|
+
context: this.context
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
get anthropic() {
|
|
1592
|
+
return new AnthropicAPI({
|
|
1593
|
+
context: this.context
|
|
1594
|
+
});
|
|
1595
|
+
}
|
|
1596
|
+
};
|
|
1597
|
+
|
|
1461
1598
|
// src/context/context.ts
|
|
1462
1599
|
var WorkflowContext = class {
|
|
1463
1600
|
executor;
|
|
@@ -1837,6 +1974,11 @@ var WorkflowContext = class {
|
|
|
1837
1974
|
async addStep(step) {
|
|
1838
1975
|
return await this.executor.addStep(step);
|
|
1839
1976
|
}
|
|
1977
|
+
get api() {
|
|
1978
|
+
return new WorkflowApi({
|
|
1979
|
+
context: this
|
|
1980
|
+
});
|
|
1981
|
+
}
|
|
1840
1982
|
};
|
|
1841
1983
|
|
|
1842
1984
|
// src/logger.ts
|
|
@@ -1914,7 +2056,7 @@ function decodeBase64(base64) {
|
|
|
1914
2056
|
}
|
|
1915
2057
|
|
|
1916
2058
|
// src/serve/authorization.ts
|
|
1917
|
-
import { Client } from "@upstash/qstash";
|
|
2059
|
+
import { Client as Client2 } from "@upstash/qstash";
|
|
1918
2060
|
var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowContext {
|
|
1919
2061
|
static disabledMessage = "disabled-qstash-worklfow-run";
|
|
1920
2062
|
/**
|
|
@@ -1945,7 +2087,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
1945
2087
|
*/
|
|
1946
2088
|
static async tryAuthentication(routeFunction, context) {
|
|
1947
2089
|
const disabledContext = new _DisabledWorkflowContext({
|
|
1948
|
-
qstashClient: new
|
|
2090
|
+
qstashClient: new Client2({
|
|
1949
2091
|
baseUrl: "disabled-client",
|
|
1950
2092
|
token: "disabled-client"
|
|
1951
2093
|
}),
|
|
@@ -2069,7 +2211,8 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
|
|
|
2069
2211
|
return {
|
|
2070
2212
|
rawInitialPayload: requestPayload ?? "",
|
|
2071
2213
|
steps: [],
|
|
2072
|
-
isLastDuplicate: false
|
|
2214
|
+
isLastDuplicate: false,
|
|
2215
|
+
workflowRunEnded: false
|
|
2073
2216
|
};
|
|
2074
2217
|
} else {
|
|
2075
2218
|
let rawSteps;
|
|
@@ -2079,7 +2222,21 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
|
|
|
2079
2222
|
"ENDPOINT_START",
|
|
2080
2223
|
"request payload is empty, steps will be fetched from QStash."
|
|
2081
2224
|
);
|
|
2082
|
-
|
|
2225
|
+
const { steps: fetchedSteps, workflowRunEnded } = await getSteps(
|
|
2226
|
+
requester,
|
|
2227
|
+
workflowRunId,
|
|
2228
|
+
messageId,
|
|
2229
|
+
debug
|
|
2230
|
+
);
|
|
2231
|
+
if (workflowRunEnded) {
|
|
2232
|
+
return {
|
|
2233
|
+
rawInitialPayload: void 0,
|
|
2234
|
+
steps: void 0,
|
|
2235
|
+
isLastDuplicate: void 0,
|
|
2236
|
+
workflowRunEnded: true
|
|
2237
|
+
};
|
|
2238
|
+
}
|
|
2239
|
+
rawSteps = fetchedSteps;
|
|
2083
2240
|
} else {
|
|
2084
2241
|
rawSteps = JSON.parse(requestPayload);
|
|
2085
2242
|
}
|
|
@@ -2089,7 +2246,8 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
|
|
|
2089
2246
|
return {
|
|
2090
2247
|
rawInitialPayload,
|
|
2091
2248
|
steps: deduplicatedSteps,
|
|
2092
|
-
isLastDuplicate
|
|
2249
|
+
isLastDuplicate,
|
|
2250
|
+
workflowRunEnded: false
|
|
2093
2251
|
};
|
|
2094
2252
|
}
|
|
2095
2253
|
};
|
|
@@ -2144,14 +2302,14 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
|
|
|
2144
2302
|
|
|
2145
2303
|
// src/serve/options.ts
|
|
2146
2304
|
import { Receiver } from "@upstash/qstash";
|
|
2147
|
-
import { Client as
|
|
2305
|
+
import { Client as Client3 } from "@upstash/qstash";
|
|
2148
2306
|
var processOptions = (options) => {
|
|
2149
2307
|
const environment = options?.env ?? (typeof process === "undefined" ? {} : process.env);
|
|
2150
2308
|
const receiverEnvironmentVariablesSet = Boolean(
|
|
2151
2309
|
environment.QSTASH_CURRENT_SIGNING_KEY && environment.QSTASH_NEXT_SIGNING_KEY
|
|
2152
2310
|
);
|
|
2153
2311
|
return {
|
|
2154
|
-
qstashClient: new
|
|
2312
|
+
qstashClient: new Client3({
|
|
2155
2313
|
baseUrl: environment.QSTASH_URL,
|
|
2156
2314
|
token: environment.QSTASH_TOKEN
|
|
2157
2315
|
}),
|
|
@@ -2192,6 +2350,7 @@ var processOptions = (options) => {
|
|
|
2192
2350
|
baseUrl: environment.UPSTASH_WORKFLOW_URL,
|
|
2193
2351
|
env: environment,
|
|
2194
2352
|
retries: DEFAULT_RETRIES,
|
|
2353
|
+
useJSONContent: false,
|
|
2195
2354
|
...options
|
|
2196
2355
|
};
|
|
2197
2356
|
};
|
|
@@ -2208,6 +2367,16 @@ var determineUrls = async (request, url, baseUrl, failureFunction, failureUrl, d
|
|
|
2208
2367
|
});
|
|
2209
2368
|
}
|
|
2210
2369
|
const workflowFailureUrl = failureFunction ? workflowUrl : failureUrl;
|
|
2370
|
+
if (workflowUrl.includes("localhost")) {
|
|
2371
|
+
await debug?.log("WARN", "ENDPOINT_START", {
|
|
2372
|
+
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}`
|
|
2373
|
+
});
|
|
2374
|
+
}
|
|
2375
|
+
if (!(workflowUrl.startsWith("http://") || workflowUrl.startsWith("https://"))) {
|
|
2376
|
+
throw new WorkflowError(
|
|
2377
|
+
`Workflow URL should start with 'http://' or 'https://'. Recevied is '${workflowUrl}'`
|
|
2378
|
+
);
|
|
2379
|
+
}
|
|
2211
2380
|
return {
|
|
2212
2381
|
workflowUrl,
|
|
2213
2382
|
workflowFailureUrl
|
|
@@ -2216,7 +2385,7 @@ var determineUrls = async (request, url, baseUrl, failureFunction, failureUrl, d
|
|
|
2216
2385
|
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`;
|
|
2217
2386
|
|
|
2218
2387
|
// src/serve/index.ts
|
|
2219
|
-
var
|
|
2388
|
+
var serveBase = (routeFunction, options) => {
|
|
2220
2389
|
const {
|
|
2221
2390
|
qstashClient,
|
|
2222
2391
|
onStepFinish,
|
|
@@ -2228,7 +2397,8 @@ var serve = (routeFunction, options) => {
|
|
|
2228
2397
|
failureFunction,
|
|
2229
2398
|
baseUrl,
|
|
2230
2399
|
env,
|
|
2231
|
-
retries
|
|
2400
|
+
retries,
|
|
2401
|
+
useJSONContent
|
|
2232
2402
|
} = processOptions(options);
|
|
2233
2403
|
const debug = WorkflowLogger.getLogger(verbose);
|
|
2234
2404
|
const handler = async (request) => {
|
|
@@ -2245,7 +2415,7 @@ var serve = (routeFunction, options) => {
|
|
|
2245
2415
|
await verifyRequest(requestPayload, request.headers.get("upstash-signature"), receiver);
|
|
2246
2416
|
const { isFirstInvocation, workflowRunId } = validateRequest(request);
|
|
2247
2417
|
debug?.setWorkflowRunId(workflowRunId);
|
|
2248
|
-
const { rawInitialPayload, steps, isLastDuplicate } = await parseRequest(
|
|
2418
|
+
const { rawInitialPayload, steps, isLastDuplicate, workflowRunEnded } = await parseRequest(
|
|
2249
2419
|
requestPayload,
|
|
2250
2420
|
isFirstInvocation,
|
|
2251
2421
|
workflowRunId,
|
|
@@ -2253,8 +2423,11 @@ var serve = (routeFunction, options) => {
|
|
|
2253
2423
|
request.headers.get("upstash-message-id"),
|
|
2254
2424
|
debug
|
|
2255
2425
|
);
|
|
2426
|
+
if (workflowRunEnded) {
|
|
2427
|
+
return onStepFinish(workflowRunId, "workflow-already-ended");
|
|
2428
|
+
}
|
|
2256
2429
|
if (isLastDuplicate) {
|
|
2257
|
-
return onStepFinish(
|
|
2430
|
+
return onStepFinish(workflowRunId, "duplicate-step");
|
|
2258
2431
|
}
|
|
2259
2432
|
const failureCheck = await handleFailure(
|
|
2260
2433
|
request,
|
|
@@ -2268,7 +2441,7 @@ var serve = (routeFunction, options) => {
|
|
|
2268
2441
|
throw failureCheck.error;
|
|
2269
2442
|
} else if (failureCheck.value === "is-failure-callback") {
|
|
2270
2443
|
await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
|
|
2271
|
-
return onStepFinish(
|
|
2444
|
+
return onStepFinish(workflowRunId, "failure-callback");
|
|
2272
2445
|
}
|
|
2273
2446
|
const workflowContext = new WorkflowContext({
|
|
2274
2447
|
qstashClient,
|
|
@@ -2311,7 +2484,7 @@ var serve = (routeFunction, options) => {
|
|
|
2311
2484
|
});
|
|
2312
2485
|
throw callReturnCheck.error;
|
|
2313
2486
|
} else if (callReturnCheck.value === "continue-workflow") {
|
|
2314
|
-
const result = isFirstInvocation ? await triggerFirstInvocation(workflowContext, retries, debug) : await triggerRouteFunction({
|
|
2487
|
+
const result = isFirstInvocation ? await triggerFirstInvocation(workflowContext, retries, useJSONContent, debug) : await triggerRouteFunction({
|
|
2315
2488
|
onStep: async () => routeFunction(workflowContext),
|
|
2316
2489
|
onCleanup: async () => {
|
|
2317
2490
|
await triggerWorkflowDelete(workflowContext, debug);
|
|
@@ -2327,6 +2500,8 @@ var serve = (routeFunction, options) => {
|
|
|
2327
2500
|
}
|
|
2328
2501
|
await debug?.log("INFO", "RESPONSE_WORKFLOW");
|
|
2329
2502
|
return onStepFinish(workflowContext.workflowRunId, "success");
|
|
2503
|
+
} else if (callReturnCheck.value === "workflow-ended") {
|
|
2504
|
+
return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended");
|
|
2330
2505
|
}
|
|
2331
2506
|
await debug?.log("INFO", "RESPONSE_DEFAULT");
|
|
2332
2507
|
return onStepFinish("no-workflow-id", "fromCallback");
|
|
@@ -2343,198 +2518,24 @@ var serve = (routeFunction, options) => {
|
|
|
2343
2518
|
};
|
|
2344
2519
|
return { handler: safeHandler };
|
|
2345
2520
|
};
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
import { Client as QStashClient } from "@upstash/qstash";
|
|
2349
|
-
var Client3 = class {
|
|
2350
|
-
client;
|
|
2351
|
-
constructor(clientConfig) {
|
|
2352
|
-
if (!clientConfig.token) {
|
|
2353
|
-
console.error(
|
|
2354
|
-
"QStash token is required for Upstash Workflow!\n\nTo fix this:\n1. Get your token from the Upstash Console (https://console.upstash.com/qstash)\n2. Initialize the workflow client with:\n\n const client = new Client({\n token: '<YOUR_QSTASH_TOKEN>'\n });"
|
|
2355
|
-
);
|
|
2356
|
-
}
|
|
2357
|
-
this.client = new QStashClient(clientConfig);
|
|
2358
|
-
}
|
|
2359
|
-
/**
|
|
2360
|
-
* Cancel an ongoing workflow
|
|
2361
|
-
*
|
|
2362
|
-
* Returns true if workflow is canceled succesfully. Otherwise, throws error.
|
|
2363
|
-
*
|
|
2364
|
-
* There are multiple ways you can cancel workflows:
|
|
2365
|
-
* - pass one or more workflow run ids to cancel them
|
|
2366
|
-
* - pass a workflow url to cancel all runs starting with this url
|
|
2367
|
-
* - cancel all pending or active workflow runs
|
|
2368
|
-
*
|
|
2369
|
-
* ### Cancel a set of workflow runs
|
|
2370
|
-
*
|
|
2371
|
-
* ```ts
|
|
2372
|
-
* // cancel a single workflow
|
|
2373
|
-
* await client.cancel({ ids: "<WORKFLOW_RUN_ID>" })
|
|
2374
|
-
*
|
|
2375
|
-
* // cancel a set of workflow runs
|
|
2376
|
-
* await client.cancel({ ids: [
|
|
2377
|
-
* "<WORKFLOW_RUN_ID_1>",
|
|
2378
|
-
* "<WORKFLOW_RUN_ID_2>",
|
|
2379
|
-
* ]})
|
|
2380
|
-
* ```
|
|
2381
|
-
*
|
|
2382
|
-
* ### Cancel workflows starting with a url
|
|
2383
|
-
*
|
|
2384
|
-
* If you have an endpoint called `https://your-endpoint.com` and you
|
|
2385
|
-
* want to cancel all workflow runs on it, you can use `urlStartingWith`.
|
|
2386
|
-
*
|
|
2387
|
-
* Note that this will cancel workflows in all endpoints under
|
|
2388
|
-
* `https://your-endpoint.com`.
|
|
2389
|
-
*
|
|
2390
|
-
* ```ts
|
|
2391
|
-
* await client.cancel({ urlStartingWith: "https://your-endpoint.com" })
|
|
2392
|
-
* ```
|
|
2393
|
-
*
|
|
2394
|
-
* ### Cancel *all* workflows
|
|
2395
|
-
*
|
|
2396
|
-
* To cancel all pending and currently running workflows, you can
|
|
2397
|
-
* do it like this:
|
|
2398
|
-
*
|
|
2399
|
-
* ```ts
|
|
2400
|
-
* await client.cancel({ all: true })
|
|
2401
|
-
* ```
|
|
2402
|
-
*
|
|
2403
|
-
* @param ids run id of the workflow to delete
|
|
2404
|
-
* @param urlStartingWith cancel workflows starting with this url. Will be ignored
|
|
2405
|
-
* if `ids` parameter is set.
|
|
2406
|
-
* @param all set to true in order to cancel all workflows. Will be ignored
|
|
2407
|
-
* if `ids` or `urlStartingWith` parameters are set.
|
|
2408
|
-
* @returns true if workflow is succesfully deleted. Otherwise throws QStashError
|
|
2409
|
-
*/
|
|
2410
|
-
async cancel({
|
|
2411
|
-
ids,
|
|
2412
|
-
urlStartingWith,
|
|
2413
|
-
all
|
|
2414
|
-
}) {
|
|
2415
|
-
let body;
|
|
2416
|
-
if (ids) {
|
|
2417
|
-
const runIdArray = typeof ids === "string" ? [ids] : ids;
|
|
2418
|
-
body = JSON.stringify({ workflowRunIds: runIdArray });
|
|
2419
|
-
} else if (urlStartingWith) {
|
|
2420
|
-
body = JSON.stringify({ workflowUrl: urlStartingWith });
|
|
2421
|
-
} else if (all) {
|
|
2422
|
-
body = "{}";
|
|
2423
|
-
} else {
|
|
2424
|
-
throw new TypeError("The `cancel` method cannot be called without any options.");
|
|
2425
|
-
}
|
|
2426
|
-
const result = await this.client.http.request({
|
|
2427
|
-
path: ["v2", "workflows", "runs"],
|
|
2428
|
-
method: "DELETE",
|
|
2429
|
-
body,
|
|
2430
|
-
headers: {
|
|
2431
|
-
"Content-Type": "application/json"
|
|
2432
|
-
}
|
|
2433
|
-
});
|
|
2434
|
-
return result;
|
|
2435
|
-
}
|
|
2436
|
-
/**
|
|
2437
|
-
* Notify a workflow run waiting for an event
|
|
2438
|
-
*
|
|
2439
|
-
* ```ts
|
|
2440
|
-
* import { Client } from "@upstash/workflow";
|
|
2441
|
-
*
|
|
2442
|
-
* const client = new Client({ token: "<QSTASH_TOKEN>" })
|
|
2443
|
-
* await client.notify({
|
|
2444
|
-
* eventId: "my-event-id",
|
|
2445
|
-
* eventData: "my-data" // data passed to the workflow run
|
|
2446
|
-
* });
|
|
2447
|
-
* ```
|
|
2448
|
-
*
|
|
2449
|
-
* @param eventId event id to notify
|
|
2450
|
-
* @param eventData data to provide to the workflow
|
|
2451
|
-
*/
|
|
2452
|
-
async notify({
|
|
2453
|
-
eventId,
|
|
2454
|
-
eventData
|
|
2455
|
-
}) {
|
|
2456
|
-
return await makeNotifyRequest(this.client.http, eventId, eventData);
|
|
2457
|
-
}
|
|
2458
|
-
/**
|
|
2459
|
-
* Check waiters of an event
|
|
2460
|
-
*
|
|
2461
|
-
* ```ts
|
|
2462
|
-
* import { Client } from "@upstash/workflow";
|
|
2463
|
-
*
|
|
2464
|
-
* const client = new Client({ token: "<QSTASH_TOKEN>" })
|
|
2465
|
-
* const result = await client.getWaiters({
|
|
2466
|
-
* eventId: "my-event-id"
|
|
2467
|
-
* })
|
|
2468
|
-
* ```
|
|
2469
|
-
*
|
|
2470
|
-
* @param eventId event id to check
|
|
2471
|
-
*/
|
|
2472
|
-
async getWaiters({ eventId }) {
|
|
2473
|
-
return await makeGetWaitersRequest(this.client.http, eventId);
|
|
2474
|
-
}
|
|
2475
|
-
/**
|
|
2476
|
-
* Trigger new workflow run and returns the workflow run id
|
|
2477
|
-
*
|
|
2478
|
-
* ```ts
|
|
2479
|
-
* const { workflowRunId } = await client.trigger({
|
|
2480
|
-
* url: "https://workflow-endpoint.com",
|
|
2481
|
-
* body: "hello there!", // Optional body
|
|
2482
|
-
* headers: { ... }, // Optional headers
|
|
2483
|
-
* workflowRunId: "my-workflow", // Optional workflow run ID
|
|
2484
|
-
* retries: 3 // Optional retries for the initial request
|
|
2485
|
-
* });
|
|
2486
|
-
*
|
|
2487
|
-
* console.log(workflowRunId)
|
|
2488
|
-
* // wfr_my-workflow
|
|
2489
|
-
* ```
|
|
2490
|
-
*
|
|
2491
|
-
* @param url URL of the workflow
|
|
2492
|
-
* @param body body to start the workflow with
|
|
2493
|
-
* @param headers headers to use in the request
|
|
2494
|
-
* @param workflowRunId optional workflow run id to use. mind that
|
|
2495
|
-
* you should pass different workflow run ids for different runs.
|
|
2496
|
-
* The final workflowRunId will be `wfr_${workflowRunId}`, in
|
|
2497
|
-
* other words: the workflow run id you pass will be prefixed
|
|
2498
|
-
* with `wfr_`.
|
|
2499
|
-
* @param retries retry to use in the initial request. in the rest of
|
|
2500
|
-
* the workflow, `retries` option of the `serve` will be used.
|
|
2501
|
-
* @returns workflow run id
|
|
2502
|
-
*/
|
|
2503
|
-
async trigger({
|
|
2504
|
-
url,
|
|
2505
|
-
body,
|
|
2506
|
-
headers,
|
|
2507
|
-
workflowRunId,
|
|
2508
|
-
retries
|
|
2509
|
-
}) {
|
|
2510
|
-
const finalWorkflowRunId = getWorkflowRunId(workflowRunId);
|
|
2511
|
-
const context = new WorkflowContext({
|
|
2512
|
-
qstashClient: this.client,
|
|
2513
|
-
// @ts-expect-error headers type mismatch
|
|
2514
|
-
headers: new Headers(headers ?? {}),
|
|
2515
|
-
initialPayload: body,
|
|
2516
|
-
steps: [],
|
|
2517
|
-
url,
|
|
2518
|
-
workflowRunId: finalWorkflowRunId
|
|
2519
|
-
});
|
|
2520
|
-
const result = await triggerFirstInvocation(context, retries ?? DEFAULT_RETRIES);
|
|
2521
|
-
if (result.isOk()) {
|
|
2522
|
-
return { workflowRunId: finalWorkflowRunId };
|
|
2523
|
-
} else {
|
|
2524
|
-
throw result.error;
|
|
2525
|
-
}
|
|
2526
|
-
}
|
|
2521
|
+
var serve = (routeFunction, options) => {
|
|
2522
|
+
return serveBase(routeFunction, options);
|
|
2527
2523
|
};
|
|
2528
2524
|
|
|
2529
2525
|
export {
|
|
2530
2526
|
__require,
|
|
2531
2527
|
__commonJS,
|
|
2532
2528
|
__toESM,
|
|
2529
|
+
makeNotifyRequest,
|
|
2530
|
+
makeGetWaitersRequest,
|
|
2533
2531
|
WorkflowError,
|
|
2534
2532
|
WorkflowAbort,
|
|
2533
|
+
DEFAULT_RETRIES,
|
|
2535
2534
|
StepTypes,
|
|
2535
|
+
triggerFirstInvocation,
|
|
2536
2536
|
WorkflowContext,
|
|
2537
2537
|
WorkflowLogger,
|
|
2538
|
-
|
|
2539
|
-
|
|
2538
|
+
getWorkflowRunId,
|
|
2539
|
+
serveBase,
|
|
2540
|
+
serve
|
|
2540
2541
|
};
|
package/cloudflare.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as RouteFunction,
|
|
1
|
+
import { R as RouteFunction, j as PublicServeOptions } from './types-R9q4MUwl.mjs';
|
|
2
2
|
import '@upstash/qstash';
|
|
3
3
|
|
|
4
4
|
type WorkflowBindings = {
|
|
@@ -28,7 +28,7 @@ type WorkersHandlerArgs = [Request, Record<string, string | undefined>];
|
|
|
28
28
|
* @param options workflow options
|
|
29
29
|
* @returns
|
|
30
30
|
*/
|
|
31
|
-
declare const serve: <TInitialPayload = unknown>(routeFunction: RouteFunction<TInitialPayload>, options?:
|
|
31
|
+
declare const serve: <TInitialPayload = unknown>(routeFunction: RouteFunction<TInitialPayload>, options?: PublicServeOptions<TInitialPayload>) => {
|
|
32
32
|
fetch: (...args: PagesHandlerArgs | WorkersHandlerArgs) => Promise<Response>;
|
|
33
33
|
};
|
|
34
34
|
|
package/cloudflare.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as RouteFunction,
|
|
1
|
+
import { R as RouteFunction, j as PublicServeOptions } from './types-R9q4MUwl.js';
|
|
2
2
|
import '@upstash/qstash';
|
|
3
3
|
|
|
4
4
|
type WorkflowBindings = {
|
|
@@ -28,7 +28,7 @@ type WorkersHandlerArgs = [Request, Record<string, string | undefined>];
|
|
|
28
28
|
* @param options workflow options
|
|
29
29
|
* @returns
|
|
30
30
|
*/
|
|
31
|
-
declare const serve: <TInitialPayload = unknown>(routeFunction: RouteFunction<TInitialPayload>, options?:
|
|
31
|
+
declare const serve: <TInitialPayload = unknown>(routeFunction: RouteFunction<TInitialPayload>, options?: PublicServeOptions<TInitialPayload>) => {
|
|
32
32
|
fetch: (...args: PagesHandlerArgs | WorkersHandlerArgs) => Promise<Response>;
|
|
33
33
|
};
|
|
34
34
|
|