import { EventEmitter } from 'node:events'; import c from 'picocolors'; import createDebug from 'debug'; function createHmrEmitter() { const emitter = new EventEmitter(); return emitter; } function viteNodeHmrPlugin() { const emitter = createHmrEmitter(); return { name: "vite-node:hmr", configureServer(server) { const _send = server.ws.send; server.emitter = emitter; server.ws.send = function(payload) { _send(payload); emitter.emit("message", payload); }; } }; } const debugHmr = createDebug("vite-node:hmr"); const cache = /* @__PURE__ */ new WeakMap(); function getCache(runner) { if (!cache.has(runner)) { cache.set(runner, { hotModulesMap: /* @__PURE__ */ new Map(), dataMap: /* @__PURE__ */ new Map(), disposeMap: /* @__PURE__ */ new Map(), pruneMap: /* @__PURE__ */ new Map(), customListenersMap: /* @__PURE__ */ new Map(), ctxToListenersMap: /* @__PURE__ */ new Map(), messageBuffer: [], isFirstUpdate: false, pending: false, queued: [] }); } return cache.get(runner); } function sendMessageBuffer(runner, emitter) { const maps = getCache(runner); maps.messageBuffer.forEach((msg) => emitter.emit("custom", msg)); maps.messageBuffer.length = 0; } async function reload(runner, files) { Array.from(runner.moduleCache.keys()).forEach((fsPath) => { if (!fsPath.includes("node_modules")) runner.moduleCache.delete(fsPath); }); return Promise.all(files.map((file) => runner.executeId(file))); } function notifyListeners(runner, event, data) { const maps = getCache(runner); const cbs = maps.customListenersMap.get(event); if (cbs) cbs.forEach((cb) => cb(data)); } async function queueUpdate(runner, p) { const maps = getCache(runner); maps.queued.push(p); if (!maps.pending) { maps.pending = true; await Promise.resolve(); maps.pending = false; const loading = [...maps.queued]; maps.queued = []; (await Promise.all(loading)).forEach((fn) => fn && fn()); } } async function fetchUpdate(runner, { path, acceptedPath }) { const maps = getCache(runner); const mod = maps.hotModulesMap.get(path); if (!mod) { return; } const moduleMap = /* @__PURE__ */ new Map(); const isSelfUpdate = path === acceptedPath; const modulesToUpdate = /* @__PURE__ */ new Set(); if (isSelfUpdate) { modulesToUpdate.add(path); } else { for (const { deps } of mod.callbacks) { deps.forEach((dep) => { if (acceptedPath === dep) modulesToUpdate.add(dep); }); } } const qualifiedCallbacks = mod.callbacks.filter(({ deps }) => { return deps.some((dep) => modulesToUpdate.has(dep)); }); await Promise.all( Array.from(modulesToUpdate).map(async (dep) => { const disposer = maps.disposeMap.get(dep); if (disposer) await disposer(maps.dataMap.get(dep)); try { const newMod = await reload(runner, [dep]); moduleMap.set(dep, newMod); } catch (e) { warnFailedFetch(e, dep); } }) ); return () => { for (const { deps, fn } of qualifiedCallbacks) fn(deps.map((dep) => moduleMap.get(dep))); const loggedPath = isSelfUpdate ? path : `${acceptedPath} via ${path}`; console.log(`${c.cyan("[vite-node]")} hot updated: ${loggedPath}`); }; } function warnFailedFetch(err, path) { if (!err.message.match("fetch")) console.error(err); console.error( `[hmr] Failed to reload ${path}. This could be due to syntax errors or importing non-existent modules. (see errors above)` ); } async function handleMessage(runner, emitter, files, payload) { const maps = getCache(runner); switch (payload.type) { case "connected": sendMessageBuffer(runner, emitter); break; case "update": notifyListeners(runner, "vite:beforeUpdate", payload); if (maps.isFirstUpdate) { reload(runner, files); maps.isFirstUpdate = true; } payload.updates.forEach((update) => { if (update.type === "js-update") { queueUpdate(runner, fetchUpdate(runner, update)); } else { console.error(`${c.cyan("[vite-node]")} no support css hmr.}`); } }); break; case "full-reload": notifyListeners(runner, "vite:beforeFullReload", payload); reload(runner, files); break; case "prune": notifyListeners(runner, "vite:beforePrune", payload); payload.paths.forEach((path) => { const fn = maps.pruneMap.get(path); if (fn) fn(maps.dataMap.get(path)); }); break; case "error": { notifyListeners(runner, "vite:error", payload); const err = payload.err; console.error(`${c.cyan("[vite-node]")} Internal Server Error ${err.message} ${err.stack}`); break; } } } function createHotContext(runner, emitter, files, ownerPath) { debugHmr("createHotContext", ownerPath); const maps = getCache(runner); if (!maps.dataMap.has(ownerPath)) maps.dataMap.set(ownerPath, {}); const mod = maps.hotModulesMap.get(ownerPath); if (mod) mod.callbacks = []; const newListeners = /* @__PURE__ */ new Map(); maps.ctxToListenersMap.set(ownerPath, newListeners); function acceptDeps(deps, callback = () => { }) { const mod2 = maps.hotModulesMap.get(ownerPath) || { id: ownerPath, callbacks: [] }; mod2.callbacks.push({ deps, fn: callback }); maps.hotModulesMap.set(ownerPath, mod2); } const hot = { get data() { return maps.dataMap.get(ownerPath); }, acceptExports(_, callback) { acceptDeps([ownerPath], callback && (([mod2]) => callback(mod2))); }, accept(deps, callback) { if (typeof deps === "function" || !deps) { acceptDeps([ownerPath], ([mod2]) => deps && deps(mod2)); } else if (typeof deps === "string") { acceptDeps([deps], ([mod2]) => callback && callback(mod2)); } else if (Array.isArray(deps)) { acceptDeps(deps, callback); } else { throw new TypeError("invalid hot.accept() usage."); } }, dispose(cb) { maps.disposeMap.set(ownerPath, cb); }, prune(cb) { maps.pruneMap.set(ownerPath, cb); }, invalidate() { notifyListeners(runner, "vite:invalidate", { path: ownerPath, message: void 0 }); return reload(runner, files); }, on(event, cb) { const addToMap = (map) => { const existing = map.get(event) || []; existing.push(cb); map.set(event, existing); }; addToMap(maps.customListenersMap); addToMap(newListeners); }, send(event, data) { maps.messageBuffer.push(JSON.stringify({ type: "custom", event, data })); sendMessageBuffer(runner, emitter); } }; return hot; } export { createHmrEmitter as a, createHotContext as c, getCache as g, handleMessage as h, reload as r, sendMessageBuffer as s, viteNodeHmrPlugin as v };