@cloudflare/vite-plugin 1.40.1 → 1.41.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
@@ -1505,7 +1505,7 @@ async function assertWranglerVersion() {
1505
1505
  * The default compatibility date to use when the user omits one.
1506
1506
  * This value is injected at build time and remains fixed for each release.
1507
1507
  */
1508
- const DEFAULT_COMPAT_DATE = "2026-06-09";
1508
+ const DEFAULT_COMPAT_DATE = "2026-06-16";
1509
1509
 
1510
1510
  //#endregion
1511
1511
  //#region ../../node_modules/.pnpm/@remix-run+node-fetch-server@0.8.0/node_modules/@remix-run/node-fetch-server/dist/node-fetch-server.js
@@ -30929,11 +30929,18 @@ __export(mod_esm_exports, { default: () => mod_esm_default });
30929
30929
  var import_mod_cjs = __toESM(require_mod_cjs3(), 1);
30930
30930
  __reExport(mod_esm_exports, __toESM(require_mod_cjs3(), 1));
30931
30931
  var mod_esm_default = import_mod_cjs.default;
30932
+ function getGlobalConfigPath({ appName = "wrangler", leadingDot = true, useLegacyHomeDir = true } = {}) {
30933
+ const dirName = `${leadingDot ? "." : ""}${appName}`;
30934
+ const configDir = mod_esm_default(dirName).config();
30935
+ if (useLegacyHomeDir) {
30936
+ const legacyConfigDir = path.join(os.homedir(), dirName);
30937
+ if (isDirectory(legacyConfigDir)) return legacyConfigDir;
30938
+ }
30939
+ return configDir;
30940
+ }
30941
+ __name(getGlobalConfigPath, "getGlobalConfigPath");
30932
30942
  function getGlobalWranglerConfigPath() {
30933
- const configDir = mod_esm_default(".wrangler").config();
30934
- const legacyConfigDir = path.join(os.homedir(), ".wrangler");
30935
- if (isDirectory(legacyConfigDir)) return legacyConfigDir;
30936
- else return configDir;
30943
+ return getGlobalConfigPath();
30937
30944
  }
30938
30945
  __name(getGlobalWranglerConfigPath, "getGlobalWranglerConfigPath");
30939
30946
  function getBooleanEnvironmentVariableFactory(options) {
@@ -34396,7 +34403,7 @@ __name(maybeThrowFriendlyError, "maybeThrowFriendlyError");
34396
34403
  function logHeaders(headers, logger) {
34397
34404
  const clone = cloneHeaders(headers);
34398
34405
  clone.delete("Authorization");
34399
- logger.debugWithSanitization("HEADERS:", JSON.stringify(Object.fromEntries(clone), null, 2));
34406
+ logger.debugWithSanitization?.("HEADERS:", JSON.stringify(Object.fromEntries(clone), null, 2));
34400
34407
  }
34401
34408
  __name(logHeaders, "logHeaders");
34402
34409
  async function performApiFetchBase(complianceConfig, resource, init = {}, userAgent, logger, queryParams, abortSignal, credentials) {
@@ -34409,10 +34416,10 @@ async function performApiFetchBase(complianceConfig, resource, init = {}, userAg
34409
34416
  maybeAddTraceHeader(headers);
34410
34417
  const queryString = queryParams ? `?${queryParams.toString()}` : "";
34411
34418
  logger.debug(`-- START CF API REQUEST: ${method} ${getCloudflareApiBaseUrl(complianceConfig)}${resource}`);
34412
- logger.debugWithSanitization("QUERY STRING:", queryString);
34419
+ logger.debugWithSanitization?.("QUERY STRING:", queryString);
34413
34420
  logHeaders(headers, logger);
34414
- logger.debugWithSanitization("INIT:", JSON.stringify({ ...init }, null, 2));
34415
- if (init.body instanceof import_undici.FormData) logger.debugWithSanitization("BODY:", await new import_undici.Response(init.body).text(), null, 2);
34421
+ logger.debugWithSanitization?.("INIT:", JSON.stringify({ ...init }, null, 2));
34422
+ if (init.body instanceof import_undici.FormData) logger.debugWithSanitization?.("BODY:", await new import_undici.Response(init.body).text(), null, 2);
34416
34423
  logger.debug("-- END CF API REQUEST");
34417
34424
  return await (0, import_undici.fetch)(`${getCloudflareApiBaseUrl(complianceConfig)}${resource}${queryString}`, {
34418
34425
  method,
@@ -34428,7 +34435,7 @@ async function fetchInternalBase(complianceConfig, resource, init = {}, userAgen
34428
34435
  const jsonText = await response.text();
34429
34436
  logger.debug("-- START CF API RESPONSE:", response.statusText, response.status);
34430
34437
  logHeaders(response.headers, logger);
34431
- logger.debugWithSanitization("RESPONSE:", jsonText);
34438
+ logger.debugWithSanitization?.("RESPONSE:", jsonText);
34432
34439
  logger.debug("-- END CF API RESPONSE");
34433
34440
  if (!jsonText && (response.status === 204 || response.status === 205)) return {
34434
34441
  response: {
@@ -34592,6 +34599,22 @@ function throwWAFBlockError(headers, method, resource, status, statusText) {
34592
34599
  });
34593
34600
  }
34594
34601
  __name(throwWAFBlockError, "throwWAFBlockError");
34602
+ async function fetchKVGetValueBase(complianceConfig, accountId, namespaceId, key, userAgent, logger, credentials) {
34603
+ const headers = new import_undici.Headers();
34604
+ addAuthorizationHeader(headers, credentials);
34605
+ headers.set("User-Agent", userAgent);
34606
+ maybeAddTraceHeader(headers);
34607
+ const resource = `${getCloudflareApiBaseUrl(complianceConfig)}/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${key}`;
34608
+ logger.debug(`-- START CF API REQUEST: GET ${resource}`);
34609
+ logger.debug("-- END CF API REQUEST");
34610
+ const response = await (0, import_undici.fetch)(resource, {
34611
+ method: "GET",
34612
+ headers
34613
+ });
34614
+ if (response.ok) return await response.arrayBuffer();
34615
+ else throw new Error(`Failed to fetch ${resource} - ${response.status}: ${response.statusText}`);
34616
+ }
34617
+ __name(fetchKVGetValueBase, "fetchKVGetValueBase");
34595
34618
  function hasCursor(result_info) {
34596
34619
  const cursor = result_info?.cursor;
34597
34620
  return cursor !== void 0 && cursor !== null && cursor !== "";
@@ -37141,8 +37164,11 @@ var PluginContext = class {
37141
37164
  getWorkerConfig(environmentName) {
37142
37165
  return this.#getWorker(environmentName)?.config;
37143
37166
  }
37167
+ getWorkerNewConfig(environmentName) {
37168
+ return this.#getWorker(environmentName)?.parsedNewConfig;
37169
+ }
37144
37170
  get allWorkerConfigs() {
37145
- if (this.resolvedPluginConfig.type === "preview") return this.resolvedPluginConfig.workers;
37171
+ if (this.resolvedPluginConfig.type === "preview") return this.resolvedPluginConfig.workers.map((worker) => worker.config);
37146
37172
  return Array.from(this.resolvedPluginConfig.environmentNameToWorkerMap.values()).map((worker) => worker.config);
37147
37173
  }
37148
37174
  get entryWorkerConfig() {
@@ -37273,6 +37299,138 @@ const defuArrayFn = createDefu((object, key, currentValue) => {
37273
37299
  }
37274
37300
  });
37275
37301
 
37302
+ //#endregion
37303
+ //#region src/build-output.ts
37304
+ /**
37305
+ * Initial draft version of the Build Output API.
37306
+ *
37307
+ * Will move to `v1` when the spec stabilises.
37308
+ */
37309
+ const BUILD_OUTPUT_VERSION = "v0";
37310
+ /**
37311
+ * Project-relative root.
37312
+ */
37313
+ const BUILD_OUTPUT_ROOT = ".cloudflare/output";
37314
+ /**
37315
+ * Filename of the per-Worker config.
37316
+ */
37317
+ const WORKER_CONFIG_FILENAME = "worker.config.json";
37318
+ /**
37319
+ * Absolute path to the Build Output API root for the current project.
37320
+ */
37321
+ function getBuildOutputDir(root) {
37322
+ return nodePath.resolve(root, BUILD_OUTPUT_ROOT);
37323
+ }
37324
+ /**
37325
+ * Clean the build output directory
37326
+ *
37327
+ * Called once at the start of each build
37328
+ */
37329
+ function cleanBuildOutputDir(root) {
37330
+ removeDirSync(getBuildOutputDir(root));
37331
+ }
37332
+ /**
37333
+ * Absolute path to the workers output directory
37334
+ */
37335
+ function getWorkersDir(root) {
37336
+ return nodePath.join(getBuildOutputDir(root), BUILD_OUTPUT_VERSION, "workers");
37337
+ }
37338
+ /**
37339
+ * Absolute path to `worker.config.json` for a given Worker.
37340
+ */
37341
+ function getWorkerConfigPath(root, workerName) {
37342
+ return nodePath.join(getWorkersDir(root), workerName, WORKER_CONFIG_FILENAME);
37343
+ }
37344
+ /**
37345
+ * Absolute path to the bundle directory for a given Worker.
37346
+ */
37347
+ function getWorkerBundleDir(root, workerName) {
37348
+ return nodePath.join(getWorkersDir(root), workerName, "bundle");
37349
+ }
37350
+ /**
37351
+ * Absolute path to the assets directory for a given Worker.
37352
+ */
37353
+ function getWorkerAssetsDir(root, workerName) {
37354
+ return nodePath.join(getWorkersDir(root), workerName, "assets");
37355
+ }
37356
+ /**
37357
+ * Map a bundle filename to its declared module type.
37358
+ */
37359
+ function detectModuleType(filename) {
37360
+ switch (nodePath.extname(filename).toLowerCase()) {
37361
+ case ".js":
37362
+ case ".mjs": return "esm";
37363
+ case ".wasm": return "wasm";
37364
+ case ".bin": return "data";
37365
+ case ".txt":
37366
+ case ".html":
37367
+ case ".sql": return "text";
37368
+ case ".json": return "json";
37369
+ case ".map": return "sourcemap";
37370
+ default: return "data";
37371
+ }
37372
+ }
37373
+ /**
37374
+ * Write the output `worker.config.json` for a given Worker to the Build
37375
+ * Output API tree.
37376
+ *
37377
+ * - Workers mode: `manifest` is provided (bundle/ present on disk).
37378
+ * - Assets-only mode: `manifest` is omitted (no bundle/ directory).
37379
+ */
37380
+ function writeOutputWorkerConfig(root, parsedConfig, manifest) {
37381
+ const { entrypoint: _entrypoint,...rest } = parsedConfig;
37382
+ const outputConfig = {
37383
+ ...rest,
37384
+ manifest
37385
+ };
37386
+ const workerOutputDir = nodePath.join(getWorkersDir(root), outputConfig.name);
37387
+ fs$1.mkdirSync(workerOutputDir, { recursive: true });
37388
+ const configPath = getWorkerConfigPath(root, outputConfig.name);
37389
+ fs$1.writeFileSync(configPath, JSON.stringify(outputConfig));
37390
+ }
37391
+
37392
+ //#endregion
37393
+ //#region src/build-output-preview.ts
37394
+ /**
37395
+ * Read the Build Output API at `<root>/.cloudflare/output/v0/workers/`
37396
+ * and reconstruct a `BuildOutputPreviewWorker` for each Worker
37397
+ */
37398
+ async function readBuildOutputWorkers(root) {
37399
+ const workersDir = getWorkersDir(root);
37400
+ if (!fs$1.existsSync(workersDir)) throw new Error(`No Build Output API tree found at ${workersDir}.`);
37401
+ const workerNames = fs$1.readdirSync(workersDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
37402
+ if (workerNames.length === 0) throw new Error(`Build Output API tree at ${workersDir} contains no Worker directories.`);
37403
+ const { OutputWorkerSchema, convertToWranglerConfig } = await import("./dist-Cr__Sz5N.mjs");
37404
+ return workerNames.map((workerName) => {
37405
+ const configPath = getWorkerConfigPath(root, workerName);
37406
+ assert(fs$1.existsSync(configPath), `Build Output API: missing \`${WORKER_CONFIG_FILENAME}\` for Worker "${workerName}" at ${configPath}.`);
37407
+ const { manifest,...inputShape } = OutputWorkerSchema.parse(JSON.parse(fs$1.readFileSync(configPath, "utf-8")));
37408
+ const { config, diagnostics } = normalizeAndValidateConfig(convertToWranglerConfig(inputShape), void 0, void 0, {}, true);
37409
+ if (diagnostics.hasWarnings()) console.warn(diagnostics.renderWarnings());
37410
+ if (diagnostics.hasErrors()) throw new Error(diagnostics.renderErrors());
37411
+ const bundleDir = getWorkerBundleDir(root, workerName);
37412
+ const assetsDir = getWorkerAssetsDir(root, workerName);
37413
+ if (fs$1.existsSync(assetsDir)) config.assets = {
37414
+ ...config.assets ?? {},
37415
+ directory: assetsDir
37416
+ };
37417
+ let bundle;
37418
+ if (manifest) {
37419
+ config.main = manifest.mainModule;
37420
+ bundle = {
37421
+ rootPath: bundleDir,
37422
+ mainModule: manifest.mainModule,
37423
+ modules: manifest.modules
37424
+ };
37425
+ }
37426
+ return {
37427
+ source: "build-output",
37428
+ config,
37429
+ bundle
37430
+ };
37431
+ });
37432
+ }
37433
+
37276
37434
  //#endregion
37277
37435
  //#region src/deploy-config.ts
37278
37436
  function getDeployConfigPath(root) {
@@ -44160,8 +44318,14 @@ const allowedWranglerConfigExtensions = [
44160
44318
  //#region src/plugin-config.ts
44161
44319
  function normalizeNewConfig(option) {
44162
44320
  if (option === void 0 || option === false) return;
44163
- if (option === true) return { types: { generate: true } };
44164
- return { types: { generate: option.types?.generate ?? true } };
44321
+ if (option === true) return {
44322
+ types: { generate: true },
44323
+ cfBuildOutput: false
44324
+ };
44325
+ return {
44326
+ types: { generate: option.types?.generate ?? true },
44327
+ cfBuildOutput: option.cfBuildOutput ?? false
44328
+ };
44165
44329
  }
44166
44330
  function filterEntryWorkerConfig(config) {
44167
44331
  const { topLevelName: _topLevelName, name: _name,...filteredConfig } = config;
@@ -44227,20 +44391,30 @@ async function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
44227
44391
  const prefixedEnv = vite.loadEnv(viteEnv.mode, root, ["CLOUDFLARE_", "WRANGLER_HYPERDRIVE_LOCAL_CONNECTION_STRING_"]);
44228
44392
  Object.assign(process.env, prefixedEnv);
44229
44393
  const remoteBindings = prefixedEnv.CLOUDFLARE_VITE_FORCE_LOCAL === "true" ? false : pluginConfig.remoteBindings ?? true;
44230
- if (viteEnv.isPreview) return {
44231
- ...shared,
44232
- remoteBindings,
44233
- type: "preview",
44234
- workers: getWorkerConfigs(root, !!process.env.CLOUDFLARE_VITE_BUILD)
44235
- };
44394
+ if (viteEnv.isPreview) {
44395
+ const workers = resolvedNewConfig?.cfBuildOutput ? await readBuildOutputWorkers(root) : getWorkerConfigs(root, !!process.env.CLOUDFLARE_VITE_BUILD).map((config) => ({
44396
+ source: "legacy",
44397
+ config
44398
+ }));
44399
+ return {
44400
+ ...shared,
44401
+ remoteBindings,
44402
+ type: "preview",
44403
+ workers
44404
+ };
44405
+ }
44236
44406
  const configPaths = /* @__PURE__ */ new Set();
44237
44407
  const cloudflareEnv = prefixedEnv.CLOUDFLARE_ENV;
44238
44408
  const validateAndAddEnvironmentName = createEnvironmentNameValidator();
44239
44409
  let configPath;
44240
44410
  let rawConfigOverride;
44411
+ let parsedNewConfig;
44241
44412
  if (resolvedNewConfig) {
44242
44413
  if (pluginConfig.configPath) throw new Error("`configPath` cannot be used together with `experimental.newConfig`. Configure the entry Worker via `cloudflare.config.ts` instead.");
44243
44414
  if (pluginConfig.auxiliaryWorkers?.length) throw new Error("`auxiliaryWorkers` are not yet supported when `experimental.newConfig` is enabled.");
44415
+ if (pluginConfig.experimental?.prerenderWorker) throw new Error("`experimental.prerenderWorker` is not yet supported when `experimental.newConfig` is enabled.");
44416
+ if (typeof pluginConfig.config !== "undefined") throw new Error("`config` cannot be used together with `experimental.newConfig`. Configure the entry Worker via `cloudflare.config.ts` instead.");
44417
+ if (resolvedNewConfig.cfBuildOutput && pluginConfig.viteEnvironment?.childEnvironments?.length) throw new Error("`viteEnvironment.childEnvironments` cannot be used together with `experimental.newConfig.cfBuildOutput`. Child environments are not yet supported in the Build Output API.");
44244
44418
  const result = await loadNewConfig({
44245
44419
  root,
44246
44420
  mode: viteEnv.mode,
@@ -44248,6 +44422,7 @@ async function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
44248
44422
  });
44249
44423
  configPath = result.configPath;
44250
44424
  rawConfigOverride = result.rawConfig;
44425
+ parsedNewConfig = result.parsedConfig;
44251
44426
  configPaths.add(result.configPath);
44252
44427
  for (const dep of result.dependencies) configPaths.add(dep);
44253
44428
  } else configPath = getValidatedWranglerConfigPath(root, pluginConfig.configPath ?? prefixedEnv.CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH);
@@ -44255,7 +44430,7 @@ async function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
44255
44430
  root,
44256
44431
  configPath: resolvedNewConfig ? void 0 : configPath,
44257
44432
  env: cloudflareEnv,
44258
- configCustomizer: pluginConfig.config,
44433
+ configCustomizer: resolvedNewConfig ? void 0 : pluginConfig.config,
44259
44434
  visitedConfigPaths: configPaths,
44260
44435
  rawConfigOverride
44261
44436
  });
@@ -44286,6 +44461,7 @@ async function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
44286
44461
  type: "assets-only",
44287
44462
  cloudflareEnv,
44288
44463
  config: entryWorkerResolvedConfig.config,
44464
+ parsedNewConfig,
44289
44465
  environmentNameToWorkerMap,
44290
44466
  environmentNameToChildEnvironmentNamesMap,
44291
44467
  prerenderWorkerEnvironmentName,
@@ -44297,7 +44473,7 @@ async function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
44297
44473
  if (Array.isArray(entryWorkerResolvedConfig.config.assets?.run_worker_first)) staticRouting = parseStaticRouting(entryWorkerResolvedConfig.config.assets.run_worker_first);
44298
44474
  const entryWorkerEnvironmentName = pluginConfig.viteEnvironment?.name ?? workerNameToEnvironmentName(entryWorkerResolvedConfig.config.topLevelName);
44299
44475
  validateAndAddEnvironmentName(entryWorkerEnvironmentName);
44300
- environmentNameToWorkerMap.set(entryWorkerEnvironmentName, resolveWorker(entryWorkerResolvedConfig.config, pluginConfig.assetsOnly));
44476
+ environmentNameToWorkerMap.set(entryWorkerEnvironmentName, resolveWorker(entryWorkerResolvedConfig.config, pluginConfig.assetsOnly, parsedNewConfig));
44301
44477
  const entryWorkerChildEnvironments = pluginConfig.viteEnvironment?.childEnvironments;
44302
44478
  if (entryWorkerChildEnvironments) {
44303
44479
  for (const childName of entryWorkerChildEnvironments) validateAndAddEnvironmentName(childName);
@@ -44360,11 +44536,12 @@ function resolveDevOnly(devOnly) {
44360
44536
  if (typeof devOnly === "function") return devOnly();
44361
44537
  return devOnly ?? false;
44362
44538
  }
44363
- function resolveWorker(workerConfig, devOnly) {
44539
+ function resolveWorker(workerConfig, devOnly, parsedNewConfig) {
44364
44540
  return {
44365
44541
  config: workerConfig,
44366
44542
  nodeJsCompat: hasNodeJsCompat(workerConfig) ? new NodeJsCompat(workerConfig) : void 0,
44367
- devOnly
44543
+ devOnly,
44544
+ parsedNewConfig
44368
44545
  };
44369
44546
  }
44370
44547
  const NEW_CONFIG_FILENAME = "cloudflare.config.ts";
@@ -44372,8 +44549,10 @@ const TYPES_OUTPUT_FILENAME = "worker-configuration.d.ts";
44372
44549
  const EXPERIMENTAL_CONFIG_PKG = "@cloudflare/vite-plugin/experimental-config";
44373
44550
  /**
44374
44551
  * Load and convert a `cloudflare.config.ts` file via `@cloudflare/config`. Returns
44375
- * the resulting Wrangler `RawConfig`, the absolute path of the loaded file,
44376
- * and the set of files imported while resolving the config (for watch-mode).
44552
+ * the resulting Wrangler `RawConfig`, the parsed new-config shape (for
44553
+ * downstream Build Output API emission), the absolute path of the loaded
44554
+ * file, and the set of files imported while resolving the config (for
44555
+ * watch-mode).
44377
44556
  *
44378
44557
  * If `generateTypes` is true, also writes `worker-configuration.d.ts` next to
44379
44558
  * the config when the generated content differs from what's already on disk.
@@ -44381,10 +44560,10 @@ const EXPERIMENTAL_CONFIG_PKG = "@cloudflare/vite-plugin/experimental-config";
44381
44560
  async function loadNewConfig(options) {
44382
44561
  const configPath = nodePath.resolve(options.root, NEW_CONFIG_FILENAME);
44383
44562
  if (!fs$1.existsSync(configPath)) throw new Error(`\`experimental.newConfig\` is enabled but no \`${NEW_CONFIG_FILENAME}\` was found at ${configPath}.`);
44384
- const { loadConfig, ConfigSchema, convertToWranglerConfig, generateTypes: generateTypesFn, resolveWorkerDefinition } = await import("./dist-MawCthRW.mjs");
44563
+ const { loadConfig, InputWorkerSchema, convertToWranglerConfig, generateTypes: generateTypesFn, resolveWorkerDefinition } = await import("./dist-Cr__Sz5N.mjs");
44385
44564
  const { config: rawExport, dependencies } = await loadConfig(configPath);
44386
44565
  const resolved = await resolveWorkerDefinition(rawExport, { mode: options.mode });
44387
- const parsed = ConfigSchema.safeParse(resolved);
44566
+ const parsed = InputWorkerSchema.safeParse(resolved);
44388
44567
  if (!parsed.success) throw new Error(`Invalid \`${NEW_CONFIG_FILENAME}\`:\n${parsed.error.message}`);
44389
44568
  const rawConfig = convertToWranglerConfig(parsed.data);
44390
44569
  if (options.generateTypes) writeWorkerConfigurationDts({
@@ -44394,6 +44573,7 @@ async function loadNewConfig(options) {
44394
44573
  });
44395
44574
  return {
44396
44575
  rawConfig,
44576
+ parsedConfig: parsed.data,
44397
44577
  configPath,
44398
44578
  dependencies
44399
44579
  };
@@ -45519,6 +45699,268 @@ function createModuleReference(type, id) {
45519
45699
  return `__CLOUDFLARE_MODULE__${type}__${id}__CLOUDFLARE_MODULE__`;
45520
45700
  }
45521
45701
 
45702
+ //#endregion
45703
+ //#region src/cloudflare-environment.ts
45704
+ const MAIN_ENTRY_NAME = "index";
45705
+ const webSocketUndefinedError = "The WebSocket is undefined";
45706
+ function createHotChannel(webSocketContainer) {
45707
+ const listenersMap = /* @__PURE__ */ new Map();
45708
+ const client = { send(payload) {
45709
+ const webSocket = webSocketContainer.webSocket;
45710
+ assert(webSocket, webSocketUndefinedError);
45711
+ webSocket.send(JSON.stringify(payload));
45712
+ } };
45713
+ function onMessage(event) {
45714
+ const payload = JSON.parse(event.data.toString());
45715
+ const listeners = listenersMap.get(payload.event) ?? /* @__PURE__ */ new Set();
45716
+ for (const listener of listeners) listener(payload.data, client);
45717
+ }
45718
+ return {
45719
+ send(payload) {
45720
+ const webSocket = webSocketContainer.webSocket;
45721
+ const message = JSON.stringify(payload);
45722
+ if (!webSocket) {
45723
+ webSocketContainer.messageBuffers ??= [];
45724
+ webSocketContainer.messageBuffers.push(message);
45725
+ return;
45726
+ }
45727
+ webSocket.send(message);
45728
+ },
45729
+ on(event, listener) {
45730
+ const listeners = listenersMap.get(event) ?? /* @__PURE__ */ new Set();
45731
+ listeners.add(listener);
45732
+ listenersMap.set(event, listeners);
45733
+ },
45734
+ off(event, listener) {
45735
+ listenersMap.get(event)?.delete(listener);
45736
+ },
45737
+ listen() {
45738
+ const webSocket = webSocketContainer.webSocket;
45739
+ assert(webSocket, webSocketUndefinedError);
45740
+ webSocket.addEventListener("message", onMessage);
45741
+ },
45742
+ close() {
45743
+ const webSocket = webSocketContainer.webSocket;
45744
+ assert(webSocket, webSocketUndefinedError);
45745
+ webSocket.removeEventListener("message", onMessage);
45746
+ }
45747
+ };
45748
+ }
45749
+ var CloudflareDevEnvironment = class extends vite.DevEnvironment {
45750
+ #webSocketContainer;
45751
+ constructor(name, config) {
45752
+ const webSocketContainer = {};
45753
+ super(name, config, {
45754
+ hot: true,
45755
+ transport: createHotChannel(webSocketContainer)
45756
+ });
45757
+ this.#webSocketContainer = webSocketContainer;
45758
+ }
45759
+ async initRunner(miniflare, workerConfig, options) {
45760
+ const response = await miniflare.dispatchFetch(new URL(INIT_PATH, UNKNOWN_HOST), { headers: {
45761
+ [CoreHeaders.ROUTE_OVERRIDE]: workerConfig.name,
45762
+ [WORKER_ENTRY_PATH_HEADER]: encodeURIComponent(workerConfig.main),
45763
+ [IS_ENTRY_WORKER_HEADER]: String(options.isEntryWorker),
45764
+ [ENVIRONMENT_NAME_HEADER]: this.name,
45765
+ [IS_PARENT_ENVIRONMENT_HEADER]: String(options.isParentEnvironment),
45766
+ upgrade: "websocket"
45767
+ } });
45768
+ assert(response.ok, `Failed to initialize module runner, error: ${await response.text()}`);
45769
+ const webSocket = response.webSocket;
45770
+ assert(webSocket, "Failed to establish WebSocket");
45771
+ webSocket.accept();
45772
+ this.#webSocketContainer.webSocket = webSocket;
45773
+ if (this.#webSocketContainer.messageBuffers) {
45774
+ for (const bufferedMessage of this.#webSocketContainer.messageBuffers) webSocket.send(bufferedMessage);
45775
+ delete this.#webSocketContainer.messageBuffers;
45776
+ }
45777
+ }
45778
+ async fetchWorkerExportTypes(miniflare, workerConfig) {
45779
+ await this.depsOptimizer?.init();
45780
+ return await (await miniflare.dispatchFetch(new URL(GET_EXPORT_TYPES_PATH, UNKNOWN_HOST), { headers: { [CoreHeaders.ROUTE_OVERRIDE]: workerConfig.name } })).json();
45781
+ }
45782
+ async fetchModule(id, importer, options) {
45783
+ if (additionalModuleRE.test(id)) return {
45784
+ externalize: id,
45785
+ type: "module"
45786
+ };
45787
+ return super.fetchModule(id, importer, options);
45788
+ }
45789
+ };
45790
+ const cloudflareBuiltInModules = [
45791
+ "cloudflare:email",
45792
+ "cloudflare:node",
45793
+ "cloudflare:sockets",
45794
+ "cloudflare:workers",
45795
+ "cloudflare:workflows"
45796
+ ];
45797
+ const defaultConditions = [
45798
+ "workerd",
45799
+ "worker",
45800
+ "module",
45801
+ "browser"
45802
+ ];
45803
+ const target = "es2024";
45804
+ const resolveExtensions = [
45805
+ ".mjs",
45806
+ ".js",
45807
+ ".mts",
45808
+ ".ts",
45809
+ ".jsx",
45810
+ ".tsx",
45811
+ ".json",
45812
+ ".cjs",
45813
+ ".cts",
45814
+ ".ctx"
45815
+ ];
45816
+ function createCloudflareEnvironmentOptions({ workerConfig, userConfig, mode, environmentName, isEntryWorker, isParentEnvironment, hasNodeJsCompat: hasNodeJsCompat$1 }) {
45817
+ const rollupOptions = isParentEnvironment ? {
45818
+ input: { [MAIN_ENTRY_NAME]: VIRTUAL_WORKER_ENTRY },
45819
+ preserveEntrySignatures: "strict"
45820
+ } : {};
45821
+ const define$1 = getProcessEnvReplacements(hasNodeJsCompat$1, mode);
45822
+ return {
45823
+ resolve: {
45824
+ noExternal: true,
45825
+ conditions: [...defaultConditions, "development|production"],
45826
+ builtins: [...cloudflareBuiltInModules]
45827
+ },
45828
+ define: define$1,
45829
+ dev: { createEnvironment(name, config) {
45830
+ if (!config.plugins.some((plugin) => plugin.name === "vite-plugin-cloudflare:dev" && plugin.configureServer !== void 0)) return vite.createRunnableDevEnvironment(name, config);
45831
+ return new CloudflareDevEnvironment(name, config);
45832
+ } },
45833
+ build: {
45834
+ createEnvironment(name, config) {
45835
+ return new vite.BuildEnvironment(name, config);
45836
+ },
45837
+ target,
45838
+ emitAssets: true,
45839
+ manifest: isEntryWorker,
45840
+ outDir: getOutputDirectory(userConfig, environmentName),
45841
+ copyPublicDir: false,
45842
+ ssr: true,
45843
+ ...isRolldown ? { rolldownOptions: {
45844
+ ...rollupOptions,
45845
+ platform: "neutral",
45846
+ resolve: { extensions: resolveExtensions }
45847
+ } } : { rollupOptions }
45848
+ },
45849
+ optimizeDeps: {
45850
+ noDiscovery: false,
45851
+ ignoreOutdatedRequests: true,
45852
+ entries: vite.normalizePath(workerConfig.main),
45853
+ exclude: [
45854
+ ...cloudflareBuiltInModules,
45855
+ ...nonPrefixedNodeModules,
45856
+ ...nonPrefixedNodeModules.map((module$1) => `node:${module$1}`),
45857
+ ...[
45858
+ "node:sea",
45859
+ "node:sqlite",
45860
+ "node:test",
45861
+ "node:test/reporters"
45862
+ ]
45863
+ ],
45864
+ ...isRolldown ? { rolldownOptions: {
45865
+ platform: "neutral",
45866
+ resolve: {
45867
+ conditionNames: [...defaultConditions, "development"],
45868
+ extensions: resolveExtensions
45869
+ },
45870
+ transform: {
45871
+ target,
45872
+ define: define$1
45873
+ },
45874
+ plugins: [vite.esmExternalRequirePlugin({
45875
+ external: [nodeBuiltinsRE],
45876
+ skipDuplicateCheck: true
45877
+ })]
45878
+ } } : { esbuildOptions: {
45879
+ platform: "neutral",
45880
+ conditions: [...defaultConditions, "development"],
45881
+ resolveExtensions,
45882
+ target,
45883
+ define: define$1
45884
+ } }
45885
+ },
45886
+ keepProcessEnv: true
45887
+ };
45888
+ }
45889
+ /**
45890
+ * Gets `process.env` replacement values.
45891
+ * `process.env.NODE_ENV` is always replaced.
45892
+ * `process.env` is replaced with an empty object if `nodejs_compat` is not enabled
45893
+ * @param hasNodeJsCompat - whether `nodejs_compat` is enabled
45894
+ * @param mode - the Vite mode
45895
+ * @returns replacement values
45896
+ */
45897
+ function getProcessEnvReplacements(hasNodeJsCompat$1, mode) {
45898
+ const nodeEnv = process.env.NODE_ENV || mode;
45899
+ const nodeEnvReplacements = {
45900
+ "process.env.NODE_ENV": JSON.stringify(nodeEnv),
45901
+ "global.process.env.NODE_ENV": JSON.stringify(nodeEnv),
45902
+ "globalThis.process.env.NODE_ENV": JSON.stringify(nodeEnv)
45903
+ };
45904
+ return hasNodeJsCompat$1 ? nodeEnvReplacements : {
45905
+ ...nodeEnvReplacements,
45906
+ "process.env": "{}",
45907
+ "global.process.env": "{}",
45908
+ "globalThis.process.env": "{}"
45909
+ };
45910
+ }
45911
+ function initRunners(resolvedPluginConfig, viteDevServer, miniflare) {
45912
+ const initPromises = [...resolvedPluginConfig.environmentNameToWorkerMap].flatMap(([environmentName, worker]) => {
45913
+ debuglog("Initializing worker:", worker.config.name);
45914
+ const isEntryWorker = environmentName === resolvedPluginConfig.entryWorkerEnvironmentName;
45915
+ const childEnvironmentNames = resolvedPluginConfig.environmentNameToChildEnvironmentNamesMap.get(environmentName) ?? [];
45916
+ return [viteDevServer.environments[environmentName].initRunner(miniflare, worker.config, {
45917
+ isEntryWorker,
45918
+ isParentEnvironment: true
45919
+ }), ...childEnvironmentNames.map((childEnvironmentName) => {
45920
+ debuglog("Initializing child environment:", childEnvironmentName);
45921
+ return viteDevServer.environments[childEnvironmentName].initRunner(miniflare, worker.config, {
45922
+ isEntryWorker: false,
45923
+ isParentEnvironment: false
45924
+ });
45925
+ })];
45926
+ });
45927
+ return Promise.all(initPromises);
45928
+ }
45929
+
45930
+ //#endregion
45931
+ //#region src/plugins/build-output.ts
45932
+ /**
45933
+ * Build Output API plugin. Replaces `outputConfigPlugin` when
45934
+ * `experimental.newConfig.cfBuildOutput` is set.
45935
+ */
45936
+ const buildOutputPlugin = createPlugin("build-output", (ctx) => {
45937
+ return { writeBundle(_options, bundle) {
45938
+ if (ctx.isChildEnvironment(this.environment.name)) return;
45939
+ if (ctx.resolvedPluginConfig.type === "assets-only" && this.environment.name === "client") {
45940
+ const workerNewConfig$1 = ctx.resolvedPluginConfig.parsedNewConfig;
45941
+ assert(workerNewConfig$1, "Expected parsedNewConfig on assets-only resolved config");
45942
+ writeOutputWorkerConfig(ctx.resolvedViteConfig.root, workerNewConfig$1);
45943
+ return;
45944
+ }
45945
+ const workerNewConfig = ctx.getWorkerNewConfig(this.environment.name);
45946
+ if (!workerNewConfig) return;
45947
+ const entryChunk = Object.values(bundle).find((chunk) => chunk.type === "chunk" && chunk.isEntry && chunk.name === MAIN_ENTRY_NAME);
45948
+ assert(entryChunk, `Expected entry chunk with name "${MAIN_ENTRY_NAME}"`);
45949
+ const importedAssetPaths = /* @__PURE__ */ new Set();
45950
+ for (const entry of Object.values(bundle)) for (const asset of entry.viteMetadata?.importedAssets ?? []) importedAssetPaths.add(asset);
45951
+ const modules = {};
45952
+ for (const fileName of Object.keys(bundle)) {
45953
+ if (fileName === ".vite/manifest.json") continue;
45954
+ if (importedAssetPaths.has(fileName)) continue;
45955
+ modules[fileName] = { type: detectModuleType(fileName) };
45956
+ }
45957
+ writeOutputWorkerConfig(ctx.resolvedViteConfig.root, workerNewConfig, {
45958
+ mainModule: entryChunk.fileName,
45959
+ modules
45960
+ });
45961
+ } };
45962
+ });
45963
+
45522
45964
  //#endregion
45523
45965
  //#region ../workers-shared/utils/configuration/constructConfiguration.ts
45524
45966
  function constructRedirects({ redirects, redirectsFile, logger }) {
@@ -51188,7 +51630,8 @@ function createBuildApp(resolvedPluginConfig) {
51188
51630
  if (hasClientEntry) await builder.build(clientEnvironment);
51189
51631
  else if (importedAssetPaths.size || getHasPublicAssets(builder.config) || resolvedPluginConfig.prerenderWorkerEnvironmentName) await fallbackBuild(builder, clientEnvironment);
51190
51632
  else {
51191
- if (!satisfiesMinimumViteVersion("7.0.0")) removeAssetsField(entryWorkerBuildDirectory);
51633
+ const cfBuildOutput = resolvedPluginConfig.experimental.newConfig?.cfBuildOutput === true;
51634
+ if (!satisfiesMinimumViteVersion("7.0.0") && !cfBuildOutput) removeAssetsField(entryWorkerBuildDirectory);
51192
51635
  return;
51193
51636
  }
51194
51637
  const clientBuildDirectory = nodePath.resolve(builder.config.root, clientEnvironment.config.build.outDir);
@@ -51243,234 +51686,6 @@ function removeAssetsField(entryWorkerBuildDirectory) {
51243
51686
  fs$1.writeFileSync(entryWorkerConfigPath, JSON.stringify(workerConfig));
51244
51687
  }
51245
51688
 
51246
- //#endregion
51247
- //#region src/cloudflare-environment.ts
51248
- const MAIN_ENTRY_NAME = "index";
51249
- const webSocketUndefinedError = "The WebSocket is undefined";
51250
- function createHotChannel(webSocketContainer) {
51251
- const listenersMap = /* @__PURE__ */ new Map();
51252
- const client = { send(payload) {
51253
- const webSocket = webSocketContainer.webSocket;
51254
- assert(webSocket, webSocketUndefinedError);
51255
- webSocket.send(JSON.stringify(payload));
51256
- } };
51257
- function onMessage(event) {
51258
- const payload = JSON.parse(event.data.toString());
51259
- const listeners = listenersMap.get(payload.event) ?? /* @__PURE__ */ new Set();
51260
- for (const listener of listeners) listener(payload.data, client);
51261
- }
51262
- return {
51263
- send(payload) {
51264
- const webSocket = webSocketContainer.webSocket;
51265
- const message = JSON.stringify(payload);
51266
- if (!webSocket) {
51267
- webSocketContainer.messageBuffers ??= [];
51268
- webSocketContainer.messageBuffers.push(message);
51269
- return;
51270
- }
51271
- webSocket.send(message);
51272
- },
51273
- on(event, listener) {
51274
- const listeners = listenersMap.get(event) ?? /* @__PURE__ */ new Set();
51275
- listeners.add(listener);
51276
- listenersMap.set(event, listeners);
51277
- },
51278
- off(event, listener) {
51279
- listenersMap.get(event)?.delete(listener);
51280
- },
51281
- listen() {
51282
- const webSocket = webSocketContainer.webSocket;
51283
- assert(webSocket, webSocketUndefinedError);
51284
- webSocket.addEventListener("message", onMessage);
51285
- },
51286
- close() {
51287
- const webSocket = webSocketContainer.webSocket;
51288
- assert(webSocket, webSocketUndefinedError);
51289
- webSocket.removeEventListener("message", onMessage);
51290
- }
51291
- };
51292
- }
51293
- var CloudflareDevEnvironment = class extends vite.DevEnvironment {
51294
- #webSocketContainer;
51295
- constructor(name, config) {
51296
- const webSocketContainer = {};
51297
- super(name, config, {
51298
- hot: true,
51299
- transport: createHotChannel(webSocketContainer)
51300
- });
51301
- this.#webSocketContainer = webSocketContainer;
51302
- }
51303
- async initRunner(miniflare, workerConfig, options) {
51304
- const response = await miniflare.dispatchFetch(new URL(INIT_PATH, UNKNOWN_HOST), { headers: {
51305
- [CoreHeaders.ROUTE_OVERRIDE]: workerConfig.name,
51306
- [WORKER_ENTRY_PATH_HEADER]: encodeURIComponent(workerConfig.main),
51307
- [IS_ENTRY_WORKER_HEADER]: String(options.isEntryWorker),
51308
- [ENVIRONMENT_NAME_HEADER]: this.name,
51309
- [IS_PARENT_ENVIRONMENT_HEADER]: String(options.isParentEnvironment),
51310
- upgrade: "websocket"
51311
- } });
51312
- assert(response.ok, `Failed to initialize module runner, error: ${await response.text()}`);
51313
- const webSocket = response.webSocket;
51314
- assert(webSocket, "Failed to establish WebSocket");
51315
- webSocket.accept();
51316
- this.#webSocketContainer.webSocket = webSocket;
51317
- if (this.#webSocketContainer.messageBuffers) {
51318
- for (const bufferedMessage of this.#webSocketContainer.messageBuffers) webSocket.send(bufferedMessage);
51319
- delete this.#webSocketContainer.messageBuffers;
51320
- }
51321
- }
51322
- async fetchWorkerExportTypes(miniflare, workerConfig) {
51323
- await this.depsOptimizer?.init();
51324
- return await (await miniflare.dispatchFetch(new URL(GET_EXPORT_TYPES_PATH, UNKNOWN_HOST), { headers: { [CoreHeaders.ROUTE_OVERRIDE]: workerConfig.name } })).json();
51325
- }
51326
- async fetchModule(id, importer, options) {
51327
- if (additionalModuleRE.test(id)) return {
51328
- externalize: id,
51329
- type: "module"
51330
- };
51331
- return super.fetchModule(id, importer, options);
51332
- }
51333
- };
51334
- const cloudflareBuiltInModules = [
51335
- "cloudflare:email",
51336
- "cloudflare:node",
51337
- "cloudflare:sockets",
51338
- "cloudflare:workers",
51339
- "cloudflare:workflows"
51340
- ];
51341
- const defaultConditions = [
51342
- "workerd",
51343
- "worker",
51344
- "module",
51345
- "browser"
51346
- ];
51347
- const target = "es2024";
51348
- const resolveExtensions = [
51349
- ".mjs",
51350
- ".js",
51351
- ".mts",
51352
- ".ts",
51353
- ".jsx",
51354
- ".tsx",
51355
- ".json",
51356
- ".cjs",
51357
- ".cts",
51358
- ".ctx"
51359
- ];
51360
- function createCloudflareEnvironmentOptions({ workerConfig, userConfig, mode, environmentName, isEntryWorker, isParentEnvironment, hasNodeJsCompat: hasNodeJsCompat$1 }) {
51361
- const rollupOptions = isParentEnvironment ? {
51362
- input: { [MAIN_ENTRY_NAME]: VIRTUAL_WORKER_ENTRY },
51363
- preserveEntrySignatures: "strict"
51364
- } : {};
51365
- const define$1 = getProcessEnvReplacements(hasNodeJsCompat$1, mode);
51366
- return {
51367
- resolve: {
51368
- noExternal: true,
51369
- conditions: [...defaultConditions, "development|production"],
51370
- builtins: [...cloudflareBuiltInModules]
51371
- },
51372
- define: define$1,
51373
- dev: { createEnvironment(name, config) {
51374
- if (!config.plugins.some((plugin) => plugin.name === "vite-plugin-cloudflare:dev" && plugin.configureServer !== void 0)) return vite.createRunnableDevEnvironment(name, config);
51375
- return new CloudflareDevEnvironment(name, config);
51376
- } },
51377
- build: {
51378
- createEnvironment(name, config) {
51379
- return new vite.BuildEnvironment(name, config);
51380
- },
51381
- target,
51382
- emitAssets: true,
51383
- manifest: isEntryWorker,
51384
- outDir: getOutputDirectory(userConfig, environmentName),
51385
- copyPublicDir: false,
51386
- ssr: true,
51387
- ...isRolldown ? { rolldownOptions: {
51388
- ...rollupOptions,
51389
- platform: "neutral",
51390
- resolve: { extensions: resolveExtensions }
51391
- } } : { rollupOptions }
51392
- },
51393
- optimizeDeps: {
51394
- noDiscovery: false,
51395
- ignoreOutdatedRequests: true,
51396
- entries: vite.normalizePath(workerConfig.main),
51397
- exclude: [
51398
- ...cloudflareBuiltInModules,
51399
- ...nonPrefixedNodeModules,
51400
- ...nonPrefixedNodeModules.map((module$1) => `node:${module$1}`),
51401
- ...[
51402
- "node:sea",
51403
- "node:sqlite",
51404
- "node:test",
51405
- "node:test/reporters"
51406
- ]
51407
- ],
51408
- ...isRolldown ? { rolldownOptions: {
51409
- platform: "neutral",
51410
- resolve: {
51411
- conditionNames: [...defaultConditions, "development"],
51412
- extensions: resolveExtensions
51413
- },
51414
- transform: {
51415
- target,
51416
- define: define$1
51417
- },
51418
- plugins: [vite.esmExternalRequirePlugin({
51419
- external: [nodeBuiltinsRE],
51420
- skipDuplicateCheck: true
51421
- })]
51422
- } } : { esbuildOptions: {
51423
- platform: "neutral",
51424
- conditions: [...defaultConditions, "development"],
51425
- resolveExtensions,
51426
- target,
51427
- define: define$1
51428
- } }
51429
- },
51430
- keepProcessEnv: true
51431
- };
51432
- }
51433
- /**
51434
- * Gets `process.env` replacement values.
51435
- * `process.env.NODE_ENV` is always replaced.
51436
- * `process.env` is replaced with an empty object if `nodejs_compat` is not enabled
51437
- * @param hasNodeJsCompat - whether `nodejs_compat` is enabled
51438
- * @param mode - the Vite mode
51439
- * @returns replacement values
51440
- */
51441
- function getProcessEnvReplacements(hasNodeJsCompat$1, mode) {
51442
- const nodeEnv = process.env.NODE_ENV || mode;
51443
- const nodeEnvReplacements = {
51444
- "process.env.NODE_ENV": JSON.stringify(nodeEnv),
51445
- "global.process.env.NODE_ENV": JSON.stringify(nodeEnv),
51446
- "globalThis.process.env.NODE_ENV": JSON.stringify(nodeEnv)
51447
- };
51448
- return hasNodeJsCompat$1 ? nodeEnvReplacements : {
51449
- ...nodeEnvReplacements,
51450
- "process.env": "{}",
51451
- "global.process.env": "{}",
51452
- "globalThis.process.env": "{}"
51453
- };
51454
- }
51455
- function initRunners(resolvedPluginConfig, viteDevServer, miniflare) {
51456
- const initPromises = [...resolvedPluginConfig.environmentNameToWorkerMap].flatMap(([environmentName, worker]) => {
51457
- debuglog("Initializing worker:", worker.config.name);
51458
- const isEntryWorker = environmentName === resolvedPluginConfig.entryWorkerEnvironmentName;
51459
- const childEnvironmentNames = resolvedPluginConfig.environmentNameToChildEnvironmentNamesMap.get(environmentName) ?? [];
51460
- return [viteDevServer.environments[environmentName].initRunner(miniflare, worker.config, {
51461
- isEntryWorker,
51462
- isParentEnvironment: true
51463
- }), ...childEnvironmentNames.map((childEnvironmentName) => {
51464
- debuglog("Initializing child environment:", childEnvironmentName);
51465
- return viteDevServer.environments[childEnvironmentName].initRunner(miniflare, worker.config, {
51466
- isEntryWorker: false,
51467
- isParentEnvironment: false
51468
- });
51469
- })];
51470
- });
51471
- return Promise.all(initPromises);
51472
- }
51473
-
51474
51689
  //#endregion
51475
51690
  //#region src/dev-vars.ts
51476
51691
  /**
@@ -51574,7 +51789,12 @@ const configPlugin = createPlugin("config", (ctx) => {
51574
51789
  },
51575
51790
  configResolved(resolvedViteConfig) {
51576
51791
  ctx.setResolvedViteConfig(resolvedViteConfig);
51577
- if (ctx.resolvedPluginConfig.type !== "preview") validateWorkerEnvironmentOptions(ctx.resolvedPluginConfig, ctx.resolvedViteConfig);
51792
+ if (ctx.resolvedPluginConfig.type === "preview") return;
51793
+ validateWorkerEnvironmentOptions(ctx.resolvedPluginConfig, ctx.resolvedViteConfig);
51794
+ if (ctx.resolvedPluginConfig.experimental.newConfig?.cfBuildOutput) {
51795
+ forceBuildOutputDirs(ctx.resolvedPluginConfig, ctx.resolvedViteConfig);
51796
+ if (ctx.resolvedViteConfig.command === "build") cleanBuildOutputDir(ctx.resolvedViteConfig.root);
51797
+ }
51578
51798
  },
51579
51799
  buildStart() {
51580
51800
  ctx.setHasShownWorkerConfigWarnings(false);
@@ -51604,26 +51824,33 @@ const configPlugin = createPlugin("config", (ctx) => {
51604
51824
  const { entryWorkerEnvironmentName } = ctx.resolvedPluginConfig;
51605
51825
  const entryWorkerEnvironment = builder.environments[entryWorkerEnvironmentName];
51606
51826
  assert(entryWorkerEnvironment, `No "${entryWorkerEnvironmentName}" environment`);
51827
+ const cfBuildOutput = ctx.resolvedPluginConfig.experimental.newConfig?.cfBuildOutput === true;
51607
51828
  if (entryWorkerEnvironment.isBuilt) {
51608
- if (!builder.environments.client?.isBuilt) removeAssetsField(nodePath.resolve(builder.config.root, entryWorkerEnvironment.config.build.outDir));
51829
+ if (!builder.environments.client?.isBuilt && !cfBuildOutput) removeAssetsField(nodePath.resolve(builder.config.root, entryWorkerEnvironment.config.build.outDir));
51609
51830
  } else {
51610
51831
  const clientEnvironment = builder.environments.client;
51611
51832
  assert(clientEnvironment, "No \"client\" environment");
51612
51833
  if (!clientEnvironment.isBuilt) throw new Error("If `assetsOnly` is set to `true`, the client environment must be built");
51613
- const entryWorkerConfig = ctx.getWorkerConfig(entryWorkerEnvironmentName);
51614
- assert(entryWorkerConfig, `No config found for "${entryWorkerEnvironmentName}" environment`);
51615
- const outputConfig = {
51616
- ...entryWorkerConfig,
51617
- main: void 0,
51618
- assets: {
51619
- ...entryWorkerConfig.assets,
51620
- directory: ".",
51621
- binding: void 0
51622
- }
51623
- };
51624
- if (outputConfig.unsafe && Object.keys(outputConfig.unsafe).length === 0) outputConfig.unsafe = void 0;
51625
- fs$1.writeFileSync(nodePath.resolve(builder.config.root, clientEnvironment.config.build.outDir, "wrangler.json"), JSON.stringify(outputConfig));
51626
- writeDeployConfig(ctx.resolvedPluginConfig, ctx.resolvedViteConfig, true);
51834
+ if (cfBuildOutput) {
51835
+ const entryWorkerNewConfig = ctx.getWorkerNewConfig(entryWorkerEnvironmentName);
51836
+ assert(entryWorkerNewConfig, `No config found for "${entryWorkerEnvironmentName}" environment`);
51837
+ writeOutputWorkerConfig(builder.config.root, entryWorkerNewConfig);
51838
+ } else {
51839
+ const entryWorkerConfig = ctx.getWorkerConfig(entryWorkerEnvironmentName);
51840
+ assert(entryWorkerConfig, `No config found for "${entryWorkerEnvironmentName}" environment`);
51841
+ const outputConfig = {
51842
+ ...entryWorkerConfig,
51843
+ main: void 0,
51844
+ assets: {
51845
+ ...entryWorkerConfig.assets,
51846
+ directory: ".",
51847
+ binding: void 0
51848
+ }
51849
+ };
51850
+ if (outputConfig.unsafe && Object.keys(outputConfig.unsafe).length === 0) outputConfig.unsafe = void 0;
51851
+ fs$1.writeFileSync(nodePath.resolve(builder.config.root, clientEnvironment.config.build.outDir, "wrangler.json"), JSON.stringify(outputConfig));
51852
+ writeDeployConfig(ctx.resolvedPluginConfig, ctx.resolvedViteConfig, true);
51853
+ }
51627
51854
  }
51628
51855
  }
51629
51856
  }
@@ -51663,6 +51890,37 @@ function getEnvironmentsConfig(ctx, userConfig, mode) {
51663
51890
  }
51664
51891
  };
51665
51892
  }
51893
+ /**
51894
+ * When the Build Output API is enabled,
51895
+ * force every Worker environment's and the client environment's `build.outDir`
51896
+ * to the spec-mandated location.
51897
+ *
51898
+ * Runs after Vite's merge in `configResolved`, so it overrides any
51899
+ * user-supplied `build.outDir`
51900
+ */
51901
+ function forceBuildOutputDirs(resolvedPluginConfig, resolvedViteConfig) {
51902
+ if (!resolvedPluginConfig.experimental.newConfig?.cfBuildOutput) return;
51903
+ const { root } = resolvedViteConfig;
51904
+ let clientWorkerName;
51905
+ if (resolvedPluginConfig.type === "workers") {
51906
+ for (const [environmentName, worker] of resolvedPluginConfig.environmentNameToWorkerMap) {
51907
+ const environment = resolvedViteConfig.environments[environmentName];
51908
+ if (!environment) continue;
51909
+ assert(worker.parsedNewConfig, "Expected parsedNewConfig to be defined");
51910
+ environment.build.outDir = getWorkerBundleDir(root, worker.parsedNewConfig.name);
51911
+ }
51912
+ const entryName = resolvedPluginConfig.entryWorkerEnvironmentName;
51913
+ const entryWorker = resolvedPluginConfig.environmentNameToWorkerMap.get(entryName);
51914
+ assert(entryWorker, `Expected entry worker for environment "${entryName}"`);
51915
+ assert(entryWorker.parsedNewConfig, "Expected parsedNewConfig to be defined");
51916
+ clientWorkerName = entryWorker.parsedNewConfig.name;
51917
+ } else {
51918
+ assert(resolvedPluginConfig.parsedNewConfig, "Expected parsedNewConfig to be defined");
51919
+ clientWorkerName = resolvedPluginConfig.parsedNewConfig.name;
51920
+ }
51921
+ const clientEnvironment = resolvedViteConfig.environments.client;
51922
+ if (clientEnvironment) clientEnvironment.build.outDir = getWorkerAssetsDir(root, clientWorkerName);
51923
+ }
51666
51924
  function getAllowedHosts(tunnelHostnames, userAllowedHosts) {
51667
51925
  if (tunnelHostnames.length === 0 || userAllowedHosts === true) return userAllowedHosts;
51668
51926
  return Array.from(new Set([...userAllowedHosts ?? [], ...tunnelHostnames]));
@@ -51763,8 +52021,8 @@ const debugPlugin = createPlugin("debug", (ctx) => {
51763
52021
  if (!!process.env.VSCODE_INSPECTOR_OPTIONS) return;
51764
52022
  if (ctx.resolvedPluginConfig.workers.length >= 1 && ctx.resolvedPluginConfig.inspectorPort !== false) addDebugToVitePrintUrls(vitePreviewServer);
51765
52023
  const workerNames = ctx.resolvedPluginConfig.workers.map((worker) => {
51766
- assert(worker.name, "Expected the Worker to have a name");
51767
- return worker.name;
52024
+ assert(worker.config.name, "Expected the Worker to have a name");
52025
+ return worker.config.name;
51768
52026
  });
51769
52027
  vitePreviewServer.middlewares.use(DEBUG_PATH, async (_, res, next) => {
51770
52028
  const resolvedInspectorPort = await ctx.getResolvedInspectorPort();
@@ -55953,11 +56211,54 @@ function getPreviewModules(main, modulesRules) {
55953
56211
  })))]
55954
56212
  };
55955
56213
  }
56214
+ /**
56215
+ * Translate a Build Output API module type to a Miniflare module type.
56216
+ */
56217
+ function toMiniflareModuleType(type) {
56218
+ switch (type) {
56219
+ case "esm": return "ESModule";
56220
+ case "cjs": return "CommonJS";
56221
+ case "wasm": return "CompiledWasm";
56222
+ case "text": return "Text";
56223
+ case "data": return "Data";
56224
+ case "json": return "Data";
56225
+ case "python": return "PythonModule";
56226
+ case "pythonRequirement": return null;
56227
+ case "sourcemap": return null;
56228
+ }
56229
+ }
56230
+ /**
56231
+ * Get Miniflare's module list directly from the `modules` manifest.
56232
+ *
56233
+ * Miniflare uses the first module in the list as the entry, so the
56234
+ * `mainModule` is hoisted to index 0 regardless of the manifest's
56235
+ * order.
56236
+ */
56237
+ function getModulesFromManifest(bundle) {
56238
+ const { mainModule } = bundle;
56239
+ const mainEntry = bundle.modules[mainModule];
56240
+ assert(mainEntry !== void 0, `Build Output API: \`mainModule\` "${mainModule}" is missing from \`modules\`.`);
56241
+ const ordered = [[mainModule, mainEntry]];
56242
+ for (const [modulePath, value] of Object.entries(bundle.modules)) if (modulePath !== mainModule) ordered.push([modulePath, value]);
56243
+ const modules = ordered.map(([modulePath, { type }]) => {
56244
+ const miniflareType = toMiniflareModuleType(type);
56245
+ if (miniflareType === null) return null;
56246
+ return {
56247
+ type: miniflareType,
56248
+ path: modulePath
56249
+ };
56250
+ }).filter((m) => m !== null);
56251
+ return {
56252
+ rootPath: bundle.rootPath,
56253
+ modules
56254
+ };
56255
+ }
55956
56256
  async function getPreviewMiniflareOptions(ctx, vitePreviewServer) {
55957
56257
  const inputInspectorPort = await getInputInspectorPort(ctx, vitePreviewServer);
55958
56258
  const { resolvedPluginConfig, resolvedViteConfig } = ctx;
55959
56259
  const containerTagToOptionsMap = /* @__PURE__ */ new Map();
55960
- const workers = (await Promise.all(resolvedPluginConfig.workers.map(async (workerConfig) => {
56260
+ const workers = (await Promise.all(resolvedPluginConfig.workers.map(async (previewWorker) => {
56261
+ const workerConfig = previewWorker.config;
55961
56262
  const bindings = wrangler.unstable_convertConfigBindingsToStartWorkerBindings(workerConfig);
55962
56263
  const preExistingRemoteProxySessionData = workerConfig.configPath ? remoteProxySessionsDataMap.get(workerConfig.configPath) : void 0;
55963
56264
  const remoteProxySessionData = !resolvedPluginConfig.remoteBindings ? null : await wrangler.maybeStartOrUpdateRemoteProxySession({
@@ -55988,7 +56289,7 @@ async function getPreviewMiniflareOptions(ctx, vitePreviewServer) {
55988
56289
  ...workerOptions,
55989
56290
  name: workerOptions.name ?? workerConfig.name,
55990
56291
  unsafeInspectorProxy: inputInspectorPort !== false,
55991
- ...miniflareWorkerOptions.main ? getPreviewModules(miniflareWorkerOptions.main, modulesRules) : {
56292
+ ...previewWorker.source === "build-output" && previewWorker.bundle ? getModulesFromManifest(previewWorker.bundle) : miniflareWorkerOptions.main ? getPreviewModules(miniflareWorkerOptions.main, modulesRules) : {
55992
56293
  modules: true,
55993
56294
  script: ""
55994
56295
  }
@@ -57253,6 +57554,8 @@ await assertWranglerVersion();
57253
57554
  */
57254
57555
  function cloudflare(pluginConfig = {}) {
57255
57556
  const ctx = new PluginContext(sharedContext);
57557
+ const newConfig = pluginConfig.experimental?.newConfig;
57558
+ const outputPlugin = typeof newConfig === "object" && newConfig?.cfBuildOutput === true ? buildOutputPlugin(ctx) : outputConfigPlugin(ctx);
57256
57559
  return [
57257
57560
  {
57258
57561
  name: "vite-plugin-cloudflare",
@@ -57285,7 +57588,7 @@ function cloudflare(pluginConfig = {}) {
57285
57588
  triggerHandlersPlugin(ctx),
57286
57589
  virtualModulesPlugin(ctx),
57287
57590
  virtualClientFallbackPlugin(ctx),
57288
- outputConfigPlugin(ctx),
57591
+ outputPlugin,
57289
57592
  wasmHelperPlugin(ctx),
57290
57593
  additionalModulesPlugin(ctx),
57291
57594
  nodeJsAlsPlugin(ctx),