@cloudflare/vite-plugin 1.10.2 → 1.11.1

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.
@@ -6012,6 +6012,18 @@ var CustomAssetWorker = class extends worker_default {
6012
6012
  const modifiedResponse = new Response(response.body, response);
6013
6013
  modifiedResponse.headers.delete("ETag");
6014
6014
  modifiedResponse.headers.delete("Cache-Control");
6015
+ const viteHeaders = JSON.parse(
6016
+ this.env.__VITE_HEADERS__
6017
+ );
6018
+ for (const [key, value] of Object.entries(viteHeaders)) {
6019
+ if (Array.isArray(value)) {
6020
+ for (const item of value) {
6021
+ modifiedResponse.headers.append(key, item);
6022
+ }
6023
+ } else if (value !== void 0) {
6024
+ modifiedResponse.headers.set(key, String(value));
6025
+ }
6026
+ }
6015
6027
  return modifiedResponse;
6016
6028
  }
6017
6029
  async unstable_getByETag(eTag) {
package/dist/index.js CHANGED
@@ -488,6 +488,7 @@ var require_mime = __commonJS({
488
488
  import assert12 from "node:assert";
489
489
  import * as fsp2 from "node:fs/promises";
490
490
  import * as path13 from "node:path";
491
+ import * as util3 from "node:util";
491
492
 
492
493
  // ../containers-shared/src/utils.ts
493
494
  import { execFileSync, spawn as spawn2 } from "child_process";
@@ -623,10 +624,22 @@ var isDockerfile = (image, configPath) => {
623
624
  }
624
625
  return false;
625
626
  };
626
- async function getContainerIdsByImageTags(dockerPath, imageTags) {
627
+ var cleanupContainers = (dockerPath, imageTags) => {
628
+ try {
629
+ const containerIds = getContainerIdsByImageTags(dockerPath, imageTags);
630
+ if (containerIds.length === 0) {
631
+ return true;
632
+ }
633
+ runDockerCmdWithOutput(dockerPath, ["rm", "--force", ...containerIds]);
634
+ return true;
635
+ } catch {
636
+ return false;
637
+ }
638
+ };
639
+ function getContainerIdsByImageTags(dockerPath, imageTags) {
627
640
  const ids = /* @__PURE__ */ new Set();
628
641
  for (const imageTag of imageTags) {
629
- const containerIdsFromImage = await getContainerIdsFromImage(
642
+ const containerIdsFromImage = getContainerIdsFromImage(
630
643
  dockerPath,
631
644
  imageTag
632
645
  );
@@ -634,7 +647,7 @@ async function getContainerIdsByImageTags(dockerPath, imageTags) {
634
647
  }
635
648
  return Array.from(ids);
636
649
  }
637
- var getContainerIdsFromImage = async (dockerPath, ancestorImage) => {
650
+ var getContainerIdsFromImage = (dockerPath, ancestorImage) => {
638
651
  const output = runDockerCmdWithOutput(dockerPath, [
639
652
  "ps",
640
653
  "-a",
@@ -1786,11 +1799,13 @@ var MagicString = class _MagicString {
1786
1799
 
1787
1800
  // src/index.ts
1788
1801
  import { Miniflare } from "miniflare";
1802
+ import colors4 from "picocolors";
1789
1803
  import * as vite6 from "vite";
1790
1804
 
1791
1805
  // src/constants.ts
1792
1806
  var ROUTER_WORKER_NAME = "__router-worker__";
1793
1807
  var ASSET_WORKER_NAME = "__asset-worker__";
1808
+ var VITE_PROXY_WORKER_NAME = "__vite_proxy_worker__";
1794
1809
  var ASSET_WORKERS_COMPATIBILITY_DATE = "2024-10-04";
1795
1810
  var ADDITIONAL_MODULE_TYPES = [
1796
1811
  "CompiledWasm",
@@ -2298,36 +2313,36 @@ function maybeGetFile(filePath) {
2298
2313
 
2299
2314
  // ../../node_modules/.pnpm/zod@3.22.3/node_modules/zod/lib/index.mjs
2300
2315
  var util;
2301
- (function(util2) {
2302
- util2.assertEqual = (val) => val;
2316
+ (function(util4) {
2317
+ util4.assertEqual = (val) => val;
2303
2318
  function assertIs(_arg) {
2304
2319
  }
2305
- util2.assertIs = assertIs;
2320
+ util4.assertIs = assertIs;
2306
2321
  function assertNever(_x) {
2307
2322
  throw new Error();
2308
2323
  }
2309
- util2.assertNever = assertNever;
2310
- util2.arrayToEnum = (items) => {
2324
+ util4.assertNever = assertNever;
2325
+ util4.arrayToEnum = (items) => {
2311
2326
  const obj = {};
2312
2327
  for (const item of items) {
2313
2328
  obj[item] = item;
2314
2329
  }
2315
2330
  return obj;
2316
2331
  };
2317
- util2.getValidEnumValues = (obj) => {
2318
- const validKeys = util2.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number");
2332
+ util4.getValidEnumValues = (obj) => {
2333
+ const validKeys = util4.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number");
2319
2334
  const filtered = {};
2320
2335
  for (const k of validKeys) {
2321
2336
  filtered[k] = obj[k];
2322
2337
  }
2323
- return util2.objectValues(filtered);
2338
+ return util4.objectValues(filtered);
2324
2339
  };
2325
- util2.objectValues = (obj) => {
2326
- return util2.objectKeys(obj).map(function(e) {
2340
+ util4.objectValues = (obj) => {
2341
+ return util4.objectKeys(obj).map(function(e) {
2327
2342
  return obj[e];
2328
2343
  });
2329
2344
  };
2330
- util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object) => {
2345
+ util4.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object) => {
2331
2346
  const keys = [];
2332
2347
  for (const key in object) {
2333
2348
  if (Object.prototype.hasOwnProperty.call(object, key)) {
@@ -2336,19 +2351,19 @@ var util;
2336
2351
  }
2337
2352
  return keys;
2338
2353
  };
2339
- util2.find = (arr, checker) => {
2354
+ util4.find = (arr, checker) => {
2340
2355
  for (const item of arr) {
2341
2356
  if (checker(item))
2342
2357
  return item;
2343
2358
  }
2344
2359
  return void 0;
2345
2360
  };
2346
- util2.isInteger = typeof Number.isInteger === "function" ? (val) => Number.isInteger(val) : (val) => typeof val === "number" && isFinite(val) && Math.floor(val) === val;
2361
+ util4.isInteger = typeof Number.isInteger === "function" ? (val) => Number.isInteger(val) : (val) => typeof val === "number" && isFinite(val) && Math.floor(val) === val;
2347
2362
  function joinValues(array, separator = " | ") {
2348
2363
  return array.map((val) => typeof val === "string" ? `'${val}'` : val).join(separator);
2349
2364
  }
2350
- util2.joinValues = joinValues;
2351
- util2.jsonStringifyReplacer = (_, value) => {
2365
+ util4.joinValues = joinValues;
2366
+ util4.jsonStringifyReplacer = (_, value) => {
2352
2367
  if (typeof value === "bigint") {
2353
2368
  return value.toString();
2354
2369
  }
@@ -6285,6 +6300,7 @@ function getImportedAssetPaths(viteManifest) {
6285
6300
 
6286
6301
  // src/cloudflare-environment.ts
6287
6302
  import assert4 from "node:assert";
6303
+ import * as util2 from "node:util";
6288
6304
  import * as vite2 from "vite";
6289
6305
 
6290
6306
  // src/node-js-compat.ts
@@ -13400,7 +13416,7 @@ var additionalModuleGlobalRE = new RegExp(
13400
13416
  ADDITIONAL_MODULE_PATTERN,
13401
13417
  "g"
13402
13418
  );
13403
- var VITE_DEV_METADATA_HEADER = "__VITE_DEV_METADATA__";
13419
+ var WORKER_ENTRY_PATH_HEADER = "__VITE_WORKER_ENTRY_PATH__";
13404
13420
 
13405
13421
  // src/utils.ts
13406
13422
  import * as path6 from "node:path";
@@ -13454,6 +13470,7 @@ function toMiniflareRequest(request2) {
13454
13470
 
13455
13471
  // src/cloudflare-environment.ts
13456
13472
  var webSocketUndefinedError = "The WebSocket is undefined";
13473
+ var debuglog2 = util2.debuglog("@cloudflare:vite-plugin");
13457
13474
  function createHotChannel(webSocketContainer) {
13458
13475
  const listenersMap = /* @__PURE__ */ new Map();
13459
13476
  const client = {
@@ -13513,9 +13530,7 @@ var CloudflareDevEnvironment = class extends vite2.DevEnvironment {
13513
13530
  new URL(INIT_PATH, UNKNOWN_HOST),
13514
13531
  {
13515
13532
  headers: {
13516
- [VITE_DEV_METADATA_HEADER]: JSON.stringify({
13517
- entryPath: workerConfig.main
13518
- }),
13533
+ [WORKER_ENTRY_PATH_HEADER]: workerConfig.main,
13519
13534
  upgrade: "websocket"
13520
13535
  }
13521
13536
  }
@@ -13602,6 +13617,7 @@ function initRunners(resolvedPluginConfig, viteDevServer, miniflare2) {
13602
13617
  return Promise.all(
13603
13618
  Object.entries(resolvedPluginConfig.workers).map(
13604
13619
  async ([environmentName, workerConfig]) => {
13620
+ debuglog2("Initializing worker:", workerConfig.name);
13605
13621
  const worker = await miniflare2.getWorker(workerConfig.name);
13606
13622
  return viteDevServer.environments[environmentName].initRunner(worker, workerConfig);
13607
13623
  }
@@ -14580,20 +14596,6 @@ function getDockerPath() {
14580
14596
  const dockerPathEnvVar = "WRANGLER_DOCKER_BIN";
14581
14597
  return process.env[dockerPathEnvVar] || defaultDockerPath;
14582
14598
  }
14583
- async function removeContainersByIds(dockerPath, containerIds) {
14584
- try {
14585
- if (containerIds.length === 0) {
14586
- return;
14587
- }
14588
- await runDockerCmd(
14589
- dockerPath,
14590
- ["rm", "--force", ...containerIds],
14591
- ["inherit", "pipe", "pipe"]
14592
- );
14593
- } catch (error) {
14594
- return;
14595
- }
14596
- }
14597
14599
  async function getContainerOptions(options) {
14598
14600
  const {
14599
14601
  containersConfig,
@@ -14826,42 +14828,52 @@ function writeDeployConfig(resolvedPluginConfig, resolvedViteConfig) {
14826
14828
  }
14827
14829
 
14828
14830
  // src/dev-vars.ts
14829
- import * as fs4 from "node:fs";
14830
14831
  import * as path9 from "node:path";
14831
- function getDotDevDotVarsContent(configPath, cloudflareEnv) {
14832
- const configDir = path9.dirname(configPath);
14833
- const defaultDotDevDotVarsPath = `${configDir}/.dev.vars`;
14834
- const inputDotDevDotVarsPath = `${defaultDotDevDotVarsPath}${cloudflareEnv ? `.${cloudflareEnv}` : ""}`;
14835
- const targetPath = fs4.existsSync(inputDotDevDotVarsPath) ? inputDotDevDotVarsPath : fs4.existsSync(defaultDotDevDotVarsPath) ? defaultDotDevDotVarsPath : null;
14836
- if (targetPath) {
14837
- const dotDevDotVarsContent = fs4.readFileSync(targetPath);
14832
+ import { unstable_getVarsForDev } from "wrangler";
14833
+ function getLocalDevVarsForPreview(configPath, cloudflareEnv) {
14834
+ const dotDevDotVars = unstable_getVarsForDev(
14835
+ configPath,
14836
+ void 0,
14837
+ // We don't currently support setting a list of custom `.env` files.
14838
+ {},
14839
+ // Don't pass actual vars since these will be loaded from the wrangler.json.
14840
+ cloudflareEnv
14841
+ );
14842
+ const dotDevDotVarsEntries = Array.from(Object.entries(dotDevDotVars));
14843
+ if (dotDevDotVarsEntries.length > 0) {
14844
+ const dotDevDotVarsContent = dotDevDotVarsEntries.map(([key, value]) => {
14845
+ return `${key} = "${value?.toString().replaceAll(`"`, `\\"`)}"
14846
+ `;
14847
+ }).join("");
14838
14848
  return dotDevDotVarsContent;
14839
14849
  }
14840
- return null;
14841
14850
  }
14842
- function hasDotDevDotVarsFileChanged(resolvedPluginConfig, changedFilePath) {
14843
- return [...resolvedPluginConfig.configPaths].some((configPath) => {
14844
- const dotDevDotVars = path9.join(path9.dirname(configPath), ".dev.vars");
14845
- if (dotDevDotVars === changedFilePath) {
14846
- return true;
14847
- }
14848
- if (resolvedPluginConfig.cloudflareEnv) {
14849
- const dotDevDotVarsForEnv = `${dotDevDotVars}.${resolvedPluginConfig.cloudflareEnv}`;
14850
- return dotDevDotVarsForEnv === changedFilePath;
14851
- }
14852
- return false;
14851
+ function hasLocalDevVarsFileChanged({
14852
+ configPaths,
14853
+ cloudflareEnv
14854
+ }, changedFilePath) {
14855
+ return [...configPaths].some((configPath) => {
14856
+ const configDir = path9.dirname(configPath);
14857
+ return [
14858
+ ".dev.vars",
14859
+ ".env",
14860
+ ...cloudflareEnv ? [`.dev.vars.${cloudflareEnv}`, `.env.${cloudflareEnv}`] : []
14861
+ ].some(
14862
+ (localDevFile) => changedFilePath === path9.join(configDir, localDevFile)
14863
+ );
14853
14864
  });
14854
14865
  }
14855
14866
 
14856
14867
  // src/miniflare-options.ts
14857
14868
  import assert8 from "node:assert";
14858
- import * as fs5 from "node:fs";
14869
+ import * as fs4 from "node:fs";
14859
14870
  import * as fsp from "node:fs/promises";
14860
14871
  import * as path10 from "node:path";
14861
14872
  import { fileURLToPath as fileURLToPath2 } from "node:url";
14862
14873
  import {
14863
14874
  getDefaultDevRegistryPath,
14864
14875
  kCurrentWorker,
14876
+ kUnsafeEphemeralUniqueKey,
14865
14877
  Log,
14866
14878
  LogLevel,
14867
14879
  Response as MiniflareResponse2
@@ -14963,6 +14975,7 @@ var ROUTER_WORKER_PATH = "./asset-workers/router-worker.js";
14963
14975
  var ASSET_WORKER_PATH = "./asset-workers/asset-worker.js";
14964
14976
  var WRAPPER_PATH = "__VITE_WORKER_ENTRY__";
14965
14977
  var RUNNER_PATH = "./runner-worker/index.js";
14978
+ var VITE_PROXY_WORKER_PATH = "./vite-proxy-worker/index.js";
14966
14979
  function getEntryWorkerConfig(resolvedPluginConfig) {
14967
14980
  if (resolvedPluginConfig.type === "assets-only") {
14968
14981
  return;
@@ -15015,7 +15028,7 @@ async function getDevMiniflareOptions(config) {
15015
15028
  {
15016
15029
  type: "ESModule",
15017
15030
  path: path10.join(miniflareModulesRoot, ROUTER_WORKER_PATH),
15018
- contents: fs5.readFileSync(
15031
+ contents: fs4.readFileSync(
15019
15032
  fileURLToPath2(new URL(ROUTER_WORKER_PATH, import.meta.url))
15020
15033
  )
15021
15034
  }
@@ -15038,13 +15051,14 @@ async function getDevMiniflareOptions(config) {
15038
15051
  {
15039
15052
  type: "ESModule",
15040
15053
  path: path10.join(miniflareModulesRoot, ASSET_WORKER_PATH),
15041
- contents: fs5.readFileSync(
15054
+ contents: fs4.readFileSync(
15042
15055
  fileURLToPath2(new URL(ASSET_WORKER_PATH, import.meta.url))
15043
15056
  )
15044
15057
  }
15045
15058
  ],
15046
15059
  bindings: {
15047
- CONFIG: assetsConfig
15060
+ CONFIG: assetsConfig,
15061
+ __VITE_HEADERS__: JSON.stringify(viteDevServer.config.server.headers)
15048
15062
  },
15049
15063
  serviceBindings: {
15050
15064
  __VITE_HTML_EXISTS__: async (request2) => {
@@ -15092,6 +15106,26 @@ async function getDevMiniflareOptions(config) {
15092
15106
  }
15093
15107
  }
15094
15108
  }
15109
+ },
15110
+ {
15111
+ name: VITE_PROXY_WORKER_NAME,
15112
+ compatibilityDate: ASSET_WORKERS_COMPATIBILITY_DATE,
15113
+ modulesRoot: miniflareModulesRoot,
15114
+ modules: [
15115
+ {
15116
+ type: "ESModule",
15117
+ path: path10.join(miniflareModulesRoot, VITE_PROXY_WORKER_PATH),
15118
+ contents: fs4.readFileSync(
15119
+ fileURLToPath2(new URL(VITE_PROXY_WORKER_PATH, import.meta.url))
15120
+ )
15121
+ }
15122
+ ],
15123
+ serviceBindings: {
15124
+ ...entryWorkerConfig ? { ENTRY_USER_WORKER: entryWorkerConfig.name } : {},
15125
+ __VITE_MIDDLEWARE__: {
15126
+ node: (req, res) => viteDevServer.middlewares(req, res)
15127
+ }
15128
+ }
15095
15129
  }
15096
15130
  ];
15097
15131
  const workersFromConfig = resolvedPluginConfig.type === "workers" ? await Promise.all(
@@ -15134,10 +15168,15 @@ async function getDevMiniflareOptions(config) {
15134
15168
  ...workerOptions,
15135
15169
  name: workerOptions.name ?? workerConfig.name,
15136
15170
  unsafeInspectorProxy: inspectorPort !== false,
15137
- unsafeDirectSockets: environmentName === resolvedPluginConfig.entryWorkerEnvironmentName ? (
15138
- // Expose the default entrypoint of the entry worker on the dev registry
15139
- [{ entrypoint: void 0, proxy: true }]
15140
- ) : [],
15171
+ unsafeDirectSockets: environmentName === resolvedPluginConfig.entryWorkerEnvironmentName ? [
15172
+ {
15173
+ // This exposes the default entrypoint of the asset proxy worker
15174
+ // on the dev registry with the name of the entry worker
15175
+ serviceName: VITE_PROXY_WORKER_NAME,
15176
+ entrypoint: void 0,
15177
+ proxy: true
15178
+ }
15179
+ ] : [],
15141
15180
  modulesRoot: miniflareModulesRoot,
15142
15181
  unsafeEvalBinding: "__VITE_UNSAFE_EVAL__",
15143
15182
  serviceBindings: {
@@ -15206,6 +15245,7 @@ async function getDevMiniflareOptions(config) {
15206
15245
  ...userWorkers.map((workerOptions) => {
15207
15246
  const wrappers = [
15208
15247
  `import { createWorkerEntrypointWrapper, createDurableObjectWrapper, createWorkflowEntrypointWrapper } from '${RUNNER_PATH}';`,
15248
+ `export { __VITE_RUNNER_OBJECT__ } from '${RUNNER_PATH}';`,
15209
15249
  `export default createWorkerEntrypointWrapper('default');`
15210
15250
  ];
15211
15251
  const workerEntrypointNames = workerToWorkerEntrypointNamesMap.get(
@@ -15249,6 +15289,14 @@ async function getDevMiniflareOptions(config) {
15249
15289
  );
15250
15290
  return {
15251
15291
  ...workerOptions,
15292
+ durableObjects: {
15293
+ ...workerOptions.durableObjects,
15294
+ __VITE_RUNNER_OBJECT__: {
15295
+ className: "__VITE_RUNNER_OBJECT__",
15296
+ unsafeUniqueKey: kUnsafeEphemeralUniqueKey,
15297
+ unsafePreventEviction: true
15298
+ }
15299
+ },
15252
15300
  modules: [
15253
15301
  {
15254
15302
  type: "ESModule",
@@ -15258,7 +15306,7 @@ async function getDevMiniflareOptions(config) {
15258
15306
  {
15259
15307
  type: "ESModule",
15260
15308
  path: path10.join(miniflareModulesRoot, RUNNER_PATH),
15261
- contents: fs5.readFileSync(
15309
+ contents: fs4.readFileSync(
15262
15310
  fileURLToPath2(new URL(RUNNER_PATH, import.meta.url))
15263
15311
  )
15264
15312
  }
@@ -15524,7 +15572,7 @@ import * as vite5 from "vite";
15524
15572
 
15525
15573
  // src/workers-configs.ts
15526
15574
  import assert9 from "node:assert";
15527
- import * as fs6 from "node:fs";
15575
+ import * as fs5 from "node:fs";
15528
15576
  import * as path11 from "node:path";
15529
15577
  import { unstable_readConfig as unstable_readConfig2 } from "wrangler";
15530
15578
  var nonApplicableWorkerConfigs = {
@@ -15708,7 +15756,7 @@ function getWorkerConfig(configPath, env2, opts) {
15708
15756
  if (!config.main) {
15709
15757
  throw new Error(missingFieldErrorMessage(`'main'`, configPath, env2));
15710
15758
  }
15711
- const mainStat = fs6.statSync(config.main, { throwIfNoEntry: false });
15759
+ const mainStat = fs5.statSync(config.main, { throwIfNoEntry: false });
15712
15760
  if (!mainStat) {
15713
15761
  throw new Error(
15714
15762
  `The provided Wrangler config main field (${config.main}) doesn't point to an existing file`
@@ -15742,7 +15790,7 @@ function getValidatedWranglerConfigPath(root, requestedConfigPath, isForAuxiliar
15742
15790
  `${errorMessagePrefix} doesn't point to a file with the correct file extension. It should point to a jsonc, json or toml file (${foundExtensionMessage} instead)`
15743
15791
  );
15744
15792
  }
15745
- const mainStat = fs6.statSync(configPath2, { throwIfNoEntry: false });
15793
+ const mainStat = fs5.statSync(configPath2, { throwIfNoEntry: false });
15746
15794
  if (!mainStat) {
15747
15795
  throw new Error(
15748
15796
  `${errorMessagePrefix} doesn't point to an existing file`
@@ -15770,7 +15818,7 @@ function getValidatedWranglerConfigPath(root, requestedConfigPath, isForAuxiliar
15770
15818
  function findWranglerConfig(root) {
15771
15819
  for (const extension of allowedWranglerConfigExtensions) {
15772
15820
  const configPath = path11.join(root, `wrangler.${extension}`);
15773
- if (fs6.existsSync(configPath)) {
15821
+ if (fs5.existsSync(configPath)) {
15774
15822
  return configPath;
15775
15823
  }
15776
15824
  }
@@ -15968,6 +16016,7 @@ function handleWebSocket(httpServer, getFetcher) {
15968
16016
  }
15969
16017
 
15970
16018
  // src/index.ts
16019
+ var debuglog4 = util3.debuglog("@cloudflare:vite-plugin");
15971
16020
  var workersConfigsWarningShown = false;
15972
16021
  var miniflare;
15973
16022
  function cloudflare(pluginConfig = {}) {
@@ -15975,8 +16024,8 @@ function cloudflare(pluginConfig = {}) {
15975
16024
  let resolvedViteConfig;
15976
16025
  const additionalModulePaths = /* @__PURE__ */ new Set();
15977
16026
  const nodeJsCompatWarningsMap = /* @__PURE__ */ new Map();
15978
- let containerImageTagsSeen;
15979
- let runningContainerIds;
16027
+ let containerImageTagsSeen = /* @__PURE__ */ new Set();
16028
+ let restartingServer = false;
15980
16029
  return [
15981
16030
  {
15982
16031
  name: "vite-plugin-cloudflare",
@@ -16114,15 +16163,15 @@ if (import.meta.hot) {
16114
16163
  }
16115
16164
  config = workerConfig;
16116
16165
  if (workerConfig.configPath) {
16117
- const dotDevDotVarsContent = getDotDevDotVarsContent(
16166
+ const localDevVars = getLocalDevVarsForPreview(
16118
16167
  workerConfig.configPath,
16119
16168
  resolvedPluginConfig.cloudflareEnv
16120
16169
  );
16121
- if (dotDevDotVarsContent) {
16170
+ if (localDevVars) {
16122
16171
  this.emitFile({
16123
16172
  type: "asset",
16124
16173
  fileName: ".dev.vars",
16125
- source: dotDevDotVarsContent
16174
+ source: localDevVars
16126
16175
  });
16127
16176
  }
16128
16177
  }
@@ -16159,27 +16208,40 @@ if (import.meta.hot) {
16159
16208
  writeDeployConfig(resolvedPluginConfig, resolvedViteConfig);
16160
16209
  }
16161
16210
  },
16162
- hotUpdate(options) {
16163
- assertIsNotPreview(resolvedPluginConfig);
16164
- const changedFilePath = path13.resolve(options.file);
16165
- if (resolvedPluginConfig.configPaths.has(changedFilePath) || hasDotDevDotVarsFileChanged(resolvedPluginConfig, changedFilePath) || hasAssetsConfigChanged(
16166
- resolvedPluginConfig,
16167
- resolvedViteConfig,
16168
- changedFilePath
16169
- )) {
16170
- options.server.restart();
16171
- return [];
16172
- }
16173
- },
16174
16211
  // Vite `configureServer` Hook
16175
16212
  // see https://vite.dev/guide/api-plugin.html#configureserver
16176
16213
  async configureServer(viteDevServer) {
16214
+ const restartServer = viteDevServer.restart.bind(viteDevServer);
16215
+ viteDevServer.restart = async () => {
16216
+ try {
16217
+ restartingServer = true;
16218
+ debuglog4("From server.restart(): Restarting server...");
16219
+ await restartServer();
16220
+ debuglog4("From server.restart(): Restarted server...");
16221
+ } finally {
16222
+ restartingServer = false;
16223
+ }
16224
+ };
16177
16225
  assertIsNotPreview(resolvedPluginConfig);
16178
16226
  const inputInspectorPort = await getInputInspectorPortOption(
16179
16227
  resolvedPluginConfig,
16180
16228
  viteDevServer,
16181
16229
  miniflare
16182
16230
  );
16231
+ const configChangedHandler = async (changedFilePath) => {
16232
+ assertIsNotPreview(resolvedPluginConfig);
16233
+ if (resolvedPluginConfig.configPaths.has(changedFilePath) || hasLocalDevVarsFileChanged(resolvedPluginConfig, changedFilePath) || hasAssetsConfigChanged(
16234
+ resolvedPluginConfig,
16235
+ resolvedViteConfig,
16236
+ changedFilePath
16237
+ )) {
16238
+ debuglog4("Config changed: " + changedFilePath);
16239
+ viteDevServer.watcher.off("change", configChangedHandler);
16240
+ debuglog4("Restarting dev server and aborting previous setup");
16241
+ await viteDevServer.restart();
16242
+ }
16243
+ };
16244
+ viteDevServer.watcher.on("change", configChangedHandler);
16183
16245
  let containerBuildId;
16184
16246
  const entryWorkerConfig = getEntryWorkerConfig(resolvedPluginConfig);
16185
16247
  const hasDevContainers = entryWorkerConfig?.containers?.length && entryWorkerConfig.dev.enable_containers;
@@ -16195,13 +16257,17 @@ if (import.meta.hot) {
16195
16257
  containerBuildId
16196
16258
  });
16197
16259
  if (!miniflare) {
16260
+ debuglog4("Creating new Miniflare instance");
16198
16261
  miniflare = new Miniflare(miniflareDevOptions);
16199
16262
  } else {
16263
+ debuglog4("Updating the existing Miniflare instance");
16200
16264
  await miniflare.setOptions(miniflareDevOptions);
16265
+ debuglog4("Miniflare is ready");
16201
16266
  }
16202
16267
  let preMiddleware;
16203
16268
  if (resolvedPluginConfig.type === "workers") {
16204
16269
  assert12(entryWorkerConfig, `No entry Worker config`);
16270
+ debuglog4("Initializing the Vite module runners");
16205
16271
  await initRunners(resolvedPluginConfig, viteDevServer, miniflare);
16206
16272
  const entryWorkerName = entryWorkerConfig.name;
16207
16273
  if (viteDevServer.httpServer) {
@@ -16240,6 +16306,13 @@ if (import.meta.hot) {
16240
16306
  };
16241
16307
  }
16242
16308
  if (hasDevContainers) {
16309
+ viteDevServer.config.logger.info(
16310
+ colors4.dim(
16311
+ colors4.yellow(
16312
+ "\u2237 Building container images for local development...\n"
16313
+ )
16314
+ )
16315
+ );
16243
16316
  containerImageTagsSeen = await prepareContainerImages({
16244
16317
  containersConfig: entryWorkerConfig.containers,
16245
16318
  containerBuildId,
@@ -16247,17 +16320,17 @@ if (import.meta.hot) {
16247
16320
  dockerPath,
16248
16321
  configPath: entryWorkerConfig.configPath
16249
16322
  });
16250
- const dockerPollIntervalId = setInterval(async () => {
16251
- if (containerImageTagsSeen?.size) {
16252
- runningContainerIds = await getContainerIdsByImageTags(
16253
- dockerPath,
16254
- containerImageTagsSeen
16255
- );
16323
+ viteDevServer.config.logger.info(
16324
+ colors4.dim(
16325
+ colors4.yellow(
16326
+ "\n\u26A1\uFE0F Containers successfully built. To rebuild your containers during development, restart the Vite dev server (r + enter)."
16327
+ )
16328
+ )
16329
+ );
16330
+ process.on("exit", async () => {
16331
+ if (containerImageTagsSeen.size) {
16332
+ cleanupContainers(dockerPath, containerImageTagsSeen);
16256
16333
  }
16257
- }, 2e3);
16258
- process.on("exit", () => {
16259
- clearInterval(dockerPollIntervalId);
16260
- removeContainersByIds(dockerPath, runningContainerIds);
16261
16334
  });
16262
16335
  }
16263
16336
  }
@@ -16316,6 +16389,13 @@ if (import.meta.hot) {
16316
16389
  );
16317
16390
  if (hasDevContainers) {
16318
16391
  const dockerPath = getDockerPath();
16392
+ vitePreviewServer.config.logger.info(
16393
+ colors4.dim(
16394
+ colors4.yellow(
16395
+ "\u2237 Building container images for local preview...\n"
16396
+ )
16397
+ )
16398
+ );
16319
16399
  containerImageTagsSeen = await prepareContainerImages({
16320
16400
  containersConfig: entryWorkerConfig.containers,
16321
16401
  containerBuildId,
@@ -16323,17 +16403,13 @@ if (import.meta.hot) {
16323
16403
  dockerPath,
16324
16404
  configPath: entryWorkerConfig.configPath
16325
16405
  });
16326
- const dockerPollIntervalId = setInterval(async () => {
16327
- if (containerImageTagsSeen?.size) {
16328
- runningContainerIds = await getContainerIdsByImageTags(
16329
- dockerPath,
16330
- containerImageTagsSeen
16331
- );
16332
- }
16333
- }, 2e3);
16406
+ vitePreviewServer.config.logger.info(
16407
+ colors4.dim(colors4.yellow("\n\u26A1\uFE0F Containers successfully built.\n"))
16408
+ );
16334
16409
  process.on("exit", () => {
16335
- clearInterval(dockerPollIntervalId);
16336
- removeContainersByIds(dockerPath, runningContainerIds);
16410
+ if (containerImageTagsSeen.size) {
16411
+ cleanupContainers(dockerPath, containerImageTagsSeen);
16412
+ }
16337
16413
  });
16338
16414
  }
16339
16415
  handleWebSocket(vitePreviewServer.httpServer, () => {
@@ -16350,13 +16426,15 @@ if (import.meta.hot) {
16350
16426
  async buildEnd() {
16351
16427
  if (resolvedViteConfig.command === "serve" && containerImageTagsSeen?.size) {
16352
16428
  const dockerPath = getDockerPath();
16353
- runningContainerIds = await getContainerIdsByImageTags(
16354
- dockerPath,
16355
- containerImageTagsSeen
16356
- );
16357
- await removeContainersByIds(dockerPath, runningContainerIds);
16358
- containerImageTagsSeen.clear();
16359
- runningContainerIds = [];
16429
+ cleanupContainers(dockerPath, containerImageTagsSeen);
16430
+ }
16431
+ debuglog4("buildEnd:", restartingServer ? "restarted" : "disposing");
16432
+ if (!restartingServer) {
16433
+ debuglog4("buildEnd: disposing Miniflare instance");
16434
+ await miniflare?.dispose().catch((error) => {
16435
+ debuglog4("buildEnd: failed to dispose Miniflare instance:", error);
16436
+ });
16437
+ miniflare = void 0;
16360
16438
  }
16361
16439
  }
16362
16440
  },
@@ -1,6 +1,6 @@
1
1
  // src/runner-worker/index.ts
2
2
  import {
3
- DurableObject,
3
+ DurableObject as DurableObject2,
4
4
  WorkerEntrypoint,
5
5
  WorkflowEntrypoint
6
6
  } from "cloudflare:workers";
@@ -22,14 +22,22 @@ var additionalModuleGlobalRE = new RegExp(
22
22
  ADDITIONAL_MODULE_PATTERN,
23
23
  "g"
24
24
  );
25
- var VITE_DEV_METADATA_HEADER = "__VITE_DEV_METADATA__";
25
+ var WORKER_ENTRY_PATH_HEADER = "__VITE_WORKER_ENTRY_PATH__";
26
26
 
27
27
  // src/runner-worker/env.ts
28
28
  function stripInternalEnv(internalEnv) {
29
- const { __VITE_INVOKE_MODULE__, __VITE_UNSAFE_EVAL__, ...userEnv } = internalEnv;
29
+ const {
30
+ __VITE_RUNNER_OBJECT__: __VITE_RUNNER_OBJECT__2,
31
+ __VITE_INVOKE_MODULE__,
32
+ __VITE_UNSAFE_EVAL__,
33
+ ...userEnv
34
+ } = internalEnv;
30
35
  return userEnv;
31
36
  }
32
37
 
38
+ // src/runner-worker/module-runner.ts
39
+ import { DurableObject } from "cloudflare:workers";
40
+
33
41
  // ../../node_modules/.pnpm/vite@7.0.0_@types+node@20.19.9_jiti@2.4.2_lightningcss@1.29.2/node_modules/vite/dist/node/module-runner.js
34
42
  var VALID_ID_PREFIX = "/@id/";
35
43
  var NULL_BYTE_PLACEHOLDER = "__x00__";
@@ -686,45 +694,6 @@ var normalizeModuleRunnerTransport = (transport) => {
686
694
  }
687
695
  };
688
696
  };
689
- var createWebSocketModuleRunnerTransport = (options) => {
690
- let pingInterval = options.pingInterval ?? 3e4, ws, pingIntervalId;
691
- return {
692
- async connect({ onMessage, onDisconnection }) {
693
- let socket = options.createConnection();
694
- socket.addEventListener("message", async ({ data }) => {
695
- onMessage(JSON.parse(data));
696
- });
697
- let isOpened = socket.readyState === socket.OPEN;
698
- isOpened || await new Promise((resolve$1, reject) => {
699
- socket.addEventListener("open", () => {
700
- isOpened = true, resolve$1();
701
- }, { once: true }), socket.addEventListener("close", async () => {
702
- if (!isOpened) {
703
- reject(/* @__PURE__ */ Error("WebSocket closed without opened."));
704
- return;
705
- }
706
- onMessage({
707
- type: "custom",
708
- event: "vite:ws:disconnect",
709
- data: { webSocket: socket }
710
- }), onDisconnection();
711
- });
712
- }), onMessage({
713
- type: "custom",
714
- event: "vite:ws:connect",
715
- data: { webSocket: socket }
716
- }), ws = socket, pingIntervalId = setInterval(() => {
717
- socket.readyState === socket.OPEN && socket.send(JSON.stringify({ type: "ping" }));
718
- }, pingInterval);
719
- },
720
- disconnect() {
721
- clearInterval(pingIntervalId), ws?.close();
722
- },
723
- send(data) {
724
- ws.send(JSON.stringify(data));
725
- }
726
- };
727
- };
728
697
  var ssrModuleExportsKey = "__vite_ssr_exports__";
729
698
  var ssrImportKey = "__vite_ssr_import__";
730
699
  var ssrDynamicImportKey = "__vite_ssr_dynamic_import__";
@@ -1223,22 +1192,108 @@ function exportAll(exports, sourceModule) {
1223
1192
  }
1224
1193
 
1225
1194
  // src/runner-worker/module-runner.ts
1195
+ var CustomModuleRunner = class extends ModuleRunner {
1196
+ #env;
1197
+ constructor(options, evaluator, env) {
1198
+ super(options, evaluator);
1199
+ this.#env = env;
1200
+ }
1201
+ async cachedModule(url, importer) {
1202
+ const stub = this.#env.__VITE_RUNNER_OBJECT__.get("singleton");
1203
+ const moduleId = await stub.getFetchedModuleId(url, importer);
1204
+ const module = this.evaluatedModules.getModuleById(moduleId);
1205
+ if (!module) {
1206
+ throw new Error(`Module "${moduleId}" is undefined`);
1207
+ }
1208
+ return module;
1209
+ }
1210
+ };
1226
1211
  var moduleRunner;
1227
- async function createModuleRunner(env, webSocket) {
1228
- if (moduleRunner) {
1229
- throw new Error("Runner already initialized");
1212
+ var __VITE_RUNNER_OBJECT__ = class extends DurableObject {
1213
+ /** WebSocket connection to the Vite dev server */
1214
+ #webSocket;
1215
+ #concurrentModuleNodePromises = /* @__PURE__ */ new Map();
1216
+ /**
1217
+ * Handles fetch requests to initialize the module runner.
1218
+ * Creates a WebSocket pair for communication with the Vite dev server and initializes the ModuleRunner.
1219
+ * @param request - The incoming fetch request
1220
+ * @returns Response with WebSocket
1221
+ * @throws Error if the path is invalid or the module runner is already initialized
1222
+ */
1223
+ async fetch(request) {
1224
+ const { pathname } = new URL(request.url);
1225
+ if (pathname !== INIT_PATH) {
1226
+ throw new Error(
1227
+ `__VITE_RUNNER_OBJECT__ received invalid pathname: ${pathname}`
1228
+ );
1229
+ }
1230
+ if (moduleRunner) {
1231
+ throw new Error(`Module runner already initialized`);
1232
+ }
1233
+ const { 0: client, 1: server } = new WebSocketPair();
1234
+ server.accept();
1235
+ this.#webSocket = server;
1236
+ moduleRunner = await createModuleRunner(this.env, this.#webSocket);
1237
+ return new Response(null, { status: 101, webSocket: client });
1230
1238
  }
1231
- const transport = createWebSocketModuleRunnerTransport({
1232
- createConnection() {
1233
- webSocket.accept();
1234
- return webSocket;
1239
+ /**
1240
+ * Sends data to the Vite dev server via the WebSocket.
1241
+ * @param data - The data to send as a string
1242
+ * @throws Error if the WebSocket is not initialized
1243
+ */
1244
+ send(data) {
1245
+ if (!this.#webSocket) {
1246
+ throw new Error(`Module runner WebSocket not initialized`);
1235
1247
  }
1236
- });
1237
- moduleRunner = new ModuleRunner(
1248
+ this.#webSocket.send(data);
1249
+ }
1250
+ /**
1251
+ * Based on the implementation of `cachedModule` from Vite's `ModuleRunner`.
1252
+ * Running this in the DO enables us to share promises across invocations.
1253
+ * @param url - The module URL
1254
+ * @param importer - The module's importer
1255
+ * @returns The ID of the fetched module
1256
+ */
1257
+ async getFetchedModuleId(url, importer) {
1258
+ if (!moduleRunner) {
1259
+ throw new Error(`Module runner not initialized`);
1260
+ }
1261
+ let cached = this.#concurrentModuleNodePromises.get(url);
1262
+ if (!cached) {
1263
+ const cachedModule = moduleRunner.evaluatedModules.getModuleByUrl(url);
1264
+ cached = moduleRunner.getModuleInformation(url, importer, cachedModule).finally(() => {
1265
+ this.#concurrentModuleNodePromises.delete(url);
1266
+ });
1267
+ this.#concurrentModuleNodePromises.set(url, cached);
1268
+ } else {
1269
+ moduleRunner.debug?.("[module runner] using cached module info for", url);
1270
+ }
1271
+ const module = await cached;
1272
+ return module.id;
1273
+ }
1274
+ };
1275
+ async function createModuleRunner(env, webSocket) {
1276
+ return new CustomModuleRunner(
1238
1277
  {
1239
1278
  sourcemapInterceptor: "prepareStackTrace",
1240
1279
  transport: {
1241
- ...transport,
1280
+ connect({ onMessage }) {
1281
+ webSocket.addEventListener("message", async ({ data }) => {
1282
+ onMessage(JSON.parse(data.toString()));
1283
+ });
1284
+ onMessage({
1285
+ type: "custom",
1286
+ event: "vite:ws:connect",
1287
+ data: { webSocket }
1288
+ });
1289
+ },
1290
+ disconnect() {
1291
+ webSocket.close();
1292
+ },
1293
+ send(data) {
1294
+ const stub = env.__VITE_RUNNER_OBJECT__.get("singleton");
1295
+ stub.send(JSON.stringify(data));
1296
+ },
1242
1297
  async invoke(data) {
1243
1298
  const response = await env.__VITE_INVOKE_MODULE__.fetch(
1244
1299
  new Request(UNKNOWN_HOST, {
@@ -1246,9 +1301,6 @@ async function createModuleRunner(env, webSocket) {
1246
1301
  body: JSON.stringify(data)
1247
1302
  })
1248
1303
  );
1249
- if (!response.ok) {
1250
- throw new Error(await response.text());
1251
- }
1252
1304
  const result = await response.json();
1253
1305
  return result;
1254
1306
  }
@@ -1257,19 +1309,17 @@ async function createModuleRunner(env, webSocket) {
1257
1309
  },
1258
1310
  {
1259
1311
  async runInlinedModule(context, transformed, module) {
1260
- const codeDefinition = `'use strict';async (${Object.keys(context).join(
1261
- ","
1262
- )})=>{{`;
1263
- const code = `${codeDefinition}${transformed}
1264
- }}`;
1312
+ const code = `"use strict";async (${Object.keys(context).join(",")})=>{${transformed}}`;
1265
1313
  try {
1266
1314
  const fn = env.__VITE_UNSAFE_EVAL__.eval(code, module.id);
1267
1315
  await fn(...Object.values(context));
1268
- Object.freeze(context.__vite_ssr_exports__);
1269
- } catch (e) {
1270
- console.error("error running", module.id);
1271
- console.error(e instanceof Error ? e.stack : e);
1272
- throw e;
1316
+ Object.seal(context[ssrModuleExportsKey]);
1317
+ } catch (error) {
1318
+ if (error instanceof Error) {
1319
+ error.message = `Error running module "${module.id}".
1320
+ ${error.message}.`;
1321
+ }
1322
+ throw error;
1273
1323
  }
1274
1324
  },
1275
1325
  async runExternalModule(filepath) {
@@ -1282,19 +1332,24 @@ async function createModuleRunner(env, webSocket) {
1282
1332
  )
1283
1333
  });
1284
1334
  }
1285
- filepath = filepath.replace(/^file:\/\//, "");
1286
1335
  return import(filepath);
1287
1336
  }
1288
- }
1337
+ },
1338
+ env
1289
1339
  );
1290
1340
  }
1291
- async function getWorkerEntryExport(path, entrypoint) {
1292
- const module = await moduleRunner.import(path);
1293
- const entrypointValue = typeof module === "object" && module !== null && entrypoint in module && module[entrypoint];
1294
- if (!entrypointValue) {
1295
- throw new Error(`${path} does not export a ${entrypoint} entrypoint.`);
1341
+ async function getWorkerEntryExport(workerEntryPath2, exportName) {
1342
+ if (!moduleRunner) {
1343
+ throw new Error(`Module runner not initialized`);
1296
1344
  }
1297
- return entrypointValue;
1345
+ const module = await moduleRunner.import(workerEntryPath2);
1346
+ const exportValue = typeof module === "object" && module !== null && exportName in module && module[exportName];
1347
+ if (!exportValue) {
1348
+ throw new Error(
1349
+ `"${workerEntryPath2}" does not define a "${exportName}" export.`
1350
+ );
1351
+ }
1352
+ return exportValue;
1298
1353
  }
1299
1354
 
1300
1355
  // src/runner-worker/index.ts
@@ -1315,7 +1370,20 @@ var DURABLE_OBJECT_KEYS = [
1315
1370
  "webSocketMessage"
1316
1371
  ];
1317
1372
  var WORKFLOW_ENTRYPOINT_KEYS = ["run"];
1318
- var entryPath = "";
1373
+ var workerEntryPath = "";
1374
+ function getRpcPropertyCallableThenable(key, property) {
1375
+ const fn = async function(...args) {
1376
+ const maybeFn = await property;
1377
+ if (typeof maybeFn !== "function") {
1378
+ throw new TypeError(`"${key}" is not a function.`);
1379
+ }
1380
+ return maybeFn(...args);
1381
+ };
1382
+ fn.then = (onFulfilled, onRejected) => property.then(onFulfilled, onRejected);
1383
+ fn.catch = (onRejected) => property.catch(onRejected);
1384
+ fn.finally = (onFinally) => property.finally(onFinally);
1385
+ return fn;
1386
+ }
1319
1387
  function getRpcProperty(ctor, instance, key) {
1320
1388
  const prototypeHasKey = Reflect.has(ctor.prototype, key);
1321
1389
  if (!prototypeHasKey) {
@@ -1323,37 +1391,24 @@ function getRpcProperty(ctor, instance, key) {
1323
1391
  if (instanceHasKey) {
1324
1392
  throw new TypeError(
1325
1393
  [
1326
- `The RPC receiver's prototype does not implement '${key}', but the receiver instance does.`,
1394
+ `The RPC receiver's prototype does not implement "${key}", but the receiver instance does.`,
1327
1395
  "Only properties and methods defined on the prototype can be accessed over RPC.",
1328
1396
  `Ensure properties are declared as \`get ${key}() { ... }\` instead of \`${key} = ...\`,`,
1329
1397
  `and methods are declared as \`${key}() { ... }\` instead of \`${key} = () => { ... }\`.`
1330
1398
  ].join("\n")
1331
1399
  );
1332
1400
  }
1333
- throw new TypeError(`The RPC receiver does not implement '${key}'.`);
1401
+ throw new TypeError(`The RPC receiver does not implement "${key}".`);
1334
1402
  }
1335
1403
  return Reflect.get(ctor.prototype, key, instance);
1336
1404
  }
1337
- function getRpcPropertyCallableThenable(key, property) {
1338
- const fn = async function(...args) {
1339
- const maybeFn = await property;
1340
- if (typeof maybeFn !== "function") {
1341
- throw new TypeError(`'${key}' is not a function.`);
1342
- }
1343
- return maybeFn(...args);
1344
- };
1345
- fn.then = (onFulfilled, onRejected) => property.then(onFulfilled, onRejected);
1346
- fn.catch = (onRejected) => property.catch(onRejected);
1347
- fn.finally = (onFinally) => property.finally(onFinally);
1348
- return fn;
1349
- }
1350
- async function getWorkerEntrypointRpcProperty(entrypoint, key) {
1405
+ async function getWorkerEntrypointRpcProperty(exportName, key) {
1351
1406
  const ctor = await getWorkerEntryExport(
1352
- entryPath,
1353
- entrypoint
1407
+ workerEntryPath,
1408
+ exportName
1354
1409
  );
1355
1410
  const userEnv = stripInternalEnv(this.env);
1356
- const expectedWorkerEntrypointMessage = `Expected ${entrypoint} export of ${entryPath} to be a subclass of \`WorkerEntrypoint\` for RPC.`;
1411
+ const expectedWorkerEntrypointMessage = `Expected "${exportName}" export of "${workerEntryPath}" to be a subclass of \`WorkerEntrypoint\` for RPC.`;
1357
1412
  if (typeof ctor !== "function") {
1358
1413
  throw new TypeError(expectedWorkerEntrypointMessage);
1359
1414
  }
@@ -1367,7 +1422,7 @@ async function getWorkerEntrypointRpcProperty(entrypoint, key) {
1367
1422
  }
1368
1423
  return value;
1369
1424
  }
1370
- function createWorkerEntrypointWrapper(entrypoint) {
1425
+ function createWorkerEntrypointWrapper(exportName) {
1371
1426
  class Wrapper extends WorkerEntrypoint {
1372
1427
  constructor(ctx, env) {
1373
1428
  super(ctx, env);
@@ -1377,12 +1432,14 @@ function createWorkerEntrypointWrapper(entrypoint) {
1377
1432
  if (value !== void 0) {
1378
1433
  return value;
1379
1434
  }
1380
- if (typeof key === "symbol" || IGNORED_KEYS.includes(key) || DURABLE_OBJECT_KEYS.includes(key)) {
1435
+ if (typeof key === "symbol" || IGNORED_KEYS.includes(key) || // The class methods are accessed to determine the type of the export.
1436
+ // We should therefore avoid proxying `DurableObject` methods on the `WorkerEntrypoint` class.
1437
+ DURABLE_OBJECT_KEYS.includes(key)) {
1381
1438
  return;
1382
1439
  }
1383
1440
  const property = getWorkerEntrypointRpcProperty.call(
1384
1441
  receiver,
1385
- entrypoint,
1442
+ exportName,
1386
1443
  key
1387
1444
  );
1388
1445
  return getRpcPropertyCallableThenable(key, property);
@@ -1395,54 +1452,51 @@ function createWorkerEntrypointWrapper(entrypoint) {
1395
1452
  if (key === "fetch") {
1396
1453
  const request = arg;
1397
1454
  const url = new URL(request.url);
1398
- let webSocket;
1399
1455
  if (url.pathname === INIT_PATH) {
1400
- try {
1401
- const viteDevMetadata = getViteDevMetadata(request);
1402
- entryPath = viteDevMetadata.entryPath;
1403
- const { 0: client, 1: server } = new WebSocketPair();
1404
- webSocket = client;
1405
- await createModuleRunner(this.env, server);
1406
- } catch (e) {
1407
- return new Response(
1408
- e instanceof Error ? e.message : JSON.stringify(e),
1409
- { status: 500 }
1456
+ const workerEntryPathHeader = request.headers.get(
1457
+ WORKER_ENTRY_PATH_HEADER
1458
+ );
1459
+ if (!workerEntryPathHeader) {
1460
+ throw new Error(
1461
+ `Unexpected error: "${WORKER_ENTRY_PATH_HEADER}" header not set.`
1410
1462
  );
1411
1463
  }
1412
- return new Response(null, {
1413
- status: 101,
1414
- webSocket
1415
- });
1464
+ workerEntryPath = workerEntryPathHeader;
1465
+ const stub = this.env.__VITE_RUNNER_OBJECT__.get("singleton");
1466
+ return stub.fetch(request);
1416
1467
  }
1417
1468
  }
1418
- const entrypointValue = await getWorkerEntryExport(entryPath, entrypoint);
1469
+ const exportValue = await getWorkerEntryExport(
1470
+ workerEntryPath,
1471
+ exportName
1472
+ );
1419
1473
  const userEnv = stripInternalEnv(this.env);
1420
- if (typeof entrypointValue === "object" && entrypointValue !== null) {
1421
- const maybeFn = entrypointValue[key];
1474
+ if (typeof exportValue === "object" && exportValue !== null) {
1475
+ const maybeFn = exportValue[key];
1422
1476
  if (typeof maybeFn !== "function") {
1423
1477
  throw new TypeError(
1424
- `Expected ${entrypoint} export of ${entryPath} to define a \`${key}()\` function.`
1478
+ `Expected "${exportName}" export of "${workerEntryPath}" to define a \`${key}()\` function.`
1425
1479
  );
1426
1480
  }
1427
- return maybeFn.call(entrypointValue, arg, userEnv, this.ctx);
1428
- } else if (typeof entrypointValue === "function") {
1429
- const ctor = entrypointValue;
1481
+ return maybeFn.call(exportValue, arg, userEnv, this.ctx);
1482
+ } else if (typeof exportValue === "function") {
1483
+ const ctor = exportValue;
1430
1484
  const instance = new ctor(this.ctx, userEnv);
1431
1485
  if (!(instance instanceof WorkerEntrypoint)) {
1432
1486
  throw new TypeError(
1433
- `Expected ${entrypoint} export of ${entryPath} to be a subclass of \`WorkerEntrypoint\`.`
1487
+ `Expected "${exportName}" export of "${workerEntryPath}" to be a subclass of \`WorkerEntrypoint\`.`
1434
1488
  );
1435
1489
  }
1436
1490
  const maybeFn = instance[key];
1437
1491
  if (typeof maybeFn !== "function") {
1438
1492
  throw new TypeError(
1439
- `Expected ${entrypoint} export of ${entryPath} to define a \`${key}()\` method.`
1493
+ `Expected "${exportName}" export of "${workerEntryPath}" to define a \`${key}()\` method.`
1440
1494
  );
1441
1495
  }
1442
1496
  return maybeFn.call(instance, arg);
1443
1497
  } else {
1444
1498
  return new TypeError(
1445
- `Expected ${entrypoint} export of ${entryPath} to be an object or a class. Got ${entrypointValue}.`
1499
+ `Expected "${exportName}" export of "${workerEntryPath}" to be an object or a class.`
1446
1500
  );
1447
1501
  }
1448
1502
  };
@@ -1451,11 +1505,11 @@ function createWorkerEntrypointWrapper(entrypoint) {
1451
1505
  }
1452
1506
  var kInstance = Symbol("kInstance");
1453
1507
  var kEnsureInstance = Symbol("kEnsureInstance");
1454
- async function getDurableObjectRpcProperty(className, key) {
1508
+ async function getDurableObjectRpcProperty(exportName, key) {
1455
1509
  const { ctor, instance } = await this[kEnsureInstance]();
1456
- if (!(instance instanceof DurableObject)) {
1510
+ if (!(instance instanceof DurableObject2)) {
1457
1511
  throw new TypeError(
1458
- `Expected ${className} export of ${entryPath} to be a subclass of \`DurableObject\` for RPC.`
1512
+ `Expected "${exportName}" export of "${workerEntryPath}" to be a subclass of \`DurableObject\` for RPC.`
1459
1513
  );
1460
1514
  }
1461
1515
  const value = getRpcProperty(ctor, instance, key);
@@ -1464,8 +1518,8 @@ async function getDurableObjectRpcProperty(className, key) {
1464
1518
  }
1465
1519
  return value;
1466
1520
  }
1467
- function createDurableObjectWrapper(className) {
1468
- class Wrapper extends DurableObject {
1521
+ function createDurableObjectWrapper(exportName) {
1522
+ class Wrapper extends DurableObject2 {
1469
1523
  [kInstance];
1470
1524
  constructor(ctx, env) {
1471
1525
  super(ctx, env);
@@ -1475,12 +1529,14 @@ function createDurableObjectWrapper(className) {
1475
1529
  if (value !== void 0) {
1476
1530
  return value;
1477
1531
  }
1478
- if (typeof key === "symbol" || IGNORED_KEYS.includes(key) || WORKER_ENTRYPOINT_KEYS.includes(key)) {
1532
+ if (typeof key === "symbol" || IGNORED_KEYS.includes(key) || // The class methods are accessed to determine the type of the export.
1533
+ // We should therefore avoid proxying `WorkerEntrypoint` methods on the `DurableObject` class.
1534
+ WORKER_ENTRYPOINT_KEYS.includes(key)) {
1479
1535
  return;
1480
1536
  }
1481
1537
  const property = getDurableObjectRpcProperty.call(
1482
1538
  receiver,
1483
- className,
1539
+ exportName,
1484
1540
  key
1485
1541
  );
1486
1542
  return getRpcPropertyCallableThenable(key, property);
@@ -1489,12 +1545,12 @@ function createDurableObjectWrapper(className) {
1489
1545
  }
1490
1546
  async [kEnsureInstance]() {
1491
1547
  const ctor = await getWorkerEntryExport(
1492
- entryPath,
1493
- className
1548
+ workerEntryPath,
1549
+ exportName
1494
1550
  );
1495
1551
  if (typeof ctor !== "function") {
1496
1552
  throw new TypeError(
1497
- `${entryPath} does not export a ${className} Durable Object.`
1553
+ `Expected "${exportName}" export of "${workerEntryPath}" to be a subclass of \`DurableObject\`.`
1498
1554
  );
1499
1555
  }
1500
1556
  if (!this[kInstance] || this[kInstance].ctor !== ctor) {
@@ -1513,7 +1569,7 @@ function createDurableObjectWrapper(className) {
1513
1569
  const maybeFn = instance[key];
1514
1570
  if (typeof maybeFn !== "function") {
1515
1571
  throw new TypeError(
1516
- `Expected ${className} export of ${entryPath} to define a \`${key}()\` function.`
1572
+ `Expected "${exportName}" export of "${workerEntryPath}" to define a \`${key}()\` function.`
1517
1573
  );
1518
1574
  }
1519
1575
  return maybeFn.apply(instance, args);
@@ -1521,26 +1577,26 @@ function createDurableObjectWrapper(className) {
1521
1577
  }
1522
1578
  return Wrapper;
1523
1579
  }
1524
- function createWorkflowEntrypointWrapper(className) {
1580
+ function createWorkflowEntrypointWrapper(exportName) {
1525
1581
  class Wrapper extends WorkflowEntrypoint {
1526
1582
  }
1527
1583
  for (const key of WORKFLOW_ENTRYPOINT_KEYS) {
1528
1584
  Wrapper.prototype[key] = async function(...args) {
1529
1585
  const ctor = await getWorkerEntryExport(
1530
- entryPath,
1531
- className
1586
+ workerEntryPath,
1587
+ exportName
1532
1588
  );
1533
1589
  const userEnv = stripInternalEnv(this.env);
1534
1590
  const instance = new ctor(this.ctx, userEnv);
1535
1591
  if (!(instance instanceof WorkflowEntrypoint)) {
1536
1592
  throw new TypeError(
1537
- `Expected ${className} export of ${entryPath} to be a subclass of \`WorkflowEntrypoint\`.`
1593
+ `Expected "${exportName}" export of "${workerEntryPath}" to be a subclass of \`WorkflowEntrypoint\`.`
1538
1594
  );
1539
1595
  }
1540
1596
  const maybeFn = instance[key];
1541
1597
  if (typeof maybeFn !== "function") {
1542
1598
  throw new TypeError(
1543
- `Expected ${className} export of ${entryPath} to define a \`${key}()\` function.`
1599
+ `Expected "${exportName}" export of "${workerEntryPath}" to define a \`${key}()\` function.`
1544
1600
  );
1545
1601
  }
1546
1602
  return maybeFn.apply(instance, args);
@@ -1548,30 +1604,8 @@ function createWorkflowEntrypointWrapper(className) {
1548
1604
  }
1549
1605
  return Wrapper;
1550
1606
  }
1551
- function getViteDevMetadata(request) {
1552
- const viteDevMetadataHeader = request.headers.get(VITE_DEV_METADATA_HEADER);
1553
- if (viteDevMetadataHeader === null) {
1554
- throw new Error(
1555
- "Unexpected internal error, vite dev metadata header not set"
1556
- );
1557
- }
1558
- let parsedViteDevMetadataHeader;
1559
- try {
1560
- parsedViteDevMetadataHeader = JSON.parse(viteDevMetadataHeader);
1561
- } catch {
1562
- throw new Error(
1563
- `Unexpected internal error, vite dev metadata header JSON parsing failed, value = ${viteDevMetadataHeader}`
1564
- );
1565
- }
1566
- const { entryPath: entryPath2 } = parsedViteDevMetadataHeader;
1567
- if (entryPath2 === void 0) {
1568
- throw new Error(
1569
- "Unexpected internal error, vite dev metadata header doesn't contain an entryPath value"
1570
- );
1571
- }
1572
- return { entryPath: entryPath2 };
1573
- }
1574
1607
  export {
1608
+ __VITE_RUNNER_OBJECT__,
1575
1609
  createDurableObjectWrapper,
1576
1610
  createWorkerEntrypointWrapper,
1577
1611
  createWorkflowEntrypointWrapper
@@ -0,0 +1,39 @@
1
+ // src/vite-proxy-worker/index.ts
2
+ import { WorkerEntrypoint } from "cloudflare:workers";
3
+ var ViteProxyWorker = class extends WorkerEntrypoint {
4
+ constructor(ctx, env) {
5
+ super(ctx, env);
6
+ return new Proxy(this, {
7
+ get(target, prop) {
8
+ if (Reflect.has(target, prop)) {
9
+ return Reflect.get(target, prop);
10
+ }
11
+ return Reflect.get(target.env.ENTRY_USER_WORKER, prop);
12
+ }
13
+ });
14
+ }
15
+ async fetch(request) {
16
+ return this.env.__VITE_MIDDLEWARE__.fetch(request);
17
+ }
18
+ tail(events) {
19
+ return this.env.ENTRY_USER_WORKER.tail(
20
+ JSON.parse(JSON.stringify(events, tailEventsReplacer), tailEventsReviver)
21
+ );
22
+ }
23
+ };
24
+ var serializedDate = "___serialized_date___";
25
+ function tailEventsReplacer(_, value) {
26
+ if (value instanceof Date) {
27
+ return { [serializedDate]: value.toISOString() };
28
+ }
29
+ return value;
30
+ }
31
+ function tailEventsReviver(_, value) {
32
+ if (value && typeof value === "object" && serializedDate in value) {
33
+ return new Date(value[serializedDate]);
34
+ }
35
+ return value;
36
+ }
37
+ export {
38
+ ViteProxyWorker as default
39
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudflare/vite-plugin",
3
- "version": "1.10.2",
3
+ "version": "1.11.1",
4
4
  "description": "Cloudflare plugin for Vite",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -40,12 +40,12 @@
40
40
  "tinyglobby": "^0.2.12",
41
41
  "unenv": "2.0.0-rc.19",
42
42
  "ws": "8.18.0",
43
- "@cloudflare/unenv-preset": "2.5.0",
44
- "miniflare": "4.20250726.0",
45
- "wrangler": "4.26.1"
43
+ "@cloudflare/unenv-preset": "2.6.0",
44
+ "miniflare": "4.20250803.0",
45
+ "wrangler": "4.28.0"
46
46
  },
47
47
  "devDependencies": {
48
- "@cloudflare/workers-types": "^4.20250726.0",
48
+ "@cloudflare/workers-types": "^4.20250803.0",
49
49
  "@types/node": "^22.10.1",
50
50
  "@types/ws": "^8.5.13",
51
51
  "magic-string": "^0.30.12",
@@ -61,7 +61,7 @@
61
61
  },
62
62
  "peerDependencies": {
63
63
  "vite": "^6.1.0 || ^7.0.0",
64
- "wrangler": "^4.26.1"
64
+ "wrangler": "^4.28.0"
65
65
  },
66
66
  "publishConfig": {
67
67
  "access": "public"