@cloudflare/vite-plugin 1.6.0 → 1.7.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.
@@ -6021,7 +6021,7 @@ var CustomAssetWorker = class extends worker_default {
6021
6021
  }
6022
6022
  async unstable_getByETag(eTag) {
6023
6023
  const url = new URL(eTag, UNKNOWN_HOST);
6024
- const response = await this.env.__VITE_FETCH_ASSET__.fetch(url);
6024
+ const response = await this.env.__VITE_FETCH_HTML__.fetch(url);
6025
6025
  if (!response.body) {
6026
6026
  throw new Error(`Unexpected error. No HTML found for "${eTag}".`);
6027
6027
  }
@@ -6033,9 +6033,8 @@ var CustomAssetWorker = class extends worker_default {
6033
6033
  }
6034
6034
  async unstable_exists(pathname) {
6035
6035
  const url = new URL(pathname.replace(/^\/{2,}/, "/"), UNKNOWN_HOST);
6036
- const response = await this.env.__VITE_ASSET_EXISTS__.fetch(url);
6037
- const exists = await response.json();
6038
- return exists ? pathname : null;
6036
+ const response = await this.env.__VITE_HTML_EXISTS__.fetch(url);
6037
+ return response.json();
6039
6038
  }
6040
6039
  async unstable_canFetch(request) {
6041
6040
  const secFetchMode = request.headers.get("X-Mf-Sec-Fetch-Mode");
package/dist/index.js CHANGED
@@ -489,7 +489,32 @@ import assert11 from "node:assert";
489
489
  import * as fs6 from "node:fs";
490
490
  import * as fsp2 from "node:fs/promises";
491
491
  import * as path10 from "node:path";
492
- import { createRequest, sendResponse } from "@mjackson/node-fetch-server";
492
+
493
+ // ../workers-shared/asset-worker/src/utils/rules-engine.ts
494
+ var ESCAPE_REGEX_CHARACTERS = /[-/\\^$*+?.()|[\]{}]/g;
495
+ var escapeRegex = (str) => {
496
+ return str.replace(ESCAPE_REGEX_CHARACTERS, "\\$&");
497
+ };
498
+ var generateGlobOnlyRuleRegExp = (rule) => {
499
+ rule = rule.split("*").map(escapeRegex).join(".*");
500
+ rule = "^" + rule + "$";
501
+ return RegExp(rule);
502
+ };
503
+ var generateStaticRoutingRuleMatcher = (rules) => ({ request }) => {
504
+ const { pathname } = new URL(request.url);
505
+ for (const rule of rules) {
506
+ try {
507
+ const regExp = generateGlobOnlyRuleRegExp(rule);
508
+ if (regExp.test(pathname)) {
509
+ return true;
510
+ }
511
+ } catch {
512
+ }
513
+ }
514
+ return false;
515
+ };
516
+
517
+ // src/index.ts
493
518
  import replace from "@rollup/plugin-replace";
494
519
 
495
520
  // ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.5.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
@@ -1066,19 +1091,19 @@ var MagicString = class _MagicString {
1066
1091
  });
1067
1092
  }
1068
1093
  let shouldIndentNextCharacter = options.indentStart !== false;
1069
- const replacer = (match) => {
1094
+ const replacer2 = (match) => {
1070
1095
  if (shouldIndentNextCharacter) return `${indentStr}${match}`;
1071
1096
  shouldIndentNextCharacter = true;
1072
1097
  return match;
1073
1098
  };
1074
- this.intro = this.intro.replace(pattern, replacer);
1099
+ this.intro = this.intro.replace(pattern, replacer2);
1075
1100
  let charIndex = 0;
1076
1101
  let chunk = this.firstChunk;
1077
1102
  while (chunk) {
1078
1103
  const end = chunk.end;
1079
1104
  if (chunk.edited) {
1080
1105
  if (!isExcluded[charIndex]) {
1081
- chunk.content = chunk.content.replace(pattern, replacer);
1106
+ chunk.content = chunk.content.replace(pattern, replacer2);
1082
1107
  if (chunk.content.length) {
1083
1108
  shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === "\n";
1084
1109
  }
@@ -1107,7 +1132,7 @@ var MagicString = class _MagicString {
1107
1132
  charIndex = chunk.end;
1108
1133
  chunk = chunk.next;
1109
1134
  }
1110
- this.outro = this.outro.replace(pattern, replacer);
1135
+ this.outro = this.outro.replace(pattern, replacer2);
1111
1136
  return this;
1112
1137
  }
1113
1138
  insert() {
@@ -1559,7 +1584,7 @@ var MagicString = class _MagicString {
1559
1584
  // src/index.ts
1560
1585
  import { Miniflare } from "miniflare";
1561
1586
  import colors4 from "picocolors";
1562
- import * as vite7 from "vite";
1587
+ import * as vite6 from "vite";
1563
1588
 
1564
1589
  // src/constants.ts
1565
1590
  var ROUTER_WORKER_NAME = "__router-worker__";
@@ -1570,6 +1595,7 @@ var ADDITIONAL_MODULE_TYPES = [
1570
1595
  "Data",
1571
1596
  "Text"
1572
1597
  ];
1598
+ var PUBLIC_DIR_PREFIX = "/__vite_public_dir__";
1573
1599
  var DEFAULT_INSPECTOR_PORT = 9229;
1574
1600
  var kRequestType = Symbol("kRequestType");
1575
1601
 
@@ -1600,8 +1626,8 @@ import * as path from "node:path";
1600
1626
  import { relative } from "node:path";
1601
1627
 
1602
1628
  // ../workers-shared/utils/configuration/constants.ts
1603
- var REDIRECTS_VERSION = 1;
1604
- var HEADERS_VERSION = 2;
1629
+ var REDIRECTS_VERSION2 = 1;
1630
+ var HEADERS_VERSION2 = 2;
1605
1631
  var PERMITTED_STATUS_CODES = /* @__PURE__ */ new Set([200, 301, 302, 303, 307, 308]);
1606
1632
  var HEADER_SEPARATOR = ":";
1607
1633
  var MAX_LINE_LENGTH = 2e3;
@@ -1611,6 +1637,8 @@ var MAX_STATIC_REDIRECT_RULES = 2e3;
1611
1637
  var UNSET_OPERATOR = "! ";
1612
1638
  var SPLAT_REGEX = /\*/g;
1613
1639
  var PLACEHOLDER_REGEX = /:[A-Za-z]\w*/g;
1640
+ var MAX_ROUTES_RULES = 100;
1641
+ var MAX_ROUTES_RULE_LENGTH = 100;
1614
1642
 
1615
1643
  // ../workers-shared/utils/configuration/constructConfiguration.ts
1616
1644
  function constructRedirects({
@@ -1669,7 +1697,7 @@ ${invalidRedirectRulesList}`
1669
1697
  }
1670
1698
  return {
1671
1699
  redirects: {
1672
- version: REDIRECTS_VERSION,
1700
+ version: REDIRECTS_VERSION2,
1673
1701
  staticRules: staticRedirects,
1674
1702
  rules: dynamicRedirects
1675
1703
  }
@@ -1721,7 +1749,7 @@ ${invalidHeaderRulesList}`
1721
1749
  }
1722
1750
  return {
1723
1751
  headers: {
1724
- version: HEADERS_VERSION,
1752
+ version: HEADERS_VERSION2,
1725
1753
  rules
1726
1754
  }
1727
1755
  };
@@ -5860,7 +5888,8 @@ function getAssetsConfig(resolvedPluginConfig, entryWorkerConfig, resolvedConfig
5860
5888
  };
5861
5889
  const config = {
5862
5890
  ...compatibilityOptions,
5863
- ...assetsConfig
5891
+ ...assetsConfig,
5892
+ has_static_routing: resolvedPluginConfig.type === "workers" && resolvedPluginConfig.staticRouting ? true : false
5864
5893
  };
5865
5894
  if (!resolvedPluginConfig.experimental?.headersAndRedirectsDevModeSupport) {
5866
5895
  return config;
@@ -6047,7 +6076,7 @@ function getImportedAssetPaths(viteManifest) {
6047
6076
 
6048
6077
  // src/cloudflare-environment.ts
6049
6078
  import assert4 from "node:assert";
6050
- import * as vite3 from "vite";
6079
+ import * as vite2 from "vite";
6051
6080
 
6052
6081
  // src/node-js-compat.ts
6053
6082
  import assert3 from "node:assert";
@@ -13030,24 +13059,41 @@ function isNodeAls(workerConfig) {
13030
13059
  function isNodeAlsModule(path11) {
13031
13060
  return /^(node:)?async_hooks$/.test(path11);
13032
13061
  }
13033
- function injectGlobalCode(id, code) {
13034
- const injectedCode = Object.entries(env.inject).map(([globalName, globalInject]) => {
13035
- if (typeof globalInject === "string") {
13036
- const moduleSpecifier2 = globalInject;
13037
- return `import var_${globalName} from "${moduleSpecifier2}";
13038
- globalThis.${globalName} = var_${globalName};
13039
- `;
13040
- }
13041
- const [moduleSpecifier, exportName] = globalInject;
13042
- assert3(
13043
- moduleSpecifier !== void 0,
13044
- "Expected moduleSpecifier to be defined"
13062
+ var injectsByModule = /* @__PURE__ */ new Map();
13063
+ var virtualModulePathToSpecifier = /* @__PURE__ */ new Map();
13064
+ var virtualModulePrefix = `\0_nodejs_global_inject-`;
13065
+ for (const [injectedName, moduleSpecifier] of Object.entries(env.inject)) {
13066
+ const [module, exportName, importName] = Array.isArray(moduleSpecifier) ? [moduleSpecifier[0], moduleSpecifier[1], moduleSpecifier[1]] : [moduleSpecifier, "default", "defaultExport"];
13067
+ if (!injectsByModule.has(module)) {
13068
+ injectsByModule.set(module, []);
13069
+ virtualModulePathToSpecifier.set(
13070
+ virtualModulePrefix + module.replaceAll("/", "-"),
13071
+ module
13045
13072
  );
13046
- assert3(exportName !== void 0, "Expected exportName to be defined");
13047
- return `import var_${globalName} from "${moduleSpecifier}";
13048
- globalThis.${globalName} = var_${globalName}.${exportName};
13049
- `;
13050
- }).join("\n");
13073
+ }
13074
+ const injects = injectsByModule.get(module);
13075
+ assert3(injects, `expected injects for ${module} to be defined`);
13076
+ injects.push({ injectedName, exportName, importName });
13077
+ }
13078
+ function isGlobalVirtualModule(modulePath) {
13079
+ return virtualModulePathToSpecifier.has(modulePath);
13080
+ }
13081
+ function getGlobalVirtualModule(modulePath) {
13082
+ const module = virtualModulePathToSpecifier.get(modulePath);
13083
+ if (!module) {
13084
+ return void 0;
13085
+ }
13086
+ const injects = injectsByModule.get(module);
13087
+ assert3(injects, `expected injects for ${module} to be defined`);
13088
+ const imports = injects.map(
13089
+ ({ exportName, importName }) => importName === exportName ? exportName : `${exportName} as ${importName}`
13090
+ );
13091
+ return `import { ${imports.join(", ")} } from "${module}";
13092
+ ${injects.map(({ injectedName, importName }) => `globalThis.${injectedName} = ${importName};`).join("\n")}`;
13093
+ }
13094
+ function injectGlobalCode(id, code) {
13095
+ const injectedCode = Array.from(virtualModulePathToSpecifier.keys()).map((moduleId) => `import "${moduleId}";
13096
+ `).join("");
13051
13097
  const polyfillCode = env.polyfill.map((polyfillPath) => `import "${polyfillPath}";
13052
13098
  `).join("");
13053
13099
  const modified = new MagicString(code);
@@ -13143,13 +13189,41 @@ var VITE_DEV_METADATA_HEADER = "__VITE_DEV_METADATA__";
13143
13189
 
13144
13190
  // src/utils.ts
13145
13191
  import * as path5 from "node:path";
13192
+ import { createRequest, sendResponse } from "@mjackson/node-fetch-server";
13146
13193
  import getPort, { portNumbers } from "get-port";
13147
- import { Request as MiniflareRequest } from "miniflare";
13148
- import "vite";
13194
+ import {
13195
+ Request as MiniflareRequest,
13196
+ Response as MiniflareResponse
13197
+ } from "miniflare";
13149
13198
  function getOutputDirectory(userConfig, environmentName) {
13150
13199
  const rootOutputDirectory = userConfig.build?.outDir ?? "dist";
13151
13200
  return userConfig.environments?.[environmentName]?.build?.outDir ?? path5.join(rootOutputDirectory, environmentName);
13152
13201
  }
13202
+ var postfixRE = /[?#].*$/;
13203
+ function cleanUrl(url) {
13204
+ return url.replace(postfixRE, "");
13205
+ }
13206
+ function getFirstAvailablePort(start) {
13207
+ return getPort({ port: portNumbers(start, 65535) });
13208
+ }
13209
+ function withTrailingSlash2(path11) {
13210
+ return path11.endsWith("/") ? path11 : `${path11}/`;
13211
+ }
13212
+ function createRequestHandler(handler) {
13213
+ return async (req, res, next) => {
13214
+ try {
13215
+ const request = createRequest(req, res);
13216
+ let response = await handler(toMiniflareRequest(request), req);
13217
+ if (req.httpVersionMajor === 2) {
13218
+ response = new MiniflareResponse(response.body, response);
13219
+ response.headers.delete("transfer-encoding");
13220
+ }
13221
+ await sendResponse(res, response);
13222
+ } catch (error) {
13223
+ next(error);
13224
+ }
13225
+ };
13226
+ }
13153
13227
  function toMiniflareRequest(request) {
13154
13228
  const host = request.headers.get("Host");
13155
13229
  if (host) {
@@ -13166,13 +13240,6 @@ function toMiniflareRequest(request) {
13166
13240
  duplex: "half"
13167
13241
  });
13168
13242
  }
13169
- var postfixRE = /[?#].*$/;
13170
- function cleanUrl(url) {
13171
- return url.replace(postfixRE, "");
13172
- }
13173
- function getFirstAvailablePort(start) {
13174
- return getPort({ port: portNumbers(start, 65535) });
13175
- }
13176
13243
 
13177
13244
  // src/cloudflare-environment.ts
13178
13245
  var webSocketUndefinedError = "The WebSocket is undefined";
@@ -13218,7 +13285,7 @@ function createHotChannel(webSocketContainer) {
13218
13285
  }
13219
13286
  };
13220
13287
  }
13221
- var CloudflareDevEnvironment = class extends vite3.DevEnvironment {
13288
+ var CloudflareDevEnvironment = class extends vite2.DevEnvironment {
13222
13289
  #webSocketContainer;
13223
13290
  #worker;
13224
13291
  constructor(name, config) {
@@ -13279,7 +13346,7 @@ function createCloudflareEnvironmentOptions(workerConfig, userConfig, environmen
13279
13346
  },
13280
13347
  build: {
13281
13348
  createEnvironment(name, config) {
13282
- return new vite3.BuildEnvironment(name, config);
13349
+ return new vite2.BuildEnvironment(name, config);
13283
13350
  },
13284
13351
  target,
13285
13352
  emitAssets: true,
@@ -13477,14 +13544,13 @@ import {
13477
13544
  kCurrentWorker,
13478
13545
  Log,
13479
13546
  LogLevel,
13480
- Response as MiniflareResponse
13547
+ Response as MiniflareResponse2
13481
13548
  } from "miniflare";
13482
13549
  import colors3 from "picocolors";
13483
13550
  import { globSync } from "tinyglobby";
13484
13551
  import "vite";
13485
13552
  import {
13486
- experimental_pickRemoteBindings,
13487
- experimental_startMixedModeSession,
13553
+ experimental_maybeStartOrUpdateMixedModeSession,
13488
13554
  unstable_convertConfigBindingsToStartWorkerBindings,
13489
13555
  unstable_getMiniflareWorkerOptions
13490
13556
  } from "wrangler";
@@ -13512,8 +13578,9 @@ function getWorkerToWorkerEntrypointNamesMap(workers) {
13512
13578
  if (typeof value === "object" && "name" in value && value.entrypoint !== void 0 && value.entrypoint !== "default") {
13513
13579
  const targetWorkerName = value.name === kCurrentWorker ? worker.name : value.name;
13514
13580
  const entrypointNames = workerToWorkerEntrypointNamesMap.get(targetWorkerName);
13515
- assert7(entrypointNames, missingWorkerErrorMessage(targetWorkerName));
13516
- entrypointNames.add(value.entrypoint);
13581
+ if (entrypointNames) {
13582
+ entrypointNames.add(value.entrypoint);
13583
+ }
13517
13584
  }
13518
13585
  }
13519
13586
  }
@@ -13604,6 +13671,7 @@ function logUnknownTails(tails, userWorkers, log) {
13604
13671
  }
13605
13672
  }
13606
13673
  }
13674
+ var mixedModeSessionsDataMap = /* @__PURE__ */ new Map();
13607
13675
  async function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer, inspectorPort) {
13608
13676
  const resolvedViteConfig = viteDevServer.config;
13609
13677
  const entryWorkerConfig = getEntryWorkerConfig(resolvedPluginConfig);
@@ -13653,26 +13721,44 @@ async function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer, inspe
13653
13721
  CONFIG: assetsConfig
13654
13722
  },
13655
13723
  serviceBindings: {
13656
- __VITE_ASSET_EXISTS__: async (request) => {
13724
+ __VITE_HTML_EXISTS__: async (request) => {
13657
13725
  const { pathname } = new URL(request.url);
13658
- let exists = false;
13659
13726
  if (pathname.endsWith(".html")) {
13660
- try {
13661
- const filePath = path7.join(resolvedViteConfig.root, pathname);
13662
- const stats = await fsp.stat(filePath);
13663
- exists = stats.isFile();
13664
- } catch (error) {
13727
+ const { root, publicDir } = resolvedViteConfig;
13728
+ const publicDirInRoot = publicDir.startsWith(
13729
+ withTrailingSlash2(root)
13730
+ );
13731
+ const publicPath = withTrailingSlash2(publicDir.slice(root.length));
13732
+ if (publicDirInRoot && pathname.startsWith(publicPath)) {
13733
+ return MiniflareResponse2.json(null);
13734
+ }
13735
+ const publicDirFilePath = path7.join(publicDir, pathname);
13736
+ const rootDirFilePath = path7.join(root, pathname);
13737
+ for (const resolvedPath of [publicDirFilePath, rootDirFilePath]) {
13738
+ try {
13739
+ const stats = await fsp.stat(resolvedPath);
13740
+ if (stats.isFile()) {
13741
+ return MiniflareResponse2.json(
13742
+ resolvedPath === publicDirFilePath ? `${PUBLIC_DIR_PREFIX}${pathname}` : pathname
13743
+ );
13744
+ }
13745
+ } catch (error) {
13746
+ }
13665
13747
  }
13666
13748
  }
13667
- return MiniflareResponse.json(exists);
13749
+ return MiniflareResponse2.json(null);
13668
13750
  },
13669
- __VITE_FETCH_ASSET__: async (request) => {
13751
+ __VITE_FETCH_HTML__: async (request) => {
13670
13752
  const { pathname } = new URL(request.url);
13671
- const filePath = path7.join(resolvedViteConfig.root, pathname);
13753
+ const { root, publicDir } = resolvedViteConfig;
13754
+ const isInPublicDir = pathname.startsWith(PUBLIC_DIR_PREFIX);
13755
+ const resolvedPath = isInPublicDir ? path7.join(publicDir, pathname.slice(PUBLIC_DIR_PREFIX.length)) : path7.join(root, pathname);
13672
13756
  try {
13673
- let html = await fsp.readFile(filePath, "utf-8");
13674
- html = await viteDevServer.transformIndexHtml(pathname, html);
13675
- return new MiniflareResponse(html, {
13757
+ let html = await fsp.readFile(resolvedPath, "utf-8");
13758
+ if (!isInPublicDir) {
13759
+ html = await viteDevServer.transformIndexHtml(resolvedPath, html);
13760
+ }
13761
+ return new MiniflareResponse2(html, {
13676
13762
  headers: { "Content-Type": "text/html" }
13677
13763
  });
13678
13764
  } catch (error) {
@@ -13685,7 +13771,23 @@ async function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer, inspe
13685
13771
  const workersFromConfig = resolvedPluginConfig.type === "workers" ? await Promise.all(
13686
13772
  Object.entries(resolvedPluginConfig.workers).map(
13687
13773
  async ([environmentName, workerConfig]) => {
13688
- const mixedModeSession = resolvedPluginConfig.experimental.mixedMode ? await maybeStartOrUpdateMixedModeSession(workerConfig) : void 0;
13774
+ const bindings = unstable_convertConfigBindingsToStartWorkerBindings(
13775
+ workerConfig
13776
+ );
13777
+ const preExistingMixedModeSession = workerConfig.configPath ? mixedModeSessionsDataMap.get(workerConfig.configPath) : void 0;
13778
+ const mixedModeSessionData = resolvedPluginConfig.experimental.mixedMode ? await experimental_maybeStartOrUpdateMixedModeSession(
13779
+ {
13780
+ name: workerConfig.name,
13781
+ bindings: bindings ?? {}
13782
+ },
13783
+ preExistingMixedModeSession ?? null
13784
+ ) : void 0;
13785
+ if (workerConfig.configPath && mixedModeSessionData) {
13786
+ mixedModeSessionsDataMap.set(
13787
+ workerConfig.configPath,
13788
+ mixedModeSessionData
13789
+ );
13790
+ }
13689
13791
  const miniflareWorkerOptions = unstable_getMiniflareWorkerOptions(
13690
13792
  {
13691
13793
  ...workerConfig,
@@ -13693,7 +13795,7 @@ async function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer, inspe
13693
13795
  },
13694
13796
  resolvedPluginConfig.cloudflareEnv,
13695
13797
  {
13696
- mixedModeConnectionString: mixedModeSession?.mixedModeConnectionString,
13798
+ mixedModeConnectionString: mixedModeSessionData?.session?.mixedModeConnectionString,
13697
13799
  mixedModeEnabled: resolvedPluginConfig.experimental.mixedMode
13698
13800
  }
13699
13801
  );
@@ -13734,11 +13836,11 @@ async function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer, inspe
13734
13836
  externalize: moduleId,
13735
13837
  type: "module"
13736
13838
  };
13737
- return MiniflareResponse.json({ result: result2 });
13839
+ return MiniflareResponse2.json({ result: result2 });
13738
13840
  }
13739
13841
  const devEnvironment = viteDevServer.environments[environmentName];
13740
13842
  const result = await devEnvironment.hot.handleInvoke(payload);
13741
- return MiniflareResponse.json(result);
13843
+ return MiniflareResponse2.json(result);
13742
13844
  }
13743
13845
  }
13744
13846
  }
@@ -13866,16 +13968,16 @@ async function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer, inspe
13866
13968
  }
13867
13969
  switch (moduleType) {
13868
13970
  case "CompiledWasm": {
13869
- return MiniflareResponse.json({ wasm: Array.from(contents) });
13971
+ return MiniflareResponse2.json({ wasm: Array.from(contents) });
13870
13972
  }
13871
13973
  case "Data": {
13872
- return MiniflareResponse.json({ data: Array.from(contents) });
13974
+ return MiniflareResponse2.json({ data: Array.from(contents) });
13873
13975
  }
13874
13976
  case "Text": {
13875
- return MiniflareResponse.json({ text: contents.toString() });
13977
+ return MiniflareResponse2.json({ text: contents.toString() });
13876
13978
  }
13877
13979
  default: {
13878
- return MiniflareResponse.error();
13980
+ return MiniflareResponse2.error();
13879
13981
  }
13880
13982
  }
13881
13983
  }
@@ -13905,12 +14007,26 @@ async function getPreviewMiniflareOptions(vitePreviewServer, workerConfigs, pers
13905
14007
  const resolvedViteConfig = vitePreviewServer.config;
13906
14008
  const workers = (await Promise.all(
13907
14009
  workerConfigs.map(async (workerConfig, i) => {
13908
- const mixedModeSession = mixedModeEnabled ? await maybeStartOrUpdateMixedModeSession(workerConfig) : void 0;
14010
+ const bindings = unstable_convertConfigBindingsToStartWorkerBindings(workerConfig);
14011
+ const preExistingMixedModeSessionData = workerConfig.configPath ? mixedModeSessionsDataMap.get(workerConfig.configPath) : void 0;
14012
+ const mixedModeSessionData = mixedModeEnabled ? await experimental_maybeStartOrUpdateMixedModeSession(
14013
+ {
14014
+ name: workerConfig.name,
14015
+ bindings: bindings ?? {}
14016
+ },
14017
+ preExistingMixedModeSessionData ?? null
14018
+ ) : void 0;
14019
+ if (workerConfig.configPath && mixedModeSessionData) {
14020
+ mixedModeSessionsDataMap.set(
14021
+ workerConfig.configPath,
14022
+ mixedModeSessionData
14023
+ );
14024
+ }
13909
14025
  const miniflareWorkerOptions = unstable_getMiniflareWorkerOptions(
13910
14026
  workerConfig,
13911
14027
  void 0,
13912
14028
  {
13913
- mixedModeConnectionString: mixedModeSession?.mixedModeConnectionString,
14029
+ mixedModeConnectionString: mixedModeSessionData?.session?.mixedModeConnectionString,
13914
14030
  mixedModeEnabled
13915
14031
  }
13916
14032
  );
@@ -13988,34 +14104,89 @@ function miniflareLogLevelFromViteLogLevel(level = "info") {
13988
14104
  return LogLevel.NONE;
13989
14105
  }
13990
14106
  }
13991
- var mixedModeSessionsMap = /* @__PURE__ */ new Map();
13992
- async function maybeStartOrUpdateMixedModeSession(workerConfig) {
13993
- const workerRemoteBindings = experimental_pickRemoteBindings(
13994
- unstable_convertConfigBindingsToStartWorkerBindings(workerConfig) ?? {}
13995
- );
13996
- assert7(workerConfig.name, "Found workerConfig without a name");
13997
- let mixedModeSession = mixedModeSessionsMap.get(workerConfig.name);
13998
- if (mixedModeSession === void 0) {
13999
- if (Object.keys(workerRemoteBindings).length > 0) {
14000
- mixedModeSession = await experimental_startMixedModeSession(
14001
- workerRemoteBindings,
14002
- {
14003
- workerName: workerConfig.name
14004
- }
14107
+
14108
+ // src/plugin-config.ts
14109
+ import assert9 from "node:assert";
14110
+ import * as path9 from "node:path";
14111
+
14112
+ // ../workers-shared/utils/configuration/parseStaticRouting.ts
14113
+ function parseStaticRouting(input) {
14114
+ if (input.length === 0) {
14115
+ throw new Error(
14116
+ "No `run_worker_first` rules were provided; must provide at least 1 rule."
14117
+ );
14118
+ }
14119
+ if (input.length > MAX_ROUTES_RULES) {
14120
+ throw new Error(
14121
+ `Too many \`run_worker_first\` rules were provided; ${input.length} rules provided exceeds max of ${MAX_ROUTES_RULES}.`
14122
+ );
14123
+ }
14124
+ const rawAssetWorkerRules = [];
14125
+ const assetWorkerRules = [];
14126
+ const userWorkerRules = [];
14127
+ const invalidRules = [];
14128
+ for (const rule of input) {
14129
+ if (rule.startsWith("!/")) {
14130
+ assetWorkerRules.push(rule.slice(1));
14131
+ rawAssetWorkerRules.push(rule);
14132
+ } else if (rule.startsWith("/")) {
14133
+ userWorkerRules.push(rule);
14134
+ } else if (rule.startsWith("!")) {
14135
+ invalidRules.push(`'${rule}': negative rules must start with '!/'`);
14136
+ } else {
14137
+ invalidRules.push(`'${rule}': rules must start with '/' or '!/'`);
14138
+ }
14139
+ }
14140
+ if (assetWorkerRules.length > 0 && userWorkerRules.length === 0) {
14141
+ throw new Error(
14142
+ "Only negative `run_worker_first` rules were provided; must provide at least 1 non-negative rule"
14143
+ );
14144
+ }
14145
+ const invalidAssetWorkerRules = validateStaticRoutingRules(rawAssetWorkerRules);
14146
+ const invalidUserWorkerRules = validateStaticRoutingRules(userWorkerRules);
14147
+ const errorMessage = formatInvalidRoutes([
14148
+ ...invalidRules,
14149
+ ...invalidUserWorkerRules,
14150
+ ...invalidAssetWorkerRules
14151
+ ]);
14152
+ if (errorMessage) {
14153
+ throw new Error(errorMessage);
14154
+ }
14155
+ return { asset_worker: assetWorkerRules, user_worker: userWorkerRules };
14156
+ }
14157
+ function validateStaticRoutingRules(rules) {
14158
+ const invalid = [];
14159
+ const seen = /* @__PURE__ */ new Set();
14160
+ for (const rule of rules) {
14161
+ if (rule.length > MAX_ROUTES_RULE_LENGTH) {
14162
+ invalid.push(
14163
+ `'${rule}': all rules must be less than ${MAX_ROUTES_RULE_LENGTH} characters in length`
14005
14164
  );
14006
- mixedModeSessionsMap.set(workerConfig.name, mixedModeSession);
14007
14165
  }
14008
- } else {
14009
- await mixedModeSession.updateBindings(workerRemoteBindings);
14166
+ if (seen.has(rule)) {
14167
+ invalid.push(`'${rule}': rule is a duplicate; rules must be unique`);
14168
+ }
14169
+ if (rule.endsWith("*")) {
14170
+ for (const otherRule of rules) {
14171
+ if (otherRule !== rule && otherRule.startsWith(rule.slice(0, -1))) {
14172
+ invalid.push(`'${otherRule}': rule '${rule}' makes it redundant`);
14173
+ }
14174
+ }
14175
+ }
14176
+ seen.add(rule);
14010
14177
  }
14011
- await mixedModeSession?.ready;
14012
- return mixedModeSession;
14178
+ return invalid;
14013
14179
  }
14180
+ var formatInvalidRoutes = (invalidRules) => {
14181
+ if (invalidRules.length === 0) {
14182
+ return void 0;
14183
+ }
14184
+ return `Invalid routes in \`run_worker_first\`:
14185
+ ` + invalidRules.join("\n");
14186
+ };
14014
14187
 
14015
14188
  // src/plugin-config.ts
14016
- import assert9 from "node:assert";
14017
- import * as path9 from "node:path";
14018
- import * as vite6 from "vite";
14189
+ import * as vite5 from "vite";
14019
14190
 
14020
14191
  // src/workers-configs.ts
14021
14192
  import assert8 from "node:assert";
@@ -14288,7 +14459,7 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
14288
14459
  const persistState = pluginConfig.persistState ?? true;
14289
14460
  const experimental = pluginConfig.experimental ?? {};
14290
14461
  const root = userConfig.root ? path9.resolve(userConfig.root) : process.cwd();
14291
- const { CLOUDFLARE_ENV: cloudflareEnv } = vite6.loadEnv(
14462
+ const { CLOUDFLARE_ENV: cloudflareEnv } = vite5.loadEnv(
14292
14463
  viteEnv.mode,
14293
14464
  root,
14294
14465
  /* prefixes */
@@ -14322,6 +14493,12 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
14322
14493
  }
14323
14494
  const entryWorkerConfig = entryWorkerResolvedConfig.config;
14324
14495
  const entryWorkerEnvironmentName = pluginConfig.viteEnvironment?.name ?? workerNameToEnvironmentName(entryWorkerConfig.topLevelName);
14496
+ let staticRouting;
14497
+ if (Array.isArray(entryWorkerConfig.assets?.run_worker_first)) {
14498
+ staticRouting = parseStaticRouting(
14499
+ entryWorkerConfig.assets.run_worker_first
14500
+ );
14501
+ }
14325
14502
  const workers = {
14326
14503
  [entryWorkerEnvironmentName]: entryWorkerConfig
14327
14504
  };
@@ -14360,6 +14537,7 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
14360
14537
  persistState,
14361
14538
  workers,
14362
14539
  entryWorkerEnvironmentName,
14540
+ staticRouting,
14363
14541
  rawConfigs: {
14364
14542
  entryWorker: entryWorkerResolvedConfig,
14365
14543
  auxiliaryWorkers: auxiliaryWorkersResolvedConfigs
@@ -14648,40 +14826,78 @@ function cloudflare2(pluginConfig = {}) {
14648
14826
  await miniflare.setOptions(miniflareDevOptions);
14649
14827
  }
14650
14828
  await initRunners(resolvedPluginConfig, viteDevServer, miniflare);
14651
- if (viteDevServer.httpServer) {
14652
- handleWebSocket(viteDevServer.httpServer, async () => {
14653
- assert11(miniflare, `Miniflare not defined`);
14654
- const routerWorker = await miniflare.getWorker(ROUTER_WORKER_NAME);
14655
- return routerWorker.fetch;
14656
- });
14829
+ let preMiddleware;
14830
+ if (resolvedPluginConfig.type === "workers") {
14831
+ const entryWorkerConfig = getWorkerConfig2(
14832
+ resolvedPluginConfig.entryWorkerEnvironmentName
14833
+ );
14834
+ assert11(entryWorkerConfig, `No entry Worker config`);
14835
+ const entryWorkerName = entryWorkerConfig.name;
14836
+ if (viteDevServer.httpServer) {
14837
+ handleWebSocket(viteDevServer.httpServer, async () => {
14838
+ assert11(miniflare, `Miniflare not defined`);
14839
+ const entryWorker = await miniflare.getWorker(entryWorkerName);
14840
+ return entryWorker.fetch;
14841
+ });
14842
+ }
14843
+ const staticRouting = entryWorkerConfig.assets?.run_worker_first === true ? { user_worker: ["/*"] } : resolvedPluginConfig.staticRouting;
14844
+ if (staticRouting) {
14845
+ const excludeRulesMatcher = generateStaticRoutingRuleMatcher(
14846
+ staticRouting.asset_worker ?? []
14847
+ );
14848
+ const includeRulesMatcher = generateStaticRoutingRuleMatcher(
14849
+ staticRouting.user_worker
14850
+ );
14851
+ const userWorkerHandler = createRequestHandler(async (request) => {
14852
+ assert11(miniflare, `Miniflare not defined`);
14853
+ const userWorker = await miniflare.getWorker(entryWorkerName);
14854
+ return userWorker.fetch(request, { redirect: "manual" });
14855
+ });
14856
+ preMiddleware = async (req, res, next) => {
14857
+ assert11(req.url, `req.url not defined`);
14858
+ const request = new Request(new URL(req.url, UNKNOWN_HOST));
14859
+ if (req[kRequestType] === "asset") {
14860
+ next();
14861
+ } else if (excludeRulesMatcher({ request })) {
14862
+ req[kRequestType] === "asset";
14863
+ next();
14864
+ } else if (includeRulesMatcher({ request })) {
14865
+ userWorkerHandler(req, res, next);
14866
+ } else {
14867
+ next();
14868
+ }
14869
+ };
14870
+ }
14657
14871
  }
14658
14872
  return () => {
14659
- viteDevServer.middlewares.use(async (req, res, next) => {
14660
- try {
14873
+ if (preMiddleware) {
14874
+ const middlewareStack = viteDevServer.middlewares.stack;
14875
+ const cachedTransformMiddlewareIndex = middlewareStack.findIndex(
14876
+ (middleware) => "name" in middleware.handle && middleware.handle.name === "viteCachedTransformMiddleware"
14877
+ );
14878
+ assert11(
14879
+ cachedTransformMiddlewareIndex !== -1,
14880
+ "Failed to find viteCachedTransformMiddleware"
14881
+ );
14882
+ middlewareStack.splice(cachedTransformMiddlewareIndex, 0, {
14883
+ route: "",
14884
+ handle: preMiddleware
14885
+ });
14886
+ }
14887
+ viteDevServer.middlewares.use(
14888
+ createRequestHandler(async (request, req) => {
14661
14889
  assert11(miniflare, `Miniflare not defined`);
14662
- const request = createRequest(req, res);
14663
- let response;
14664
14890
  if (req[kRequestType] === "asset") {
14665
14891
  const assetWorker = await miniflare.getWorker(ASSET_WORKER_NAME);
14666
- response = await assetWorker.fetch(
14667
- toMiniflareRequest(request),
14668
- { redirect: "manual" }
14669
- );
14892
+ return assetWorker.fetch(request, { redirect: "manual" });
14670
14893
  } else {
14671
14894
  const routerWorker = await miniflare.getWorker(ROUTER_WORKER_NAME);
14672
- response = await routerWorker.fetch(
14673
- toMiniflareRequest(request),
14674
- { redirect: "manual" }
14675
- );
14676
- }
14677
- if (req.httpVersionMajor === 2) {
14678
- response.headers.delete("transfer-encoding");
14895
+ return routerWorker.fetch(request, {
14896
+ redirect: "manual"
14897
+ });
14679
14898
  }
14680
- await sendResponse(res, response);
14681
- } catch (error) {
14682
- next(error);
14683
- }
14684
- });
14899
+ })
14900
+ );
14685
14901
  };
14686
14902
  },
14687
14903
  async configurePreviewServer(vitePreviewServer) {
@@ -14706,21 +14922,11 @@ function cloudflare2(pluginConfig = {}) {
14706
14922
  vitePreviewServer.httpServer,
14707
14923
  () => miniflare2.dispatchFetch
14708
14924
  );
14709
- vitePreviewServer.middlewares.use(async (req, res, next) => {
14710
- try {
14711
- const request = createRequest(req, res);
14712
- const response = await miniflare2.dispatchFetch(
14713
- toMiniflareRequest(request),
14714
- { redirect: "manual" }
14715
- );
14716
- if (req.httpVersionMajor === 2) {
14717
- response.headers.delete("transfer-encoding");
14718
- }
14719
- await sendResponse(res, response);
14720
- } catch (error) {
14721
- next(error);
14722
- }
14723
- });
14925
+ vitePreviewServer.middlewares.use(
14926
+ createRequestHandler((request) => {
14927
+ return miniflare2.dispatchFetch(request, { redirect: "manual" });
14928
+ })
14929
+ );
14724
14930
  }
14725
14931
  },
14726
14932
  // Plugin to provide a fallback entry file
@@ -14815,7 +15021,7 @@ function cloudflare2(pluginConfig = {}) {
14815
15021
  source
14816
15022
  });
14817
15023
  const emittedFileName = this.getFileName(referenceId);
14818
- const relativePath = vite7.normalizePath(
15024
+ const relativePath = vite6.normalizePath(
14819
15025
  path10.relative(path10.dirname(chunk.fileName), emittedFileName)
14820
15026
  );
14821
15027
  const importPath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
@@ -14876,6 +15082,9 @@ function cloudflare2(pluginConfig = {}) {
14876
15082
  // rather than allowing the resolve hook here to alias then to polyfills.
14877
15083
  enforce: "pre",
14878
15084
  async resolveId(source, importer, options) {
15085
+ if (isGlobalVirtualModule(source)) {
15086
+ return source;
15087
+ }
14879
15088
  const result = resolveNodeJSImport(source);
14880
15089
  if (!result) {
14881
15090
  return this.resolve(source, importer, options);
@@ -14893,6 +15102,9 @@ function cloudflare2(pluginConfig = {}) {
14893
15102
  }
14894
15103
  return this.resolve(result.resolved, importer, options);
14895
15104
  },
15105
+ load(id) {
15106
+ return getGlobalVirtualModule(id);
15107
+ },
14896
15108
  async transform(code, id) {
14897
15109
  const workerConfig = getWorkerConfig2(this.environment.name);
14898
15110
  if (!workerConfig) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudflare/vite-plugin",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "Cloudflare plugin for Vite",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -33,7 +33,7 @@
33
33
  "dist"
34
34
  ],
35
35
  "dependencies": {
36
- "@cloudflare/unenv-preset": "2.3.2",
36
+ "@cloudflare/unenv-preset": "2.3.3",
37
37
  "@mjackson/node-fetch-server": "^0.6.1",
38
38
  "@rollup/plugin-replace": "^6.0.1",
39
39
  "get-port": "^7.1.0",
@@ -41,11 +41,11 @@
41
41
  "tinyglobby": "^0.2.12",
42
42
  "unenv": "2.0.0-rc.17",
43
43
  "ws": "8.18.0",
44
- "miniflare": "4.20250604.1",
45
- "wrangler": "4.20.0"
44
+ "miniflare": "4.20250612.0",
45
+ "wrangler": "4.20.1"
46
46
  },
47
47
  "devDependencies": {
48
- "@cloudflare/workers-types": "^4.20250604.0",
48
+ "@cloudflare/workers-types": "^4.20250612.0",
49
49
  "@types/node": "^22.10.1",
50
50
  "@types/ws": "^8.5.13",
51
51
  "magic-string": "^0.30.12",
@@ -54,9 +54,9 @@
54
54
  "typescript": "^5.7.2",
55
55
  "vite": "^6.1.0",
56
56
  "vitest": "~3.2.0",
57
+ "@cloudflare/mock-npm-registry": "0.0.0",
57
58
  "@cloudflare/workers-shared": "0.17.6",
58
- "@cloudflare/workers-tsconfig": "0.0.0",
59
- "@cloudflare/mock-npm-registry": "0.0.0"
59
+ "@cloudflare/workers-tsconfig": "0.0.0"
60
60
  },
61
61
  "peerDependencies": {
62
62
  "vite": "^6.1.0",