import { t as overrideEnv } from "./env-DV8TWRZt.mjs"; import { i as withNodePath, t as loadKit } from "./kit-B3S8uoS_.mjs"; import { r as showVersionsFromConfig } from "./banner-DMgRAl0q.mjs"; import { t as clearBuildDir } from "./fs-CQH7NJn6.mjs"; import { a as writeNuxtManifest, i as resolveNuxtManifest, n as loadNuxtManifest } from "./nuxt-B1NSR4xh.mjs"; import process from "node:process"; import { provider } from "std-env"; import { pathToFileURL } from "node:url"; import defu, { defu as defu$1 } from "defu"; import EventEmitter from "node:events"; import { existsSync, readdirSync, statSync, watch } from "node:fs"; import { mkdir } from "node:fs/promises"; import { resolveModulePath } from "exsolve"; import { joinURL } from "ufo"; import { listen } from "listhen"; import { join, resolve } from "pathe"; import { debounce } from "perfect-debounce"; import { toNodeHandler } from "srvx/node"; import { Youch } from "youch"; //#region ../../node_modules/.pnpm/h3@1.15.4/node_modules/h3/dist/index.mjs function hasProp(obj, prop) { try { return prop in obj; } catch { return false; } } var H3Error = class extends Error { static __h3_error__ = true; statusCode = 500; fatal = false; unhandled = false; statusMessage; data; cause; constructor(message, opts = {}) { super(message, opts); if (opts.cause && !this.cause) this.cause = opts.cause; } toJSON() { const obj = { message: this.message, statusCode: sanitizeStatusCode(this.statusCode, 500) }; if (this.statusMessage) obj.statusMessage = sanitizeStatusMessage(this.statusMessage); if (this.data !== void 0) obj.data = this.data; return obj; } }; function createError(input) { if (typeof input === "string") return new H3Error(input); if (isError(input)) return input; const err = new H3Error(input.message ?? input.statusMessage ?? "", { cause: input.cause || input }); if (hasProp(input, "stack")) try { Object.defineProperty(err, "stack", { get() { return input.stack; } }); } catch { try { err.stack = input.stack; } catch {} } if (input.data) err.data = input.data; if (input.statusCode) err.statusCode = sanitizeStatusCode(input.statusCode, err.statusCode); else if (input.status) err.statusCode = sanitizeStatusCode(input.status, err.statusCode); if (input.statusMessage) err.statusMessage = input.statusMessage; else if (input.statusText) err.statusMessage = input.statusText; if (err.statusMessage) { const originalMessage = err.statusMessage; if (sanitizeStatusMessage(err.statusMessage) !== originalMessage) console.warn("[h3] Please prefer using `message` for longer error messages instead of `statusMessage`. In the future, `statusMessage` will be sanitized by default."); } if (input.fatal !== void 0) err.fatal = input.fatal; if (input.unhandled !== void 0) err.unhandled = input.unhandled; return err; } function sendError(event, error, debug) { if (event.handled) return; const h3Error = isError(error) ? error : createError(error); const responseBody = { statusCode: h3Error.statusCode, statusMessage: h3Error.statusMessage, stack: [], data: h3Error.data }; if (debug) responseBody.stack = (h3Error.stack || "").split("\n").map((l) => l.trim()); if (event.handled) return; setResponseStatus(event, Number.parseInt(h3Error.statusCode), h3Error.statusMessage); event.node.res.setHeader("content-type", MIMES.json); event.node.res.end(JSON.stringify(responseBody, void 0, 2)); } function isError(input) { return input?.constructor?.__h3_error__ === true; } const RawBodySymbol = Symbol.for("h3RawBody"); const ParsedBodySymbol = Symbol.for("h3ParsedBody"); const MIMES = { html: "text/html", json: "application/json" }; const DISALLOWED_STATUS_CHARS = /[^\u0009\u0020-\u007E]/g; function sanitizeStatusMessage(statusMessage = "") { return statusMessage.replace(DISALLOWED_STATUS_CHARS, ""); } function sanitizeStatusCode(statusCode, defaultStatusCode = 200) { if (!statusCode) return defaultStatusCode; if (typeof statusCode === "string") statusCode = Number.parseInt(statusCode, 10); if (statusCode < 100 || statusCode > 999) return defaultStatusCode; return statusCode; } function splitCookiesString(cookiesString) { if (Array.isArray(cookiesString)) return cookiesString.flatMap((c) => splitCookiesString(c)); if (typeof cookiesString !== "string") return []; const cookiesStrings = []; let pos = 0; let start$1; let ch; let lastComma; let nextStart; let cookiesSeparatorFound; const skipWhitespace = () => { while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) pos += 1; return pos < cookiesString.length; }; const notSpecialChar = () => { ch = cookiesString.charAt(pos); return ch !== "=" && ch !== ";" && ch !== ","; }; while (pos < cookiesString.length) { start$1 = pos; cookiesSeparatorFound = false; while (skipWhitespace()) { ch = cookiesString.charAt(pos); if (ch === ",") { lastComma = pos; pos += 1; skipWhitespace(); nextStart = pos; while (pos < cookiesString.length && notSpecialChar()) pos += 1; if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") { cookiesSeparatorFound = true; pos = nextStart; cookiesStrings.push(cookiesString.slice(start$1, lastComma)); start$1 = pos; } else pos = lastComma + 1; } else pos += 1; } if (!cookiesSeparatorFound || pos >= cookiesString.length) cookiesStrings.push(cookiesString.slice(start$1)); } return cookiesStrings; } function setResponseStatus(event, code, text) { if (code) event.node.res.statusCode = sanitizeStatusCode(code, event.node.res.statusCode); if (text) event.node.res.statusMessage = sanitizeStatusMessage(text); } function sendStream(event, stream) { if (!stream || typeof stream !== "object") throw new Error("[h3] Invalid stream provided."); event.node.res._data = stream; if (!event.node.res.socket) { event._handled = true; return Promise.resolve(); } if (hasProp(stream, "pipeTo") && typeof stream.pipeTo === "function") return stream.pipeTo(new WritableStream({ write(chunk) { event.node.res.write(chunk); } })).then(() => { event.node.res.end(); }); if (hasProp(stream, "pipe") && typeof stream.pipe === "function") return new Promise((resolve$1, reject) => { stream.pipe(event.node.res); if (stream.on) { stream.on("end", () => { event.node.res.end(); resolve$1(); }); stream.on("error", (error) => { reject(error); }); } event.node.res.on("close", () => { if (stream.abort) stream.abort(); }); }); throw new Error("[h3] Invalid or incompatible stream provided."); } function sendWebResponse(event, response) { for (const [key, value] of response.headers) if (key === "set-cookie") event.node.res.appendHeader(key, splitCookiesString(value)); else event.node.res.setHeader(key, value); if (response.status) event.node.res.statusCode = sanitizeStatusCode(response.status, event.node.res.statusCode); if (response.statusText) event.node.res.statusMessage = sanitizeStatusMessage(response.statusText); if (response.redirected) event.node.res.setHeader("location", response.url); if (!response.body) { event.node.res.end(); return; } return sendStream(event, response.body); } var H3Event = class { "__is_event__" = true; node; web; context = {}; _method; _path; _headers; _requestBody; _handled = false; _onBeforeResponseCalled; _onAfterResponseCalled; constructor(req, res) { this.node = { req, res }; } get method() { if (!this._method) this._method = (this.node.req.method || "GET").toUpperCase(); return this._method; } get path() { return this._path || this.node.req.url || "/"; } get headers() { if (!this._headers) this._headers = _normalizeNodeHeaders(this.node.req.headers); return this._headers; } get handled() { return this._handled || this.node.res.writableEnded || this.node.res.headersSent; } respondWith(response) { return Promise.resolve(response).then((_response) => sendWebResponse(this, _response)); } toString() { return `[${this.method}] ${this.path}`; } toJSON() { return this.toString(); } /** @deprecated Please use `event.node.req` instead. */ get req() { return this.node.req; } /** @deprecated Please use `event.node.res` instead. */ get res() { return this.node.res; } }; function createEvent(req, res) { return new H3Event(req, res); } function _normalizeNodeHeaders(nodeHeaders) { const headers = new Headers(); for (const [name, value] of Object.entries(nodeHeaders)) if (Array.isArray(value)) for (const item of value) headers.append(name, item); else if (value) headers.set(name, value); return headers; } const H3Headers = globalThis.Headers; const H3Response = globalThis.Response; function toNodeListener(app) { const toNodeHandle = async function(req, res) { const event = createEvent(req, res); try { await app.handler(event); } catch (_error) { const error = createError(_error); if (!isError(_error)) error.unhandled = true; setResponseStatus(event, error.statusCode, error.statusMessage); if (app.options.onError) await app.options.onError(error, event); if (event.handled) return; if (error.unhandled || error.fatal) console.error("[h3]", error.fatal ? "[fatal]" : "[unhandled]", error); if (app.options.onBeforeResponse && !event._onBeforeResponseCalled) await app.options.onBeforeResponse(event, { body: error }); await sendError(event, error, !!app.options.debug); if (app.options.onAfterResponse && !event._onAfterResponseCalled) await app.options.onAfterResponse(event, { body: error }); } }; return toNodeHandle; } //#endregion //#region ../nuxi/src/dev/error.ts async function renderError(req, res, error) { if (res.headersSent) { if (!res.writableEnded) res.end(); return; } const youch = new Youch(); res.statusCode = 500; res.setHeader("Content-Type", "text/html"); res.setHeader("Cache-Control", "no-store"); res.setHeader("Refresh", "3"); const html = await youch.toHTML(error, { request: { url: req.url, method: req.method, headers: req.headers } }); res.end(html); } //#endregion //#region ../nuxi/src/dev/utils.ts const RESTART_RE = /^(?:nuxt\.config\.[a-z0-9]+|\.nuxtignore|\.nuxtrc|\.config\/nuxt(?:\.config)?\.[a-z0-9]+)$/; var FileChangeTracker = class { mtimes = /* @__PURE__ */ new Map(); shouldEmitChange(filePath) { const resolved = resolve(filePath); try { const currentMtime = statSync(resolved).mtimeMs; const lastMtime = this.mtimes.get(resolved); this.mtimes.set(resolved, currentMtime); return lastMtime === void 0 || currentMtime !== lastMtime; } catch { this.mtimes.delete(resolved); return true; } } prime(filePath, recursive = false) { const resolved = resolve(filePath); const stat = statSync(resolved); this.mtimes.set(resolved, stat.mtimeMs); if (stat.isDirectory()) { const entries = readdirSync(resolved); for (const entry of entries) { const fullPath = resolve(resolved, entry); try { const stats = statSync(fullPath); this.mtimes.set(fullPath, stats.mtimeMs); if (recursive && stats.isDirectory()) this.prime(fullPath, recursive); } catch {} } } } }; var NuxtDevServer = class extends EventEmitter { #handler; #distWatcher; #configWatcher; #currentNuxt; #loadingMessage; #loadingError; #fileChangeTracker = new FileChangeTracker(); #cwd; #websocketConnections = /* @__PURE__ */ new Set(); loadDebounced; handler; listener; constructor(options) { super(); this.options = options; this.loadDebounced = debounce(this.load); let _initResolve; const _initPromise = new Promise((resolve$1) => { _initResolve = resolve$1; }); this.once("ready", () => { _initResolve(); }); this.#cwd = options.cwd; this.handler = async (req, res) => { if (this.#loadingError) { renderError(req, res, this.#loadingError); return; } await _initPromise; if (this.#handler) this.#handler(req, res); else this.#renderLoadingScreen(req, res); }; } async #renderLoadingScreen(req, res) { if (res.headersSent) { if (!res.writableEnded) res.end(); return; } res.statusCode = 503; res.setHeader("Content-Type", "text/html"); const loadingTemplate = this.options.loadingTemplate || this.#currentNuxt?.options.devServer.loadingTemplate || await resolveLoadingTemplate(this.#cwd); res.end(loadingTemplate({ loading: this.#loadingMessage || "Loading..." })); } async init() { this.#loadingMessage = `Starting Nuxt...`; this.#handler = void 0; this.emit("loading", this.#loadingMessage); await this.#loadNuxtInstance(); if (this.options.showBanner) showVersionsFromConfig(this.options.cwd, this.#currentNuxt.options); await this.#createListener(); await this.#initializeNuxt(false); this.#watchConfig(); } closeWatchers() { this.#distWatcher?.close(); this.#configWatcher?.(); } async load(reload, reason) { try { this.closeWatchers(); await this.#load(reload, reason); this.#loadingError = void 0; } catch (error) { console.error(`Cannot ${reload ? "restart" : "start"} nuxt: `, error); this.#handler = void 0; this.#loadingError = error; this.#loadingMessage = "Error while loading Nuxt. Please check console and fix errors."; this.emit("loading:error", error); } this.#watchConfig(); } async #loadNuxtInstance(urls) { const kit = await loadKit(this.options.cwd); const loadOptions = { cwd: this.options.cwd, dev: true, ready: false, envName: this.options.envName, dotenv: { cwd: this.options.cwd, fileName: this.options.dotenv.fileName }, overrides: { logLevel: this.options.logLevel, ...this.options.overrides, vite: { clearScreen: this.options.clear, ...this.options.overrides.vite } } }; if (urls) { const overrides = this.options.listenOverrides || {}; const hostname = overrides.hostname; const https = overrides.https; loadOptions.defaults = resolveDevServerDefaults({ hostname, https }, urls); } this.#currentNuxt = await kit.loadNuxt(loadOptions); } async #createListener() { if (!this.#currentNuxt) throw new Error("Nuxt must be loaded before creating listener"); const listenOptions = this.#resolveListenOptions(); this.listener = await listen(this.handler, listenOptions); if (listenOptions.public) { this.#currentNuxt.options.devServer.cors = { origin: "*" }; if (this.#currentNuxt.options.vite?.server) this.#currentNuxt.options.vite.server.allowedHosts = true; return; } const urls = await this.listener.getURLs().then((r) => r.map((r$1) => r$1.url)); if (urls && urls.length > 0) this.#currentNuxt.options.vite = defu(this.#currentNuxt.options.vite, { server: { allowedHosts: urls.map((u) => new URL(u).hostname) } }); } #resolveListenOptions() { if (!this.#currentNuxt) throw new Error("Nuxt must be loaded before resolving listen options"); const nuxtConfig = this.#currentNuxt.options; const overrides = this.options.listenOverrides || {}; const port = overrides.port ?? nuxtConfig.devServer?.port; const hostname = overrides.hostname ?? nuxtConfig.devServer?.host; const isPublic = provider === "codesandbox" || (overrides.public ?? (isPublicHostname(hostname) ? true : void 0)); const httpsFromConfig = typeof nuxtConfig.devServer?.https !== "boolean" && nuxtConfig.devServer?.https ? nuxtConfig.devServer.https : {}; overrides._https ??= !!nuxtConfig.devServer?.https; const httpsOptions = overrides.https && defu(typeof overrides.https === "object" ? overrides.https : {}, httpsFromConfig); const baseURL = nuxtConfig.app?.baseURL?.startsWith?.("./") ? nuxtConfig.app.baseURL.slice(1) : nuxtConfig.app?.baseURL; return { ...overrides, port, hostname, public: isPublic, https: httpsOptions || void 0, baseURL }; } async #initializeNuxt(reload) { if (!this.#currentNuxt) throw new Error("Nuxt must be loaded before configuration"); if (!process.env.NUXI_DISABLE_VITE_HMR) this.#currentNuxt.hooks.hook("vite:extend", ({ config }) => { if (config.server) config.server.hmr = { protocol: void 0, ...config.server.hmr, port: void 0, host: void 0, server: this.listener.server }; }); this.#currentNuxt.hooks.hookOnce("close", () => { this.#closeWebSocketConnections(); this.listener.server.removeAllListeners("upgrade"); }); if (!reload) { const previousManifest = await loadNuxtManifest(this.#currentNuxt.options.buildDir); const newManifest = resolveNuxtManifest(this.#currentNuxt); const promise = writeNuxtManifest(this.#currentNuxt, newManifest); this.#currentNuxt.hooks.hookOnce("ready", async () => { await promise; }); if (previousManifest && newManifest && previousManifest._hash !== newManifest._hash) await clearBuildDir(this.#currentNuxt.options.buildDir); } await this.#currentNuxt.ready(); const unsub = this.#currentNuxt.hooks.hook("restart", async (options) => { unsub(); if (options?.hard) { this.emit("restart"); return; } await this.load(true); }); if (this.#currentNuxt.server && "upgrade" in this.#currentNuxt.server) this.listener.server.on("upgrade", (req, socket, head) => { const nuxt = this.#currentNuxt; if (!nuxt || !nuxt.server) return; const viteHmrPath = joinURL(nuxt.options.app.baseURL.startsWith("./") ? nuxt.options.app.baseURL.slice(1) : nuxt.options.app.baseURL, nuxt.options.app.buildAssetsDir); if (req.url?.startsWith(viteHmrPath)) return; nuxt.server.upgrade(req, socket, head); this.#websocketConnections.add(socket); socket.on("close", () => { this.#websocketConnections.delete(socket); }); }); await this.#currentNuxt.hooks.callHook("listen", this.listener.server, this.listener); const addr = this.listener.address; this.#currentNuxt.options.devServer.host = addr.address; this.#currentNuxt.options.devServer.port = addr.port; this.#currentNuxt.options.devServer.url = getAddressURL(addr, !!this.listener.https); this.#currentNuxt.options.devServer.https = this.listener.https; if (this.listener.https && !process.env.NODE_TLS_REJECT_UNAUTHORIZED) console.warn("You might need `NODE_TLS_REJECT_UNAUTHORIZED=0` environment variable to make https work."); const kit = await loadKit(this.options.cwd); const typesPromise = existsSync(join(this.#currentNuxt.options.buildDir, "tsconfig.json")) ? kit.writeTypes(this.#currentNuxt).catch(console.error) : await kit.writeTypes(this.#currentNuxt).catch(console.error); await Promise.all([typesPromise, kit.buildNuxt(this.#currentNuxt)]); if (!this.#currentNuxt.server) throw new Error("Nitro server has not been initialized."); const distDir = join(this.#currentNuxt.options.buildDir, "dist"); await mkdir(distDir, { recursive: true }); this.#fileChangeTracker.prime(distDir); this.#distWatcher = watch(distDir); this.#distWatcher.on("change", (_event, file) => { if (!this.#fileChangeTracker.shouldEmitChange(resolve(distDir, file || ""))) return; this.loadDebounced(true, ".nuxt/dist directory has been removed"); }); if ("fetch" in this.#currentNuxt.server) this.#handler = toNodeHandler(this.#currentNuxt.server.fetch); else this.#handler = toNodeListener(this.#currentNuxt.server.app); const proto = this.listener.https ? "https" : "http"; this.emit("ready", `${proto}://127.0.0.1:${addr.port}`); } async close() { if (this.#currentNuxt) await this.#currentNuxt.close(); } #closeWebSocketConnections() { for (const socket of this.#websocketConnections) socket.destroy(); this.#websocketConnections.clear(); } async #load(reload, reason) { const action = reload ? "Restarting" : "Starting"; this.#loadingMessage = `${reason ? `${reason}. ` : ""}${action} Nuxt...`; this.#handler = void 0; this.emit("loading", this.#loadingMessage); if (reload) console.info(this.#loadingMessage); await this.close(); const urls = await this.listener.getURLs().then((r) => r.map((r$1) => r$1.url)); await this.#loadNuxtInstance(urls); await this.#initializeNuxt(!!reload); } #watchConfig() { this.#configWatcher = createConfigWatcher(this.#cwd, this.options.dotenv.fileName, () => this.emit("restart"), (file) => this.loadDebounced(true, `${file} updated`)); } }; function getAddressURL(addr, https) { const proto = https ? "https" : "http"; let host = addr.address.includes(":") ? `[${addr.address}]` : addr.address; if (host === "[::]") host = "localhost"; const port = addr.port || 3e3; return `${proto}://${host}:${port}/`; } function resolveDevServerDefaults(listenOptions, urls = []) { const defaultConfig = {}; if (urls && urls.length > 0) defaultConfig.vite = { server: { allowedHosts: urls.map((u) => new URL(u).hostname) } }; if (listenOptions.hostname) { defaultConfig.devServer = { cors: { origin: [`${listenOptions.https ? "https" : "http"}://${listenOptions.hostname}`, ...urls] } }; defaultConfig.vite = defu(defaultConfig.vite, { server: { allowedHosts: [listenOptions.hostname] } }); } return defaultConfig; } function createConfigWatcher(cwd, dotenvFileName = ".env", onRestart, onReload) { const fileWatcher = new FileChangeTracker(); fileWatcher.prime(cwd); const configWatcher = watch(cwd); let configDirWatcher = existsSync(join(cwd, ".config")) ? createConfigDirWatcher(cwd, onReload) : void 0; const dotenvFileNames = new Set(Array.isArray(dotenvFileName) ? dotenvFileName : [dotenvFileName]); configWatcher.on("change", (_event, file) => { if (!fileWatcher.shouldEmitChange(resolve(cwd, file))) return; if (dotenvFileNames.has(file)) onRestart(); if (RESTART_RE.test(file)) onReload(file); if (file === ".config") configDirWatcher ||= createConfigDirWatcher(cwd, onReload); }); return () => { configWatcher.close(); configDirWatcher?.(); }; } function createConfigDirWatcher(cwd, onReload) { const configDir = join(cwd, ".config"); const fileWatcher = new FileChangeTracker(); fileWatcher.prime(configDir); const configDirWatcher = watch(configDir); configDirWatcher.on("change", (_event, file) => { if (!fileWatcher.shouldEmitChange(resolve(configDir, file))) return; if (RESTART_RE.test(file)) onReload(file); }); return () => configDirWatcher.close(); } async function resolveLoadingTemplate(cwd) { return (await import(pathToFileURL(resolveModulePath("@nuxt/ui-templates", { from: withNodePath(resolveModulePath("nuxt", { from: withNodePath(cwd), try: true }) || cwd) })).href)).loading || ((params) => `