@upstash/workflow 1.2.1 → 1.3.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 +10 -0
- package/astro.d.mts +2 -2
- package/astro.d.ts +2 -2
- package/astro.js +80 -14
- package/astro.mjs +1 -1
- package/{chunk-THS5AX2D.mjs → chunk-CWCCIOXR.mjs} +83 -14
- package/cloudflare.d.mts +2 -2
- package/cloudflare.d.ts +2 -2
- package/cloudflare.js +80 -14
- package/cloudflare.mjs +1 -1
- package/express.d.mts +2 -2
- package/express.d.ts +2 -2
- package/express.js +80 -14
- package/express.mjs +1 -1
- package/h3.d.mts +2 -2
- package/h3.d.ts +2 -2
- package/h3.js +80 -14
- package/h3.mjs +1 -1
- package/hono.d.mts +2 -2
- package/hono.d.ts +2 -2
- package/hono.js +80 -14
- package/hono.mjs +1 -1
- package/index.d.mts +24 -5
- package/index.d.ts +24 -5
- package/index.js +83 -15
- package/index.mjs +8 -3
- package/nextjs.d.mts +2 -2
- package/nextjs.d.ts +2 -2
- package/nextjs.js +80 -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 +80 -14
- package/react-router.mjs +1 -1
- package/{serve-many-C6sa_DxN.d.mts → serve-many-CG3BFvO3.d.mts} +1 -1
- package/{serve-many-B-fe7bh7.d.ts → serve-many-iJF1IUXk.d.ts} +1 -1
- package/solidjs.d.mts +1 -1
- package/solidjs.d.ts +1 -1
- package/solidjs.js +80 -14
- package/solidjs.mjs +1 -1
- package/svelte.d.mts +2 -2
- package/svelte.d.ts +2 -2
- package/svelte.js +80 -14
- package/svelte.mjs +1 -1
- package/tanstack.d.mts +2 -2
- package/tanstack.d.ts +2 -2
- package/tanstack.js +80 -14
- package/tanstack.mjs +1 -1
- package/{types-B2S08hRU.d.ts → types-CekOpKvz.d.mts} +23 -7
- package/{types-B2S08hRU.d.mts → types-CekOpKvz.d.ts} +23 -7
package/README.md
CHANGED
|
@@ -108,6 +108,16 @@ const result = await client.getWaiters({
|
|
|
108
108
|
});
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
+
## Local Development
|
|
112
|
+
|
|
113
|
+
For local development, set `QSTASH_DEV=true` in your environment and the SDK will automatically download and run a local QStash dev server. No tokens or signing keys required: workflow endpoints will verify signatures against the dev server's keys automatically.
|
|
114
|
+
|
|
115
|
+
```bash .env
|
|
116
|
+
QSTASH_DEV=true
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
See [Local Development](https://upstash.com/docs/workflow/howto/local-development/development-server) for details.
|
|
120
|
+
|
|
111
121
|
## Telemetry
|
|
112
122
|
|
|
113
123
|
This sdk sends anonymous telemetry headers to help us improve your experience.
|
package/astro.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { APIContext, APIRoute } from 'astro';
|
|
2
|
-
import { u as WorkflowContext, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-
|
|
3
|
-
import { s as serveManyBase } from './serve-many-
|
|
2
|
+
import { u as WorkflowContext, 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/astro.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { APIContext, APIRoute } from 'astro';
|
|
2
|
-
import { u as WorkflowContext, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-
|
|
3
|
-
import { s as serveManyBase } from './serve-many-
|
|
2
|
+
import { u as WorkflowContext, 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/astro.js
CHANGED
|
@@ -192,6 +192,7 @@ var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
|
|
|
192
192
|
var WORKFLOW_FAILURE_CALLBACK_HEADER = "Upstash-Workflow-Failure-Callback";
|
|
193
193
|
var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
|
|
194
194
|
var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
|
|
195
|
+
var WORKFLOW_RETRIED_HEADER = "Upstash-Retried";
|
|
195
196
|
var WORKFLOW_LABEL_HEADER = "Upstash-Label";
|
|
196
197
|
var WORKFLOW_UNKOWN_SDK_VERSION_HEADER = "Upstash-Workflow-Unknown-Sdk";
|
|
197
198
|
var WORKFLOW_UNKOWN_SDK_TRIGGER_HEADER = "upstash-workflow-trigger-by-sdk";
|
|
@@ -200,7 +201,7 @@ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
|
200
201
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
201
202
|
var NO_CONCURRENCY = 1;
|
|
202
203
|
var DEFAULT_RETRIES = 3;
|
|
203
|
-
var VERSION = "v1.
|
|
204
|
+
var VERSION = "v1.2.1";
|
|
204
205
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
205
206
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
206
207
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
@@ -215,6 +216,31 @@ var import_qstash4 = require("@upstash/qstash");
|
|
|
215
216
|
// src/utils.ts
|
|
216
217
|
var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
|
217
218
|
var NANOID_LENGTH = 21;
|
|
219
|
+
var RESOURCE_NAME_PATTERN = /^[a-zA-Z0-9\-_.]+$/;
|
|
220
|
+
function validateLabel(label) {
|
|
221
|
+
if (label === void 0) return;
|
|
222
|
+
const labels = Array.isArray(label) ? label : [label];
|
|
223
|
+
if (labels.length === 0) {
|
|
224
|
+
throw new WorkflowNonRetryableError("Invalid label: label array must not be empty.");
|
|
225
|
+
}
|
|
226
|
+
for (const value of labels) {
|
|
227
|
+
if (!RESOURCE_NAME_PATTERN.test(value)) {
|
|
228
|
+
throw new WorkflowNonRetryableError(
|
|
229
|
+
`Invalid label "${value}": must be alphanumeric, hyphen, underscore, or period.`
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function serializeLabel(label) {
|
|
235
|
+
return Array.isArray(label) ? label.join(",") : label;
|
|
236
|
+
}
|
|
237
|
+
function validateFlowControl(flowControl) {
|
|
238
|
+
if (flowControl?.key !== void 0 && !RESOURCE_NAME_PATTERN.test(flowControl.key)) {
|
|
239
|
+
throw new WorkflowNonRetryableError(
|
|
240
|
+
`Invalid flow control key "${flowControl.key}": must be alphanumeric, hyphen, underscore, or period.`
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
218
244
|
function getRandomInt() {
|
|
219
245
|
return Math.floor(Math.random() * NANOID_CHARS.length);
|
|
220
246
|
}
|
|
@@ -750,8 +776,8 @@ var triggerFirstInvocation = async (params) => {
|
|
|
750
776
|
if (unknownSdk) {
|
|
751
777
|
headers[WORKFLOW_UNKOWN_SDK_TRIGGER_HEADER] = "true";
|
|
752
778
|
}
|
|
753
|
-
if (workflowContext.
|
|
754
|
-
headers[WORKFLOW_LABEL_HEADER] = workflowContext.
|
|
779
|
+
if (workflowContext.labels.length > 0) {
|
|
780
|
+
headers[WORKFLOW_LABEL_HEADER] = serializeLabel(workflowContext.labels);
|
|
755
781
|
}
|
|
756
782
|
const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
|
|
757
783
|
return {
|
|
@@ -855,6 +881,9 @@ var recreateUserHeaders = (headers) => {
|
|
|
855
881
|
}
|
|
856
882
|
return filteredHeaders;
|
|
857
883
|
};
|
|
884
|
+
var isThirdPartyCallResult = (request) => {
|
|
885
|
+
return request.headers.get("Upstash-Workflow-Callback") !== null;
|
|
886
|
+
};
|
|
858
887
|
var handleThirdPartyCallResult = async ({
|
|
859
888
|
request,
|
|
860
889
|
requestPayload,
|
|
@@ -864,7 +893,7 @@ var handleThirdPartyCallResult = async ({
|
|
|
864
893
|
middlewareManager
|
|
865
894
|
}) => {
|
|
866
895
|
try {
|
|
867
|
-
if (request
|
|
896
|
+
if (isThirdPartyCallResult(request)) {
|
|
868
897
|
let callbackPayload;
|
|
869
898
|
if (requestPayload) {
|
|
870
899
|
callbackPayload = requestPayload;
|
|
@@ -1550,8 +1579,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1550
1579
|
});
|
|
1551
1580
|
triggerHeaders["Upstash-Workflow-Invoke"] = "true";
|
|
1552
1581
|
if (label) {
|
|
1553
|
-
|
|
1554
|
-
triggerHeaders[
|
|
1582
|
+
const labelHeader = serializeLabel(label);
|
|
1583
|
+
triggerHeaders[WORKFLOW_LABEL_HEADER] = labelHeader;
|
|
1584
|
+
triggerHeaders[`upstash-forward-${WORKFLOW_LABEL_HEADER}`] = labelHeader;
|
|
1555
1585
|
}
|
|
1556
1586
|
return { headers: triggerHeaders, contentType };
|
|
1557
1587
|
}
|
|
@@ -2692,9 +2722,10 @@ var WorkflowContext = class {
|
|
|
2692
2722
|
*/
|
|
2693
2723
|
env;
|
|
2694
2724
|
/**
|
|
2695
|
-
*
|
|
2725
|
+
* Labels attached to the workflow run.
|
|
2696
2726
|
*
|
|
2697
|
-
* Can be used to filter the workflow run logs.
|
|
2727
|
+
* Can be used to filter the workflow run logs. A run can have multiple
|
|
2728
|
+
* labels when triggered with `label: string[]`.
|
|
2698
2729
|
*
|
|
2699
2730
|
* Can be set by passing a `label` parameter when triggering the workflow
|
|
2700
2731
|
* with `client.trigger`:
|
|
@@ -2702,11 +2733,27 @@ var WorkflowContext = class {
|
|
|
2702
2733
|
* ```ts
|
|
2703
2734
|
* await client.trigger({
|
|
2704
2735
|
* url: "https://workflow-endpoint.com",
|
|
2705
|
-
* label: "
|
|
2736
|
+
* label: ["label-1", "label-2"]
|
|
2706
2737
|
* });
|
|
2707
2738
|
* ```
|
|
2708
2739
|
*/
|
|
2709
|
-
|
|
2740
|
+
labels;
|
|
2741
|
+
/**
|
|
2742
|
+
* Label of the workflow run.
|
|
2743
|
+
*
|
|
2744
|
+
* @deprecated Use `labels` instead. When a run has multiple labels, this
|
|
2745
|
+
* only returns the first one.
|
|
2746
|
+
*/
|
|
2747
|
+
get label() {
|
|
2748
|
+
return this.labels[0];
|
|
2749
|
+
}
|
|
2750
|
+
/**
|
|
2751
|
+
* Number of times QStash has retried delivering the current request.
|
|
2752
|
+
*
|
|
2753
|
+
* Sourced from the `Upstash-Retried` header. `0` on the first delivery,
|
|
2754
|
+
* `1` on the first retry, `2` on the second, and so on.
|
|
2755
|
+
*/
|
|
2756
|
+
retried;
|
|
2710
2757
|
constructor({
|
|
2711
2758
|
qstashClient,
|
|
2712
2759
|
workflowRunId,
|
|
@@ -2719,6 +2766,7 @@ var WorkflowContext = class {
|
|
|
2719
2766
|
telemetry: telemetry2,
|
|
2720
2767
|
invokeCount,
|
|
2721
2768
|
label,
|
|
2769
|
+
retried,
|
|
2722
2770
|
middlewareManager
|
|
2723
2771
|
}) {
|
|
2724
2772
|
this.qstashClient = qstashClient;
|
|
@@ -2729,7 +2777,8 @@ var WorkflowContext = class {
|
|
|
2729
2777
|
this.headers = headers;
|
|
2730
2778
|
this.requestPayload = initialPayload;
|
|
2731
2779
|
this.env = env ?? {};
|
|
2732
|
-
this.
|
|
2780
|
+
this.labels = label === void 0 ? [] : Array.isArray(label) ? label : label ? label.split(",") : [];
|
|
2781
|
+
this.retried = retried ?? 0;
|
|
2733
2782
|
const middlewareManagerInstance = middlewareManager ?? new MiddlewareManager([]);
|
|
2734
2783
|
middlewareManagerInstance.assignContext(this);
|
|
2735
2784
|
this.executor = new AutoExecutor(
|
|
@@ -2809,8 +2858,10 @@ var WorkflowContext = class {
|
|
|
2809
2858
|
await this.addStep(new LazySleepUntilStep(this, stepName, time));
|
|
2810
2859
|
}
|
|
2811
2860
|
async call(stepName, settings) {
|
|
2861
|
+
validateFlowControl(settings.flowControl);
|
|
2812
2862
|
let callStep;
|
|
2813
2863
|
if ("workflow" in settings) {
|
|
2864
|
+
validateLabel(settings.label);
|
|
2814
2865
|
const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
|
|
2815
2866
|
const stringBody = typeof settings.body === "string" ? settings.body : settings.body === void 0 ? void 0 : JSON.stringify(settings.body);
|
|
2816
2867
|
callStep = new LazyCallStep({
|
|
@@ -2918,6 +2969,8 @@ var WorkflowContext = class {
|
|
|
2918
2969
|
);
|
|
2919
2970
|
}
|
|
2920
2971
|
async invoke(stepName, settings) {
|
|
2972
|
+
validateLabel(settings.label);
|
|
2973
|
+
validateFlowControl(settings.flowControl);
|
|
2921
2974
|
return await this.addStep(
|
|
2922
2975
|
new LazyInvokeStep(this, stepName, settings)
|
|
2923
2976
|
);
|
|
@@ -2993,7 +3046,8 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
2993
3046
|
const disabledContext = new _DisabledWorkflowContext({
|
|
2994
3047
|
qstashClient: new import_qstash10.Client({
|
|
2995
3048
|
baseUrl: "disabled-client",
|
|
2996
|
-
token: "disabled-client"
|
|
3049
|
+
token: "disabled-client",
|
|
3050
|
+
devMode: false
|
|
2997
3051
|
}),
|
|
2998
3052
|
workflowRunId: context.workflowRunId,
|
|
2999
3053
|
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
@@ -3002,7 +3056,8 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3002
3056
|
url: context.url,
|
|
3003
3057
|
initialPayload: context.requestPayload,
|
|
3004
3058
|
env: context.env,
|
|
3005
|
-
label: context.
|
|
3059
|
+
label: context.labels,
|
|
3060
|
+
retried: context.retried
|
|
3006
3061
|
});
|
|
3007
3062
|
try {
|
|
3008
3063
|
await routeFunction(disabledContext);
|
|
@@ -3218,6 +3273,7 @@ var handleFailure = async ({
|
|
|
3218
3273
|
errorMessage = `Couldn't parse 'failResponse' in 'failureFunction', received: '${decodedBody}'`;
|
|
3219
3274
|
}
|
|
3220
3275
|
const userHeaders = recreateUserHeaders(request.headers);
|
|
3276
|
+
const retried = Number(request.headers.get(WORKFLOW_RETRIED_HEADER) ?? "0");
|
|
3221
3277
|
const workflowContext = new WorkflowContext({
|
|
3222
3278
|
qstashClient,
|
|
3223
3279
|
workflowRunId,
|
|
@@ -3229,6 +3285,7 @@ var handleFailure = async ({
|
|
|
3229
3285
|
telemetry: void 0,
|
|
3230
3286
|
// not going to make requests in authentication check
|
|
3231
3287
|
label: userHeaders.get(WORKFLOW_LABEL_HEADER) ?? void 0,
|
|
3288
|
+
retried,
|
|
3232
3289
|
workflowRunCreatedAt: workflowCreatedAt,
|
|
3233
3290
|
middlewareManager: void 0
|
|
3234
3291
|
});
|
|
@@ -3388,6 +3445,9 @@ var getReceiver = (environment, receiverConfig, region) => {
|
|
|
3388
3445
|
if (receiverConfig === "set-to-undefined") {
|
|
3389
3446
|
return void 0;
|
|
3390
3447
|
}
|
|
3448
|
+
if (isQStashDevModeEnabled(environment)) {
|
|
3449
|
+
return new import_qstash11.Receiver({ devMode: true });
|
|
3450
|
+
}
|
|
3391
3451
|
const receiverEnv = readReceiverEnvironmentVariables(environment, region);
|
|
3392
3452
|
return receiverEnv.QSTASH_CURRENT_SIGNING_KEY && receiverEnv.QSTASH_NEXT_SIGNING_KEY ? new import_qstash11.Receiver({
|
|
3393
3453
|
currentSigningKey: receiverEnv.QSTASH_CURRENT_SIGNING_KEY,
|
|
@@ -3397,6 +3457,10 @@ var getReceiver = (environment, receiverConfig, region) => {
|
|
|
3397
3457
|
return receiverConfig;
|
|
3398
3458
|
}
|
|
3399
3459
|
};
|
|
3460
|
+
var isQStashDevModeEnabled = (env) => {
|
|
3461
|
+
const value = env.QSTASH_DEV;
|
|
3462
|
+
return value === "true" || value === "1";
|
|
3463
|
+
};
|
|
3400
3464
|
var getQStashHandlerOptions = (...params) => {
|
|
3401
3465
|
const handlers = getQStashHandlers(...params);
|
|
3402
3466
|
return {
|
|
@@ -3706,12 +3770,13 @@ var serveBase = (routeFunction, telemetry2, options, internalOptions) => {
|
|
|
3706
3770
|
);
|
|
3707
3771
|
}
|
|
3708
3772
|
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
3773
|
+
const retried = Number(request.headers.get(WORKFLOW_RETRIED_HEADER) ?? "0");
|
|
3709
3774
|
const label = request.headers.get(WORKFLOW_LABEL_HEADER) ?? void 0;
|
|
3710
3775
|
const workflowRunCreatedAt = request.headers.get(WORKFLOW_CREATED_AT_HEADER);
|
|
3711
3776
|
const workflowContext = new WorkflowContext({
|
|
3712
3777
|
qstashClient: regionalClient,
|
|
3713
3778
|
workflowRunId,
|
|
3714
|
-
initialPayload: initialPayloadParser(rawInitialPayload),
|
|
3779
|
+
initialPayload: isThirdPartyCallResult(request) ? JSON.parse(rawInitialPayload) : initialPayloadParser(rawInitialPayload),
|
|
3715
3780
|
headers: recreateUserHeaders(request.headers),
|
|
3716
3781
|
steps,
|
|
3717
3782
|
url: workflowUrl,
|
|
@@ -3719,6 +3784,7 @@ var serveBase = (routeFunction, telemetry2, options, internalOptions) => {
|
|
|
3719
3784
|
telemetry: telemetry2,
|
|
3720
3785
|
invokeCount,
|
|
3721
3786
|
label,
|
|
3787
|
+
retried,
|
|
3722
3788
|
workflowRunCreatedAt: Number(workflowRunCreatedAt),
|
|
3723
3789
|
middlewareManager
|
|
3724
3790
|
});
|
package/astro.mjs
CHANGED
|
@@ -103,6 +103,7 @@ var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
|
|
|
103
103
|
var WORKFLOW_FAILURE_CALLBACK_HEADER = "Upstash-Workflow-Failure-Callback";
|
|
104
104
|
var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
|
|
105
105
|
var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
|
|
106
|
+
var WORKFLOW_RETRIED_HEADER = "Upstash-Retried";
|
|
106
107
|
var WORKFLOW_LABEL_HEADER = "Upstash-Label";
|
|
107
108
|
var WORKFLOW_UNKOWN_SDK_VERSION_HEADER = "Upstash-Workflow-Unknown-Sdk";
|
|
108
109
|
var WORKFLOW_UNKOWN_SDK_TRIGGER_HEADER = "upstash-workflow-trigger-by-sdk";
|
|
@@ -111,7 +112,7 @@ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
|
111
112
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
112
113
|
var NO_CONCURRENCY = 1;
|
|
113
114
|
var DEFAULT_RETRIES = 3;
|
|
114
|
-
var VERSION = "v1.
|
|
115
|
+
var VERSION = "v1.2.1";
|
|
115
116
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
116
117
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
117
118
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
@@ -341,6 +342,31 @@ function buildBulkActionQueryParameters(request, options) {
|
|
|
341
342
|
// src/utils.ts
|
|
342
343
|
var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
|
343
344
|
var NANOID_LENGTH = 21;
|
|
345
|
+
var RESOURCE_NAME_PATTERN = /^[a-zA-Z0-9\-_.]+$/;
|
|
346
|
+
function validateLabel(label) {
|
|
347
|
+
if (label === void 0) return;
|
|
348
|
+
const labels = Array.isArray(label) ? label : [label];
|
|
349
|
+
if (labels.length === 0) {
|
|
350
|
+
throw new WorkflowNonRetryableError("Invalid label: label array must not be empty.");
|
|
351
|
+
}
|
|
352
|
+
for (const value of labels) {
|
|
353
|
+
if (!RESOURCE_NAME_PATTERN.test(value)) {
|
|
354
|
+
throw new WorkflowNonRetryableError(
|
|
355
|
+
`Invalid label "${value}": must be alphanumeric, hyphen, underscore, or period.`
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function serializeLabel(label) {
|
|
361
|
+
return Array.isArray(label) ? label.join(",") : label;
|
|
362
|
+
}
|
|
363
|
+
function validateFlowControl(flowControl) {
|
|
364
|
+
if (flowControl?.key !== void 0 && !RESOURCE_NAME_PATTERN.test(flowControl.key)) {
|
|
365
|
+
throw new WorkflowNonRetryableError(
|
|
366
|
+
`Invalid flow control key "${flowControl.key}": must be alphanumeric, hyphen, underscore, or period.`
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
344
370
|
function getRandomInt() {
|
|
345
371
|
return Math.floor(Math.random() * NANOID_CHARS.length);
|
|
346
372
|
}
|
|
@@ -862,8 +888,8 @@ var triggerFirstInvocation = async (params) => {
|
|
|
862
888
|
if (unknownSdk) {
|
|
863
889
|
headers[WORKFLOW_UNKOWN_SDK_TRIGGER_HEADER] = "true";
|
|
864
890
|
}
|
|
865
|
-
if (workflowContext.
|
|
866
|
-
headers[WORKFLOW_LABEL_HEADER] = workflowContext.
|
|
891
|
+
if (workflowContext.labels.length > 0) {
|
|
892
|
+
headers[WORKFLOW_LABEL_HEADER] = serializeLabel(workflowContext.labels);
|
|
867
893
|
}
|
|
868
894
|
const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
|
|
869
895
|
return {
|
|
@@ -967,6 +993,9 @@ var recreateUserHeaders = (headers) => {
|
|
|
967
993
|
}
|
|
968
994
|
return filteredHeaders;
|
|
969
995
|
};
|
|
996
|
+
var isThirdPartyCallResult = (request) => {
|
|
997
|
+
return request.headers.get("Upstash-Workflow-Callback") !== null;
|
|
998
|
+
};
|
|
970
999
|
var handleThirdPartyCallResult = async ({
|
|
971
1000
|
request,
|
|
972
1001
|
requestPayload,
|
|
@@ -976,7 +1005,7 @@ var handleThirdPartyCallResult = async ({
|
|
|
976
1005
|
middlewareManager
|
|
977
1006
|
}) => {
|
|
978
1007
|
try {
|
|
979
|
-
if (request
|
|
1008
|
+
if (isThirdPartyCallResult(request)) {
|
|
980
1009
|
let callbackPayload;
|
|
981
1010
|
if (requestPayload) {
|
|
982
1011
|
callbackPayload = requestPayload;
|
|
@@ -1662,8 +1691,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1662
1691
|
});
|
|
1663
1692
|
triggerHeaders["Upstash-Workflow-Invoke"] = "true";
|
|
1664
1693
|
if (label) {
|
|
1665
|
-
|
|
1666
|
-
triggerHeaders[
|
|
1694
|
+
const labelHeader = serializeLabel(label);
|
|
1695
|
+
triggerHeaders[WORKFLOW_LABEL_HEADER] = labelHeader;
|
|
1696
|
+
triggerHeaders[`upstash-forward-${WORKFLOW_LABEL_HEADER}`] = labelHeader;
|
|
1667
1697
|
}
|
|
1668
1698
|
return { headers: triggerHeaders, contentType };
|
|
1669
1699
|
}
|
|
@@ -2729,9 +2759,10 @@ var WorkflowContext = class {
|
|
|
2729
2759
|
*/
|
|
2730
2760
|
env;
|
|
2731
2761
|
/**
|
|
2732
|
-
*
|
|
2762
|
+
* Labels attached to the workflow run.
|
|
2733
2763
|
*
|
|
2734
|
-
* Can be used to filter the workflow run logs.
|
|
2764
|
+
* Can be used to filter the workflow run logs. A run can have multiple
|
|
2765
|
+
* labels when triggered with `label: string[]`.
|
|
2735
2766
|
*
|
|
2736
2767
|
* Can be set by passing a `label` parameter when triggering the workflow
|
|
2737
2768
|
* with `client.trigger`:
|
|
@@ -2739,11 +2770,27 @@ var WorkflowContext = class {
|
|
|
2739
2770
|
* ```ts
|
|
2740
2771
|
* await client.trigger({
|
|
2741
2772
|
* url: "https://workflow-endpoint.com",
|
|
2742
|
-
* label: "
|
|
2773
|
+
* label: ["label-1", "label-2"]
|
|
2743
2774
|
* });
|
|
2744
2775
|
* ```
|
|
2745
2776
|
*/
|
|
2746
|
-
|
|
2777
|
+
labels;
|
|
2778
|
+
/**
|
|
2779
|
+
* Label of the workflow run.
|
|
2780
|
+
*
|
|
2781
|
+
* @deprecated Use `labels` instead. When a run has multiple labels, this
|
|
2782
|
+
* only returns the first one.
|
|
2783
|
+
*/
|
|
2784
|
+
get label() {
|
|
2785
|
+
return this.labels[0];
|
|
2786
|
+
}
|
|
2787
|
+
/**
|
|
2788
|
+
* Number of times QStash has retried delivering the current request.
|
|
2789
|
+
*
|
|
2790
|
+
* Sourced from the `Upstash-Retried` header. `0` on the first delivery,
|
|
2791
|
+
* `1` on the first retry, `2` on the second, and so on.
|
|
2792
|
+
*/
|
|
2793
|
+
retried;
|
|
2747
2794
|
constructor({
|
|
2748
2795
|
qstashClient,
|
|
2749
2796
|
workflowRunId,
|
|
@@ -2756,6 +2803,7 @@ var WorkflowContext = class {
|
|
|
2756
2803
|
telemetry,
|
|
2757
2804
|
invokeCount,
|
|
2758
2805
|
label,
|
|
2806
|
+
retried,
|
|
2759
2807
|
middlewareManager
|
|
2760
2808
|
}) {
|
|
2761
2809
|
this.qstashClient = qstashClient;
|
|
@@ -2766,7 +2814,8 @@ var WorkflowContext = class {
|
|
|
2766
2814
|
this.headers = headers;
|
|
2767
2815
|
this.requestPayload = initialPayload;
|
|
2768
2816
|
this.env = env ?? {};
|
|
2769
|
-
this.
|
|
2817
|
+
this.labels = label === void 0 ? [] : Array.isArray(label) ? label : label ? label.split(",") : [];
|
|
2818
|
+
this.retried = retried ?? 0;
|
|
2770
2819
|
const middlewareManagerInstance = middlewareManager ?? new MiddlewareManager([]);
|
|
2771
2820
|
middlewareManagerInstance.assignContext(this);
|
|
2772
2821
|
this.executor = new AutoExecutor(
|
|
@@ -2846,8 +2895,10 @@ var WorkflowContext = class {
|
|
|
2846
2895
|
await this.addStep(new LazySleepUntilStep(this, stepName, time));
|
|
2847
2896
|
}
|
|
2848
2897
|
async call(stepName, settings) {
|
|
2898
|
+
validateFlowControl(settings.flowControl);
|
|
2849
2899
|
let callStep;
|
|
2850
2900
|
if ("workflow" in settings) {
|
|
2901
|
+
validateLabel(settings.label);
|
|
2851
2902
|
const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
|
|
2852
2903
|
const stringBody = typeof settings.body === "string" ? settings.body : settings.body === void 0 ? void 0 : JSON.stringify(settings.body);
|
|
2853
2904
|
callStep = new LazyCallStep({
|
|
@@ -2955,6 +3006,8 @@ var WorkflowContext = class {
|
|
|
2955
3006
|
);
|
|
2956
3007
|
}
|
|
2957
3008
|
async invoke(stepName, settings) {
|
|
3009
|
+
validateLabel(settings.label);
|
|
3010
|
+
validateFlowControl(settings.flowControl);
|
|
2958
3011
|
return await this.addStep(
|
|
2959
3012
|
new LazyInvokeStep(this, stepName, settings)
|
|
2960
3013
|
);
|
|
@@ -3104,7 +3157,8 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3104
3157
|
const disabledContext = new _DisabledWorkflowContext({
|
|
3105
3158
|
qstashClient: new Client2({
|
|
3106
3159
|
baseUrl: "disabled-client",
|
|
3107
|
-
token: "disabled-client"
|
|
3160
|
+
token: "disabled-client",
|
|
3161
|
+
devMode: false
|
|
3108
3162
|
}),
|
|
3109
3163
|
workflowRunId: context.workflowRunId,
|
|
3110
3164
|
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
@@ -3113,7 +3167,8 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3113
3167
|
url: context.url,
|
|
3114
3168
|
initialPayload: context.requestPayload,
|
|
3115
3169
|
env: context.env,
|
|
3116
|
-
label: context.
|
|
3170
|
+
label: context.labels,
|
|
3171
|
+
retried: context.retried
|
|
3117
3172
|
});
|
|
3118
3173
|
try {
|
|
3119
3174
|
await routeFunction(disabledContext);
|
|
@@ -3329,6 +3384,7 @@ var handleFailure = async ({
|
|
|
3329
3384
|
errorMessage = `Couldn't parse 'failResponse' in 'failureFunction', received: '${decodedBody}'`;
|
|
3330
3385
|
}
|
|
3331
3386
|
const userHeaders = recreateUserHeaders(request.headers);
|
|
3387
|
+
const retried = Number(request.headers.get(WORKFLOW_RETRIED_HEADER) ?? "0");
|
|
3332
3388
|
const workflowContext = new WorkflowContext({
|
|
3333
3389
|
qstashClient,
|
|
3334
3390
|
workflowRunId,
|
|
@@ -3340,6 +3396,7 @@ var handleFailure = async ({
|
|
|
3340
3396
|
telemetry: void 0,
|
|
3341
3397
|
// not going to make requests in authentication check
|
|
3342
3398
|
label: userHeaders.get(WORKFLOW_LABEL_HEADER) ?? void 0,
|
|
3399
|
+
retried,
|
|
3343
3400
|
workflowRunCreatedAt: workflowCreatedAt,
|
|
3344
3401
|
middlewareManager: void 0
|
|
3345
3402
|
});
|
|
@@ -3499,6 +3556,9 @@ var getReceiver = (environment, receiverConfig, region) => {
|
|
|
3499
3556
|
if (receiverConfig === "set-to-undefined") {
|
|
3500
3557
|
return void 0;
|
|
3501
3558
|
}
|
|
3559
|
+
if (isQStashDevModeEnabled(environment)) {
|
|
3560
|
+
return new Receiver({ devMode: true });
|
|
3561
|
+
}
|
|
3502
3562
|
const receiverEnv = readReceiverEnvironmentVariables(environment, region);
|
|
3503
3563
|
return receiverEnv.QSTASH_CURRENT_SIGNING_KEY && receiverEnv.QSTASH_NEXT_SIGNING_KEY ? new Receiver({
|
|
3504
3564
|
currentSigningKey: receiverEnv.QSTASH_CURRENT_SIGNING_KEY,
|
|
@@ -3508,6 +3568,10 @@ var getReceiver = (environment, receiverConfig, region) => {
|
|
|
3508
3568
|
return receiverConfig;
|
|
3509
3569
|
}
|
|
3510
3570
|
};
|
|
3571
|
+
var isQStashDevModeEnabled = (env) => {
|
|
3572
|
+
const value = env.QSTASH_DEV;
|
|
3573
|
+
return value === "true" || value === "1";
|
|
3574
|
+
};
|
|
3511
3575
|
var getQStashHandlerOptions = (...params) => {
|
|
3512
3576
|
const handlers = getQStashHandlers(...params);
|
|
3513
3577
|
return {
|
|
@@ -3743,12 +3807,13 @@ var serveBase = (routeFunction, telemetry, options, internalOptions) => {
|
|
|
3743
3807
|
);
|
|
3744
3808
|
}
|
|
3745
3809
|
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
3810
|
+
const retried = Number(request.headers.get(WORKFLOW_RETRIED_HEADER) ?? "0");
|
|
3746
3811
|
const label = request.headers.get(WORKFLOW_LABEL_HEADER) ?? void 0;
|
|
3747
3812
|
const workflowRunCreatedAt = request.headers.get(WORKFLOW_CREATED_AT_HEADER);
|
|
3748
3813
|
const workflowContext = new WorkflowContext({
|
|
3749
3814
|
qstashClient: regionalClient,
|
|
3750
3815
|
workflowRunId,
|
|
3751
|
-
initialPayload: initialPayloadParser(rawInitialPayload),
|
|
3816
|
+
initialPayload: isThirdPartyCallResult(request) ? JSON.parse(rawInitialPayload) : initialPayloadParser(rawInitialPayload),
|
|
3752
3817
|
headers: recreateUserHeaders(request.headers),
|
|
3753
3818
|
steps,
|
|
3754
3819
|
url: workflowUrl,
|
|
@@ -3756,6 +3821,7 @@ var serveBase = (routeFunction, telemetry, options, internalOptions) => {
|
|
|
3756
3821
|
telemetry,
|
|
3757
3822
|
invokeCount,
|
|
3758
3823
|
label,
|
|
3824
|
+
retried,
|
|
3759
3825
|
workflowRunCreatedAt: Number(workflowRunCreatedAt),
|
|
3760
3826
|
middlewareManager
|
|
3761
3827
|
});
|
|
@@ -3897,6 +3963,9 @@ export {
|
|
|
3897
3963
|
buildBulkActionQueryParameters,
|
|
3898
3964
|
WORKFLOW_LABEL_HEADER,
|
|
3899
3965
|
SDK_TELEMETRY,
|
|
3966
|
+
validateLabel,
|
|
3967
|
+
serializeLabel,
|
|
3968
|
+
validateFlowControl,
|
|
3900
3969
|
getWorkflowRunId,
|
|
3901
3970
|
StepTypes,
|
|
3902
3971
|
triggerFirstInvocation,
|
package/cloudflare.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/cloudflare.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
|
|