@upstash/qstash 2.10.1 → 2.11.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 +20 -0
- package/{chunk-Z37KJCW7.mjs → chunk-ATX5KA4T.mjs} +1 -1
- package/{chunk-PIBVA43B.mjs → chunk-KGYBZXTJ.mjs} +1 -1
- package/{chunk-35B33QW3.mjs → chunk-T3Z5YUS4.mjs} +492 -12
- package/{client-CsM1dTnz.d.ts → client-BHOXiX0H.d.mts} +52 -2
- package/{client-CsM1dTnz.d.mts → client-BHOXiX0H.d.ts} +52 -2
- package/cloudflare.d.mts +1 -1
- package/cloudflare.d.ts +1 -1
- package/cloudflare.js +490 -12
- package/cloudflare.mjs +1 -1
- package/h3.d.mts +1 -1
- package/h3.d.ts +1 -1
- package/h3.js +490 -12
- package/h3.mjs +3 -3
- package/hono.d.mts +1 -1
- package/hono.d.ts +1 -1
- package/hono.js +490 -12
- package/hono.mjs +1 -1
- package/index.d.mts +2 -2
- package/index.d.ts +2 -2
- package/index.js +490 -12
- package/index.mjs +2 -2
- package/nextjs.d.mts +33 -2
- package/nextjs.d.ts +33 -2
- package/nextjs.js +511 -18
- package/nextjs.mjs +24 -8
- package/nuxt.js +70 -3
- 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 +490 -12
- package/solidjs.mjs +2 -2
- package/svelte.d.mts +1 -1
- package/svelte.d.ts +1 -1
- package/svelte.js +490 -12
- package/svelte.mjs +2 -2
- package/workflow.d.mts +1 -1
- package/workflow.d.ts +1 -1
- package/workflow.js +490 -12
- package/workflow.mjs +1 -1
package/nextjs.js
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// platforms/nextjs.ts
|
|
31
31
|
var nextjs_exports = {};
|
|
32
32
|
__export(nextjs_exports, {
|
|
33
|
+
registerQStashDev: () => registerQStashDev,
|
|
33
34
|
serve: () => serve2,
|
|
34
35
|
servePagesRouter: () => servePagesRouter,
|
|
35
36
|
verifySignature: () => verifySignature,
|
|
@@ -280,6 +281,9 @@ var formatWorkflowError = (error) => {
|
|
|
280
281
|
|
|
281
282
|
// src/client/utils.ts
|
|
282
283
|
var DEFAULT_BULK_COUNT = 100;
|
|
284
|
+
function serializeLabel(label) {
|
|
285
|
+
return Array.isArray(label) ? label.join(",") : label;
|
|
286
|
+
}
|
|
283
287
|
var isIgnoredHeader = (header) => {
|
|
284
288
|
const lowerCaseHeader = header.toLowerCase();
|
|
285
289
|
return lowerCaseHeader.startsWith("content-type") || lowerCaseHeader.startsWith("upstash-");
|
|
@@ -364,7 +368,7 @@ function processHeaders(request) {
|
|
|
364
368
|
headers.set("Upstash-Flow-Control-Value", controlValue.join(", "));
|
|
365
369
|
}
|
|
366
370
|
if (request.label !== void 0) {
|
|
367
|
-
headers.set("Upstash-Label", request.label);
|
|
371
|
+
headers.set("Upstash-Label", serializeLabel(request.label));
|
|
368
372
|
}
|
|
369
373
|
if (request.redact !== void 0) {
|
|
370
374
|
const redactParts = [];
|
|
@@ -461,17 +465,23 @@ function normalizeCursor(response) {
|
|
|
461
465
|
const cursor = response.cursor;
|
|
462
466
|
return { ...response, cursor: cursor || void 0 };
|
|
463
467
|
}
|
|
468
|
+
function _processGlobal() {
|
|
469
|
+
const proc = globalThis["process"];
|
|
470
|
+
return proc;
|
|
471
|
+
}
|
|
464
472
|
function getRuntime() {
|
|
465
|
-
|
|
466
|
-
|
|
473
|
+
const proc = _processGlobal();
|
|
474
|
+
if (proc?.versions?.bun)
|
|
475
|
+
return `bun@${proc.versions.bun}`;
|
|
467
476
|
if (typeof EdgeRuntime === "string")
|
|
468
477
|
return "edge-light";
|
|
469
|
-
|
|
470
|
-
return `node@${
|
|
478
|
+
if (typeof proc?.version === "string")
|
|
479
|
+
return `node@${proc.version}`;
|
|
471
480
|
return "";
|
|
472
481
|
}
|
|
473
482
|
function getSafeEnvironment() {
|
|
474
|
-
|
|
483
|
+
const proc = _processGlobal();
|
|
484
|
+
return proc?.env ?? {};
|
|
475
485
|
}
|
|
476
486
|
|
|
477
487
|
// src/client/multi-region/utils.ts
|
|
@@ -515,12 +525,453 @@ function normalizeRegionHeader(region) {
|
|
|
515
525
|
return void 0;
|
|
516
526
|
}
|
|
517
527
|
|
|
528
|
+
// src/dev-server/constants.ts
|
|
529
|
+
var DEFAULT_DEV_PORT = 8080;
|
|
530
|
+
var DEV_CREDENTIALS = {
|
|
531
|
+
token: "eyJVc2VySUQiOiJkZWZhdWx0VXNlciIsIlBhc3N3b3JkIjoiZGVmYXVsdFBhc3N3b3JkIn0=",
|
|
532
|
+
currentSigningKey: "sig_7kYjw48mhY7kAjqNGcy6cr29RJ6r",
|
|
533
|
+
nextSigningKey: "sig_5ZB6DVzB1wjE8S6rZ7eenA8Pdnhs"
|
|
534
|
+
};
|
|
535
|
+
var GITHUB_RELEASES_URL = "https://api.github.com/repos/upstash/qstash-cli/releases/latest";
|
|
536
|
+
var BINARY_URL_BASE = "https://artifacts.upstash.com/qstash/versions";
|
|
537
|
+
var CONSOLE_URL = "https://console.upstash.com/qstash/local-mode-user";
|
|
538
|
+
var DEV_PREFIX = "\x1B[2m[QStash Dev]\x1B[0m";
|
|
539
|
+
var CLI_PREFIX = "\x1B[2m[QStash CLI]\x1B[0m";
|
|
540
|
+
var _n = (m) => `node:${m}`;
|
|
541
|
+
var importHttp = () => import(
|
|
542
|
+
/* webpackIgnore: true */
|
|
543
|
+
_n("http")
|
|
544
|
+
);
|
|
545
|
+
var importHttps = () => import(
|
|
546
|
+
/* webpackIgnore: true */
|
|
547
|
+
_n("https")
|
|
548
|
+
);
|
|
549
|
+
var importFs = () => import(
|
|
550
|
+
/* webpackIgnore: true */
|
|
551
|
+
_n("fs")
|
|
552
|
+
);
|
|
553
|
+
var importChildProcess = () => import(
|
|
554
|
+
/* webpackIgnore: true */
|
|
555
|
+
_n("child_process")
|
|
556
|
+
);
|
|
557
|
+
var importOs = () => import(
|
|
558
|
+
/* webpackIgnore: true */
|
|
559
|
+
_n("os")
|
|
560
|
+
);
|
|
561
|
+
|
|
562
|
+
// src/dev-server/http.ts
|
|
563
|
+
var HTTP_OK = 200;
|
|
564
|
+
var HTTP_MULTI_CHOICE = 300;
|
|
565
|
+
var nativeGet = async (url, headers, timeoutMs) => {
|
|
566
|
+
const parsedUrl = new URL(url);
|
|
567
|
+
const httpModule = parsedUrl.protocol === "https:" ? await importHttps() : await importHttp();
|
|
568
|
+
return new Promise((resolve, reject) => {
|
|
569
|
+
const request = httpModule.get(url, { headers }, (response) => {
|
|
570
|
+
const chunks = [];
|
|
571
|
+
response.on("data", (chunk) => chunks.push(chunk));
|
|
572
|
+
response.on("end", () => {
|
|
573
|
+
const statusCode = response.statusCode ?? 0;
|
|
574
|
+
resolve({
|
|
575
|
+
ok: statusCode >= HTTP_OK && statusCode < HTTP_MULTI_CHOICE,
|
|
576
|
+
statusCode,
|
|
577
|
+
body: Buffer.concat(chunks)
|
|
578
|
+
});
|
|
579
|
+
});
|
|
580
|
+
response.on("error", reject);
|
|
581
|
+
});
|
|
582
|
+
if (timeoutMs) {
|
|
583
|
+
request.setTimeout(timeoutMs, () => {
|
|
584
|
+
request.destroy(new Error("Request timed out"));
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
request.on("error", reject);
|
|
588
|
+
});
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
// src/dev-server/health.ts
|
|
592
|
+
var HEALTH_CHECK_TIMEOUT_MS = 2e3;
|
|
593
|
+
var isDevServerRunning = async (baseUrl) => {
|
|
594
|
+
try {
|
|
595
|
+
const { ok: ok4, body } = await nativeGet(
|
|
596
|
+
`${baseUrl}/v2/keys`,
|
|
597
|
+
{ Authorization: `Bearer ${DEV_CREDENTIALS.token}` },
|
|
598
|
+
HEALTH_CHECK_TIMEOUT_MS
|
|
599
|
+
);
|
|
600
|
+
if (!ok4)
|
|
601
|
+
return false;
|
|
602
|
+
const data = JSON.parse(body.toString());
|
|
603
|
+
return data.current === DEV_CREDENTIALS.currentSigningKey && data.next === DEV_CREDENTIALS.nextSigningKey;
|
|
604
|
+
} catch {
|
|
605
|
+
return false;
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
var _didLogUnreachable = false;
|
|
609
|
+
var checkDevServerReachable = async (baseUrl, runtime) => {
|
|
610
|
+
if (await pingEdge(baseUrl))
|
|
611
|
+
return;
|
|
612
|
+
if (!_didLogUnreachable) {
|
|
613
|
+
console.error(unreachableMessage(baseUrl, runtime));
|
|
614
|
+
_didLogUnreachable = true;
|
|
615
|
+
}
|
|
616
|
+
throw new Error(`${DEV_PREFIX} dev server unreachable at ${baseUrl}`);
|
|
617
|
+
};
|
|
618
|
+
var pingEdge = async (baseUrl) => {
|
|
619
|
+
try {
|
|
620
|
+
const controller = new AbortController();
|
|
621
|
+
const timeout = setTimeout(() => {
|
|
622
|
+
controller.abort();
|
|
623
|
+
}, HEALTH_CHECK_TIMEOUT_MS);
|
|
624
|
+
const response = await fetch(`${baseUrl}/v2/keys`, {
|
|
625
|
+
headers: { Authorization: `Bearer ${DEV_CREDENTIALS.token}` },
|
|
626
|
+
signal: controller.signal
|
|
627
|
+
});
|
|
628
|
+
clearTimeout(timeout);
|
|
629
|
+
return response.ok;
|
|
630
|
+
} catch {
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
var unreachableMessage = (baseUrl, runtime) => {
|
|
635
|
+
const port = new URL(baseUrl).port;
|
|
636
|
+
const manualStartCmd = `npx @upstash/qstash-cli dev --port ${port}`;
|
|
637
|
+
const header = `
|
|
638
|
+
${DEV_PREFIX} The dev server is not running at ${baseUrl}.
|
|
639
|
+
|
|
640
|
+
`;
|
|
641
|
+
if (runtime === "cloudflare-workers") {
|
|
642
|
+
return header + `Cloudflare Workers cannot start the dev server automatically.
|
|
643
|
+
Start it manually before running wrangler dev:
|
|
644
|
+
|
|
645
|
+
${manualStartCmd}
|
|
646
|
+
`;
|
|
647
|
+
}
|
|
648
|
+
return header + `Edge runtimes cannot start the dev server automatically.
|
|
649
|
+
Either:
|
|
650
|
+
1. Add the instrumentation hook to start it with your app:
|
|
651
|
+
|
|
652
|
+
// instrumentation.ts
|
|
653
|
+
import { registerQStashDev } from "@upstash/qstash/nextjs";
|
|
654
|
+
export async function register() { await registerQStashDev(); }
|
|
655
|
+
|
|
656
|
+
2. Or start it manually:
|
|
657
|
+
|
|
658
|
+
${manualStartCmd}
|
|
659
|
+
`;
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
// src/dev-server/binary.ts
|
|
663
|
+
var ensureBinary = async () => {
|
|
664
|
+
const fs = await importFs();
|
|
665
|
+
const os = await importOs();
|
|
666
|
+
const cacheDirectory = await findCacheDirectory();
|
|
667
|
+
const isWindows = os.platform() === "win32";
|
|
668
|
+
const binaryName = isWindows ? "qstash.exe" : "qstash";
|
|
669
|
+
const binaryPath = `${cacheDirectory}/${binaryName}`;
|
|
670
|
+
const versionFile = `${cacheDirectory}/.version`;
|
|
671
|
+
let version;
|
|
672
|
+
try {
|
|
673
|
+
version = await fetchLatestVersion();
|
|
674
|
+
} catch (error) {
|
|
675
|
+
if (fs.existsSync(binaryPath)) {
|
|
676
|
+
const cachedVersion = fs.existsSync(versionFile) ? fs.readFileSync(versionFile, "utf8").trim() : "unknown";
|
|
677
|
+
console.log(`${DEV_PREFIX} Offline, using local v${cachedVersion}`);
|
|
678
|
+
return binaryPath;
|
|
679
|
+
}
|
|
680
|
+
throw error;
|
|
681
|
+
}
|
|
682
|
+
return downloadBinary(version, cacheDirectory);
|
|
683
|
+
};
|
|
684
|
+
var fetchLatestVersion = async () => {
|
|
685
|
+
const { ok: ok4, statusCode, body } = await nativeGet(GITHUB_RELEASES_URL, {
|
|
686
|
+
Accept: "application/vnd.github.v3+json",
|
|
687
|
+
"User-Agent": "upstash-qstash-js"
|
|
688
|
+
});
|
|
689
|
+
if (!ok4) {
|
|
690
|
+
throw new Error(`[QStash Dev] Failed to fetch latest version: HTTP ${statusCode}`);
|
|
691
|
+
}
|
|
692
|
+
const data = JSON.parse(body.toString());
|
|
693
|
+
return data.tag_name.replace(/^v/, "");
|
|
694
|
+
};
|
|
695
|
+
var findCacheDirectory = async () => {
|
|
696
|
+
const fs = await importFs();
|
|
697
|
+
const os = await importOs();
|
|
698
|
+
const home = os.homedir();
|
|
699
|
+
const platform = os.platform();
|
|
700
|
+
let base;
|
|
701
|
+
if (platform === "darwin") {
|
|
702
|
+
base = `${home}/Library/Caches/upstash`;
|
|
703
|
+
} else if (platform === "win32") {
|
|
704
|
+
base = `${process.env.LOCALAPPDATA ?? `${home}/AppData/Local`}/upstash`;
|
|
705
|
+
} else {
|
|
706
|
+
base = `${home}/.cache/upstash`;
|
|
707
|
+
}
|
|
708
|
+
const cacheDirectory = `${base}/qstash-dev`;
|
|
709
|
+
await fs.promises.mkdir(cacheDirectory, { recursive: true });
|
|
710
|
+
return cacheDirectory;
|
|
711
|
+
};
|
|
712
|
+
var downloadBinary = async (version, cacheDirectory) => {
|
|
713
|
+
const fs = await importFs();
|
|
714
|
+
const childProcess = await importChildProcess();
|
|
715
|
+
const os = await importOs();
|
|
716
|
+
const osPlatform = os.platform();
|
|
717
|
+
const isWindows = osPlatform === "win32";
|
|
718
|
+
const platform = isWindows ? "windows" : osPlatform === "darwin" ? "darwin" : "linux";
|
|
719
|
+
const arch = os.arch() === "arm64" ? "arm64" : "amd64";
|
|
720
|
+
const archiveName = `qstash-server_${version}_${platform}_${arch}`;
|
|
721
|
+
const binaryName = isWindows ? "qstash.exe" : "qstash";
|
|
722
|
+
const binaryPath = `${cacheDirectory}/${binaryName}`;
|
|
723
|
+
const versionFile = `${cacheDirectory}/.version`;
|
|
724
|
+
if (fs.existsSync(binaryPath) && fs.existsSync(versionFile)) {
|
|
725
|
+
const cachedVersion = fs.readFileSync(versionFile, "utf8").trim();
|
|
726
|
+
if (cachedVersion === version) {
|
|
727
|
+
return binaryPath;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
await fs.promises.rm(cacheDirectory, { recursive: true, force: true });
|
|
731
|
+
await fs.promises.mkdir(cacheDirectory, { recursive: true });
|
|
732
|
+
const extension = isWindows ? "zip" : "tar.gz";
|
|
733
|
+
const archiveUrl = `${BINARY_URL_BASE}/${version}/${archiveName}.${extension}`;
|
|
734
|
+
console.log(`${DEV_PREFIX} Downloading dev server v${version}...`);
|
|
735
|
+
const { ok: ok4, statusCode, body } = await nativeGet(archiveUrl);
|
|
736
|
+
if (!ok4) {
|
|
737
|
+
throw new Error(`[QStash Dev] Failed to download binary: HTTP ${statusCode}`);
|
|
738
|
+
}
|
|
739
|
+
const archivePath = `${cacheDirectory}/${archiveName}.${extension}`;
|
|
740
|
+
await fs.promises.writeFile(archivePath, new Uint8Array(body));
|
|
741
|
+
childProcess.execFileSync("tar", ["-xf", archivePath, "-C", cacheDirectory], {
|
|
742
|
+
stdio: "pipe"
|
|
743
|
+
});
|
|
744
|
+
if (!isWindows) {
|
|
745
|
+
const EXECUTABLE_PERMISSION = 493;
|
|
746
|
+
await fs.promises.chmod(binaryPath, EXECUTABLE_PERMISSION);
|
|
747
|
+
}
|
|
748
|
+
await fs.promises.writeFile(versionFile, version);
|
|
749
|
+
await fs.promises.unlink(archivePath).catch(() => {
|
|
750
|
+
});
|
|
751
|
+
return binaryPath;
|
|
752
|
+
};
|
|
753
|
+
|
|
754
|
+
// src/dev-server/process.ts
|
|
755
|
+
var STARTUP_TIMEOUT_MS = 3e4;
|
|
756
|
+
var _proc = () => {
|
|
757
|
+
return globalThis["process"] ?? {};
|
|
758
|
+
};
|
|
759
|
+
var spawnServer = async (binaryPath, port, onUnexpectedExit) => {
|
|
760
|
+
const childProcess = await importChildProcess();
|
|
761
|
+
const child = await new Promise((resolve, reject) => {
|
|
762
|
+
const child2 = childProcess.spawn(binaryPath, ["dev", "--port", String(port)], {
|
|
763
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
764
|
+
});
|
|
765
|
+
const timeout = setTimeout(() => {
|
|
766
|
+
child2.kill();
|
|
767
|
+
reject(new Error("[QStash Dev] Server failed to start within 30 seconds"));
|
|
768
|
+
}, STARTUP_TIMEOUT_MS);
|
|
769
|
+
let startupOutput = "";
|
|
770
|
+
let started = false;
|
|
771
|
+
const bufferLine = (line) => {
|
|
772
|
+
if (!started)
|
|
773
|
+
startupOutput += `${line}
|
|
774
|
+
`;
|
|
775
|
+
};
|
|
776
|
+
forwardWithPrefix(child2.stdout, _proc().stdout, (line) => {
|
|
777
|
+
bufferLine(line);
|
|
778
|
+
if (!started && /runn+ing( at|\.)/i.test(line)) {
|
|
779
|
+
clearTimeout(timeout);
|
|
780
|
+
started = true;
|
|
781
|
+
resolve(child2);
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
forwardWithPrefix(child2.stderr, _proc().stderr, bufferLine);
|
|
785
|
+
child2.on("error", (error) => {
|
|
786
|
+
clearTimeout(timeout);
|
|
787
|
+
reject(new Error(`[QStash Dev] Failed to start server: ${error.message}`));
|
|
788
|
+
});
|
|
789
|
+
child2.on("close", (code, _signal) => {
|
|
790
|
+
if (started) {
|
|
791
|
+
onUnexpectedExit?.();
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
clearTimeout(timeout);
|
|
795
|
+
reject(new Error(formatStartupError(code, startupOutput)));
|
|
796
|
+
});
|
|
797
|
+
});
|
|
798
|
+
registerCleanup(child);
|
|
799
|
+
child.unref?.();
|
|
800
|
+
child.stdout?.unref?.();
|
|
801
|
+
child.stderr?.unref?.();
|
|
802
|
+
};
|
|
803
|
+
var formatStartupError = (code, startupOutput) => {
|
|
804
|
+
const cleaned = startupOutput.replaceAll(/\u001B\[[\d;]*m/g, "").replaceAll(/^\d{1,2}:\d{2}(AM|PM)\s+\w{3}\s+/gm, "").trim();
|
|
805
|
+
if (/address already in use/i.test(cleaned)) {
|
|
806
|
+
const match = /:(\d+)\s*$/.exec(cleaned);
|
|
807
|
+
const portHint = match ? ` on port ${match[1]}` : "";
|
|
808
|
+
return `[QStash Dev] Port already in use${portHint}. Set QSTASH_DEV_PORT to use a different port, or stop the process holding it.`;
|
|
809
|
+
}
|
|
810
|
+
const codeSuffix = code ? ` with code ${code}` : "";
|
|
811
|
+
const detail = cleaned ? `: ${cleaned}` : "";
|
|
812
|
+
return `[QStash Dev] Server exited unexpectedly${codeSuffix}${detail}`;
|
|
813
|
+
};
|
|
814
|
+
var forwardWithPrefix = (source, destination, onLine) => {
|
|
815
|
+
if (!source)
|
|
816
|
+
return;
|
|
817
|
+
let buffer = "";
|
|
818
|
+
const flushLine = (line) => {
|
|
819
|
+
destination?.write(`${CLI_PREFIX} ${line}
|
|
820
|
+
`);
|
|
821
|
+
onLine(line);
|
|
822
|
+
};
|
|
823
|
+
source.on("data", (data) => {
|
|
824
|
+
buffer += data.toString();
|
|
825
|
+
let newlineIndex = buffer.indexOf("\n");
|
|
826
|
+
while (newlineIndex !== -1) {
|
|
827
|
+
flushLine(buffer.slice(0, newlineIndex));
|
|
828
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
829
|
+
newlineIndex = buffer.indexOf("\n");
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
source.on("end", () => {
|
|
833
|
+
if (buffer.length > 0) {
|
|
834
|
+
flushLine(buffer);
|
|
835
|
+
buffer = "";
|
|
836
|
+
}
|
|
837
|
+
});
|
|
838
|
+
source.on("error", () => {
|
|
839
|
+
});
|
|
840
|
+
};
|
|
841
|
+
var currentChild;
|
|
842
|
+
var processHandlersRegistered = false;
|
|
843
|
+
var killCurrentChild = () => {
|
|
844
|
+
if (!currentChild)
|
|
845
|
+
return;
|
|
846
|
+
try {
|
|
847
|
+
currentChild.kill("SIGTERM");
|
|
848
|
+
} catch {
|
|
849
|
+
}
|
|
850
|
+
currentChild = void 0;
|
|
851
|
+
};
|
|
852
|
+
var registerCleanup = (child) => {
|
|
853
|
+
currentChild = child;
|
|
854
|
+
if (!processHandlersRegistered) {
|
|
855
|
+
processHandlersRegistered = true;
|
|
856
|
+
const proc = _proc();
|
|
857
|
+
proc.on?.("exit", killCurrentChild);
|
|
858
|
+
proc.on?.("SIGINT", () => {
|
|
859
|
+
killCurrentChild();
|
|
860
|
+
proc.exit?.(0);
|
|
861
|
+
});
|
|
862
|
+
proc.on?.("SIGTERM", () => {
|
|
863
|
+
killCurrentChild();
|
|
864
|
+
proc.exit?.(0);
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
};
|
|
868
|
+
|
|
869
|
+
// src/dev-server/index.ts
|
|
870
|
+
var _processGlobal2 = () => {
|
|
871
|
+
const proc = globalThis["process"];
|
|
872
|
+
return proc;
|
|
873
|
+
};
|
|
874
|
+
var devServerPromise;
|
|
875
|
+
var ensureDevelopmentServer = (env, devMode) => {
|
|
876
|
+
if (!shouldUseDevelopmentMode(devMode, env))
|
|
877
|
+
return Promise.resolve();
|
|
878
|
+
const procEnv = _processGlobal2()?.env;
|
|
879
|
+
if (procEnv?.NEXT_PHASE === "phase-production-build")
|
|
880
|
+
return Promise.resolve();
|
|
881
|
+
if (procEnv?.NODE_ENV === "production")
|
|
882
|
+
return Promise.resolve();
|
|
883
|
+
const runtime = getRuntime2();
|
|
884
|
+
if (runtime !== "nodejs") {
|
|
885
|
+
return checkDevServerReachable(getDevUrl(env), runtime);
|
|
886
|
+
}
|
|
887
|
+
if (!devServerPromise) {
|
|
888
|
+
devServerPromise = startPipeline(env).catch((error) => {
|
|
889
|
+
devServerPromise = void 0;
|
|
890
|
+
throw error;
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
return devServerPromise;
|
|
894
|
+
};
|
|
895
|
+
var startPipeline = async (env) => {
|
|
896
|
+
const baseUrl = getDevUrl(env);
|
|
897
|
+
const port = new URL(baseUrl).port;
|
|
898
|
+
const consoleLink = `\x1B[36m${CONSOLE_URL}?port=${port}\x1B[0m`;
|
|
899
|
+
if (await isDevServerRunning(baseUrl)) {
|
|
900
|
+
console.log(
|
|
901
|
+
`${DEV_PREFIX} Server already running at ${baseUrl}
|
|
902
|
+
${DEV_PREFIX} Console: ${consoleLink}`
|
|
903
|
+
);
|
|
904
|
+
return;
|
|
905
|
+
}
|
|
906
|
+
const binaryPath = await ensureBinary();
|
|
907
|
+
await spawnServer(binaryPath, port, () => {
|
|
908
|
+
devServerPromise = void 0;
|
|
909
|
+
});
|
|
910
|
+
};
|
|
911
|
+
var shouldUseDevelopmentMode = (devMode, env) => {
|
|
912
|
+
if (devMode !== void 0)
|
|
913
|
+
return devMode;
|
|
914
|
+
const value = env?.QSTASH_DEV ?? getProcessEnvironment("QSTASH_DEV");
|
|
915
|
+
if (value === void 0 || value === "" || value === "false" || value === "0")
|
|
916
|
+
return false;
|
|
917
|
+
if (value === "true" || value === "1")
|
|
918
|
+
return true;
|
|
919
|
+
throw new Error(`[QStash Dev] Invalid value for QSTASH_DEV in environment: ${value}`);
|
|
920
|
+
};
|
|
921
|
+
var getDevelopmentCredentials = (env) => {
|
|
922
|
+
return {
|
|
923
|
+
...DEV_CREDENTIALS,
|
|
924
|
+
baseUrl: getDevUrl(env)
|
|
925
|
+
};
|
|
926
|
+
};
|
|
927
|
+
var getDevUrl = (env) => {
|
|
928
|
+
const portString = env?.QSTASH_DEV_PORT ?? getProcessEnvironment("QSTASH_DEV_PORT");
|
|
929
|
+
let port = DEFAULT_DEV_PORT;
|
|
930
|
+
if (portString) {
|
|
931
|
+
const parsed = Number.parseInt(portString, 10);
|
|
932
|
+
if (!Number.isNaN(parsed) && parsed > 0) {
|
|
933
|
+
port = parsed;
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
return `http://127.0.0.1:${port}`;
|
|
937
|
+
};
|
|
938
|
+
var getRuntime2 = () => {
|
|
939
|
+
if (typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers") {
|
|
940
|
+
return "cloudflare-workers";
|
|
941
|
+
}
|
|
942
|
+
const proc = _processGlobal2();
|
|
943
|
+
if (!proc) {
|
|
944
|
+
return "browser";
|
|
945
|
+
}
|
|
946
|
+
if (!proc.release?.name) {
|
|
947
|
+
return "edge";
|
|
948
|
+
}
|
|
949
|
+
return "nodejs";
|
|
950
|
+
};
|
|
951
|
+
var getProcessEnvironment = (key) => {
|
|
952
|
+
const proc = _processGlobal2();
|
|
953
|
+
return proc?.env ? proc.env[key] : void 0;
|
|
954
|
+
};
|
|
955
|
+
|
|
518
956
|
// src/client/multi-region/incoming.ts
|
|
519
957
|
var getReceiverSigningKeys = ({
|
|
520
958
|
environment,
|
|
521
959
|
regionFromHeader,
|
|
522
|
-
config
|
|
960
|
+
config,
|
|
961
|
+
devMode
|
|
523
962
|
}) => {
|
|
963
|
+
if (shouldUseDevelopmentMode(devMode, environment)) {
|
|
964
|
+
if (config?.currentSigningKey || config?.nextSigningKey) {
|
|
965
|
+
console.warn(
|
|
966
|
+
`${DEV_PREFIX} Dev mode is active. Ignoring signing keys from config. Set devMode: false to use your own keys.`
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
const developmentCreds = getDevelopmentCredentials(environment);
|
|
970
|
+
return {
|
|
971
|
+
currentSigningKey: developmentCreds.currentSigningKey,
|
|
972
|
+
nextSigningKey: developmentCreds.nextSigningKey
|
|
973
|
+
};
|
|
974
|
+
}
|
|
524
975
|
if (config?.currentSigningKey && config.nextSigningKey) {
|
|
525
976
|
return {
|
|
526
977
|
currentSigningKey: config.currentSigningKey,
|
|
@@ -565,8 +1016,21 @@ var getClientCredentials = (clientCredentialConfig) => {
|
|
|
565
1016
|
};
|
|
566
1017
|
var resolveCredentials = ({
|
|
567
1018
|
environment,
|
|
568
|
-
config
|
|
1019
|
+
config,
|
|
1020
|
+
devMode
|
|
569
1021
|
}) => {
|
|
1022
|
+
if (shouldUseDevelopmentMode(devMode, environment)) {
|
|
1023
|
+
if (config?.baseUrl || config?.token) {
|
|
1024
|
+
console.warn(
|
|
1025
|
+
`${DEV_PREFIX} Dev mode is active. Ignoring baseUrl/token from config. Set devMode: false to use your own credentials.`
|
|
1026
|
+
);
|
|
1027
|
+
}
|
|
1028
|
+
const developmentCreds = getDevelopmentCredentials(environment);
|
|
1029
|
+
return {
|
|
1030
|
+
baseUrl: developmentCreds.baseUrl,
|
|
1031
|
+
token: developmentCreds.token
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
570
1034
|
if (config?.baseUrl && config.token) {
|
|
571
1035
|
return {
|
|
572
1036
|
baseUrl: config.baseUrl,
|
|
@@ -619,9 +1083,11 @@ var SignatureError = class extends Error {
|
|
|
619
1083
|
var Receiver = class {
|
|
620
1084
|
currentSigningKey;
|
|
621
1085
|
nextSigningKey;
|
|
1086
|
+
devMode;
|
|
622
1087
|
constructor(config) {
|
|
623
1088
|
this.currentSigningKey = config?.currentSigningKey;
|
|
624
1089
|
this.nextSigningKey = config?.nextSigningKey;
|
|
1090
|
+
this.devMode = config?.devMode;
|
|
625
1091
|
}
|
|
626
1092
|
/**
|
|
627
1093
|
* Verify the signature of a request.
|
|
@@ -640,7 +1106,8 @@ var Receiver = class {
|
|
|
640
1106
|
config: {
|
|
641
1107
|
currentSigningKey: this.currentSigningKey,
|
|
642
1108
|
nextSigningKey: this.nextSigningKey
|
|
643
|
-
}
|
|
1109
|
+
},
|
|
1110
|
+
devMode: this.devMode
|
|
644
1111
|
});
|
|
645
1112
|
if (!signingKeys) {
|
|
646
1113
|
throw new Error(
|
|
@@ -906,12 +1373,14 @@ var HttpClient = class {
|
|
|
906
1373
|
baseUrl;
|
|
907
1374
|
authorization;
|
|
908
1375
|
options;
|
|
1376
|
+
devMode;
|
|
909
1377
|
retry;
|
|
910
1378
|
headers;
|
|
911
1379
|
telemetryHeaders;
|
|
912
1380
|
constructor(config) {
|
|
913
1381
|
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
914
1382
|
this.authorization = config.authorization;
|
|
1383
|
+
this.devMode = config.devMode;
|
|
915
1384
|
this.retry = // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
916
1385
|
typeof config.retry === "boolean" && !config.retry ? {
|
|
917
1386
|
attempts: 1,
|
|
@@ -924,6 +1393,7 @@ var HttpClient = class {
|
|
|
924
1393
|
this.telemetryHeaders = config.telemetryHeaders;
|
|
925
1394
|
}
|
|
926
1395
|
async request(request) {
|
|
1396
|
+
await ensureDevelopmentServer(void 0, this.devMode);
|
|
927
1397
|
const { response } = await this.requestWithBackoff(request);
|
|
928
1398
|
if (request.parseResponseAsJson === false) {
|
|
929
1399
|
return void 0;
|
|
@@ -931,6 +1401,7 @@ var HttpClient = class {
|
|
|
931
1401
|
return await response.json();
|
|
932
1402
|
}
|
|
933
1403
|
async *requestStream(request) {
|
|
1404
|
+
await ensureDevelopmentServer(void 0, this.devMode);
|
|
934
1405
|
const { response } = await this.requestWithBackoff(request);
|
|
935
1406
|
if (!response.body) {
|
|
936
1407
|
throw new Error("No response body");
|
|
@@ -1653,7 +2124,7 @@ var UrlGroups = class {
|
|
|
1653
2124
|
};
|
|
1654
2125
|
|
|
1655
2126
|
// version.ts
|
|
1656
|
-
var VERSION = "2.
|
|
2127
|
+
var VERSION = "2.11.1";
|
|
1657
2128
|
|
|
1658
2129
|
// src/client/client.ts
|
|
1659
2130
|
var Client = class {
|
|
@@ -1661,7 +2132,14 @@ var Client = class {
|
|
|
1661
2132
|
token;
|
|
1662
2133
|
constructor(config) {
|
|
1663
2134
|
const environment = getSafeEnvironment();
|
|
1664
|
-
const { baseUrl, token } = getClientCredentials({
|
|
2135
|
+
const { baseUrl, token } = getClientCredentials({
|
|
2136
|
+
environment,
|
|
2137
|
+
config,
|
|
2138
|
+
devMode: config?.devMode
|
|
2139
|
+
});
|
|
2140
|
+
if (shouldUseDevelopmentMode(config?.devMode, environment)) {
|
|
2141
|
+
void ensureDevelopmentServer(environment, config?.devMode);
|
|
2142
|
+
}
|
|
1665
2143
|
const enableTelemetry = environment.UPSTASH_DISABLE_TELEMETRY ? false : config?.enableTelemetry ?? true;
|
|
1666
2144
|
const isCloudflare = typeof caches !== "undefined" && "default" in caches;
|
|
1667
2145
|
const telemetryHeaders = new Headers(
|
|
@@ -1678,7 +2156,8 @@ var Client = class {
|
|
|
1678
2156
|
//@ts-expect-error caused by undici and bunjs type overlap
|
|
1679
2157
|
headers: prefixHeaders(new Headers(config?.headers ?? {})),
|
|
1680
2158
|
//@ts-expect-error caused by undici and bunjs type overlap
|
|
1681
|
-
telemetryHeaders
|
|
2159
|
+
telemetryHeaders,
|
|
2160
|
+
devMode: config?.devMode
|
|
1682
2161
|
});
|
|
1683
2162
|
this.token = token;
|
|
1684
2163
|
}
|
|
@@ -3286,14 +3765,16 @@ var BAD_REQUEST = 400;
|
|
|
3286
3765
|
function verifySignature(handler, config) {
|
|
3287
3766
|
const currentSigningKey = config?.currentSigningKey ?? process.env.QSTASH_CURRENT_SIGNING_KEY;
|
|
3288
3767
|
const nextSigningKey = config?.nextSigningKey ?? process.env.QSTASH_NEXT_SIGNING_KEY;
|
|
3289
|
-
|
|
3768
|
+
const devMode = shouldUseDevelopmentMode(config?.devMode, process.env);
|
|
3769
|
+
if (!devMode && !currentSigningKey && !nextSigningKey && !process.env.QSTASH_REGION) {
|
|
3290
3770
|
throw new Error(
|
|
3291
3771
|
"currentSigningKey and nextSigningKey are required, either in the config or as env variables (QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY)"
|
|
3292
3772
|
);
|
|
3293
3773
|
}
|
|
3294
3774
|
const receiver = new Receiver({
|
|
3295
3775
|
currentSigningKey,
|
|
3296
|
-
nextSigningKey
|
|
3776
|
+
nextSigningKey,
|
|
3777
|
+
devMode: config?.devMode
|
|
3297
3778
|
});
|
|
3298
3779
|
return async (request, response) => {
|
|
3299
3780
|
const signature = request.headers["upstash-signature"];
|
|
@@ -3335,14 +3816,16 @@ function verifySignature(handler, config) {
|
|
|
3335
3816
|
function verifySignatureEdge(handler, config) {
|
|
3336
3817
|
const currentSigningKey = config?.currentSigningKey ?? process.env.QSTASH_CURRENT_SIGNING_KEY;
|
|
3337
3818
|
const nextSigningKey = config?.nextSigningKey ?? process.env.QSTASH_NEXT_SIGNING_KEY;
|
|
3338
|
-
|
|
3819
|
+
const devMode = shouldUseDevelopmentMode(config?.devMode, process.env);
|
|
3820
|
+
if (!devMode && !currentSigningKey && !nextSigningKey && !process.env.QSTASH_REGION) {
|
|
3339
3821
|
throw new Error(
|
|
3340
3822
|
"currentSigningKey and nextSigningKey are required, either in the config or as env variables (QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY)"
|
|
3341
3823
|
);
|
|
3342
3824
|
}
|
|
3343
3825
|
const receiver = new Receiver({
|
|
3344
3826
|
currentSigningKey,
|
|
3345
|
-
nextSigningKey
|
|
3827
|
+
nextSigningKey,
|
|
3828
|
+
devMode: config?.devMode
|
|
3346
3829
|
});
|
|
3347
3830
|
return async (request, nfe) => {
|
|
3348
3831
|
const requestClone = request.clone();
|
|
@@ -3372,14 +3855,16 @@ function verifySignatureEdge(handler, config) {
|
|
|
3372
3855
|
function verifySignatureAppRouter(handler, config) {
|
|
3373
3856
|
const currentSigningKey = config?.currentSigningKey ?? process.env.QSTASH_CURRENT_SIGNING_KEY;
|
|
3374
3857
|
const nextSigningKey = config?.nextSigningKey ?? process.env.QSTASH_NEXT_SIGNING_KEY;
|
|
3375
|
-
|
|
3858
|
+
const devMode = shouldUseDevelopmentMode(config?.devMode, process.env);
|
|
3859
|
+
if (!devMode && !currentSigningKey && !nextSigningKey && !process.env.QSTASH_REGION) {
|
|
3376
3860
|
throw new Error(
|
|
3377
3861
|
"currentSigningKey and nextSigningKey are required, either in the config or as env variables (QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY)"
|
|
3378
3862
|
);
|
|
3379
3863
|
}
|
|
3380
3864
|
const receiver = new Receiver({
|
|
3381
3865
|
currentSigningKey,
|
|
3382
|
-
nextSigningKey
|
|
3866
|
+
nextSigningKey,
|
|
3867
|
+
devMode: config?.devMode
|
|
3383
3868
|
});
|
|
3384
3869
|
return async (request, params) => {
|
|
3385
3870
|
const requestClone = request.clone();
|
|
@@ -3437,8 +3922,16 @@ var servePagesRouter = (routeFunction, options) => {
|
|
|
3437
3922
|
res.status(response.status).json(await response.json());
|
|
3438
3923
|
};
|
|
3439
3924
|
};
|
|
3925
|
+
async function registerQStashDev() {
|
|
3926
|
+
if (process.env.NODE_ENV === "production")
|
|
3927
|
+
return;
|
|
3928
|
+
if (process.env.NEXT_PHASE === "phase-production-build")
|
|
3929
|
+
return;
|
|
3930
|
+
await ensureDevelopmentServer(void 0, true);
|
|
3931
|
+
}
|
|
3440
3932
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3441
3933
|
0 && (module.exports = {
|
|
3934
|
+
registerQStashDev,
|
|
3442
3935
|
serve,
|
|
3443
3936
|
servePagesRouter,
|
|
3444
3937
|
verifySignature,
|