@upstash/workflow 1.2.0-demo-rc.1 → 1.2.1
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/README.md +1 -0
- package/astro.d.mts +2 -2
- package/astro.d.ts +2 -2
- package/astro.js +72 -69
- package/astro.mjs +1 -1
- package/{chunk-NZCQPOPR.mjs → chunk-THS5AX2D.mjs} +128 -257
- package/cloudflare.d.mts +2 -2
- package/cloudflare.d.ts +2 -2
- package/cloudflare.js +72 -69
- package/cloudflare.mjs +1 -1
- package/express.d.mts +2 -2
- package/express.d.ts +2 -2
- package/express.js +72 -69
- package/express.mjs +1 -1
- package/h3.d.mts +2 -2
- package/h3.d.ts +2 -2
- package/h3.js +76 -73
- package/h3.mjs +5 -5
- package/hono.d.mts +2 -2
- package/hono.d.ts +2 -2
- package/hono.js +73 -265
- package/hono.mjs +2 -7
- package/index.d.mts +229 -138
- package/index.d.ts +229 -138
- package/index.js +275 -454
- package/index.mjs +144 -196
- package/nextjs.d.mts +2 -2
- package/nextjs.d.ts +2 -2
- package/nextjs.js +72 -263
- package/nextjs.mjs +1 -5
- package/package.json +1 -1
- package/react-router.d.mts +38 -0
- package/react-router.d.ts +38 -0
- package/react-router.js +3881 -0
- package/react-router.mjs +45 -0
- package/{serve-many-Bi8XaOyq.d.ts → serve-many-B-fe7bh7.d.ts} +1 -1
- package/{serve-many-CppVPJrh.d.mts → serve-many-C6sa_DxN.d.mts} +1 -1
- package/solidjs.d.mts +1 -1
- package/solidjs.d.ts +1 -1
- package/solidjs.js +72 -69
- package/solidjs.mjs +1 -1
- package/svelte.d.mts +2 -2
- package/svelte.d.ts +2 -2
- package/svelte.js +72 -69
- package/svelte.mjs +1 -1
- package/tanstack.d.mts +2 -2
- package/tanstack.d.ts +2 -2
- package/tanstack.js +72 -69
- package/tanstack.mjs +1 -1
- package/{types-CUwgrpCM.d.ts → types-B2S08hRU.d.mts} +18 -3
- package/{types-CUwgrpCM.d.mts → types-B2S08hRU.d.ts} +18 -3
|
@@ -98,6 +98,7 @@ function isInstanceOf(v, ctor) {
|
|
|
98
98
|
var WORKFLOW_ID_HEADER = "Upstash-Workflow-RunId";
|
|
99
99
|
var WORKFLOW_INIT_HEADER = "Upstash-Workflow-Init";
|
|
100
100
|
var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
|
|
101
|
+
var WORKFLOW_CREATED_AT_HEADER = "Upstash-Workflow-CreatedAt";
|
|
101
102
|
var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
|
|
102
103
|
var WORKFLOW_FAILURE_CALLBACK_HEADER = "Upstash-Workflow-Failure-Callback";
|
|
103
104
|
var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
|
|
@@ -213,9 +214,10 @@ import { QstashError as QstashError4 } from "@upstash/qstash";
|
|
|
213
214
|
|
|
214
215
|
// src/client/utils.ts
|
|
215
216
|
import { QstashError as QstashError2 } from "@upstash/qstash";
|
|
216
|
-
var makeNotifyRequest = async (requester, eventId, eventData) => {
|
|
217
|
+
var makeNotifyRequest = async (requester, eventId, eventData, workflowRunId) => {
|
|
218
|
+
const path = workflowRunId ? ["v2", "notify", workflowRunId, eventId] : ["v2", "notify", eventId];
|
|
217
219
|
const result = await requester.request({
|
|
218
|
-
path
|
|
220
|
+
path,
|
|
219
221
|
method: "POST",
|
|
220
222
|
body: typeof eventData === "string" ? eventData : JSON.stringify(eventData)
|
|
221
223
|
});
|
|
@@ -275,6 +277,66 @@ var getSteps = async (requester, workflowRunId, messageId, dispatchDebug) => {
|
|
|
275
277
|
}
|
|
276
278
|
}
|
|
277
279
|
};
|
|
280
|
+
function normalizeCursor(response) {
|
|
281
|
+
const cursor = response.cursor;
|
|
282
|
+
return { ...response, cursor: cursor || void 0 };
|
|
283
|
+
}
|
|
284
|
+
var DEFAULT_BULK_COUNT = 100;
|
|
285
|
+
function buildBulkActionQueryParameters(request, options) {
|
|
286
|
+
const cursor = "cursor" in request ? request.cursor : void 0;
|
|
287
|
+
if ("all" in request) {
|
|
288
|
+
return { count: request.count ?? DEFAULT_BULK_COUNT, cursor };
|
|
289
|
+
}
|
|
290
|
+
if ("dlqIds" in request) {
|
|
291
|
+
const ids = request.dlqIds;
|
|
292
|
+
if (Array.isArray(ids) && ids.length === 0) {
|
|
293
|
+
throw new QstashError2(
|
|
294
|
+
"Empty dlqIds array provided. If you intend to target all DLQ messages, use { all: true } explicitly."
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
return { dlqIds: ids, cursor };
|
|
298
|
+
}
|
|
299
|
+
if ("workflowRunIds" in request && request.workflowRunIds) {
|
|
300
|
+
if (request.workflowRunIds.length === 0) {
|
|
301
|
+
throw new QstashError2(
|
|
302
|
+
"Empty workflowRunIds array provided. If you intend to target all workflow runs, use { all: true } explicitly."
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
return { workflowRunIds: request.workflowRunIds };
|
|
306
|
+
}
|
|
307
|
+
const filter = request.filter;
|
|
308
|
+
if (!filter) {
|
|
309
|
+
throw new QstashError2(
|
|
310
|
+
"No filter provided. Use { filter: { ... } } with at least one filter field, or { all: true }."
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
if (options?.translateWorkflowUrl) {
|
|
314
|
+
const { workflowUrlStartingWith, workflowUrl, ...rest } = filter;
|
|
315
|
+
if (workflowUrlStartingWith && workflowUrl) {
|
|
316
|
+
throw new QstashError2(
|
|
317
|
+
"workflowUrl and workflowUrlStartingWith are mutually exclusive. Use workflowUrl for exact match or workflowUrlStartingWith for prefix match."
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
const urlParams = {};
|
|
321
|
+
if (workflowUrlStartingWith) {
|
|
322
|
+
urlParams.workflowUrl = workflowUrlStartingWith;
|
|
323
|
+
} else if (workflowUrl) {
|
|
324
|
+
urlParams.workflowUrl = workflowUrl;
|
|
325
|
+
urlParams.workflowUrlExactMatch = true;
|
|
326
|
+
}
|
|
327
|
+
return {
|
|
328
|
+
...rest,
|
|
329
|
+
...urlParams,
|
|
330
|
+
count: request.count ?? DEFAULT_BULK_COUNT,
|
|
331
|
+
cursor
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
...filter,
|
|
336
|
+
count: request.count ?? DEFAULT_BULK_COUNT,
|
|
337
|
+
cursor
|
|
338
|
+
};
|
|
339
|
+
}
|
|
278
340
|
|
|
279
341
|
// src/utils.ts
|
|
280
342
|
var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
|
@@ -773,6 +835,7 @@ var triggerFirstInvocation = async (params) => {
|
|
|
773
835
|
retries,
|
|
774
836
|
retryDelay,
|
|
775
837
|
flowControl,
|
|
838
|
+
redact,
|
|
776
839
|
unknownSdk
|
|
777
840
|
}) => {
|
|
778
841
|
const { headers } = getHeaders({
|
|
@@ -809,7 +872,8 @@ var triggerFirstInvocation = async (params) => {
|
|
|
809
872
|
body,
|
|
810
873
|
url: workflowContext.url,
|
|
811
874
|
delay,
|
|
812
|
-
notBefore
|
|
875
|
+
notBefore,
|
|
876
|
+
redact
|
|
813
877
|
};
|
|
814
878
|
}
|
|
815
879
|
);
|
|
@@ -968,7 +1032,6 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
968
1032
|
})}`
|
|
969
1033
|
);
|
|
970
1034
|
}
|
|
971
|
-
const userHeaders = recreateUserHeaders(request.headers);
|
|
972
1035
|
const { headers: requestHeaders } = getHeaders({
|
|
973
1036
|
initHeaderValue: "false",
|
|
974
1037
|
workflowConfig: {
|
|
@@ -976,7 +1039,6 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
976
1039
|
workflowUrl,
|
|
977
1040
|
telemetry
|
|
978
1041
|
},
|
|
979
|
-
userHeaders,
|
|
980
1042
|
invokeCount: Number(invokeCount)
|
|
981
1043
|
});
|
|
982
1044
|
const callResponse = {
|
|
@@ -1125,7 +1187,6 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
1125
1187
|
useJSONContent: false,
|
|
1126
1188
|
telemetry
|
|
1127
1189
|
},
|
|
1128
|
-
userHeaders: context.headers,
|
|
1129
1190
|
invokeCount,
|
|
1130
1191
|
stepInfo: {
|
|
1131
1192
|
step,
|
|
@@ -1483,9 +1544,9 @@ var LazyWaitEventStep = class extends BaseLazyStep {
|
|
|
1483
1544
|
};
|
|
1484
1545
|
var LazyNotifyStep = class extends LazyFunctionStep {
|
|
1485
1546
|
stepType = "Notify";
|
|
1486
|
-
constructor(context, stepName, eventId, eventData, requester) {
|
|
1547
|
+
constructor(context, stepName, eventId, eventData, requester, workflowRunId) {
|
|
1487
1548
|
super(context, stepName, async () => {
|
|
1488
|
-
const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
|
|
1549
|
+
const notifyResponse = await makeNotifyRequest(requester, eventId, eventData, workflowRunId);
|
|
1489
1550
|
return {
|
|
1490
1551
|
eventId,
|
|
1491
1552
|
eventData,
|
|
@@ -1555,7 +1616,6 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1555
1616
|
telemetry,
|
|
1556
1617
|
useJSONContent: false
|
|
1557
1618
|
},
|
|
1558
|
-
userHeaders: context.headers,
|
|
1559
1619
|
invokeCount
|
|
1560
1620
|
});
|
|
1561
1621
|
context.qstashClient.http.headers?.forEach((value, key) => {
|
|
@@ -1568,6 +1628,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1568
1628
|
Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
|
|
1569
1629
|
),
|
|
1570
1630
|
workflowRunId: context.workflowRunId,
|
|
1631
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
1571
1632
|
workflowUrl: context.url,
|
|
1572
1633
|
step
|
|
1573
1634
|
};
|
|
@@ -1663,12 +1724,14 @@ var LazyWaitForWebhookStep = class extends LazyWaitEventStep {
|
|
|
1663
1724
|
const parsedEventData = BaseLazyStep.tryParsing(eventData);
|
|
1664
1725
|
const body = parsedEventData.body;
|
|
1665
1726
|
const parsedBody = typeof body === "string" ? decodeBase64(body) : void 0;
|
|
1727
|
+
const methodUpper = parsedEventData.method.toUpperCase();
|
|
1728
|
+
const canHaveBody = methodUpper !== "GET" && methodUpper !== "HEAD";
|
|
1666
1729
|
const request = new Request(
|
|
1667
1730
|
`${parsedEventData.proto}://${parsedEventData.host}${parsedEventData.url}`,
|
|
1668
1731
|
{
|
|
1669
1732
|
method: parsedEventData.method,
|
|
1670
1733
|
headers: parsedEventData.header,
|
|
1671
|
-
body: parsedBody
|
|
1734
|
+
body: canHaveBody ? parsedBody : void 0
|
|
1672
1735
|
}
|
|
1673
1736
|
);
|
|
1674
1737
|
return {
|
|
@@ -1802,6 +1865,9 @@ var WorkflowHeaders = class {
|
|
|
1802
1865
|
}
|
|
1803
1866
|
}
|
|
1804
1867
|
addUserHeaders() {
|
|
1868
|
+
if (!this.userHeaders) {
|
|
1869
|
+
return;
|
|
1870
|
+
}
|
|
1805
1871
|
for (const [key, value] of this.userHeaders.entries()) {
|
|
1806
1872
|
const forwardKey = `Forward-${key}`;
|
|
1807
1873
|
this.headers.workflowHeaders[forwardKey] = value;
|
|
@@ -1908,7 +1974,6 @@ var submitParallelSteps = async ({
|
|
|
1908
1974
|
workflowUrl: context.url,
|
|
1909
1975
|
telemetry
|
|
1910
1976
|
},
|
|
1911
|
-
userHeaders: context.headers,
|
|
1912
1977
|
invokeCount
|
|
1913
1978
|
});
|
|
1914
1979
|
return {
|
|
@@ -2161,7 +2226,7 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
2161
2226
|
});
|
|
2162
2227
|
throw new WorkflowAbort(parallelStep.stepName, resultStep);
|
|
2163
2228
|
} catch (error) {
|
|
2164
|
-
if (isInstanceOf(error, WorkflowAbort) || isInstanceOf(error, QstashError5) && error.status === 400) {
|
|
2229
|
+
if (isInstanceOf(error, WorkflowAbort) || isInstanceOf(error, QstashError5) && error.status === 400 || isInstanceOf(error, QstashError5) && error.status === 412) {
|
|
2165
2230
|
throw error;
|
|
2166
2231
|
}
|
|
2167
2232
|
throw new WorkflowError(
|
|
@@ -2560,6 +2625,7 @@ var MiddlewareManager = class {
|
|
|
2560
2625
|
};
|
|
2561
2626
|
|
|
2562
2627
|
// src/context/context.ts
|
|
2628
|
+
import { QstashError as QstashError6 } from "@upstash/qstash";
|
|
2563
2629
|
var WorkflowContext = class {
|
|
2564
2630
|
executor;
|
|
2565
2631
|
steps;
|
|
@@ -2586,6 +2652,10 @@ var WorkflowContext = class {
|
|
|
2586
2652
|
* Run id of the workflow
|
|
2587
2653
|
*/
|
|
2588
2654
|
workflowRunId;
|
|
2655
|
+
/**
|
|
2656
|
+
* Creation time of the workflow run
|
|
2657
|
+
*/
|
|
2658
|
+
workflowRunCreatedAt;
|
|
2589
2659
|
/**
|
|
2590
2660
|
* URL of the workflow
|
|
2591
2661
|
*
|
|
@@ -2677,6 +2747,7 @@ var WorkflowContext = class {
|
|
|
2677
2747
|
constructor({
|
|
2678
2748
|
qstashClient,
|
|
2679
2749
|
workflowRunId,
|
|
2750
|
+
workflowRunCreatedAt,
|
|
2680
2751
|
headers,
|
|
2681
2752
|
steps,
|
|
2682
2753
|
url,
|
|
@@ -2689,6 +2760,7 @@ var WorkflowContext = class {
|
|
|
2689
2760
|
}) {
|
|
2690
2761
|
this.qstashClient = qstashClient;
|
|
2691
2762
|
this.workflowRunId = workflowRunId;
|
|
2763
|
+
this.workflowRunCreatedAt = workflowRunCreatedAt;
|
|
2692
2764
|
this.steps = steps;
|
|
2693
2765
|
this.url = url;
|
|
2694
2766
|
this.headers = headers;
|
|
@@ -2863,14 +2935,23 @@ var WorkflowContext = class {
|
|
|
2863
2935
|
* a notifyResponse field which contains a list of `Waiter` objects, each corresponding
|
|
2864
2936
|
* to a notified workflow run.
|
|
2865
2937
|
*
|
|
2938
|
+
* Optionally, you can pass a workflowRunId to enable lookback functionality:
|
|
2939
|
+
*
|
|
2940
|
+
* ```ts
|
|
2941
|
+
* const { eventId, eventData, notifyResponse } = await context.notify(
|
|
2942
|
+
* "notify step", "event-id", "event-data", "wfr_123"
|
|
2943
|
+
* );
|
|
2944
|
+
* ```
|
|
2945
|
+
*
|
|
2866
2946
|
* @param stepName
|
|
2867
2947
|
* @param eventId event id to notify
|
|
2868
2948
|
* @param eventData event data to notify with
|
|
2949
|
+
* @param workflowRunId optional workflow run id for lookback support
|
|
2869
2950
|
* @returns notify response which has event id, event data and list of waiters which were notified
|
|
2870
2951
|
*/
|
|
2871
|
-
async notify(stepName, eventId, eventData) {
|
|
2952
|
+
async notify(stepName, eventId, eventData, workflowRunId) {
|
|
2872
2953
|
return await this.addStep(
|
|
2873
|
-
new LazyNotifyStep(this, stepName, eventId, eventData, this.qstashClient.http)
|
|
2954
|
+
new LazyNotifyStep(this, stepName, eventId, eventData, this.qstashClient.http, workflowRunId)
|
|
2874
2955
|
);
|
|
2875
2956
|
}
|
|
2876
2957
|
async invoke(stepName, settings) {
|
|
@@ -2898,7 +2979,14 @@ var WorkflowContext = class {
|
|
|
2898
2979
|
* DisabledWorkflowContext.
|
|
2899
2980
|
*/
|
|
2900
2981
|
async addStep(step) {
|
|
2901
|
-
|
|
2982
|
+
try {
|
|
2983
|
+
return await this.executor.addStep(step);
|
|
2984
|
+
} catch (error) {
|
|
2985
|
+
if (isInstanceOf(error, QstashError6) && error.status === 412) {
|
|
2986
|
+
throw new WorkflowNonRetryableError(error.message);
|
|
2987
|
+
}
|
|
2988
|
+
throw error;
|
|
2989
|
+
}
|
|
2902
2990
|
}
|
|
2903
2991
|
get api() {
|
|
2904
2992
|
return new WorkflowApi({
|
|
@@ -2907,212 +2995,6 @@ var WorkflowContext = class {
|
|
|
2907
2995
|
}
|
|
2908
2996
|
};
|
|
2909
2997
|
|
|
2910
|
-
// src/dev-server.ts
|
|
2911
|
-
import { execSync, spawn } from "child_process";
|
|
2912
|
-
import { createWriteStream, existsSync, mkdirSync, chmodSync } from "fs";
|
|
2913
|
-
import { get as httpsGetRaw } from "https";
|
|
2914
|
-
import { get as httpGetRaw } from "http";
|
|
2915
|
-
import { join } from "path";
|
|
2916
|
-
import { tmpdir } from "os";
|
|
2917
|
-
var DEV_QSTASH_TOKEN = "eyJVc2VySUQiOiJkZWZhdWx0VXNlciIsIlBhc3N3b3JkIjoiZGVmYXVsdFBhc3N3b3JkIn0=";
|
|
2918
|
-
var DEV_QSTASH_CURRENT_SIGNING_KEY = "sig_7kYjw48mhY7kAjqNGcy6cr29RJ6r";
|
|
2919
|
-
var DEV_QSTASH_NEXT_SIGNING_KEY = "sig_5ZB6DVzB1wjE8S6rZ7eenA8Pdnhs";
|
|
2920
|
-
function getDevCredentials(port) {
|
|
2921
|
-
return {
|
|
2922
|
-
QSTASH_URL: `http://localhost:${port}`,
|
|
2923
|
-
QSTASH_TOKEN: DEV_QSTASH_TOKEN,
|
|
2924
|
-
QSTASH_CURRENT_SIGNING_KEY: DEV_QSTASH_CURRENT_SIGNING_KEY,
|
|
2925
|
-
QSTASH_NEXT_SIGNING_KEY: DEV_QSTASH_NEXT_SIGNING_KEY
|
|
2926
|
-
};
|
|
2927
|
-
}
|
|
2928
|
-
var CACHE_DIR = join("node_modules", ".cache", "upstash");
|
|
2929
|
-
function getPlatformArch() {
|
|
2930
|
-
const platform = process.platform === "darwin" ? "darwin" : "linux";
|
|
2931
|
-
const arch = process.arch === "arm64" ? "arm64" : "amd64";
|
|
2932
|
-
return { platform, arch };
|
|
2933
|
-
}
|
|
2934
|
-
function httpsGet(url) {
|
|
2935
|
-
return new Promise((resolve, reject) => {
|
|
2936
|
-
const request = (currentUrl) => {
|
|
2937
|
-
httpsGetRaw(currentUrl, { headers: { "User-Agent": "upstash-workflow" } }, (res) => {
|
|
2938
|
-
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
2939
|
-
request(res.headers.location);
|
|
2940
|
-
return;
|
|
2941
|
-
}
|
|
2942
|
-
if (res.statusCode && res.statusCode >= 400) {
|
|
2943
|
-
reject(new Error(`HTTP ${res.statusCode} fetching ${currentUrl}`));
|
|
2944
|
-
return;
|
|
2945
|
-
}
|
|
2946
|
-
const chunks = [];
|
|
2947
|
-
res.on("data", (chunk) => chunks.push(chunk));
|
|
2948
|
-
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
2949
|
-
res.on("error", reject);
|
|
2950
|
-
}).on("error", reject);
|
|
2951
|
-
};
|
|
2952
|
-
request(url);
|
|
2953
|
-
});
|
|
2954
|
-
}
|
|
2955
|
-
function downloadToFile(url, dest) {
|
|
2956
|
-
return new Promise((resolve, reject) => {
|
|
2957
|
-
const request = (currentUrl) => {
|
|
2958
|
-
httpsGetRaw(currentUrl, { headers: { "User-Agent": "upstash-workflow" } }, (res) => {
|
|
2959
|
-
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
2960
|
-
request(res.headers.location);
|
|
2961
|
-
return;
|
|
2962
|
-
}
|
|
2963
|
-
if (res.statusCode && res.statusCode >= 400) {
|
|
2964
|
-
reject(new Error(`HTTP ${res.statusCode} downloading ${currentUrl}`));
|
|
2965
|
-
return;
|
|
2966
|
-
}
|
|
2967
|
-
const file = createWriteStream(dest);
|
|
2968
|
-
res.pipe(file);
|
|
2969
|
-
file.on("finish", () => {
|
|
2970
|
-
file.close(() => resolve());
|
|
2971
|
-
});
|
|
2972
|
-
file.on("error", reject);
|
|
2973
|
-
}).on("error", reject);
|
|
2974
|
-
};
|
|
2975
|
-
request(url);
|
|
2976
|
-
});
|
|
2977
|
-
}
|
|
2978
|
-
async function resolveLatestVersion() {
|
|
2979
|
-
const data = await httpsGet("https://api.github.com/repos/upstash/qstash-cli/releases/latest");
|
|
2980
|
-
const json = JSON.parse(data.toString());
|
|
2981
|
-
return json.tag_name;
|
|
2982
|
-
}
|
|
2983
|
-
async function ensureBinary() {
|
|
2984
|
-
const version = await resolveLatestVersion();
|
|
2985
|
-
const cacheDir = join(CACHE_DIR, `qstash-server-${version}`);
|
|
2986
|
-
const binaryPath = join(cacheDir, "qstash");
|
|
2987
|
-
if (existsSync(binaryPath)) {
|
|
2988
|
-
return binaryPath;
|
|
2989
|
-
}
|
|
2990
|
-
const { platform, arch } = getPlatformArch();
|
|
2991
|
-
const downloadUrl = `https://artifacts.upstash.com/qstash/versions/${version}/qstash-server_${version}_${platform}_${arch}.tar.gz`;
|
|
2992
|
-
console.log(`[workflow-dev] Downloading QStash server...`);
|
|
2993
|
-
mkdirSync(cacheDir, { recursive: true });
|
|
2994
|
-
const tempFile = join(tmpdir(), `qstash-server-${version}-${Date.now()}.tar.gz`);
|
|
2995
|
-
await downloadToFile(downloadUrl, tempFile);
|
|
2996
|
-
execSync(`tar -xzf "${tempFile}" -C "${cacheDir}"`);
|
|
2997
|
-
chmodSync(binaryPath, 493);
|
|
2998
|
-
return binaryPath;
|
|
2999
|
-
}
|
|
3000
|
-
function startServer(binaryPath, port) {
|
|
3001
|
-
return new Promise((resolve, reject) => {
|
|
3002
|
-
const child = spawn(binaryPath, ["dev", "-port", String(port)], {
|
|
3003
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
3004
|
-
});
|
|
3005
|
-
let resolved = false;
|
|
3006
|
-
const cleanup = () => {
|
|
3007
|
-
if (!child.killed) {
|
|
3008
|
-
child.kill("SIGTERM");
|
|
3009
|
-
}
|
|
3010
|
-
};
|
|
3011
|
-
process.on("exit", cleanup);
|
|
3012
|
-
process.on("SIGINT", () => {
|
|
3013
|
-
cleanup();
|
|
3014
|
-
process.exit(0);
|
|
3015
|
-
});
|
|
3016
|
-
process.on("SIGTERM", () => {
|
|
3017
|
-
cleanup();
|
|
3018
|
-
process.exit(0);
|
|
3019
|
-
});
|
|
3020
|
-
let stdoutBuffer = "";
|
|
3021
|
-
child.stdout.on("data", (data) => {
|
|
3022
|
-
const text = data.toString();
|
|
3023
|
-
stdoutBuffer += text;
|
|
3024
|
-
const lines = stdoutBuffer.split("\n");
|
|
3025
|
-
stdoutBuffer = lines.pop() ?? "";
|
|
3026
|
-
for (const line of lines) {
|
|
3027
|
-
if (line.match(/runn+ing at/) && !resolved) {
|
|
3028
|
-
resolved = true;
|
|
3029
|
-
const creds = getDevCredentials(port);
|
|
3030
|
-
console.log(`[workflow-dev] QStash server running at ${creds.QSTASH_URL}`);
|
|
3031
|
-
console.log(
|
|
3032
|
-
`[workflow-dev] View logs at \x1B[1;32mhttps://console.upstash.com/workflow/local-mode-user/logs\x1B[0m`
|
|
3033
|
-
);
|
|
3034
|
-
resolve(cleanup);
|
|
3035
|
-
}
|
|
3036
|
-
}
|
|
3037
|
-
});
|
|
3038
|
-
child.stderr.on("data", (data) => {
|
|
3039
|
-
const text = data.toString();
|
|
3040
|
-
if (!resolved) {
|
|
3041
|
-
process.stderr.write(`[workflow-dev] ${text}`);
|
|
3042
|
-
}
|
|
3043
|
-
});
|
|
3044
|
-
child.on("error", (err2) => {
|
|
3045
|
-
if (!resolved) {
|
|
3046
|
-
reject(new Error(`[workflow-dev] Failed to start QStash server: ${err2.message}`));
|
|
3047
|
-
}
|
|
3048
|
-
});
|
|
3049
|
-
child.on("exit", (code) => {
|
|
3050
|
-
if (!resolved) {
|
|
3051
|
-
reject(
|
|
3052
|
-
new Error(`[workflow-dev] QStash server exited with code ${code} before becoming ready`)
|
|
3053
|
-
);
|
|
3054
|
-
}
|
|
3055
|
-
});
|
|
3056
|
-
setTimeout(() => {
|
|
3057
|
-
if (!resolved) {
|
|
3058
|
-
cleanup();
|
|
3059
|
-
reject(new Error("[workflow-dev] QStash server did not become ready within 30 seconds"));
|
|
3060
|
-
}
|
|
3061
|
-
}, 3e4);
|
|
3062
|
-
});
|
|
3063
|
-
}
|
|
3064
|
-
function isDevServerRunning(port) {
|
|
3065
|
-
return new Promise((resolve) => {
|
|
3066
|
-
const req = httpGetRaw(
|
|
3067
|
-
`http://127.0.0.1:${port}/v2/keys`,
|
|
3068
|
-
{
|
|
3069
|
-
headers: { Authorization: `Bearer ${DEV_QSTASH_TOKEN}` },
|
|
3070
|
-
timeout: 2e3
|
|
3071
|
-
},
|
|
3072
|
-
(res) => {
|
|
3073
|
-
if (res.statusCode !== 200) {
|
|
3074
|
-
resolve(false);
|
|
3075
|
-
return;
|
|
3076
|
-
}
|
|
3077
|
-
const chunks = [];
|
|
3078
|
-
res.on("data", (chunk) => chunks.push(chunk));
|
|
3079
|
-
res.on("end", () => {
|
|
3080
|
-
try {
|
|
3081
|
-
const body = JSON.parse(Buffer.concat(chunks).toString());
|
|
3082
|
-
resolve(
|
|
3083
|
-
body.current === DEV_QSTASH_CURRENT_SIGNING_KEY && body.next === DEV_QSTASH_NEXT_SIGNING_KEY
|
|
3084
|
-
);
|
|
3085
|
-
} catch {
|
|
3086
|
-
resolve(false);
|
|
3087
|
-
}
|
|
3088
|
-
});
|
|
3089
|
-
res.on("error", () => resolve(false));
|
|
3090
|
-
}
|
|
3091
|
-
);
|
|
3092
|
-
req.on("error", () => resolve(false));
|
|
3093
|
-
req.on("timeout", () => {
|
|
3094
|
-
req.destroy();
|
|
3095
|
-
resolve(false);
|
|
3096
|
-
});
|
|
3097
|
-
});
|
|
3098
|
-
}
|
|
3099
|
-
var serverPromise = null;
|
|
3100
|
-
var serverCleanup = null;
|
|
3101
|
-
function ensureDevServer(environment) {
|
|
3102
|
-
if (!serverPromise) {
|
|
3103
|
-
const port = Number(environment.WORKFLOW_DEV_PORT) || 8080;
|
|
3104
|
-
serverPromise = isDevServerRunning(port).then((alreadyRunning) => {
|
|
3105
|
-
if (alreadyRunning) {
|
|
3106
|
-
return;
|
|
3107
|
-
}
|
|
3108
|
-
return ensureBinary().then((binaryPath) => startServer(binaryPath, port)).then((cleanup) => {
|
|
3109
|
-
serverCleanup = cleanup;
|
|
3110
|
-
});
|
|
3111
|
-
});
|
|
3112
|
-
}
|
|
3113
|
-
return serverPromise;
|
|
3114
|
-
}
|
|
3115
|
-
|
|
3116
2998
|
// src/middleware/middleware.ts
|
|
3117
2999
|
var WorkflowMiddleware = class {
|
|
3118
3000
|
name;
|
|
@@ -3225,6 +3107,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3225
3107
|
token: "disabled-client"
|
|
3226
3108
|
}),
|
|
3227
3109
|
workflowRunId: context.workflowRunId,
|
|
3110
|
+
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
3228
3111
|
headers: context.headers,
|
|
3229
3112
|
steps: [],
|
|
3230
3113
|
url: context.url,
|
|
@@ -3426,7 +3309,9 @@ var handleFailure = async ({
|
|
|
3426
3309
|
return ok({ result: "failure-function-undefined" });
|
|
3427
3310
|
}
|
|
3428
3311
|
try {
|
|
3429
|
-
const { status, header, body, url, sourceBody, workflowRunId } = JSON.parse(
|
|
3312
|
+
const { status, header, body, url, sourceBody, workflowRunId, workflowCreatedAt } = JSON.parse(
|
|
3313
|
+
requestPayload
|
|
3314
|
+
);
|
|
3430
3315
|
const decodedBody = body ? decodeBase64(body) : "{}";
|
|
3431
3316
|
let errorMessage = "";
|
|
3432
3317
|
let failStack = "";
|
|
@@ -3455,6 +3340,7 @@ var handleFailure = async ({
|
|
|
3455
3340
|
telemetry: void 0,
|
|
3456
3341
|
// not going to make requests in authentication check
|
|
3457
3342
|
label: userHeaders.get(WORKFLOW_LABEL_HEADER) ?? void 0,
|
|
3343
|
+
workflowRunCreatedAt: workflowCreatedAt,
|
|
3458
3344
|
middlewareManager: void 0
|
|
3459
3345
|
});
|
|
3460
3346
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
@@ -3766,33 +3652,19 @@ var AUTH_FAIL_MESSAGE = `Failed to authenticate Workflow request. If this is une
|
|
|
3766
3652
|
|
|
3767
3653
|
// src/serve/index.ts
|
|
3768
3654
|
var serveBase = (routeFunction, telemetry, options, internalOptions) => {
|
|
3769
|
-
const
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
const
|
|
3781
|
-
options,
|
|
3782
|
-
internalOptions
|
|
3783
|
-
);
|
|
3655
|
+
const {
|
|
3656
|
+
initialPayloadParser,
|
|
3657
|
+
url,
|
|
3658
|
+
failureFunction,
|
|
3659
|
+
baseUrl,
|
|
3660
|
+
env,
|
|
3661
|
+
disableTelemetry,
|
|
3662
|
+
middlewares,
|
|
3663
|
+
internal
|
|
3664
|
+
} = processOptions(options, internalOptions);
|
|
3665
|
+
telemetry = disableTelemetry ? void 0 : telemetry;
|
|
3666
|
+
const { generateResponse: responseGenerator, useJSONContent } = internal;
|
|
3784
3667
|
const handler = async (request, middlewareManager) => {
|
|
3785
|
-
const {
|
|
3786
|
-
initialPayloadParser,
|
|
3787
|
-
url,
|
|
3788
|
-
failureFunction,
|
|
3789
|
-
baseUrl,
|
|
3790
|
-
env,
|
|
3791
|
-
disableTelemetry: optDisableTelemetry,
|
|
3792
|
-
internal
|
|
3793
|
-
} = resolvedOptions;
|
|
3794
|
-
const currentTelemetry = optDisableTelemetry ? void 0 : telemetry;
|
|
3795
|
-
const { generateResponse: responseGenerator, useJSONContent } = internal;
|
|
3796
3668
|
await middlewareManager.dispatchDebug("onInfo", {
|
|
3797
3669
|
info: `Received request for workflow execution.`
|
|
3798
3670
|
});
|
|
@@ -3872,6 +3744,7 @@ var serveBase = (routeFunction, telemetry, options, internalOptions) => {
|
|
|
3872
3744
|
}
|
|
3873
3745
|
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
3874
3746
|
const label = request.headers.get(WORKFLOW_LABEL_HEADER) ?? void 0;
|
|
3747
|
+
const workflowRunCreatedAt = request.headers.get(WORKFLOW_CREATED_AT_HEADER);
|
|
3875
3748
|
const workflowContext = new WorkflowContext({
|
|
3876
3749
|
qstashClient: regionalClient,
|
|
3877
3750
|
workflowRunId,
|
|
@@ -3880,9 +3753,10 @@ var serveBase = (routeFunction, telemetry, options, internalOptions) => {
|
|
|
3880
3753
|
steps,
|
|
3881
3754
|
url: workflowUrl,
|
|
3882
3755
|
env,
|
|
3883
|
-
telemetry
|
|
3756
|
+
telemetry,
|
|
3884
3757
|
invokeCount,
|
|
3885
3758
|
label,
|
|
3759
|
+
workflowRunCreatedAt: Number(workflowRunCreatedAt),
|
|
3886
3760
|
middlewareManager
|
|
3887
3761
|
});
|
|
3888
3762
|
const authCheck = await DisabledWorkflowContext.tryAuthentication(
|
|
@@ -3906,7 +3780,7 @@ var serveBase = (routeFunction, telemetry, options, internalOptions) => {
|
|
|
3906
3780
|
requestPayload: rawInitialPayload,
|
|
3907
3781
|
client: regionalClient,
|
|
3908
3782
|
workflowUrl,
|
|
3909
|
-
telemetry
|
|
3783
|
+
telemetry,
|
|
3910
3784
|
middlewareManager
|
|
3911
3785
|
});
|
|
3912
3786
|
if (callReturnCheck.isErr()) {
|
|
@@ -3915,7 +3789,7 @@ var serveBase = (routeFunction, telemetry, options, internalOptions) => {
|
|
|
3915
3789
|
const result = isFirstInvocation ? await triggerFirstInvocation({
|
|
3916
3790
|
workflowContext,
|
|
3917
3791
|
useJSONContent,
|
|
3918
|
-
telemetry
|
|
3792
|
+
telemetry,
|
|
3919
3793
|
invokeCount,
|
|
3920
3794
|
middlewareManager,
|
|
3921
3795
|
unknownSdk
|
|
@@ -3983,9 +3857,7 @@ var serveBase = (routeFunction, telemetry, options, internalOptions) => {
|
|
|
3983
3857
|
);
|
|
3984
3858
|
};
|
|
3985
3859
|
const safeHandler = async (request) => {
|
|
3986
|
-
const middlewareManager = new MiddlewareManager(
|
|
3987
|
-
resolvedOptions.middlewares
|
|
3988
|
-
);
|
|
3860
|
+
const middlewareManager = new MiddlewareManager(middlewares);
|
|
3989
3861
|
try {
|
|
3990
3862
|
return await handler(request, middlewareManager);
|
|
3991
3863
|
} catch (error) {
|
|
@@ -4021,6 +3893,8 @@ export {
|
|
|
4021
3893
|
WorkflowRetryAfterError,
|
|
4022
3894
|
makeNotifyRequest,
|
|
4023
3895
|
makeGetWaitersRequest,
|
|
3896
|
+
normalizeCursor,
|
|
3897
|
+
buildBulkActionQueryParameters,
|
|
4024
3898
|
WORKFLOW_LABEL_HEADER,
|
|
4025
3899
|
SDK_TELEMETRY,
|
|
4026
3900
|
getWorkflowRunId,
|
|
@@ -4029,9 +3903,6 @@ export {
|
|
|
4029
3903
|
prepareFlowControl,
|
|
4030
3904
|
serveManyBase,
|
|
4031
3905
|
WorkflowContext,
|
|
4032
|
-
DEV_QSTASH_TOKEN,
|
|
4033
|
-
getDevCredentials,
|
|
4034
|
-
ensureDevServer,
|
|
4035
3906
|
WorkflowMiddleware,
|
|
4036
3907
|
loggingMiddleware,
|
|
4037
3908
|
serveBase,
|
package/cloudflare.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as RouteFunction, d as WorkflowServeOptions,
|
|
2
|
-
import { s as serveManyBase } from './serve-many-
|
|
1
|
+
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-B2S08hRU.mjs';
|
|
2
|
+
import { s as serveManyBase } from './serve-many-C6sa_DxN.mjs';
|
|
3
3
|
import '@upstash/qstash';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|
package/cloudflare.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as RouteFunction, d as WorkflowServeOptions,
|
|
2
|
-
import { s as serveManyBase } from './serve-many-
|
|
1
|
+
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-B2S08hRU.js';
|
|
2
|
+
import { s as serveManyBase } from './serve-many-B-fe7bh7.js';
|
|
3
3
|
import '@upstash/qstash';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|