@depup/cloudflare__vite-plugin 1.55.0-depup.0 → 1.56.0-depup.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.mjs CHANGED
@@ -16,7 +16,7 @@ import net from "node:net";
16
16
  import http from "node:http";
17
17
  import events, { EventEmitter } from "node:events";
18
18
  import { Buffer as Buffer$1 } from "node:buffer";
19
- import crypto$1, { createCipheriv, createDecipheriv, createHash, randomBytes, randomUUID, webcrypto } from "node:crypto";
19
+ import crypto2, { createCipheriv, createDecipheriv, createHash, randomBytes, randomUUID, webcrypto } from "node:crypto";
20
20
  import { AsyncLocalStorage } from "node:async_hooks";
21
21
  import * as fsp from "node:fs/promises";
22
22
  import fs, { constants as constants$1 } from "node:fs/promises";
@@ -2614,8 +2614,8 @@ function formatConfigSnippet(snippet, configPath, formatted = true) {
2614
2614
  __name$6(formatConfigSnippet, "formatConfigSnippet");
2615
2615
 
2616
2616
  //#endregion
2617
- //#region ../workers-utils/dist/chunk-2OPNWQJ5.mjs
2618
- var DEFAULT_COMPAT_DATE = "2026-09-17";
2617
+ //#region ../workers-utils/dist/chunk-S6ZAI5DC.mjs
2618
+ var DEFAULT_COMPAT_DATE = "2026-09-18";
2619
2619
  function assertNever(_value) {}
2620
2620
  __name$6(assertNever, "assertNever");
2621
2621
  function mapWorkerMetadataBindings(bindings) {
@@ -15573,7 +15573,7 @@ var require_snapshot_utils = /* @__PURE__ */ __commonJS$2({ "../../node_modules/
15573
15573
  match: new Set(matchHeaders$1.map((header) => caseSensitive ? header : header.toLowerCase()))
15574
15574
  };
15575
15575
  }
15576
- const crypto$4 = runtimeFeatures$5.has("crypto") ? __require$2("node:crypto") : null;
15576
+ const crypto$3 = runtimeFeatures$5.has("crypto") ? __require$2("node:crypto") : null;
15577
15577
  /**
15578
15578
  * @callback HashIdFunction
15579
15579
  * @param {string} value - The value to hash
@@ -15583,7 +15583,7 @@ var require_snapshot_utils = /* @__PURE__ */ __commonJS$2({ "../../node_modules/
15583
15583
  * Generates a hash for a given value
15584
15584
  * @type {HashIdFunction}
15585
15585
  */
15586
- const hashId$1 = crypto$4?.hash ? (value) => crypto$4.hash("sha256", value, "base64url") : (value) => Buffer.from(value).toString("base64url");
15586
+ const hashId$1 = crypto$3?.hash ? (value) => crypto$3.hash("sha256", value, "base64url") : (value) => Buffer.from(value).toString("base64url");
15587
15587
  /**
15588
15588
  * @typedef {(url: string) => boolean} IsUrlExcluded Checks if a URL matches any of the exclude patterns
15589
15589
  */
@@ -21153,10 +21153,10 @@ var require_subresource_integrity = /* @__PURE__ */ __commonJS$2({ "../../node_m
21153
21153
  ["sha512", 2]
21154
21154
  ]);
21155
21155
  /** @type {import('node:crypto')} */
21156
- let crypto$3;
21156
+ let crypto$2;
21157
21157
  if (runtimeFeatures$3.has("crypto")) {
21158
- crypto$3 = __require$2("node:crypto");
21159
- const cryptoHashes = crypto$3.getHashes();
21158
+ crypto$2 = __require$2("node:crypto");
21159
+ const cryptoHashes = crypto$2.getHashes();
21160
21160
  if (cryptoHashes.length === 0) validSRIHashAlgorithmTokenSet.clear();
21161
21161
  for (const algorithm of validSRIHashAlgorithmTokenSet.keys()) if (cryptoHashes.includes(algorithm) === false) validSRIHashAlgorithmTokenSet.delete(algorithm);
21162
21162
  } else validSRIHashAlgorithmTokenSet.clear();
@@ -21254,7 +21254,7 @@ var require_subresource_integrity = /* @__PURE__ */ __commonJS$2({ "../../node_m
21254
21254
  * @returns {string}
21255
21255
  */
21256
21256
  const applyAlgorithmToBytes = (algorithm, bytes) => {
21257
- return crypto$3.hash(algorithm, bytes, "base64");
21257
+ return crypto$2.hash(algorithm, bytes, "base64");
21258
21258
  };
21259
21259
  /**
21260
21260
  * Compares two base64 strings, allowing for base64url
@@ -23838,7 +23838,7 @@ var require_connection = /* @__PURE__ */ __commonJS$2({ "../../node_modules/.pnp
23838
23838
  const { WebsocketFrameSend: WebsocketFrameSend$4 } = require_frame();
23839
23839
  const assert$3 = __require$2("node:assert");
23840
23840
  const { runtimeFeatures } = require_runtime_features();
23841
- const crypto$2 = runtimeFeatures.has("crypto") ? __require$2("node:crypto") : null;
23841
+ const crypto$1 = runtimeFeatures.has("crypto") ? __require$2("node:crypto") : null;
23842
23842
  let warningEmitted = false;
23843
23843
  /**
23844
23844
  * @see https://websockets.spec.whatwg.org/#concept-websocket-establish
@@ -23862,7 +23862,7 @@ var require_connection = /* @__PURE__ */ __commonJS$2({ "../../node_modules/.pnp
23862
23862
  useURLCredentials: true
23863
23863
  });
23864
23864
  if (options.headers) request$2.headersList = getHeadersList(new Headers$2(options.headers));
23865
- const keyValue = crypto$2.randomBytes(16).toString("base64");
23865
+ const keyValue = crypto$1.randomBytes(16).toString("base64");
23866
23866
  request$2.headersList.append("sec-websocket-key", keyValue, true);
23867
23867
  request$2.headersList.append("sec-websocket-version", "13", true);
23868
23868
  for (const protocol of protocols) request$2.headersList.append("sec-websocket-protocol", protocol, true);
@@ -23898,7 +23898,7 @@ var require_connection = /* @__PURE__ */ __commonJS$2({ "../../node_modules/.pnp
23898
23898
  failWebsocketConnection$3(handler, 1002, "Server did not set Connection header to \"upgrade\".");
23899
23899
  return;
23900
23900
  }
23901
- if (response.headersList.get("Sec-WebSocket-Accept") !== crypto$2.hash("sha1", keyValue + uid, "base64")) {
23901
+ if (response.headersList.get("Sec-WebSocket-Accept") !== crypto$1.hash("sha1", keyValue + uid, "base64")) {
23902
23902
  failWebsocketConnection$3(handler, 1002, "Incorrect hash received in Sec-WebSocket-Accept header.");
23903
23903
  return;
23904
23904
  }
@@ -44357,6 +44357,7 @@ var BINDING_LOCAL_SUPPORT = {
44357
44357
  pipeline: "local-and-remote",
44358
44358
  service: "local-and-remote",
44359
44359
  queue: "local-and-remote",
44360
+ flagship: "local-and-remote",
44360
44361
  vectorize: "remote",
44361
44362
  mtls_certificate: "remote",
44362
44363
  dispatch_namespace: "remote",
@@ -44365,7 +44366,6 @@ var BINDING_LOCAL_SUPPORT = {
44365
44366
  ai_search_namespace: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
44366
44367
  media: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
44367
44368
  artifacts: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
44368
- flagship: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
44369
44369
  vpc_service: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
44370
44370
  vpc_network: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
44371
44371
  agent_memory: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator"
@@ -45080,12 +45080,12 @@ function printBindings(bindings, options) {
45080
45080
  mode: getMode({ isSimulatedLocally: true })
45081
45081
  };
45082
45082
  }));
45083
- if (flagship.length > 0) output.push(...flagship.map(({ binding, app_id }) => {
45083
+ if (flagship.length > 0) output.push(...flagship.map(({ binding, app_id, remote }) => {
45084
45084
  return {
45085
45085
  name: binding,
45086
45086
  type: getBindingTypeFriendlyName("flagship"),
45087
45087
  value: app_id,
45088
- mode: getMode({ isSimulatedLocally: !context.remoteBindingsDisabled ? false : void 0 })
45088
+ mode: getMode({ isSimulatedLocally: context.remoteBindingsDisabled || !remote })
45089
45089
  };
45090
45090
  }));
45091
45091
  if (services.length > 0) output.push(...services.map(({ binding, service, entrypoint, remote, dev }) => {
@@ -48168,10 +48168,14 @@ async function assertWranglerVersion() {
48168
48168
  * delegate uses to force the experimental Build Output Specification on by default.
48169
48169
  */
48170
48170
  const FORCE_BUILD_OUTPUT_ENV_VAR = "CLOUDFLARE_VITE_FORCE_BUILD_OUTPUT";
48171
+ const PREVIEW_BUILD_ENV_VAR = "CLOUDFLARE_VITE_PREVIEW_BUILD";
48171
48172
  /** Whether `cf-vite build` has forced the Build Output Specification on. */
48172
48173
  function isForcedBuildOutput() {
48173
48174
  return process.env[FORCE_BUILD_OUTPUT_ENV_VAR] === "true";
48174
48175
  }
48176
+ function isPreviewBuild() {
48177
+ return process.env[PREVIEW_BUILD_ENV_VAR] === "true";
48178
+ }
48175
48179
 
48176
48180
  //#endregion
48177
48181
  //#region ../../node_modules/.pnpm/@remix-run+node-fetch-server@0.8.0/node_modules/@remix-run/node-fetch-server/dist/node-fetch-server.js
@@ -55624,14 +55628,14 @@ const ContainerObservabilityBaseSchema = strictObject({
55624
55628
  enabled: boolean().optional(),
55625
55629
  logs: strictObject({ enabled: boolean().optional() }).optional()
55626
55630
  });
55627
- const ContainerObservabilitySchema = union([ContainerObservabilityBaseSchema.extend({ targetInstancePercentage: number().min(0).max(100).optional() }), ContainerObservabilityBaseSchema.extend({ targetInstanceCount: number().int().nonnegative().optional() })]);
55631
+ const StandardContainerObservabilitySchema = union([ContainerObservabilityBaseSchema.extend({ targetInstancePercentage: number().min(0).max(100).optional() }), ContainerObservabilityBaseSchema.extend({ targetInstanceCount: number().int().nonnegative().optional() })]);
55628
55632
  const BaseContainerSchema = strictObject({
55629
55633
  type: literal$1("container"),
55630
55634
  name: string().min(1),
55631
- observability: ContainerObservabilitySchema.optional(),
55632
55635
  unsafe: record(string(), unknown()).optional()
55633
55636
  });
55634
55637
  const StandardContainerBaseSchema = BaseContainerSchema.extend({
55638
+ observability: StandardContainerObservabilitySchema.optional(),
55635
55639
  maxInstances: number().int().nonnegative().default(20),
55636
55640
  instanceType: union([_enum([
55637
55641
  "basic",
@@ -55678,7 +55682,10 @@ const StandardContainerBaseSchema = BaseContainerSchema.extend({
55678
55682
  activeGracePeriod: number().nonnegative().optional()
55679
55683
  }).optional()
55680
55684
  });
55681
- const DurableObjectContainerBaseSchema = BaseContainerSchema.extend({ schedulingPolicy: literal$1("durable-object") });
55685
+ const DurableObjectContainerBaseSchema = BaseContainerSchema.extend({
55686
+ schedulingPolicy: literal$1("durable-object"),
55687
+ observability: ContainerObservabilityBaseSchema.optional()
55688
+ });
55682
55689
  /**
55683
55690
  * Input Container schema — validates user-authored `cloudflare.config.ts`
55684
55691
  * Container exports. Dockerfiles are built by the consuming build tool.
@@ -55866,9 +55873,12 @@ const InputSettingsSchema = strictObject({
55866
55873
  });
55867
55874
  /**
55868
55875
  * Output settings schema — the shape of the top-level `config.json` in the
55869
- * Build Output Specification. Adds the `mode` the build was produced in.
55876
+ * Build Output Specification. Adds the build mode and Preview intent.
55870
55877
  */
55871
- const OutputSettingsSchema = InputSettingsSchema.extend({ mode: string().optional() });
55878
+ const OutputSettingsSchema = InputSettingsSchema.extend({
55879
+ isPreview: boolean().optional(),
55880
+ mode: string().optional()
55881
+ });
55872
55882
  const DEFAULT_EXPORT_NAME = "default";
55873
55883
  const SETTINGS_EXPORT_NAME = "settings";
55874
55884
  const SUPPORTED_EXPORT_TYPES = new Set([
@@ -56114,10 +56124,14 @@ function convertToWranglerConfig(workerConfig, settingsConfig, containerExports
56114
56124
  return result;
56115
56125
  }
56116
56126
  function convertContainer(container) {
56117
- if (container.schedulingPolicy === "durable-object") throw new UserError$1("Durable Object-managed Containers are not currently supported by `convertToWranglerConfig()`.", { telemetryMessage: false });
56118
56127
  const converted = { name: container.name };
56119
56128
  if (container.observability !== void 0) converted.observability = convertContainerObservability(container.observability);
56120
56129
  if (container.unsafe !== void 0) converted.unsafe = container.unsafe;
56130
+ if (container.schedulingPolicy === "durable-object") {
56131
+ converted.scheduling_policy = "durable_object";
56132
+ if (container.images !== void 0) converted.images = Object.fromEntries(Object.entries(container.images).map(([name, image]) => [name, convertDurableObjectContainerImage(image)]));
56133
+ return converted;
56134
+ }
56121
56135
  converted.image = "dockerfile" in container.image ? container.image.dockerfile : container.image.reference;
56122
56136
  converted.max_instances = container.maxInstances;
56123
56137
  if ("dockerfile" in container.image) {
@@ -56146,6 +56160,13 @@ function convertContainer(container) {
56146
56160
  }
56147
56161
  return converted;
56148
56162
  }
56163
+ function convertDurableObjectContainerImage(image) {
56164
+ if ("reference" in image) return { image: image.reference };
56165
+ const converted = { dockerfile: image.dockerfile };
56166
+ if (image.buildContext !== void 0) converted.build_context = image.buildContext;
56167
+ if (image.buildVars !== void 0) converted.build_vars = image.buildVars;
56168
+ return converted;
56169
+ }
56149
56170
  function convertContainerObservability(observability) {
56150
56171
  const converted = {};
56151
56172
  if (observability.enabled !== void 0) converted.enabled = observability.enabled;
@@ -56810,6 +56831,15 @@ const CROSS_WORKER_BINDING_TYPES = new Set([
56810
56831
  "worker",
56811
56832
  "workflow"
56812
56833
  ]);
56834
+ /**
56835
+ * Selects the Container exports from a validated project configuration.
56836
+ *
56837
+ * @param config - Validated exports keyed by their JavaScript export names.
56838
+ * @returns Container configurations keyed by those same export names.
56839
+ */
56840
+ function getContainerConfigExports(config$2) {
56841
+ return Object.fromEntries(Object.entries(config$2).filter((entry) => entry[1]?.type === "container"));
56842
+ }
56813
56843
  function isRecord(value) {
56814
56844
  return typeof value === "object" && value !== null;
56815
56845
  }
@@ -57441,20 +57471,31 @@ async function writeWorkerConfig({ root, config: config$2, manifest, directoryNa
57441
57471
  await fsp.writeFile(getWorkerConfigPath(root, directoryName), JSON.stringify(outputConfig));
57442
57472
  }
57443
57473
  /**
57474
+ * Write an output Container `config.json` to the Build Output Specification
57475
+ * tree.
57476
+ *
57477
+ * Local Dockerfiles must already have been built and represented by a
57478
+ * `localReference` in the output config.
57479
+ */
57480
+ async function writeContainerConfig({ root, config: config$2, directoryName }) {
57481
+ await fsp.mkdir(getContainerDir(root, directoryName), { recursive: true });
57482
+ await fsp.writeFile(getContainerConfigPath(root, directoryName), JSON.stringify(config$2));
57483
+ }
57484
+ /**
57444
57485
  * Write the top-level `config.json` to the Build Output Specification tree.
57445
57486
  *
57446
- * Holds the project-level settings shared by every Worker: those declared by
57447
- * the `settings` export, including the `mode`, which is supplied at build time
57448
- * rather than declared. Always written, even when there are no declared
57449
- * settings and no mode: the result then degrades to `{ "type": "settings" }`.
57487
+ * Holds the project settings shared by every Worker, plus the build mode and
57488
+ * whether the build is for a Preview. Always written, even without declared
57489
+ * settings or a mode.
57450
57490
  *
57451
57491
  * `mode` is omitted when undefined, which is the case for Wrangler builds that
57452
57492
  * selected no mode (Vite always resolves one).
57453
57493
  */
57454
- async function writeSettingsConfig(root, settings, mode) {
57494
+ async function writeSettingsConfig(root, settings, mode, isPreview = false) {
57455
57495
  const outputConfig = {
57456
57496
  ...settings,
57457
57497
  type: "settings",
57498
+ ...isPreview ? { isPreview: true } : {},
57458
57499
  ...mode !== void 0 ? { mode } : {}
57459
57500
  };
57460
57501
  const configPath = getSettingsConfigPath(root);
@@ -57646,10 +57687,10 @@ function parseJson(contents, configPath) {
57646
57687
  * single-element array.
57647
57688
  */
57648
57689
  async function readBuildOutputWorkers(root) {
57649
- const { workers, settings } = await readBuildOutput(root);
57690
+ const { workers, settings, containers } = await readBuildOutput(root);
57650
57691
  const worker = workers[DEFAULT_WORKER_DIRECTORY_NAME];
57651
57692
  const { manifest,...inputShape } = worker.config;
57652
- const { config: config$2, diagnostics } = normalizeAndValidateConfig(convertToWranglerConfig(inputShape, settings), void 0, void 0, {}, true);
57693
+ const { config: config$2, diagnostics } = normalizeAndValidateConfig(convertToWranglerConfig(inputShape, settings, Object.values(containers).map(({ config: config$3 }) => convertOutputContainerToInput(config$3))), void 0, void 0, { enableContainers: false }, true);
57653
57694
  if (diagnostics.hasWarnings()) console.warn(diagnostics.renderWarnings());
57654
57695
  if (diagnostics.hasErrors()) throw new Error(diagnostics.renderErrors());
57655
57696
  if (worker.assetsDir) config$2.assets = {
@@ -57671,6 +57712,19 @@ async function readBuildOutputWorkers(root) {
57671
57712
  bundle
57672
57713
  }];
57673
57714
  }
57715
+ function convertOutputContainerToInput(config$2) {
57716
+ if (config$2.schedulingPolicy === "durable-object") {
57717
+ const { images: _images,...container } = config$2;
57718
+ return container;
57719
+ }
57720
+ return {
57721
+ ...config$2,
57722
+ image: convertOutputContainerImage(config$2.image)
57723
+ };
57724
+ }
57725
+ function convertOutputContainerImage(image) {
57726
+ return { reference: "reference" in image ? image.reference : image.localReference };
57727
+ }
57674
57728
 
57675
57729
  //#endregion
57676
57730
  //#region src/deploy-config.ts
@@ -64398,8 +64452,8 @@ function readWorkerConfig(configPath, env$3) {
64398
64452
  * validation pipeline as on-disk Wrangler config files, then apply the
64399
64453
  * Vite-specific sanitization.
64400
64454
  */
64401
- function readWorkerConfigFromRaw(rawConfig) {
64402
- const { config: config$2, diagnostics } = normalizeAndValidateConfig(rawConfig, void 0, void 0, {}, true);
64455
+ function readWorkerConfigFromRaw(rawConfig, configPath) {
64456
+ const { config: config$2, diagnostics } = normalizeAndValidateConfig(rawConfig, configPath, configPath, {}, true);
64403
64457
  if (diagnostics.hasWarnings()) console.warn(diagnostics.renderWarnings());
64404
64458
  if (diagnostics.hasErrors()) throw new Error(diagnostics.renderErrors());
64405
64459
  return processNormalizedWorkerConfig(config$2);
@@ -64598,7 +64652,7 @@ function resolveWorkerConfig(options) {
64598
64652
  let workerConfig;
64599
64653
  let raw;
64600
64654
  let nonApplicable;
64601
- if (options.rawConfigOverride) ({raw, config: workerConfig, nonApplicable} = readWorkerConfigFromRaw(options.rawConfigOverride));
64655
+ if (options.rawConfigOverride) ({raw, config: workerConfig, nonApplicable} = readWorkerConfigFromRaw(options.rawConfigOverride, options.rawConfigPath));
64602
64656
  else if (options.configPath) ({raw, config: workerConfig, nonApplicable} = readWorkerConfigFromFile(options.configPath, options.env, { visitedConfigPaths: options.visitedConfigPaths }));
64603
64657
  else {
64604
64658
  workerConfig = { ...wrangler.unstable_defaultWranglerConfig };
@@ -64687,7 +64741,8 @@ async function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
64687
64741
  env: cloudflareEnv,
64688
64742
  configCustomizer: resolvedNewConfig ? void 0 : pluginConfig.config,
64689
64743
  visitedConfigPaths: configPaths,
64690
- rawConfigOverride
64744
+ rawConfigOverride,
64745
+ rawConfigPath: resolvedNewConfig ? configPath : void 0
64691
64746
  });
64692
64747
  const environmentNameToWorkerMap = /* @__PURE__ */ new Map();
64693
64748
  const environmentNameToChildEnvironmentNamesMap = /* @__PURE__ */ new Map();
@@ -64818,11 +64873,14 @@ const EXPERIMENTAL_CONFIG_PKG = "@cloudflare/vite-plugin/experimental-config";
64818
64873
  async function loadNewConfig(options) {
64819
64874
  const configPath = path.resolve(options.root, NEW_CONFIG_FILENAME);
64820
64875
  if (!fs$1.existsSync(configPath)) throw new Error(`\`experimental.newConfig\` is enabled but no \`${NEW_CONFIG_FILENAME}\` was found at ${configPath}.`);
64821
- const { result, dependencies } = await loadAndValidateConfig(configPath, { mode: options.mode });
64876
+ const { result, dependencies } = await loadAndValidateConfig(configPath, {
64877
+ isPreview: isPreviewBuild(),
64878
+ mode: options.mode
64879
+ });
64822
64880
  if (!result.success) throw new Error(`Invalid \`${NEW_CONFIG_FILENAME}\`:\n${result.error.message}`);
64823
64881
  const worker = result.data.default?.type === "worker" ? result.data.default : void 0;
64824
64882
  if (worker === void 0) throw new Error(`\`${NEW_CONFIG_FILENAME}\` must have a default worker export.`);
64825
- const rawConfig = convertToWranglerConfig(worker, result.data.settings?.type === "settings" ? result.data.settings : void 0);
64883
+ const rawConfig = convertToWranglerConfig(worker, result.data.settings?.type === "settings" ? result.data.settings : void 0, Object.values(getContainerConfigExports(result.data)));
64826
64884
  if (options.command === "serve" && options.types.generate) await writeWorkerConfigurationDts({
64827
64885
  root: options.root,
64828
64886
  configPath,
@@ -66736,7 +66794,7 @@ const buildOutputPlugin = createPlugin("build-output", (ctx) => {
66736
66794
  if (ctx.resolvedPluginConfig.type === "preview") return;
66737
66795
  const settingsExport = ctx.resolvedPluginConfig.parsedNewConfig?.settings;
66738
66796
  const settings = settingsExport?.type === "settings" ? settingsExport : void 0;
66739
- await writeSettingsConfig(ctx.resolvedViteConfig.root, settings, ctx.resolvedViteConfig.mode);
66797
+ await writeSettingsConfig(ctx.resolvedViteConfig.root, settings, ctx.resolvedViteConfig.mode, isPreviewBuild());
66740
66798
  }
66741
66799
  });
66742
66800
  /**
@@ -68935,392 +68993,6 @@ function removeAssetsField(entryWorkerBuildDirectory) {
68935
68993
  fs$1.writeFileSync(entryWorkerConfigPath, JSON.stringify(workerConfig));
68936
68994
  }
68937
68995
 
68938
- //#endregion
68939
- //#region src/dev-vars.ts
68940
- /**
68941
- * Gets any variables with which to augment the Worker config in preview mode.
68942
- *
68943
- * Calls `unstable_getVarsForDev` with the current Cloudflare environment to get local dev variables from the .dev.vars/.env/process.env.
68944
- * When `secrets` is defined in the Worker config, only declared secrets are loaded.
68945
- */
68946
- function getLocalDevVarsForPreview(config$2, cloudflareEnv) {
68947
- const dotDevDotVars = wrangler.unstable_getVarsForDev(config$2.configPath, void 0, {}, cloudflareEnv, false, config$2.secrets);
68948
- const dotDevDotVarsEntries = Array.from(Object.entries(dotDevDotVars));
68949
- if (dotDevDotVarsEntries.length > 0) return dotDevDotVarsEntries.map(([key, { value }]) => {
68950
- return `${key}=${quoteForDotenv(value?.toString() ?? "")}\n`;
68951
- }).join("");
68952
- }
68953
- /**
68954
- * Quote a value so that wrangler reads it back unchanged when it parses
68955
- * `dist/<env>/.dev.vars` at preview time.
68956
- *
68957
- * Strategy: To quote the string pick the first quote character that does not
68958
- * appear in the value (single → backtick → double). Throw if a value cannot
68959
- * be losslessly serialized rather than silently corrupting it.
68960
- *
68961
- * @internal exported for tests
68962
- */
68963
- function quoteForDotenv(value) {
68964
- if (!value.includes("'")) return `'${value}'`;
68965
- if (!value.includes("`")) return `\`${value}\``;
68966
- if (!value.includes("\"") && !/[\\\n\r]/.test(value)) return `"${value}"`;
68967
- throw new Error("Unable to serialize value to .dev.vars: contains every supported quote character or unsafe escape sequence.");
68968
- }
68969
- /**
68970
- * Returns `true` if the `changedFile` matches a `.dev.vars` or `.env` file.
68971
- */
68972
- function hasLocalDevVarsFileChanged({ configPaths, cloudflareEnv }, changedFilePath) {
68973
- return [...configPaths].some((configPath) => {
68974
- const configDir = path.dirname(configPath);
68975
- return [
68976
- ".dev.vars",
68977
- ".env",
68978
- ...cloudflareEnv ? [`.dev.vars.${cloudflareEnv}`, `.env.${cloudflareEnv}`] : []
68979
- ].some((localDevFile) => changedFilePath === path.join(configDir, localDevFile));
68980
- });
68981
- }
68982
-
68983
- //#endregion
68984
- //#region src/vite-config.ts
68985
- const NODE_BUILTIN_SET = new Set([...builtinModules, ...builtinModules.filter((m) => !m.startsWith("node:")).map((m) => `node:${m}`)]);
68986
- function isOnlyNodeBuiltins(external) {
68987
- if (!Array.isArray(external)) return false;
68988
- return external.every((entry) => typeof entry === "string" && NODE_BUILTIN_SET.has(entry));
68989
- }
68990
- /**
68991
- * Throws an error if Worker environments include configuration options that are incompatible with the plugin.
68992
- */
68993
- function validateWorkerEnvironmentOptions(resolvedPluginConfig, resolvedViteConfig) {
68994
- const disallowedEnvironmentOptionsMap = /* @__PURE__ */ new Map();
68995
- for (const environmentName of resolvedPluginConfig.environmentNameToWorkerMap.keys()) {
68996
- const environmentOptions = resolvedViteConfig.environments[environmentName];
68997
- assert2(environmentOptions, `Missing environment config for "${environmentName}"`);
68998
- const { resolve: resolve$4 } = environmentOptions;
68999
- const disallowedEnvironmentOptions = {};
69000
- if ((resolve$4.external === true || Array.isArray(resolve$4.external) && resolve$4.external.length > 0) && !isOnlyNodeBuiltins(resolve$4.external)) disallowedEnvironmentOptions.resolveExternal = resolve$4.external;
69001
- if (Object.keys(disallowedEnvironmentOptions).length) disallowedEnvironmentOptionsMap.set(environmentName, disallowedEnvironmentOptions);
69002
- }
69003
- if (disallowedEnvironmentOptionsMap.size) {
69004
- const errorMessage = `The following environment options are incompatible with the Cloudflare Vite plugin:\n${[...disallowedEnvironmentOptionsMap].map(([environmentName, disallowedEnvironmentOptions]) => disallowedEnvironmentOptions.resolveExternal && ` - "${environmentName}" environment: \`resolve.external\`: ${JSON.stringify(disallowedEnvironmentOptions.resolveExternal)}\n`).join("")}To resolve this issue, avoid setting \`resolve.external\` in your Cloudflare Worker environments.\n`;
69005
- throw new Error(errorMessage);
69006
- }
69007
- }
69008
-
69009
- //#endregion
69010
- //#region src/plugins/wrangler-watch-ignore.ts
69011
- const WRANGLER_STATE_WATCH_IGNORE = "**/.wrangler/**";
69012
- /**
69013
- * Keep Miniflare persistence writes out of Vite's file watcher without
69014
- * replacing any ignore patterns the user already configured.
69015
- *
69016
- * @param userIgnored - Existing `server.watch.ignored` patterns, if any
69017
- * @returns Ignore patterns that always include `.wrangler` directories
69018
- */
69019
- function withWranglerStateIgnored(userIgnored) {
69020
- if (userIgnored == null) return WRANGLER_STATE_WATCH_IGNORE;
69021
- if (Array.isArray(userIgnored)) return [...userIgnored, WRANGLER_STATE_WATCH_IGNORE];
69022
- return [userIgnored, WRANGLER_STATE_WATCH_IGNORE];
69023
- }
69024
- /**
69025
- * Merge `.wrangler` into Vite's `server.watch` config.
69026
- *
69027
- * Returns `null` when the user disabled watching with `server.watch: null`,
69028
- * so this plugin does not turn the watcher back on.
69029
- *
69030
- * @param userWatch - The user's `server.watch` value from Vite config
69031
- * @returns `null` when watching is disabled, otherwise a watch object whose
69032
- * `ignored` list includes `.wrangler` directories
69033
- */
69034
- function getServerWatchConfig(userWatch) {
69035
- if (userWatch === null) return null;
69036
- return {
69037
- ...userWatch,
69038
- ignored: withWranglerStateIgnored(userWatch?.ignored)
69039
- };
69040
- }
69041
-
69042
- //#endregion
69043
- //#region src/plugins/config.ts
69044
- /**
69045
- * Plugin to handle configuration and config file watching
69046
- */
69047
- const configPlugin = createPlugin("config", (ctx) => {
69048
- return {
69049
- config(userConfig, env$3) {
69050
- if (ctx.resolvedPluginConfig.type === "preview") return { appType: "custom" };
69051
- if (!ctx.hasShownWorkerConfigWarnings) {
69052
- ctx.setHasShownWorkerConfigWarnings(true);
69053
- const workerConfigWarnings = getWarningForWorkersConfigs(ctx.resolvedPluginConfig.rawConfigs);
69054
- if (workerConfigWarnings) console.warn(workerConfigWarnings);
69055
- }
69056
- return {
69057
- appType: "custom",
69058
- server: {
69059
- allowedHosts: getAllowedHosts(ctx.getTunnelHostnames(), userConfig.server?.allowedHosts),
69060
- watch: getServerWatchConfig(userConfig.server?.watch),
69061
- fs: { deny: [...[
69062
- ".env",
69063
- ".env.*",
69064
- ".npmrc",
69065
- ".yarnrc",
69066
- ".yarnrc.yml",
69067
- "*.{crt,pem,key,pfx,p12,p8,jks}",
69068
- "**/.git/**",
69069
- ".dev.vars",
69070
- ".dev.vars.*",
69071
- "**/.wrangler/**"
69072
- ], ...Array.from(ctx.resolvedPluginConfig.configPaths, (configPath) => normalizePath(configPath))] }
69073
- },
69074
- environments: getEnvironmentsConfig(ctx, userConfig, env$3.mode),
69075
- builder: { buildApp: userConfig.builder?.buildApp ?? createBuildApp(ctx.resolvedPluginConfig) }
69076
- };
69077
- },
69078
- async configResolved(resolvedViteConfig) {
69079
- ctx.setResolvedViteConfig(resolvedViteConfig);
69080
- if (ctx.resolvedPluginConfig.type === "preview") return;
69081
- validateWorkerEnvironmentOptions(ctx.resolvedPluginConfig, ctx.resolvedViteConfig);
69082
- if (ctx.resolvedPluginConfig.experimental.newConfig?.cfBuildOutput) {
69083
- forceBuildOutputDirs(ctx.resolvedPluginConfig, ctx.resolvedViteConfig);
69084
- if (ctx.resolvedViteConfig.command === "build") await cleanBuildOutputDir(ctx.resolvedViteConfig.root);
69085
- }
69086
- },
69087
- buildStart() {
69088
- ctx.setHasShownWorkerConfigWarnings(false);
69089
- },
69090
- configureServer(viteDevServer) {
69091
- let restartInFlight = false;
69092
- const configChangedHandler = async (changedFilePath) => {
69093
- assertIsNotPreview(ctx);
69094
- if (restartInFlight) return;
69095
- if (ctx.resolvedPluginConfig.configPaths.has(changedFilePath) || hasLocalDevVarsFileChanged(ctx.resolvedPluginConfig, changedFilePath) || hasAssetsConfigChanged(ctx.resolvedPluginConfig, ctx.resolvedViteConfig, changedFilePath)) {
69096
- debuglog("Config changed: " + changedFilePath);
69097
- restartInFlight = true;
69098
- debuglog("Restarting dev server and aborting previous setup");
69099
- try {
69100
- await viteDevServer.restart();
69101
- } finally {
69102
- restartInFlight = false;
69103
- }
69104
- }
69105
- };
69106
- viteDevServer.watcher.on("change", configChangedHandler);
69107
- },
69108
- buildApp: {
69109
- order: "post",
69110
- async handler(builder) {
69111
- if (ctx.resolvedPluginConfig.type !== "workers") return;
69112
- const workerEnvironments = [...ctx.resolvedPluginConfig.environmentNameToWorkerMap.entries()].filter(([_, worker]) => !resolveDevOnly(worker.devOnly)).map(([environmentName]) => {
69113
- const environment = builder.environments[environmentName];
69114
- assert2(environment, `"${environmentName}" environment not found`);
69115
- return environment;
69116
- });
69117
- await Promise.all(workerEnvironments.filter((environment) => !environment.isBuilt).map((environment) => builder.build(environment)));
69118
- const { entryWorkerEnvironmentName } = ctx.resolvedPluginConfig;
69119
- const entryWorkerEnvironment = builder.environments[entryWorkerEnvironmentName];
69120
- assert2(entryWorkerEnvironment, `No "${entryWorkerEnvironmentName}" environment`);
69121
- const cfBuildOutput = ctx.resolvedPluginConfig.experimental.newConfig?.cfBuildOutput === true;
69122
- if (entryWorkerEnvironment.isBuilt) {
69123
- if (!builder.environments.client?.isBuilt && !cfBuildOutput) removeAssetsField(path.resolve(builder.config.root, entryWorkerEnvironment.config.build.outDir));
69124
- } else {
69125
- const clientEnvironment = builder.environments.client;
69126
- assert2(clientEnvironment, "No \"client\" environment");
69127
- if (!clientEnvironment.isBuilt) throw new Error("If `assetsOnly` is set to `true`, the client environment must be built");
69128
- if (cfBuildOutput) {
69129
- const entryWorkerNewConfig = ctx.getWorkerNewConfig(entryWorkerEnvironmentName);
69130
- assert2(entryWorkerNewConfig, `No config found for "${entryWorkerEnvironmentName}" environment`);
69131
- await writeWorkerConfig({
69132
- root: builder.config.root,
69133
- config: entryWorkerNewConfig
69134
- });
69135
- } else {
69136
- const entryWorkerConfig = ctx.getWorkerConfig(entryWorkerEnvironmentName);
69137
- assert2(entryWorkerConfig, `No config found for "${entryWorkerEnvironmentName}" environment`);
69138
- const outputConfig = {
69139
- ...entryWorkerConfig,
69140
- main: void 0,
69141
- assets: {
69142
- ...entryWorkerConfig.assets,
69143
- directory: ".",
69144
- binding: void 0
69145
- }
69146
- };
69147
- if (outputConfig.unsafe && Object.keys(outputConfig.unsafe).length === 0) outputConfig.unsafe = void 0;
69148
- fs$1.writeFileSync(path.resolve(builder.config.root, clientEnvironment.config.build.outDir, "wrangler.json"), JSON.stringify(outputConfig));
69149
- writeDeployConfig(ctx.resolvedPluginConfig, ctx.resolvedViteConfig, true);
69150
- }
69151
- }
69152
- }
69153
- }
69154
- };
69155
- });
69156
- /**
69157
- * Generates the environment configuration for all Worker environments.
69158
- */
69159
- function getEnvironmentsConfig(ctx, userConfig, mode) {
69160
- assertIsNotPreview(ctx);
69161
- if (!ctx.resolvedPluginConfig.environmentNameToWorkerMap.size) return;
69162
- return {
69163
- ...Object.fromEntries([...ctx.resolvedPluginConfig.environmentNameToWorkerMap].flatMap(([environmentName, worker]) => {
69164
- const childEnvironmentNames = ctx.resolvedPluginConfig.environmentNameToChildEnvironmentNamesMap.get(environmentName) ?? [];
69165
- const sharedOptions = {
69166
- workerConfig: worker.config,
69167
- userConfig,
69168
- mode,
69169
- hasNodeJsCompat: ctx.getNodeJsCompat(environmentName) !== void 0
69170
- };
69171
- const isEntryWorker = environmentName === ctx.resolvedPluginConfig.prerenderWorkerEnvironmentName || ctx.resolvedPluginConfig.type === "workers" && environmentName === ctx.resolvedPluginConfig.entryWorkerEnvironmentName;
69172
- return [[environmentName, createCloudflareEnvironmentOptions({
69173
- ...sharedOptions,
69174
- environmentName,
69175
- isEntryWorker,
69176
- isParentEnvironment: true
69177
- })], ...childEnvironmentNames.map((childEnvironmentName) => [childEnvironmentName, createCloudflareEnvironmentOptions({
69178
- ...sharedOptions,
69179
- environmentName: childEnvironmentName,
69180
- isEntryWorker: false,
69181
- isParentEnvironment: false
69182
- })])];
69183
- })),
69184
- client: {
69185
- build: { outDir: getOutputDirectory(userConfig, "client") },
69186
- optimizeDeps: { exclude: [...cloudflareBuiltInModules] }
69187
- }
69188
- };
69189
- }
69190
- /**
69191
- * When the Build Output Specification is enabled,
69192
- * force every Worker environment's and the client environment's `build.outDir`
69193
- * to the spec-mandated location.
69194
- *
69195
- * Runs after Vite's merge in `configResolved`, so it overrides any
69196
- * user-supplied `build.outDir`
69197
- */
69198
- function forceBuildOutputDirs(resolvedPluginConfig, resolvedViteConfig) {
69199
- if (!resolvedPluginConfig.experimental.newConfig?.cfBuildOutput) return;
69200
- const { root } = resolvedViteConfig;
69201
- if (resolvedPluginConfig.type === "workers") {
69202
- const entryName = resolvedPluginConfig.entryWorkerEnvironmentName;
69203
- const entryEnvironment = resolvedViteConfig.environments[entryName];
69204
- if (entryEnvironment) entryEnvironment.build.outDir = getWorkerBundleDir(root);
69205
- }
69206
- const clientEnvironment = resolvedViteConfig.environments.client;
69207
- if (clientEnvironment) clientEnvironment.build.outDir = getWorkerAssetsDir(root);
69208
- }
69209
- function getAllowedHosts(tunnelHostnames, userAllowedHosts) {
69210
- if (tunnelHostnames.length === 0 || userAllowedHosts === true) return userAllowedHosts;
69211
- return Array.from(new Set([...userAllowedHosts ?? [], ...tunnelHostnames]));
69212
- }
69213
-
69214
- //#endregion
69215
- //#region src/debug.ts
69216
- var import_picocolors$3 = /* @__PURE__ */ __toESM$1(require_picocolors(), 1);
69217
- const DEBUG_PATH = "/__debug";
69218
- const DEFAULT_INSPECTOR_PORT = 9229;
69219
- /**
69220
- * Gets the inspector port option that should be passed to Miniflare based on the user's plugin config
69221
- */
69222
- async function getInputInspectorPort(ctx, viteServer) {
69223
- if (ctx.resolvedPluginConfig.inspectorPort === void 0 || ctx.resolvedPluginConfig.inspectorPort === 0) {
69224
- const resolvedInspectorPort = await ctx.getResolvedInspectorPort();
69225
- if (resolvedInspectorPort !== null) return resolvedInspectorPort;
69226
- }
69227
- const inputInspectorPort = ctx.resolvedPluginConfig.inspectorPort ?? await getFirstAvailablePort(DEFAULT_INSPECTOR_PORT);
69228
- if (ctx.resolvedPluginConfig.inspectorPort === void 0 && inputInspectorPort !== DEFAULT_INSPECTOR_PORT) viteServer.config.logger.warn(import_picocolors$3.default.dim(`Default inspector port ${DEFAULT_INSPECTOR_PORT} not available, using ${inputInspectorPort} instead\n`));
69229
- return inputInspectorPort;
69230
- }
69231
- function getFirstAvailablePort(start) {
69232
- return getPorts({ port: portNumbers(start, 65535) });
69233
- }
69234
- /**
69235
- * Modifies the URL printing logic to also include a URL that developers can use to open DevTools to debug their Worker(s)
69236
- */
69237
- function addDebugToVitePrintUrls(server) {
69238
- const originalPrintUrls = server.printUrls;
69239
- server.printUrls = () => {
69240
- originalPrintUrls();
69241
- const localUrl = server.resolvedUrls?.local[0];
69242
- if (localUrl) {
69243
- const { protocol, hostname: hostname$1, port } = new URL(localUrl);
69244
- const colorDebugUrl = (url$2) => import_picocolors$3.default.dim(import_picocolors$3.default.yellow(url$2.replace(/:(\d+)\//, (_, portNumber) => `:${import_picocolors$3.default.bold(portNumber)}/`)));
69245
- server.config.logger.info(` ${import_picocolors$3.default.green("➜")} ${import_picocolors$3.default.bold("Debug")}: ${colorDebugUrl(`${protocol}//${hostname$1}:${port}${DEBUG_PATH}`)}`);
69246
- }
69247
- };
69248
- }
69249
- /**
69250
- * Generate HTML that comprises a single script that:
69251
- * - redirects the page to the DevTools for debugging the first available Worker
69252
- * - opens tabs to the DevTools for all the remaining workers if any
69253
- *
69254
- * Note: this works based on the Miniflare inspector proxy logic (where Workers are available via
69255
- * their names)
69256
- */
69257
- function getDebugPathHtml(workerNames, inspectorPort) {
69258
- assert2(workerNames.length >= 1, "no workers present to debug");
69259
- const workerDevtoolsUrls = workerNames.map((workerName) => {
69260
- const localhost = `localhost:${inspectorPort}/${workerName}`;
69261
- return `https://devtools.devprod.cloudflare.dev/js_app?${new URLSearchParams({
69262
- theme: "systemPreferred",
69263
- debugger: "true",
69264
- ws: localhost,
69265
- domain: workerName
69266
- })}`;
69267
- });
69268
- return `
69269
- <script>
69270
- const workerUrls = ${JSON.stringify(workerDevtoolsUrls)};
69271
- const [firstUrl, ...rest] = workerUrls;
69272
- for (const workerUrl of rest) {
69273
- // open new tabs for the devtools of the various workers
69274
- window.open(workerUrl);
69275
- }
69276
- // redirect the current tab to the devtools of the first worker
69277
- window.location.replace(firstUrl);
69278
- <\/script>
69279
- `;
69280
- }
69281
-
69282
- //#endregion
69283
- //#region src/plugins/debug.ts
69284
- /**
69285
- * Plugin to provide a `/__debug` path for debugging Workers
69286
- */
69287
- const debugPlugin = createPlugin("debug", (ctx) => {
69288
- return {
69289
- enforce: "pre",
69290
- configureServer(viteDevServer) {
69291
- assertIsNotPreview(ctx);
69292
- if (!!process.env.VSCODE_INSPECTOR_OPTIONS) return;
69293
- if (ctx.resolvedPluginConfig.type === "workers" && ctx.resolvedPluginConfig.inspectorPort !== false) addDebugToVitePrintUrls(viteDevServer);
69294
- const workerNames = ctx.resolvedPluginConfig.type === "workers" ? [...ctx.resolvedPluginConfig.environmentNameToWorkerMap.values()].map((worker) => worker.config.name) : [];
69295
- viteDevServer.middlewares.use(DEBUG_PATH, async (_, res, next) => {
69296
- const resolvedInspectorPort = await ctx.getResolvedInspectorPort();
69297
- if (resolvedInspectorPort) {
69298
- const html = getDebugPathHtml(workerNames, resolvedInspectorPort);
69299
- res.setHeader("Content-Type", "text/html");
69300
- res.end(html);
69301
- } else next();
69302
- });
69303
- },
69304
- async configurePreviewServer(vitePreviewServer) {
69305
- assertIsPreview(ctx);
69306
- if (!!process.env.VSCODE_INSPECTOR_OPTIONS) return;
69307
- if (ctx.resolvedPluginConfig.workers.length >= 1 && ctx.resolvedPluginConfig.inspectorPort !== false) addDebugToVitePrintUrls(vitePreviewServer);
69308
- const workerNames = ctx.resolvedPluginConfig.workers.map((worker) => {
69309
- assert2(worker.config.name, "Expected the Worker to have a name");
69310
- return worker.config.name;
69311
- });
69312
- vitePreviewServer.middlewares.use(DEBUG_PATH, async (_, res, next) => {
69313
- const resolvedInspectorPort = await ctx.getResolvedInspectorPort();
69314
- if (resolvedInspectorPort) {
69315
- const html = getDebugPathHtml(workerNames, resolvedInspectorPort);
69316
- res.setHeader("Content-Type", "text/html");
69317
- res.end(html);
69318
- } else next();
69319
- });
69320
- }
69321
- };
69322
- });
69323
-
69324
68996
  //#endregion
69325
68997
  //#region ../cli/dist/colors.mjs
69326
68998
  const { white, gray, dim, hidden, bold, cyanBright, bgCyan } = source_default;
@@ -72024,11 +71696,11 @@ var getQueryString = /* @__PURE__ */ __name$2((params) => {
72024
71696
  }, "getQueryString");
72025
71697
  var getUrl = /* @__PURE__ */ __name$2((config$2, options) => {
72026
71698
  const encoder$1 = config$2.ENCODE_PATH || encodeURI;
72027
- const path2 = options.url.replace("{api-version}", config$2.VERSION).replace(/{(.*?)}/g, (substring, group) => {
71699
+ const path3 = options.url.replace("{api-version}", config$2.VERSION).replace(/{(.*?)}/g, (substring, group) => {
72028
71700
  if (options.path?.hasOwnProperty(group)) return encoder$1(String(options.path[group]));
72029
71701
  return substring;
72030
71702
  });
72031
- const url$2 = `${config$2.BASE}${path2}`;
71703
+ const url$2 = `${config$2.BASE}${path3}`;
72032
71704
  if (options.query) return `${url$2}${getQueryString(options.query)}`;
72033
71705
  return url$2;
72034
71706
  }, "getUrl");
@@ -74349,6 +74021,11 @@ async function getContainerAccount(accountId, complianceConfig) {
74349
74021
  return await fetchResult$1(complianceConfig ?? {}, `/accounts/${accountId}/containers/me`);
74350
74022
  }
74351
74023
  __name$2(getContainerAccount, "getContainerAccount");
74024
+ var MAX_DOCKER_REPOSITORY_NAME_LENGTH = 255;
74025
+ function normalizeContainerImageRepositoryName(value) {
74026
+ return value.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/[._-]+/g, (separators) => separators === "." || separators === "_" || separators === "__" || /^-+$/.test(separators) ? separators : "-").replace(/^[._-]+|[._-]+$/g, "").slice(0, MAX_DOCKER_REPOSITORY_NAME_LENGTH).replace(/[._-]+$/g, "") || "container";
74027
+ }
74028
+ __name$2(normalizeContainerImageRepositoryName, "normalizeContainerImageRepositoryName");
74352
74029
  function isDockerfileContainerConfig(container) {
74353
74030
  return "dockerfile" in container;
74354
74031
  }
@@ -74591,7 +74268,7 @@ async function buildAndMaybePush(args, pathToDocker, push, containerConfig, veri
74591
74268
  }
74592
74269
  __name$2(buildAndMaybePush, "buildAndMaybePush");
74593
74270
  async function buildContainerImage(containerConfig, pathToDocker, verifyDockerIsRunning) {
74594
- const localTag = `${getContainerImageRepositoryName(containerConfig)}:wrangler-${crypto$1.randomUUID()}`;
74271
+ const localTag = `${getContainerImageRepositoryName(containerConfig)}:wrangler-${crypto2.randomUUID()}`;
74595
74272
  logger$1.log("Building image", localTag);
74596
74273
  try {
74597
74274
  await (await startContainerBuild({
@@ -74729,6 +74406,157 @@ async function dockerBuild(dockerPath, options) {
74729
74406
  };
74730
74407
  }
74731
74408
  __name$2(dockerBuild, "dockerBuild");
74409
+ var BUILD_OUTPUT_IMAGE_NAMESPACE = "cloudflare-build";
74410
+ var DOCKER_REPOSITORY_NAME_LENGTH = 255;
74411
+ async function buildAndWriteContainerOutput(options) {
74412
+ const containers = Object.entries(options.containers);
74413
+ await cleanupPreviousBuildOutputImageTags({
74414
+ root: options.root,
74415
+ pathToDocker: options.pathToDocker
74416
+ });
74417
+ const buildId = createBuildId();
74418
+ const localTags = /* @__PURE__ */ new Set();
74419
+ try {
74420
+ const dockerfileCount = countDockerfiles(containers);
74421
+ if (dockerfileCount > 0) await verifyDockerInstalled({
74422
+ dockerPath: options.pathToDocker,
74423
+ operation: "building the project",
74424
+ imageNoun: dockerfileCount === 1 ? "the configured image" : "the configured images"
74425
+ });
74426
+ const outputConfigs = [];
74427
+ try {
74428
+ for (const [directoryName, config$2] of containers) outputConfigs.push({
74429
+ root: options.root,
74430
+ directoryName,
74431
+ config: await buildContainerOutputConfig({
74432
+ config: config$2,
74433
+ root: options.root,
74434
+ pathToDocker: options.pathToDocker,
74435
+ buildId,
74436
+ localTags
74437
+ })
74438
+ });
74439
+ } catch (error$2) {
74440
+ throwBuildError(error$2);
74441
+ }
74442
+ for (const outputConfig of outputConfigs) await writeContainerConfig(outputConfig);
74443
+ } catch (error$2) {
74444
+ await Promise.allSettled([cleanBuildOutputDir(options.root), cleanupBuiltImages(Array.from(localTags, (localTag) => ({ localTag })), options.pathToDocker)]);
74445
+ throw error$2;
74446
+ }
74447
+ }
74448
+ __name$2(buildAndWriteContainerOutput, "buildAndWriteContainerOutput");
74449
+ async function buildContainerOutputConfig(options) {
74450
+ if (options.config.schedulingPolicy === "durable-object") {
74451
+ if (options.config.images === void 0) return {
74452
+ ...options.config,
74453
+ images: void 0
74454
+ };
74455
+ const images = {};
74456
+ for (const [imageName, image2] of Object.entries(options.config.images)) images[imageName] = await buildContainerImage2({
74457
+ image: image2,
74458
+ repositoryName: `${options.config.name}-${imageName}`,
74459
+ root: options.root,
74460
+ pathToDocker: options.pathToDocker,
74461
+ buildId: options.buildId,
74462
+ localTags: options.localTags
74463
+ });
74464
+ return {
74465
+ ...options.config,
74466
+ images
74467
+ };
74468
+ }
74469
+ const image = await buildContainerImage2({
74470
+ image: options.config.image,
74471
+ repositoryName: options.config.name,
74472
+ root: options.root,
74473
+ pathToDocker: options.pathToDocker,
74474
+ buildId: options.buildId,
74475
+ localTags: options.localTags
74476
+ });
74477
+ return {
74478
+ ...options.config,
74479
+ image
74480
+ };
74481
+ }
74482
+ __name$2(buildContainerOutputConfig, "buildContainerOutputConfig");
74483
+ async function buildContainerImage2(options) {
74484
+ if ("reference" in options.image) return { reference: options.image.reference };
74485
+ const pathToDockerfile = path__default.resolve(options.root, options.image.dockerfile);
74486
+ const localTag = createBuildOutputImageTag({
74487
+ root: options.root,
74488
+ repositoryName: options.repositoryName,
74489
+ buildId: options.buildId
74490
+ });
74491
+ if (options.localTags.has(localTag)) throw new UserError(`Container image name ${JSON.stringify(options.repositoryName)} conflicts with another image after Docker name normalization.`, { telemetryMessage: "container build output image name conflict" });
74492
+ await (await startContainerBuild({
74493
+ build: {
74494
+ tag: localTag,
74495
+ pathToDockerfile,
74496
+ buildContext: options.image.buildContext === void 0 ? path__default.dirname(pathToDockerfile) : path__default.resolve(options.root, options.image.buildContext),
74497
+ args: options.image.buildVars,
74498
+ platform: "linux/amd64"
74499
+ },
74500
+ pathToDocker: options.pathToDocker,
74501
+ verifyDockerIsRunning: false
74502
+ })).ready;
74503
+ options.localTags.add(localTag);
74504
+ return { localReference: localTag };
74505
+ }
74506
+ __name$2(buildContainerImage2, "buildContainerImage");
74507
+ function createBuildOutputImageTag(options) {
74508
+ const repositoryPrefix = getBuildOutputImageRepositoryPrefix(options.root);
74509
+ const maxNameLength = DOCKER_REPOSITORY_NAME_LENGTH - repositoryPrefix.length;
74510
+ return `${repositoryPrefix}${normalizeContainerImageRepositoryName(options.repositoryName).slice(0, maxNameLength).replace(/[._-]+$/g, "")}:${options.buildId}`;
74511
+ }
74512
+ __name$2(createBuildOutputImageTag, "createBuildOutputImageTag");
74513
+ async function cleanupPreviousBuildOutputImageTags(options) {
74514
+ const repositoryPrefix = getBuildOutputImageRepositoryPrefix(options.root);
74515
+ let existingTags;
74516
+ try {
74517
+ const output = runDockerCmdWithOutput(options.pathToDocker, [
74518
+ "image",
74519
+ "ls",
74520
+ "--filter",
74521
+ `reference=${repositoryPrefix}*`,
74522
+ "--format",
74523
+ "{{.Repository}}:{{.Tag}}"
74524
+ ]);
74525
+ existingTags = output === "" ? [] : output.split(/\r?\n/);
74526
+ } catch {
74527
+ return;
74528
+ }
74529
+ if (existingTags.length > 0) await cleanupBuiltImages(existingTags.map((localTag) => ({ localTag })), options.pathToDocker);
74530
+ }
74531
+ __name$2(cleanupPreviousBuildOutputImageTags, "cleanupPreviousBuildOutputImageTags");
74532
+ function getBuildOutputImageRepositoryPrefix(root) {
74533
+ return `${BUILD_OUTPUT_IMAGE_NAMESPACE}/${shortHash(path__default.resolve(root))}/`;
74534
+ }
74535
+ __name$2(getBuildOutputImageRepositoryPrefix, "getBuildOutputImageRepositoryPrefix");
74536
+ function shortHash(value) {
74537
+ return crypto2.createHash("sha256").update(value).digest("hex").slice(0, 12);
74538
+ }
74539
+ __name$2(shortHash, "shortHash");
74540
+ function createBuildId() {
74541
+ return crypto2.randomUUID().replaceAll("-", "").slice(0, 12);
74542
+ }
74543
+ __name$2(createBuildId, "createBuildId");
74544
+ function countDockerfiles(containers) {
74545
+ let count = 0;
74546
+ for (const [, config$2] of containers) if (config$2.schedulingPolicy === "durable-object") count += Object.values(config$2.images ?? {}).filter((image) => "dockerfile" in image).length;
74547
+ else if ("dockerfile" in config$2.image) count++;
74548
+ return count;
74549
+ }
74550
+ __name$2(countDockerfiles, "countDockerfiles");
74551
+ function throwBuildError(error$2) {
74552
+ if (error$2 instanceof UserError) throw error$2;
74553
+ if (error$2 instanceof Error) throw new UserError(error$2.message, {
74554
+ cause: error$2,
74555
+ telemetryMessage: "container build image operation failed"
74556
+ });
74557
+ throw new UserError("An unknown error occurred", { telemetryMessage: "container build unknown error" });
74558
+ }
74559
+ __name$2(throwBuildError, "throwBuildError");
74732
74560
  var Diff = class {
74733
74561
  static {
74734
74562
  __name$2(this, "Diff");
@@ -74893,10 +74721,10 @@ var Diff = class {
74893
74721
  print(options = { contextLines: 3 }) {
74894
74722
  log$1(this.toString(options));
74895
74723
  }
74896
- #addToPath(path2, added, removed, oldPosInc) {
74897
- const last = path2.lastComponent;
74724
+ #addToPath(path3, added, removed, oldPosInc) {
74725
+ const last = path3.lastComponent;
74898
74726
  if (last && last.added === added && last.removed === removed) return {
74899
- oldPos: path2.oldPos + oldPosInc,
74727
+ oldPos: path3.oldPos + oldPosInc,
74900
74728
  lastComponent: {
74901
74729
  count: last.count + 1,
74902
74730
  added,
@@ -74905,7 +74733,7 @@ var Diff = class {
74905
74733
  }
74906
74734
  };
74907
74735
  return {
74908
- oldPos: path2.oldPos + oldPosInc,
74736
+ oldPos: path3.oldPos + oldPosInc,
74909
74737
  lastComponent: {
74910
74738
  count: 1,
74911
74739
  added,
@@ -75509,6 +75337,412 @@ function createContainerDevPlan(options) {
75509
75337
  }
75510
75338
  __name$2(createContainerDevPlan, "createContainerDevPlan");
75511
75339
 
75340
+ //#endregion
75341
+ //#region src/build-output-containers.ts
75342
+ /**
75343
+ * Build and write the Container portion of the Build Output Specification.
75344
+ *
75345
+ * @param resolvedPluginConfig - The resolved Cloudflare Vite plugin config.
75346
+ * @param root - The Vite project root and Build Output root.
75347
+ */
75348
+ async function buildOutputContainers(resolvedPluginConfig, root) {
75349
+ if (resolvedPluginConfig.type === "preview" || resolvedPluginConfig.experimental.newConfig?.cfBuildOutput !== true) return;
75350
+ const config$2 = resolvedPluginConfig.parsedNewConfig;
75351
+ if (config$2 === void 0) return;
75352
+ await buildAndWriteContainerOutput({
75353
+ containers: getContainerConfigExports(config$2),
75354
+ root,
75355
+ pathToDocker: getDockerPath$1()
75356
+ });
75357
+ }
75358
+
75359
+ //#endregion
75360
+ //#region src/dev-vars.ts
75361
+ /**
75362
+ * Gets any variables with which to augment the Worker config in preview mode.
75363
+ *
75364
+ * Calls `unstable_getVarsForDev` with the current Cloudflare environment to get local dev variables from the .dev.vars/.env/process.env.
75365
+ * When `secrets` is defined in the Worker config, only declared secrets are loaded.
75366
+ */
75367
+ function getLocalDevVarsForPreview(config$2, cloudflareEnv) {
75368
+ const dotDevDotVars = wrangler.unstable_getVarsForDev(config$2.configPath, void 0, {}, cloudflareEnv, false, config$2.secrets);
75369
+ const dotDevDotVarsEntries = Array.from(Object.entries(dotDevDotVars));
75370
+ if (dotDevDotVarsEntries.length > 0) return dotDevDotVarsEntries.map(([key, { value }]) => {
75371
+ return `${key}=${quoteForDotenv(value?.toString() ?? "")}\n`;
75372
+ }).join("");
75373
+ }
75374
+ /**
75375
+ * Quote a value so that wrangler reads it back unchanged when it parses
75376
+ * `dist/<env>/.dev.vars` at preview time.
75377
+ *
75378
+ * Strategy: To quote the string pick the first quote character that does not
75379
+ * appear in the value (single → backtick → double). Throw if a value cannot
75380
+ * be losslessly serialized rather than silently corrupting it.
75381
+ *
75382
+ * @internal exported for tests
75383
+ */
75384
+ function quoteForDotenv(value) {
75385
+ if (!value.includes("'")) return `'${value}'`;
75386
+ if (!value.includes("`")) return `\`${value}\``;
75387
+ if (!value.includes("\"") && !/[\\\n\r]/.test(value)) return `"${value}"`;
75388
+ throw new Error("Unable to serialize value to .dev.vars: contains every supported quote character or unsafe escape sequence.");
75389
+ }
75390
+ /**
75391
+ * Returns `true` if the `changedFile` matches a `.dev.vars` or `.env` file.
75392
+ */
75393
+ function hasLocalDevVarsFileChanged({ configPaths, cloudflareEnv }, changedFilePath) {
75394
+ return [...configPaths].some((configPath) => {
75395
+ const configDir = path.dirname(configPath);
75396
+ return [
75397
+ ".dev.vars",
75398
+ ".env",
75399
+ ...cloudflareEnv ? [`.dev.vars.${cloudflareEnv}`, `.env.${cloudflareEnv}`] : []
75400
+ ].some((localDevFile) => changedFilePath === path.join(configDir, localDevFile));
75401
+ });
75402
+ }
75403
+
75404
+ //#endregion
75405
+ //#region src/vite-config.ts
75406
+ const NODE_BUILTIN_SET = new Set([...builtinModules, ...builtinModules.filter((m) => !m.startsWith("node:")).map((m) => `node:${m}`)]);
75407
+ function isOnlyNodeBuiltins(external) {
75408
+ if (!Array.isArray(external)) return false;
75409
+ return external.every((entry) => typeof entry === "string" && NODE_BUILTIN_SET.has(entry));
75410
+ }
75411
+ /**
75412
+ * Throws an error if Worker environments include configuration options that are incompatible with the plugin.
75413
+ */
75414
+ function validateWorkerEnvironmentOptions(resolvedPluginConfig, resolvedViteConfig) {
75415
+ const disallowedEnvironmentOptionsMap = /* @__PURE__ */ new Map();
75416
+ for (const environmentName of resolvedPluginConfig.environmentNameToWorkerMap.keys()) {
75417
+ const environmentOptions = resolvedViteConfig.environments[environmentName];
75418
+ assert2(environmentOptions, `Missing environment config for "${environmentName}"`);
75419
+ const { resolve: resolve$4 } = environmentOptions;
75420
+ const disallowedEnvironmentOptions = {};
75421
+ if ((resolve$4.external === true || Array.isArray(resolve$4.external) && resolve$4.external.length > 0) && !isOnlyNodeBuiltins(resolve$4.external)) disallowedEnvironmentOptions.resolveExternal = resolve$4.external;
75422
+ if (Object.keys(disallowedEnvironmentOptions).length) disallowedEnvironmentOptionsMap.set(environmentName, disallowedEnvironmentOptions);
75423
+ }
75424
+ if (disallowedEnvironmentOptionsMap.size) {
75425
+ const errorMessage = `The following environment options are incompatible with the Cloudflare Vite plugin:\n${[...disallowedEnvironmentOptionsMap].map(([environmentName, disallowedEnvironmentOptions]) => disallowedEnvironmentOptions.resolveExternal && ` - "${environmentName}" environment: \`resolve.external\`: ${JSON.stringify(disallowedEnvironmentOptions.resolveExternal)}\n`).join("")}To resolve this issue, avoid setting \`resolve.external\` in your Cloudflare Worker environments.\n`;
75426
+ throw new Error(errorMessage);
75427
+ }
75428
+ }
75429
+
75430
+ //#endregion
75431
+ //#region src/plugins/wrangler-watch-ignore.ts
75432
+ const WRANGLER_STATE_WATCH_IGNORE = "**/.wrangler/**";
75433
+ /**
75434
+ * Keep Miniflare persistence writes out of Vite's file watcher without
75435
+ * replacing any ignore patterns the user already configured.
75436
+ *
75437
+ * @param userIgnored - Existing `server.watch.ignored` patterns, if any
75438
+ * @returns Ignore patterns that always include `.wrangler` directories
75439
+ */
75440
+ function withWranglerStateIgnored(userIgnored) {
75441
+ if (userIgnored == null) return WRANGLER_STATE_WATCH_IGNORE;
75442
+ if (Array.isArray(userIgnored)) return [...userIgnored, WRANGLER_STATE_WATCH_IGNORE];
75443
+ return [userIgnored, WRANGLER_STATE_WATCH_IGNORE];
75444
+ }
75445
+ /**
75446
+ * Merge `.wrangler` into Vite's `server.watch` config.
75447
+ *
75448
+ * Returns `null` when the user disabled watching with `server.watch: null`,
75449
+ * so this plugin does not turn the watcher back on.
75450
+ *
75451
+ * @param userWatch - The user's `server.watch` value from Vite config
75452
+ * @returns `null` when watching is disabled, otherwise a watch object whose
75453
+ * `ignored` list includes `.wrangler` directories
75454
+ */
75455
+ function getServerWatchConfig(userWatch) {
75456
+ if (userWatch === null) return null;
75457
+ return {
75458
+ ...userWatch,
75459
+ ignored: withWranglerStateIgnored(userWatch?.ignored)
75460
+ };
75461
+ }
75462
+
75463
+ //#endregion
75464
+ //#region src/plugins/config.ts
75465
+ /**
75466
+ * Plugin to handle configuration and config file watching
75467
+ */
75468
+ const configPlugin = createPlugin("config", (ctx) => {
75469
+ return {
75470
+ config(userConfig, env$3) {
75471
+ if (ctx.resolvedPluginConfig.type === "preview") return { appType: "custom" };
75472
+ if (!ctx.hasShownWorkerConfigWarnings) {
75473
+ ctx.setHasShownWorkerConfigWarnings(true);
75474
+ const workerConfigWarnings = getWarningForWorkersConfigs(ctx.resolvedPluginConfig.rawConfigs);
75475
+ if (workerConfigWarnings) console.warn(workerConfigWarnings);
75476
+ }
75477
+ return {
75478
+ appType: "custom",
75479
+ server: {
75480
+ allowedHosts: getAllowedHosts(ctx.getTunnelHostnames(), userConfig.server?.allowedHosts),
75481
+ watch: getServerWatchConfig(userConfig.server?.watch),
75482
+ fs: { deny: [...[
75483
+ ".env",
75484
+ ".env.*",
75485
+ ".npmrc",
75486
+ ".yarnrc",
75487
+ ".yarnrc.yml",
75488
+ "*.{crt,pem,key,pfx,p12,p8,jks}",
75489
+ "**/.git/**",
75490
+ ".dev.vars",
75491
+ ".dev.vars.*",
75492
+ "**/.wrangler/**"
75493
+ ], ...Array.from(ctx.resolvedPluginConfig.configPaths, (configPath) => normalizePath(configPath))] }
75494
+ },
75495
+ environments: getEnvironmentsConfig(ctx, userConfig, env$3.mode),
75496
+ builder: { buildApp: userConfig.builder?.buildApp ?? createBuildApp(ctx.resolvedPluginConfig) }
75497
+ };
75498
+ },
75499
+ async configResolved(resolvedViteConfig) {
75500
+ ctx.setResolvedViteConfig(resolvedViteConfig);
75501
+ if (ctx.resolvedPluginConfig.type === "preview") return;
75502
+ validateWorkerEnvironmentOptions(ctx.resolvedPluginConfig, ctx.resolvedViteConfig);
75503
+ if (ctx.resolvedPluginConfig.experimental.newConfig?.cfBuildOutput) {
75504
+ forceBuildOutputDirs(ctx.resolvedPluginConfig, ctx.resolvedViteConfig);
75505
+ if (ctx.resolvedViteConfig.command === "build") await cleanBuildOutputDir(ctx.resolvedViteConfig.root);
75506
+ }
75507
+ },
75508
+ buildStart() {
75509
+ ctx.setHasShownWorkerConfigWarnings(false);
75510
+ },
75511
+ configureServer(viteDevServer) {
75512
+ let restartInFlight = false;
75513
+ const configChangedHandler = async (changedFilePath) => {
75514
+ assertIsNotPreview(ctx);
75515
+ if (restartInFlight) return;
75516
+ if (ctx.resolvedPluginConfig.configPaths.has(changedFilePath) || hasLocalDevVarsFileChanged(ctx.resolvedPluginConfig, changedFilePath) || hasAssetsConfigChanged(ctx.resolvedPluginConfig, ctx.resolvedViteConfig, changedFilePath)) {
75517
+ debuglog("Config changed: " + changedFilePath);
75518
+ restartInFlight = true;
75519
+ debuglog("Restarting dev server and aborting previous setup");
75520
+ try {
75521
+ await viteDevServer.restart();
75522
+ } finally {
75523
+ restartInFlight = false;
75524
+ }
75525
+ }
75526
+ };
75527
+ viteDevServer.watcher.on("change", configChangedHandler);
75528
+ },
75529
+ buildApp: {
75530
+ order: "post",
75531
+ async handler(builder) {
75532
+ if (ctx.resolvedPluginConfig.type !== "workers") return;
75533
+ const workerEnvironments = [...ctx.resolvedPluginConfig.environmentNameToWorkerMap.entries()].filter(([_, worker]) => !resolveDevOnly(worker.devOnly)).map(([environmentName]) => {
75534
+ const environment = builder.environments[environmentName];
75535
+ assert2(environment, `"${environmentName}" environment not found`);
75536
+ return environment;
75537
+ });
75538
+ await Promise.all(workerEnvironments.filter((environment) => !environment.isBuilt).map((environment) => builder.build(environment)));
75539
+ const { entryWorkerEnvironmentName } = ctx.resolvedPluginConfig;
75540
+ const entryWorkerEnvironment = builder.environments[entryWorkerEnvironmentName];
75541
+ assert2(entryWorkerEnvironment, `No "${entryWorkerEnvironmentName}" environment`);
75542
+ const cfBuildOutput = ctx.resolvedPluginConfig.experimental.newConfig?.cfBuildOutput === true;
75543
+ if (entryWorkerEnvironment.isBuilt) {
75544
+ if (!builder.environments.client?.isBuilt && !cfBuildOutput) removeAssetsField(path.resolve(builder.config.root, entryWorkerEnvironment.config.build.outDir));
75545
+ } else {
75546
+ const clientEnvironment = builder.environments.client;
75547
+ assert2(clientEnvironment, "No \"client\" environment");
75548
+ if (!clientEnvironment.isBuilt) throw new Error("If `assetsOnly` is set to `true`, the client environment must be built");
75549
+ if (cfBuildOutput) {
75550
+ const entryWorkerNewConfig = ctx.getWorkerNewConfig(entryWorkerEnvironmentName);
75551
+ assert2(entryWorkerNewConfig, `No config found for "${entryWorkerEnvironmentName}" environment`);
75552
+ await writeWorkerConfig({
75553
+ root: builder.config.root,
75554
+ config: entryWorkerNewConfig
75555
+ });
75556
+ } else {
75557
+ const entryWorkerConfig = ctx.getWorkerConfig(entryWorkerEnvironmentName);
75558
+ assert2(entryWorkerConfig, `No config found for "${entryWorkerEnvironmentName}" environment`);
75559
+ const outputConfig = {
75560
+ ...entryWorkerConfig,
75561
+ main: void 0,
75562
+ assets: {
75563
+ ...entryWorkerConfig.assets,
75564
+ directory: ".",
75565
+ binding: void 0
75566
+ }
75567
+ };
75568
+ if (outputConfig.unsafe && Object.keys(outputConfig.unsafe).length === 0) outputConfig.unsafe = void 0;
75569
+ fs$1.writeFileSync(path.resolve(builder.config.root, clientEnvironment.config.build.outDir, "wrangler.json"), JSON.stringify(outputConfig));
75570
+ writeDeployConfig(ctx.resolvedPluginConfig, ctx.resolvedViteConfig, true);
75571
+ }
75572
+ }
75573
+ await buildOutputContainers(ctx.resolvedPluginConfig, builder.config.root);
75574
+ }
75575
+ }
75576
+ };
75577
+ });
75578
+ /**
75579
+ * Generates the environment configuration for all Worker environments.
75580
+ */
75581
+ function getEnvironmentsConfig(ctx, userConfig, mode) {
75582
+ assertIsNotPreview(ctx);
75583
+ if (!ctx.resolvedPluginConfig.environmentNameToWorkerMap.size) return;
75584
+ return {
75585
+ ...Object.fromEntries([...ctx.resolvedPluginConfig.environmentNameToWorkerMap].flatMap(([environmentName, worker]) => {
75586
+ const childEnvironmentNames = ctx.resolvedPluginConfig.environmentNameToChildEnvironmentNamesMap.get(environmentName) ?? [];
75587
+ const sharedOptions = {
75588
+ workerConfig: worker.config,
75589
+ userConfig,
75590
+ mode,
75591
+ hasNodeJsCompat: ctx.getNodeJsCompat(environmentName) !== void 0
75592
+ };
75593
+ const isEntryWorker = environmentName === ctx.resolvedPluginConfig.prerenderWorkerEnvironmentName || ctx.resolvedPluginConfig.type === "workers" && environmentName === ctx.resolvedPluginConfig.entryWorkerEnvironmentName;
75594
+ return [[environmentName, createCloudflareEnvironmentOptions({
75595
+ ...sharedOptions,
75596
+ environmentName,
75597
+ isEntryWorker,
75598
+ isParentEnvironment: true
75599
+ })], ...childEnvironmentNames.map((childEnvironmentName) => [childEnvironmentName, createCloudflareEnvironmentOptions({
75600
+ ...sharedOptions,
75601
+ environmentName: childEnvironmentName,
75602
+ isEntryWorker: false,
75603
+ isParentEnvironment: false
75604
+ })])];
75605
+ })),
75606
+ client: {
75607
+ build: { outDir: getOutputDirectory(userConfig, "client") },
75608
+ optimizeDeps: { exclude: [...cloudflareBuiltInModules] }
75609
+ }
75610
+ };
75611
+ }
75612
+ /**
75613
+ * When the Build Output Specification is enabled,
75614
+ * force every Worker environment's and the client environment's `build.outDir`
75615
+ * to the spec-mandated location.
75616
+ *
75617
+ * Runs after Vite's merge in `configResolved`, so it overrides any
75618
+ * user-supplied `build.outDir`
75619
+ */
75620
+ function forceBuildOutputDirs(resolvedPluginConfig, resolvedViteConfig) {
75621
+ if (!resolvedPluginConfig.experimental.newConfig?.cfBuildOutput) return;
75622
+ const { root } = resolvedViteConfig;
75623
+ if (resolvedPluginConfig.type === "workers") {
75624
+ const entryName = resolvedPluginConfig.entryWorkerEnvironmentName;
75625
+ const entryEnvironment = resolvedViteConfig.environments[entryName];
75626
+ if (entryEnvironment) entryEnvironment.build.outDir = getWorkerBundleDir(root);
75627
+ }
75628
+ const clientEnvironment = resolvedViteConfig.environments.client;
75629
+ if (clientEnvironment) clientEnvironment.build.outDir = getWorkerAssetsDir(root);
75630
+ }
75631
+ function getAllowedHosts(tunnelHostnames, userAllowedHosts) {
75632
+ if (tunnelHostnames.length === 0 || userAllowedHosts === true) return userAllowedHosts;
75633
+ return Array.from(new Set([...userAllowedHosts ?? [], ...tunnelHostnames]));
75634
+ }
75635
+
75636
+ //#endregion
75637
+ //#region src/debug.ts
75638
+ var import_picocolors$3 = /* @__PURE__ */ __toESM$1(require_picocolors(), 1);
75639
+ const DEBUG_PATH = "/__debug";
75640
+ const DEFAULT_INSPECTOR_PORT = 9229;
75641
+ /**
75642
+ * Gets the inspector port option that should be passed to Miniflare based on the user's plugin config
75643
+ */
75644
+ async function getInputInspectorPort(ctx, viteServer) {
75645
+ if (ctx.resolvedPluginConfig.inspectorPort === void 0 || ctx.resolvedPluginConfig.inspectorPort === 0) {
75646
+ const resolvedInspectorPort = await ctx.getResolvedInspectorPort();
75647
+ if (resolvedInspectorPort !== null) return resolvedInspectorPort;
75648
+ }
75649
+ const inputInspectorPort = ctx.resolvedPluginConfig.inspectorPort ?? await getFirstAvailablePort(DEFAULT_INSPECTOR_PORT);
75650
+ if (ctx.resolvedPluginConfig.inspectorPort === void 0 && inputInspectorPort !== DEFAULT_INSPECTOR_PORT) viteServer.config.logger.warn(import_picocolors$3.default.dim(`Default inspector port ${DEFAULT_INSPECTOR_PORT} not available, using ${inputInspectorPort} instead\n`));
75651
+ return inputInspectorPort;
75652
+ }
75653
+ function getFirstAvailablePort(start) {
75654
+ return getPorts({ port: portNumbers(start, 65535) });
75655
+ }
75656
+ /**
75657
+ * Modifies the URL printing logic to also include a URL that developers can use to open DevTools to debug their Worker(s)
75658
+ */
75659
+ function addDebugToVitePrintUrls(server) {
75660
+ const originalPrintUrls = server.printUrls;
75661
+ server.printUrls = () => {
75662
+ originalPrintUrls();
75663
+ const localUrl = server.resolvedUrls?.local[0];
75664
+ if (localUrl) {
75665
+ const { protocol, hostname: hostname$1, port } = new URL(localUrl);
75666
+ const colorDebugUrl = (url$2) => import_picocolors$3.default.dim(import_picocolors$3.default.yellow(url$2.replace(/:(\d+)\//, (_, portNumber) => `:${import_picocolors$3.default.bold(portNumber)}/`)));
75667
+ server.config.logger.info(` ${import_picocolors$3.default.green("➜")} ${import_picocolors$3.default.bold("Debug")}: ${colorDebugUrl(`${protocol}//${hostname$1}:${port}${DEBUG_PATH}`)}`);
75668
+ }
75669
+ };
75670
+ }
75671
+ /**
75672
+ * Generate HTML that comprises a single script that:
75673
+ * - redirects the page to the DevTools for debugging the first available Worker
75674
+ * - opens tabs to the DevTools for all the remaining workers if any
75675
+ *
75676
+ * Note: this works based on the Miniflare inspector proxy logic (where Workers are available via
75677
+ * their names)
75678
+ */
75679
+ function getDebugPathHtml(workerNames, inspectorPort) {
75680
+ assert2(workerNames.length >= 1, "no workers present to debug");
75681
+ const workerDevtoolsUrls = workerNames.map((workerName) => {
75682
+ const localhost = `localhost:${inspectorPort}/${workerName}`;
75683
+ return `https://devtools.devprod.cloudflare.dev/js_app?${new URLSearchParams({
75684
+ theme: "systemPreferred",
75685
+ debugger: "true",
75686
+ ws: localhost,
75687
+ domain: workerName
75688
+ })}`;
75689
+ });
75690
+ return `
75691
+ <script>
75692
+ const workerUrls = ${JSON.stringify(workerDevtoolsUrls)};
75693
+ const [firstUrl, ...rest] = workerUrls;
75694
+ for (const workerUrl of rest) {
75695
+ // open new tabs for the devtools of the various workers
75696
+ window.open(workerUrl);
75697
+ }
75698
+ // redirect the current tab to the devtools of the first worker
75699
+ window.location.replace(firstUrl);
75700
+ <\/script>
75701
+ `;
75702
+ }
75703
+
75704
+ //#endregion
75705
+ //#region src/plugins/debug.ts
75706
+ /**
75707
+ * Plugin to provide a `/__debug` path for debugging Workers
75708
+ */
75709
+ const debugPlugin = createPlugin("debug", (ctx) => {
75710
+ return {
75711
+ enforce: "pre",
75712
+ configureServer(viteDevServer) {
75713
+ assertIsNotPreview(ctx);
75714
+ if (!!process.env.VSCODE_INSPECTOR_OPTIONS) return;
75715
+ if (ctx.resolvedPluginConfig.type === "workers" && ctx.resolvedPluginConfig.inspectorPort !== false) addDebugToVitePrintUrls(viteDevServer);
75716
+ const workerNames = ctx.resolvedPluginConfig.type === "workers" ? [...ctx.resolvedPluginConfig.environmentNameToWorkerMap.values()].map((worker) => worker.config.name) : [];
75717
+ viteDevServer.middlewares.use(DEBUG_PATH, async (_, res, next) => {
75718
+ const resolvedInspectorPort = await ctx.getResolvedInspectorPort();
75719
+ if (resolvedInspectorPort) {
75720
+ const html = getDebugPathHtml(workerNames, resolvedInspectorPort);
75721
+ res.setHeader("Content-Type", "text/html");
75722
+ res.end(html);
75723
+ } else next();
75724
+ });
75725
+ },
75726
+ async configurePreviewServer(vitePreviewServer) {
75727
+ assertIsPreview(ctx);
75728
+ if (!!process.env.VSCODE_INSPECTOR_OPTIONS) return;
75729
+ if (ctx.resolvedPluginConfig.workers.length >= 1 && ctx.resolvedPluginConfig.inspectorPort !== false) addDebugToVitePrintUrls(vitePreviewServer);
75730
+ const workerNames = ctx.resolvedPluginConfig.workers.map((worker) => {
75731
+ assert2(worker.config.name, "Expected the Worker to have a name");
75732
+ return worker.config.name;
75733
+ });
75734
+ vitePreviewServer.middlewares.use(DEBUG_PATH, async (_, res, next) => {
75735
+ const resolvedInspectorPort = await ctx.getResolvedInspectorPort();
75736
+ if (resolvedInspectorPort) {
75737
+ const html = getDebugPathHtml(workerNames, resolvedInspectorPort);
75738
+ res.setHeader("Content-Type", "text/html");
75739
+ res.end(html);
75740
+ } else next();
75741
+ });
75742
+ }
75743
+ };
75744
+ });
75745
+
75512
75746
  //#endregion
75513
75747
  //#region ../workers-shared/asset-worker/src/utils/rules-engine.ts
75514
75748
  const ESCAPE_REGEX_CHARACTERS = /[-/\\^$*+?.()|[\]{}]/g;
@@ -81158,7 +81392,7 @@ __name(createWorkerUploadForm, "createWorkerUploadForm");
81158
81392
  //#endregion
81159
81393
  //#region ../remote-bindings/dist/index.mjs
81160
81394
  var import_undici = require_undici();
81161
- var version$2 = "0.0.27";
81395
+ var version$2 = "0.0.28";
81162
81396
  var NoDefaultValueProvided = class extends UserError {
81163
81397
  constructor() {
81164
81398
  super("This command cannot be run in a non-interactive context", { telemetryMessage: "remote bindings prompt default missing" });
@@ -81442,7 +81676,7 @@ async function getOrRegisterWorkersDevSubdomain(complianceConfig, account, abort
81442
81676
  } catch (error$2) {
81443
81677
  if (!(error$2 instanceof APIError) || error$2.code !== 10007) throw error$2;
81444
81678
  }
81445
- const subdomain = crypto$1.randomBytes(4).toString("hex");
81679
+ const subdomain = crypto2.randomBytes(4).toString("hex");
81446
81680
  return (await fetchResult(complianceConfig, account, resource, {
81447
81681
  method: "PUT",
81448
81682
  body: JSON.stringify({ subdomain })