@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/index.js
CHANGED
|
@@ -314,6 +314,9 @@ var formatWorkflowError = (error) => {
|
|
|
314
314
|
|
|
315
315
|
// src/client/utils.ts
|
|
316
316
|
var DEFAULT_BULK_COUNT = 100;
|
|
317
|
+
function serializeLabel(label) {
|
|
318
|
+
return Array.isArray(label) ? label.join(",") : label;
|
|
319
|
+
}
|
|
317
320
|
var isIgnoredHeader = (header) => {
|
|
318
321
|
const lowerCaseHeader = header.toLowerCase();
|
|
319
322
|
return lowerCaseHeader.startsWith("content-type") || lowerCaseHeader.startsWith("upstash-");
|
|
@@ -398,7 +401,7 @@ function processHeaders(request) {
|
|
|
398
401
|
headers.set("Upstash-Flow-Control-Value", controlValue.join(", "));
|
|
399
402
|
}
|
|
400
403
|
if (request.label !== void 0) {
|
|
401
|
-
headers.set("Upstash-Label", request.label);
|
|
404
|
+
headers.set("Upstash-Label", serializeLabel(request.label));
|
|
402
405
|
}
|
|
403
406
|
if (request.redact !== void 0) {
|
|
404
407
|
const redactParts = [];
|
|
@@ -490,17 +493,23 @@ function normalizeCursor(response) {
|
|
|
490
493
|
const cursor = response.cursor;
|
|
491
494
|
return { ...response, cursor: cursor || void 0 };
|
|
492
495
|
}
|
|
496
|
+
function _processGlobal() {
|
|
497
|
+
const proc = globalThis["process"];
|
|
498
|
+
return proc;
|
|
499
|
+
}
|
|
493
500
|
function getRuntime() {
|
|
494
|
-
|
|
495
|
-
|
|
501
|
+
const proc = _processGlobal();
|
|
502
|
+
if (proc?.versions?.bun)
|
|
503
|
+
return `bun@${proc.versions.bun}`;
|
|
496
504
|
if (typeof EdgeRuntime === "string")
|
|
497
505
|
return "edge-light";
|
|
498
|
-
|
|
499
|
-
return `node@${
|
|
506
|
+
if (typeof proc?.version === "string")
|
|
507
|
+
return `node@${proc.version}`;
|
|
500
508
|
return "";
|
|
501
509
|
}
|
|
502
510
|
function getSafeEnvironment() {
|
|
503
|
-
|
|
511
|
+
const proc = _processGlobal();
|
|
512
|
+
return proc?.env ?? {};
|
|
504
513
|
}
|
|
505
514
|
|
|
506
515
|
// src/client/multi-region/utils.ts
|
|
@@ -544,12 +553,453 @@ function normalizeRegionHeader(region) {
|
|
|
544
553
|
return void 0;
|
|
545
554
|
}
|
|
546
555
|
|
|
556
|
+
// src/dev-server/constants.ts
|
|
557
|
+
var DEFAULT_DEV_PORT = 8080;
|
|
558
|
+
var DEV_CREDENTIALS = {
|
|
559
|
+
token: "eyJVc2VySUQiOiJkZWZhdWx0VXNlciIsIlBhc3N3b3JkIjoiZGVmYXVsdFBhc3N3b3JkIn0=",
|
|
560
|
+
currentSigningKey: "sig_7kYjw48mhY7kAjqNGcy6cr29RJ6r",
|
|
561
|
+
nextSigningKey: "sig_5ZB6DVzB1wjE8S6rZ7eenA8Pdnhs"
|
|
562
|
+
};
|
|
563
|
+
var GITHUB_RELEASES_URL = "https://api.github.com/repos/upstash/qstash-cli/releases/latest";
|
|
564
|
+
var BINARY_URL_BASE = "https://artifacts.upstash.com/qstash/versions";
|
|
565
|
+
var CONSOLE_URL = "https://console.upstash.com/qstash/local-mode-user";
|
|
566
|
+
var DEV_PREFIX = "\x1B[2m[QStash Dev]\x1B[0m";
|
|
567
|
+
var CLI_PREFIX = "\x1B[2m[QStash CLI]\x1B[0m";
|
|
568
|
+
var _n = (m) => `node:${m}`;
|
|
569
|
+
var importHttp = () => import(
|
|
570
|
+
/* webpackIgnore: true */
|
|
571
|
+
_n("http")
|
|
572
|
+
);
|
|
573
|
+
var importHttps = () => import(
|
|
574
|
+
/* webpackIgnore: true */
|
|
575
|
+
_n("https")
|
|
576
|
+
);
|
|
577
|
+
var importFs = () => import(
|
|
578
|
+
/* webpackIgnore: true */
|
|
579
|
+
_n("fs")
|
|
580
|
+
);
|
|
581
|
+
var importChildProcess = () => import(
|
|
582
|
+
/* webpackIgnore: true */
|
|
583
|
+
_n("child_process")
|
|
584
|
+
);
|
|
585
|
+
var importOs = () => import(
|
|
586
|
+
/* webpackIgnore: true */
|
|
587
|
+
_n("os")
|
|
588
|
+
);
|
|
589
|
+
|
|
590
|
+
// src/dev-server/http.ts
|
|
591
|
+
var HTTP_OK = 200;
|
|
592
|
+
var HTTP_MULTI_CHOICE = 300;
|
|
593
|
+
var nativeGet = async (url, headers, timeoutMs) => {
|
|
594
|
+
const parsedUrl = new URL(url);
|
|
595
|
+
const httpModule = parsedUrl.protocol === "https:" ? await importHttps() : await importHttp();
|
|
596
|
+
return new Promise((resolve, reject) => {
|
|
597
|
+
const request = httpModule.get(url, { headers }, (response) => {
|
|
598
|
+
const chunks = [];
|
|
599
|
+
response.on("data", (chunk) => chunks.push(chunk));
|
|
600
|
+
response.on("end", () => {
|
|
601
|
+
const statusCode = response.statusCode ?? 0;
|
|
602
|
+
resolve({
|
|
603
|
+
ok: statusCode >= HTTP_OK && statusCode < HTTP_MULTI_CHOICE,
|
|
604
|
+
statusCode,
|
|
605
|
+
body: Buffer.concat(chunks)
|
|
606
|
+
});
|
|
607
|
+
});
|
|
608
|
+
response.on("error", reject);
|
|
609
|
+
});
|
|
610
|
+
if (timeoutMs) {
|
|
611
|
+
request.setTimeout(timeoutMs, () => {
|
|
612
|
+
request.destroy(new Error("Request timed out"));
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
request.on("error", reject);
|
|
616
|
+
});
|
|
617
|
+
};
|
|
618
|
+
|
|
619
|
+
// src/dev-server/health.ts
|
|
620
|
+
var HEALTH_CHECK_TIMEOUT_MS = 2e3;
|
|
621
|
+
var isDevServerRunning = async (baseUrl) => {
|
|
622
|
+
try {
|
|
623
|
+
const { ok: ok4, body } = await nativeGet(
|
|
624
|
+
`${baseUrl}/v2/keys`,
|
|
625
|
+
{ Authorization: `Bearer ${DEV_CREDENTIALS.token}` },
|
|
626
|
+
HEALTH_CHECK_TIMEOUT_MS
|
|
627
|
+
);
|
|
628
|
+
if (!ok4)
|
|
629
|
+
return false;
|
|
630
|
+
const data = JSON.parse(body.toString());
|
|
631
|
+
return data.current === DEV_CREDENTIALS.currentSigningKey && data.next === DEV_CREDENTIALS.nextSigningKey;
|
|
632
|
+
} catch {
|
|
633
|
+
return false;
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
var _didLogUnreachable = false;
|
|
637
|
+
var checkDevServerReachable = async (baseUrl, runtime) => {
|
|
638
|
+
if (await pingEdge(baseUrl))
|
|
639
|
+
return;
|
|
640
|
+
if (!_didLogUnreachable) {
|
|
641
|
+
console.error(unreachableMessage(baseUrl, runtime));
|
|
642
|
+
_didLogUnreachable = true;
|
|
643
|
+
}
|
|
644
|
+
throw new Error(`${DEV_PREFIX} dev server unreachable at ${baseUrl}`);
|
|
645
|
+
};
|
|
646
|
+
var pingEdge = async (baseUrl) => {
|
|
647
|
+
try {
|
|
648
|
+
const controller = new AbortController();
|
|
649
|
+
const timeout = setTimeout(() => {
|
|
650
|
+
controller.abort();
|
|
651
|
+
}, HEALTH_CHECK_TIMEOUT_MS);
|
|
652
|
+
const response = await fetch(`${baseUrl}/v2/keys`, {
|
|
653
|
+
headers: { Authorization: `Bearer ${DEV_CREDENTIALS.token}` },
|
|
654
|
+
signal: controller.signal
|
|
655
|
+
});
|
|
656
|
+
clearTimeout(timeout);
|
|
657
|
+
return response.ok;
|
|
658
|
+
} catch {
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
var unreachableMessage = (baseUrl, runtime) => {
|
|
663
|
+
const port = new URL(baseUrl).port;
|
|
664
|
+
const manualStartCmd = `npx @upstash/qstash-cli dev --port ${port}`;
|
|
665
|
+
const header = `
|
|
666
|
+
${DEV_PREFIX} The dev server is not running at ${baseUrl}.
|
|
667
|
+
|
|
668
|
+
`;
|
|
669
|
+
if (runtime === "cloudflare-workers") {
|
|
670
|
+
return header + `Cloudflare Workers cannot start the dev server automatically.
|
|
671
|
+
Start it manually before running wrangler dev:
|
|
672
|
+
|
|
673
|
+
${manualStartCmd}
|
|
674
|
+
`;
|
|
675
|
+
}
|
|
676
|
+
return header + `Edge runtimes cannot start the dev server automatically.
|
|
677
|
+
Either:
|
|
678
|
+
1. Add the instrumentation hook to start it with your app:
|
|
679
|
+
|
|
680
|
+
// instrumentation.ts
|
|
681
|
+
import { registerQStashDev } from "@upstash/qstash/nextjs";
|
|
682
|
+
export async function register() { await registerQStashDev(); }
|
|
683
|
+
|
|
684
|
+
2. Or start it manually:
|
|
685
|
+
|
|
686
|
+
${manualStartCmd}
|
|
687
|
+
`;
|
|
688
|
+
};
|
|
689
|
+
|
|
690
|
+
// src/dev-server/binary.ts
|
|
691
|
+
var ensureBinary = async () => {
|
|
692
|
+
const fs = await importFs();
|
|
693
|
+
const os = await importOs();
|
|
694
|
+
const cacheDirectory = await findCacheDirectory();
|
|
695
|
+
const isWindows = os.platform() === "win32";
|
|
696
|
+
const binaryName = isWindows ? "qstash.exe" : "qstash";
|
|
697
|
+
const binaryPath = `${cacheDirectory}/${binaryName}`;
|
|
698
|
+
const versionFile = `${cacheDirectory}/.version`;
|
|
699
|
+
let version;
|
|
700
|
+
try {
|
|
701
|
+
version = await fetchLatestVersion();
|
|
702
|
+
} catch (error) {
|
|
703
|
+
if (fs.existsSync(binaryPath)) {
|
|
704
|
+
const cachedVersion = fs.existsSync(versionFile) ? fs.readFileSync(versionFile, "utf8").trim() : "unknown";
|
|
705
|
+
console.log(`${DEV_PREFIX} Offline, using local v${cachedVersion}`);
|
|
706
|
+
return binaryPath;
|
|
707
|
+
}
|
|
708
|
+
throw error;
|
|
709
|
+
}
|
|
710
|
+
return downloadBinary(version, cacheDirectory);
|
|
711
|
+
};
|
|
712
|
+
var fetchLatestVersion = async () => {
|
|
713
|
+
const { ok: ok4, statusCode, body } = await nativeGet(GITHUB_RELEASES_URL, {
|
|
714
|
+
Accept: "application/vnd.github.v3+json",
|
|
715
|
+
"User-Agent": "upstash-qstash-js"
|
|
716
|
+
});
|
|
717
|
+
if (!ok4) {
|
|
718
|
+
throw new Error(`[QStash Dev] Failed to fetch latest version: HTTP ${statusCode}`);
|
|
719
|
+
}
|
|
720
|
+
const data = JSON.parse(body.toString());
|
|
721
|
+
return data.tag_name.replace(/^v/, "");
|
|
722
|
+
};
|
|
723
|
+
var findCacheDirectory = async () => {
|
|
724
|
+
const fs = await importFs();
|
|
725
|
+
const os = await importOs();
|
|
726
|
+
const home = os.homedir();
|
|
727
|
+
const platform = os.platform();
|
|
728
|
+
let base;
|
|
729
|
+
if (platform === "darwin") {
|
|
730
|
+
base = `${home}/Library/Caches/upstash`;
|
|
731
|
+
} else if (platform === "win32") {
|
|
732
|
+
base = `${process.env.LOCALAPPDATA ?? `${home}/AppData/Local`}/upstash`;
|
|
733
|
+
} else {
|
|
734
|
+
base = `${home}/.cache/upstash`;
|
|
735
|
+
}
|
|
736
|
+
const cacheDirectory = `${base}/qstash-dev`;
|
|
737
|
+
await fs.promises.mkdir(cacheDirectory, { recursive: true });
|
|
738
|
+
return cacheDirectory;
|
|
739
|
+
};
|
|
740
|
+
var downloadBinary = async (version, cacheDirectory) => {
|
|
741
|
+
const fs = await importFs();
|
|
742
|
+
const childProcess = await importChildProcess();
|
|
743
|
+
const os = await importOs();
|
|
744
|
+
const osPlatform = os.platform();
|
|
745
|
+
const isWindows = osPlatform === "win32";
|
|
746
|
+
const platform = isWindows ? "windows" : osPlatform === "darwin" ? "darwin" : "linux";
|
|
747
|
+
const arch = os.arch() === "arm64" ? "arm64" : "amd64";
|
|
748
|
+
const archiveName = `qstash-server_${version}_${platform}_${arch}`;
|
|
749
|
+
const binaryName = isWindows ? "qstash.exe" : "qstash";
|
|
750
|
+
const binaryPath = `${cacheDirectory}/${binaryName}`;
|
|
751
|
+
const versionFile = `${cacheDirectory}/.version`;
|
|
752
|
+
if (fs.existsSync(binaryPath) && fs.existsSync(versionFile)) {
|
|
753
|
+
const cachedVersion = fs.readFileSync(versionFile, "utf8").trim();
|
|
754
|
+
if (cachedVersion === version) {
|
|
755
|
+
return binaryPath;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
await fs.promises.rm(cacheDirectory, { recursive: true, force: true });
|
|
759
|
+
await fs.promises.mkdir(cacheDirectory, { recursive: true });
|
|
760
|
+
const extension = isWindows ? "zip" : "tar.gz";
|
|
761
|
+
const archiveUrl = `${BINARY_URL_BASE}/${version}/${archiveName}.${extension}`;
|
|
762
|
+
console.log(`${DEV_PREFIX} Downloading dev server v${version}...`);
|
|
763
|
+
const { ok: ok4, statusCode, body } = await nativeGet(archiveUrl);
|
|
764
|
+
if (!ok4) {
|
|
765
|
+
throw new Error(`[QStash Dev] Failed to download binary: HTTP ${statusCode}`);
|
|
766
|
+
}
|
|
767
|
+
const archivePath = `${cacheDirectory}/${archiveName}.${extension}`;
|
|
768
|
+
await fs.promises.writeFile(archivePath, new Uint8Array(body));
|
|
769
|
+
childProcess.execFileSync("tar", ["-xf", archivePath, "-C", cacheDirectory], {
|
|
770
|
+
stdio: "pipe"
|
|
771
|
+
});
|
|
772
|
+
if (!isWindows) {
|
|
773
|
+
const EXECUTABLE_PERMISSION = 493;
|
|
774
|
+
await fs.promises.chmod(binaryPath, EXECUTABLE_PERMISSION);
|
|
775
|
+
}
|
|
776
|
+
await fs.promises.writeFile(versionFile, version);
|
|
777
|
+
await fs.promises.unlink(archivePath).catch(() => {
|
|
778
|
+
});
|
|
779
|
+
return binaryPath;
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
// src/dev-server/process.ts
|
|
783
|
+
var STARTUP_TIMEOUT_MS = 3e4;
|
|
784
|
+
var _proc = () => {
|
|
785
|
+
return globalThis["process"] ?? {};
|
|
786
|
+
};
|
|
787
|
+
var spawnServer = async (binaryPath, port, onUnexpectedExit) => {
|
|
788
|
+
const childProcess = await importChildProcess();
|
|
789
|
+
const child = await new Promise((resolve, reject) => {
|
|
790
|
+
const child2 = childProcess.spawn(binaryPath, ["dev", "--port", String(port)], {
|
|
791
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
792
|
+
});
|
|
793
|
+
const timeout = setTimeout(() => {
|
|
794
|
+
child2.kill();
|
|
795
|
+
reject(new Error("[QStash Dev] Server failed to start within 30 seconds"));
|
|
796
|
+
}, STARTUP_TIMEOUT_MS);
|
|
797
|
+
let startupOutput = "";
|
|
798
|
+
let started = false;
|
|
799
|
+
const bufferLine = (line) => {
|
|
800
|
+
if (!started)
|
|
801
|
+
startupOutput += `${line}
|
|
802
|
+
`;
|
|
803
|
+
};
|
|
804
|
+
forwardWithPrefix(child2.stdout, _proc().stdout, (line) => {
|
|
805
|
+
bufferLine(line);
|
|
806
|
+
if (!started && /runn+ing( at|\.)/i.test(line)) {
|
|
807
|
+
clearTimeout(timeout);
|
|
808
|
+
started = true;
|
|
809
|
+
resolve(child2);
|
|
810
|
+
}
|
|
811
|
+
});
|
|
812
|
+
forwardWithPrefix(child2.stderr, _proc().stderr, bufferLine);
|
|
813
|
+
child2.on("error", (error) => {
|
|
814
|
+
clearTimeout(timeout);
|
|
815
|
+
reject(new Error(`[QStash Dev] Failed to start server: ${error.message}`));
|
|
816
|
+
});
|
|
817
|
+
child2.on("close", (code, _signal) => {
|
|
818
|
+
if (started) {
|
|
819
|
+
onUnexpectedExit?.();
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
clearTimeout(timeout);
|
|
823
|
+
reject(new Error(formatStartupError(code, startupOutput)));
|
|
824
|
+
});
|
|
825
|
+
});
|
|
826
|
+
registerCleanup(child);
|
|
827
|
+
child.unref?.();
|
|
828
|
+
child.stdout?.unref?.();
|
|
829
|
+
child.stderr?.unref?.();
|
|
830
|
+
};
|
|
831
|
+
var formatStartupError = (code, startupOutput) => {
|
|
832
|
+
const cleaned = startupOutput.replaceAll(/\u001B\[[\d;]*m/g, "").replaceAll(/^\d{1,2}:\d{2}(AM|PM)\s+\w{3}\s+/gm, "").trim();
|
|
833
|
+
if (/address already in use/i.test(cleaned)) {
|
|
834
|
+
const match = /:(\d+)\s*$/.exec(cleaned);
|
|
835
|
+
const portHint = match ? ` on port ${match[1]}` : "";
|
|
836
|
+
return `[QStash Dev] Port already in use${portHint}. Set QSTASH_DEV_PORT to use a different port, or stop the process holding it.`;
|
|
837
|
+
}
|
|
838
|
+
const codeSuffix = code ? ` with code ${code}` : "";
|
|
839
|
+
const detail = cleaned ? `: ${cleaned}` : "";
|
|
840
|
+
return `[QStash Dev] Server exited unexpectedly${codeSuffix}${detail}`;
|
|
841
|
+
};
|
|
842
|
+
var forwardWithPrefix = (source, destination, onLine) => {
|
|
843
|
+
if (!source)
|
|
844
|
+
return;
|
|
845
|
+
let buffer = "";
|
|
846
|
+
const flushLine = (line) => {
|
|
847
|
+
destination?.write(`${CLI_PREFIX} ${line}
|
|
848
|
+
`);
|
|
849
|
+
onLine(line);
|
|
850
|
+
};
|
|
851
|
+
source.on("data", (data) => {
|
|
852
|
+
buffer += data.toString();
|
|
853
|
+
let newlineIndex = buffer.indexOf("\n");
|
|
854
|
+
while (newlineIndex !== -1) {
|
|
855
|
+
flushLine(buffer.slice(0, newlineIndex));
|
|
856
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
857
|
+
newlineIndex = buffer.indexOf("\n");
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
source.on("end", () => {
|
|
861
|
+
if (buffer.length > 0) {
|
|
862
|
+
flushLine(buffer);
|
|
863
|
+
buffer = "";
|
|
864
|
+
}
|
|
865
|
+
});
|
|
866
|
+
source.on("error", () => {
|
|
867
|
+
});
|
|
868
|
+
};
|
|
869
|
+
var currentChild;
|
|
870
|
+
var processHandlersRegistered = false;
|
|
871
|
+
var killCurrentChild = () => {
|
|
872
|
+
if (!currentChild)
|
|
873
|
+
return;
|
|
874
|
+
try {
|
|
875
|
+
currentChild.kill("SIGTERM");
|
|
876
|
+
} catch {
|
|
877
|
+
}
|
|
878
|
+
currentChild = void 0;
|
|
879
|
+
};
|
|
880
|
+
var registerCleanup = (child) => {
|
|
881
|
+
currentChild = child;
|
|
882
|
+
if (!processHandlersRegistered) {
|
|
883
|
+
processHandlersRegistered = true;
|
|
884
|
+
const proc = _proc();
|
|
885
|
+
proc.on?.("exit", killCurrentChild);
|
|
886
|
+
proc.on?.("SIGINT", () => {
|
|
887
|
+
killCurrentChild();
|
|
888
|
+
proc.exit?.(0);
|
|
889
|
+
});
|
|
890
|
+
proc.on?.("SIGTERM", () => {
|
|
891
|
+
killCurrentChild();
|
|
892
|
+
proc.exit?.(0);
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
};
|
|
896
|
+
|
|
897
|
+
// src/dev-server/index.ts
|
|
898
|
+
var _processGlobal2 = () => {
|
|
899
|
+
const proc = globalThis["process"];
|
|
900
|
+
return proc;
|
|
901
|
+
};
|
|
902
|
+
var devServerPromise;
|
|
903
|
+
var ensureDevelopmentServer = (env, devMode) => {
|
|
904
|
+
if (!shouldUseDevelopmentMode(devMode, env))
|
|
905
|
+
return Promise.resolve();
|
|
906
|
+
const procEnv = _processGlobal2()?.env;
|
|
907
|
+
if (procEnv?.NEXT_PHASE === "phase-production-build")
|
|
908
|
+
return Promise.resolve();
|
|
909
|
+
if (procEnv?.NODE_ENV === "production")
|
|
910
|
+
return Promise.resolve();
|
|
911
|
+
const runtime = getRuntime2();
|
|
912
|
+
if (runtime !== "nodejs") {
|
|
913
|
+
return checkDevServerReachable(getDevUrl(env), runtime);
|
|
914
|
+
}
|
|
915
|
+
if (!devServerPromise) {
|
|
916
|
+
devServerPromise = startPipeline(env).catch((error) => {
|
|
917
|
+
devServerPromise = void 0;
|
|
918
|
+
throw error;
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
return devServerPromise;
|
|
922
|
+
};
|
|
923
|
+
var startPipeline = async (env) => {
|
|
924
|
+
const baseUrl = getDevUrl(env);
|
|
925
|
+
const port = new URL(baseUrl).port;
|
|
926
|
+
const consoleLink = `\x1B[36m${CONSOLE_URL}?port=${port}\x1B[0m`;
|
|
927
|
+
if (await isDevServerRunning(baseUrl)) {
|
|
928
|
+
console.log(
|
|
929
|
+
`${DEV_PREFIX} Server already running at ${baseUrl}
|
|
930
|
+
${DEV_PREFIX} Console: ${consoleLink}`
|
|
931
|
+
);
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
const binaryPath = await ensureBinary();
|
|
935
|
+
await spawnServer(binaryPath, port, () => {
|
|
936
|
+
devServerPromise = void 0;
|
|
937
|
+
});
|
|
938
|
+
};
|
|
939
|
+
var shouldUseDevelopmentMode = (devMode, env) => {
|
|
940
|
+
if (devMode !== void 0)
|
|
941
|
+
return devMode;
|
|
942
|
+
const value = env?.QSTASH_DEV ?? getProcessEnvironment("QSTASH_DEV");
|
|
943
|
+
if (value === void 0 || value === "" || value === "false" || value === "0")
|
|
944
|
+
return false;
|
|
945
|
+
if (value === "true" || value === "1")
|
|
946
|
+
return true;
|
|
947
|
+
throw new Error(`[QStash Dev] Invalid value for QSTASH_DEV in environment: ${value}`);
|
|
948
|
+
};
|
|
949
|
+
var getDevelopmentCredentials = (env) => {
|
|
950
|
+
return {
|
|
951
|
+
...DEV_CREDENTIALS,
|
|
952
|
+
baseUrl: getDevUrl(env)
|
|
953
|
+
};
|
|
954
|
+
};
|
|
955
|
+
var getDevUrl = (env) => {
|
|
956
|
+
const portString = env?.QSTASH_DEV_PORT ?? getProcessEnvironment("QSTASH_DEV_PORT");
|
|
957
|
+
let port = DEFAULT_DEV_PORT;
|
|
958
|
+
if (portString) {
|
|
959
|
+
const parsed = Number.parseInt(portString, 10);
|
|
960
|
+
if (!Number.isNaN(parsed) && parsed > 0) {
|
|
961
|
+
port = parsed;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
return `http://127.0.0.1:${port}`;
|
|
965
|
+
};
|
|
966
|
+
var getRuntime2 = () => {
|
|
967
|
+
if (typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers") {
|
|
968
|
+
return "cloudflare-workers";
|
|
969
|
+
}
|
|
970
|
+
const proc = _processGlobal2();
|
|
971
|
+
if (!proc) {
|
|
972
|
+
return "browser";
|
|
973
|
+
}
|
|
974
|
+
if (!proc.release?.name) {
|
|
975
|
+
return "edge";
|
|
976
|
+
}
|
|
977
|
+
return "nodejs";
|
|
978
|
+
};
|
|
979
|
+
var getProcessEnvironment = (key) => {
|
|
980
|
+
const proc = _processGlobal2();
|
|
981
|
+
return proc?.env ? proc.env[key] : void 0;
|
|
982
|
+
};
|
|
983
|
+
|
|
547
984
|
// src/client/multi-region/incoming.ts
|
|
548
985
|
var getReceiverSigningKeys = ({
|
|
549
986
|
environment,
|
|
550
987
|
regionFromHeader,
|
|
551
|
-
config
|
|
988
|
+
config,
|
|
989
|
+
devMode
|
|
552
990
|
}) => {
|
|
991
|
+
if (shouldUseDevelopmentMode(devMode, environment)) {
|
|
992
|
+
if (config?.currentSigningKey || config?.nextSigningKey) {
|
|
993
|
+
console.warn(
|
|
994
|
+
`${DEV_PREFIX} Dev mode is active. Ignoring signing keys from config. Set devMode: false to use your own keys.`
|
|
995
|
+
);
|
|
996
|
+
}
|
|
997
|
+
const developmentCreds = getDevelopmentCredentials(environment);
|
|
998
|
+
return {
|
|
999
|
+
currentSigningKey: developmentCreds.currentSigningKey,
|
|
1000
|
+
nextSigningKey: developmentCreds.nextSigningKey
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
553
1003
|
if (config?.currentSigningKey && config.nextSigningKey) {
|
|
554
1004
|
return {
|
|
555
1005
|
currentSigningKey: config.currentSigningKey,
|
|
@@ -594,8 +1044,21 @@ var getClientCredentials = (clientCredentialConfig) => {
|
|
|
594
1044
|
};
|
|
595
1045
|
var resolveCredentials = ({
|
|
596
1046
|
environment,
|
|
597
|
-
config
|
|
1047
|
+
config,
|
|
1048
|
+
devMode
|
|
598
1049
|
}) => {
|
|
1050
|
+
if (shouldUseDevelopmentMode(devMode, environment)) {
|
|
1051
|
+
if (config?.baseUrl || config?.token) {
|
|
1052
|
+
console.warn(
|
|
1053
|
+
`${DEV_PREFIX} Dev mode is active. Ignoring baseUrl/token from config. Set devMode: false to use your own credentials.`
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1056
|
+
const developmentCreds = getDevelopmentCredentials(environment);
|
|
1057
|
+
return {
|
|
1058
|
+
baseUrl: developmentCreds.baseUrl,
|
|
1059
|
+
token: developmentCreds.token
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
599
1062
|
if (config?.baseUrl && config.token) {
|
|
600
1063
|
return {
|
|
601
1064
|
baseUrl: config.baseUrl,
|
|
@@ -648,9 +1111,11 @@ var SignatureError = class extends Error {
|
|
|
648
1111
|
var Receiver = class {
|
|
649
1112
|
currentSigningKey;
|
|
650
1113
|
nextSigningKey;
|
|
1114
|
+
devMode;
|
|
651
1115
|
constructor(config) {
|
|
652
1116
|
this.currentSigningKey = config?.currentSigningKey;
|
|
653
1117
|
this.nextSigningKey = config?.nextSigningKey;
|
|
1118
|
+
this.devMode = config?.devMode;
|
|
654
1119
|
}
|
|
655
1120
|
/**
|
|
656
1121
|
* Verify the signature of a request.
|
|
@@ -669,7 +1134,8 @@ var Receiver = class {
|
|
|
669
1134
|
config: {
|
|
670
1135
|
currentSigningKey: this.currentSigningKey,
|
|
671
1136
|
nextSigningKey: this.nextSigningKey
|
|
672
|
-
}
|
|
1137
|
+
},
|
|
1138
|
+
devMode: this.devMode
|
|
673
1139
|
});
|
|
674
1140
|
if (!signingKeys) {
|
|
675
1141
|
throw new Error(
|
|
@@ -935,12 +1401,14 @@ var HttpClient = class {
|
|
|
935
1401
|
baseUrl;
|
|
936
1402
|
authorization;
|
|
937
1403
|
options;
|
|
1404
|
+
devMode;
|
|
938
1405
|
retry;
|
|
939
1406
|
headers;
|
|
940
1407
|
telemetryHeaders;
|
|
941
1408
|
constructor(config) {
|
|
942
1409
|
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
943
1410
|
this.authorization = config.authorization;
|
|
1411
|
+
this.devMode = config.devMode;
|
|
944
1412
|
this.retry = // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
945
1413
|
typeof config.retry === "boolean" && !config.retry ? {
|
|
946
1414
|
attempts: 1,
|
|
@@ -953,6 +1421,7 @@ var HttpClient = class {
|
|
|
953
1421
|
this.telemetryHeaders = config.telemetryHeaders;
|
|
954
1422
|
}
|
|
955
1423
|
async request(request) {
|
|
1424
|
+
await ensureDevelopmentServer(void 0, this.devMode);
|
|
956
1425
|
const { response } = await this.requestWithBackoff(request);
|
|
957
1426
|
if (request.parseResponseAsJson === false) {
|
|
958
1427
|
return void 0;
|
|
@@ -960,6 +1429,7 @@ var HttpClient = class {
|
|
|
960
1429
|
return await response.json();
|
|
961
1430
|
}
|
|
962
1431
|
async *requestStream(request) {
|
|
1432
|
+
await ensureDevelopmentServer(void 0, this.devMode);
|
|
963
1433
|
const { response } = await this.requestWithBackoff(request);
|
|
964
1434
|
if (!response.body) {
|
|
965
1435
|
throw new Error("No response body");
|
|
@@ -1713,7 +2183,7 @@ var Workflow = class {
|
|
|
1713
2183
|
};
|
|
1714
2184
|
|
|
1715
2185
|
// version.ts
|
|
1716
|
-
var VERSION = "2.
|
|
2186
|
+
var VERSION = "2.11.1";
|
|
1717
2187
|
|
|
1718
2188
|
// src/client/client.ts
|
|
1719
2189
|
var Client = class {
|
|
@@ -1721,7 +2191,14 @@ var Client = class {
|
|
|
1721
2191
|
token;
|
|
1722
2192
|
constructor(config) {
|
|
1723
2193
|
const environment = getSafeEnvironment();
|
|
1724
|
-
const { baseUrl, token } = getClientCredentials({
|
|
2194
|
+
const { baseUrl, token } = getClientCredentials({
|
|
2195
|
+
environment,
|
|
2196
|
+
config,
|
|
2197
|
+
devMode: config?.devMode
|
|
2198
|
+
});
|
|
2199
|
+
if (shouldUseDevelopmentMode(config?.devMode, environment)) {
|
|
2200
|
+
void ensureDevelopmentServer(environment, config?.devMode);
|
|
2201
|
+
}
|
|
1725
2202
|
const enableTelemetry = environment.UPSTASH_DISABLE_TELEMETRY ? false : config?.enableTelemetry ?? true;
|
|
1726
2203
|
const isCloudflare = typeof caches !== "undefined" && "default" in caches;
|
|
1727
2204
|
const telemetryHeaders = new Headers(
|
|
@@ -1738,7 +2215,8 @@ var Client = class {
|
|
|
1738
2215
|
//@ts-expect-error caused by undici and bunjs type overlap
|
|
1739
2216
|
headers: prefixHeaders(new Headers(config?.headers ?? {})),
|
|
1740
2217
|
//@ts-expect-error caused by undici and bunjs type overlap
|
|
1741
|
-
telemetryHeaders
|
|
2218
|
+
telemetryHeaders,
|
|
2219
|
+
devMode: config?.devMode
|
|
1742
2220
|
});
|
|
1743
2221
|
this.token = token;
|
|
1744
2222
|
}
|
package/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resend
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ATX5KA4T.mjs";
|
|
4
4
|
import {
|
|
5
5
|
Chat,
|
|
6
6
|
Client,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
openai,
|
|
25
25
|
setupAnalytics,
|
|
26
26
|
upstash
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-T3Z5YUS4.mjs";
|
|
28
28
|
export {
|
|
29
29
|
Chat,
|
|
30
30
|
Client,
|
package/nextjs.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextApiHandler } from 'next';
|
|
2
2
|
import { NextRequest, NextFetchEvent } from 'next/server';
|
|
3
|
-
import { ae as RouteFunction, af as WorkflowServeOptions } from './client-
|
|
3
|
+
import { ae as RouteFunction, af as WorkflowServeOptions } from './client-BHOXiX0H.mjs';
|
|
4
4
|
import 'neverthrow';
|
|
5
5
|
|
|
6
6
|
type VerifySignatureConfig = {
|
|
@@ -18,6 +18,17 @@ type VerifySignatureConfig = {
|
|
|
18
18
|
* @default 0
|
|
19
19
|
*/
|
|
20
20
|
clockTolerance?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Use the local dev server signing keys. Pair this with
|
|
23
|
+
* `new Client({ devMode: true })` for end-to-end local development.
|
|
24
|
+
*
|
|
25
|
+
* - `true`: use dev server signing keys
|
|
26
|
+
* - `false`: never use dev server signing keys (ignores QSTASH_DEV env var)
|
|
27
|
+
* - `undefined`: check QSTASH_DEV env var
|
|
28
|
+
*
|
|
29
|
+
* @default undefined
|
|
30
|
+
*/
|
|
31
|
+
devMode?: boolean;
|
|
21
32
|
};
|
|
22
33
|
declare function verifySignature(handler: NextApiHandler, config?: VerifySignatureConfig): NextApiHandler;
|
|
23
34
|
declare function verifySignatureEdge(handler: (request: NextRequest, nfe?: NextFetchEvent) => Response | Promise<Response>, config?: VerifySignatureConfig): (request: NextRequest, nfe: NextFetchEvent) => Promise<Response>;
|
|
@@ -43,5 +54,25 @@ declare const serve: <TInitialPayload = unknown>(routeFunction: RouteFunction<TI
|
|
|
43
54
|
* Migration Guide: https://upstash.com/docs/workflow/migration
|
|
44
55
|
*/
|
|
45
56
|
declare const servePagesRouter: <TInitialPayload = unknown>(routeFunction: RouteFunction<TInitialPayload>, options?: Omit<WorkflowServeOptions<Response, TInitialPayload>, "onStepFinish">) => NextApiHandler;
|
|
57
|
+
/**
|
|
58
|
+
* Start the QStash dev server early during Next.js initialization.
|
|
59
|
+
*
|
|
60
|
+
* Call this inside your `instrumentation.ts` `register()` function so
|
|
61
|
+
* the dev server is ready before any request — including edge routes
|
|
62
|
+
* that cannot start it themselves.
|
|
63
|
+
*
|
|
64
|
+
* No-op in production, during `next build`, or in edge runtime.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* // instrumentation.ts
|
|
69
|
+
* import { registerQStashDev } from "@upstash/qstash/nextjs";
|
|
70
|
+
*
|
|
71
|
+
* export function register() {
|
|
72
|
+
* registerQStashDev();
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
declare function registerQStashDev(): Promise<void>;
|
|
46
77
|
|
|
47
|
-
export { type VerifySignatureConfig, serve, servePagesRouter, verifySignature, verifySignatureAppRouter, verifySignatureEdge };
|
|
78
|
+
export { type VerifySignatureConfig, registerQStashDev, serve, servePagesRouter, verifySignature, verifySignatureAppRouter, verifySignatureEdge };
|