@cloudflare/vite-plugin 0.0.0-8bef7ea1e → 0.0.0-8e6ede5ca

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.js CHANGED
@@ -1,18 +1,8 @@
1
1
  // src/index.ts
2
- import assert7 from "node:assert";
2
+ import assert8 from "node:assert";
3
3
  import * as fs4 from "node:fs";
4
4
  import * as path6 from "node:path";
5
5
  import { createMiddleware } from "@hattip/adapter-node";
6
- import { Miniflare } from "miniflare";
7
- import "vite";
8
-
9
- // src/cloudflare-environment.ts
10
- import assert from "node:assert";
11
- import { builtinModules } from "node:module";
12
- import * as vite2 from "vite";
13
-
14
- // src/node-js-compat.ts
15
- import { createRequire } from "node:module";
16
6
 
17
7
  // ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.5.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
18
8
  var comma = ",".charCodeAt(0);
@@ -1078,100 +1068,25 @@ var MagicString = class _MagicString {
1078
1068
  }
1079
1069
  };
1080
1070
 
1081
- // src/node-js-compat.ts
1082
- import { getNodeCompat } from "miniflare";
1083
- import * as unenv from "unenv";
1084
- var require2 = createRequire(import.meta.url);
1085
- var preset = unenv.env(unenv.nodeless, unenv.cloudflare);
1086
- var CLOUDFLARE_VIRTUAL_PREFIX = "\0cloudflare-";
1087
- function isNodeCompat({
1088
- compatibility_date,
1089
- compatibility_flags
1090
- }) {
1091
- const nodeCompatMode = getNodeCompat(
1092
- compatibility_date,
1093
- compatibility_flags ?? []
1094
- ).mode;
1095
- if (nodeCompatMode === "v2") {
1096
- return true;
1097
- }
1098
- if (nodeCompatMode === "legacy") {
1099
- throw new Error(
1100
- "Unsupported Node.js compat mode (legacy). Remove the `node_compat` setting and add the `nodejs_compat` flag instead."
1101
- );
1102
- }
1103
- if (nodeCompatMode === "v1") {
1104
- throw new Error(
1105
- `Unsupported Node.js compat mode (v1). Only the v2 mode is supported, either change your compat date to "2024-09-23" or later, or set the "nodejs_compat_v2" compatibility flag`
1106
- );
1107
- }
1108
- return false;
1109
- }
1110
- function injectGlobalCode(id, code, workerConfig) {
1111
- if (!isNodeCompat(workerConfig)) {
1112
- return;
1113
- }
1114
- const injectedCode = Object.entries(preset.inject).map(([globalName, globalInject]) => {
1115
- if (typeof globalInject === "string") {
1116
- const moduleSpecifier2 = globalInject;
1117
- return `import var_${globalName} from "${moduleSpecifier2}";
1118
- globalThis.${globalName} = var_${globalName};
1119
- `;
1120
- }
1121
- const [moduleSpecifier, exportName] = globalInject;
1122
- return `import var_${globalName} from "${moduleSpecifier}";
1123
- globalThis.${globalName} = var_${globalName}.${exportName};
1124
- `;
1125
- }).join("\n");
1126
- const modified = new MagicString(code);
1127
- modified.prepend(injectedCode);
1128
- return {
1129
- code: modified.toString(),
1130
- map: modified.generateMap({ hires: "boundary", source: id })
1131
- };
1132
- }
1133
- function getNodeCompatAliases() {
1134
- const aliases = {};
1135
- Object.keys(preset.alias).forEach((key) => {
1136
- if (!preset.external.includes(key)) {
1137
- aliases[key] = CLOUDFLARE_VIRTUAL_PREFIX + key;
1138
- }
1139
- });
1140
- return aliases;
1141
- }
1142
- function resolveNodeCompatId(environment, workerConfig, id) {
1143
- const aliased = resolveNodeAliases(id, workerConfig) ?? id;
1144
- if (aliased.startsWith("unenv/")) {
1145
- const resolvedDep = require2.resolve(aliased).replace(/\.cjs$/, ".mjs");
1146
- if (environment.mode === "dev" && environment.depsOptimizer) {
1147
- const dep = environment.depsOptimizer.registerMissingImport(
1148
- aliased,
1149
- resolvedDep
1150
- );
1151
- return dep.id;
1152
- } else {
1153
- return resolvedDep;
1154
- }
1155
- }
1156
- }
1157
- function getNodeCompatExternals() {
1158
- return preset.external;
1159
- }
1160
- function resolveNodeAliases(source, workerConfig) {
1161
- if (!source.startsWith(CLOUDFLARE_VIRTUAL_PREFIX) || !isNodeCompat(workerConfig)) {
1162
- return;
1163
- }
1164
- const from = source.slice(CLOUDFLARE_VIRTUAL_PREFIX.length);
1165
- const alias = preset.alias[from];
1166
- if (alias && preset.external.includes(alias)) {
1167
- throw new Error(`Alias to external: ${source} -> ${alias}`);
1168
- }
1169
- return alias;
1170
- }
1071
+ // src/index.ts
1072
+ import { Miniflare } from "miniflare";
1073
+ import * as vite6 from "vite";
1074
+
1075
+ // src/cloudflare-environment.ts
1076
+ import assert from "node:assert";
1077
+ import { builtinModules } from "node:module";
1078
+ import * as vite2 from "vite";
1079
+
1080
+ // src/constants.ts
1081
+ var ROUTER_WORKER_NAME = "__router-worker__";
1082
+ var ASSET_WORKER_NAME = "__asset-worker__";
1083
+ var ASSET_WORKERS_COMPATIBILITY_DATE = "2024-10-04";
1084
+ var MODULE_TYPES = ["CompiledWasm"];
1171
1085
 
1172
1086
  // src/shared.ts
1173
1087
  var UNKNOWN_HOST = "http://localhost";
1174
1088
  var INIT_PATH = "/__vite_plugin_cloudflare_init__";
1089
+ var MODULE_PATTERN = `__CLOUDFLARE_MODULE__(${MODULE_TYPES.join("|")})__(.*?)__`;
1175
1090
 
1176
1091
  // src/utils.ts
1177
1092
  import * as path from "node:path";
@@ -1284,6 +1199,7 @@ var cloudflareBuiltInModules = [
1284
1199
  "cloudflare:workers",
1285
1200
  "cloudflare:workflows"
1286
1201
  ];
1202
+ var defaultConditions = ["workerd", "module", "browser"];
1287
1203
  function createCloudflareEnvironmentOptions(workerConfig, userConfig, environmentName) {
1288
1204
  return {
1289
1205
  resolve: {
@@ -1291,7 +1207,7 @@ function createCloudflareEnvironmentOptions(workerConfig, userConfig, environmen
1291
1207
  // dependencies as not external
1292
1208
  noExternal: true,
1293
1209
  // We want to use `workerd` package exports if available (e.g. for postgres).
1294
- conditions: ["workerd", "module", "browser", "development|production"]
1210
+ conditions: [...defaultConditions, "development|production"]
1295
1211
  },
1296
1212
  dev: {
1297
1213
  createEnvironment(name2, config) {
@@ -1302,7 +1218,11 @@ function createCloudflareEnvironmentOptions(workerConfig, userConfig, environmen
1302
1218
  createEnvironment(name2, config) {
1303
1219
  return new vite2.BuildEnvironment(name2, config);
1304
1220
  },
1221
+ target: "es2022",
1222
+ // We need to enable `emitAssets` in order to support additional modules defined by `rules`
1223
+ emitAssets: true,
1305
1224
  outDir: getOutputDirectory(userConfig, environmentName),
1225
+ copyPublicDir: false,
1306
1226
  ssr: true,
1307
1227
  rollupOptions: {
1308
1228
  // Note: vite starts dev pre-bundling crawling from either optimizeDeps.entries or rollupOptions.input
@@ -1310,12 +1230,13 @@ function createCloudflareEnvironmentOptions(workerConfig, userConfig, environmen
1310
1230
  // dev pre-bundling crawling (were we not to set this input field we'd have to appropriately set
1311
1231
  // optimizeDeps.entries in the dev config)
1312
1232
  input: workerConfig.main,
1313
- external: [...cloudflareBuiltInModules, ...getNodeCompatExternals()]
1233
+ external: [...cloudflareBuiltInModules]
1314
1234
  }
1315
1235
  },
1316
1236
  optimizeDeps: {
1317
1237
  // Note: ssr pre-bundling is opt-in and we need to enable it by setting `noDiscovery` to false
1318
1238
  noDiscovery: false,
1239
+ entries: workerConfig.main,
1319
1240
  exclude: [
1320
1241
  ...cloudflareBuiltInModules,
1321
1242
  // we have to exclude all node modules to work in dev-mode not just the unenv externals...
@@ -1323,6 +1244,7 @@ function createCloudflareEnvironmentOptions(workerConfig, userConfig, environmen
1323
1244
  ],
1324
1245
  esbuildOptions: {
1325
1246
  platform: "neutral",
1247
+ conditions: [...defaultConditions, "development"],
1326
1248
  resolveExtensions: [
1327
1249
  ".mjs",
1328
1250
  ".js",
@@ -1400,46 +1322,39 @@ function writeDeployConfig(resolvedPluginConfig, resolvedViteConfig) {
1400
1322
  };
1401
1323
  fs.writeFileSync(deployConfigPath, JSON.stringify(deployConfig));
1402
1324
  } else {
1403
- const workerConfigPaths = Object.fromEntries(
1404
- Object.keys(resolvedPluginConfig.workers).map((environmentName) => {
1405
- const outputDirectory = resolvedViteConfig.environments[environmentName]?.build.outDir;
1406
- assert2(
1407
- outputDirectory,
1408
- `Unexpected error: ${environmentName} environment output directory is undefined`
1409
- );
1410
- return [
1411
- environmentName,
1412
- getRelativePathToWorkerConfig(
1413
- deployConfigDirectory,
1414
- resolvedViteConfig.root,
1415
- outputDirectory
1416
- )
1417
- ];
1418
- })
1419
- );
1420
- const { entryWorkerEnvironmentName } = resolvedPluginConfig;
1421
- const configPath = workerConfigPaths[entryWorkerEnvironmentName];
1325
+ let entryWorkerConfigPath;
1326
+ const auxiliaryWorkers = [];
1327
+ for (const environmentName of Object.keys(resolvedPluginConfig.workers)) {
1328
+ const outputDirectory = resolvedViteConfig.environments[environmentName]?.build.outDir;
1329
+ assert2(
1330
+ outputDirectory,
1331
+ `Unexpected error: ${environmentName} environment output directory is undefined`
1332
+ );
1333
+ const configPath = getRelativePathToWorkerConfig(
1334
+ deployConfigDirectory,
1335
+ resolvedViteConfig.root,
1336
+ outputDirectory
1337
+ );
1338
+ if (environmentName === resolvedPluginConfig.entryWorkerEnvironmentName) {
1339
+ entryWorkerConfigPath = configPath;
1340
+ } else {
1341
+ auxiliaryWorkers.push({ configPath });
1342
+ }
1343
+ }
1422
1344
  assert2(
1423
- configPath,
1424
- `Unexpected error: ${entryWorkerEnvironmentName} environment output directory is undefined`
1345
+ entryWorkerConfigPath,
1346
+ `Unexpected error: entryWorkerConfigPath is undefined`
1425
1347
  );
1426
- const auxiliaryWorkers = Object.entries(workerConfigPaths).filter(
1427
- ([environmentName]) => environmentName !== entryWorkerEnvironmentName
1428
- ).map(([_, configPath2]) => ({ configPath: configPath2 }));
1429
- const deployConfig = { configPath, auxiliaryWorkers };
1348
+ const deployConfig = {
1349
+ configPath: entryWorkerConfigPath,
1350
+ auxiliaryWorkers
1351
+ };
1430
1352
  fs.writeFileSync(deployConfigPath, JSON.stringify(deployConfig));
1431
1353
  }
1432
1354
  }
1433
1355
 
1434
1356
  // src/dev.ts
1435
1357
  import assert3 from "node:assert";
1436
-
1437
- // src/constants.ts
1438
- var ROUTER_WORKER_NAME = "__router-worker__";
1439
- var ASSET_WORKER_NAME = "__asset-worker__";
1440
- var ASSET_WORKERS_COMPATIBILITY_DATE = "2024-10-04";
1441
-
1442
- // src/dev.ts
1443
1358
  function getDevEntryWorker(resolvedPluginConfig, miniflare) {
1444
1359
  const entryWorkerConfig = resolvedPluginConfig.type === "assets-only" ? resolvedPluginConfig.config : resolvedPluginConfig.workers[resolvedPluginConfig.entryWorkerEnvironmentName];
1445
1360
  assert3(entryWorkerConfig, "Unexpected error: No entry worker configuration");
@@ -1637,10 +1552,13 @@ function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer) {
1637
1552
  ];
1638
1553
  const userWorkers = resolvedPluginConfig.type === "workers" ? Object.entries(resolvedPluginConfig.workers).map(
1639
1554
  ([environmentName, workerConfig]) => {
1640
- const miniflareWorkerOptions = unstable_getMiniflareWorkerOptions({
1641
- ...workerConfig,
1642
- assets: void 0
1643
- });
1555
+ const miniflareWorkerOptions = unstable_getMiniflareWorkerOptions(
1556
+ {
1557
+ ...workerConfig,
1558
+ assets: void 0
1559
+ },
1560
+ resolvedPluginConfig.cloudflareEnv
1561
+ );
1644
1562
  const { ratelimits, ...workerOptions } = miniflareWorkerOptions.workerOptions;
1645
1563
  return {
1646
1564
  ...workerOptions,
@@ -1666,16 +1584,24 @@ function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer) {
1666
1584
  `Invalid invoke event: ${invokePayloadData.name}`
1667
1585
  );
1668
1586
  const [moduleId] = invokePayloadData.data;
1587
+ const moduleRE = new RegExp(MODULE_PATTERN);
1588
+ if (moduleRE.test(moduleId)) {
1589
+ const result2 = {
1590
+ externalize: moduleId,
1591
+ type: "module"
1592
+ };
1593
+ return MiniflareResponse.json({ result: result2 });
1594
+ }
1669
1595
  if (moduleId.startsWith("cloudflare:")) {
1670
1596
  const result2 = {
1671
1597
  externalize: moduleId,
1672
1598
  type: "builtin"
1673
1599
  };
1674
- return new MiniflareResponse(JSON.stringify({ result: result2 }));
1600
+ return MiniflareResponse.json({ result: result2 });
1675
1601
  }
1676
1602
  const devEnvironment = viteDevServer.environments[environmentName];
1677
1603
  const result = await devEnvironment.hot.handleInvoke(payload);
1678
- return new MiniflareResponse(JSON.stringify(result));
1604
+ return MiniflareResponse.json(result);
1679
1605
  }
1680
1606
  }
1681
1607
  };
@@ -1754,10 +1680,37 @@ function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer) {
1754
1680
  fileURLToPath(new URL(RUNNER_PATH, import.meta.url))
1755
1681
  )
1756
1682
  }
1757
- ]
1683
+ ],
1684
+ unsafeUseModuleFallbackService: true
1758
1685
  };
1759
1686
  })
1760
- ]
1687
+ ],
1688
+ unsafeModuleFallbackService(request) {
1689
+ const url = new URL(request.url);
1690
+ const rawSpecifier = url.searchParams.get("rawSpecifier");
1691
+ assert4(
1692
+ rawSpecifier,
1693
+ `Unexpected error: no specifier in request to module fallback service.`
1694
+ );
1695
+ const moduleRE = new RegExp(MODULE_PATTERN);
1696
+ const match = moduleRE.exec(rawSpecifier);
1697
+ assert4(match, `Unexpected error: no match for module ${rawSpecifier}.`);
1698
+ const [full, moduleType, modulePath] = match;
1699
+ assert4(
1700
+ modulePath,
1701
+ `Unexpected error: module path not found in reference ${full}.`
1702
+ );
1703
+ let source;
1704
+ try {
1705
+ source = fs2.readFileSync(modulePath);
1706
+ } catch (error) {
1707
+ throw new Error(`Import ${modulePath} not found. Does the file exist?`);
1708
+ }
1709
+ return MiniflareResponse.json({
1710
+ // Cap'n Proto expects byte arrays for `:Data` typed fields from JSON
1711
+ wasm: Array.from(source)
1712
+ });
1713
+ }
1761
1714
  };
1762
1715
  }
1763
1716
  function getPreviewMiniflareOptions(vitePreviewServer, persistState) {
@@ -1824,13 +1777,94 @@ function miniflareLogLevelFromViteLogLevel(level = "info") {
1824
1777
  }
1825
1778
  }
1826
1779
 
1780
+ // src/node-js-compat.ts
1781
+ import assert5 from "node:assert";
1782
+ import { cloudflare } from "@cloudflare/unenv-preset";
1783
+ import { getNodeCompat } from "miniflare";
1784
+ import { defineEnv } from "unenv";
1785
+ var { env } = defineEnv({
1786
+ nodeCompat: true,
1787
+ presets: [cloudflare]
1788
+ });
1789
+ var CLOUDFLARE_VIRTUAL_PREFIX = "\0__CLOUDFLARE_NODEJS_COMPAT__";
1790
+ function isNodeCompat(workerConfig) {
1791
+ if (workerConfig === void 0) {
1792
+ return false;
1793
+ }
1794
+ const nodeCompatMode = getNodeCompat(
1795
+ workerConfig.compatibility_date,
1796
+ workerConfig.compatibility_flags ?? []
1797
+ ).mode;
1798
+ if (nodeCompatMode === "v2") {
1799
+ return true;
1800
+ }
1801
+ if (nodeCompatMode === "legacy") {
1802
+ throw new Error(
1803
+ "Unsupported Node.js compat mode (legacy). Remove the `node_compat` setting and add the `nodejs_compat` flag instead."
1804
+ );
1805
+ }
1806
+ if (nodeCompatMode === "v1") {
1807
+ throw new Error(
1808
+ `Unsupported Node.js compat mode (v1). Only the v2 mode is supported, either change your compat date to "2024-09-23" or later, or set the "nodejs_compat_v2" compatibility flag`
1809
+ );
1810
+ }
1811
+ return false;
1812
+ }
1813
+ function injectGlobalCode(id, code) {
1814
+ const injectedCode = Object.entries(env.inject).map(([globalName, globalInject]) => {
1815
+ if (typeof globalInject === "string") {
1816
+ const moduleSpecifier2 = globalInject;
1817
+ return `import var_${globalName} from "${moduleSpecifier2}";
1818
+ globalThis.${globalName} = var_${globalName};
1819
+ `;
1820
+ }
1821
+ const [moduleSpecifier, exportName] = globalInject;
1822
+ return `import var_${globalName} from "${moduleSpecifier}";
1823
+ globalThis.${globalName} = var_${globalName}.${exportName};
1824
+ `;
1825
+ }).join("\n");
1826
+ const modified = new MagicString(code);
1827
+ modified.prepend(injectedCode);
1828
+ return {
1829
+ code: modified.toString(),
1830
+ map: modified.generateMap({ hires: "boundary", source: id })
1831
+ };
1832
+ }
1833
+ function getNodeCompatAliases() {
1834
+ const aliases = {};
1835
+ Object.keys(env.alias).forEach((key) => {
1836
+ if (!env.external.includes(key)) {
1837
+ aliases[key] = CLOUDFLARE_VIRTUAL_PREFIX + key;
1838
+ }
1839
+ });
1840
+ return aliases;
1841
+ }
1842
+ function getNodeCompatExternals() {
1843
+ return env.external;
1844
+ }
1845
+ function maybeStripNodeJsVirtualPrefix(source) {
1846
+ return source.startsWith(CLOUDFLARE_VIRTUAL_PREFIX) ? source.slice(CLOUDFLARE_VIRTUAL_PREFIX.length) : void 0;
1847
+ }
1848
+ function dealiasVirtualNodeJSImport(source) {
1849
+ const alias = env.alias[source];
1850
+ assert5(
1851
+ alias,
1852
+ `Expected "${source}" to have a Node.js compat alias, but none was found`
1853
+ );
1854
+ assert5(
1855
+ !env.external.includes(alias),
1856
+ `Unexpected unenv alias to external module: ${source} -> ${alias}`
1857
+ );
1858
+ return alias;
1859
+ }
1860
+
1827
1861
  // src/plugin-config.ts
1828
- import assert6 from "node:assert";
1862
+ import assert7 from "node:assert";
1829
1863
  import * as path5 from "node:path";
1830
1864
  import * as vite5 from "vite";
1831
1865
 
1832
1866
  // src/workers-configs.ts
1833
- import assert5 from "node:assert";
1867
+ import assert6 from "node:assert";
1834
1868
  import * as fs3 from "node:fs";
1835
1869
  import * as path4 from "node:path";
1836
1870
  import { unstable_readConfig as unstable_readConfig2 } from "wrangler";
@@ -2006,17 +2040,17 @@ function getWorkerConfig(configPath, env2, opts) {
2006
2040
  }
2007
2041
  const { raw, config, nonApplicable } = readWorkerConfig(configPath, env2);
2008
2042
  opts?.visitedConfigPaths?.add(configPath);
2009
- assert5(
2043
+ assert6(
2010
2044
  config.topLevelName,
2011
2045
  missingFieldErrorMessage(`top-level 'name'`, configPath, env2)
2012
2046
  );
2013
- assert5(config.name, missingFieldErrorMessage(`'name'`, configPath, env2));
2014
- assert5(
2047
+ assert6(config.name, missingFieldErrorMessage(`'name'`, configPath, env2));
2048
+ assert6(
2015
2049
  config.compatibility_date,
2016
2050
  missingFieldErrorMessage(`'compatibility_date'`, configPath, env2)
2017
2051
  );
2018
2052
  if (opts?.isEntryWorker && !config.main) {
2019
- assert5(
2053
+ assert6(
2020
2054
  config.assets,
2021
2055
  missingFieldErrorMessage(`'main' or 'assets'`, configPath, env2)
2022
2056
  );
@@ -2033,7 +2067,7 @@ function getWorkerConfig(configPath, env2, opts) {
2033
2067
  nonApplicable
2034
2068
  };
2035
2069
  }
2036
- assert5(config.main, missingFieldErrorMessage(`'main'`, configPath, env2));
2070
+ assert6(config.main, missingFieldErrorMessage(`'main'`, configPath, env2));
2037
2071
  return {
2038
2072
  type: "worker",
2039
2073
  raw,
@@ -2064,20 +2098,21 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
2064
2098
  const configPaths = /* @__PURE__ */ new Set();
2065
2099
  const persistState = pluginConfig.persistState ?? true;
2066
2100
  const root = userConfig.root ? path5.resolve(userConfig.root) : process.cwd();
2067
- const { CLOUDFLARE_ENV } = vite5.loadEnv(viteEnv.mode, root, "");
2101
+ const { CLOUDFLARE_ENV: cloudflareEnv } = vite5.loadEnv(
2102
+ viteEnv.mode,
2103
+ root,
2104
+ /* prefixes */
2105
+ ""
2106
+ );
2068
2107
  const configPath = pluginConfig.configPath ? path5.resolve(root, pluginConfig.configPath) : findWranglerConfig(root);
2069
- assert6(
2108
+ assert7(
2070
2109
  configPath,
2071
2110
  `Config not found. Have you created a wrangler.json(c) or wrangler.toml file?`
2072
2111
  );
2073
- const entryWorkerResolvedConfig = getWorkerConfig(
2074
- configPath,
2075
- CLOUDFLARE_ENV,
2076
- {
2077
- visitedConfigPaths: configPaths,
2078
- isEntryWorker: true
2079
- }
2080
- );
2112
+ const entryWorkerResolvedConfig = getWorkerConfig(configPath, cloudflareEnv, {
2113
+ visitedConfigPaths: configPaths,
2114
+ isEntryWorker: true
2115
+ });
2081
2116
  if (entryWorkerResolvedConfig.type === "assets-only") {
2082
2117
  return {
2083
2118
  type: "assets-only",
@@ -2086,7 +2121,8 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
2086
2121
  persistState,
2087
2122
  rawConfigs: {
2088
2123
  entryWorker: entryWorkerResolvedConfig
2089
- }
2124
+ },
2125
+ cloudflareEnv
2090
2126
  };
2091
2127
  }
2092
2128
  const entryWorkerConfig = entryWorkerResolvedConfig.config;
@@ -2098,13 +2134,13 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
2098
2134
  for (const auxiliaryWorker of pluginConfig.auxiliaryWorkers ?? []) {
2099
2135
  const workerResolvedConfig = getWorkerConfig(
2100
2136
  path5.resolve(root, auxiliaryWorker.configPath),
2101
- CLOUDFLARE_ENV,
2137
+ cloudflareEnv,
2102
2138
  {
2103
2139
  visitedConfigPaths: configPaths
2104
2140
  }
2105
2141
  );
2106
2142
  auxiliaryWorkersResolvedConfigs.push(workerResolvedConfig);
2107
- assert6(
2143
+ assert7(
2108
2144
  workerResolvedConfig.type === "worker",
2109
2145
  "Unexpected error: received AssetsOnlyResult with auxiliary workers."
2110
2146
  );
@@ -2126,7 +2162,8 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
2126
2162
  rawConfigs: {
2127
2163
  entryWorker: entryWorkerResolvedConfig,
2128
2164
  auxiliaryWorkers: auxiliaryWorkersResolvedConfigs
2129
- }
2165
+ },
2166
+ cloudflareEnv
2130
2167
  };
2131
2168
  }
2132
2169
 
@@ -2170,8 +2207,10 @@ ${event.error?.stack || event.error?.message}`,
2170
2207
  workerWebSocket.addEventListener("close", () => {
2171
2208
  clientWebSocket.close();
2172
2209
  });
2173
- clientWebSocket.on("message", (event) => {
2174
- workerWebSocket.send(event);
2210
+ clientWebSocket.on("message", (data, isBinary) => {
2211
+ workerWebSocket.send(
2212
+ isBinary ? Array.isArray(data) ? Buffer.concat(data) : data : data.toString()
2213
+ );
2175
2214
  });
2176
2215
  clientWebSocket.on("error", (error) => {
2177
2216
  logger.error(`WebSocket error:
@@ -2195,213 +2234,371 @@ function cloudflare2(pluginConfig = {}) {
2195
2234
  let resolvedViteConfig;
2196
2235
  let miniflare;
2197
2236
  let workersConfigsWarningShown = false;
2198
- return {
2199
- name: "vite-plugin-cloudflare",
2200
- config(userConfig, env2) {
2201
- if (env2.isPreview) {
2202
- return { appType: "custom" };
2203
- }
2204
- resolvedPluginConfig = resolvePluginConfig(pluginConfig, userConfig, env2);
2205
- if (!workersConfigsWarningShown) {
2206
- workersConfigsWarningShown = true;
2207
- const workersConfigsWarning = getWarningForWorkersConfigs(
2208
- resolvedPluginConfig.rawConfigs
2237
+ return [
2238
+ {
2239
+ name: "vite-plugin-cloudflare",
2240
+ config(userConfig, env2) {
2241
+ if (env2.isPreview) {
2242
+ return { appType: "custom" };
2243
+ }
2244
+ resolvedPluginConfig = resolvePluginConfig(
2245
+ pluginConfig,
2246
+ userConfig,
2247
+ env2
2209
2248
  );
2210
- if (workersConfigsWarning) {
2211
- console.warn(workersConfigsWarning);
2249
+ if (!workersConfigsWarningShown) {
2250
+ workersConfigsWarningShown = true;
2251
+ const workersConfigsWarning = getWarningForWorkersConfigs(
2252
+ resolvedPluginConfig.rawConfigs
2253
+ );
2254
+ if (workersConfigsWarning) {
2255
+ console.warn(workersConfigsWarning);
2256
+ }
2212
2257
  }
2213
- }
2214
- return {
2215
- appType: "custom",
2216
- resolve: {
2217
- alias: getNodeCompatAliases()
2218
- },
2219
- environments: resolvedPluginConfig.type === "workers" ? {
2220
- ...Object.fromEntries(
2221
- Object.entries(resolvedPluginConfig.workers).map(
2222
- ([environmentName, workerConfig]) => {
2223
- return [
2224
- environmentName,
2225
- createCloudflareEnvironmentOptions(
2226
- workerConfig,
2227
- userConfig,
2228
- environmentName
2258
+ return {
2259
+ appType: "custom",
2260
+ environments: resolvedPluginConfig.type === "workers" ? {
2261
+ ...Object.fromEntries(
2262
+ Object.entries(resolvedPluginConfig.workers).map(
2263
+ ([environmentName, workerConfig]) => {
2264
+ return [
2265
+ environmentName,
2266
+ createCloudflareEnvironmentOptions(
2267
+ workerConfig,
2268
+ userConfig,
2269
+ environmentName
2270
+ )
2271
+ ];
2272
+ }
2273
+ )
2274
+ ),
2275
+ client: {
2276
+ build: {
2277
+ outDir: getOutputDirectory(userConfig, "client")
2278
+ }
2279
+ }
2280
+ } : void 0,
2281
+ builder: {
2282
+ async buildApp(builder) {
2283
+ const clientEnvironment = builder.environments.client;
2284
+ const defaultHtmlPath = path6.resolve(
2285
+ builder.config.root,
2286
+ "index.html"
2287
+ );
2288
+ if (clientEnvironment && (clientEnvironment.config.build.rollupOptions.input || fs4.existsSync(defaultHtmlPath))) {
2289
+ await builder.build(clientEnvironment);
2290
+ }
2291
+ if (resolvedPluginConfig.type === "workers") {
2292
+ const workerEnvironments = Object.keys(
2293
+ resolvedPluginConfig.workers
2294
+ ).map((environmentName) => {
2295
+ const environment = builder.environments[environmentName];
2296
+ assert8(
2297
+ environment,
2298
+ `${environmentName} environment not found`
2299
+ );
2300
+ return environment;
2301
+ });
2302
+ await Promise.all(
2303
+ workerEnvironments.map(
2304
+ (environment) => builder.build(environment)
2229
2305
  )
2230
- ];
2306
+ );
2231
2307
  }
2232
- )
2233
- ),
2234
- client: {
2235
- build: {
2236
- outDir: getOutputDirectory(userConfig, "client")
2237
2308
  }
2238
2309
  }
2239
- } : void 0,
2240
- builder: {
2241
- async buildApp(builder) {
2242
- const clientEnvironment = builder.environments.client;
2243
- const defaultHtmlPath = path6.resolve(
2244
- builder.config.root,
2245
- "index.html"
2310
+ };
2311
+ },
2312
+ configResolved(config) {
2313
+ resolvedViteConfig = config;
2314
+ },
2315
+ generateBundle(_, bundle) {
2316
+ let config;
2317
+ if (resolvedPluginConfig.type === "workers") {
2318
+ const workerConfig = resolvedPluginConfig.workers[this.environment.name];
2319
+ const entryChunk = Object.entries(bundle).find(
2320
+ ([_2, chunk]) => chunk.type === "chunk" && chunk.isEntry
2321
+ );
2322
+ if (!workerConfig || !entryChunk) {
2323
+ return;
2324
+ }
2325
+ workerConfig.main = entryChunk[0];
2326
+ const isEntryWorker = this.environment.name === resolvedPluginConfig.entryWorkerEnvironmentName;
2327
+ if (isEntryWorker && workerConfig.assets) {
2328
+ const workerOutputDirectory = this.environment.config.build.outDir;
2329
+ const clientOutputDirectory = resolvedViteConfig.environments.client?.build.outDir;
2330
+ assert8(
2331
+ clientOutputDirectory,
2332
+ "Unexpected error: client output directory is undefined"
2246
2333
  );
2247
- if (clientEnvironment && (clientEnvironment.config.build.rollupOptions.input || fs4.existsSync(defaultHtmlPath))) {
2248
- await builder.build(clientEnvironment);
2249
- }
2250
- if (resolvedPluginConfig.type === "workers") {
2251
- const workerEnvironments = Object.keys(
2252
- resolvedPluginConfig.workers
2253
- ).map((environmentName) => {
2254
- const environment = builder.environments[environmentName];
2255
- assert7(environment, `${environmentName} environment not found`);
2256
- return environment;
2334
+ workerConfig.assets.directory = path6.relative(
2335
+ path6.resolve(resolvedViteConfig.root, workerOutputDirectory),
2336
+ path6.resolve(resolvedViteConfig.root, clientOutputDirectory)
2337
+ );
2338
+ }
2339
+ config = workerConfig;
2340
+ if (workerConfig.configPath) {
2341
+ const dotDevDotVarsContent = getDotDevDotVarsContent(
2342
+ workerConfig.configPath,
2343
+ resolvedPluginConfig.cloudflareEnv
2344
+ );
2345
+ if (dotDevDotVarsContent) {
2346
+ this.emitFile({
2347
+ type: "asset",
2348
+ fileName: ".dev.vars",
2349
+ source: dotDevDotVarsContent
2257
2350
  });
2258
- await Promise.all(
2259
- workerEnvironments.map(
2260
- (environment) => builder.build(environment)
2261
- )
2262
- );
2263
2351
  }
2264
- writeDeployConfig(resolvedPluginConfig, resolvedViteConfig);
2265
2352
  }
2353
+ } else if (this.environment.name === "client") {
2354
+ const assetsOnlyConfig = resolvedPluginConfig.config;
2355
+ assetsOnlyConfig.assets.directory = ".";
2356
+ const filesToAssetsIgnore = ["wrangler.json", ".dev.vars"];
2357
+ this.emitFile({
2358
+ type: "asset",
2359
+ fileName: ".assetsignore",
2360
+ source: `${filesToAssetsIgnore.join("\n")}
2361
+ `
2362
+ });
2363
+ config = assetsOnlyConfig;
2266
2364
  }
2267
- };
2268
- },
2269
- configResolved(config) {
2270
- resolvedViteConfig = config;
2271
- },
2272
- async resolveId(source) {
2273
- if (resolvedPluginConfig.type === "assets-only") {
2274
- return;
2275
- }
2276
- const workerConfig = resolvedPluginConfig.workers[this.environment.name];
2277
- if (!workerConfig) {
2278
- return;
2279
- }
2280
- return resolveNodeCompatId(this.environment, workerConfig, source);
2281
- },
2282
- async transform(code, id) {
2283
- if (resolvedPluginConfig.type === "assets-only") {
2284
- return;
2285
- }
2286
- const workerConfig = resolvedPluginConfig.workers[this.environment.name];
2287
- if (!workerConfig) {
2288
- return;
2289
- }
2290
- const resolvedId = await this.resolve(workerConfig.main);
2291
- if (id === resolvedId?.id) {
2292
- return injectGlobalCode(id, code, workerConfig);
2293
- }
2294
- },
2295
- generateBundle(_, bundle) {
2296
- let config;
2297
- if (resolvedPluginConfig.type === "workers") {
2298
- const workerConfig = resolvedPluginConfig.workers[this.environment.name];
2299
- const entryChunk = Object.entries(bundle).find(
2300
- ([_2, chunk]) => chunk.type === "chunk" && chunk.isEntry
2301
- );
2302
- if (!workerConfig || !entryChunk) {
2365
+ if (!config) {
2303
2366
  return;
2304
2367
  }
2305
- workerConfig.main = entryChunk[0];
2306
- const isEntryWorker = this.environment.name === resolvedPluginConfig.entryWorkerEnvironmentName;
2307
- if (isEntryWorker && workerConfig.assets) {
2308
- const workerOutputDirectory = this.environment.config.build.outDir;
2309
- const clientOutputDirectory = resolvedViteConfig.environments.client?.build.outDir;
2310
- assert7(
2311
- clientOutputDirectory,
2312
- "Unexpected error: client output directory is undefined"
2313
- );
2314
- workerConfig.assets.directory = path6.relative(
2315
- path6.resolve(resolvedViteConfig.root, workerOutputDirectory),
2316
- path6.resolve(resolvedViteConfig.root, clientOutputDirectory)
2317
- );
2368
+ config.no_bundle = true;
2369
+ config.rules = [{ type: "ESModule", globs: ["**/*.js"] }];
2370
+ if (config.unsafe && Object.keys(config.unsafe).length === 0) {
2371
+ config.unsafe = void 0;
2318
2372
  }
2319
- config = workerConfig;
2320
- } else if (this.environment.name === "client") {
2321
- const assetsOnlyConfig = resolvedPluginConfig.config;
2322
- assetsOnlyConfig.assets.directory = ".";
2323
2373
  this.emitFile({
2324
2374
  type: "asset",
2325
- fileName: ".assetsignore",
2326
- source: "wrangler.json"
2375
+ fileName: "wrangler.json",
2376
+ source: JSON.stringify(config)
2327
2377
  });
2328
- config = assetsOnlyConfig;
2329
- }
2330
- if (!config) {
2331
- return;
2332
- }
2333
- config.no_bundle = true;
2334
- config.rules = [{ type: "ESModule", globs: ["**/*.js"] }];
2335
- if (config.unsafe && Object.keys(config.unsafe).length === 0) {
2336
- config.unsafe = void 0;
2378
+ },
2379
+ writeBundle() {
2380
+ if (this.environment.name === (resolvedPluginConfig.type === "assets-only" ? "client" : resolvedPluginConfig.entryWorkerEnvironmentName)) {
2381
+ writeDeployConfig(resolvedPluginConfig, resolvedViteConfig);
2382
+ }
2383
+ },
2384
+ handleHotUpdate(options) {
2385
+ if (resolvedPluginConfig.configPaths.has(options.file)) {
2386
+ options.server.restart();
2387
+ }
2388
+ },
2389
+ async buildEnd() {
2390
+ if (miniflare) {
2391
+ await miniflare.dispose();
2392
+ miniflare = void 0;
2393
+ }
2394
+ },
2395
+ async configureServer(viteDevServer) {
2396
+ assert8(
2397
+ viteDevServer.httpServer,
2398
+ "Unexpected error: No Vite HTTP server"
2399
+ );
2400
+ miniflare = new Miniflare(
2401
+ getDevMiniflareOptions(resolvedPluginConfig, viteDevServer)
2402
+ );
2403
+ await initRunners(resolvedPluginConfig, viteDevServer, miniflare);
2404
+ const entryWorker = await getDevEntryWorker(
2405
+ resolvedPluginConfig,
2406
+ miniflare
2407
+ );
2408
+ const middleware = createMiddleware(
2409
+ ({ request }) => {
2410
+ return entryWorker.fetch(toMiniflareRequest(request), {
2411
+ redirect: "manual"
2412
+ });
2413
+ },
2414
+ { alwaysCallNext: false }
2415
+ );
2416
+ handleWebSocket(
2417
+ viteDevServer.httpServer,
2418
+ entryWorker.fetch,
2419
+ viteDevServer.config.logger
2420
+ );
2421
+ return () => {
2422
+ viteDevServer.middlewares.use((req, res, next) => {
2423
+ middleware(req, res, next);
2424
+ });
2425
+ };
2426
+ },
2427
+ configurePreviewServer(vitePreviewServer) {
2428
+ const miniflare2 = new Miniflare(
2429
+ getPreviewMiniflareOptions(
2430
+ vitePreviewServer,
2431
+ pluginConfig.persistState ?? true
2432
+ )
2433
+ );
2434
+ const middleware = createMiddleware(
2435
+ ({ request }) => {
2436
+ return miniflare2.dispatchFetch(toMiniflareRequest(request), {
2437
+ redirect: "manual"
2438
+ });
2439
+ },
2440
+ { alwaysCallNext: false }
2441
+ );
2442
+ handleWebSocket(
2443
+ vitePreviewServer.httpServer,
2444
+ miniflare2.dispatchFetch,
2445
+ vitePreviewServer.config.logger
2446
+ );
2447
+ return () => {
2448
+ vitePreviewServer.middlewares.use((req, res, next) => {
2449
+ middleware(req, res, next);
2450
+ });
2451
+ };
2337
2452
  }
2338
- this.emitFile({
2339
- type: "asset",
2340
- fileName: "wrangler.json",
2341
- source: JSON.stringify(config)
2342
- });
2343
2453
  },
2344
- handleHotUpdate(options) {
2345
- if (resolvedPluginConfig.configPaths.has(options.file)) {
2346
- options.server.restart();
2454
+ // Plugin to support `CompiledWasm` modules
2455
+ {
2456
+ name: "vite-plugin-cloudflare:modules",
2457
+ // We set `enforce: "pre"` so that this plugin runs before the Vite core plugins.
2458
+ // Otherwise the `vite:wasm-fallback` plugin prevents the `.wasm` extension being used for module imports.
2459
+ enforce: "pre",
2460
+ applyToEnvironment(environment) {
2461
+ return getWorkerConfig2(environment.name) !== void 0;
2462
+ },
2463
+ async resolveId(source, importer) {
2464
+ if (!source.endsWith(".wasm")) {
2465
+ return;
2466
+ }
2467
+ const resolved = await this.resolve(source, importer);
2468
+ assert8(
2469
+ resolved,
2470
+ `Unexpected error: could not resolve Wasm module ${source}`
2471
+ );
2472
+ return {
2473
+ external: true,
2474
+ id: createModuleReference("CompiledWasm", resolved.id)
2475
+ };
2476
+ },
2477
+ renderChunk(code, chunk) {
2478
+ const moduleRE = new RegExp(MODULE_PATTERN, "g");
2479
+ let match;
2480
+ let magicString;
2481
+ while (match = moduleRE.exec(code)) {
2482
+ magicString ??= new MagicString(code);
2483
+ const [full, moduleType, modulePath] = match;
2484
+ assert8(
2485
+ modulePath,
2486
+ `Unexpected error: module path not found in reference ${full}.`
2487
+ );
2488
+ let source;
2489
+ try {
2490
+ source = fs4.readFileSync(modulePath);
2491
+ } catch (error) {
2492
+ throw new Error(
2493
+ `Import ${modulePath} not found. Does the file exist?`
2494
+ );
2495
+ }
2496
+ const referenceId = this.emitFile({
2497
+ type: "asset",
2498
+ name: path6.basename(modulePath),
2499
+ originalFileName: modulePath,
2500
+ source
2501
+ });
2502
+ const emittedFileName = this.getFileName(referenceId);
2503
+ const relativePath = vite6.normalizePath(
2504
+ path6.relative(path6.dirname(chunk.fileName), emittedFileName)
2505
+ );
2506
+ const importPath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
2507
+ magicString.update(
2508
+ match.index,
2509
+ match.index + full.length,
2510
+ importPath
2511
+ );
2512
+ }
2513
+ if (magicString) {
2514
+ return {
2515
+ code: magicString.toString(),
2516
+ map: this.environment.config.build.sourcemap ? magicString.generateMap({ hires: "boundary" }) : null
2517
+ };
2518
+ }
2347
2519
  }
2348
2520
  },
2349
- async buildEnd() {
2350
- if (miniflare) {
2351
- await miniflare.dispose();
2352
- miniflare = void 0;
2521
+ // Plugin that can provide Node.js compatibility support for Vite Environments that are hosted in Cloudflare Workers.
2522
+ {
2523
+ name: "vite-plugin-cloudflare:nodejs-compat",
2524
+ apply(_config, env2) {
2525
+ return !env2.isPreview;
2526
+ },
2527
+ config() {
2528
+ return {
2529
+ resolve: {
2530
+ alias: getNodeCompatAliases()
2531
+ }
2532
+ };
2533
+ },
2534
+ configEnvironment(environmentName) {
2535
+ const workerConfig = getWorkerConfig2(environmentName);
2536
+ if (isNodeCompat(workerConfig)) {
2537
+ return {
2538
+ build: {
2539
+ rollupOptions: {
2540
+ external: getNodeCompatExternals()
2541
+ }
2542
+ }
2543
+ };
2544
+ }
2545
+ },
2546
+ async resolveId(source, importer, options) {
2547
+ const from = maybeStripNodeJsVirtualPrefix(source);
2548
+ if (!from) {
2549
+ return;
2550
+ }
2551
+ const workerConfig = getWorkerConfig2(this.environment.name);
2552
+ if (!isNodeCompat(workerConfig)) {
2553
+ return this.resolve(from, importer, options);
2554
+ }
2555
+ const unresolvedAlias = dealiasVirtualNodeJSImport(from);
2556
+ const resolvedAlias = await this.resolve(
2557
+ unresolvedAlias,
2558
+ import.meta.url
2559
+ );
2560
+ assert8(
2561
+ resolvedAlias,
2562
+ "Failed to resolve aliased nodejs import: " + unresolvedAlias
2563
+ );
2564
+ if (this.environment.mode === "dev" && this.environment.depsOptimizer) {
2565
+ this.environment.depsOptimizer.registerMissingImport(
2566
+ unresolvedAlias,
2567
+ resolvedAlias.id
2568
+ );
2569
+ }
2570
+ return resolvedAlias;
2571
+ },
2572
+ async transform(code, id) {
2573
+ const workerConfig = getWorkerConfig2(this.environment.name);
2574
+ if (!isNodeCompat(workerConfig)) {
2575
+ return;
2576
+ }
2577
+ const resolvedId = await this.resolve(workerConfig.main);
2578
+ if (id === resolvedId?.id) {
2579
+ return injectGlobalCode(id, code);
2580
+ }
2353
2581
  }
2354
- },
2355
- async configureServer(viteDevServer) {
2356
- assert7(viteDevServer.httpServer, "Unexpected error: No Vite HTTP server");
2357
- miniflare = new Miniflare(
2358
- getDevMiniflareOptions(resolvedPluginConfig, viteDevServer)
2359
- );
2360
- await initRunners(resolvedPluginConfig, viteDevServer, miniflare);
2361
- const entryWorker = await getDevEntryWorker(
2362
- resolvedPluginConfig,
2363
- miniflare
2364
- );
2365
- const middleware = createMiddleware(({ request }) => {
2366
- return entryWorker.fetch(toMiniflareRequest(request), {
2367
- redirect: "manual"
2368
- });
2369
- });
2370
- handleWebSocket(
2371
- viteDevServer.httpServer,
2372
- entryWorker.fetch,
2373
- viteDevServer.config.logger
2374
- );
2375
- return () => {
2376
- viteDevServer.middlewares.use((req, res, next) => {
2377
- middleware(req, res, next);
2378
- });
2379
- };
2380
- },
2381
- configurePreviewServer(vitePreviewServer) {
2382
- const miniflare2 = new Miniflare(
2383
- getPreviewMiniflareOptions(
2384
- vitePreviewServer,
2385
- pluginConfig.persistState ?? true
2386
- )
2387
- );
2388
- const middleware = createMiddleware(({ request }) => {
2389
- return miniflare2.dispatchFetch(toMiniflareRequest(request), {
2390
- redirect: "manual"
2391
- });
2392
- });
2393
- handleWebSocket(
2394
- vitePreviewServer.httpServer,
2395
- miniflare2.dispatchFetch,
2396
- vitePreviewServer.config.logger
2397
- );
2398
- return () => {
2399
- vitePreviewServer.middlewares.use((req, res, next) => {
2400
- middleware(req, res, next);
2401
- });
2402
- };
2403
2582
  }
2404
- };
2583
+ ];
2584
+ function getWorkerConfig2(environmentName) {
2585
+ assert8(resolvedPluginConfig, "Expected resolvedPluginConfig to be defined");
2586
+ return resolvedPluginConfig.type !== "assets-only" ? resolvedPluginConfig.workers[environmentName] : void 0;
2587
+ }
2588
+ }
2589
+ function getDotDevDotVarsContent(configPath, cloudflareEnv) {
2590
+ const configDir = path6.dirname(configPath);
2591
+ const defaultDotDevDotVarsPath = `${configDir}/.dev.vars`;
2592
+ const inputDotDevDotVarsPath = `${defaultDotDevDotVarsPath}${cloudflareEnv ? `.${cloudflareEnv}` : ""}`;
2593
+ const targetPath = fs4.existsSync(inputDotDevDotVarsPath) ? inputDotDevDotVarsPath : fs4.existsSync(defaultDotDevDotVarsPath) ? defaultDotDevDotVarsPath : null;
2594
+ if (targetPath) {
2595
+ const dotDevDotVarsContent = fs4.readFileSync(targetPath);
2596
+ return dotDevDotVarsContent;
2597
+ }
2598
+ return null;
2599
+ }
2600
+ function createModuleReference(type, id) {
2601
+ return `__CLOUDFLARE_MODULE__${type}__${id}__`;
2405
2602
  }
2406
2603
  export {
2407
2604
  cloudflare2 as cloudflare