void 0.21.5 → 0.21.6

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 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-CmePjn6m.mjs").then(({ runDeploy }) => {
2023
+ import("../deploy-f1j5MyEP.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-CYq8VQ96.mjs").then(({ runEmailCommand }) => runEmailCommand(root, parsed)));
2056
- else if (command === "db") runSubcommandGroup("db", dbSubcommands, parseDbArgs, (root, parsed) => import("../db-BAJbaEVn.mjs").then(({ runDbCommand }) => runDbCommand(root, parsed)));
2055
+ else if (command === "email") runSubcommandGroup("email", emailSubcommands, parseEmailArgs, (root, parsed) => import("../email-BXBtqadx.mjs").then(({ runEmailCommand }) => runEmailCommand(root, parsed)));
2056
+ else if (command === "db") runSubcommandGroup("db", dbSubcommands, parseDbArgs, (root, parsed) => import("../db-CyHAAGkK.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-CmePjn6m.mjs");
2225
+ const { runDeploy } = await import("../deploy-f1j5MyEP.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-CYq8VQ96.mjs").then(({ runEmailCommand }) => runEmailCommand(r, p)));
2239
- case "db": return runSubcommandGroup("db", dbSubcommands, parseDbArgs, (r, p) => import("../db-BAJbaEVn.mjs").then(({ runDbCommand }) => runDbCommand(r, p)));
2238
+ case "email": return runSubcommandGroup("email", emailSubcommands, parseEmailArgs, (r, p) => import("../email-BXBtqadx.mjs").then(({ runEmailCommand }) => runEmailCommand(r, p)));
2239
+ case "db": return runSubcommandGroup("db", dbSubcommands, parseDbArgs, (r, p) => import("../db-CyHAAGkK.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-CmePjn6m.mjs");
865
+ const { checkWranglerMigrationApplySet, parseRootWranglerConfig } = await import("./deploy-f1j5MyEP.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);
@@ -57,7 +57,7 @@ import { applyEdits, modify, parse } from "jsonc-parser";
57
57
  import { isDeepStrictEqual } from "node:util";
58
58
  import { Minimatch } from "minimatch";
59
59
  import { activateCloudflareVersion, assertCloudflareBindingsPreserved, assertCloudflareDurableObjectLifecycleSupported, assertExistingCloudflareConfig, encodeCloudflareVersionMessage, extractWorkersDevSubdomain, normalizeWorkersDevSubdomain, parseRootWranglerConfig, parseRootWranglerConfig as parseRootWranglerConfig$1, readBindingFieldPresence, readCloudflareTriggerConfig, readConfigEntryString, readExistingCloudflareWorker, readStoredResourceName, readWranglerTopLevelString, renderCloudflareStaticEntry, resolveD1MigrateTarget, stageCloudflareStaticAssets, writeCloudflareFrameworkDeployConfig, writeCloudflareStaticDeployConfig } from "@void/deploy-cloudflare";
60
- import { getWorkerConfigPath, readBuildOutput } from "@cloudflare/build-output-utils";
60
+ import { getWorkerAssetsDir, getWorkerBundleDir, getWorkerConfigPath, readBuildOutput } from "@cloudflare/build-output-utils";
61
61
  import ignore from "ignore";
62
62
  import { hash } from "blake3-jit";
63
63
  //#region src/asset-routing.ts
@@ -1857,6 +1857,321 @@ async function prerenderPagesNode(options) {
1857
1857
  return result;
1858
1858
  }
1859
1859
  //#endregion
1860
+ //#region src/cli/cf-version-api.ts
1861
+ function object(value) {
1862
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
1863
+ }
1864
+ function requiredString(value, label) {
1865
+ if (typeof value !== "string" || !value) throw new Error(`The Cloudflare ${label} is missing from the verified Worker output.`);
1866
+ return value;
1867
+ }
1868
+ function textValue(value, label) {
1869
+ if (typeof value !== "string") throw new Error(`The Cloudflare ${label} is missing from the verified Worker output.`);
1870
+ return value;
1871
+ }
1872
+ const moduleContentTypes = {
1873
+ esm: "application/javascript+module",
1874
+ cjs: "application/javascript",
1875
+ wasm: "application/wasm",
1876
+ text: "text/plain",
1877
+ data: "application/octet-stream",
1878
+ json: "text/plain",
1879
+ sourcemap: "application/source-map"
1880
+ };
1881
+ function bindingsFromOutput(env, workerName, activeSecrets, explicitSecrets) {
1882
+ const inherited = new Map(activeSecrets.bindings.map((binding) => [binding.name, binding.type]));
1883
+ const names = /* @__PURE__ */ new Set([
1884
+ ...Object.keys(env),
1885
+ ...inherited.keys(),
1886
+ ...Object.keys(explicitSecrets)
1887
+ ]);
1888
+ const bindings = [];
1889
+ for (const name of names) {
1890
+ const value = object(env[name]);
1891
+ const explicit = explicitSecrets[name];
1892
+ if (explicit !== void 0) {
1893
+ if (typeof explicit !== "string" || inherited.get(name) === "secret_key" || value && value.type !== "secret") throw new Error(`Cloudflare secret ${name} has an invalid explicit value or binding.`);
1894
+ bindings.push({
1895
+ name,
1896
+ type: "secret_text",
1897
+ text: explicit
1898
+ });
1899
+ continue;
1900
+ }
1901
+ if (inherited.has(name)) {
1902
+ if (value && ![
1903
+ "secret",
1904
+ "inherit",
1905
+ "unsafe:inherit"
1906
+ ].includes(String(value.type))) throw new Error(`Cloudflare secret ${name} conflicts with a Worker binding.`);
1907
+ bindings.push({
1908
+ name,
1909
+ type: "inherit",
1910
+ version_id: activeSecrets.versionId
1911
+ });
1912
+ continue;
1913
+ }
1914
+ if (!value) throw new Error(`Cloudflare binding ${name} is missing from the Worker output.`);
1915
+ switch (value.type) {
1916
+ case "text":
1917
+ bindings.push({
1918
+ name,
1919
+ type: "plain_text",
1920
+ text: textValue(value.value, name)
1921
+ });
1922
+ break;
1923
+ case "json":
1924
+ bindings.push({
1925
+ name,
1926
+ type: "json",
1927
+ json: value.value
1928
+ });
1929
+ break;
1930
+ case "kv":
1931
+ bindings.push({
1932
+ name,
1933
+ type: "kv_namespace",
1934
+ namespace_id: requiredString(value.id, name)
1935
+ });
1936
+ break;
1937
+ case "d1":
1938
+ bindings.push({
1939
+ name,
1940
+ type: "d1",
1941
+ database_id: requiredString(value.id, name)
1942
+ });
1943
+ break;
1944
+ case "r2":
1945
+ bindings.push({
1946
+ name,
1947
+ type: "r2_bucket",
1948
+ bucket_name: requiredString(value.name, name),
1949
+ ...value.jurisdiction ? { jurisdiction: value.jurisdiction } : {}
1950
+ });
1951
+ break;
1952
+ case "durable-object":
1953
+ bindings.push({
1954
+ name,
1955
+ type: "durable_object_namespace",
1956
+ class_name: requiredString(value.exportName, name),
1957
+ ...value.worker !== workerName ? { script_name: requiredString(value.worker, name) } : {}
1958
+ });
1959
+ break;
1960
+ case "assets":
1961
+ bindings.push({
1962
+ name,
1963
+ type: "assets"
1964
+ });
1965
+ break;
1966
+ default: throw new Error(`Cloudflare binding ${name} cannot be uploaded with pinned secrets.`);
1967
+ }
1968
+ }
1969
+ return bindings;
1970
+ }
1971
+ function exportsFromOutput(exports) {
1972
+ if (exports === void 0) return;
1973
+ const entries = object(exports);
1974
+ if (!entries) throw new Error("Cloudflare Durable Object exports were not readable.");
1975
+ const result = {};
1976
+ for (const [name, raw] of Object.entries(entries)) {
1977
+ const value = object(raw);
1978
+ if (!value || value.type !== "durable-object") throw new Error(`Cloudflare export ${name} cannot be uploaded with pinned secrets.`);
1979
+ if (value.state === "deleted") result[name] = {
1980
+ type: "durable-object",
1981
+ state: "deleted"
1982
+ };
1983
+ else if (value.storage === "sqlite" || value.storage === "legacy-kv") result[name] = {
1984
+ type: "durable-object",
1985
+ storage: value.storage,
1986
+ state: "created"
1987
+ };
1988
+ else throw new Error(`Cloudflare Durable Object export ${name} has no storage type.`);
1989
+ }
1990
+ return result;
1991
+ }
1992
+ function assetConfigFromOutput(value) {
1993
+ if (value === void 0) return;
1994
+ const config = object(value);
1995
+ if (!config) throw new Error("Cloudflare asset configuration was not readable.");
1996
+ const supported = /* @__PURE__ */ new Set([
1997
+ "basePath",
1998
+ "htmlHandling",
1999
+ "notFoundHandling",
2000
+ "runWorkerFirst"
2001
+ ]);
2002
+ if (Object.keys(config).some((key) => !supported.has(key))) throw new Error("Cloudflare asset configuration has an unsupported setting.");
2003
+ return {
2004
+ ...config.basePath === void 0 ? {} : { base_path: config.basePath },
2005
+ ...config.htmlHandling === void 0 ? {} : { html_handling: config.htmlHandling },
2006
+ ...config.notFoundHandling === void 0 ? {} : { not_found_handling: config.notFoundHandling },
2007
+ ...config.runWorkerFirst === void 0 ? {} : { run_worker_first: config.runWorkerFirst }
2008
+ };
2009
+ }
2010
+ async function apiResult(url, token, method, body, verifyUploader, timeout = 12e4) {
2011
+ if (!verifyUploader()) throw new Error("The Cloudflare uploader changed during deployment.");
2012
+ const form = body instanceof FormData;
2013
+ const response = await fetch(url, {
2014
+ method,
2015
+ headers: {
2016
+ Authorization: `Bearer ${token}`,
2017
+ ...body && !form ? { "Content-Type": "application/json" } : {}
2018
+ },
2019
+ ...body ? { body: form ? body : JSON.stringify(body) } : {},
2020
+ redirect: "manual",
2021
+ signal: AbortSignal.timeout(timeout)
2022
+ });
2023
+ const parsed = object(await response.json());
2024
+ const result = object(parsed?.result);
2025
+ if (!response.ok || parsed?.success !== true || !result) {
2026
+ const error = Array.isArray(parsed?.errors) ? object(parsed.errors[0]) : null;
2027
+ const code = Number.isSafeInteger(error?.code) ? ` [code: ${error.code}]` : "";
2028
+ const message = typeof error?.message === "string" ? ` ${error.message}` : "";
2029
+ throw new Error(`Cloudflare version upload failed (${response.status})${code}.${message}`);
2030
+ }
2031
+ return result;
2032
+ }
2033
+ async function uploadAssets(options) {
2034
+ if (!options.output.assetsDirectory) return;
2035
+ const directory = getWorkerAssetsDir(options.output.directory);
2036
+ const manifest = {};
2037
+ const byHash = /* @__PURE__ */ new Map();
2038
+ const ignored = ignore().add([
2039
+ "/.assetsignore",
2040
+ "/_headers",
2041
+ "/_redirects",
2042
+ ".DS_Store",
2043
+ ".env",
2044
+ ".env.*",
2045
+ ".dev.vars",
2046
+ ".dev.vars.*"
2047
+ ]);
2048
+ const ignorePath = join(directory, ".assetsignore");
2049
+ try {
2050
+ ignored.add(readFileSync(ignorePath, "utf8"));
2051
+ } catch (cause) {
2052
+ if (!(cause instanceof Error && "code" in cause && cause.code === "ENOENT")) throw cause;
2053
+ }
2054
+ for (const entry of readdirSync(directory, {
2055
+ recursive: true,
2056
+ withFileTypes: true
2057
+ })) {
2058
+ if (entry.isDirectory()) continue;
2059
+ if (!entry.isFile()) throw new Error("The Cloudflare asset output contains an unsupported entry.");
2060
+ const path = join(entry.parentPath, entry.name);
2061
+ const relativeName = relative(directory, path).replaceAll("\\", "/");
2062
+ if (ignored.ignores(relativeName)) continue;
2063
+ const name = `/${relativeName}`;
2064
+ const content = readFileSync(path);
2065
+ const extension = extname(entry.name).slice(1);
2066
+ const hash = createHash("sha256").update(content.toString("base64") + extension).digest("hex").slice(0, 32);
2067
+ manifest[name] = {
2068
+ hash,
2069
+ size: content.length
2070
+ };
2071
+ byHash.set(hash, path);
2072
+ }
2073
+ const session = await apiResult(`${options.accountUrl}/workers/scripts/${encodeURIComponent(options.workerName)}/assets-upload-session`, options.token, "POST", { manifest }, options.verifyUploader);
2074
+ let jwt = requiredString(session.jwt, "asset upload token");
2075
+ if (!Array.isArray(session.buckets)) throw new Error("Cloudflare did not provide asset upload batches.");
2076
+ for (const bucket of session.buckets) {
2077
+ if (!Array.isArray(bucket) || !bucket.every((hash) => typeof hash === "string")) throw new Error("Cloudflare returned an invalid asset upload batch.");
2078
+ const form = new FormData();
2079
+ for (const hash of bucket) {
2080
+ const path = byHash.get(hash);
2081
+ if (!path) throw new Error("Cloudflare requested an asset outside the verified Worker output.");
2082
+ form.append(hash, readFileSync(path).toString("base64"));
2083
+ }
2084
+ jwt = requiredString((await apiResult(`${options.accountUrl}/workers/assets/upload?base64=true`, jwt, "POST", form, options.verifyUploader)).jwt, "asset completion token");
2085
+ }
2086
+ return jwt;
2087
+ }
2088
+ /** The Workers beta API is the only upload endpoint that accepts a version UUID as an inheritance source. */
2089
+ async function uploadPinnedCloudflareVersion(options) {
2090
+ const activeSecrets = options.output.activeSecrets;
2091
+ if (!activeSecrets) throw new Error("The active Worker secret source was not verified.");
2092
+ const config = (await readBuildOutput(options.output.directory)).workers.default.config;
2093
+ if (config.name !== options.workerName || !config.manifest || config.manifest.type !== "complete") throw new Error("The verified Cloudflare Worker output changed before upload.");
2094
+ const unsupported = Object.keys(config).filter((key) => !(/* @__PURE__ */ new Set([
2095
+ "name",
2096
+ "compatibilityDate",
2097
+ "compatibilityFlags",
2098
+ "assets",
2099
+ "domains",
2100
+ "observability",
2101
+ "workersDev",
2102
+ "previewUrls",
2103
+ "unsafe",
2104
+ "env",
2105
+ "exports",
2106
+ "manifest",
2107
+ "triggers"
2108
+ ])).has(key));
2109
+ if (unsupported.length) throw new Error(`Cloudflare Worker setting ${unsupported[0]} cannot be uploaded with pinned secrets.`);
2110
+ const unsafe = object(config.unsafe);
2111
+ const metadata = object(unsafe?.metadata);
2112
+ if (unsafe && Object.keys(unsafe).some((key) => key !== "metadata") || metadata && Object.keys(metadata).some((key) => key !== "keep_bindings") || metadata?.keep_bindings !== void 0 && (!Array.isArray(metadata.keep_bindings) || !metadata.keep_bindings.every((type) => typeof type === "string"))) throw new Error("Cloudflare Worker upload metadata has an unsupported setting.");
2113
+ const explicitSecrets = options.secretsFilePath ? object(JSON.parse(readFileSync(options.secretsFilePath, "utf8"))) : {};
2114
+ if (!explicitSecrets) throw new Error("The explicit Cloudflare secrets file was not readable.");
2115
+ const bindings = bindingsFromOutput(config.env ?? {}, options.workerName, activeSecrets, explicitSecrets);
2116
+ const active = await apiResult(`${options.apiBaseUrl.replace(/\/$/, "")}/accounts/${encodeURIComponent(options.accountId)}/workers/workers/${encodeURIComponent(options.workerName)}/versions/${encodeURIComponent(activeSecrets.versionId)}`, options.token, "GET", void 0, options.verifyUploader);
2117
+ if (active.id !== activeSecrets.versionId || !Array.isArray(active.bindings)) throw new Error("The active Cloudflare Worker bindings could not be verified.");
2118
+ const activeBindingNames = /* @__PURE__ */ new Set();
2119
+ const candidateNames = new Set(bindings.map((binding) => String(binding.name)));
2120
+ const keptTypes = new Set(metadata?.keep_bindings ?? []);
2121
+ for (const entry of active.bindings) {
2122
+ const binding = object(entry);
2123
+ if (!binding || typeof binding.name !== "string" || typeof binding.type !== "string") throw new Error("The active Cloudflare Worker bindings could not be verified.");
2124
+ activeBindingNames.add(binding.name);
2125
+ if (!candidateNames.has(binding.name) && keptTypes.has(binding.type) && ["plain_text", "json"].includes(binding.type)) {
2126
+ bindings.push({
2127
+ name: binding.name,
2128
+ type: "inherit",
2129
+ version_id: activeSecrets.versionId
2130
+ });
2131
+ candidateNames.add(binding.name);
2132
+ }
2133
+ }
2134
+ if (activeSecrets.bindings.some(({ name }) => !activeBindingNames.has(name))) throw new Error("The active Cloudflare Worker secrets changed before upload.");
2135
+ const exports = exportsFromOutput(config.exports);
2136
+ const assetConfig = assetConfigFromOutput(config.assets);
2137
+ if (bindings.some((binding) => binding.type === "assets") && !options.output.assetsDirectory) throw new Error("The Cloudflare Worker has an assets binding without verified assets.");
2138
+ const modules = [];
2139
+ for (const [name, entry] of Object.entries(config.manifest.modules)) {
2140
+ const type = moduleContentTypes[entry.type];
2141
+ if (!type || name.startsWith("/") || name.split("/").includes("..")) throw new Error(`Cloudflare Worker module ${name} cannot be uploaded with pinned secrets.`);
2142
+ modules.push({
2143
+ name,
2144
+ content_type: type,
2145
+ content_base64: readFileSync(join(getWorkerBundleDir(options.output.directory), name)).toString("base64")
2146
+ });
2147
+ }
2148
+ const accountUrl = `${options.apiBaseUrl.replace(/\/$/, "")}/accounts/${encodeURIComponent(options.accountId)}`;
2149
+ const jwt = await uploadAssets({
2150
+ output: options.output,
2151
+ accountUrl,
2152
+ workerName: options.workerName,
2153
+ token: options.token,
2154
+ verifyUploader: options.verifyUploader
2155
+ });
2156
+ const uploaded = await apiResult(`${accountUrl}/workers/workers/${encodeURIComponent(options.workerName)}/versions${options.atomic ? "?deploy=true" : ""}`, options.token, "POST", {
2157
+ main_module: config.manifest.mainModule,
2158
+ modules,
2159
+ compatibility_date: config.compatibilityDate,
2160
+ compatibility_flags: config.compatibilityFlags,
2161
+ bindings,
2162
+ ...exports ? { exports } : {},
2163
+ ...jwt ? { assets: {
2164
+ jwt,
2165
+ ...assetConfig ? { config: assetConfig } : {}
2166
+ } } : {},
2167
+ annotations: { "workers/message": options.message ?? "" }
2168
+ }, options.verifyUploader);
2169
+ return {
2170
+ id: requiredString(uploaded.id, "Worker Version ID"),
2171
+ urls: Array.isArray(uploaded.urls) ? uploaded.urls.filter((url) => typeof url === "string") : []
2172
+ };
2173
+ }
2174
+ //#endregion
1860
2175
  //#region src/cli/cf-version-runner.ts
1861
2176
  function failed(message) {
1862
2177
  return {
@@ -1897,7 +2212,7 @@ function createActiveSecretPinner(options) {
1897
2212
  explicitNames: options.explicitNames
1898
2213
  });
1899
2214
  }
1900
- /** Pin opaque secrets to the live version in the private, disposable Build Output. */
2215
+ /** Record the live secret source for the version-aware API uploader. */
1901
2216
  async function pinActiveWorkerSecrets(options) {
1902
2217
  const { activeVersionId, bindings, requiredNames, explicitNames = [] } = options;
1903
2218
  if (!/^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i.test(activeVersionId)) return false;
@@ -1908,31 +2223,17 @@ async function pinActiveWorkerSecrets(options) {
1908
2223
  const path = getWorkerConfigPath(options.output.directory);
1909
2224
  const worker = parseJson(readFileSync(path, "utf8"));
1910
2225
  if (!record(worker) || worker.env !== void 0 && !record(worker.env)) return false;
1911
- const env = { ...worker.env ?? {} };
1912
- for (const name of explicit) delete env[name];
2226
+ const env = worker.env ?? {};
1913
2227
  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;
1914
2228
  for (const { name } of bindings) {
1915
2229
  if (explicit.has(name)) continue;
1916
2230
  const current = env[name];
1917
2231
  if (current !== void 0 && (!record(current) || current.type !== "secret" && current.type !== "inherit" && current.type !== "unsafe:inherit")) return false;
1918
- env[name] = {
1919
- type: "unsafe:inherit",
1920
- version_id: activeVersionId
1921
- };
1922
2232
  }
1923
- const unsafe = record(worker.unsafe) ? { ...worker.unsafe } : {};
1924
- const metadata = record(unsafe.metadata) ? { ...unsafe.metadata } : {};
1925
- if (metadata.bindings !== void 0) return false;
1926
- if (metadata.keep_bindings !== void 0 && (!Array.isArray(metadata.keep_bindings) || !metadata.keep_bindings.every((type) => typeof type === "string"))) return false;
1927
- metadata.keep_bindings = (metadata.keep_bindings ?? []).filter((type) => type !== "secret_text" && type !== "secret_key");
1928
- unsafe.metadata = metadata;
1929
- const next = {
1930
- ...worker,
1931
- env,
1932
- unsafe
2233
+ options.output.activeSecrets = {
2234
+ versionId: activeVersionId,
2235
+ bindings: [...bindings]
1933
2236
  };
1934
- writeFileSync(path, JSON.stringify(next), { mode: 384 });
1935
- await readBuildOutput(options.output.directory);
1936
2237
  return true;
1937
2238
  }
1938
2239
  /** Prevent cf's prebuilt uploader from creating a resource as a side effect. */
@@ -2089,6 +2390,32 @@ function createCfVersionRunner(options) {
2089
2390
  return failed("Cloudflare resources could not be verified before upload.");
2090
2391
  }
2091
2392
  };
2393
+ const uploadPinnedVersion = async (args, atomic) => {
2394
+ if (!options.pinnedUpload || !options.pinnedUpload.verifyUploader()) return failed("The version-aware Cloudflare uploader is unavailable.");
2395
+ const token = await options.pinnedUpload.getToken();
2396
+ if (!token) return failed("Cloudflare session has no bearer for version-aware upload.");
2397
+ try {
2398
+ const version = await uploadPinnedCloudflareVersion({
2399
+ output,
2400
+ accountId: options.pinnedUpload.accountId,
2401
+ apiBaseUrl: options.pinnedUpload.apiBaseUrl,
2402
+ workerName,
2403
+ token,
2404
+ ...flag(args, "--message") ? { message: flag(args, "--message") } : {},
2405
+ ...flag(args, "--secrets-file") ? { secretsFilePath: flag(args, "--secrets-file") } : {},
2406
+ atomic,
2407
+ verifyUploader: options.pinnedUpload.verifyUploader
2408
+ });
2409
+ const preview = version.urls.find((url) => /^https:\/\//.test(url));
2410
+ return {
2411
+ status: 0,
2412
+ stdout: `Worker Version ID: ${version.id}\n${preview ? `Version Preview URL: ${preview}\n` : ""}`,
2413
+ stderr: ""
2414
+ };
2415
+ } catch (cause) {
2416
+ return failed(cause instanceof Error ? cause.message : "Cloudflare version upload failed.");
2417
+ }
2418
+ };
2092
2419
  return async (args, command) => {
2093
2420
  if (args[0] === "deployments" && args[1] === "status") {
2094
2421
  const result = await run([
@@ -2184,6 +2511,7 @@ function createCfVersionRunner(options) {
2184
2511
  if (flag(args, "--name") !== workerName || args.includes("--assets") && flag(args, "--assets") !== output.assetsDirectory) return failed("The Cloudflare version upload target changed.");
2185
2512
  const verified = await verifyResources(output.directory);
2186
2513
  if (verified.status !== 0 || verified.signal || verified.error) return verified;
2514
+ if (output.activeSecrets) return uploadPinnedVersion(args, false);
2187
2515
  return run([
2188
2516
  "workers",
2189
2517
  "versions",
@@ -2228,6 +2556,7 @@ function createCfVersionRunner(options) {
2228
2556
  if (flag(args, "--name") !== workerName || args.includes("--assets") && flag(args, "--assets") !== output.assetsDirectory) return failed("The Cloudflare bootstrap target changed.");
2229
2557
  const verified = await verifyResources(output.directory);
2230
2558
  if (verified.status !== 0 || verified.signal || verified.error) return verified;
2559
+ if (output.activeSecrets) return uploadPinnedVersion(args, true);
2231
2560
  return run([
2232
2561
  "deploy",
2233
2562
  "--prebuilt",
@@ -7504,6 +7833,12 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
7504
7833
  output: cfOutput,
7505
7834
  workerName,
7506
7835
  runCf: cfCommand,
7836
+ pinnedUpload: {
7837
+ accountId,
7838
+ apiBaseUrl,
7839
+ getToken: () => runWranglerAuthToken(runWrangler, generatedConfigPath),
7840
+ verifyUploader: cfUploaderIsPinned
7841
+ },
7507
7842
  verifyResources: createCfResourceVerifier({
7508
7843
  configPath: generatedConfigPath,
7509
7844
  runCf: cfCommand,
@@ -7983,6 +8318,12 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
7983
8318
  output: cfOutput,
7984
8319
  workerName,
7985
8320
  runCf: cfCommand,
8321
+ pinnedUpload: {
8322
+ accountId,
8323
+ apiBaseUrl,
8324
+ getToken: () => runWranglerAuthToken(runWrangler, staticConfigPath),
8325
+ verifyUploader: cfUploaderIsPinned
8326
+ },
7986
8327
  verifyResources: createCfResourceVerifier({
7987
8328
  configPath: staticConfigPath,
7988
8329
  runCf: cfCommand,
@@ -1,2 +1,2 @@
1
- import { A as parseRootWranglerConfig, J as runDeploy, f as checkWranglerMigrationApplySet } from "./deploy-BfZyWZIn.mjs";
1
+ import { A as parseRootWranglerConfig, J as runDeploy, f as checkWranglerMigrationApplySet } from "./deploy-CAOwIvwP.mjs";
2
2
  export { checkWranglerMigrationApplySet, parseRootWranglerConfig, runDeploy };
@@ -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-BfZyWZIn.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-CAOwIvwP.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-BfZyWZIn.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-CAOwIvwP.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.5",
3
+ "version": "0.21.6",
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.5",
329
- "@void/deploy-core": "0.21.5",
330
- "@void/edge": "0.21.5",
331
- "@void/isr": "0.21.5",
332
- "@void/platform": "0.21.5",
328
+ "@void/deploy-cloudflare": "0.21.6",
329
+ "@void/deploy-core": "0.21.6",
330
+ "@void/edge": "0.21.6",
331
+ "@void/isr": "0.21.6",
332
+ "@void/platform": "0.21.6",
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.5",
382
+ "@void/md": "0.21.6",
383
383
  "arktype": ">=2.0.0",
384
384
  "valibot": ">=1.0.0-beta.7",
385
385
  "vite": "^8.0.0",