@void/deploy-cloudflare 0.24.0 → 0.25.0

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.
Files changed (3) hide show
  1. package/README.md +2 -25
  2. package/dist/index.mjs +16 -21
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -1,28 +1,5 @@
1
1
  # @void/deploy-cloudflare
2
2
 
3
- Public Cloudflare target adapter primitives for Void deployments.
3
+ Cloudflare deployment primitives used by the Void CLI. Provides Worker configuration reads, uploads, activation, and deployment verification.
4
4
 
5
- This package owns Wrangler JSON/JSONC config reads and the final verified
6
- Cloudflare upload boundary. Source inference and app builds remain in `void`;
7
- provider-neutral contracts and plans remain in `@void/deploy-core`.
8
-
9
- Existing Worker handoffs read the active version, validate resource identities,
10
- and check the uploaded bindings before activation. Traffic-only activation uses
11
- an isolated config to retain Worker settings and triggers. Trigger snapshots
12
- record when configuration was preserved, so rollback can keep those settings
13
- for versions originally deployed outside Void.
14
-
15
- Handoff verifiers can accept an explicit list of new KV binding identities.
16
- Only those exact namespaces may be added; existing bindings, variables, secrets,
17
- and handlers must remain unchanged. New bindings cannot alias an existing KV
18
- namespace. The Void CLI uses this for the migration's explicit ISR cache choice.
19
-
20
- First-deployment readiness allows up to one minute for the new Worker's public
21
- route to propagate, with bounded requests and backoff. A successful check still
22
- requires the ready response, and Cloudflare Access denials fail immediately.
23
- Subsequent version previews retain the shorter retry window.
24
-
25
- Failed version uploads and first-deployment bootstraps return a bounded diagnostic
26
- alongside the exit status and Cloudflare error code. It retains validation messages
27
- and stack locations, strips terminal formatting, excludes stdout binding tables,
28
- and redacts common credential formats before callers display or log it.
5
+ Applications normally deploy with `void deploy --platform cloudflare`. See the [Cloudflare guide](https://void.cloud/integrations/cloudflare) for configuration and credentials, or [Platform Development](https://void.cloud/guide/platform-development) for runtime and adapter work.
package/dist/index.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import { isDeepStrictEqual, stripVTControlCharacters } from "node:util";
2
2
  import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
3
  import { SyntaxKind, applyEdits, createScanner, modify, parse, parseTree } from "jsonc-parser";
4
+ import { isRecord } from "@void/deploy-core";
4
5
  import nodePath from "node:path";
5
6
  import { createHash } from "node:crypto";
6
7
  import { tmpdir } from "node:os";
@@ -88,16 +89,16 @@ function resolveD1MigrateTarget(config, binding) {
88
89
  * application code configuration or non-secret resource that an ordinary deploy could own.
89
90
  */
90
91
  function isWranglerSecretOnlyDraft(entry) {
91
- if (!isRecord$1(entry.annotations)) return false;
92
+ if (!isRecord(entry.annotations)) return false;
92
93
  const annotationKeys = Object.keys(entry.annotations);
93
94
  if (entry.annotations["workers/triggered_by"] !== "secret" || annotationKeys.some((key) => key !== "workers/triggered_by")) return false;
94
- if (!isRecord$1(entry.resources)) return false;
95
+ if (!isRecord(entry.resources)) return false;
95
96
  const { bindings, script, script_runtime: scriptRuntime } = entry.resources;
96
- if (!Array.isArray(bindings) || bindings.length === 0 || !bindings.every((binding) => isRecord$1(binding) && typeof binding.name === "string" && binding.name.length > 0 && binding.type === "secret_text" && Object.keys(binding).every((key) => key === "name" || key === "type"))) return false;
97
- if (!isRecord$1(script) || !Array.isArray(script.handlers) || script.handlers.length !== 1 || script.handlers[0] !== "fetch" || script.placement_mode !== void 0) return false;
98
- if (!isRecord$1(scriptRuntime)) return false;
97
+ if (!Array.isArray(bindings) || bindings.length === 0 || !bindings.every((binding) => isRecord(binding) && typeof binding.name === "string" && binding.name.length > 0 && binding.type === "secret_text" && Object.keys(binding).every((key) => key === "name" || key === "type"))) return false;
98
+ if (!isRecord(script) || !Array.isArray(script.handlers) || script.handlers.length !== 1 || script.handlers[0] !== "fetch" || script.placement_mode !== void 0) return false;
99
+ if (!isRecord(scriptRuntime)) return false;
99
100
  const runtimeKeys = Object.keys(scriptRuntime);
100
- return scriptRuntime.usage_model === "standard" && (scriptRuntime.limits === void 0 || isRecord$1(scriptRuntime.limits) && Object.keys(scriptRuntime.limits).length === 0) && runtimeKeys.every((key) => key === "usage_model" || key === "limits");
101
+ return scriptRuntime.usage_model === "standard" && (scriptRuntime.limits === void 0 || isRecord(scriptRuntime.limits) && Object.keys(scriptRuntime.limits).length === 0) && runtimeKeys.every((key) => key === "usage_model" || key === "limits");
101
102
  }
102
103
  const VOID_SECRET_DRAFT_SOURCE = "export default { fetch() { return new Response(\"\"); } };\n";
103
104
  /** Prove a cf-created placeholder from the exact immutable version's source. */
@@ -120,25 +121,22 @@ function isVoidSecretOnlyDraft(entry) {
120
121
  "env",
121
122
  "resources"
122
123
  ]);
123
- if (Object.keys(entry).some((key) => !metadataFields.has(key)) || entry.source !== "cf_cli" || !isRecord$1(entry.annotations) || Object.keys(entry.annotations).length !== 1 || entry.annotations["workers/triggered_by"] !== "secret" || entry.main_module !== "index.js" || !Array.isArray(entry.urls) || entry.urls.length !== 0 || !Array.isArray(entry.modules) || entry.modules.length !== 1 || !Array.isArray(entry.bindings) || entry.bindings.length === 0) return false;
124
+ if (Object.keys(entry).some((key) => !metadataFields.has(key)) || entry.source !== "cf_cli" || !isRecord(entry.annotations) || Object.keys(entry.annotations).length !== 1 || entry.annotations["workers/triggered_by"] !== "secret" || entry.main_module !== "index.js" || !Array.isArray(entry.urls) || entry.urls.length !== 0 || !Array.isArray(entry.modules) || entry.modules.length !== 1 || !Array.isArray(entry.bindings) || entry.bindings.length === 0) return false;
124
125
  const module = entry.modules[0];
125
- if (!isRecord$1(module) || Object.keys(module).length !== 3 || module.name !== "index.js" || module.content_type !== "application/javascript+module" || module.content_base64 !== Buffer.from("export default { fetch() { return new Response(\"\"); } };\n").toString("base64")) return false;
126
+ if (!isRecord(module) || Object.keys(module).length !== 3 || module.name !== "index.js" || module.content_type !== "application/javascript+module" || module.content_base64 !== Buffer.from("export default { fetch() { return new Response(\"\"); } };\n").toString("base64")) return false;
126
127
  const names = /* @__PURE__ */ new Set();
127
128
  for (const binding of entry.bindings) {
128
- if (!isRecord$1(binding) || Object.keys(binding).length !== 2 || typeof binding.name !== "string" || binding.name.length === 0 || names.has(binding.name) || binding.type !== "secret_text") return false;
129
+ if (!isRecord(binding) || Object.keys(binding).length !== 2 || typeof binding.name !== "string" || binding.name.length === 0 || names.has(binding.name) || binding.type !== "secret_text") return false;
129
130
  names.add(binding.name);
130
131
  }
131
- if (entry.env !== void 0 && (!isRecord$1(entry.env) || Object.keys(entry.env).length !== names.size || Object.entries(entry.env).some(([name, binding]) => !names.has(name) || !isRecord$1(binding) || Object.keys(binding).length !== 1 || binding.type !== "secret_text"))) return false;
132
+ if (entry.env !== void 0 && (!isRecord(entry.env) || Object.keys(entry.env).length !== names.size || Object.entries(entry.env).some(([name, binding]) => !names.has(name) || !isRecord(binding) || Object.keys(binding).length !== 1 || binding.type !== "secret_text"))) return false;
132
133
  if (entry.resources !== void 0) {
133
- if (!isRecord$1(entry.resources) || Object.keys(entry.resources).length !== 1) return false;
134
+ if (!isRecord(entry.resources) || Object.keys(entry.resources).length !== 1) return false;
134
135
  const bindings = entry.resources.bindings;
135
136
  if (!Array.isArray(bindings) || !isDeepStrictEqual(bindings, entry.bindings)) return false;
136
137
  }
137
138
  return true;
138
139
  }
139
- function isRecord$1(value) {
140
- return typeof value === "object" && value !== null && !Array.isArray(value);
141
- }
142
140
  //#endregion
143
141
  //#region src/existing.ts
144
142
  /** A failed remote read, distinct from an invalid or changing Worker configuration. */
@@ -1058,9 +1056,10 @@ function hasCustomDomains(routes) {
1058
1056
  /** Select a configured HTTPS route that is guaranteed to cover /__void/ready. */
1059
1057
  function customRouteReadinessUrl(routes) {
1060
1058
  for (const route of routes) {
1061
- const pattern = typeof route === "string" ? route : isRecord(route) && typeof route.pattern === "string" ? route.pattern : void 0;
1059
+ const record = isRecord(route) ? route : void 0;
1060
+ const pattern = typeof route === "string" ? route : typeof record?.pattern === "string" ? record.pattern : void 0;
1062
1061
  if (!pattern) continue;
1063
- const customDomain = isRecord(route) && route.custom_domain === true;
1062
+ const customDomain = record?.custom_domain === true;
1064
1063
  const withoutScheme = pattern.replace(/^https?:\/\//i, "");
1065
1064
  const slash = withoutScheme.indexOf("/");
1066
1065
  const hostname = (slash < 0 ? withoutScheme : withoutScheme.slice(0, slash)).trim();
@@ -1108,7 +1107,6 @@ function stableJson(value) {
1108
1107
  return JSON.stringify(value);
1109
1108
  }
1110
1109
  function parseTriggerConfig(value) {
1111
- if (value === void 0) return null;
1112
1110
  if (!isRecord(value)) return null;
1113
1111
  if ([
1114
1112
  "preserve",
@@ -1165,9 +1163,6 @@ function resolvePreservedTraffic(desired, previous, workerExists) {
1165
1163
  ...desired.addresses === void 0 ? {} : { addresses: desired.addresses }
1166
1164
  };
1167
1165
  }
1168
- function isRecord(value) {
1169
- return typeof value === "object" && value !== null && !Array.isArray(value);
1170
- }
1171
1166
  function isCandidatePreviewUrl(value, workerName, versionId, alias) {
1172
1167
  try {
1173
1168
  const url = new URL(value);
@@ -1803,7 +1798,7 @@ async function readCloudflareVersionInspection(options, configPath, versionId, k
1803
1798
  const isVoidDraft = isVoidSecretOnlyDraft(draft);
1804
1799
  return {
1805
1800
  metadata: typeof message === "string" ? parseCloudflareVersionMessage(message) : null,
1806
- isSecretOnlyDraft: isWranglerSecretOnlyDraft(draft) || isVoidSecretOnlyDraft(draft),
1801
+ isSecretOnlyDraft: isWranglerSecretOnlyDraft(draft) || isVoidDraft,
1807
1802
  isVoidSecretOnlyDraft: isVoidDraft,
1808
1803
  voidDraftSecretNames: isVoidDraft ? draft.bindings.map((binding) => binding.name) : null
1809
1804
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@void/deploy-cloudflare",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/voidzero-dev/void.git",
@@ -20,12 +20,12 @@
20
20
  "access": "public"
21
21
  },
22
22
  "dependencies": {
23
- "@void/deploy-core": "0.24.0",
23
+ "@void/deploy-core": "0.25.0",
24
24
  "jsonc-parser": "3.3.1"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@cloudflare/workers-types": "^4.20260702.1",
28
- "@types/node": "^26.6.3",
28
+ "@types/node": "^26.6.4",
29
29
  "pathslash": "^0.1.0",
30
30
  "typescript": "7.0.2",
31
31
  "vite-plus": "1.0.0"