@void/deploy-cloudflare 1.4.0 → 1.6.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.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { AssetConfig, HeaderRule, RedirectRule } from "@void/deploy-core";
2
- //#region src/operations.d.ts
3
2
  /** Typed provider operations shared by app deployment and platform installation. */
4
3
  type ConfigTarget = {
5
4
  configPath?: string;
@@ -120,8 +119,6 @@ type CloudflareProviderError = {
120
119
  code?: number;
121
120
  message: string;
122
121
  };
123
- //#endregion
124
- //#region src/execute.d.ts
125
122
  type CloudflareCommandResult = {
126
123
  /** Structured provider response. stdout is diagnostics only. */
127
124
  data?: unknown;
@@ -153,8 +150,6 @@ export declare function executeCloudflareDeploy(options: {
153
150
  verifyUploader: () => boolean;
154
151
  configPath?: string;
155
152
  }): Promise<CloudflareDeployExecution>;
156
- //#endregion
157
- //#region src/existing.d.ts
158
153
  type ExistingCloudflareWorker = {
159
154
  versionId: string;
160
155
  bindings: Array<Record<string, unknown>>;
@@ -208,8 +203,6 @@ export declare function assertCloudflareBindingsPreserved(before: ExistingCloudf
208
203
  }): void;
209
204
  /** Preserve the existing Worker, allowing only explicitly approved KV additions. */
210
205
  export declare function assertExistingCloudflareConfig(existing: ExistingCloudflareWorker, config: Record<string, unknown>, built?: boolean, approvedKv?: ReadonlyArray<ApprovedCloudflareKvBinding>): void;
211
- //#endregion
212
- //#region src/config.d.ts
213
206
  /** Parse a root Wrangler JSON/JSONC config without accepting a partial parse. */
214
207
  export declare function parseRootWranglerConfig(configPath: string): Record<string, unknown>;
215
208
  export declare function readWranglerTopLevelString(config: Record<string, unknown>, field: string): string | undefined;
@@ -226,8 +219,6 @@ export declare function resolveD1MigrateTarget(config: Record<string, unknown>,
226
219
  ok: false;
227
220
  reason: string;
228
221
  };
229
- //#endregion
230
- //#region src/framework.d.ts
231
222
  type CloudflareFrameworkDeployConfig = Readonly<{
232
223
  configPath: string;
233
224
  deployPointerPath: string;
@@ -254,8 +245,6 @@ type CloudflareFrameworkDeployConfig = Readonly<{
254
245
  * that file, so Wrangler uploads the exact config Void verifies.
255
246
  */
256
247
  export declare function writeCloudflareFrameworkDeployConfig(options: CloudflareFrameworkDeployConfig): boolean;
257
- //#endregion
258
- //#region src/static.d.ts
259
248
  type CloudflareStaticDeployConfig = Readonly<{
260
249
  configPath: string;
261
250
  name: string;
@@ -280,18 +269,18 @@ export declare function renderCloudflareStaticEntry(options: {
280
269
  * Void has already compiled the root `_headers` and `_redirects` files into the thin edge
281
270
  * Worker. Wrangler parses those files independently of `.assetsignore`, so uploading the source
282
271
  * directory would apply every rule twice and can reject valid Void fallbacks as redirect loops.
272
+ * `headers` becomes the staged `_headers` for rules Cloudflare applies to asset responses itself.
283
273
  */
284
274
  export declare function stageCloudflareStaticAssets(options: {
285
275
  sourceDirectory: string;
286
276
  destinationDirectory: string;
277
+ headers?: string;
287
278
  }): void;
288
279
  /**
289
280
  * Persist the mutable Cloudflare target state without replacing comments,
290
281
  * Durable Object migrations, resource ids, or unrelated user configuration.
291
282
  */
292
283
  export declare function writeCloudflareStaticDeployConfig(options: CloudflareStaticDeployConfig): boolean;
293
- //#endregion
294
- //#region src/version.d.ts
295
284
  type CloudflareVersionMetadata = Readonly<{
296
285
  schema: 1;
297
286
  migrations: ReadonlyArray<string>;
@@ -524,8 +513,6 @@ export declare function deployCloudflareVersionTraffic(options: {
524
513
  export declare function normalizeWorkersDevSubdomain(value: string | undefined): string | undefined;
525
514
  /** Extract the account subdomain from a Wrangler-reported workers.dev URL. */
526
515
  export declare function extractWorkersDevSubdomain(url: string): string | undefined;
527
- //#endregion
528
- //#region src/metadata.d.ts
529
516
  /**
530
517
  * Share one authenticated transport for the activator's read-only metadata calls.
531
518
  * Writes and unsupported commands use the pinned cf command adapter. Responses
@@ -543,12 +530,7 @@ export declare function createCloudflareMetadataRunner(options: {
543
530
  /** Environment used to decide whether the CLI's proxy-aware transport is required. */
544
531
  env?: Readonly<Record<string, string | undefined>>;
545
532
  }): CloudflareCommandRunner;
546
- //#endregion
547
- //#region src/diagnostics.d.ts
548
- /** Keep the uploader's error, excluding stdout binding tables and redacting common credential formats. */
533
+ /** Keep the uploader's error, excluding cf's log lines and redacting common credential formats. */
549
534
  export declare function cloudflareCommandDiagnostic(result: CloudflareCommandResult): string | undefined;
550
- //#endregion
551
- //#region src/secret-draft.d.ts
552
535
  export declare const VOID_SECRET_DRAFT_SOURCE = "export default { fetch() { return new Response(\"\"); } };\n";
553
- //#endregion
554
536
  export type { ApprovedCloudflareKvBinding, CloudflareCommandResult, CloudflareCommandRunner, CloudflareDeployExecution, CloudflareFrameworkDeployConfig, CloudflareOperation, CloudflareProviderError, CloudflareStaticDeployConfig, CloudflareTrafficConfig, CloudflareTriggerConfig, CloudflareTriggerStabilization, CloudflareUploadResult, CloudflareVersionActivation, CloudflareVersionActivationOptions, CloudflareVersionMetadata, CloudflareWorkerMigrationTagOptions, CloudflareWorkersDevSubdomainLookup, ExistingCloudflareWorker };
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import nodePath from "node:path";
6
6
  import { createHash } from "node:crypto";
7
7
  import { tmpdir } from "node:os";
8
8
  import { setTimeout } from "node:timers/promises";
9
- //#region src/config.ts
9
+ // src/config.ts
10
10
  /** Parse a root Wrangler JSON/JSONC config without accepting a partial parse. */
11
11
  function parseRootWranglerConfig(configPath) {
12
12
  if (!existsSync(configPath)) return {};
@@ -82,8 +82,7 @@ function resolveD1MigrateTarget(config, binding) {
82
82
  token
83
83
  };
84
84
  }
85
- //#endregion
86
- //#region src/execute.ts
85
+ // src/execute.ts
87
86
  /** Upload the already-verified Worker artifact without Wrangler autoconfiguration. */
88
87
  async function executeCloudflareDeploy(options) {
89
88
  if (!options.verifyUploader()) return {
@@ -112,8 +111,7 @@ function isCleanCommandExit(result) {
112
111
  function isWorkerNotFound(result) {
113
112
  return isCompletedCommand(result) && (result.failure === "not-found" || result.errorCode === 10007);
114
113
  }
115
- //#endregion
116
- //#region src/secret-draft.ts
114
+ // src/secret-draft.ts
117
115
  /**
118
116
  * `wrangler secret put` creates a fetch-only draft before attaching a first secret to a Worker.
119
117
  * Accept that draft as first-deployment proof only when its complete deployable shape contains no
@@ -168,8 +166,7 @@ function isVoidSecretOnlyDraft(entry) {
168
166
  }
169
167
  return true;
170
168
  }
171
- //#endregion
172
- //#region src/existing.ts
169
+ // src/existing.ts
173
170
  /** A failed remote read, distinct from an invalid or changing Worker configuration. */
174
171
  var CloudflareWorkerInspectionError = class extends Error {
175
172
  name = "CloudflareWorkerInspectionError";
@@ -531,8 +528,7 @@ function hasContent(value) {
531
528
  if (isRecord(value)) return Object.values(value).some(hasContent);
532
529
  return true;
533
530
  }
534
- //#endregion
535
- //#region ../../node_modules/.pnpm/pathslash@0.1.0/node_modules/pathslash/dist/index.mjs
531
+ // ../../node_modules/.pnpm/pathslash@0.1.0/node_modules/pathslash/dist/index.mjs
536
532
  const BACKSLASH_RE = /\\/g;
537
533
  const isWindows = process.platform === "win32";
538
534
  /**
@@ -570,8 +566,7 @@ const posix = { ...nodePath.posix };
570
566
  posix.posix = win32.posix = posix;
571
567
  posix.win32 = win32.win32 = win32;
572
568
  const { basename, delimiter, dirname, extname, format, isAbsolute, join, matchesGlob, normalize, parse: parse$1, relative, resolve, sep, toNamespacedPath } = isWindows ? win32 : posix;
573
- //#endregion
574
- //#region src/framework.ts
569
+ // src/framework.ts
575
570
  /**
576
571
  * Point a standalone framework Worker at the canonical root Cloudflare state.
577
572
  *
@@ -640,8 +635,7 @@ function writeCloudflareFrameworkDeployConfig(options) {
640
635
  }
641
636
  return changed;
642
637
  }
643
- //#endregion
644
- //#region src/static.ts
638
+ // src/static.ts
645
639
  /** Generate the deterministic thin Worker entry bundled by Wrangler. */
646
640
  function renderCloudflareStaticEntry(options) {
647
641
  const config = JSON.stringify({
@@ -663,6 +657,7 @@ function renderCloudflareStaticEntry(options) {
663
657
  * Void has already compiled the root `_headers` and `_redirects` files into the thin edge
664
658
  * Worker. Wrangler parses those files independently of `.assetsignore`, so uploading the source
665
659
  * directory would apply every rule twice and can reject valid Void fallbacks as redirect loops.
660
+ * `headers` becomes the staged `_headers` for rules Cloudflare applies to asset responses itself.
666
661
  */
667
662
  function stageCloudflareStaticAssets(options) {
668
663
  const sourceDirectory = resolve(options.sourceDirectory);
@@ -685,6 +680,7 @@ function stageCloudflareStaticAssets(options) {
685
680
  return !reserved.has(absolute) && !isInsideDestination(absolute);
686
681
  }
687
682
  });
683
+ if (options.headers !== void 0) writeFileSync(join(destinationDirectory, "_headers"), options.headers);
688
684
  }
689
685
  /**
690
686
  * Persist the mutable Cloudflare target state without replacing comments,
@@ -707,7 +703,7 @@ function writeCloudflareStaticDeployConfig(options) {
707
703
  upsert(["no_bundle"], false);
708
704
  upsert(["assets", "directory"], options.assetsDirectory);
709
705
  upsert(["assets", "binding"], "ASSETS");
710
- upsert(["assets", "run_worker_first"], true);
706
+ upsert(["assets", "run_worker_first"], options.assetConfig.run_worker_first ?? true);
711
707
  upsert(["assets", "not_found_handling"], options.assetConfig.not_found_handling ?? "none");
712
708
  upsert(["assets", "html_handling"], options.assetConfig.html_handling ?? "auto-trailing-slash");
713
709
  upsert(["durable_objects", "bindings"], []);
@@ -763,11 +759,17 @@ function findDroppedComment(before, after) {
763
759
  counts.set(token, remaining - 1);
764
760
  }
765
761
  }
766
- //#endregion
767
- //#region src/diagnostics.ts
762
+ // src/diagnostics.ts
768
763
  const MAX_DIAGNOSTIC_LENGTH = 4096;
769
764
  const MAX_DIAGNOSTIC_LINES = 24;
770
- /** Keep the uploader's error, excluding stdout binding tables and redacting common credential formats. */
765
+ const ERROR_BOX = /(?:^|\n)[ \t]*┌[ \t]*(?:APIError|Error)\b[^\n]*\n(?:[ \t]*│[^\n]*\n)*[ \t]*└[^\n]*/i;
766
+ const LOG_LINE = /^[├│◆◇●▲■└|*o•!x—](?: {2}|$)/;
767
+ const UPLOAD_CONFLICT = /^[ \t]*(?:\S[ \t]+)?(Aborting the upload operation because of conflicts\..*)$/m;
768
+ const SCRIPT_API_ORIGIN = /^[ \t]*(?:\S[ \t]+)?(You are about to upload a Worker that was last updated via the script API\.)/m;
769
+ function withoutLogLines(output) {
770
+ return output.split("\n").filter((line) => !LOG_LINE.test(line)).join("\n");
771
+ }
772
+ /** Keep the uploader's error, excluding cf's log lines and redacting common credential formats. */
771
773
  function cloudflareCommandDiagnostic(result) {
772
774
  const stderr = stripVTControlCharacters(result.stderr).replace(/\r\n?/g, "\n");
773
775
  const stdout = stripVTControlCharacters(result.stdout).replace(/\r\n?/g, "\n");
@@ -780,15 +782,13 @@ function cloudflareCommandDiagnostic(result) {
780
782
  }
781
783
  }
782
784
  if (message === stderr && !/(?:^|\n)[ \t]*(?:[✘×X][ \t]+)?\[ERROR\]/i.test(stderr)) {
783
- const box = /(?:^|\n)[ \t]*┌[ \t]*(?:APIError|Error)\b[^\n]*\n(?:[ \t]*│[^\n]*\n)*[ \t]*└[^\n]*/i.exec(stdout);
785
+ const box = ERROR_BOX.exec(stdout);
786
+ const conflict = UPLOAD_CONFLICT.exec(`${stdout}\n${stderr}`);
784
787
  if (box) message = box[0].trim();
788
+ else if (conflict) message = [SCRIPT_API_ORIGIN.exec(`${stdout}\n${stderr}`)?.[1], conflict[1]].filter(Boolean).join("\n");
785
789
  else {
786
- const lines = stdout.split("\n");
787
- const abort = lines.find((line) => line.startsWith("■ Aborting the upload operation because of conflicts."));
788
- if (abort) {
789
- const reason = "You are about to upload a Worker that was last updated via the script API.";
790
- message = [lines.includes(`▲ ${reason}`) ? reason : "", abort.slice(3)].filter(Boolean).join("\n");
791
- }
790
+ const stderrBox = ERROR_BOX.exec(stderr);
791
+ message = stderrBox ? withoutLogLines(stderr.slice(0, stderrBox.index)) + stderrBox[0] + withoutLogLines(stderr.slice(stderrBox.index + stderrBox[0].length)) : withoutLogLines(stderr);
792
792
  }
793
793
  }
794
794
  message = stripVTControlCharacters(message).split(/\n\s*(?:🪵|Logs (?:were )?written|If you think this is a bug)/)[0].trim();
@@ -797,8 +797,7 @@ function cloudflareCommandDiagnostic(result) {
797
797
  const bounded = message.split("\n").slice(0, MAX_DIAGNOSTIC_LINES).join("\n").slice(0, MAX_DIAGNOSTIC_LENGTH);
798
798
  return bounded.length < message.length ? `${bounded}\n[diagnostic truncated]` : bounded;
799
799
  }
800
- //#endregion
801
- //#region src/version.ts
800
+ // src/version.ts
802
801
  const DURABLE_MIGRATION_VERSION_ERROR = 10211;
803
802
  const CLOUDFLARE_SECRET_CHANGED_ERROR = 10220;
804
803
  /** Encode migration state into Cloudflare's version annotation for safe rollback diagnostics. */
@@ -2406,8 +2405,7 @@ function workersDevSubdomainResult(url) {
2406
2405
  const workersDevSubdomain = extractWorkersDevSubdomain(url);
2407
2406
  return workersDevSubdomain ? { workersDevSubdomain } : {};
2408
2407
  }
2409
- //#endregion
2410
- //#region src/metadata.ts
2408
+ // src/metadata.ts
2411
2409
  /**
2412
2410
  * Share one authenticated transport for the activator's read-only metadata calls.
2413
2411
  * Writes and unsupported commands use the pinned cf command adapter. Responses
@@ -2497,5 +2495,4 @@ function createCloudflareMetadataRunner(options) {
2497
2495
  return fallback(operation, runOptions);
2498
2496
  };
2499
2497
  }
2500
- //#endregion
2501
2498
  export { CloudflareWorkerInspectionError, VOID_SECRET_DRAFT_SOURCE, activateCloudflareVersion, assertCloudflareBindingsPreserved, assertCloudflareDurableObjectLifecycleSupported, assertExistingCloudflareConfig, cloudflareCommandDiagnostic, createCloudflareMetadataRunner, deployCloudflareVersionTraffic, deployCloudflareVersionTriggers, encodeCloudflareVersionMessage, executeCloudflareDeploy, extractWorkersDevSubdomain, normalizeReadinessAccessOrigin, normalizeWorkersDevSubdomain, parseCloudflareVersionMessage, parseRootWranglerConfig, readBindingFieldPresence, readCloudflareTriggerConfig, readCloudflareVersionMigrationTag, readCloudflareWorkerMigrationTag, readConfigEntryString, readExistingCloudflareWorker, readStoredResourceName, readWranglerTopLevelString, renderCloudflareStaticEntry, resolveD1MigrateTarget, stabilizeCloudflareVersionTriggers, stageCloudflareStaticAssets, writeCloudflareFrameworkDeployConfig, writeCloudflareStaticDeployConfig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@void/deploy-cloudflare",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "description": "Cloudflare deployment primitives for Void runtimes and deployment adapters.",
5
5
  "homepage": "https://void.cloud",
6
6
  "bugs": {
@@ -26,15 +26,15 @@
26
26
  "access": "public"
27
27
  },
28
28
  "dependencies": {
29
- "@void/deploy-core": "1.4.0",
29
+ "@void/deploy-core": "1.6.0",
30
30
  "jsonc-parser": "^3.3.1"
31
31
  },
32
32
  "devDependencies": {
33
- "@cloudflare/workers-types": "^5.20261019.1",
34
- "@types/node": "^26.6.5",
33
+ "@cloudflare/workers-types": "^5.20261102.1",
34
+ "@types/node": "^26.6.6",
35
35
  "pathslash": "^0.1.0",
36
36
  "typescript": "7.0.2",
37
- "vite-plus": "1.3.0"
37
+ "vite-plus": "1.4.0"
38
38
  },
39
39
  "scripts": {
40
40
  "build": "vp pack",