void 0.21.3 → 0.21.4
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/dist/cli/cli.mjs +6 -6
- package/dist/{db-DzJRn-qz.mjs → db-CTXIWD42.mjs} +1 -1
- package/dist/{deploy-BH0grP4y.mjs → deploy-BVwow28d.mjs} +1 -1
- package/dist/{deploy-CsMJrPfM.mjs → deploy-F1exK5F4.mjs} +47 -3
- package/dist/{email-BRKOG2RG.mjs → email-BxHabktK.mjs} +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +7 -7
- package/skills/void/docs/integrations/cloudflare.md +1 -0
- package/skills/void/docs/reference/cli.md +1 -0
package/dist/cli/cli.mjs
CHANGED
|
@@ -2020,7 +2020,7 @@ if (helpPath) {
|
|
|
2020
2020
|
log.error(formatCloudflareUserMessage(err instanceof Error ? err.message : String(err)));
|
|
2021
2021
|
process.exit(1);
|
|
2022
2022
|
}
|
|
2023
|
-
import("../deploy-
|
|
2023
|
+
import("../deploy-BVwow28d.mjs").then(({ runDeploy }) => {
|
|
2024
2024
|
runDeploy(root, {
|
|
2025
2025
|
projectSlug: deployArgs.projectSlug,
|
|
2026
2026
|
dir: deployArgs.dir,
|
|
@@ -2052,8 +2052,8 @@ else if (command === "cloudflare") runSubcommandGroup("cloudflare", cloudflareSu
|
|
|
2052
2052
|
else if (command === "project") runSubcommandGroup("project", projectSubcommands, parseProjectArgs, (root, parsed) => import("../project-cmd-B44I8J_W.mjs").then(({ runProjectCommand }) => runProjectCommand(root, parsed)));
|
|
2053
2053
|
else if (command === "secret") runSubcommandGroup("secret", secretSubcommands, parseSecretArgs, (root, parsed) => import("../secret-DN9sSNiV.mjs").then(({ runSecretCommand }) => runSecretCommand(root, parsed)));
|
|
2054
2054
|
else if (command === "domain") runSubcommandGroup("domain", domainSubcommands, parseDomainArgs, (root, parsed) => import("../domain-Dmhvb2oU.mjs").then(({ runDomainCommand }) => runDomainCommand(root, parsed)));
|
|
2055
|
-
else if (command === "email") runSubcommandGroup("email", emailSubcommands, parseEmailArgs, (root, parsed) => import("../email-
|
|
2056
|
-
else if (command === "db") runSubcommandGroup("db", dbSubcommands, parseDbArgs, (root, parsed) => import("../db-
|
|
2055
|
+
else if (command === "email") runSubcommandGroup("email", emailSubcommands, parseEmailArgs, (root, parsed) => import("../email-BxHabktK.mjs").then(({ runEmailCommand }) => runEmailCommand(root, parsed)));
|
|
2056
|
+
else if (command === "db") runSubcommandGroup("db", dbSubcommands, parseDbArgs, (root, parsed) => import("../db-CTXIWD42.mjs").then(({ runDbCommand }) => runDbCommand(root, parsed)));
|
|
2057
2057
|
else if (command === "env") runSubcommandGroup("env", envSubcommands, parseEnvArgs, (root, parsed) => import("../env-Csi-tMbT.mjs").then(({ runEnvCommand }) => runEnvCommand(root, parsed)));
|
|
2058
2058
|
else if (command === "gen") runSubcommandGroup("gen", genSubcommands, parseGenArgs, (root, parsed) => import("../gen-Vnv2f65C.mjs").then(({ runGenCommand }) => runGenCommand(root, parsed)));
|
|
2059
2059
|
else if (command === "github") runSubcommandGroup("github", githubSubcommands, parseGithubArgs, (root, parsed) => import("../github-cmd-BED3_9JD.mjs").then(({ runGithubCommand }) => runGithubCommand(root, parsed)));
|
|
@@ -2222,7 +2222,7 @@ else if (command === "prepare") {
|
|
|
2222
2222
|
return;
|
|
2223
2223
|
}
|
|
2224
2224
|
case "deploy": {
|
|
2225
|
-
const { runDeploy } = await import("../deploy-
|
|
2225
|
+
const { runDeploy } = await import("../deploy-BVwow28d.mjs");
|
|
2226
2226
|
await runDeploy(root);
|
|
2227
2227
|
return;
|
|
2228
2228
|
}
|
|
@@ -2235,8 +2235,8 @@ else if (command === "prepare") {
|
|
|
2235
2235
|
case "domain": return runSubcommandGroup("domain", domainSubcommands, parseDomainArgs, (r, p) => import("../domain-Dmhvb2oU.mjs").then(({ runDomainCommand }) => runDomainCommand(r, p)));
|
|
2236
2236
|
case "github": return runSubcommandGroup("github", githubSubcommands, parseGithubArgs, (r, p) => import("../github-cmd-BED3_9JD.mjs").then(({ runGithubCommand }) => runGithubCommand(r, p)));
|
|
2237
2237
|
case "build": return runSubcommandGroup("build", buildSubcommands, parseBuildArgs, (r, p) => import("../build-cmd-Dpt0jd-x.mjs").then(({ runBuildCommand }) => runBuildCommand(r, p)));
|
|
2238
|
-
case "email": return runSubcommandGroup("email", emailSubcommands, parseEmailArgs, (r, p) => import("../email-
|
|
2239
|
-
case "db": return runSubcommandGroup("db", dbSubcommands, parseDbArgs, (r, p) => import("../db-
|
|
2238
|
+
case "email": return runSubcommandGroup("email", emailSubcommands, parseEmailArgs, (r, p) => import("../email-BxHabktK.mjs").then(({ runEmailCommand }) => runEmailCommand(r, p)));
|
|
2239
|
+
case "db": return runSubcommandGroup("db", dbSubcommands, parseDbArgs, (r, p) => import("../db-CTXIWD42.mjs").then(({ runDbCommand }) => runDbCommand(r, p)));
|
|
2240
2240
|
case "env": return runSubcommandGroup("env", envSubcommands, parseEnvArgs, (r, p) => import("../env-Csi-tMbT.mjs").then(({ runEnvCommand }) => runEnvCommand(r, p)));
|
|
2241
2241
|
case "gen": return runSubcommandGroup("gen", genSubcommands, parseGenArgs, (r, p) => import("../gen-Vnv2f65C.mjs").then(({ runGenCommand }) => runGenCommand(r, p)));
|
|
2242
2242
|
case "prepare": {
|
|
@@ -862,7 +862,7 @@ async function runMigrate(root, dialect, remote) {
|
|
|
862
862
|
log.error(getErrorMessage(error));
|
|
863
863
|
process.exit(1);
|
|
864
864
|
}
|
|
865
|
-
const { checkWranglerMigrationApplySet, parseRootWranglerConfig } = await import("./deploy-
|
|
865
|
+
const { checkWranglerMigrationApplySet, parseRootWranglerConfig } = await import("./deploy-BVwow28d.mjs");
|
|
866
866
|
const applySet = await checkWranglerMigrationApplySet(context.operation.configPath, parseRootWranglerConfig(context.operation.configPath), binding, context.migrationsDir, rawMigrations);
|
|
867
867
|
if (!applySet.ok) {
|
|
868
868
|
log.error(applySet.reason);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as parseRootWranglerConfig, J as runDeploy, f as checkWranglerMigrationApplySet } from "./deploy-
|
|
1
|
+
import { A as parseRootWranglerConfig, J as runDeploy, f as checkWranglerMigrationApplySet } from "./deploy-F1exK5F4.mjs";
|
|
2
2
|
export { checkWranglerMigrationApplySet, parseRootWranglerConfig, runDeploy };
|
|
@@ -1885,6 +1885,44 @@ function safePositional(value) {
|
|
|
1885
1885
|
return code < 32 || code === 127;
|
|
1886
1886
|
});
|
|
1887
1887
|
}
|
|
1888
|
+
/** Pin opaque secrets to the live version in the private, disposable Build Output. */
|
|
1889
|
+
async function pinActiveWorkerSecrets(options) {
|
|
1890
|
+
const { activeVersionId, bindings, requiredNames, explicitNames = [] } = options;
|
|
1891
|
+
if (!/^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i.test(activeVersionId)) return false;
|
|
1892
|
+
const secretNames = new Set(bindings.map((binding) => binding.name));
|
|
1893
|
+
const explicit = new Set(explicitNames);
|
|
1894
|
+
if (bindings.some((binding) => !safePositional(binding.name)) || secretNames.size !== bindings.length) return false;
|
|
1895
|
+
if (requiredNames.some((name) => !secretNames.has(name) && !explicit.has(name))) return false;
|
|
1896
|
+
const path = getWorkerConfigPath(options.output.directory);
|
|
1897
|
+
const worker = parseJson(readFileSync(path, "utf8"));
|
|
1898
|
+
if (!record(worker) || worker.env !== void 0 && !record(worker.env)) return false;
|
|
1899
|
+
const env = { ...worker.env ?? {} };
|
|
1900
|
+
for (const name of explicit) delete env[name];
|
|
1901
|
+
for (const [name, value] of Object.entries(env)) if (record(value) && (value.type === "secret" || value.type === "inherit" || value.type === "unsafe:inherit") && !secretNames.has(name) && !explicit.has(name)) return false;
|
|
1902
|
+
for (const { name } of bindings) {
|
|
1903
|
+
if (explicit.has(name)) continue;
|
|
1904
|
+
const current = env[name];
|
|
1905
|
+
if (current !== void 0 && (!record(current) || current.type !== "secret" && current.type !== "inherit" && current.type !== "unsafe:inherit")) return false;
|
|
1906
|
+
env[name] = {
|
|
1907
|
+
type: "unsafe:inherit",
|
|
1908
|
+
version_id: activeVersionId
|
|
1909
|
+
};
|
|
1910
|
+
}
|
|
1911
|
+
const unsafe = record(worker.unsafe) ? { ...worker.unsafe } : {};
|
|
1912
|
+
const metadata = record(unsafe.metadata) ? { ...unsafe.metadata } : {};
|
|
1913
|
+
if (metadata.bindings !== void 0) return false;
|
|
1914
|
+
if (metadata.keep_bindings !== void 0 && (!Array.isArray(metadata.keep_bindings) || !metadata.keep_bindings.every((type) => typeof type === "string"))) return false;
|
|
1915
|
+
metadata.keep_bindings = (metadata.keep_bindings ?? []).filter((type) => type !== "secret_text" && type !== "secret_key");
|
|
1916
|
+
unsafe.metadata = metadata;
|
|
1917
|
+
const next = {
|
|
1918
|
+
...worker,
|
|
1919
|
+
env,
|
|
1920
|
+
unsafe
|
|
1921
|
+
};
|
|
1922
|
+
writeFileSync(path, JSON.stringify(next), { mode: 384 });
|
|
1923
|
+
await readBuildOutput(options.output.directory);
|
|
1924
|
+
return true;
|
|
1925
|
+
}
|
|
1888
1926
|
/** Prevent cf's prebuilt uploader from creating a resource as a side effect. */
|
|
1889
1927
|
function createCfResourceVerifier(options) {
|
|
1890
1928
|
return async (directory) => {
|
|
@@ -7507,6 +7545,13 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7507
7545
|
previousTrafficConfig: readWranglerPublishedTrafficSnapshot(configPath),
|
|
7508
7546
|
queueConsumerCleanup,
|
|
7509
7547
|
verifyInheritedSecrets: true,
|
|
7548
|
+
...cfOutput && existingWorker && !pinnedHandoffLink ? { pinActiveSecrets: (activeVersionId, bindings) => pinActiveWorkerSecrets({
|
|
7549
|
+
output: cfOutput,
|
|
7550
|
+
activeVersionId,
|
|
7551
|
+
bindings,
|
|
7552
|
+
requiredNames: schemaFacts.requiredKeys,
|
|
7553
|
+
...initialAuthSecret ? { explicitNames: [BETTER_AUTH_SECRET_NAME] } : {}
|
|
7554
|
+
}) } : {},
|
|
7510
7555
|
atomic,
|
|
7511
7556
|
...initialAuthSecret ? { candidateSecrets: { [BETTER_AUTH_SECRET_NAME]: initialAuthSecret } } : {}
|
|
7512
7557
|
}).finally(() => cfOutput?.dispose());
|
|
@@ -7581,9 +7626,8 @@ function formatCloudflareActivationError(result) {
|
|
|
7581
7626
|
case "deployment-changed": return result.triggerRepair === "succeeded" ? `deploy: another Cloudflare operation superseded this deployment. Void restored triggers for the active version ${result.activeVersionId ?? "(unknown)"}; retry from fresh deployment status.` : `deploy: another Cloudflare operation superseded this deployment, but its trigger state could not be verified. Inspect the active Worker version ${result.activeVersionId ?? "(unknown)"} immediately.`;
|
|
7582
7627
|
case "inheritance-source-unavailable": return "deploy: could not verify which Worker Version would supply inherited secrets; production traffic is unchanged.";
|
|
7583
7628
|
case "inheritance-source-changed": return [
|
|
7584
|
-
"deploy: the active Worker Version is not the latest upload,
|
|
7585
|
-
"
|
|
7586
|
-
"non-text secret bindings, inspect its active and latest versions in Cloudflare before proceeding.",
|
|
7629
|
+
"deploy: the active Worker Version is not the latest upload, and its secrets could not be pinned safely.",
|
|
7630
|
+
"Inspect the active and latest Worker versions in Cloudflare before retrying.",
|
|
7587
7631
|
"No version was uploaded; production traffic is unchanged."
|
|
7588
7632
|
].join("\n");
|
|
7589
7633
|
case "traffic-preservation-unavailable": return ["deploy: the existing Worker has dashboard-managed routes or visibility that Void cannot safely republish.", "Add its current routes, workers_dev, and preview_urls values to the root Wrangler config, then retry; no version was uploaded."].join("\n");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as join } from "./dist-BVqXeR_h.mjs";
|
|
2
2
|
import { c as import_picocolors, i as createSpinner } from "./output-CCH48AMM.mjs";
|
|
3
|
-
import { L as resolveDeployTransport, O as isWranglerNonInteractiveOrCI, X as runWranglerAuthToken, _ as deriveWorkerName, _t as findEmailConfigConflicts, bt as renderEmailChecklist, gt as createNodeEmailDns, h as createDeployWranglerRunner, ht as applyEmailSetup, k as loadProvisionModule, v as discoverRootWranglerConfig, vt as preflightEmail, yt as renderAddressMap } from "./deploy-
|
|
3
|
+
import { L as resolveDeployTransport, O as isWranglerNonInteractiveOrCI, X as runWranglerAuthToken, _ as deriveWorkerName, _t as findEmailConfigConflicts, bt as renderEmailChecklist, gt as createNodeEmailDns, h as createDeployWranglerRunner, ht as applyEmailSetup, k as loadProvisionModule, v as discoverRootWranglerConfig, vt as preflightEmail, yt as renderAddressMap } from "./deploy-F1exK5F4.mjs";
|
|
4
4
|
import { n as readProjectPaths } from "./project-paths-GgcMozYz.mjs";
|
|
5
5
|
import { c as getToken, d as openBrowser } from "./auth-DLNN0D3Z.mjs";
|
|
6
6
|
import { o as readProjectConfig } from "./project-C0Fqu05O.mjs";
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as __toESM } from "./rolldown-runtime-DXIUcv95.mjs";
|
|
2
2
|
import { a as join, l as relative, n as dirname, u as resolve } from "./dist-BVqXeR_h.mjs";
|
|
3
3
|
import { d as require_picocolors } from "./output-CCH48AMM.mjs";
|
|
4
|
-
import { G as resolveWorkerDirName, St as hasDocumentRoutes, V as resolveDistDir, ct as prerenderPagesNode, dt as collectRevalidate, ft as hasRevalidate, mt as SEND_EMAIL_BINDING, ot as generateQueueResolverSource, pt as scanDurableObjectModules, st as prerenderPages, ut as collectPages, wt as resolveAssetRoutingPolicy, xt as hasApiRoutes } from "./deploy-
|
|
4
|
+
import { G as resolveWorkerDirName, St as hasDocumentRoutes, V as resolveDistDir, ct as prerenderPagesNode, dt as collectRevalidate, ft as hasRevalidate, mt as SEND_EMAIL_BINDING, ot as generateQueueResolverSource, pt as scanDurableObjectModules, st as prerenderPages, ut as collectPages, wt as resolveAssetRoutingPolicy, xt as hasApiRoutes } from "./deploy-F1exK5F4.mjs";
|
|
5
5
|
import { i as resolveProjectPaths, n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-GgcMozYz.mjs";
|
|
6
6
|
import { n as loadVoidAuthConfig, t as findVoidAuthConfig } from "./config-DPByhVck.mjs";
|
|
7
7
|
import { r as scopedAccessCredentials } from "./cf-access-DRsQRe6k.mjs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "void",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.4",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/voidzero-dev/void.git",
|
|
@@ -325,11 +325,11 @@
|
|
|
325
325
|
"@cloudflare/vite-plugin": "1.54.7",
|
|
326
326
|
"@cloudflare/workers-types": "^4.20260702.1",
|
|
327
327
|
"@napi-rs/keyring": "2.0.0",
|
|
328
|
-
"@void/deploy-cloudflare": "0.21.
|
|
329
|
-
"@void/deploy-core": "0.21.
|
|
330
|
-
"@void/edge": "0.21.
|
|
331
|
-
"@void/isr": "0.21.
|
|
332
|
-
"@void/platform": "0.21.
|
|
328
|
+
"@void/deploy-cloudflare": "0.21.4",
|
|
329
|
+
"@void/deploy-core": "0.21.4",
|
|
330
|
+
"@void/edge": "0.21.4",
|
|
331
|
+
"@void/isr": "0.21.4",
|
|
332
|
+
"@void/platform": "0.21.4",
|
|
333
333
|
"acorn": "^8.15.0",
|
|
334
334
|
"better-auth": "^1.7.3",
|
|
335
335
|
"better-sqlite3": "^13.0.3",
|
|
@@ -379,7 +379,7 @@
|
|
|
379
379
|
"zod": "^4.6.1"
|
|
380
380
|
},
|
|
381
381
|
"peerDependencies": {
|
|
382
|
-
"@void/md": "0.21.
|
|
382
|
+
"@void/md": "0.21.4",
|
|
383
383
|
"arktype": ">=2.0.0",
|
|
384
384
|
"valibot": ">=1.0.0-beta.7",
|
|
385
385
|
"vite": "^8.0.0",
|
|
@@ -308,6 +308,7 @@ Custom D1 layouts are supported through `migrations_dir`, `migrations_table`, an
|
|
|
308
308
|
Root `.env` is local-only and is never emitted into Worker vars. Every non-client key declared in `env.ts` is a server value: store it with `void secret put <NAME>`. Void emits required server names through `secrets.required`, rejects plaintext Worker vars with those names, and preserves existing remote secrets.
|
|
309
309
|
|
|
310
310
|
For apps using auth, Void creates a random 32-byte `BETTER_AUTH_SECRET` only when the remote secret is missing. It reuses that value on later deploys. Both auth secrets and schema-marked secrets can be set up on a new Worker's draft before its first upload.
|
|
311
|
+
If an earlier deployment leaves a newer inactive upload, Void pins later uploads to the active version's secret bindings. You do not need to recover the plaintext values from Cloudflare.
|
|
311
312
|
|
|
312
313
|
### Readiness and rollback
|
|
313
314
|
|
|
@@ -995,6 +995,7 @@ Void records provisioned resource IDs in `void.lock.json`. Commit it for other m
|
|
|
995
995
|
`.env` stays local. Store server keys declared in `env.ts` with `void secret put <NAME>`; Void rejects them as plaintext Worker vars. If the first deploy reports missing remote secrets, set them and retry. Custom D1 migration layouts must match the exact files, contents, and order Void validated. Direct deploy and Cloudflare commands use the top-level settings, not named environments or alternate config paths.
|
|
996
996
|
|
|
997
997
|
Existing remote secrets are preserved. Void also preserves or creates `BETTER_AUTH_SECRET` for auth apps.
|
|
998
|
+
If a failed upload leaves a newer inactive version, later deployments inherit secret bindings from the live version without requiring their plaintext values.
|
|
998
999
|
|
|
999
1000
|
**Email.** If the app uses `sendEmail()` or `email/` handlers, set `email.from` in `void.config.ts`. Void shows the Cloudflare account changes and asks before applying them. Later deploys skip the prompt once setup is ready. Without `email.from`, deploy continues without email. For CI, run `void email setup --platform cloudflare` locally and commit `void.lock.json`; pass `--require-email` to fail when email is unavailable. DNS propagation may delay a deploy after setup. See [Email on your own Cloudflare account](../guide/email.md#your-own-cloudflare-account) for setup and recovery.
|
|
1000
1001
|
|