@upstash/workflow 1.3.0 → 1.3.2-rc
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 +81 -14
- package/astro.mjs +1 -1
- package/{chunk-G24J5PCC.mjs → chunk-ICDNN4UW.mjs} +84 -14
- package/cloudflare.d.mts +2 -2
- package/cloudflare.d.ts +2 -2
- package/cloudflare.js +81 -14
- package/cloudflare.mjs +1 -1
- package/express.d.mts +2 -2
- package/express.d.ts +2 -2
- package/express.js +81 -14
- package/express.mjs +1 -1
- package/h3.d.mts +2 -2
- package/h3.d.ts +2 -2
- package/h3.js +81 -14
- package/h3.mjs +1 -1
- package/hono.d.mts +2 -2
- package/hono.d.ts +2 -2
- package/hono.js +81 -14
- package/hono.mjs +1 -1
- package/index.d.mts +43 -7
- package/index.d.ts +43 -7
- package/index.js +84 -15
- package/index.mjs +8 -3
- package/nextjs.d.mts +2 -2
- package/nextjs.d.ts +2 -2
- package/nextjs.js +81 -14
- package/nextjs.mjs +1 -1
- package/package.json +1 -1
- package/react-router.d.mts +2 -2
- package/react-router.d.ts +2 -2
- package/react-router.js +81 -14
- package/react-router.mjs +1 -1
- package/{serve-many-D3D9uE4u.d.mts → serve-many-CG3BFvO3.d.mts} +1 -1
- package/{serve-many-kPOasiyb.d.ts → serve-many-iJF1IUXk.d.ts} +1 -1
- package/solidjs.d.mts +1 -1
- package/solidjs.d.ts +1 -1
- package/solidjs.js +81 -14
- package/solidjs.mjs +1 -1
- package/svelte.d.mts +2 -2
- package/svelte.d.ts +2 -2
- package/svelte.js +81 -14
- package/svelte.mjs +1 -1
- package/tanstack.d.mts +2 -2
- package/tanstack.d.ts +2 -2
- package/tanstack.js +81 -14
- package/tanstack.mjs +1 -1
- package/{types-B_E1VAK6.d.ts → types-CekOpKvz.d.mts} +14 -6
- package/{types-B_E1VAK6.d.mts → types-CekOpKvz.d.ts} +14 -6
package/nextjs.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next';
|
|
2
|
-
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-
|
|
3
|
-
import { s as serveManyBase } from './serve-many-
|
|
2
|
+
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-CekOpKvz.mjs';
|
|
3
|
+
import { s as serveManyBase } from './serve-many-CG3BFvO3.mjs';
|
|
4
4
|
import '@upstash/qstash';
|
|
5
5
|
import 'zod';
|
|
6
6
|
|
package/nextjs.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next';
|
|
2
|
-
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-
|
|
3
|
-
import { s as serveManyBase } from './serve-many-
|
|
2
|
+
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-CekOpKvz.js';
|
|
3
|
+
import { s as serveManyBase } from './serve-many-iJF1IUXk.js';
|
|
4
4
|
import '@upstash/qstash';
|
|
5
5
|
import 'zod';
|
|
6
6
|
|
package/nextjs.js
CHANGED
|
@@ -106,6 +106,22 @@ var formatWorkflowError = (error) => {
|
|
|
106
106
|
message: `An error occured while executing workflow: '${typeof error === "string" ? error : JSON.stringify(error)}'`
|
|
107
107
|
};
|
|
108
108
|
};
|
|
109
|
+
var attachStepNameToError = (error, stepName) => {
|
|
110
|
+
if (typeof error !== "object" || error === null) return;
|
|
111
|
+
if ("errorStepName" in error) return;
|
|
112
|
+
if (!Object.isExtensible(error)) return;
|
|
113
|
+
try {
|
|
114
|
+
error.errorStepName = stepName;
|
|
115
|
+
} catch {
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
var getStepNameFromError = (error) => {
|
|
119
|
+
if (typeof error === "object" && error !== null) {
|
|
120
|
+
const stepName = error.errorStepName;
|
|
121
|
+
return typeof stepName === "string" ? stepName : void 0;
|
|
122
|
+
}
|
|
123
|
+
return void 0;
|
|
124
|
+
};
|
|
109
125
|
function getConstructorName(obj) {
|
|
110
126
|
if (obj === null || obj === void 0) {
|
|
111
127
|
return null;
|
|
@@ -199,12 +215,13 @@ var WORKFLOW_RETRIED_HEADER = "Upstash-Retried";
|
|
|
199
215
|
var WORKFLOW_LABEL_HEADER = "Upstash-Label";
|
|
200
216
|
var WORKFLOW_UNKOWN_SDK_VERSION_HEADER = "Upstash-Workflow-Unknown-Sdk";
|
|
201
217
|
var WORKFLOW_UNKOWN_SDK_TRIGGER_HEADER = "upstash-workflow-trigger-by-sdk";
|
|
218
|
+
var WORKFLOW_ERROR_STEP_NAME_HEADER = "Upstash-Error-Step-Name";
|
|
202
219
|
var WORKFLOW_PROTOCOL_VERSION = "1";
|
|
203
220
|
var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
204
221
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
205
222
|
var NO_CONCURRENCY = 1;
|
|
206
223
|
var DEFAULT_RETRIES = 3;
|
|
207
|
-
var VERSION = "v1.2
|
|
224
|
+
var VERSION = "v1.3.2";
|
|
208
225
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
209
226
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
210
227
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
@@ -219,6 +236,31 @@ var import_qstash4 = require("@upstash/qstash");
|
|
|
219
236
|
// src/utils.ts
|
|
220
237
|
var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
|
221
238
|
var NANOID_LENGTH = 21;
|
|
239
|
+
var RESOURCE_NAME_PATTERN = /^[a-zA-Z0-9\-_.]+$/;
|
|
240
|
+
function validateLabel(label) {
|
|
241
|
+
if (label === void 0) return;
|
|
242
|
+
const labels = Array.isArray(label) ? label : [label];
|
|
243
|
+
if (labels.length === 0) {
|
|
244
|
+
throw new WorkflowNonRetryableError("Invalid label: label array must not be empty.");
|
|
245
|
+
}
|
|
246
|
+
for (const value of labels) {
|
|
247
|
+
if (!RESOURCE_NAME_PATTERN.test(value)) {
|
|
248
|
+
throw new WorkflowNonRetryableError(
|
|
249
|
+
`Invalid label "${value}": must be alphanumeric, hyphen, underscore, or period.`
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
function serializeLabel(label) {
|
|
255
|
+
return Array.isArray(label) ? label.join(",") : label;
|
|
256
|
+
}
|
|
257
|
+
function validateFlowControl(flowControl) {
|
|
258
|
+
if (flowControl?.key !== void 0 && !RESOURCE_NAME_PATTERN.test(flowControl.key)) {
|
|
259
|
+
throw new WorkflowNonRetryableError(
|
|
260
|
+
`Invalid flow control key "${flowControl.key}": must be alphanumeric, hyphen, underscore, or period.`
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
222
264
|
function getRandomInt() {
|
|
223
265
|
return Math.floor(Math.random() * NANOID_CHARS.length);
|
|
224
266
|
}
|
|
@@ -754,8 +796,8 @@ var triggerFirstInvocation = async (params) => {
|
|
|
754
796
|
if (unknownSdk) {
|
|
755
797
|
headers[WORKFLOW_UNKOWN_SDK_TRIGGER_HEADER] = "true";
|
|
756
798
|
}
|
|
757
|
-
if (workflowContext.
|
|
758
|
-
headers[WORKFLOW_LABEL_HEADER] = workflowContext.
|
|
799
|
+
if (workflowContext.labels.length > 0) {
|
|
800
|
+
headers[WORKFLOW_LABEL_HEADER] = serializeLabel(workflowContext.labels);
|
|
759
801
|
}
|
|
760
802
|
const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
|
|
761
803
|
return {
|
|
@@ -1557,8 +1599,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1557
1599
|
});
|
|
1558
1600
|
triggerHeaders["Upstash-Workflow-Invoke"] = "true";
|
|
1559
1601
|
if (label) {
|
|
1560
|
-
|
|
1561
|
-
triggerHeaders[
|
|
1602
|
+
const labelHeader = serializeLabel(label);
|
|
1603
|
+
triggerHeaders[WORKFLOW_LABEL_HEADER] = labelHeader;
|
|
1604
|
+
triggerHeaders[`upstash-forward-${WORKFLOW_LABEL_HEADER}`] = labelHeader;
|
|
1562
1605
|
}
|
|
1563
1606
|
return { headers: triggerHeaders, contentType };
|
|
1564
1607
|
}
|
|
@@ -1901,7 +1944,13 @@ var submitSingleStep = async ({
|
|
|
1901
1944
|
await dispatchLifecycle("beforeExecution", {
|
|
1902
1945
|
stepName: lazyStep.stepName
|
|
1903
1946
|
});
|
|
1904
|
-
|
|
1947
|
+
let resultStep;
|
|
1948
|
+
try {
|
|
1949
|
+
resultStep = await lazyStep.getResultStep(concurrency, stepId);
|
|
1950
|
+
} catch (error) {
|
|
1951
|
+
attachStepNameToError(error, lazyStep.stepName);
|
|
1952
|
+
throw error;
|
|
1953
|
+
}
|
|
1905
1954
|
const { headers } = lazyStep.getHeaders({
|
|
1906
1955
|
context,
|
|
1907
1956
|
step: resultStep,
|
|
@@ -2124,9 +2173,11 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
2124
2173
|
if (isInstanceOf(error, WorkflowAbort) || isInstanceOf(error, import_qstash5.QstashError) && error.status === 400 || isInstanceOf(error, import_qstash5.QstashError) && error.status === 412) {
|
|
2125
2174
|
throw error;
|
|
2126
2175
|
}
|
|
2127
|
-
|
|
2176
|
+
const wrappedError = new WorkflowError(
|
|
2128
2177
|
`Error submitting steps to QStash in partial parallel step execution: ${error}`
|
|
2129
2178
|
);
|
|
2179
|
+
attachStepNameToError(wrappedError, parallelSteps[stepIndex].stepName);
|
|
2180
|
+
throw wrappedError;
|
|
2130
2181
|
}
|
|
2131
2182
|
break;
|
|
2132
2183
|
}
|
|
@@ -2699,9 +2750,10 @@ var WorkflowContext = class {
|
|
|
2699
2750
|
*/
|
|
2700
2751
|
env;
|
|
2701
2752
|
/**
|
|
2702
|
-
*
|
|
2753
|
+
* Labels attached to the workflow run.
|
|
2703
2754
|
*
|
|
2704
|
-
* Can be used to filter the workflow run logs.
|
|
2755
|
+
* Can be used to filter the workflow run logs. A run can have multiple
|
|
2756
|
+
* labels when triggered with `label: string[]`.
|
|
2705
2757
|
*
|
|
2706
2758
|
* Can be set by passing a `label` parameter when triggering the workflow
|
|
2707
2759
|
* with `client.trigger`:
|
|
@@ -2709,11 +2761,20 @@ var WorkflowContext = class {
|
|
|
2709
2761
|
* ```ts
|
|
2710
2762
|
* await client.trigger({
|
|
2711
2763
|
* url: "https://workflow-endpoint.com",
|
|
2712
|
-
* label: "
|
|
2764
|
+
* label: ["label-1", "label-2"]
|
|
2713
2765
|
* });
|
|
2714
2766
|
* ```
|
|
2715
2767
|
*/
|
|
2716
|
-
|
|
2768
|
+
labels;
|
|
2769
|
+
/**
|
|
2770
|
+
* Label of the workflow run.
|
|
2771
|
+
*
|
|
2772
|
+
* @deprecated Use `labels` instead. When a run has multiple labels, this
|
|
2773
|
+
* only returns the first one.
|
|
2774
|
+
*/
|
|
2775
|
+
get label() {
|
|
2776
|
+
return this.labels[0];
|
|
2777
|
+
}
|
|
2717
2778
|
/**
|
|
2718
2779
|
* Number of times QStash has retried delivering the current request.
|
|
2719
2780
|
*
|
|
@@ -2744,7 +2805,7 @@ var WorkflowContext = class {
|
|
|
2744
2805
|
this.headers = headers;
|
|
2745
2806
|
this.requestPayload = initialPayload;
|
|
2746
2807
|
this.env = env ?? {};
|
|
2747
|
-
this.
|
|
2808
|
+
this.labels = label === void 0 ? [] : Array.isArray(label) ? label : label ? label.split(",") : [];
|
|
2748
2809
|
this.retried = retried ?? 0;
|
|
2749
2810
|
const middlewareManagerInstance = middlewareManager ?? new MiddlewareManager([]);
|
|
2750
2811
|
middlewareManagerInstance.assignContext(this);
|
|
@@ -2825,8 +2886,10 @@ var WorkflowContext = class {
|
|
|
2825
2886
|
await this.addStep(new LazySleepUntilStep(this, stepName, time));
|
|
2826
2887
|
}
|
|
2827
2888
|
async call(stepName, settings) {
|
|
2889
|
+
validateFlowControl(settings.flowControl);
|
|
2828
2890
|
let callStep;
|
|
2829
2891
|
if ("workflow" in settings) {
|
|
2892
|
+
validateLabel(settings.label);
|
|
2830
2893
|
const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
|
|
2831
2894
|
const stringBody = typeof settings.body === "string" ? settings.body : settings.body === void 0 ? void 0 : JSON.stringify(settings.body);
|
|
2832
2895
|
callStep = new LazyCallStep({
|
|
@@ -2934,6 +2997,8 @@ var WorkflowContext = class {
|
|
|
2934
2997
|
);
|
|
2935
2998
|
}
|
|
2936
2999
|
async invoke(stepName, settings) {
|
|
3000
|
+
validateLabel(settings.label);
|
|
3001
|
+
validateFlowControl(settings.flowControl);
|
|
2937
3002
|
return await this.addStep(
|
|
2938
3003
|
new LazyInvokeStep(this, stepName, settings)
|
|
2939
3004
|
);
|
|
@@ -3019,7 +3084,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3019
3084
|
url: context.url,
|
|
3020
3085
|
initialPayload: context.requestPayload,
|
|
3021
3086
|
env: context.env,
|
|
3022
|
-
label: context.
|
|
3087
|
+
label: context.labels,
|
|
3023
3088
|
retried: context.retried
|
|
3024
3089
|
});
|
|
3025
3090
|
try {
|
|
@@ -3857,10 +3922,12 @@ var serveBase = (routeFunction, telemetry, options, internalOptions) => {
|
|
|
3857
3922
|
await middlewareManager.dispatchDebug("onError", {
|
|
3858
3923
|
error: isInstanceOf(error, Error) ? error : new Error(formattedError.message)
|
|
3859
3924
|
});
|
|
3925
|
+
const stepName = getStepNameFromError(error)?.replace(/[\u0000-\u001F\u007F]+/g, " ").trim();
|
|
3860
3926
|
return new Response(JSON.stringify(formattedError), {
|
|
3861
3927
|
status: 500,
|
|
3862
3928
|
headers: {
|
|
3863
|
-
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3929
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
3930
|
+
...stepName ? { [WORKFLOW_ERROR_STEP_NAME_HEADER]: stepName } : {}
|
|
3864
3931
|
}
|
|
3865
3932
|
});
|
|
3866
3933
|
}
|
package/nextjs.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@upstash/workflow","version":"1.3.
|
|
1
|
+
{"name":"@upstash/workflow","version":"1.3.2-rc","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"},"./tanstack":{"import":"./tanstack.mjs","require":"./tanstack.js"},"./react-router":{"import":"./react-router.mjs","require":"./react-router.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@github.com:upstash/workflow-js.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.6","astro":"^4.16.7","eslint":"^9.11.1","eslint-plugin-unicorn":"^55.0.0","express":"^5.1.0","globals":"^15.10.0","h3":"^1.12.0","hono":"^4.6.20","husky":"^9.1.6","next":"^14.2.14","prettier":"3.3.3","tsup":"^8.3.0","typescript":"^5.7.2","typescript-eslint":"^8.18.0"},"dependencies":{"@upstash/qstash":"^2.11.0"},"directories":{"example":"examples"},"peerDependencies":{"zod":"^3.25.0 || ^4.0.0"}}
|
package/react-router.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-
|
|
2
|
-
import { s as serveManyBase } from './serve-many-
|
|
1
|
+
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-CekOpKvz.mjs';
|
|
2
|
+
import { s as serveManyBase } from './serve-many-CG3BFvO3.mjs';
|
|
3
3
|
import '@upstash/qstash';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|
package/react-router.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-
|
|
2
|
-
import { s as serveManyBase } from './serve-many-
|
|
1
|
+
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-CekOpKvz.js';
|
|
2
|
+
import { s as serveManyBase } from './serve-many-iJF1IUXk.js';
|
|
3
3
|
import '@upstash/qstash';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|
package/react-router.js
CHANGED
|
@@ -39,12 +39,13 @@ var WORKFLOW_RETRIED_HEADER = "Upstash-Retried";
|
|
|
39
39
|
var WORKFLOW_LABEL_HEADER = "Upstash-Label";
|
|
40
40
|
var WORKFLOW_UNKOWN_SDK_VERSION_HEADER = "Upstash-Workflow-Unknown-Sdk";
|
|
41
41
|
var WORKFLOW_UNKOWN_SDK_TRIGGER_HEADER = "upstash-workflow-trigger-by-sdk";
|
|
42
|
+
var WORKFLOW_ERROR_STEP_NAME_HEADER = "Upstash-Error-Step-Name";
|
|
42
43
|
var WORKFLOW_PROTOCOL_VERSION = "1";
|
|
43
44
|
var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
44
45
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
45
46
|
var NO_CONCURRENCY = 1;
|
|
46
47
|
var DEFAULT_RETRIES = 3;
|
|
47
|
-
var VERSION = "v1.2
|
|
48
|
+
var VERSION = "v1.3.2";
|
|
48
49
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
49
50
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
50
51
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
@@ -127,6 +128,22 @@ var formatWorkflowError = (error) => {
|
|
|
127
128
|
message: `An error occured while executing workflow: '${typeof error === "string" ? error : JSON.stringify(error)}'`
|
|
128
129
|
};
|
|
129
130
|
};
|
|
131
|
+
var attachStepNameToError = (error, stepName) => {
|
|
132
|
+
if (typeof error !== "object" || error === null) return;
|
|
133
|
+
if ("errorStepName" in error) return;
|
|
134
|
+
if (!Object.isExtensible(error)) return;
|
|
135
|
+
try {
|
|
136
|
+
error.errorStepName = stepName;
|
|
137
|
+
} catch {
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
var getStepNameFromError = (error) => {
|
|
141
|
+
if (typeof error === "object" && error !== null) {
|
|
142
|
+
const stepName = error.errorStepName;
|
|
143
|
+
return typeof stepName === "string" ? stepName : void 0;
|
|
144
|
+
}
|
|
145
|
+
return void 0;
|
|
146
|
+
};
|
|
130
147
|
function getConstructorName(obj) {
|
|
131
148
|
if (obj === null || obj === void 0) {
|
|
132
149
|
return null;
|
|
@@ -216,6 +233,31 @@ var import_qstash4 = require("@upstash/qstash");
|
|
|
216
233
|
// src/utils.ts
|
|
217
234
|
var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
|
218
235
|
var NANOID_LENGTH = 21;
|
|
236
|
+
var RESOURCE_NAME_PATTERN = /^[a-zA-Z0-9\-_.]+$/;
|
|
237
|
+
function validateLabel(label) {
|
|
238
|
+
if (label === void 0) return;
|
|
239
|
+
const labels = Array.isArray(label) ? label : [label];
|
|
240
|
+
if (labels.length === 0) {
|
|
241
|
+
throw new WorkflowNonRetryableError("Invalid label: label array must not be empty.");
|
|
242
|
+
}
|
|
243
|
+
for (const value of labels) {
|
|
244
|
+
if (!RESOURCE_NAME_PATTERN.test(value)) {
|
|
245
|
+
throw new WorkflowNonRetryableError(
|
|
246
|
+
`Invalid label "${value}": must be alphanumeric, hyphen, underscore, or period.`
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
function serializeLabel(label) {
|
|
252
|
+
return Array.isArray(label) ? label.join(",") : label;
|
|
253
|
+
}
|
|
254
|
+
function validateFlowControl(flowControl) {
|
|
255
|
+
if (flowControl?.key !== void 0 && !RESOURCE_NAME_PATTERN.test(flowControl.key)) {
|
|
256
|
+
throw new WorkflowNonRetryableError(
|
|
257
|
+
`Invalid flow control key "${flowControl.key}": must be alphanumeric, hyphen, underscore, or period.`
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
219
261
|
function getRandomInt() {
|
|
220
262
|
return Math.floor(Math.random() * NANOID_CHARS.length);
|
|
221
263
|
}
|
|
@@ -751,8 +793,8 @@ var triggerFirstInvocation = async (params) => {
|
|
|
751
793
|
if (unknownSdk) {
|
|
752
794
|
headers[WORKFLOW_UNKOWN_SDK_TRIGGER_HEADER] = "true";
|
|
753
795
|
}
|
|
754
|
-
if (workflowContext.
|
|
755
|
-
headers[WORKFLOW_LABEL_HEADER] = workflowContext.
|
|
796
|
+
if (workflowContext.labels.length > 0) {
|
|
797
|
+
headers[WORKFLOW_LABEL_HEADER] = serializeLabel(workflowContext.labels);
|
|
756
798
|
}
|
|
757
799
|
const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
|
|
758
800
|
return {
|
|
@@ -1554,8 +1596,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1554
1596
|
});
|
|
1555
1597
|
triggerHeaders["Upstash-Workflow-Invoke"] = "true";
|
|
1556
1598
|
if (label) {
|
|
1557
|
-
|
|
1558
|
-
triggerHeaders[
|
|
1599
|
+
const labelHeader = serializeLabel(label);
|
|
1600
|
+
triggerHeaders[WORKFLOW_LABEL_HEADER] = labelHeader;
|
|
1601
|
+
triggerHeaders[`upstash-forward-${WORKFLOW_LABEL_HEADER}`] = labelHeader;
|
|
1559
1602
|
}
|
|
1560
1603
|
return { headers: triggerHeaders, contentType };
|
|
1561
1604
|
}
|
|
@@ -1898,7 +1941,13 @@ var submitSingleStep = async ({
|
|
|
1898
1941
|
await dispatchLifecycle("beforeExecution", {
|
|
1899
1942
|
stepName: lazyStep.stepName
|
|
1900
1943
|
});
|
|
1901
|
-
|
|
1944
|
+
let resultStep;
|
|
1945
|
+
try {
|
|
1946
|
+
resultStep = await lazyStep.getResultStep(concurrency, stepId);
|
|
1947
|
+
} catch (error) {
|
|
1948
|
+
attachStepNameToError(error, lazyStep.stepName);
|
|
1949
|
+
throw error;
|
|
1950
|
+
}
|
|
1902
1951
|
const { headers } = lazyStep.getHeaders({
|
|
1903
1952
|
context,
|
|
1904
1953
|
step: resultStep,
|
|
@@ -2121,9 +2170,11 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
2121
2170
|
if (isInstanceOf(error, WorkflowAbort) || isInstanceOf(error, import_qstash5.QstashError) && error.status === 400 || isInstanceOf(error, import_qstash5.QstashError) && error.status === 412) {
|
|
2122
2171
|
throw error;
|
|
2123
2172
|
}
|
|
2124
|
-
|
|
2173
|
+
const wrappedError = new WorkflowError(
|
|
2125
2174
|
`Error submitting steps to QStash in partial parallel step execution: ${error}`
|
|
2126
2175
|
);
|
|
2176
|
+
attachStepNameToError(wrappedError, parallelSteps[stepIndex].stepName);
|
|
2177
|
+
throw wrappedError;
|
|
2127
2178
|
}
|
|
2128
2179
|
break;
|
|
2129
2180
|
}
|
|
@@ -2696,9 +2747,10 @@ var WorkflowContext = class {
|
|
|
2696
2747
|
*/
|
|
2697
2748
|
env;
|
|
2698
2749
|
/**
|
|
2699
|
-
*
|
|
2750
|
+
* Labels attached to the workflow run.
|
|
2700
2751
|
*
|
|
2701
|
-
* Can be used to filter the workflow run logs.
|
|
2752
|
+
* Can be used to filter the workflow run logs. A run can have multiple
|
|
2753
|
+
* labels when triggered with `label: string[]`.
|
|
2702
2754
|
*
|
|
2703
2755
|
* Can be set by passing a `label` parameter when triggering the workflow
|
|
2704
2756
|
* with `client.trigger`:
|
|
@@ -2706,11 +2758,20 @@ var WorkflowContext = class {
|
|
|
2706
2758
|
* ```ts
|
|
2707
2759
|
* await client.trigger({
|
|
2708
2760
|
* url: "https://workflow-endpoint.com",
|
|
2709
|
-
* label: "
|
|
2761
|
+
* label: ["label-1", "label-2"]
|
|
2710
2762
|
* });
|
|
2711
2763
|
* ```
|
|
2712
2764
|
*/
|
|
2713
|
-
|
|
2765
|
+
labels;
|
|
2766
|
+
/**
|
|
2767
|
+
* Label of the workflow run.
|
|
2768
|
+
*
|
|
2769
|
+
* @deprecated Use `labels` instead. When a run has multiple labels, this
|
|
2770
|
+
* only returns the first one.
|
|
2771
|
+
*/
|
|
2772
|
+
get label() {
|
|
2773
|
+
return this.labels[0];
|
|
2774
|
+
}
|
|
2714
2775
|
/**
|
|
2715
2776
|
* Number of times QStash has retried delivering the current request.
|
|
2716
2777
|
*
|
|
@@ -2741,7 +2802,7 @@ var WorkflowContext = class {
|
|
|
2741
2802
|
this.headers = headers;
|
|
2742
2803
|
this.requestPayload = initialPayload;
|
|
2743
2804
|
this.env = env ?? {};
|
|
2744
|
-
this.
|
|
2805
|
+
this.labels = label === void 0 ? [] : Array.isArray(label) ? label : label ? label.split(",") : [];
|
|
2745
2806
|
this.retried = retried ?? 0;
|
|
2746
2807
|
const middlewareManagerInstance = middlewareManager ?? new MiddlewareManager([]);
|
|
2747
2808
|
middlewareManagerInstance.assignContext(this);
|
|
@@ -2822,8 +2883,10 @@ var WorkflowContext = class {
|
|
|
2822
2883
|
await this.addStep(new LazySleepUntilStep(this, stepName, time));
|
|
2823
2884
|
}
|
|
2824
2885
|
async call(stepName, settings) {
|
|
2886
|
+
validateFlowControl(settings.flowControl);
|
|
2825
2887
|
let callStep;
|
|
2826
2888
|
if ("workflow" in settings) {
|
|
2889
|
+
validateLabel(settings.label);
|
|
2827
2890
|
const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
|
|
2828
2891
|
const stringBody = typeof settings.body === "string" ? settings.body : settings.body === void 0 ? void 0 : JSON.stringify(settings.body);
|
|
2829
2892
|
callStep = new LazyCallStep({
|
|
@@ -2931,6 +2994,8 @@ var WorkflowContext = class {
|
|
|
2931
2994
|
);
|
|
2932
2995
|
}
|
|
2933
2996
|
async invoke(stepName, settings) {
|
|
2997
|
+
validateLabel(settings.label);
|
|
2998
|
+
validateFlowControl(settings.flowControl);
|
|
2934
2999
|
return await this.addStep(
|
|
2935
3000
|
new LazyInvokeStep(this, stepName, settings)
|
|
2936
3001
|
);
|
|
@@ -3016,7 +3081,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3016
3081
|
url: context.url,
|
|
3017
3082
|
initialPayload: context.requestPayload,
|
|
3018
3083
|
env: context.env,
|
|
3019
|
-
label: context.
|
|
3084
|
+
label: context.labels,
|
|
3020
3085
|
retried: context.retried
|
|
3021
3086
|
});
|
|
3022
3087
|
try {
|
|
@@ -3854,10 +3919,12 @@ var serveBase = (routeFunction, telemetry2, options, internalOptions) => {
|
|
|
3854
3919
|
await middlewareManager.dispatchDebug("onError", {
|
|
3855
3920
|
error: isInstanceOf(error, Error) ? error : new Error(formattedError.message)
|
|
3856
3921
|
});
|
|
3922
|
+
const stepName = getStepNameFromError(error)?.replace(/[\u0000-\u001F\u007F]+/g, " ").trim();
|
|
3857
3923
|
return new Response(JSON.stringify(formattedError), {
|
|
3858
3924
|
status: 500,
|
|
3859
3925
|
headers: {
|
|
3860
|
-
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3926
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
3927
|
+
...stepName ? { [WORKFLOW_ERROR_STEP_NAME_HEADER]: stepName } : {}
|
|
3861
3928
|
}
|
|
3862
3929
|
});
|
|
3863
3930
|
}
|
package/react-router.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as WorkflowServeOptions, c as RouteFunction, I as InvokableWorkflow } from './types-
|
|
1
|
+
import { d as WorkflowServeOptions, c as RouteFunction, I as InvokableWorkflow } from './types-CekOpKvz.mjs';
|
|
2
2
|
|
|
3
3
|
type OmitOptionsInServeMany<TOptions> = Omit<TOptions, "env" | "url" | "schema" | "initialPayloadParser">;
|
|
4
4
|
declare const serveManyBase: <THandler extends (...params: any[]) => any, TOptions extends OmitOptionsInServeMany<WorkflowServeOptions> = OmitOptionsInServeMany<WorkflowServeOptions>, TServeParams extends [routeFunction: RouteFunction<any, any>, options: TOptions] = [routeFunction: RouteFunction<any, any>, options: TOptions]>({ workflows, getUrl, serveMethod, options, }: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as WorkflowServeOptions, c as RouteFunction, I as InvokableWorkflow } from './types-
|
|
1
|
+
import { d as WorkflowServeOptions, c as RouteFunction, I as InvokableWorkflow } from './types-CekOpKvz.js';
|
|
2
2
|
|
|
3
3
|
type OmitOptionsInServeMany<TOptions> = Omit<TOptions, "env" | "url" | "schema" | "initialPayloadParser">;
|
|
4
4
|
declare const serveManyBase: <THandler extends (...params: any[]) => any, TOptions extends OmitOptionsInServeMany<WorkflowServeOptions> = OmitOptionsInServeMany<WorkflowServeOptions>, TServeParams extends [routeFunction: RouteFunction<any, any>, options: TOptions] = [routeFunction: RouteFunction<any, any>, options: TOptions]>({ workflows, getUrl, serveMethod, options, }: {
|
package/solidjs.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { APIEvent } from '@solidjs/start/server';
|
|
2
|
-
import { c as RouteFunction, d as WorkflowServeOptions } from './types-
|
|
2
|
+
import { c as RouteFunction, d as WorkflowServeOptions } from './types-CekOpKvz.mjs';
|
|
3
3
|
import '@upstash/qstash';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|
package/solidjs.d.ts
CHANGED