@upstash/qstash 2.8.3 → 2.9.0-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/{chunk-5ACKA46J.mjs → chunk-NU64UBMT.mjs} +1 -1
- package/{chunk-TLUU4FA7.mjs → chunk-PB5UCB6Z.mjs} +6 -9
- package/{chunk-CR3B3DK3.mjs → chunk-WOMVRJIB.mjs} +640 -495
- package/{client-BpQp_dGA.d.ts → client-BVG9vt90.d.mts} +35 -5
- package/{client-BpQp_dGA.d.mts → client-BVG9vt90.d.ts} +35 -5
- package/cloudflare.d.mts +1 -1
- package/cloudflare.d.ts +1 -1
- package/cloudflare.js +812 -667
- package/cloudflare.mjs +1 -1
- package/h3.d.mts +1 -1
- package/h3.d.ts +1 -1
- package/h3.js +825 -683
- package/h3.mjs +3 -3
- package/hono.d.mts +1 -1
- package/hono.d.ts +1 -1
- package/hono.js +812 -667
- package/hono.mjs +1 -1
- package/index.d.mts +2 -2
- package/index.d.ts +2 -2
- package/index.js +637 -492
- package/index.mjs +2 -2
- package/nextjs.d.mts +1 -1
- package/nextjs.d.ts +1 -1
- package/nextjs.js +647 -511
- package/nextjs.mjs +16 -25
- package/nuxt.js +110 -12
- package/nuxt.mjs +3 -3
- package/package.json +1 -1
- package/solidjs.d.mts +1 -1
- package/solidjs.d.ts +1 -1
- package/solidjs.js +828 -682
- package/solidjs.mjs +9 -8
- package/svelte.d.mts +4 -4
- package/svelte.d.ts +4 -4
- package/svelte.js +830 -684
- package/svelte.mjs +11 -10
- package/workflow.d.mts +1 -1
- package/workflow.d.ts +1 -1
- package/workflow.js +812 -667
- package/workflow.mjs +1 -1
package/nextjs.mjs
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Receiver,
|
|
3
3
|
serve
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WOMVRJIB.mjs";
|
|
5
5
|
|
|
6
6
|
// platforms/nextjs.ts
|
|
7
7
|
var BAD_REQUEST = 400;
|
|
8
8
|
function verifySignature(handler, config) {
|
|
9
9
|
const currentSigningKey = config?.currentSigningKey ?? process.env.QSTASH_CURRENT_SIGNING_KEY;
|
|
10
|
-
if (!currentSigningKey) {
|
|
11
|
-
throw new Error(
|
|
12
|
-
"currentSigningKey is required, either in the config or as env variable QSTASH_CURRENT_SIGNING_KEY"
|
|
13
|
-
);
|
|
14
|
-
}
|
|
15
10
|
const nextSigningKey = config?.nextSigningKey ?? process.env.QSTASH_NEXT_SIGNING_KEY;
|
|
16
|
-
if (!nextSigningKey) {
|
|
11
|
+
if (!currentSigningKey && !nextSigningKey && !process.env.QSTASH_REGION) {
|
|
17
12
|
throw new Error(
|
|
18
|
-
"nextSigningKey
|
|
13
|
+
"currentSigningKey and nextSigningKey are required, either in the config or as env variables (QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY)"
|
|
19
14
|
);
|
|
20
15
|
}
|
|
21
16
|
const receiver = new Receiver({
|
|
@@ -33,6 +28,7 @@ function verifySignature(handler, config) {
|
|
|
33
28
|
if (typeof signature !== "string") {
|
|
34
29
|
throw new TypeError("`Upstash-Signature` header is not a string");
|
|
35
30
|
}
|
|
31
|
+
const upstashRegion = request.headers["upstash-region"];
|
|
36
32
|
const chunks = [];
|
|
37
33
|
for await (const chunk of request) {
|
|
38
34
|
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
@@ -41,7 +37,8 @@ function verifySignature(handler, config) {
|
|
|
41
37
|
const isValid = await receiver.verify({
|
|
42
38
|
signature,
|
|
43
39
|
body,
|
|
44
|
-
clockTolerance: config?.clockTolerance
|
|
40
|
+
clockTolerance: config?.clockTolerance,
|
|
41
|
+
upstashRegion: typeof upstashRegion === "string" ? upstashRegion : void 0
|
|
45
42
|
});
|
|
46
43
|
if (!isValid) {
|
|
47
44
|
response.status(BAD_REQUEST);
|
|
@@ -59,15 +56,10 @@ function verifySignature(handler, config) {
|
|
|
59
56
|
}
|
|
60
57
|
function verifySignatureEdge(handler, config) {
|
|
61
58
|
const currentSigningKey = config?.currentSigningKey ?? process.env.QSTASH_CURRENT_SIGNING_KEY;
|
|
62
|
-
if (!currentSigningKey) {
|
|
63
|
-
throw new Error(
|
|
64
|
-
"currentSigningKey is required, either in the config or as env variable QSTASH_CURRENT_SIGNING_KEY"
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
59
|
const nextSigningKey = config?.nextSigningKey ?? process.env.QSTASH_NEXT_SIGNING_KEY;
|
|
68
|
-
if (!nextSigningKey) {
|
|
60
|
+
if (!currentSigningKey && !nextSigningKey && !process.env.QSTASH_REGION) {
|
|
69
61
|
throw new Error(
|
|
70
|
-
"nextSigningKey
|
|
62
|
+
"currentSigningKey and nextSigningKey are required, either in the config or as env variables (QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY)"
|
|
71
63
|
);
|
|
72
64
|
}
|
|
73
65
|
const receiver = new Receiver({
|
|
@@ -85,11 +77,13 @@ function verifySignatureEdge(handler, config) {
|
|
|
85
77
|
if (typeof signature !== "string") {
|
|
86
78
|
throw new TypeError("`Upstash-Signature` header is not a string");
|
|
87
79
|
}
|
|
80
|
+
const upstashRegion = request.headers.get("upstash-region");
|
|
88
81
|
const body = await requestClone.text();
|
|
89
82
|
const isValid = await receiver.verify({
|
|
90
83
|
signature,
|
|
91
84
|
body,
|
|
92
|
-
clockTolerance: config?.clockTolerance
|
|
85
|
+
clockTolerance: config?.clockTolerance,
|
|
86
|
+
upstashRegion: upstashRegion ?? void 0
|
|
93
87
|
});
|
|
94
88
|
if (!isValid) {
|
|
95
89
|
return new Response(new TextEncoder().encode("invalid signature"), { status: 403 });
|
|
@@ -99,15 +93,10 @@ function verifySignatureEdge(handler, config) {
|
|
|
99
93
|
}
|
|
100
94
|
function verifySignatureAppRouter(handler, config) {
|
|
101
95
|
const currentSigningKey = config?.currentSigningKey ?? process.env.QSTASH_CURRENT_SIGNING_KEY;
|
|
102
|
-
if (!currentSigningKey) {
|
|
103
|
-
throw new Error(
|
|
104
|
-
"currentSigningKey is required, either in the config or as env variable QSTASH_CURRENT_SIGNING_KEY"
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
96
|
const nextSigningKey = config?.nextSigningKey ?? process.env.QSTASH_NEXT_SIGNING_KEY;
|
|
108
|
-
if (!nextSigningKey) {
|
|
97
|
+
if (!currentSigningKey && !nextSigningKey && !process.env.QSTASH_REGION) {
|
|
109
98
|
throw new Error(
|
|
110
|
-
"nextSigningKey
|
|
99
|
+
"currentSigningKey and nextSigningKey are required, either in the config or as env variables (QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY)"
|
|
111
100
|
);
|
|
112
101
|
}
|
|
113
102
|
const receiver = new Receiver({
|
|
@@ -125,11 +114,13 @@ function verifySignatureAppRouter(handler, config) {
|
|
|
125
114
|
if (typeof signature !== "string") {
|
|
126
115
|
throw new TypeError("`Upstash-Signature` header is not a string");
|
|
127
116
|
}
|
|
117
|
+
const upstashRegion = request.headers.get("upstash-region");
|
|
128
118
|
const body = await requestClone.text();
|
|
129
119
|
const isValid = await receiver.verify({
|
|
130
120
|
signature,
|
|
131
121
|
body,
|
|
132
|
-
clockTolerance: config?.clockTolerance
|
|
122
|
+
clockTolerance: config?.clockTolerance,
|
|
123
|
+
upstashRegion: upstashRegion ?? void 0
|
|
133
124
|
});
|
|
134
125
|
if (!isValid) {
|
|
135
126
|
return new Response(new TextEncoder().encode("invalid signature"), { status: 403 });
|
package/nuxt.js
CHANGED
|
@@ -360,6 +360,93 @@ var H3Response = globalThis.Response;
|
|
|
360
360
|
// src/receiver.ts
|
|
361
361
|
var jose = __toESM(require("jose"));
|
|
362
362
|
var import_crypto_js = __toESM(require("crypto-js"));
|
|
363
|
+
|
|
364
|
+
// src/client/utils.ts
|
|
365
|
+
function getSafeEnvironment() {
|
|
366
|
+
return typeof process === "undefined" ? {} : process.env;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// src/client/multi-region/utils.ts
|
|
370
|
+
var VALID_REGIONS = ["EU_CENTRAL_1", "US_EAST_1"];
|
|
371
|
+
var getRegionFromEnvironment = (environment) => {
|
|
372
|
+
const region = environment.QSTASH_REGION;
|
|
373
|
+
return normalizeRegionHeader(region);
|
|
374
|
+
};
|
|
375
|
+
function readEnvironmentVariables(environmentVariables, environment, region) {
|
|
376
|
+
const result = {};
|
|
377
|
+
for (const variable of environmentVariables) {
|
|
378
|
+
const key = region ? `${region}_${variable}` : variable;
|
|
379
|
+
result[variable] = environment[key];
|
|
380
|
+
}
|
|
381
|
+
return result;
|
|
382
|
+
}
|
|
383
|
+
function readReceiverEnvironmentVariables(environment, region) {
|
|
384
|
+
return readEnvironmentVariables(
|
|
385
|
+
["QSTASH_CURRENT_SIGNING_KEY", "QSTASH_NEXT_SIGNING_KEY"],
|
|
386
|
+
environment,
|
|
387
|
+
region
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
function normalizeRegionHeader(region) {
|
|
391
|
+
if (!region) {
|
|
392
|
+
return void 0;
|
|
393
|
+
}
|
|
394
|
+
region = region.replaceAll("-", "_").toUpperCase();
|
|
395
|
+
if (VALID_REGIONS.includes(region)) {
|
|
396
|
+
return region;
|
|
397
|
+
}
|
|
398
|
+
console.warn(
|
|
399
|
+
`[Upstash QStash] Invalid UPSTASH_REGION header value: "${region}". Expected one of: ${VALID_REGIONS.join(
|
|
400
|
+
", "
|
|
401
|
+
)}.`
|
|
402
|
+
);
|
|
403
|
+
return void 0;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// src/client/multi-region/incoming.ts
|
|
407
|
+
var getReceiverSigningKeys = ({
|
|
408
|
+
environment,
|
|
409
|
+
regionFromHeader,
|
|
410
|
+
config
|
|
411
|
+
}) => {
|
|
412
|
+
if (config?.currentSigningKey && config.nextSigningKey) {
|
|
413
|
+
return {
|
|
414
|
+
currentSigningKey: config.currentSigningKey,
|
|
415
|
+
nextSigningKey: config.nextSigningKey
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
const regionEnvironment = getRegionFromEnvironment(environment);
|
|
419
|
+
if (regionEnvironment) {
|
|
420
|
+
const regionHeader = normalizeRegionHeader(regionFromHeader);
|
|
421
|
+
if (regionHeader) {
|
|
422
|
+
const regionCreds = readReceiverEnvironmentVariables(environment, regionHeader);
|
|
423
|
+
if (regionCreds.QSTASH_CURRENT_SIGNING_KEY && regionCreds.QSTASH_NEXT_SIGNING_KEY) {
|
|
424
|
+
return {
|
|
425
|
+
currentSigningKey: regionCreds.QSTASH_CURRENT_SIGNING_KEY,
|
|
426
|
+
nextSigningKey: regionCreds.QSTASH_NEXT_SIGNING_KEY,
|
|
427
|
+
region: regionHeader
|
|
428
|
+
};
|
|
429
|
+
} else {
|
|
430
|
+
console.warn(
|
|
431
|
+
`[Upstash QStash] Signing keys not found for region "${regionHeader}". Falling back to default signing keys.`
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
} else {
|
|
435
|
+
console.warn(
|
|
436
|
+
`[Upstash QStash] Invalid UPSTASH_REGION header value: "${regionFromHeader}". Expected one of: EU-CENTRAL-1, US-EAST-1. Falling back to default signing keys.`
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
const defaultCreds = readReceiverEnvironmentVariables(environment);
|
|
441
|
+
if (defaultCreds.QSTASH_CURRENT_SIGNING_KEY && defaultCreds.QSTASH_NEXT_SIGNING_KEY) {
|
|
442
|
+
return {
|
|
443
|
+
currentSigningKey: defaultCreds.QSTASH_CURRENT_SIGNING_KEY,
|
|
444
|
+
nextSigningKey: defaultCreds.QSTASH_NEXT_SIGNING_KEY
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
// src/receiver.ts
|
|
363
450
|
var SignatureError = class extends Error {
|
|
364
451
|
constructor(message) {
|
|
365
452
|
super(message);
|
|
@@ -370,8 +457,8 @@ var Receiver = class {
|
|
|
370
457
|
currentSigningKey;
|
|
371
458
|
nextSigningKey;
|
|
372
459
|
constructor(config) {
|
|
373
|
-
this.currentSigningKey = config
|
|
374
|
-
this.nextSigningKey = config
|
|
460
|
+
this.currentSigningKey = config?.currentSigningKey;
|
|
461
|
+
this.nextSigningKey = config?.nextSigningKey;
|
|
375
462
|
}
|
|
376
463
|
/**
|
|
377
464
|
* Verify the signature of a request.
|
|
@@ -383,11 +470,25 @@ var Receiver = class {
|
|
|
383
470
|
* If that fails, the signature is invalid and a `SignatureError` is thrown.
|
|
384
471
|
*/
|
|
385
472
|
async verify(request) {
|
|
473
|
+
const environment = getSafeEnvironment();
|
|
474
|
+
const signingKeys = getReceiverSigningKeys({
|
|
475
|
+
environment,
|
|
476
|
+
regionFromHeader: request.upstashRegion,
|
|
477
|
+
config: {
|
|
478
|
+
currentSigningKey: this.currentSigningKey,
|
|
479
|
+
nextSigningKey: this.nextSigningKey
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
if (!signingKeys) {
|
|
483
|
+
throw new Error(
|
|
484
|
+
"[Upstash QStash] No signing keys available for verification. See the warning above for more details."
|
|
485
|
+
);
|
|
486
|
+
}
|
|
386
487
|
let payload;
|
|
387
488
|
try {
|
|
388
|
-
payload = await this.verifyWithKey(
|
|
489
|
+
payload = await this.verifyWithKey(signingKeys.currentSigningKey, request);
|
|
389
490
|
} catch {
|
|
390
|
-
payload = await this.verifyWithKey(
|
|
491
|
+
payload = await this.verifyWithKey(signingKeys.nextSigningKey, request);
|
|
391
492
|
}
|
|
392
493
|
this.verifyBodyAndUrl(payload, request);
|
|
393
494
|
return true;
|
|
@@ -429,15 +530,10 @@ var import_neverthrow3 = require("neverthrow");
|
|
|
429
530
|
// platforms/h3.ts
|
|
430
531
|
var verifySignatureH3 = (handler, config) => {
|
|
431
532
|
const currentSigningKey = config?.currentSigningKey ?? process.env.QSTASH_CURRENT_SIGNING_KEY;
|
|
432
|
-
if (!currentSigningKey) {
|
|
433
|
-
throw new Error(
|
|
434
|
-
"currentSigningKey is required, either in the config or as env variable QSTASH_CURRENT_SIGNING_KEY"
|
|
435
|
-
);
|
|
436
|
-
}
|
|
437
533
|
const nextSigningKey = config?.nextSigningKey ?? process.env.QSTASH_NEXT_SIGNING_KEY;
|
|
438
|
-
if (!nextSigningKey) {
|
|
534
|
+
if (!currentSigningKey && !nextSigningKey && !process.env.QSTASH_REGION) {
|
|
439
535
|
throw new Error(
|
|
440
|
-
"nextSigningKey
|
|
536
|
+
"currentSigningKey and nextSigningKey are required, either in the config or as env variables (QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY)"
|
|
441
537
|
);
|
|
442
538
|
}
|
|
443
539
|
const receiver = new Receiver({
|
|
@@ -452,11 +548,13 @@ var verifySignatureH3 = (handler, config) => {
|
|
|
452
548
|
if (typeof signature !== "string") {
|
|
453
549
|
throw new TypeError("`Upstash-Signature` header is not a string");
|
|
454
550
|
}
|
|
551
|
+
const upstashRegion = getHeader(event, "upstash-region");
|
|
455
552
|
const body = await readRawBody(event);
|
|
456
553
|
const isValid = await receiver.verify({
|
|
457
554
|
signature,
|
|
458
555
|
body: JSON.stringify(body),
|
|
459
|
-
clockTolerance: config?.clockTolerance
|
|
556
|
+
clockTolerance: config?.clockTolerance,
|
|
557
|
+
upstashRegion: typeof upstashRegion === "string" ? upstashRegion : void 0
|
|
460
558
|
});
|
|
461
559
|
if (!isValid) {
|
|
462
560
|
return { status: 403, body: "invalid signature" };
|
package/nuxt.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
verifySignatureH3
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-PB5UCB6Z.mjs";
|
|
4
|
+
import "./chunk-NU64UBMT.mjs";
|
|
5
|
+
import "./chunk-WOMVRJIB.mjs";
|
|
6
6
|
|
|
7
7
|
// platforms/nuxt.ts
|
|
8
8
|
var verifySignatureNuxt = verifySignatureH3;
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"v2.
|
|
1
|
+
{"version":"v2.9.0-rc","name":"@upstash/qstash","description":"Official Typescript client for QStash","author":"Andreas Thomas <dev@chronark.com>","license":"MIT","homepage":"https://github.com/upstash/sdk-qstash-ts#readme","repository":{"type":"git","url":"git+https://github.com/upstash/sdk-qstash-ts.git"},"bugs":{"url":"https://github.com/upstash/sdk-qstash-ts/issues"},"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"},"./nuxt":{"import":"./nuxt.mjs","require":"./nuxt.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"}},"keywords":["qstash","queue","events","serverless","upstash"],"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"},"devDependencies":{"@commitlint/cli":"^19.2.2","@commitlint/config-conventional":"^19.2.2","@eslint/eslintrc":"^3.1.0","@eslint/js":"^9.10.0","@solidjs/start":"^1.0.6","@sveltejs/kit":"^2.5.18","@types/bun":"^1.1.1","@types/crypto-js":"^4.2.0","@typescript-eslint/eslint-plugin":"^8.4.0","@typescript-eslint/parser":"^8.4.0","bun-types":"^1.1.7","eslint":"^9.10.0","eslint-plugin-unicorn":"^51.0.1","h3":"^1.12.0","hono":"^4.5.8","husky":"^9.0.10","next":"^14.0.2","prettier":"^3.2.5","tsup":"latest","typescript":"^5.4.5","undici-types":"^6.16.0","vitest":"latest"},"dependencies":{"crypto-js":">=4.2.0","jose":"^5.2.3","neverthrow":"^7.0.1"}}
|
package/solidjs.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { APIHandler, APIEvent } from '@solidjs/start/server';
|
|
2
|
-
import { a9 as RouteFunction, aa as WorkflowServeOptions } from './client-
|
|
2
|
+
import { a9 as RouteFunction, aa as WorkflowServeOptions } from './client-BVG9vt90.mjs';
|
|
3
3
|
import 'neverthrow';
|
|
4
4
|
|
|
5
5
|
type VerifySignatureConfig = {
|
package/solidjs.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { APIHandler, APIEvent } from '@solidjs/start/server';
|
|
2
|
-
import { a9 as RouteFunction, aa as WorkflowServeOptions } from './client-
|
|
2
|
+
import { a9 as RouteFunction, aa as WorkflowServeOptions } from './client-BVG9vt90.js';
|
|
3
3
|
import 'neverthrow';
|
|
4
4
|
|
|
5
5
|
type VerifySignatureConfig = {
|