@cloudflare/vite-plugin 0.0.0-910007bce → 0.0.0-91d0c408c

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
@@ -485,11 +485,12 @@ var require_mime = __commonJS({
485
485
  });
486
486
 
487
487
  // src/index.ts
488
- import assert8 from "node:assert";
488
+ import assert10 from "node:assert";
489
489
  import * as fs5 from "node:fs";
490
490
  import * as fsp2 from "node:fs/promises";
491
491
  import * as path9 from "node:path";
492
- import { createMiddleware } from "@hattip/adapter-node";
492
+ import { createRequest, sendResponse } from "@mjackson/node-fetch-server";
493
+ import replace from "@rollup/plugin-replace";
493
494
 
494
495
  // ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.5.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
495
496
  var comma = ",".charCodeAt(0);
@@ -1557,6 +1558,7 @@ var MagicString = class _MagicString {
1557
1558
 
1558
1559
  // src/index.ts
1559
1560
  import { Miniflare } from "miniflare";
1561
+ import colors3 from "picocolors";
1560
1562
  import * as vite7 from "vite";
1561
1563
 
1562
1564
  // src/constants.ts
@@ -5782,7 +5784,8 @@ var z = /* @__PURE__ */ Object.freeze({
5782
5784
  // ../workers-shared/utils/types.ts
5783
5785
  var InternalConfigSchema = z.object({
5784
5786
  account_id: z.number().optional(),
5785
- script_id: z.number().optional()
5787
+ script_id: z.number().optional(),
5788
+ debug: z.boolean().optional()
5786
5789
  });
5787
5790
  var RouterConfigSchema = z.object({
5788
5791
  invoke_user_worker_ahead_of_assets: z.boolean().optional(),
@@ -5830,14 +5833,14 @@ var AssetConfigSchema = z.object({
5830
5833
  });
5831
5834
 
5832
5835
  // src/asset-config.ts
5833
- function hasAssetsConfigChanged(resolvedPluginConfig, resolvedViteConfig, changedFile) {
5836
+ function hasAssetsConfigChanged(resolvedPluginConfig, resolvedViteConfig, changedFilePath) {
5834
5837
  if (!resolvedPluginConfig.experimental?.headersAndRedirectsDevModeSupport) {
5835
5838
  return false;
5836
5839
  }
5837
5840
  return [
5838
5841
  getRedirectsConfigPath(resolvedViteConfig),
5839
5842
  getHeadersConfigPath(resolvedViteConfig)
5840
- ].includes(path.resolve(changedFile));
5843
+ ].includes(changedFilePath);
5841
5844
  }
5842
5845
  function getAssetsConfig(resolvedPluginConfig, entryWorkerConfig, resolvedConfig) {
5843
5846
  const assetsConfig = resolvedPluginConfig.type === "assets-only" ? resolvedPluginConfig.config.assets : entryWorkerConfig?.assets;
@@ -12878,6 +12881,15 @@ function isNodeCompat(workerConfig) {
12878
12881
  }
12879
12882
  return false;
12880
12883
  }
12884
+ function isNodeAls(workerConfig) {
12885
+ return workerConfig !== void 0 && getNodeCompat(
12886
+ workerConfig.compatibility_date,
12887
+ workerConfig.compatibility_flags ?? []
12888
+ ).mode === "als";
12889
+ }
12890
+ function isNodeAlsModule(path10) {
12891
+ return /^(node:)?async_hooks$/.test(path10);
12892
+ }
12881
12893
  function injectGlobalCode(id, code) {
12882
12894
  const injectedCode = Object.entries(env.inject).map(([globalName, globalInject]) => {
12883
12895
  if (typeof globalInject === "string") {
@@ -12908,7 +12920,7 @@ globalThis.${globalName} = var_${globalName}.${exportName};
12908
12920
  }
12909
12921
  function resolveNodeJSImport(source) {
12910
12922
  const alias = env.alias[source];
12911
- if (alias) {
12923
+ if (alias && !nodeCompatExternals.has(alias)) {
12912
12924
  return {
12913
12925
  unresolved: alias,
12914
12926
  resolved: resolvePathSync(alias, { url: import.meta.url })
@@ -12939,8 +12951,9 @@ function getNodeCompatEntries() {
12939
12951
  return entries;
12940
12952
  }
12941
12953
  var NodeJsCompatWarnings = class {
12942
- constructor(environment) {
12943
- this.environment = environment;
12954
+ constructor(environmentName, resolvedViteConfig) {
12955
+ this.environmentName = environmentName;
12956
+ this.resolvedViteConfig = resolvedViteConfig;
12944
12957
  }
12945
12958
  sources = /* @__PURE__ */ new Map();
12946
12959
  timer;
@@ -12948,6 +12961,7 @@ var NodeJsCompatWarnings = class {
12948
12961
  const importers = this.sources.get(source) ?? /* @__PURE__ */ new Set();
12949
12962
  this.sources.set(source, importers);
12950
12963
  importers.add(importer);
12964
+ this.renderWarningsOnIdle();
12951
12965
  }
12952
12966
  renderWarningsOnIdle() {
12953
12967
  if (this.timer) {
@@ -12960,19 +12974,16 @@ var NodeJsCompatWarnings = class {
12960
12974
  }
12961
12975
  renderWarnings() {
12962
12976
  if (this.sources.size > 0) {
12963
- let message = `
12964
-
12965
- Unexpected Node.js imports for environment "${this.environment.name}". Do you need to enable the "nodejs_compat" compatibility flag?
12966
- Refer to https://developers.cloudflare.com/workers/runtime-apis/nodejs/ for more details.
12977
+ let message = `Unexpected Node.js imports for environment "${this.environmentName}". Do you need to enable the "nodejs_compat" compatibility flag? Refer to https://developers.cloudflare.com/workers/runtime-apis/nodejs/ for more details.
12967
12978
  `;
12968
12979
  this.sources.forEach((importers, source) => {
12969
12980
  importers.forEach((importer) => {
12970
- message += ` - "${source}" imported from "${path3.relative(this.environment.config.root, importer)}"
12981
+ message += ` - "${source}" imported from "${path3.relative(this.resolvedViteConfig.root, importer)}"
12971
12982
  `;
12972
12983
  });
12973
12984
  });
12974
- this.environment.logger.warn(message, {
12975
- environment: this.environment.name
12985
+ this.resolvedViteConfig.logger.warn(message, {
12986
+ timestamp: true
12976
12987
  });
12977
12988
  this.sources.clear();
12978
12989
  }
@@ -12992,6 +13003,7 @@ var VITE_DEV_METADATA_HEADER = "__VITE_DEV_METADATA__";
12992
13003
 
12993
13004
  // src/utils.ts
12994
13005
  import * as path4 from "node:path";
13006
+ import getPort, { portNumbers } from "get-port";
12995
13007
  import { Request as MiniflareRequest } from "miniflare";
12996
13008
  import "vite";
12997
13009
  function getOutputDirectory(userConfig, environmentName) {
@@ -13002,6 +13014,10 @@ function getRouterWorker(miniflare2) {
13002
13014
  return miniflare2.getWorker(ROUTER_WORKER_NAME);
13003
13015
  }
13004
13016
  function toMiniflareRequest(request) {
13017
+ const host = request.headers.get("Host");
13018
+ if (host) {
13019
+ request.headers.set("X-Forwarded-Host", host);
13020
+ }
13005
13021
  const secFetchMode = request.headers.get("Sec-Fetch-Mode");
13006
13022
  if (secFetchMode) {
13007
13023
  request.headers.set("X-Mf-Sec-Fetch-Mode", secFetchMode);
@@ -13030,6 +13046,9 @@ var postfixRE = /[?#].*$/;
13030
13046
  function cleanUrl(url) {
13031
13047
  return url.replace(postfixRE, "");
13032
13048
  }
13049
+ function getFirstAvailablePort(start) {
13050
+ return getPort({ port: portNumbers(start, 65535) });
13051
+ }
13033
13052
 
13034
13053
  // src/cloudflare-environment.ts
13035
13054
  var webSocketUndefinedError = "The WebSocket is undefined";
@@ -13336,6 +13355,7 @@ import {
13336
13355
  LogLevel,
13337
13356
  Response as MiniflareResponse
13338
13357
  } from "miniflare";
13358
+ import colors2 from "picocolors";
13339
13359
  import { globSync } from "tinyglobby";
13340
13360
  import "vite";
13341
13361
  import { unstable_getMiniflareWorkerOptions } from "wrangler";
@@ -13440,7 +13460,30 @@ function getEntryWorkerConfig(resolvedPluginConfig) {
13440
13460
  }
13441
13461
  return resolvedPluginConfig.workers[resolvedPluginConfig.entryWorkerEnvironmentName];
13442
13462
  }
13443
- function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer) {
13463
+ function filterTails(tails, userWorkers, log) {
13464
+ return tails?.filter((tailService) => {
13465
+ let name;
13466
+ if (typeof tailService === "string") {
13467
+ name = tailService;
13468
+ } else if (typeof tailService === "object" && "name" in tailService && typeof tailService.name === "string") {
13469
+ name = tailService.name;
13470
+ } else {
13471
+ return true;
13472
+ }
13473
+ const found = userWorkers.some((w) => w.name === name);
13474
+ if (!found) {
13475
+ log(
13476
+ colors2.dim(
13477
+ colors2.yellow(
13478
+ `Tail consumer "${name}" was not found in your config. Make sure you add it if you'd like to simulate receiving tail events locally.`
13479
+ )
13480
+ )
13481
+ );
13482
+ }
13483
+ return found;
13484
+ });
13485
+ }
13486
+ function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer, inspectorPort) {
13444
13487
  const resolvedViteConfig = viteDevServer.config;
13445
13488
  const entryWorkerConfig = getEntryWorkerConfig(resolvedPluginConfig);
13446
13489
  const assetsConfig = getAssetsConfig(
@@ -13532,7 +13575,7 @@ function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer) {
13532
13575
  worker: {
13533
13576
  ...workerOptions,
13534
13577
  name: workerOptions.name ?? workerConfig.name,
13535
- unsafeInspectorProxy: resolvedPluginConfig.inspectorPort !== false,
13578
+ unsafeInspectorProxy: inspectorPort !== false,
13536
13579
  modulesRoot: miniflareModulesRoot,
13537
13580
  unsafeEvalBinding: "__VITE_UNSAFE_EVAL__",
13538
13581
  serviceBindings: {
@@ -13574,8 +13617,8 @@ function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer) {
13574
13617
  const logger = new ViteMiniflareLogger(resolvedViteConfig);
13575
13618
  return {
13576
13619
  log: logger,
13577
- inspectorPort: resolvedPluginConfig.inspectorPort || void 0,
13578
- unsafeInspectorProxy: resolvedPluginConfig.inspectorPort !== false,
13620
+ inspectorPort: inspectorPort === false ? void 0 : inspectorPort,
13621
+ unsafeInspectorProxy: inspectorPort !== false,
13579
13622
  handleRuntimeStdio(stdout, stderr) {
13580
13623
  const decoder = new TextDecoder();
13581
13624
  stdout.forEach((data2) => logger.info(decoder.decode(data2)));
@@ -13631,6 +13674,11 @@ function getDevMiniflareOptions(resolvedPluginConfig, viteDevServer) {
13631
13674
  }
13632
13675
  return {
13633
13676
  ...workerOptions,
13677
+ tails: filterTails(
13678
+ workerOptions.tails,
13679
+ userWorkers,
13680
+ viteDevServer.config.logger.warn
13681
+ ),
13634
13682
  modules: [
13635
13683
  {
13636
13684
  type: "ESModule",
@@ -13712,7 +13760,7 @@ function getPreviewModules(main, modulesRules) {
13712
13760
  ]
13713
13761
  };
13714
13762
  }
13715
- function getPreviewMiniflareOptions(vitePreviewServer, workerConfigs, persistState, inspectorPort = DEFAULT_INSPECTOR_PORT) {
13763
+ function getPreviewMiniflareOptions(vitePreviewServer, workerConfigs, persistState, inspectorPort) {
13716
13764
  const resolvedViteConfig = vitePreviewServer.config;
13717
13765
  const workers = workerConfigs.flatMap((config) => {
13718
13766
  const miniflareWorkerOptions = unstable_getMiniflareWorkerOptions(config);
@@ -13721,6 +13769,11 @@ function getPreviewMiniflareOptions(vitePreviewServer, workerConfigs, persistSta
13721
13769
  return [
13722
13770
  {
13723
13771
  ...workerOptions,
13772
+ tails: filterTails(
13773
+ workerOptions.tails,
13774
+ workerConfigs,
13775
+ vitePreviewServer.config.logger.warn
13776
+ ),
13724
13777
  name: workerOptions.name ?? config.name,
13725
13778
  unsafeInspectorProxy: inspectorPort !== false,
13726
13779
  ...miniflareWorkerOptions.main ? getPreviewModules(miniflareWorkerOptions.main, modulesRules) : { modules: true, script: "" }
@@ -13731,7 +13784,7 @@ function getPreviewMiniflareOptions(vitePreviewServer, workerConfigs, persistSta
13731
13784
  const logger = new ViteMiniflareLogger(resolvedViteConfig);
13732
13785
  return {
13733
13786
  log: logger,
13734
- inspectorPort: inspectorPort || void 0,
13787
+ inspectorPort: inspectorPort === false ? void 0 : inspectorPort,
13735
13788
  unsafeInspectorProxy: inspectorPort !== false,
13736
13789
  handleRuntimeStdio(stdout, stderr) {
13737
13790
  const decoder = new TextDecoder();
@@ -13781,11 +13834,12 @@ function miniflareLogLevelFromViteLogLevel(level = "info") {
13781
13834
  }
13782
13835
 
13783
13836
  // src/plugin-config.ts
13784
- import assert7 from "node:assert";
13837
+ import assert8 from "node:assert";
13785
13838
  import * as path8 from "node:path";
13786
13839
  import * as vite6 from "vite";
13787
13840
 
13788
13841
  // src/workers-configs.ts
13842
+ import assert7 from "node:assert";
13789
13843
  import * as fs4 from "node:fs";
13790
13844
  import * as path7 from "node:path";
13791
13845
  import { unstable_readConfig as unstable_readConfig2 } from "wrangler";
@@ -13819,8 +13873,7 @@ var nonApplicableWorkerConfigs = {
13819
13873
  "preserve_file_names",
13820
13874
  "rules",
13821
13875
  "site",
13822
- "tsconfig",
13823
- "upload_source_maps"
13876
+ "tsconfig"
13824
13877
  ]
13825
13878
  };
13826
13879
  var nullableNonApplicable = [
@@ -13831,8 +13884,7 @@ var nullableNonApplicable = [
13831
13884
  "no_bundle",
13832
13885
  "preserve_file_names",
13833
13886
  "site",
13834
- "tsconfig",
13835
- "upload_source_maps"
13887
+ "tsconfig"
13836
13888
  ];
13837
13889
  function readWorkerConfig(configPath, env2) {
13838
13890
  const nonApplicable = {
@@ -13994,14 +14046,52 @@ function getWorkerConfig(configPath, env2, opts) {
13994
14046
  nonApplicable
13995
14047
  };
13996
14048
  }
14049
+ function getValidatedWranglerConfigPath(root, requestedConfigPath, isForAuxiliaryWorker = false) {
14050
+ if (requestedConfigPath) {
14051
+ const configPath2 = path7.resolve(root, requestedConfigPath);
14052
+ const forAuxiliaryWorkerErrorMessage = isForAuxiliaryWorker ? " requested for one of your auxiliary workers" : "";
14053
+ const errorMessagePrefix = `The provided configPath (${configPath2})${forAuxiliaryWorkerErrorMessage}`;
14054
+ const fileExtension = path7.extname(configPath2).slice(1);
14055
+ if (!allowedWranglerConfigExtensions.includes(fileExtension)) {
14056
+ const foundExtensionMessage = !fileExtension ? "no extension found" : `"${fileExtension}" found`;
14057
+ throw new Error(
14058
+ `${errorMessagePrefix} doesn't point to a file with the correct file extension. It should point to a jsonc, json or toml file (${foundExtensionMessage} instead)`
14059
+ );
14060
+ }
14061
+ const mainStat = fs4.statSync(configPath2, { throwIfNoEntry: false });
14062
+ if (!mainStat) {
14063
+ throw new Error(
14064
+ `${errorMessagePrefix} doesn't point to an existing file`
14065
+ );
14066
+ }
14067
+ if (mainStat.isDirectory()) {
14068
+ throw new Error(
14069
+ `${errorMessagePrefix} points to a directory. It should point to a file.`
14070
+ );
14071
+ }
14072
+ return configPath2;
14073
+ }
14074
+ assert7(
14075
+ isForAuxiliaryWorker === false,
14076
+ "Unexpected Error: trying to find the wrangler config for an auxiliary worker"
14077
+ );
14078
+ const configPath = findWranglerConfig(root);
14079
+ if (!configPath) {
14080
+ throw new Error(
14081
+ `No config file found in the ${root} directory. Please add a wrangler.(jsonc|json|toml) file.`
14082
+ );
14083
+ }
14084
+ return configPath;
14085
+ }
13997
14086
  function findWranglerConfig(root) {
13998
- for (const extension of ["json", "jsonc", "toml"]) {
14087
+ for (const extension of allowedWranglerConfigExtensions) {
13999
14088
  const configPath = path7.join(root, `wrangler.${extension}`);
14000
14089
  if (fs4.existsSync(configPath)) {
14001
14090
  return configPath;
14002
14091
  }
14003
14092
  }
14004
14093
  }
14094
+ var allowedWranglerConfigExtensions = ["jsonc", "json", "toml"];
14005
14095
 
14006
14096
  // src/plugin-config.ts
14007
14097
  function workerNameToEnvironmentName(workerName) {
@@ -14010,7 +14100,6 @@ function workerNameToEnvironmentName(workerName) {
14010
14100
  function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
14011
14101
  const configPaths = /* @__PURE__ */ new Set();
14012
14102
  const persistState = pluginConfig.persistState ?? true;
14013
- const inspectorPort = pluginConfig.inspectorPort ?? DEFAULT_INSPECTOR_PORT;
14014
14103
  const experimental = pluginConfig.experimental ?? {};
14015
14104
  const root = userConfig.root ? path8.resolve(userConfig.root) : process.cwd();
14016
14105
  const { CLOUDFLARE_ENV: cloudflareEnv } = vite6.loadEnv(
@@ -14019,22 +14108,23 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
14019
14108
  /* prefixes */
14020
14109
  ""
14021
14110
  );
14022
- const configPath = pluginConfig.configPath ? path8.resolve(root, pluginConfig.configPath) : findWranglerConfig(root);
14023
- if (!configPath) {
14024
- throw new Error(
14025
- `Config not found. Have you created a wrangler.json(c) or wrangler.toml file?`
14026
- );
14027
- }
14028
- const entryWorkerResolvedConfig = getWorkerConfig(configPath, cloudflareEnv, {
14029
- visitedConfigPaths: configPaths,
14030
- isEntryWorker: true
14031
- });
14111
+ const entryWorkerConfigPath = getValidatedWranglerConfigPath(
14112
+ root,
14113
+ pluginConfig.configPath
14114
+ );
14115
+ const entryWorkerResolvedConfig = getWorkerConfig(
14116
+ entryWorkerConfigPath,
14117
+ cloudflareEnv,
14118
+ {
14119
+ visitedConfigPaths: configPaths,
14120
+ isEntryWorker: true
14121
+ }
14122
+ );
14032
14123
  if (entryWorkerResolvedConfig.type === "assets-only") {
14033
14124
  return {
14034
14125
  type: "assets-only",
14035
14126
  config: entryWorkerResolvedConfig.config,
14036
14127
  configPaths,
14037
- inspectorPort,
14038
14128
  persistState,
14039
14129
  rawConfigs: {
14040
14130
  entryWorker: entryWorkerResolvedConfig
@@ -14050,15 +14140,20 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
14050
14140
  };
14051
14141
  const auxiliaryWorkersResolvedConfigs = [];
14052
14142
  for (const auxiliaryWorker of pluginConfig.auxiliaryWorkers ?? []) {
14143
+ const workerConfigPath = getValidatedWranglerConfigPath(
14144
+ root,
14145
+ auxiliaryWorker.configPath,
14146
+ true
14147
+ );
14053
14148
  const workerResolvedConfig = getWorkerConfig(
14054
- path8.resolve(root, auxiliaryWorker.configPath),
14149
+ workerConfigPath,
14055
14150
  cloudflareEnv,
14056
14151
  {
14057
14152
  visitedConfigPaths: configPaths
14058
14153
  }
14059
14154
  );
14060
14155
  auxiliaryWorkersResolvedConfigs.push(workerResolvedConfig);
14061
- assert7(
14156
+ assert8(
14062
14157
  workerResolvedConfig.type === "worker",
14063
14158
  "Unexpected error: received AssetsOnlyResult with auxiliary workers."
14064
14159
  );
@@ -14075,7 +14170,6 @@ function resolvePluginConfig(pluginConfig, userConfig, viteEnv) {
14075
14170
  type: "workers",
14076
14171
  configPaths,
14077
14172
  persistState,
14078
- inspectorPort,
14079
14173
  workers,
14080
14174
  entryWorkerEnvironmentName,
14081
14175
  rawConfigs: {
@@ -14123,6 +14217,57 @@ function handleWebSocket(httpServer, getFetcher) {
14123
14217
  );
14124
14218
  }
14125
14219
 
14220
+ // src/worker-environments-validation.ts
14221
+ import assert9 from "node:assert";
14222
+ function validateWorkerEnvironmentsResolvedConfigs(resolvedPluginConfig, resolvedViteConfig) {
14223
+ const workersEnvironmentNames = Object.keys(resolvedPluginConfig.workers);
14224
+ const disallowedEnvsConfigs = /* @__PURE__ */ new Map();
14225
+ for (const envName of workersEnvironmentNames) {
14226
+ const workerEnvConfig = resolvedViteConfig.environments[envName];
14227
+ assert9(workerEnvConfig, `Missing environment config for "${envName}"`);
14228
+ const { optimizeDeps, resolve: resolve7 } = workerEnvConfig;
14229
+ const disallowedConfig = {};
14230
+ const disallowedOptimizeDepsExcludeEntries = (optimizeDeps.exclude ?? []).filter((entry) => {
14231
+ if (cloudflareBuiltInModules.includes(entry)) {
14232
+ return false;
14233
+ }
14234
+ if (isNodeAlsModule(entry) && isNodeAls(resolvedPluginConfig.workers[envName])) {
14235
+ return false;
14236
+ }
14237
+ if (NODEJS_MODULES_RE.test(entry) && isNodeCompat(resolvedPluginConfig.workers[envName])) {
14238
+ return false;
14239
+ }
14240
+ return true;
14241
+ });
14242
+ if (disallowedOptimizeDepsExcludeEntries.length > 0) {
14243
+ disallowedConfig.optimizeDepsExclude = disallowedOptimizeDepsExcludeEntries;
14244
+ }
14245
+ if (resolve7.external === true || resolve7.external.length > 0) {
14246
+ disallowedConfig.resolveExternal = resolve7.external;
14247
+ }
14248
+ if (Object.keys(disallowedConfig).length > 0) {
14249
+ disallowedEnvsConfigs.set(envName, disallowedConfig);
14250
+ }
14251
+ }
14252
+ if (disallowedEnvsConfigs.size > 0) {
14253
+ const errorMessage = `The following environment configurations are incompatible with the Cloudflare Vite plugin:
14254
+ ${[
14255
+ ...disallowedEnvsConfigs
14256
+ ].map(
14257
+ ([envName, disallowedConfig]) => [
14258
+ disallowedConfig.optimizeDepsExclude ? ` - "${envName}" environment: \`optimizeDeps.exclude\`: ${JSON.stringify(disallowedConfig.optimizeDepsExclude)}
14259
+ ` : null,
14260
+ disallowedConfig.resolveExternal ? ` - "${envName}" environment: \`resolve.external\`: ${JSON.stringify(disallowedConfig.resolveExternal)}
14261
+ ` : null
14262
+ ].join("")
14263
+ ).join(
14264
+ ""
14265
+ )}To resolve this issue, avoid setting \`optimizeDeps.exclude\` and \`resolve.external\` in your Cloudflare Worker environments.
14266
+ `;
14267
+ throw new Error(errorMessage);
14268
+ }
14269
+ }
14270
+
14126
14271
  // src/index.ts
14127
14272
  var workersConfigsWarningShown = false;
14128
14273
  var miniflare;
@@ -14193,7 +14338,7 @@ function cloudflare2(pluginConfig = {}) {
14193
14338
  resolvedPluginConfig.workers
14194
14339
  ).map((environmentName) => {
14195
14340
  const environment = builder.environments[environmentName];
14196
- assert8(
14341
+ assert10(
14197
14342
  environment,
14198
14343
  `${environmentName} environment not found`
14199
14344
  );
@@ -14214,6 +14359,12 @@ function cloudflare2(pluginConfig = {}) {
14214
14359
  },
14215
14360
  configResolved(config) {
14216
14361
  resolvedViteConfig = config;
14362
+ if (resolvedPluginConfig?.type === "workers") {
14363
+ validateWorkerEnvironmentsResolvedConfigs(
14364
+ resolvedPluginConfig,
14365
+ resolvedViteConfig
14366
+ );
14367
+ }
14217
14368
  },
14218
14369
  generateBundle(_, bundle) {
14219
14370
  let config;
@@ -14234,7 +14385,7 @@ function cloudflare2(pluginConfig = {}) {
14234
14385
  if (isEntryWorker && hasClientBuild) {
14235
14386
  const workerOutputDirectory = this.environment.config.build.outDir;
14236
14387
  const clientOutputDirectory = resolvedViteConfig.environments.client?.build.outDir;
14237
- assert8(
14388
+ assert10(
14238
14389
  clientOutputDirectory,
14239
14390
  "Unexpected error: client output directory is undefined"
14240
14391
  );
@@ -14298,78 +14449,100 @@ function cloudflare2(pluginConfig = {}) {
14298
14449
  }
14299
14450
  },
14300
14451
  hotUpdate(options) {
14301
- if (
14302
- // Vite normalizes `options.file` so we use `path.resolve` for Windows compatibility
14303
- resolvedPluginConfig.configPaths.has(path9.resolve(options.file)) || hasAssetsConfigChanged(
14304
- resolvedPluginConfig,
14305
- resolvedViteConfig,
14306
- options.file
14307
- )
14308
- ) {
14452
+ const changedFilePath = path9.resolve(options.file);
14453
+ if (resolvedPluginConfig.configPaths.has(changedFilePath) || hasDotDevDotVarsFileChanged(resolvedPluginConfig, changedFilePath) || hasAssetsConfigChanged(
14454
+ resolvedPluginConfig,
14455
+ resolvedViteConfig,
14456
+ changedFilePath
14457
+ )) {
14309
14458
  options.server.restart();
14310
14459
  return [];
14311
14460
  }
14312
14461
  },
14313
14462
  async configureServer(viteDevServer) {
14314
- assert8(
14315
- viteDevServer.httpServer,
14316
- "Unexpected error: No Vite HTTP server"
14463
+ const inputInspectorPort = await getInputInspectorPortOption(
14464
+ pluginConfig,
14465
+ viteDevServer
14317
14466
  );
14318
- if (miniflare) {
14319
- await miniflare.setOptions(
14320
- getDevMiniflareOptions(resolvedPluginConfig, viteDevServer)
14467
+ if (!miniflare) {
14468
+ miniflare = new Miniflare(
14469
+ getDevMiniflareOptions(
14470
+ resolvedPluginConfig,
14471
+ viteDevServer,
14472
+ inputInspectorPort
14473
+ )
14321
14474
  );
14322
14475
  } else {
14323
- miniflare = new Miniflare(
14324
- getDevMiniflareOptions(resolvedPluginConfig, viteDevServer)
14476
+ await miniflare.setOptions(
14477
+ getDevMiniflareOptions(
14478
+ resolvedPluginConfig,
14479
+ viteDevServer,
14480
+ inputInspectorPort
14481
+ )
14325
14482
  );
14326
14483
  }
14327
14484
  await initRunners(resolvedPluginConfig, viteDevServer, miniflare);
14328
- const middleware = createMiddleware(
14329
- async ({ request }) => {
14330
- assert8(miniflare, `Miniflare not defined`);
14485
+ if (viteDevServer.httpServer) {
14486
+ handleWebSocket(viteDevServer.httpServer, async () => {
14487
+ assert10(miniflare, `Miniflare not defined`);
14331
14488
  const routerWorker = await getRouterWorker(miniflare);
14332
- return routerWorker.fetch(toMiniflareRequest(request), {
14333
- redirect: "manual"
14334
- });
14335
- },
14336
- { alwaysCallNext: false }
14337
- );
14338
- handleWebSocket(viteDevServer.httpServer, async () => {
14339
- assert8(miniflare, `Miniflare not defined`);
14340
- const routerWorker = await getRouterWorker(miniflare);
14341
- return routerWorker.fetch;
14342
- });
14489
+ return routerWorker.fetch;
14490
+ });
14491
+ }
14343
14492
  return () => {
14344
- viteDevServer.middlewares.use((req, res, next) => {
14345
- middleware(req, res, next);
14493
+ viteDevServer.middlewares.use(async (req, res, next) => {
14494
+ try {
14495
+ assert10(miniflare, `Miniflare not defined`);
14496
+ const routerWorker = await getRouterWorker(miniflare);
14497
+ const request = createRequest(req, res);
14498
+ const response = await routerWorker.fetch(
14499
+ toMiniflareRequest(request),
14500
+ {
14501
+ redirect: "manual"
14502
+ }
14503
+ );
14504
+ if (req.httpVersionMajor === 2) {
14505
+ response.headers.delete("transfer-encoding");
14506
+ }
14507
+ await sendResponse(res, response);
14508
+ } catch (error) {
14509
+ next(error);
14510
+ }
14346
14511
  });
14347
14512
  };
14348
14513
  },
14349
- configurePreviewServer(vitePreviewServer) {
14514
+ async configurePreviewServer(vitePreviewServer) {
14350
14515
  const workerConfigs = getWorkerConfigs(vitePreviewServer.config.root);
14516
+ const inputInspectorPort = await getInputInspectorPortOption(
14517
+ pluginConfig,
14518
+ vitePreviewServer
14519
+ );
14351
14520
  const miniflare2 = new Miniflare(
14352
14521
  getPreviewMiniflareOptions(
14353
14522
  vitePreviewServer,
14354
14523
  workerConfigs,
14355
14524
  pluginConfig.persistState ?? true,
14356
- pluginConfig.inspectorPort
14525
+ inputInspectorPort
14357
14526
  )
14358
14527
  );
14359
- const middleware = createMiddleware(
14360
- ({ request }) => {
14361
- return miniflare2.dispatchFetch(toMiniflareRequest(request), {
14362
- redirect: "manual"
14363
- });
14364
- },
14365
- { alwaysCallNext: false }
14366
- );
14367
14528
  handleWebSocket(
14368
14529
  vitePreviewServer.httpServer,
14369
14530
  () => miniflare2.dispatchFetch
14370
14531
  );
14371
- vitePreviewServer.middlewares.use((req, res, next) => {
14372
- middleware(req, res, next);
14532
+ vitePreviewServer.middlewares.use(async (req, res, next) => {
14533
+ try {
14534
+ const request = createRequest(req, res);
14535
+ const response = await miniflare2.dispatchFetch(
14536
+ toMiniflareRequest(request),
14537
+ { redirect: "manual" }
14538
+ );
14539
+ if (req.httpVersionMajor === 2) {
14540
+ response.headers.delete("transfer-encoding");
14541
+ }
14542
+ await sendResponse(res, response);
14543
+ } catch (error) {
14544
+ next(error);
14545
+ }
14373
14546
  });
14374
14547
  }
14375
14548
  },
@@ -14432,7 +14605,7 @@ function cloudflare2(pluginConfig = {}) {
14432
14605
  for (const match of matches) {
14433
14606
  magicString ??= new MagicString(code);
14434
14607
  const [full, _, modulePath] = match;
14435
- assert8(
14608
+ assert10(
14436
14609
  modulePath,
14437
14610
  `Unexpected error: module path not found in reference ${full}.`
14438
14611
  );
@@ -14478,17 +14651,22 @@ function cloudflare2(pluginConfig = {}) {
14478
14651
  configEnvironment(name) {
14479
14652
  if (isNodeCompat(getWorkerConfig2(name))) {
14480
14653
  return {
14654
+ build: {
14655
+ rollupOptions: {
14656
+ plugins: [
14657
+ replace({
14658
+ "process.env.NODE_ENV": JSON.stringify(
14659
+ process.env.NODE_ENV ?? "production"
14660
+ ),
14661
+ preventAssignment: true
14662
+ })
14663
+ ]
14664
+ }
14665
+ },
14481
14666
  resolve: {
14482
14667
  builtins: [...nodeCompatExternals]
14483
14668
  },
14484
14669
  optimizeDeps: {
14485
- // This is a list of dependency entry-points that should be pre-bundled.
14486
- // In this case we provide a list of all the possible polyfills so that they are pre-bundled,
14487
- // ready ahead the first request to the dev server.
14488
- // Without this the dependency optimizer will try to bundle them on-the-fly in the middle of the first request,
14489
- // which can potentially cause problems if it leads to previous pre-bundling to become stale and needing to be reloaded.
14490
- // TODO: work out how to re-enable pre-bundling of these
14491
- // include: [...getNodeCompatEntries()],
14492
14670
  // This is a list of module specifiers that the dependency optimizer should not follow when doing import analysis.
14493
14671
  // In this case we provide a list of all the Node.js modules, both those built-in to workerd and those that will be polyfilled.
14494
14672
  // Obviously we don't want/need the optimizer to try to process modules that are built-in;
@@ -14512,7 +14690,7 @@ function cloudflare2(pluginConfig = {}) {
14512
14690
  return this.resolve(source, importer, options);
14513
14691
  }
14514
14692
  if (this.environment.mode === "dev") {
14515
- assert8(
14693
+ assert10(
14516
14694
  this.environment.depsOptimizer,
14517
14695
  "depsOptimizer is required in dev mode"
14518
14696
  );
@@ -14526,11 +14704,54 @@ function cloudflare2(pluginConfig = {}) {
14526
14704
  },
14527
14705
  async transform(code, id) {
14528
14706
  const workerConfig = getWorkerConfig2(this.environment.name);
14529
- assert8(workerConfig, "Expected a worker config");
14707
+ if (!workerConfig) {
14708
+ return;
14709
+ }
14530
14710
  const resolvedId = await this.resolve(workerConfig.main);
14531
14711
  if (id === resolvedId?.id) {
14532
14712
  return injectGlobalCode(id, code);
14533
14713
  }
14714
+ },
14715
+ async configureServer(viteDevServer) {
14716
+ await Promise.all(
14717
+ Object.values(viteDevServer.environments).flatMap(
14718
+ async (environment) => {
14719
+ const workerConfig = getWorkerConfig2(environment.name);
14720
+ if (isNodeCompat(workerConfig)) {
14721
+ await environment.depsOptimizer?.init();
14722
+ return Array.from(nodeCompatEntries).map((entry) => {
14723
+ const result = resolveNodeJSImport(entry);
14724
+ if (result) {
14725
+ const registration = environment.depsOptimizer?.registerMissingImport(
14726
+ result.unresolved,
14727
+ result.resolved
14728
+ );
14729
+ return registration?.processing;
14730
+ }
14731
+ });
14732
+ }
14733
+ }
14734
+ )
14735
+ );
14736
+ }
14737
+ },
14738
+ // Plugin that handles Node.js Async Local Storage (ALS) compatibility support for Vite Environments that are hosted in Cloudflare Workers.
14739
+ {
14740
+ name: "vite-plugin-cloudflare:nodejs-als",
14741
+ apply(_config, env2) {
14742
+ return !env2.isPreview;
14743
+ },
14744
+ configEnvironment(name, config) {
14745
+ if (isNodeAls(getWorkerConfig2(name))) {
14746
+ return {
14747
+ resolve: {
14748
+ builtins: ["async_hooks", "node:async_hooks"]
14749
+ },
14750
+ optimizeDeps: {
14751
+ exclude: ["async_hooks", "node:async_hooks"]
14752
+ }
14753
+ };
14754
+ }
14534
14755
  }
14535
14756
  },
14536
14757
  // Plugin that provides an __debug path for debugging the Cloudflare Workers.
@@ -14540,39 +14761,35 @@ function cloudflare2(pluginConfig = {}) {
14540
14761
  // the preview middleware here can take precedence
14541
14762
  enforce: "pre",
14542
14763
  configureServer(viteDevServer) {
14543
- if (resolvedPluginConfig.type === "workers" && resolvedPluginConfig.inspectorPort !== false) {
14764
+ if (resolvedPluginConfig.type === "workers" && pluginConfig.inspectorPort !== false) {
14544
14765
  addDebugToVitePrintUrls(viteDevServer);
14545
14766
  }
14546
14767
  const workerNames = resolvedPluginConfig.type === "assets-only" ? [] : Object.values(resolvedPluginConfig.workers).map(
14547
14768
  (worker) => worker.name
14548
14769
  );
14549
- viteDevServer.middlewares.use((req, res, next) => {
14550
- if (req.url === debuggingPath && resolvedPluginConfig.inspectorPort !== false) {
14551
- const html = getDebugPathHtml(
14552
- workerNames,
14553
- resolvedPluginConfig.inspectorPort
14554
- );
14770
+ viteDevServer.middlewares.use(async (req, res, next) => {
14771
+ const resolvedInspectorPort = await getResolvedInspectorPort(pluginConfig);
14772
+ if (req.url === debuggingPath && resolvedInspectorPort) {
14773
+ const html = getDebugPathHtml(workerNames, resolvedInspectorPort);
14555
14774
  res.setHeader("Content-Type", "text/html");
14556
14775
  return res.end(html);
14557
14776
  }
14558
14777
  next();
14559
14778
  });
14560
14779
  },
14561
- configurePreviewServer(vitePreviewServer) {
14780
+ async configurePreviewServer(vitePreviewServer) {
14562
14781
  const workerConfigs = getWorkerConfigs(vitePreviewServer.config.root);
14563
14782
  if (workerConfigs.length >= 1 && pluginConfig.inspectorPort !== false) {
14564
14783
  addDebugToVitePrintUrls(vitePreviewServer);
14565
14784
  }
14566
14785
  const workerNames = workerConfigs.map((worker) => {
14567
- assert8(worker.name, "Expected the Worker to have a name");
14786
+ assert10(worker.name, "Expected the Worker to have a name");
14568
14787
  return worker.name;
14569
14788
  });
14570
- vitePreviewServer.middlewares.use((req, res, next) => {
14571
- if (req.url === debuggingPath && pluginConfig.inspectorPort !== false) {
14572
- const html = getDebugPathHtml(
14573
- workerNames,
14574
- pluginConfig.inspectorPort ?? DEFAULT_INSPECTOR_PORT
14575
- );
14789
+ vitePreviewServer.middlewares.use(async (req, res, next) => {
14790
+ const resolvedInspectorPort = await getResolvedInspectorPort(pluginConfig);
14791
+ if (req.url === debuggingPath && resolvedInspectorPort) {
14792
+ const html = getDebugPathHtml(workerNames, resolvedInspectorPort);
14576
14793
  res.setHeader("Content-Type", "text/html");
14577
14794
  return res.end(html);
14578
14795
  }
@@ -14586,6 +14803,9 @@ function cloudflare2(pluginConfig = {}) {
14586
14803
  apply(_config, env2) {
14587
14804
  return !env2.isPreview;
14588
14805
  },
14806
+ // We must ensure that the `resolveId` hook runs before the built-in ones.
14807
+ // Otherwise we never see the Node.js built-in imports since they get handled by default Vite behavior.
14808
+ enforce: "pre",
14589
14809
  configEnvironment(environmentName) {
14590
14810
  const workerConfig = getWorkerConfig2(environmentName);
14591
14811
  if (workerConfig && !isNodeCompat(workerConfig)) {
@@ -14599,21 +14819,14 @@ function cloudflare2(pluginConfig = {}) {
14599
14819
  build.onResolve(
14600
14820
  { filter: NODEJS_MODULES_RE },
14601
14821
  ({ path: path10, importer }) => {
14822
+ if (isNodeAls(workerConfig) && isNodeAlsModule(path10)) {
14823
+ return;
14824
+ }
14602
14825
  const nodeJsCompatWarnings = nodeJsCompatWarningsMap.get(workerConfig);
14603
- assert8(
14604
- nodeJsCompatWarnings,
14605
- `expected nodeJsCompatWarnings to be defined for Worker "${workerConfig.name}"`
14606
- );
14607
- nodeJsCompatWarnings.registerImport(path10, importer);
14826
+ nodeJsCompatWarnings?.registerImport(path10, importer);
14608
14827
  return { path: path10, external: true };
14609
14828
  }
14610
14829
  );
14611
- build.onEnd(() => {
14612
- const nodeJsCompatWarnings = nodeJsCompatWarningsMap.get(workerConfig);
14613
- if (nodeJsCompatWarnings) {
14614
- nodeJsCompatWarnings.renderWarnings();
14615
- }
14616
- });
14617
14830
  }
14618
14831
  }
14619
14832
  ]
@@ -14622,51 +14835,28 @@ function cloudflare2(pluginConfig = {}) {
14622
14835
  };
14623
14836
  }
14624
14837
  },
14625
- configureServer(viteDevServer) {
14626
- for (const environment of Object.values(viteDevServer.environments)) {
14627
- const workerConfig = getWorkerConfig2(environment.name);
14838
+ configResolved(resolvedViteConfig2) {
14839
+ for (const environmentName of Object.keys(
14840
+ resolvedViteConfig2.environments
14841
+ )) {
14842
+ const workerConfig = getWorkerConfig2(environmentName);
14628
14843
  if (workerConfig && !isNodeCompat(workerConfig)) {
14629
14844
  nodeJsCompatWarningsMap.set(
14630
14845
  workerConfig,
14631
- new NodeJsCompatWarnings(environment)
14846
+ new NodeJsCompatWarnings(environmentName, resolvedViteConfig2)
14632
14847
  );
14633
14848
  }
14634
14849
  }
14635
14850
  },
14636
- buildStart() {
14637
- const workerConfig = getWorkerConfig2(this.environment.name);
14638
- if (workerConfig && !isNodeCompat(workerConfig)) {
14639
- nodeJsCompatWarningsMap.set(
14640
- workerConfig,
14641
- new NodeJsCompatWarnings(this.environment)
14642
- );
14643
- }
14644
- },
14645
- buildEnd() {
14646
- const workerConfig = getWorkerConfig2(this.environment.name);
14647
- if (workerConfig && !isNodeCompat(workerConfig)) {
14648
- const nodeJsCompatWarnings = nodeJsCompatWarningsMap.get(workerConfig);
14649
- assert8(
14650
- nodeJsCompatWarnings,
14651
- `expected nodeJsCompatWarnings to be defined for Worker "${workerConfig.name}"`
14652
- );
14653
- nodeJsCompatWarnings.renderWarnings();
14654
- }
14655
- },
14656
- // We must ensure that the `resolveId` hook runs before the built-in ones otherwise we
14657
- // never see the Node.js built-in imports since they get handled by default Vite behavior.
14658
- enforce: "pre",
14659
14851
  async resolveId(source, importer) {
14660
14852
  const workerConfig = getWorkerConfig2(this.environment.name);
14661
14853
  if (workerConfig && !isNodeCompat(workerConfig)) {
14854
+ if (isNodeAls(workerConfig) && isNodeAlsModule(source)) {
14855
+ return;
14856
+ }
14662
14857
  const nodeJsCompatWarnings = nodeJsCompatWarningsMap.get(workerConfig);
14663
- assert8(
14664
- nodeJsCompatWarnings,
14665
- `expected nodeJsCompatWarnings to be defined for Worker "${workerConfig.name}"`
14666
- );
14667
14858
  if (nodejsBuiltins.has(source)) {
14668
- nodeJsCompatWarnings.registerImport(source, importer);
14669
- nodeJsCompatWarnings.renderWarningsOnIdle();
14859
+ nodeJsCompatWarnings?.registerImport(source, importer);
14670
14860
  return {
14671
14861
  id: source,
14672
14862
  external: true
@@ -14677,10 +14867,35 @@ function cloudflare2(pluginConfig = {}) {
14677
14867
  }
14678
14868
  ];
14679
14869
  function getWorkerConfig2(environmentName) {
14680
- assert8(resolvedPluginConfig, "Expected resolvedPluginConfig to be defined");
14870
+ assert10(resolvedPluginConfig, "Expected resolvedPluginConfig to be defined");
14681
14871
  return resolvedPluginConfig.type !== "assets-only" ? resolvedPluginConfig.workers[environmentName] : void 0;
14682
14872
  }
14683
14873
  }
14874
+ async function getInputInspectorPortOption(pluginConfig, viteServer) {
14875
+ if (pluginConfig.inspectorPort === void 0 || pluginConfig.inspectorPort === 0) {
14876
+ const resolvedInspectorPort = await getResolvedInspectorPort(pluginConfig);
14877
+ if (resolvedInspectorPort !== null) {
14878
+ return resolvedInspectorPort;
14879
+ }
14880
+ }
14881
+ const inputInspectorPort = pluginConfig.inspectorPort ?? await getFirstAvailablePort(DEFAULT_INSPECTOR_PORT);
14882
+ if (pluginConfig.inspectorPort === void 0 && inputInspectorPort !== DEFAULT_INSPECTOR_PORT) {
14883
+ viteServer.config.logger.warn(
14884
+ colors3.dim(
14885
+ `Default inspector port ${DEFAULT_INSPECTOR_PORT} not available, using ${inputInspectorPort} instead
14886
+ `
14887
+ )
14888
+ );
14889
+ }
14890
+ return inputInspectorPort;
14891
+ }
14892
+ async function getResolvedInspectorPort(pluginConfig) {
14893
+ if (miniflare && pluginConfig.inspectorPort !== false) {
14894
+ const miniflareInspectorUrl = await miniflare.getInspectorURL();
14895
+ return Number.parseInt(miniflareInspectorUrl.port);
14896
+ }
14897
+ return null;
14898
+ }
14684
14899
  function getDotDevDotVarsContent(configPath, cloudflareEnv) {
14685
14900
  const configDir = path9.dirname(configPath);
14686
14901
  const defaultDotDevDotVarsPath = `${configDir}/.dev.vars`;
@@ -14692,6 +14907,19 @@ function getDotDevDotVarsContent(configPath, cloudflareEnv) {
14692
14907
  }
14693
14908
  return null;
14694
14909
  }
14910
+ function hasDotDevDotVarsFileChanged(resolvedPluginConfig, changedFilePath) {
14911
+ return [...resolvedPluginConfig.configPaths].some((configPath) => {
14912
+ const dotDevDotVars = path9.join(path9.dirname(configPath), ".dev.vars");
14913
+ if (dotDevDotVars === changedFilePath) {
14914
+ return true;
14915
+ }
14916
+ if (resolvedPluginConfig.cloudflareEnv) {
14917
+ const dotDevDotVarsForEnv = `${dotDevDotVars}.${resolvedPluginConfig.cloudflareEnv}`;
14918
+ return dotDevDotVarsForEnv === changedFilePath;
14919
+ }
14920
+ return false;
14921
+ });
14922
+ }
14695
14923
  export {
14696
14924
  cloudflare2 as cloudflare
14697
14925
  };