import { t as C } from "./dist-B2ebky9O.mjs"; import { n as KNOWN_ASSET_RE } from "./constants-DRkacFwN.mjs"; import { _ as withTrailingSlash, c as isNodeBuiltin, d as normalizeModuleId, g as toFilePath, h as toArray, i as findNearestPackageData, m as slash } from "./utils-ExLpYVUV.mjs"; import { r as withInlineSourcemap } from "./source-map-DQLD3K8K.mjs"; import assert from "node:assert"; import { existsSync, promises } from "node:fs"; import { performance } from "node:perf_hooks"; import process from "node:process"; import { pathToFileURL } from "node:url"; import { createDebug } from "obug"; import { dirname, extname, join, normalize, relative, resolve } from "pathe"; import { version } from "vite"; import * as esModuleLexer from "es-module-lexer"; //#region src/debug.ts function hashCode(s) { return s.split("").reduce((a, b) => { a = (a << 5) - a + b.charCodeAt(0); return a & a; }, 0); } var Debugger = class { dumpDir; initPromise; externalizeMap = /* @__PURE__ */ new Map(); constructor(root, options) { this.options = options; if (options.dumpModules) this.dumpDir = resolve(root, options.dumpModules === true ? ".vite-node/dump" : options.dumpModules); if (this.dumpDir) if (options.loadDumppedModules) console.info(C.gray(`[vite-node] [debug] load modules from ${this.dumpDir}`)); else console.info(C.gray(`[vite-node] [debug] dump modules to ${this.dumpDir}`)); this.initPromise = this.clearDump(); } async clearDump() { if (!this.dumpDir) return; if (!this.options.loadDumppedModules && existsSync(this.dumpDir)) await promises.rm(this.dumpDir, { recursive: true, force: true }); await promises.mkdir(this.dumpDir, { recursive: true }); } encodeId(id) { return `${id.replace(/[^\w@\-]/g, "_").replace(/_+/g, "_")}-${hashCode(id)}.js`; } async recordExternalize(id, path) { if (!this.dumpDir) return; this.externalizeMap.set(id, path); await this.writeInfo(); } async dumpFile(id, result) { if (!result || !this.dumpDir) return; await this.initPromise; const name = this.encodeId(id); return await promises.writeFile(join(this.dumpDir, name), `// ${id.replace(/\0/g, "\\0")}\n${result.code}`, "utf-8"); } async loadDump(id) { if (!this.dumpDir) return null; await this.initPromise; const name = this.encodeId(id); const path = join(this.dumpDir, name); if (!existsSync(path)) return null; return { code: (await promises.readFile(path, "utf-8")).replace(/^\/\/.*\n/, ""), map: void 0 }; } async writeInfo() { if (!this.dumpDir) return; const info = JSON.stringify({ time: (/* @__PURE__ */ new Date()).toLocaleString(), externalize: Object.fromEntries(this.externalizeMap.entries()) }, null, 2); return promises.writeFile(join(this.dumpDir, "info.json"), info, "utf-8"); } }; //#endregion //#region src/externalize.ts const BUILTIN_EXTENSIONS = new Set([ ".mjs", ".cjs", ".node", ".wasm" ]); const ESM_EXT_RE = /\.(es|esm|esm-browser|esm-bundler|es6|module)\.js$/; const ESM_FOLDER_RE = /\/(es|esm)\/(.*\.js)$/; const defaultInline = [ /virtual:/, /\.[mc]?ts$/, /[?&](init|raw|url|inline)\b/, KNOWN_ASSET_RE ]; const depsExternal = [/\/node_modules\/.*\.cjs\.js$/, /\/node_modules\/.*\.mjs$/]; function guessCJSversion(id) { if (id.match(ESM_EXT_RE)) { for (const i of [ id.replace(ESM_EXT_RE, ".mjs"), id.replace(ESM_EXT_RE, ".umd.js"), id.replace(ESM_EXT_RE, ".cjs.js"), id.replace(ESM_EXT_RE, ".js") ]) if (existsSync(i)) return i; } if (id.match(ESM_FOLDER_RE)) { for (const i of [ id.replace(ESM_FOLDER_RE, "/umd/$1"), id.replace(ESM_FOLDER_RE, "/cjs/$1"), id.replace(ESM_FOLDER_RE, "/lib/$1"), id.replace(ESM_FOLDER_RE, "/$1") ]) if (existsSync(i)) return i; } } async function isValidNodeImport(id) { const extension = extname(id); if (BUILTIN_EXTENSIONS.has(extension)) return true; if (extension !== ".js") return false; id = id.replace("file:///", ""); if ((await findNearestPackageData(dirname(id))).type === "module") return true; if (/\.(?:\w+-)?esm?(?:-\w+)?\.js$|\/esm?\//.test(id)) return false; try { await esModuleLexer.init; const code = await promises.readFile(id, "utf8"); const [, , , hasModuleSyntax] = esModuleLexer.parse(code); return !hasModuleSyntax; } catch { return false; } } const _defaultExternalizeCache = /* @__PURE__ */ new Map(); async function shouldExternalize(id, options, cache = _defaultExternalizeCache) { if (!cache.has(id)) cache.set(id, _shouldExternalize(id, options)); return cache.get(id); } async function _shouldExternalize(id, options) { if (isNodeBuiltin(id)) return id; if (id.startsWith("data:") || /^(?:https?:)?\/\//.test(id)) return id; id = patchWindowsImportPath(id); const moduleDirectories = options?.moduleDirectories || ["/node_modules/"]; if (matchExternalizePattern(id, moduleDirectories, options?.inline)) return false; if (options?.inlineFiles && options?.inlineFiles.includes(id)) return false; if (matchExternalizePattern(id, moduleDirectories, options?.external)) return id; if (options?.cacheDir && id.includes(options.cacheDir)) return id; const isLibraryModule = moduleDirectories.some((dir) => id.includes(dir)); id = isLibraryModule && options?.fallbackCJS ? guessCJSversion(id) || id : id; if (matchExternalizePattern(id, moduleDirectories, defaultInline)) return false; if (matchExternalizePattern(id, moduleDirectories, depsExternal)) return id; if (isLibraryModule && await isValidNodeImport(id)) return id; return false; } function matchExternalizePattern(id, moduleDirectories, patterns) { if (patterns == null) return false; if (patterns === true) return true; for (const ex of patterns) if (typeof ex === "string") { if (moduleDirectories.some((dir) => id.includes(join(dir, ex)))) return true; } else if (ex.test(id)) return true; return false; } function patchWindowsImportPath(path) { if (path.match(/^\w:\\/)) return `file:///${slash(path)}`; else if (path.match(/^\w:\//)) return `file:///${path}`; else return path; } //#endregion //#region src/server.ts const debugRequest = createDebug("vite-node:server:request"); var ViteNodeServer = class { fetchPromiseMap = { ssr: /* @__PURE__ */ new Map(), web: /* @__PURE__ */ new Map() }; transformPromiseMap = { ssr: /* @__PURE__ */ new Map(), web: /* @__PURE__ */ new Map() }; durations = { ssr: /* @__PURE__ */ new Map(), web: /* @__PURE__ */ new Map() }; existingOptimizedDeps = /* @__PURE__ */ new Set(); fetchCaches = { ssr: /* @__PURE__ */ new Map(), web: /* @__PURE__ */ new Map() }; fetchCache = /* @__PURE__ */ new Map(); externalizeCache = /* @__PURE__ */ new Map(); debugger; constructor(server, options = {}) { this.server = server; this.options = options; const ssrOptions = server.config.ssr; options.deps ??= {}; options.deps.cacheDir = relative(server.config.root, options.deps.cacheDir || server.config.cacheDir); if (ssrOptions) { if (ssrOptions.noExternal === true) options.deps.inline ??= true; else if (options.deps.inline !== true) { options.deps.inline ??= []; const inline = options.deps.inline; options.deps.inline.push(...toArray(ssrOptions.noExternal).filter((dep) => !inline.includes(dep))); } } if (process.env.VITE_NODE_DEBUG_DUMP) options.debug = Object.assign({ dumpModules: !!process.env.VITE_NODE_DEBUG_DUMP, loadDumppedModules: process.env.VITE_NODE_DEBUG_DUMP === "load" }, options.debug ?? {}); if (options.debug) this.debugger = new Debugger(server.config.root, options.debug); if (options.deps.inlineFiles) options.deps.inlineFiles = options.deps.inlineFiles.flatMap((file) => { if (file.startsWith("file://")) return file; const resolvedId = resolve(file); return [resolvedId, pathToFileURL(resolvedId).href]; }); options.deps.moduleDirectories ??= []; const customModuleDirectories = (process.env.VITE_NODE_DEPS_MODULE_DIRECTORIES || process.env.npm_config_VITE_NODE_DEPS_MODULE_DIRECTORIES)?.split(","); if (customModuleDirectories) options.deps.moduleDirectories.push(...customModuleDirectories); options.deps.moduleDirectories = options.deps.moduleDirectories.map((dir) => { if (!dir.startsWith("/")) dir = `/${dir}`; if (!dir.endsWith("/")) dir += "/"; return normalize(dir); }); if (!options.deps.moduleDirectories.includes("/node_modules/")) options.deps.moduleDirectories.push("/node_modules/"); } shouldExternalize(id) { return shouldExternalize(id, this.options.deps, this.externalizeCache); } getTotalDuration() { const ssrDurations = [...this.durations.ssr.values()].flat(); const webDurations = [...this.durations.web.values()].flat(); return [...ssrDurations, ...webDurations].reduce((a, b) => a + b, 0); } async ensureExists(id) { if (this.existingOptimizedDeps.has(id)) return true; if (existsSync(id)) { this.existingOptimizedDeps.add(id); return true; } return new Promise((resolve$1) => { setTimeout(() => { this.ensureExists(id).then(() => { resolve$1(true); }); }); }); } async resolveId(id, importer, transformMode) { if (importer && !importer.startsWith(withTrailingSlash(this.server.config.root))) importer = resolve(this.server.config.root, importer); const mode = transformMode ?? (importer && this.getTransformMode(importer) || "ssr"); return this.server.pluginContainer.resolveId(id, importer, { ssr: mode === "ssr" }); } getSourceMap(source) { source = normalizeModuleId(source); const fetchResult = this.fetchCache.get(source)?.result; if (fetchResult?.map) return fetchResult.map; return (this.server.moduleGraph.getModuleById(source)?.ssrTransformResult)?.map || null; } assertMode(mode) { assert(mode === "web" || mode === "ssr", `"transformMode" can only be "web" or "ssr", received "${mode}".`); } async fetchModule(id, transformMode) { const mode = transformMode || this.getTransformMode(id); return this.fetchResult(id, mode).then((r) => { return this.options.sourcemap !== true ? { ...r, map: void 0 } : r; }); } async fetchResult(id, mode) { const moduleId = normalizeModuleId(id); this.assertMode(mode); const promiseMap = this.fetchPromiseMap[mode]; if (!promiseMap.has(moduleId)) promiseMap.set(moduleId, this._fetchModule(moduleId, mode).finally(() => { promiseMap.delete(moduleId); })); return promiseMap.get(moduleId); } async transformRequest(id, filepath = id, transformMode) { const mode = transformMode || this.getTransformMode(id); this.assertMode(mode); const promiseMap = this.transformPromiseMap[mode]; if (!promiseMap.has(id)) promiseMap.set(id, this._transformRequest(id, filepath, mode).finally(() => { promiseMap.delete(id); })); return promiseMap.get(id); } async transformModule(id, transformMode) { if (transformMode !== "web") throw new Error("`transformModule` only supports `transformMode: \"web\"`."); const normalizedId = normalizeModuleId(id); return { code: (this.server.moduleGraph.getModuleById(normalizedId)?.transformResult || await this.server.transformRequest(normalizedId))?.code }; } getTransformMode(id) { const withoutQuery = id.split("?")[0]; if (this.options.transformMode?.web?.some((r) => withoutQuery.match(r))) return "web"; if (this.options.transformMode?.ssr?.some((r) => withoutQuery.match(r))) return "ssr"; if (withoutQuery.match(/\.([cm]?[jt]sx?|json)$/)) return "ssr"; return "web"; } getChangedModule(id, file) { const module = this.server.moduleGraph.getModuleById(id) || this.server.moduleGraph.getModuleById(file); if (module) return module; const _modules = this.server.moduleGraph.getModulesByFile(file); if (!_modules || !_modules.size) return null; let mod = [..._modules][0]; let latestMax = -1; for (const m of _modules) { const timestamp = Math.max(m.lastHMRTimestamp, m.lastInvalidationTimestamp); if (timestamp > latestMax) { latestMax = timestamp; mod = m; } } return mod; } async _fetchModule(id, transformMode) { let result; const cacheDir = this.options.deps?.cacheDir; if (cacheDir && id.includes(cacheDir)) { if (!id.startsWith(withTrailingSlash(this.server.config.root))) id = join(this.server.config.root, id); const timeout = setTimeout(() => { throw new Error(`ViteNodeServer: ${id} not found. This is a bug, please report it.`); }, 5e3); await this.ensureExists(id); clearTimeout(timeout); } const { path: filePath } = toFilePath(id, this.server.config.root); const moduleNode = this.getChangedModule(id, filePath); const cache = this.fetchCaches[transformMode].get(filePath); const timestamp = moduleNode ? Math.max(moduleNode.lastHMRTimestamp, moduleNode.lastInvalidationTimestamp) : 0; if (cache && (timestamp === 0 || cache.timestamp >= timestamp)) return cache.result; const time = Date.now(); const externalize = await this.shouldExternalize(filePath); let duration; if (externalize) { result = { externalize }; this.debugger?.recordExternalize(id, externalize); } else { const start = performance.now(); const r = await this._transformRequest(id, filePath, transformMode); duration = performance.now() - start; result = { code: r?.code, map: r?.map }; } const cacheEntry = { duration, timestamp: time, result }; const durations = this.durations[transformMode].get(filePath) || []; this.durations[transformMode].set(filePath, [...durations, duration ?? 0]); this.fetchCaches[transformMode].set(filePath, cacheEntry); this.fetchCache.set(filePath, cacheEntry); return result; } async processTransformResult(filepath, result) { return withInlineSourcemap(result, { filepath: this.server.moduleGraph.getModuleById(filepath)?.file || filepath, root: this.server.config.root, noFirstLineMapping: Number(version.split(".")[0]) >= 6 }); } async _transformRequest(id, filepath, transformMode) { debugRequest(id); let result = null; if (this.options.debug?.loadDumppedModules) { result = await this.debugger?.loadDump(id) ?? null; if (result) return result; } if (transformMode === "web") { result = await this.server.transformRequest(id); if (result) result = await this.server.ssrTransform(result.code, result.map, id); } else result = await this.server.transformRequest(id, { ssr: true }); if ((this.options.sourcemap ?? "inline") === "inline" && result) result = await this.processTransformResult(filepath, result); if (this.options.debug?.dumpModules) await this.debugger?.dumpFile(id, result); return result; } }; //#endregion export { guessCJSversion as n, shouldExternalize as r, ViteNodeServer as t };