Time slots app prototype
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
6.9 KiB

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 };