@cloudflare/vite-plugin 0.0.0-97d2a1bb5 → 0.0.0-99ba292d8

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";
@@ -1268,7 +1183,10 @@ var CloudflareDevEnvironment = class extends vite2.DevEnvironment {
1268
1183
  }
1269
1184
  }
1270
1185
  );
1271
- assert(response.ok, "Failed to initialize module runner");
1186
+ assert(
1187
+ response.ok,
1188
+ `Failed to initialize module runner, error: ${await response.text()}`
1189
+ );
1272
1190
  const webSocket = response.webSocket;
1273
1191
  assert(webSocket, "Failed to establish WebSocket");
1274
1192
  webSocket.accept();
@@ -1281,6 +1199,7 @@ var cloudflareBuiltInModules = [
1281
1199
  "cloudflare:workers",
1282
1200
  "cloudflare:workflows"
1283
1201
  ];
1202
+ var defaultConditions = ["workerd", "module", "browser"];
1284
1203
  function createCloudflareEnvironmentOptions(workerConfig, userConfig, environmentName) {
1285
1204
  return {
1286
1205
  resolve: {
@@ -1288,7 +1207,7 @@ function createCloudflareEnvironmentOptions(workerConfig, userConfig, environmen
1288
1207
  // dependencies as not external
1289
1208
  noExternal: true,
1290
1209
  // We want to use `workerd` package exports if available (e.g. for postgres).
1291
- conditions: ["workerd", "module", "browser", "development|production"]
1210
+ conditions: [...defaultConditions, "development|production"]
1292
1211
  },
1293
1212
  dev: {
1294
1213
  createEnvironment(name2, config) {
@@ -1299,7 +1218,11 @@ function createCloudflareEnvironmentOptions(workerConfig, userConfig, environmen
1299
1218
  createEnvironment(name2, config) {
1300
1219
  return new vite2.BuildEnvironment(name2, config);
1301
1220
  },
1221
+ target: "es2022",
1222
+ // We need to enable `emitAssets` in order to support additional modules defined by `rules`
1223
+ emitAssets: true,
1302
1224
  outDir: getOutputDirectory(userConfig, environmentName),
1225
+ copyPublicDir: false,
1303
1226
  ssr: true,
1304
1227
  rollupOptions: {
1305
1228
  // Note: vite starts dev pre-bundling crawling from either optimizeDeps.entries or rollupOptions.input
@@ -1307,7 +1230,7 @@ function createCloudflareEnvironmentOptions(workerConfig, userConfig, environmen
1307
1230
  // dev pre-bundling crawling (were we not to set this input field we'd have to appropriately set
1308
1231
  // optimizeDeps.entries in the dev config)
1309
1232
  input: workerConfig.main,
1310
- external: [...cloudflareBuiltInModules, ...getNodeCompatExternals()]
1233
+ external: [...cloudflareBuiltInModules]
1311
1234
  }
1312
1235
  },
1313
1236
  optimizeDeps: {
@@ -1320,6 +1243,7 @@ function createCloudflareEnvironmentOptions(workerConfig, userConfig, environmen
1320
1243
  ],
1321
1244
  esbuildOptions: {
1322
1245
  platform: "neutral",
1246
+ conditions: [...defaultConditions, "development"],
1323
1247
  resolveExtensions: [
1324
1248
  ".mjs",
1325
1249
  ".js",
@@ -1430,13 +1354,6 @@ function writeDeployConfig(resolvedPluginConfig, resolvedViteConfig) {
1430
1354
 
1431
1355
  // src/dev.ts
1432
1356
  import assert3 from "node:assert";
1433
-
1434
- // src/constants.ts
1435
- var ROUTER_WORKER_NAME = "__router-worker__";
1436
- var ASSET_WORKER_NAME = "__asset-worker__";
1437
- var ASSET_WORKERS_COMPATIBILITY_DATE = "2024-10-04";
1438
-
1439
- // src/dev.ts
1440
1357
  function getDevEntryWorker(resolvedPluginConfig, miniflare) {
1441
1358
  const entryWorkerConfig = resolvedPluginConfig.type === "assets-only" ? resolvedPluginConfig.config : resolvedPluginConfig.workers[resolvedPluginConfig.entryWorkerEnvironmentName];
1442
1359
  assert3(entryWorkerConfig, "Unexpected error: No entry worker configuration");
@@ -1634,10 +1551,13 @@ function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer) {
1634
1551
  ];
1635
1552
  const userWorkers = resolvedPluginConfig.type === "workers" ? Object.entries(resolvedPluginConfig.workers).map(
1636
1553
  ([environmentName, workerConfig]) => {
1637
- const miniflareWorkerOptions = unstable_getMiniflareWorkerOptions({
1638
- ...workerConfig,
1639
- assets: void 0
1640
- });
1554
+ const miniflareWorkerOptions = unstable_getMiniflareWorkerOptions(
1555
+ {
1556
+ ...workerConfig,
1557
+ assets: void 0
1558
+ },
1559
+ resolvedPluginConfig.cloudflareEnv
1560
+ );
1641
1561
  const { ratelimits, ...workerOptions } = miniflareWorkerOptions.workerOptions;
1642
1562
  return {
1643
1563
  ...workerOptions,
@@ -1663,16 +1583,24 @@ function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer) {
1663
1583
  `Invalid invoke event: ${invokePayloadData.name}`
1664
1584
  );
1665
1585
  const [moduleId] = invokePayloadData.data;
1586
+ const moduleRE = new RegExp(MODULE_PATTERN);
1587
+ if (moduleRE.test(moduleId)) {
1588
+ const result2 = {
1589
+ externalize: moduleId,
1590
+ type: "module"
1591
+ };
1592
+ return MiniflareResponse.json({ result: result2 });
1593
+ }
1666
1594
  if (moduleId.startsWith("cloudflare:")) {
1667
1595
  const result2 = {
1668
1596
  externalize: moduleId,
1669
1597
  type: "builtin"
1670
1598
  };
1671
- return new MiniflareResponse(JSON.stringify({ result: result2 }));
1599
+ return MiniflareResponse.json({ result: result2 });
1672
1600
  }
1673
1601
  const devEnvironment = viteDevServer.environments[environmentName];
1674
1602
  const result = await devEnvironment.hot.handleInvoke(payload);
1675
- return new MiniflareResponse(JSON.stringify(result));
1603
+ return MiniflareResponse.json(result);
1676
1604
  }
1677
1605
  }
1678
1606
  };
@@ -1751,10 +1679,37 @@ function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer) {
1751
1679
  fileURLToPath(new URL(RUNNER_PATH, import.meta.url))
1752
1680
  )
1753
1681
  }
1754
- ]
1682
+ ],
1683
+ unsafeUseModuleFallbackService: true
1755
1684
  };
1756
1685
  })
1757
- ]
1686
+ ],
1687
+ unsafeModuleFallbackService(request) {
1688
+ const url = new URL(request.url);
1689
+ const rawSpecifier = url.searchParams.get("rawSpecifier");
1690
+ assert4(
1691
+ rawSpecifier,
1692
+ `Unexpected error: no specifier in request to module fallback service.`
1693
+ );
1694
+ const moduleRE = new RegExp(MODULE_PATTERN);
1695
+ const match = moduleRE.exec(rawSpecifier);
1696
+ assert4(match, `Unexpected error: no match for module ${rawSpecifier}.`);
1697
+ const [full, moduleType, modulePath] = match;
1698
+ assert4(
1699
+ modulePath,
1700
+ `Unexpected error: module path not found in reference ${full}.`
1701
+ );
1702
+ let source;
1703
+ try {
1704
+ source = fs2.readFileSync(modulePath);
1705
+ } catch (error) {
1706
+ throw new Error(`Import ${modulePath} not found. Does the file exist?`);
1707
+ }
1708
+ return MiniflareResponse.json({
1709
+ // Cap'n Proto expects byte arrays for `:Data` typed fields from JSON
1710
+ wasm: Array.from(source)
1711
+ });
1712
+ }
1758
1713
  };
1759
1714
  }
1760
1715
  function getPreviewMiniflareOptions(vitePreviewServer, persistState) {
@@ -1821,13 +1776,94 @@ function miniflareLogLevelFromViteLogLevel(level = "info") {
1821
1776
  }
1822
1777
  }
1823
1778
 
1779
+ // src/node-js-compat.ts
1780
+ import assert5 from "node:assert";
1781
+ import { cloudflare } from "@cloudflare/unenv-preset";
1782
+ import { getNodeCompat } from "miniflare";
1783
+ import { defineEnv } from "unenv";
1784
+ var { env } = defineEnv({
1785
+ nodeCompat: true,
1786
+ presets: [cloudflare]
1787
+ });
1788
+ var CLOUDFLARE_VIRTUAL_PREFIX = "\0__CLOUDFLARE_NODEJS_COMPAT__";
1789
+ function isNodeCompat(workerConfig) {
1790
+ if (workerConfig === void 0) {
1791
+ return false;
1792
+ }
1793
+ const nodeCompatMode = getNodeCompat(
1794
+ workerConfig.compatibility_date,
1795
+ workerConfig.compatibility_flags ?? []
1796
+ ).mode;
1797
+ if (nodeCompatMode === "v2") {
1798
+ return true;
1799
+ }
1800
+ if (nodeCompatMode === "legacy") {
1801
+ throw new Error(
1802
+ "Unsupported Node.js compat mode (legacy). Remove the `node_compat` setting and add the `nodejs_compat` flag instead."
1803
+ );
1804
+ }
1805
+ if (nodeCompatMode === "v1") {
1806
+ throw new Error(
1807
+ `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`
1808
+ );
1809
+ }
1810
+ return false;
1811
+ }
1812
+ function injectGlobalCode(id, code) {
1813
+ const injectedCode = Object.entries(env.inject).map(([globalName, globalInject]) => {
1814
+ if (typeof globalInject === "string") {
1815
+ const moduleSpecifier2 = globalInject;
1816
+ return `import var_${globalName} from "${moduleSpecifier2}";
1817
+ globalThis.${globalName} = var_${globalName};
1818
+ `;
1819
+ }
1820
+ const [moduleSpecifier, exportName] = globalInject;
1821
+ return `import var_${globalName} from "${moduleSpecifier}";
1822
+ globalThis.${globalName} = var_${globalName}.${exportName};
1823
+ `;
1824
+ }).join("\n");
1825
+ const modified = new MagicString(code);
1826
+ modified.prepend(injectedCode);
1827
+ return {
1828
+ code: modified.toString(),
1829
+ map: modified.generateMap({ hires: "boundary", source: id })
1830
+ };
1831
+ }
1832
+ function getNodeCompatAliases() {
1833
+ const aliases = {};
1834
+ Object.keys(env.alias).forEach((key) => {
1835
+ if (!env.external.includes(key)) {
1836
+ aliases[key] = CLOUDFLARE_VIRTUAL_PREFIX + key;
1837
+ }
1838
+ });
1839
+ return aliases;
1840
+ }
1841
+ function getNodeCompatExternals() {
1842
+ return env.external;
1843
+ }
1844
+ function maybeStripNodeJsVirtualPrefix(source) {
1845
+ return source.startsWith(CLOUDFLARE_VIRTUAL_PREFIX) ? source.slice(CLOUDFLARE_VIRTUAL_PREFIX.length) : void 0;
1846
+ }
1847
+ function dealiasVirtualNodeJSImport(source) {
1848
+ const alias = env.alias[source];
1849
+ assert5(
1850
+ alias,
1851
+ `Expected "${source}" to have a Node.js compat alias, but none was found`
1852
+ );
1853
+ assert5(
1854
+ !env.external.includes(alias),
1855
+ `Unexpected unenv alias to external module: ${source} -> ${alias}`
1856
+ );
1857
+ return alias;
1858
+ }
1859
+
1824
1860
  // src/plugin-config.ts
1825
- import assert6 from "node:assert";
1861
+ import assert7 from "node:assert";
1826
1862
  import * as path5 from "node:path";
1827
1863
  import * as vite5 from "vite";
1828
1864
 
1829
1865
  // src/workers-configs.ts
1830
- import assert5 from "node:assert";
1866
+ import assert6 from "node:assert";
1831
1867
  import * as fs3 from "node:fs";
1832
1868
  import * as path4 from "node:path";
1833
1869
  import { unstable_readConfig as unstable_readConfig2 } from "wrangler";
@@ -2003,17 +2039,17 @@ function getWorkerConfig(configPath, env2, opts) {
2003
2039
  }
2004
2040
  const { raw, config, nonApplicable } = readWorkerConfig(configPath, env2);
2005
2041
  opts?.visitedConfigPaths?.add(configPath);
2006
- assert5(
2042
+ assert6(
2007
2043
  config.topLevelName,
2008
2044
  missingFieldErrorMessage(`top-level 'name'`, configPath, env2)
2009
2045
  );
2010
- assert5(config.name, missingFieldErrorMessage(`'name'`, configPath, env2));
2011
- assert5(
2046
+ assert6(config.name, missingFieldErrorMessage(`'name'`, configPath, env2));
2047
+ assert6(
2012
2048
  config.compatibility_date,
2013
2049
  missingFieldErrorMessage(`'compatibility_date'`, configPath, env2)
2014
2050
  );
2015
2051
  if (opts?.isEntryWorker && !config.main) {
2016
- assert5(
2052
+ assert6(
2017
2053
  config.assets,
2018
2054
  missingFieldErrorMessage(`'main' or 'assets'`, configPath, env2)
2019
2055
  );
@@ -2030,7 +2066,7 @@ function getWorkerConfig(configPath, env2, opts) {
2030
2066
  nonApplicable
2031
2067
  };
2032
2068
  }
2033
- assert5(config.main, missingFieldErrorMessage(`'main'`, configPath, env2));
2069
+ assert6(config.main, missingFieldErrorMessage(`'main'`, configPath, env2));
2034
2070
  return {
2035
2071
  type: "worker",
2036
2072
  raw,
@@ -2061,20 +2097,21 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
2061
2097
  const configPaths = /* @__PURE__ */ new Set();
2062
2098
  const persistState = pluginConfig.persistState ?? true;
2063
2099
  const root = userConfig.root ? path5.resolve(userConfig.root) : process.cwd();
2064
- const { CLOUDFLARE_ENV } = vite5.loadEnv(viteEnv.mode, root, "");
2100
+ const { CLOUDFLARE_ENV: cloudflareEnv } = vite5.loadEnv(
2101
+ viteEnv.mode,
2102
+ root,
2103
+ /* prefixes */
2104
+ ""
2105
+ );
2065
2106
  const configPath = pluginConfig.configPath ? path5.resolve(root, pluginConfig.configPath) : findWranglerConfig(root);
2066
- assert6(
2107
+ assert7(
2067
2108
  configPath,
2068
2109
  `Config not found. Have you created a wrangler.json(c) or wrangler.toml file?`
2069
2110
  );
2070
- const entryWorkerResolvedConfig = getWorkerConfig(
2071
- configPath,
2072
- CLOUDFLARE_ENV,
2073
- {
2074
- visitedConfigPaths: configPaths,
2075
- isEntryWorker: true
2076
- }
2077
- );
2111
+ const entryWorkerResolvedConfig = getWorkerConfig(configPath, cloudflareEnv, {
2112
+ visitedConfigPaths: configPaths,
2113
+ isEntryWorker: true
2114
+ });
2078
2115
  if (entryWorkerResolvedConfig.type === "assets-only") {
2079
2116
  return {
2080
2117
  type: "assets-only",
@@ -2083,7 +2120,8 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
2083
2120
  persistState,
2084
2121
  rawConfigs: {
2085
2122
  entryWorker: entryWorkerResolvedConfig
2086
- }
2123
+ },
2124
+ cloudflareEnv
2087
2125
  };
2088
2126
  }
2089
2127
  const entryWorkerConfig = entryWorkerResolvedConfig.config;
@@ -2095,13 +2133,13 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
2095
2133
  for (const auxiliaryWorker of pluginConfig.auxiliaryWorkers ?? []) {
2096
2134
  const workerResolvedConfig = getWorkerConfig(
2097
2135
  path5.resolve(root, auxiliaryWorker.configPath),
2098
- CLOUDFLARE_ENV,
2136
+ cloudflareEnv,
2099
2137
  {
2100
2138
  visitedConfigPaths: configPaths
2101
2139
  }
2102
2140
  );
2103
2141
  auxiliaryWorkersResolvedConfigs.push(workerResolvedConfig);
2104
- assert6(
2142
+ assert7(
2105
2143
  workerResolvedConfig.type === "worker",
2106
2144
  "Unexpected error: received AssetsOnlyResult with auxiliary workers."
2107
2145
  );
@@ -2123,7 +2161,8 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
2123
2161
  rawConfigs: {
2124
2162
  entryWorker: entryWorkerResolvedConfig,
2125
2163
  auxiliaryWorkers: auxiliaryWorkersResolvedConfigs
2126
- }
2164
+ },
2165
+ cloudflareEnv
2127
2166
  };
2128
2167
  }
2129
2168
 
@@ -2167,8 +2206,10 @@ ${event.error?.stack || event.error?.message}`,
2167
2206
  workerWebSocket.addEventListener("close", () => {
2168
2207
  clientWebSocket.close();
2169
2208
  });
2170
- clientWebSocket.on("message", (event) => {
2171
- workerWebSocket.send(event);
2209
+ clientWebSocket.on("message", (data, isBinary) => {
2210
+ workerWebSocket.send(
2211
+ isBinary ? Array.isArray(data) ? Buffer.concat(data) : data : data.toString()
2212
+ );
2172
2213
  });
2173
2214
  clientWebSocket.on("error", (error) => {
2174
2215
  logger.error(`WebSocket error:
@@ -2192,211 +2233,361 @@ function cloudflare2(pluginConfig = {}) {
2192
2233
  let resolvedViteConfig;
2193
2234
  let miniflare;
2194
2235
  let workersConfigsWarningShown = false;
2195
- return {
2196
- name: "vite-plugin-cloudflare",
2197
- config(userConfig, env2) {
2198
- if (env2.isPreview) {
2199
- return { appType: "custom" };
2200
- }
2201
- resolvedPluginConfig = resolvePluginConfig(pluginConfig, userConfig, env2);
2202
- if (!workersConfigsWarningShown) {
2203
- workersConfigsWarningShown = true;
2204
- const workersConfigsWarning = getWarningForWorkersConfigs(
2205
- resolvedPluginConfig.rawConfigs
2236
+ return [
2237
+ {
2238
+ name: "vite-plugin-cloudflare",
2239
+ config(userConfig, env2) {
2240
+ if (env2.isPreview) {
2241
+ return { appType: "custom" };
2242
+ }
2243
+ resolvedPluginConfig = resolvePluginConfig(
2244
+ pluginConfig,
2245
+ userConfig,
2246
+ env2
2206
2247
  );
2207
- if (workersConfigsWarning) {
2208
- console.warn(workersConfigsWarning);
2248
+ if (!workersConfigsWarningShown) {
2249
+ workersConfigsWarningShown = true;
2250
+ const workersConfigsWarning = getWarningForWorkersConfigs(
2251
+ resolvedPluginConfig.rawConfigs
2252
+ );
2253
+ if (workersConfigsWarning) {
2254
+ console.warn(workersConfigsWarning);
2255
+ }
2209
2256
  }
2210
- }
2211
- return {
2212
- appType: "custom",
2213
- resolve: {
2214
- alias: getNodeCompatAliases()
2215
- },
2216
- environments: resolvedPluginConfig.type === "workers" ? {
2217
- ...Object.fromEntries(
2218
- Object.entries(resolvedPluginConfig.workers).map(
2219
- ([environmentName, workerConfig]) => {
2220
- return [
2221
- environmentName,
2222
- createCloudflareEnvironmentOptions(
2223
- workerConfig,
2224
- userConfig,
2225
- environmentName
2257
+ return {
2258
+ appType: "custom",
2259
+ environments: resolvedPluginConfig.type === "workers" ? {
2260
+ ...Object.fromEntries(
2261
+ Object.entries(resolvedPluginConfig.workers).map(
2262
+ ([environmentName, workerConfig]) => {
2263
+ return [
2264
+ environmentName,
2265
+ createCloudflareEnvironmentOptions(
2266
+ workerConfig,
2267
+ userConfig,
2268
+ environmentName
2269
+ )
2270
+ ];
2271
+ }
2272
+ )
2273
+ ),
2274
+ client: {
2275
+ build: {
2276
+ outDir: getOutputDirectory(userConfig, "client")
2277
+ }
2278
+ }
2279
+ } : void 0,
2280
+ builder: {
2281
+ async buildApp(builder) {
2282
+ const clientEnvironment = builder.environments.client;
2283
+ const defaultHtmlPath = path6.resolve(
2284
+ builder.config.root,
2285
+ "index.html"
2286
+ );
2287
+ if (clientEnvironment && (clientEnvironment.config.build.rollupOptions.input || fs4.existsSync(defaultHtmlPath))) {
2288
+ await builder.build(clientEnvironment);
2289
+ }
2290
+ if (resolvedPluginConfig.type === "workers") {
2291
+ const workerEnvironments = Object.keys(
2292
+ resolvedPluginConfig.workers
2293
+ ).map((environmentName) => {
2294
+ const environment = builder.environments[environmentName];
2295
+ assert8(
2296
+ environment,
2297
+ `${environmentName} environment not found`
2298
+ );
2299
+ return environment;
2300
+ });
2301
+ await Promise.all(
2302
+ workerEnvironments.map(
2303
+ (environment) => builder.build(environment)
2226
2304
  )
2227
- ];
2305
+ );
2228
2306
  }
2229
- )
2230
- ),
2231
- client: {
2232
- build: {
2233
- outDir: getOutputDirectory(userConfig, "client")
2307
+ writeDeployConfig(resolvedPluginConfig, resolvedViteConfig);
2234
2308
  }
2235
2309
  }
2236
- } : void 0,
2237
- builder: {
2238
- async buildApp(builder) {
2239
- const clientEnvironment = builder.environments.client;
2240
- const defaultHtmlPath = path6.resolve(
2241
- builder.config.root,
2242
- "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"
2243
2333
  );
2244
- if (clientEnvironment && (clientEnvironment.config.build.rollupOptions.input || fs4.existsSync(defaultHtmlPath))) {
2245
- await builder.build(clientEnvironment);
2246
- }
2247
- if (resolvedPluginConfig.type === "workers") {
2248
- const workerEnvironments = Object.keys(
2249
- resolvedPluginConfig.workers
2250
- ).map((environmentName) => {
2251
- const environment = builder.environments[environmentName];
2252
- assert7(environment, `${environmentName} environment not found`);
2253
- 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
2254
2350
  });
2255
- await Promise.all(
2256
- workerEnvironments.map(
2257
- (environment) => builder.build(environment)
2258
- )
2259
- );
2260
2351
  }
2261
- writeDeployConfig(resolvedPluginConfig, resolvedViteConfig);
2262
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;
2263
2364
  }
2264
- };
2265
- },
2266
- configResolved(config) {
2267
- resolvedViteConfig = config;
2268
- },
2269
- async resolveId(source) {
2270
- if (resolvedPluginConfig.type === "assets-only") {
2271
- return;
2272
- }
2273
- const workerConfig = resolvedPluginConfig.workers[this.environment.name];
2274
- if (!workerConfig) {
2275
- return;
2276
- }
2277
- return resolveNodeCompatId(this.environment, workerConfig, source);
2278
- },
2279
- async transform(code, id) {
2280
- if (resolvedPluginConfig.type === "assets-only") {
2281
- return;
2282
- }
2283
- const workerConfig = resolvedPluginConfig.workers[this.environment.name];
2284
- if (!workerConfig) {
2285
- return;
2286
- }
2287
- const resolvedId = await this.resolve(workerConfig.main);
2288
- if (id === resolvedId?.id) {
2289
- return injectGlobalCode(id, code, workerConfig);
2290
- }
2291
- },
2292
- generateBundle(_, bundle) {
2293
- let config;
2294
- if (resolvedPluginConfig.type === "workers") {
2295
- const workerConfig = resolvedPluginConfig.workers[this.environment.name];
2296
- const entryChunk = Object.entries(bundle).find(
2297
- ([_2, chunk]) => chunk.type === "chunk" && chunk.isEntry
2298
- );
2299
- if (!workerConfig || !entryChunk) {
2365
+ if (!config) {
2300
2366
  return;
2301
2367
  }
2302
- workerConfig.main = entryChunk[0];
2303
- const isEntryWorker = this.environment.name === resolvedPluginConfig.entryWorkerEnvironmentName;
2304
- if (isEntryWorker && workerConfig.assets) {
2305
- const workerOutputDirectory = this.environment.config.build.outDir;
2306
- const clientOutputDirectory = resolvedViteConfig.environments.client?.build.outDir;
2307
- assert7(
2308
- clientOutputDirectory,
2309
- "Unexpected error: client output directory is undefined"
2310
- );
2311
- workerConfig.assets.directory = path6.relative(
2312
- path6.resolve(resolvedViteConfig.root, workerOutputDirectory),
2313
- path6.resolve(resolvedViteConfig.root, clientOutputDirectory)
2314
- );
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;
2315
2372
  }
2316
- config = workerConfig;
2317
- } else if (this.environment.name === "client") {
2318
- const assetsOnlyConfig = resolvedPluginConfig.config;
2319
- assetsOnlyConfig.assets.directory = ".";
2320
2373
  this.emitFile({
2321
2374
  type: "asset",
2322
- fileName: ".assetsignore",
2323
- source: "wrangler.json"
2375
+ fileName: "wrangler.json",
2376
+ source: JSON.stringify(config)
2324
2377
  });
2325
- config = assetsOnlyConfig;
2326
- }
2327
- if (!config) {
2328
- return;
2378
+ },
2379
+ handleHotUpdate(options) {
2380
+ if (resolvedPluginConfig.configPaths.has(options.file)) {
2381
+ options.server.restart();
2382
+ }
2383
+ },
2384
+ async buildEnd() {
2385
+ if (miniflare) {
2386
+ await miniflare.dispose();
2387
+ miniflare = void 0;
2388
+ }
2389
+ },
2390
+ async configureServer(viteDevServer) {
2391
+ assert8(
2392
+ viteDevServer.httpServer,
2393
+ "Unexpected error: No Vite HTTP server"
2394
+ );
2395
+ miniflare = new Miniflare(
2396
+ getDevMiniflareOptions(resolvedPluginConfig, viteDevServer)
2397
+ );
2398
+ await initRunners(resolvedPluginConfig, viteDevServer, miniflare);
2399
+ const entryWorker = await getDevEntryWorker(
2400
+ resolvedPluginConfig,
2401
+ miniflare
2402
+ );
2403
+ const middleware = createMiddleware(({ request }) => {
2404
+ return entryWorker.fetch(toMiniflareRequest(request), {
2405
+ redirect: "manual"
2406
+ });
2407
+ });
2408
+ handleWebSocket(
2409
+ viteDevServer.httpServer,
2410
+ entryWorker.fetch,
2411
+ viteDevServer.config.logger
2412
+ );
2413
+ return () => {
2414
+ viteDevServer.middlewares.use((req, res, next) => {
2415
+ middleware(req, res, next);
2416
+ });
2417
+ };
2418
+ },
2419
+ configurePreviewServer(vitePreviewServer) {
2420
+ const miniflare2 = new Miniflare(
2421
+ getPreviewMiniflareOptions(
2422
+ vitePreviewServer,
2423
+ pluginConfig.persistState ?? true
2424
+ )
2425
+ );
2426
+ const middleware = createMiddleware(({ request }) => {
2427
+ return miniflare2.dispatchFetch(toMiniflareRequest(request), {
2428
+ redirect: "manual"
2429
+ });
2430
+ });
2431
+ handleWebSocket(
2432
+ vitePreviewServer.httpServer,
2433
+ miniflare2.dispatchFetch,
2434
+ vitePreviewServer.config.logger
2435
+ );
2436
+ return () => {
2437
+ vitePreviewServer.middlewares.use((req, res, next) => {
2438
+ middleware(req, res, next);
2439
+ });
2440
+ };
2329
2441
  }
2330
- config.no_bundle = true;
2331
- config.rules = [{ type: "ESModule", globs: ["**/*.js"] }];
2332
- config.unsafe = void 0;
2333
- this.emitFile({
2334
- type: "asset",
2335
- fileName: "wrangler.json",
2336
- source: JSON.stringify(config)
2337
- });
2338
2442
  },
2339
- handleHotUpdate(options) {
2340
- if (resolvedPluginConfig.configPaths.has(options.file)) {
2341
- options.server.restart();
2443
+ // Plugin to support `CompiledWasm` modules
2444
+ {
2445
+ name: "vite-plugin-cloudflare:modules",
2446
+ // We set `enforce: "pre"` so that this plugin runs before the Vite core plugins.
2447
+ // Otherwise the `vite:wasm-fallback` plugin prevents the `.wasm` extension being used for module imports.
2448
+ enforce: "pre",
2449
+ applyToEnvironment(environment) {
2450
+ return getWorkerConfig2(environment.name) !== void 0;
2451
+ },
2452
+ async resolveId(source, importer) {
2453
+ if (!source.endsWith(".wasm")) {
2454
+ return;
2455
+ }
2456
+ const resolved = await this.resolve(source, importer);
2457
+ assert8(
2458
+ resolved,
2459
+ `Unexpected error: could not resolve Wasm module ${source}`
2460
+ );
2461
+ return {
2462
+ external: true,
2463
+ id: createModuleReference("CompiledWasm", resolved.id)
2464
+ };
2465
+ },
2466
+ renderChunk(code, chunk) {
2467
+ const moduleRE = new RegExp(MODULE_PATTERN, "g");
2468
+ let match;
2469
+ let magicString;
2470
+ while (match = moduleRE.exec(code)) {
2471
+ magicString ??= new MagicString(code);
2472
+ const [full, moduleType, modulePath] = match;
2473
+ assert8(
2474
+ modulePath,
2475
+ `Unexpected error: module path not found in reference ${full}.`
2476
+ );
2477
+ let source;
2478
+ try {
2479
+ source = fs4.readFileSync(modulePath);
2480
+ } catch (error) {
2481
+ throw new Error(
2482
+ `Import ${modulePath} not found. Does the file exist?`
2483
+ );
2484
+ }
2485
+ const referenceId = this.emitFile({
2486
+ type: "asset",
2487
+ name: path6.basename(modulePath),
2488
+ originalFileName: modulePath,
2489
+ source
2490
+ });
2491
+ const emittedFileName = this.getFileName(referenceId);
2492
+ const relativePath = vite6.normalizePath(
2493
+ path6.relative(path6.dirname(chunk.fileName), emittedFileName)
2494
+ );
2495
+ const importPath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
2496
+ magicString.update(
2497
+ match.index,
2498
+ match.index + full.length,
2499
+ importPath
2500
+ );
2501
+ }
2502
+ if (magicString) {
2503
+ return {
2504
+ code: magicString.toString(),
2505
+ map: this.environment.config.build.sourcemap ? magicString.generateMap({ hires: "boundary" }) : null
2506
+ };
2507
+ }
2342
2508
  }
2343
2509
  },
2344
- async buildEnd() {
2345
- if (miniflare) {
2346
- await miniflare.dispose();
2347
- miniflare = void 0;
2510
+ // Plugin that can provide Node.js compatibility support for Vite Environments that are hosted in Cloudflare Workers.
2511
+ {
2512
+ name: "vite-plugin-cloudflare:nodejs-compat",
2513
+ apply(_config, env2) {
2514
+ return !env2.isPreview;
2515
+ },
2516
+ config() {
2517
+ return {
2518
+ resolve: {
2519
+ alias: getNodeCompatAliases()
2520
+ }
2521
+ };
2522
+ },
2523
+ configEnvironment(environmentName) {
2524
+ const workerConfig = getWorkerConfig2(environmentName);
2525
+ if (isNodeCompat(workerConfig)) {
2526
+ return {
2527
+ build: {
2528
+ rollupOptions: {
2529
+ external: getNodeCompatExternals()
2530
+ }
2531
+ }
2532
+ };
2533
+ }
2534
+ },
2535
+ async resolveId(source, importer, options) {
2536
+ const from = maybeStripNodeJsVirtualPrefix(source);
2537
+ if (!from) {
2538
+ return;
2539
+ }
2540
+ const workerConfig = getWorkerConfig2(this.environment.name);
2541
+ if (!isNodeCompat(workerConfig)) {
2542
+ return this.resolve(from, importer, options);
2543
+ }
2544
+ const unresolvedAlias = dealiasVirtualNodeJSImport(from);
2545
+ const resolvedAlias = await this.resolve(
2546
+ unresolvedAlias,
2547
+ import.meta.url
2548
+ );
2549
+ assert8(
2550
+ resolvedAlias,
2551
+ "Failed to resolve aliased nodejs import: " + unresolvedAlias
2552
+ );
2553
+ if (this.environment.mode === "dev" && this.environment.depsOptimizer) {
2554
+ this.environment.depsOptimizer.registerMissingImport(
2555
+ unresolvedAlias,
2556
+ resolvedAlias.id
2557
+ );
2558
+ }
2559
+ return resolvedAlias;
2560
+ },
2561
+ async transform(code, id) {
2562
+ const workerConfig = getWorkerConfig2(this.environment.name);
2563
+ if (!isNodeCompat(workerConfig)) {
2564
+ return;
2565
+ }
2566
+ const resolvedId = await this.resolve(workerConfig.main);
2567
+ if (id === resolvedId?.id) {
2568
+ return injectGlobalCode(id, code);
2569
+ }
2348
2570
  }
2349
- },
2350
- async configureServer(viteDevServer) {
2351
- assert7(viteDevServer.httpServer, "Unexpected error: No Vite HTTP server");
2352
- miniflare = new Miniflare(
2353
- getDevMiniflareOptions(resolvedPluginConfig, viteDevServer)
2354
- );
2355
- await initRunners(resolvedPluginConfig, viteDevServer, miniflare);
2356
- const entryWorker = await getDevEntryWorker(
2357
- resolvedPluginConfig,
2358
- miniflare
2359
- );
2360
- const middleware = createMiddleware(({ request }) => {
2361
- return entryWorker.fetch(toMiniflareRequest(request), {
2362
- redirect: "manual"
2363
- });
2364
- });
2365
- handleWebSocket(
2366
- viteDevServer.httpServer,
2367
- entryWorker.fetch,
2368
- viteDevServer.config.logger
2369
- );
2370
- return () => {
2371
- viteDevServer.middlewares.use((req, res, next) => {
2372
- middleware(req, res, next);
2373
- });
2374
- };
2375
- },
2376
- configurePreviewServer(vitePreviewServer) {
2377
- const miniflare2 = new Miniflare(
2378
- getPreviewMiniflareOptions(
2379
- vitePreviewServer,
2380
- pluginConfig.persistState ?? true
2381
- )
2382
- );
2383
- const middleware = createMiddleware(({ request }) => {
2384
- return miniflare2.dispatchFetch(toMiniflareRequest(request), {
2385
- redirect: "manual"
2386
- });
2387
- });
2388
- handleWebSocket(
2389
- vitePreviewServer.httpServer,
2390
- miniflare2.dispatchFetch,
2391
- vitePreviewServer.config.logger
2392
- );
2393
- return () => {
2394
- vitePreviewServer.middlewares.use((req, res, next) => {
2395
- middleware(req, res, next);
2396
- });
2397
- };
2398
2571
  }
2399
- };
2572
+ ];
2573
+ function getWorkerConfig2(environmentName) {
2574
+ assert8(resolvedPluginConfig, "Expected resolvedPluginConfig to be defined");
2575
+ return resolvedPluginConfig.type !== "assets-only" ? resolvedPluginConfig.workers[environmentName] : void 0;
2576
+ }
2577
+ }
2578
+ function getDotDevDotVarsContent(configPath, cloudflareEnv) {
2579
+ const configDir = path6.dirname(configPath);
2580
+ const defaultDotDevDotVarsPath = `${configDir}/.dev.vars`;
2581
+ const inputDotDevDotVarsPath = `${defaultDotDevDotVarsPath}${cloudflareEnv ? `.${cloudflareEnv}` : ""}`;
2582
+ const targetPath = fs4.existsSync(inputDotDevDotVarsPath) ? inputDotDevDotVarsPath : fs4.existsSync(defaultDotDevDotVarsPath) ? defaultDotDevDotVarsPath : null;
2583
+ if (targetPath) {
2584
+ const dotDevDotVarsContent = fs4.readFileSync(targetPath);
2585
+ return dotDevDotVarsContent;
2586
+ }
2587
+ return null;
2588
+ }
2589
+ function createModuleReference(type, id) {
2590
+ return `__CLOUDFLARE_MODULE__${type}__${id}__`;
2400
2591
  }
2401
2592
  export {
2402
2593
  cloudflare2 as cloudflare