@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/h3.js
CHANGED
|
@@ -501,6 +501,7 @@ var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
|
|
|
501
501
|
var WORKFLOW_FAILURE_CALLBACK_HEADER = "Upstash-Workflow-Failure-Callback";
|
|
502
502
|
var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
|
|
503
503
|
var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
|
|
504
|
+
var WORKFLOW_RETRIED_HEADER = "Upstash-Retried";
|
|
504
505
|
var WORKFLOW_LABEL_HEADER = "Upstash-Label";
|
|
505
506
|
var WORKFLOW_UNKOWN_SDK_VERSION_HEADER = "Upstash-Workflow-Unknown-Sdk";
|
|
506
507
|
var WORKFLOW_UNKOWN_SDK_TRIGGER_HEADER = "upstash-workflow-trigger-by-sdk";
|
|
@@ -509,7 +510,7 @@ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
|
509
510
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
510
511
|
var NO_CONCURRENCY = 1;
|
|
511
512
|
var DEFAULT_RETRIES = 3;
|
|
512
|
-
var VERSION = "v1.
|
|
513
|
+
var VERSION = "v1.2.1";
|
|
513
514
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
514
515
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
515
516
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
@@ -524,6 +525,31 @@ var import_qstash4 = require("@upstash/qstash");
|
|
|
524
525
|
// src/utils.ts
|
|
525
526
|
var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
|
526
527
|
var NANOID_LENGTH = 21;
|
|
528
|
+
var RESOURCE_NAME_PATTERN = /^[a-zA-Z0-9\-_.]+$/;
|
|
529
|
+
function validateLabel(label) {
|
|
530
|
+
if (label === void 0) return;
|
|
531
|
+
const labels = Array.isArray(label) ? label : [label];
|
|
532
|
+
if (labels.length === 0) {
|
|
533
|
+
throw new WorkflowNonRetryableError("Invalid label: label array must not be empty.");
|
|
534
|
+
}
|
|
535
|
+
for (const value of labels) {
|
|
536
|
+
if (!RESOURCE_NAME_PATTERN.test(value)) {
|
|
537
|
+
throw new WorkflowNonRetryableError(
|
|
538
|
+
`Invalid label "${value}": must be alphanumeric, hyphen, underscore, or period.`
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
function serializeLabel(label) {
|
|
544
|
+
return Array.isArray(label) ? label.join(",") : label;
|
|
545
|
+
}
|
|
546
|
+
function validateFlowControl(flowControl) {
|
|
547
|
+
if (flowControl?.key !== void 0 && !RESOURCE_NAME_PATTERN.test(flowControl.key)) {
|
|
548
|
+
throw new WorkflowNonRetryableError(
|
|
549
|
+
`Invalid flow control key "${flowControl.key}": must be alphanumeric, hyphen, underscore, or period.`
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
527
553
|
function getRandomInt() {
|
|
528
554
|
return Math.floor(Math.random() * NANOID_CHARS.length);
|
|
529
555
|
}
|
|
@@ -1059,8 +1085,8 @@ var triggerFirstInvocation = async (params) => {
|
|
|
1059
1085
|
if (unknownSdk) {
|
|
1060
1086
|
headers[WORKFLOW_UNKOWN_SDK_TRIGGER_HEADER] = "true";
|
|
1061
1087
|
}
|
|
1062
|
-
if (workflowContext.
|
|
1063
|
-
headers[WORKFLOW_LABEL_HEADER] = workflowContext.
|
|
1088
|
+
if (workflowContext.labels.length > 0) {
|
|
1089
|
+
headers[WORKFLOW_LABEL_HEADER] = serializeLabel(workflowContext.labels);
|
|
1064
1090
|
}
|
|
1065
1091
|
const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
|
|
1066
1092
|
return {
|
|
@@ -1164,6 +1190,9 @@ var recreateUserHeaders = (headers) => {
|
|
|
1164
1190
|
}
|
|
1165
1191
|
return filteredHeaders;
|
|
1166
1192
|
};
|
|
1193
|
+
var isThirdPartyCallResult = (request) => {
|
|
1194
|
+
return request.headers.get("Upstash-Workflow-Callback") !== null;
|
|
1195
|
+
};
|
|
1167
1196
|
var handleThirdPartyCallResult = async ({
|
|
1168
1197
|
request,
|
|
1169
1198
|
requestPayload,
|
|
@@ -1173,7 +1202,7 @@ var handleThirdPartyCallResult = async ({
|
|
|
1173
1202
|
middlewareManager
|
|
1174
1203
|
}) => {
|
|
1175
1204
|
try {
|
|
1176
|
-
if (request
|
|
1205
|
+
if (isThirdPartyCallResult(request)) {
|
|
1177
1206
|
let callbackPayload;
|
|
1178
1207
|
if (requestPayload) {
|
|
1179
1208
|
callbackPayload = requestPayload;
|
|
@@ -1859,8 +1888,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1859
1888
|
});
|
|
1860
1889
|
triggerHeaders["Upstash-Workflow-Invoke"] = "true";
|
|
1861
1890
|
if (label) {
|
|
1862
|
-
|
|
1863
|
-
triggerHeaders[
|
|
1891
|
+
const labelHeader = serializeLabel(label);
|
|
1892
|
+
triggerHeaders[WORKFLOW_LABEL_HEADER] = labelHeader;
|
|
1893
|
+
triggerHeaders[`upstash-forward-${WORKFLOW_LABEL_HEADER}`] = labelHeader;
|
|
1864
1894
|
}
|
|
1865
1895
|
return { headers: triggerHeaders, contentType };
|
|
1866
1896
|
}
|
|
@@ -3001,9 +3031,10 @@ var WorkflowContext = class {
|
|
|
3001
3031
|
*/
|
|
3002
3032
|
env;
|
|
3003
3033
|
/**
|
|
3004
|
-
*
|
|
3034
|
+
* Labels attached to the workflow run.
|
|
3005
3035
|
*
|
|
3006
|
-
* Can be used to filter the workflow run logs.
|
|
3036
|
+
* Can be used to filter the workflow run logs. A run can have multiple
|
|
3037
|
+
* labels when triggered with `label: string[]`.
|
|
3007
3038
|
*
|
|
3008
3039
|
* Can be set by passing a `label` parameter when triggering the workflow
|
|
3009
3040
|
* with `client.trigger`:
|
|
@@ -3011,11 +3042,27 @@ var WorkflowContext = class {
|
|
|
3011
3042
|
* ```ts
|
|
3012
3043
|
* await client.trigger({
|
|
3013
3044
|
* url: "https://workflow-endpoint.com",
|
|
3014
|
-
* label: "
|
|
3045
|
+
* label: ["label-1", "label-2"]
|
|
3015
3046
|
* });
|
|
3016
3047
|
* ```
|
|
3017
3048
|
*/
|
|
3018
|
-
|
|
3049
|
+
labels;
|
|
3050
|
+
/**
|
|
3051
|
+
* Label of the workflow run.
|
|
3052
|
+
*
|
|
3053
|
+
* @deprecated Use `labels` instead. When a run has multiple labels, this
|
|
3054
|
+
* only returns the first one.
|
|
3055
|
+
*/
|
|
3056
|
+
get label() {
|
|
3057
|
+
return this.labels[0];
|
|
3058
|
+
}
|
|
3059
|
+
/**
|
|
3060
|
+
* Number of times QStash has retried delivering the current request.
|
|
3061
|
+
*
|
|
3062
|
+
* Sourced from the `Upstash-Retried` header. `0` on the first delivery,
|
|
3063
|
+
* `1` on the first retry, `2` on the second, and so on.
|
|
3064
|
+
*/
|
|
3065
|
+
retried;
|
|
3019
3066
|
constructor({
|
|
3020
3067
|
qstashClient,
|
|
3021
3068
|
workflowRunId,
|
|
@@ -3028,6 +3075,7 @@ var WorkflowContext = class {
|
|
|
3028
3075
|
telemetry: telemetry2,
|
|
3029
3076
|
invokeCount,
|
|
3030
3077
|
label,
|
|
3078
|
+
retried,
|
|
3031
3079
|
middlewareManager
|
|
3032
3080
|
}) {
|
|
3033
3081
|
this.qstashClient = qstashClient;
|
|
@@ -3038,7 +3086,8 @@ var WorkflowContext = class {
|
|
|
3038
3086
|
this.headers = headers;
|
|
3039
3087
|
this.requestPayload = initialPayload;
|
|
3040
3088
|
this.env = env ?? {};
|
|
3041
|
-
this.
|
|
3089
|
+
this.labels = label === void 0 ? [] : Array.isArray(label) ? label : label ? label.split(",") : [];
|
|
3090
|
+
this.retried = retried ?? 0;
|
|
3042
3091
|
const middlewareManagerInstance = middlewareManager ?? new MiddlewareManager([]);
|
|
3043
3092
|
middlewareManagerInstance.assignContext(this);
|
|
3044
3093
|
this.executor = new AutoExecutor(
|
|
@@ -3118,8 +3167,10 @@ var WorkflowContext = class {
|
|
|
3118
3167
|
await this.addStep(new LazySleepUntilStep(this, stepName, time));
|
|
3119
3168
|
}
|
|
3120
3169
|
async call(stepName, settings) {
|
|
3170
|
+
validateFlowControl(settings.flowControl);
|
|
3121
3171
|
let callStep;
|
|
3122
3172
|
if ("workflow" in settings) {
|
|
3173
|
+
validateLabel(settings.label);
|
|
3123
3174
|
const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
|
|
3124
3175
|
const stringBody = typeof settings.body === "string" ? settings.body : settings.body === void 0 ? void 0 : JSON.stringify(settings.body);
|
|
3125
3176
|
callStep = new LazyCallStep({
|
|
@@ -3227,6 +3278,8 @@ var WorkflowContext = class {
|
|
|
3227
3278
|
);
|
|
3228
3279
|
}
|
|
3229
3280
|
async invoke(stepName, settings) {
|
|
3281
|
+
validateLabel(settings.label);
|
|
3282
|
+
validateFlowControl(settings.flowControl);
|
|
3230
3283
|
return await this.addStep(
|
|
3231
3284
|
new LazyInvokeStep(this, stepName, settings)
|
|
3232
3285
|
);
|
|
@@ -3302,7 +3355,8 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3302
3355
|
const disabledContext = new _DisabledWorkflowContext({
|
|
3303
3356
|
qstashClient: new import_qstash10.Client({
|
|
3304
3357
|
baseUrl: "disabled-client",
|
|
3305
|
-
token: "disabled-client"
|
|
3358
|
+
token: "disabled-client",
|
|
3359
|
+
devMode: false
|
|
3306
3360
|
}),
|
|
3307
3361
|
workflowRunId: context.workflowRunId,
|
|
3308
3362
|
workflowRunCreatedAt: context.workflowRunCreatedAt,
|
|
@@ -3311,7 +3365,8 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3311
3365
|
url: context.url,
|
|
3312
3366
|
initialPayload: context.requestPayload,
|
|
3313
3367
|
env: context.env,
|
|
3314
|
-
label: context.
|
|
3368
|
+
label: context.labels,
|
|
3369
|
+
retried: context.retried
|
|
3315
3370
|
});
|
|
3316
3371
|
try {
|
|
3317
3372
|
await routeFunction(disabledContext);
|
|
@@ -3527,6 +3582,7 @@ var handleFailure = async ({
|
|
|
3527
3582
|
errorMessage = `Couldn't parse 'failResponse' in 'failureFunction', received: '${decodedBody}'`;
|
|
3528
3583
|
}
|
|
3529
3584
|
const userHeaders = recreateUserHeaders(request.headers);
|
|
3585
|
+
const retried = Number(request.headers.get(WORKFLOW_RETRIED_HEADER) ?? "0");
|
|
3530
3586
|
const workflowContext = new WorkflowContext({
|
|
3531
3587
|
qstashClient,
|
|
3532
3588
|
workflowRunId,
|
|
@@ -3538,6 +3594,7 @@ var handleFailure = async ({
|
|
|
3538
3594
|
telemetry: void 0,
|
|
3539
3595
|
// not going to make requests in authentication check
|
|
3540
3596
|
label: userHeaders.get(WORKFLOW_LABEL_HEADER) ?? void 0,
|
|
3597
|
+
retried,
|
|
3541
3598
|
workflowRunCreatedAt: workflowCreatedAt,
|
|
3542
3599
|
middlewareManager: void 0
|
|
3543
3600
|
});
|
|
@@ -3697,6 +3754,9 @@ var getReceiver = (environment, receiverConfig, region) => {
|
|
|
3697
3754
|
if (receiverConfig === "set-to-undefined") {
|
|
3698
3755
|
return void 0;
|
|
3699
3756
|
}
|
|
3757
|
+
if (isQStashDevModeEnabled(environment)) {
|
|
3758
|
+
return new import_qstash11.Receiver({ devMode: true });
|
|
3759
|
+
}
|
|
3700
3760
|
const receiverEnv = readReceiverEnvironmentVariables(environment, region);
|
|
3701
3761
|
return receiverEnv.QSTASH_CURRENT_SIGNING_KEY && receiverEnv.QSTASH_NEXT_SIGNING_KEY ? new import_qstash11.Receiver({
|
|
3702
3762
|
currentSigningKey: receiverEnv.QSTASH_CURRENT_SIGNING_KEY,
|
|
@@ -3706,6 +3766,10 @@ var getReceiver = (environment, receiverConfig, region) => {
|
|
|
3706
3766
|
return receiverConfig;
|
|
3707
3767
|
}
|
|
3708
3768
|
};
|
|
3769
|
+
var isQStashDevModeEnabled = (env) => {
|
|
3770
|
+
const value = env.QSTASH_DEV;
|
|
3771
|
+
return value === "true" || value === "1";
|
|
3772
|
+
};
|
|
3709
3773
|
var getQStashHandlerOptions = (...params) => {
|
|
3710
3774
|
const handlers = getQStashHandlers(...params);
|
|
3711
3775
|
return {
|
|
@@ -4015,12 +4079,13 @@ var serveBase = (routeFunction, telemetry2, options, internalOptions) => {
|
|
|
4015
4079
|
);
|
|
4016
4080
|
}
|
|
4017
4081
|
const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
|
|
4082
|
+
const retried = Number(request.headers.get(WORKFLOW_RETRIED_HEADER) ?? "0");
|
|
4018
4083
|
const label = request.headers.get(WORKFLOW_LABEL_HEADER) ?? void 0;
|
|
4019
4084
|
const workflowRunCreatedAt = request.headers.get(WORKFLOW_CREATED_AT_HEADER);
|
|
4020
4085
|
const workflowContext = new WorkflowContext({
|
|
4021
4086
|
qstashClient: regionalClient,
|
|
4022
4087
|
workflowRunId,
|
|
4023
|
-
initialPayload: initialPayloadParser(rawInitialPayload),
|
|
4088
|
+
initialPayload: isThirdPartyCallResult(request) ? JSON.parse(rawInitialPayload) : initialPayloadParser(rawInitialPayload),
|
|
4024
4089
|
headers: recreateUserHeaders(request.headers),
|
|
4025
4090
|
steps,
|
|
4026
4091
|
url: workflowUrl,
|
|
@@ -4028,6 +4093,7 @@ var serveBase = (routeFunction, telemetry2, options, internalOptions) => {
|
|
|
4028
4093
|
telemetry: telemetry2,
|
|
4029
4094
|
invokeCount,
|
|
4030
4095
|
label,
|
|
4096
|
+
retried,
|
|
4031
4097
|
workflowRunCreatedAt: Number(workflowRunCreatedAt),
|
|
4032
4098
|
middlewareManager
|
|
4033
4099
|
});
|
package/h3.mjs
CHANGED
package/hono.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Context } from 'hono';
|
|
2
|
-
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-
|
|
2
|
+
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-CekOpKvz.mjs';
|
|
3
3
|
import { Variables } from 'hono/types';
|
|
4
|
-
import { s as serveManyBase } from './serve-many-
|
|
4
|
+
import { s as serveManyBase } from './serve-many-CG3BFvO3.mjs';
|
|
5
5
|
import '@upstash/qstash';
|
|
6
6
|
import 'zod';
|
|
7
7
|
|
package/hono.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Context } from 'hono';
|
|
2
|
-
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-
|
|
2
|
+
import { c as RouteFunction, d as WorkflowServeOptions, I as InvokableWorkflow } from './types-CekOpKvz.js';
|
|
3
3
|
import { Variables } from 'hono/types';
|
|
4
|
-
import { s as serveManyBase } from './serve-many-
|
|
4
|
+
import { s as serveManyBase } from './serve-many-iJF1IUXk.js';
|
|
5
5
|
import '@upstash/qstash';
|
|
6
6
|
import 'zod';
|
|
7
7
|
|
package/hono.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/hono.mjs
CHANGED
package/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as StepType, R as RawStep, W as WorkflowMiddleware, a as WorkflowClient, b as WorkflowReceiver, c as RouteFunction, d as WorkflowServeOptions, T as Telemetry, N as NotifyResponse, e as Waiter } from './types-
|
|
2
|
-
export { A as AsyncStepFunction, C as CallResponse, f as CallSettings, D as DetailedFinishCondition, g as Duration, E as ExclusiveValidationOptions, F as FailureFunctionPayload, h as FinishCondition, H as HeaderParams, I as InvokableWorkflow, i as InvokeStepResponse, j as InvokeWorkflowRequest, L as LazyInvokeStepParams, k as NotifyStepResponse, P as ParallelCallState, Q as QStashClientExtraConfig, l as RequiredExceptFields, m as Step, n as StepFunction, o as StepTypes, p as SyncStepFunction, q as WaitEventOptions, r as WaitRequest, s as WaitStepResponse, t as WorkflowAbort, u as WorkflowContext, v as WorkflowError, w as WorkflowNonRetryableError, x as WorkflowRetryAfterError } from './types-
|
|
1
|
+
import { S as StepType, R as RawStep, W as WorkflowMiddleware, a as WorkflowClient, b as WorkflowReceiver, c as RouteFunction, d as WorkflowServeOptions, T as Telemetry, N as NotifyResponse, e as Waiter } from './types-CekOpKvz.mjs';
|
|
2
|
+
export { A as AsyncStepFunction, C as CallResponse, f as CallSettings, D as DetailedFinishCondition, g as Duration, E as ExclusiveValidationOptions, F as FailureFunctionPayload, h as FinishCondition, H as HeaderParams, I as InvokableWorkflow, i as InvokeStepResponse, j as InvokeWorkflowRequest, L as LazyInvokeStepParams, k as NotifyStepResponse, P as ParallelCallState, Q as QStashClientExtraConfig, l as RequiredExceptFields, m as Step, n as StepFunction, o as StepTypes, p as SyncStepFunction, q as WaitEventOptions, r as WaitRequest, s as WaitStepResponse, t as WorkflowAbort, u as WorkflowContext, v as WorkflowError, w as WorkflowNonRetryableError, x as WorkflowRetryAfterError } from './types-CekOpKvz.mjs';
|
|
3
3
|
import { FlowControl, PublishRequest, HTTPMethods, Client as Client$1 } from '@upstash/qstash';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|
|
@@ -317,9 +317,18 @@ type WorkflowRunLog = {
|
|
|
317
317
|
*/
|
|
318
318
|
dlqId?: string;
|
|
319
319
|
/**
|
|
320
|
-
* Label of the workflow run
|
|
320
|
+
* Label of the workflow run.
|
|
321
|
+
*
|
|
322
|
+
* @deprecated Use `labels` instead. When a run has multiple labels, this
|
|
323
|
+
* field only contains the first one.
|
|
321
324
|
*/
|
|
322
325
|
label?: string;
|
|
326
|
+
/**
|
|
327
|
+
* Labels attached to the workflow run.
|
|
328
|
+
*
|
|
329
|
+
* A run can have multiple labels when triggered with `label: string[]`.
|
|
330
|
+
*/
|
|
331
|
+
labels?: string[];
|
|
323
332
|
};
|
|
324
333
|
type WorkflowRunLogs = {
|
|
325
334
|
cursor: string;
|
|
@@ -403,8 +412,11 @@ type TriggerOptions = {
|
|
|
403
412
|
* Label to apply to the workflow run.
|
|
404
413
|
*
|
|
405
414
|
* Can be used to filter the workflow run logs.
|
|
415
|
+
*
|
|
416
|
+
* Pass an array to attach multiple labels to a single workflow run; they are
|
|
417
|
+
* sent as a comma-separated value in the `Upstash-Label` header.
|
|
406
418
|
*/
|
|
407
|
-
label?: string;
|
|
419
|
+
label?: string | string[];
|
|
408
420
|
/**
|
|
409
421
|
* By default, Workflow SDK sends telemetry about SDK version, framework or runtime.
|
|
410
422
|
*
|
|
@@ -526,7 +538,14 @@ type UniversalFilterFields = {
|
|
|
526
538
|
fromDate?: Date | number;
|
|
527
539
|
toDate?: Date | number;
|
|
528
540
|
callerIp?: string;
|
|
529
|
-
|
|
541
|
+
/**
|
|
542
|
+
* Filter by label.
|
|
543
|
+
*
|
|
544
|
+
* Pass an array to match runs that have any of the given labels (OR semantics).
|
|
545
|
+
* For example, with runs labelled `[label_1, label_2]` and `[label_2, label_3]`,
|
|
546
|
+
* filtering by `[label_1, label_2]` returns both.
|
|
547
|
+
*/
|
|
548
|
+
label?: string | string[];
|
|
530
549
|
flowControlKey?: string;
|
|
531
550
|
};
|
|
532
551
|
/** Workflow-specific filter fields for DLQ and bulk endpoints. */
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as StepType, R as RawStep, W as WorkflowMiddleware, a as WorkflowClient, b as WorkflowReceiver, c as RouteFunction, d as WorkflowServeOptions, T as Telemetry, N as NotifyResponse, e as Waiter } from './types-
|
|
2
|
-
export { A as AsyncStepFunction, C as CallResponse, f as CallSettings, D as DetailedFinishCondition, g as Duration, E as ExclusiveValidationOptions, F as FailureFunctionPayload, h as FinishCondition, H as HeaderParams, I as InvokableWorkflow, i as InvokeStepResponse, j as InvokeWorkflowRequest, L as LazyInvokeStepParams, k as NotifyStepResponse, P as ParallelCallState, Q as QStashClientExtraConfig, l as RequiredExceptFields, m as Step, n as StepFunction, o as StepTypes, p as SyncStepFunction, q as WaitEventOptions, r as WaitRequest, s as WaitStepResponse, t as WorkflowAbort, u as WorkflowContext, v as WorkflowError, w as WorkflowNonRetryableError, x as WorkflowRetryAfterError } from './types-
|
|
1
|
+
import { S as StepType, R as RawStep, W as WorkflowMiddleware, a as WorkflowClient, b as WorkflowReceiver, c as RouteFunction, d as WorkflowServeOptions, T as Telemetry, N as NotifyResponse, e as Waiter } from './types-CekOpKvz.js';
|
|
2
|
+
export { A as AsyncStepFunction, C as CallResponse, f as CallSettings, D as DetailedFinishCondition, g as Duration, E as ExclusiveValidationOptions, F as FailureFunctionPayload, h as FinishCondition, H as HeaderParams, I as InvokableWorkflow, i as InvokeStepResponse, j as InvokeWorkflowRequest, L as LazyInvokeStepParams, k as NotifyStepResponse, P as ParallelCallState, Q as QStashClientExtraConfig, l as RequiredExceptFields, m as Step, n as StepFunction, o as StepTypes, p as SyncStepFunction, q as WaitEventOptions, r as WaitRequest, s as WaitStepResponse, t as WorkflowAbort, u as WorkflowContext, v as WorkflowError, w as WorkflowNonRetryableError, x as WorkflowRetryAfterError } from './types-CekOpKvz.js';
|
|
3
3
|
import { FlowControl, PublishRequest, HTTPMethods, Client as Client$1 } from '@upstash/qstash';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|
|
@@ -317,9 +317,18 @@ type WorkflowRunLog = {
|
|
|
317
317
|
*/
|
|
318
318
|
dlqId?: string;
|
|
319
319
|
/**
|
|
320
|
-
* Label of the workflow run
|
|
320
|
+
* Label of the workflow run.
|
|
321
|
+
*
|
|
322
|
+
* @deprecated Use `labels` instead. When a run has multiple labels, this
|
|
323
|
+
* field only contains the first one.
|
|
321
324
|
*/
|
|
322
325
|
label?: string;
|
|
326
|
+
/**
|
|
327
|
+
* Labels attached to the workflow run.
|
|
328
|
+
*
|
|
329
|
+
* A run can have multiple labels when triggered with `label: string[]`.
|
|
330
|
+
*/
|
|
331
|
+
labels?: string[];
|
|
323
332
|
};
|
|
324
333
|
type WorkflowRunLogs = {
|
|
325
334
|
cursor: string;
|
|
@@ -403,8 +412,11 @@ type TriggerOptions = {
|
|
|
403
412
|
* Label to apply to the workflow run.
|
|
404
413
|
*
|
|
405
414
|
* Can be used to filter the workflow run logs.
|
|
415
|
+
*
|
|
416
|
+
* Pass an array to attach multiple labels to a single workflow run; they are
|
|
417
|
+
* sent as a comma-separated value in the `Upstash-Label` header.
|
|
406
418
|
*/
|
|
407
|
-
label?: string;
|
|
419
|
+
label?: string | string[];
|
|
408
420
|
/**
|
|
409
421
|
* By default, Workflow SDK sends telemetry about SDK version, framework or runtime.
|
|
410
422
|
*
|
|
@@ -526,7 +538,14 @@ type UniversalFilterFields = {
|
|
|
526
538
|
fromDate?: Date | number;
|
|
527
539
|
toDate?: Date | number;
|
|
528
540
|
callerIp?: string;
|
|
529
|
-
|
|
541
|
+
/**
|
|
542
|
+
* Filter by label.
|
|
543
|
+
*
|
|
544
|
+
* Pass an array to match runs that have any of the given labels (OR semantics).
|
|
545
|
+
* For example, with runs labelled `[label_1, label_2]` and `[label_2, label_3]`,
|
|
546
|
+
* filtering by `[label_1, label_2]` returns both.
|
|
547
|
+
*/
|
|
548
|
+
label?: string | string[];
|
|
530
549
|
flowControlKey?: string;
|
|
531
550
|
};
|
|
532
551
|
/** Workflow-specific filter fields for DLQ and bulk endpoints. */
|