@nuxt/cli
Advanced tools
| //#region ../nuxi/src/commands/_shared.ts | ||
| const cwdArgs = { cwd: { | ||
| type: "string", | ||
| description: "Specify the working directory", | ||
| valueHint: "directory", | ||
| default: "." | ||
| } }; | ||
| const logLevelArgs = { logLevel: { | ||
| type: "string", | ||
| description: "Specify build-time log level", | ||
| valueHint: "silent|info|verbose" | ||
| } }; | ||
| const envNameArgs = { envName: { | ||
| type: "string", | ||
| description: "The environment to use when resolving configuration overrides (default is `production` when building, and `development` when running the dev server)" | ||
| } }; | ||
| const dotEnvArgs = { dotenv: { | ||
| type: "string", | ||
| description: "Path to `.env` file to load, relative to the root directory" | ||
| } }; | ||
| const extendsArgs = { extends: { | ||
| type: "string", | ||
| description: "Extend from a Nuxt layer", | ||
| valueHint: "layer-name", | ||
| alias: ["e"] | ||
| } }; | ||
| const profileArgs = { profile: { | ||
| type: "string", | ||
| description: "Profile performance. Use --profile for CPU only, --profile=verbose for full report.", | ||
| default: void 0, | ||
| valueHint: "verbose" | ||
| } }; | ||
| const legacyRootDirArgs = { | ||
| cwd: { | ||
| ...cwdArgs.cwd, | ||
| description: "Specify the working directory, this takes precedence over ROOTDIR (default: `.`)", | ||
| default: void 0 | ||
| }, | ||
| rootDir: { | ||
| type: "positional", | ||
| description: "Specifies the working directory (default: `.`)", | ||
| required: false, | ||
| default: "." | ||
| } | ||
| }; | ||
| //#endregion | ||
| export { legacyRootDirArgs as a, extendsArgs as i, dotEnvArgs as n, logLevelArgs as o, envNameArgs as r, profileArgs as s, cwdArgs as t }; |
| import { satisfies } from "semver"; | ||
| import { $fetch } from "ofetch"; | ||
| import { parseINI } from "confbox"; | ||
| //#region ../nuxi/src/commands/module/_utils.ts | ||
| async function fetchModules() { | ||
| const { modules } = await $fetch(`https://api.nuxt.com/modules?version=all`); | ||
| return modules; | ||
| } | ||
| function checkNuxtCompatibility(module, nuxtVersion) { | ||
| if (!module.compatibility?.nuxt) return true; | ||
| return satisfies(nuxtVersion, module.compatibility.nuxt, { includePrerelease: true }); | ||
| } | ||
| function getRegistryFromContent(content, scope) { | ||
| try { | ||
| const npmConfig = parseINI(content); | ||
| if (scope) { | ||
| const scopeKey = `${scope}:registry`; | ||
| if (npmConfig[scopeKey]) return npmConfig[scopeKey].trim(); | ||
| } | ||
| if (npmConfig.registry) return npmConfig.registry.trim(); | ||
| return null; | ||
| } catch { | ||
| return null; | ||
| } | ||
| } | ||
| //#endregion | ||
| export { fetchModules as n, getRegistryFromContent as r, checkNuxtCompatibility as t }; |
| import { o as logLevelArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { r as relativeToProcess } from "./kit-BzPscsEd.mjs"; | ||
| import { t as getNuxtVersion } from "./versions--iBjrFVR.mjs"; | ||
| import { n as fetchModules, r as getRegistryFromContent, t as checkNuxtCompatibility } from "./_utils-D57pBv3m.mjs"; | ||
| import { t as prepare_default } from "./prepare-DZj9Ie1E.mjs"; | ||
| import { join } from "node:path"; | ||
| import process from "node:process"; | ||
| import { defineCommand, runCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { hasTTY } from "std-env"; | ||
| import { autocompleteMultiselect, cancel, confirm, isCancel, select, spinner } from "@clack/prompts"; | ||
| import { fileURLToPath } from "node:url"; | ||
| import * as fs from "node:fs"; | ||
| import { existsSync } from "node:fs"; | ||
| import { resolve as resolve$1 } from "pathe"; | ||
| import { joinURL } from "ufo"; | ||
| import { readPackageJSON } from "pkg-types"; | ||
| import { satisfies } from "semver"; | ||
| import { homedir } from "node:os"; | ||
| import { addDependency, detectPackageManager } from "nypm"; | ||
| import { $fetch } from "ofetch"; | ||
| import { Fzf, byLengthAsc } from "fzf"; | ||
| import { updateConfig } from "c12/update"; | ||
| //#region ../nuxi/src/commands/_utils.ts | ||
| const nuxiCommands = [ | ||
| "add", | ||
| "add-template", | ||
| "analyze", | ||
| "build", | ||
| "cleanup", | ||
| "_dev", | ||
| "dev", | ||
| "devtools", | ||
| "generate", | ||
| "info", | ||
| "init", | ||
| "module", | ||
| "prepare", | ||
| "preview", | ||
| "start", | ||
| "test", | ||
| "typecheck", | ||
| "upgrade" | ||
| ]; | ||
| function isNuxiCommand(command) { | ||
| return nuxiCommands.includes(command); | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/run.ts | ||
| globalThis.__nuxt_cli__ = globalThis.__nuxt_cli__ || { | ||
| startTime: Date.now(), | ||
| entry: fileURLToPath(new URL("../../bin/nuxi.mjs", import.meta.url)), | ||
| devEntry: fileURLToPath(new URL("../dev/index.mjs", import.meta.url)) | ||
| }; | ||
| async function runCommand$1(command, argv = process.argv.slice(2), data = {}) { | ||
| argv.push("--no-clear"); | ||
| if (command.meta && "name" in command.meta && typeof command.meta.name === "string") { | ||
| const name = command.meta.name; | ||
| if (!isNuxiCommand(name)) throw new Error(`Invalid command ${name}`); | ||
| } else throw new Error(`Invalid command, must be named`); | ||
| return await runCommand(command, { | ||
| rawArgs: argv, | ||
| data: { overrides: data.overrides || {} } | ||
| }); | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/commands/module/_autocomplete.ts | ||
| const TRAILING_DOT_RE = /\.$/; | ||
| /** | ||
| * Interactive fuzzy search for selecting Nuxt modules | ||
| * Returns object with selected module npm package names and cancellation status | ||
| */ | ||
| async function selectModulesAutocomplete(options) { | ||
| const { modules, message = "Search and select modules:" } = options; | ||
| if (!hasTTY) { | ||
| logger.warn("Interactive module selection requires a TTY. Skipping."); | ||
| return { | ||
| selected: [], | ||
| cancelled: false | ||
| }; | ||
| } | ||
| const sortedModules = modules.toSorted((a, b) => { | ||
| if (a.type === "official" && b.type !== "official") return -1; | ||
| if (a.type !== "official" && b.type === "official") return 1; | ||
| return a.npm.localeCompare(b.npm); | ||
| }); | ||
| const fzf = new Fzf(sortedModules, { | ||
| selector: (m) => `${m.npm} ${m.name} ${m.category}`, | ||
| casing: "case-insensitive", | ||
| tiebreakers: [byLengthAsc] | ||
| }); | ||
| const clackOptions = sortedModules.map((m) => ({ | ||
| value: m.npm, | ||
| label: m.npm, | ||
| hint: m.description.replace(TRAILING_DOT_RE, "") | ||
| })); | ||
| const filter = (search, option) => { | ||
| if (!search) return true; | ||
| return fzf.find(search).some((r) => r.item.npm === option.value); | ||
| }; | ||
| const result = await autocompleteMultiselect({ | ||
| message, | ||
| options: clackOptions, | ||
| filter, | ||
| required: false | ||
| }); | ||
| if (isCancel(result)) return { | ||
| selected: [], | ||
| cancelled: true | ||
| }; | ||
| return { | ||
| selected: result, | ||
| cancelled: false | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/commands/module/add.ts | ||
| const PROTOCOL_RE = /^https?:\/\//; | ||
| const TRAILING_SLASH_RE = /\/$/; | ||
| const REGEX_SPECIAL_RE = /[.*+?^${}()|[\]\\]/g; | ||
| var add_default = defineCommand({ | ||
| meta: { | ||
| name: "add", | ||
| description: "Add Nuxt modules" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| moduleName: { | ||
| type: "positional", | ||
| description: "Specify one or more modules to install by name, separated by spaces" | ||
| }, | ||
| skipInstall: { | ||
| type: "boolean", | ||
| description: "Skip npm install" | ||
| }, | ||
| skipConfig: { | ||
| type: "boolean", | ||
| description: "Skip nuxt.config.ts update" | ||
| }, | ||
| dev: { | ||
| type: "boolean", | ||
| description: "Install modules as dev dependencies" | ||
| } | ||
| }, | ||
| async setup(ctx) { | ||
| const cwd = resolve$1(ctx.args.cwd); | ||
| let modules = ctx.args._.map((e) => e.trim()).filter(Boolean); | ||
| const projectPkg = await readPackageJSON(cwd).catch(() => ({})); | ||
| if (!projectPkg.dependencies?.nuxt && !projectPkg.devDependencies?.nuxt) { | ||
| logger.warn(`No ${colors.cyan("nuxt")} dependency detected in ${colors.cyan(relativeToProcess(cwd))}.`); | ||
| const shouldContinue = await confirm({ | ||
| message: `Do you want to continue anyway?`, | ||
| initialValue: false | ||
| }); | ||
| if (isCancel(shouldContinue) || shouldContinue !== true) process.exit(1); | ||
| } | ||
| if (modules.length === 0) { | ||
| const modulesSpinner = spinner(); | ||
| modulesSpinner.start("Fetching available modules"); | ||
| const [allModules, nuxtVersion] = await Promise.all([fetchModules(), getNuxtVersion(cwd)]); | ||
| const compatibleModules = allModules.filter((m) => !m.compatibility.nuxt || checkNuxtCompatibility(m, nuxtVersion)); | ||
| modulesSpinner.stop("Modules loaded"); | ||
| const result = await selectModulesAutocomplete({ | ||
| modules: compatibleModules, | ||
| message: "Search modules to add (Esc to finish):" | ||
| }); | ||
| if (result.selected.length === 0) { | ||
| cancel("No modules selected."); | ||
| process.exit(0); | ||
| } | ||
| modules = result.selected; | ||
| } | ||
| const resolvedModules = []; | ||
| for (const moduleName of modules) { | ||
| const resolvedModule = await resolveModule(moduleName, cwd); | ||
| if (resolvedModule) resolvedModules.push(resolvedModule); | ||
| } | ||
| if (resolvedModules.length === 0) { | ||
| cancel("No modules to add."); | ||
| process.exit(1); | ||
| } | ||
| logger.info(`Resolved ${resolvedModules.map((x) => colors.cyan(x.pkgName)).join(", ")}, adding module${resolvedModules.length > 1 ? "s" : ""}...`); | ||
| await addModules(resolvedModules, { | ||
| ...ctx.args, | ||
| cwd | ||
| }, projectPkg); | ||
| if (!ctx.args.skipInstall) await runCommand$1(prepare_default, Object.entries(ctx.args).filter(([k]) => k in cwdArgs || k in logLevelArgs).map(([k, v]) => `--${k}=${v}`)); | ||
| } | ||
| }); | ||
| async function addModules(modules, { skipInstall = false, skipConfig = false, cwd, dev = false }, projectPkg) { | ||
| if (!skipInstall) { | ||
| const installedModules = []; | ||
| const notInstalledModules = []; | ||
| const dependencies = new Set([...Object.keys(projectPkg.dependencies || {}), ...Object.keys(projectPkg.devDependencies || {})]); | ||
| for (const module of modules) if (dependencies.has(module.pkgName)) installedModules.push(module); | ||
| else notInstalledModules.push(module); | ||
| if (installedModules.length > 0) { | ||
| const installedModulesList = installedModules.map((module) => colors.cyan(module.pkgName)).join(", "); | ||
| const are = installedModules.length > 1 ? "are" : "is"; | ||
| logger.info(`${installedModulesList} ${are} already installed`); | ||
| } | ||
| if (notInstalledModules.length > 0) { | ||
| const isDev = Boolean(projectPkg.devDependencies?.nuxt) || dev; | ||
| const notInstalledModulesList = notInstalledModules.map((module) => colors.cyan(module.pkg)).join(", "); | ||
| const dependency = notInstalledModules.length > 1 ? "dependencies" : "dependency"; | ||
| const a = notInstalledModules.length > 1 ? "" : " a"; | ||
| logger.info(`Installing ${notInstalledModulesList} as${a}${isDev ? " development" : ""} ${dependency}`); | ||
| const packageManager = await detectPackageManager(cwd); | ||
| if (await addDependency(notInstalledModules.map((module) => module.pkg), { | ||
| cwd, | ||
| dev: isDev, | ||
| installPeerDependencies: true, | ||
| packageManager, | ||
| workspace: packageManager?.name === "pnpm" && existsSync(resolve$1(cwd, "pnpm-workspace.yaml")) | ||
| }).then(() => true).catch(async (error) => { | ||
| logger.error(String(error)); | ||
| const result = await confirm({ | ||
| message: `Install failed for ${notInstalledModules.map((module) => colors.cyan(module.pkg)).join(", ")}. Do you want to continue adding the module${notInstalledModules.length > 1 ? "s" : ""} to ${colors.cyan("nuxt.config")}?`, | ||
| initialValue: false | ||
| }); | ||
| if (isCancel(result)) return false; | ||
| return result; | ||
| }) !== true) return; | ||
| } | ||
| } | ||
| if (!skipConfig) await updateConfig({ | ||
| cwd, | ||
| configFile: "nuxt.config", | ||
| async onCreate() { | ||
| logger.info(`Creating ${colors.cyan("nuxt.config.ts")}`); | ||
| return getDefaultNuxtConfig(); | ||
| }, | ||
| async onUpdate(config) { | ||
| if (!config.modules) config.modules = []; | ||
| for (const resolved of modules) { | ||
| if (config.modules.includes(resolved.pkgName)) { | ||
| logger.info(`${colors.cyan(resolved.pkgName)} is already in the ${colors.cyan("modules")}`); | ||
| continue; | ||
| } | ||
| logger.info(`Adding ${colors.cyan(resolved.pkgName)} to the ${colors.cyan("modules")}`); | ||
| config.modules.push(resolved.pkgName); | ||
| } | ||
| } | ||
| }).catch((error) => { | ||
| logger.error(`Failed to update ${colors.cyan("nuxt.config")}: ${error.message}`); | ||
| logger.error(`Please manually add ${colors.cyan(modules.map((module) => module.pkgName).join(", "))} to the ${colors.cyan("modules")} in ${colors.cyan("nuxt.config.ts")}`); | ||
| return null; | ||
| }); | ||
| } | ||
| function getDefaultNuxtConfig() { | ||
| return ` | ||
| // https://nuxt.com/docs/api/configuration/nuxt-config | ||
| export default defineNuxtConfig({ | ||
| modules: [] | ||
| })`; | ||
| } | ||
| const packageRegex = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?([a-z0-9-~][a-z0-9-._~]*)(@[^@]+)?$/; | ||
| async function resolveModule(moduleName, cwd) { | ||
| let pkgName = moduleName; | ||
| let pkgVersion; | ||
| const reMatch = moduleName.match(packageRegex); | ||
| if (reMatch) { | ||
| if (reMatch[3]) { | ||
| pkgName = `${reMatch[1] || ""}${reMatch[2] || ""}`; | ||
| pkgVersion = reMatch[3].slice(1); | ||
| } | ||
| } else { | ||
| logger.error(`Invalid package name ${colors.cyan(pkgName)}.`); | ||
| return false; | ||
| } | ||
| const matchedModule = (await fetchModules().catch((err) => { | ||
| logger.warn(`Cannot search in the Nuxt Modules database: ${err}`); | ||
| return []; | ||
| })).find((module) => module.name === moduleName || pkgVersion && module.name === pkgName || module.npm === pkgName || module.aliases?.includes(pkgName)); | ||
| if (matchedModule?.npm) pkgName = matchedModule.npm; | ||
| if (matchedModule && matchedModule.compatibility.nuxt) { | ||
| const nuxtVersion = await getNuxtVersion(cwd); | ||
| if (!checkNuxtCompatibility(matchedModule, nuxtVersion)) { | ||
| logger.warn(`The module ${colors.cyan(pkgName)} is not compatible with Nuxt ${colors.cyan(nuxtVersion)} (requires ${colors.cyan(matchedModule.compatibility.nuxt)})`); | ||
| const shouldContinue = await confirm({ | ||
| message: "Do you want to continue installing incompatible version?", | ||
| initialValue: false | ||
| }); | ||
| if (isCancel(shouldContinue) || !shouldContinue) return false; | ||
| } | ||
| const versionMap = matchedModule.compatibility.versionMap; | ||
| if (versionMap) { | ||
| for (const [_nuxtVersion, _moduleVersion] of Object.entries(versionMap)) if (satisfies(nuxtVersion, _nuxtVersion)) { | ||
| if (!pkgVersion) pkgVersion = _moduleVersion; | ||
| else { | ||
| logger.warn(`Recommended version of ${colors.cyan(pkgName)} for Nuxt ${colors.cyan(nuxtVersion)} is ${colors.cyan(_moduleVersion)} but you have requested ${colors.cyan(pkgVersion)}.`); | ||
| const result = await select({ | ||
| message: "Choose a version:", | ||
| options: [{ | ||
| value: _moduleVersion, | ||
| label: _moduleVersion | ||
| }, { | ||
| value: pkgVersion, | ||
| label: pkgVersion | ||
| }] | ||
| }); | ||
| if (isCancel(result)) return false; | ||
| pkgVersion = result; | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| let version = pkgVersion || "latest"; | ||
| const meta = await detectNpmRegistry(pkgName.startsWith("@") ? pkgName.split("/")[0] : null); | ||
| const headers = {}; | ||
| if (meta.authToken) headers.Authorization = `Bearer ${meta.authToken}`; | ||
| const pkgDetails = await $fetch(joinURL(meta.registry, `${pkgName}`), { headers }).catch(() => null); | ||
| if (!pkgDetails) { | ||
| logger.error(`Failed to fetch package details for ${colors.cyan(pkgName)}.`); | ||
| return false; | ||
| } | ||
| if (pkgDetails["dist-tags"]?.[version]) version = pkgDetails["dist-tags"][version]; | ||
| else version = Object.keys(pkgDetails.versions)?.findLast((v) => satisfies(v, version)) || version; | ||
| const pkg = pkgDetails.versions[version] || {}; | ||
| const pkgDependencies = Object.assign(pkg.dependencies || {}, pkg.devDependencies || {}); | ||
| if (!pkgDependencies.nuxt && !pkgDependencies["nuxt-edge"] && !pkgDependencies["@nuxt/kit"]) { | ||
| logger.warn(`It seems that ${colors.cyan(pkgName)} is not a Nuxt module.`); | ||
| const shouldContinue = await confirm({ | ||
| message: `Do you want to continue installing ${colors.cyan(pkgName)} anyway?`, | ||
| initialValue: false | ||
| }); | ||
| if (isCancel(shouldContinue) || !shouldContinue) return false; | ||
| } | ||
| return { | ||
| nuxtModule: matchedModule, | ||
| pkg: `${pkgName}@${version}`, | ||
| pkgName, | ||
| pkgVersion: version | ||
| }; | ||
| } | ||
| function getNpmrcPaths() { | ||
| const userNpmrcPath = join(homedir(), ".npmrc"); | ||
| return [join(process.cwd(), ".npmrc"), userNpmrcPath]; | ||
| } | ||
| async function getAuthToken(registry) { | ||
| const paths = getNpmrcPaths(); | ||
| const registryHost = registry.replace(PROTOCOL_RE, "").replace(TRAILING_SLASH_RE, "").replace(REGEX_SPECIAL_RE, "\\$&"); | ||
| const authTokenRegex = new RegExp(`^//${registryHost}/:_authToken=(.+)$`, "m"); | ||
| for (const npmrcPath of paths) { | ||
| let fd; | ||
| try { | ||
| fd = await fs.promises.open(npmrcPath, "r"); | ||
| if (await fd.stat().then((r) => r.isFile())) { | ||
| const authTokenMatch = (await fd.readFile("utf-8")).match(authTokenRegex)?.[1]; | ||
| if (authTokenMatch) return authTokenMatch.trim(); | ||
| } | ||
| } catch {} finally { | ||
| await fd?.close(); | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| async function detectNpmRegistry(scope) { | ||
| const registry = await getRegistry(scope); | ||
| return { | ||
| registry, | ||
| authToken: await getAuthToken(registry) | ||
| }; | ||
| } | ||
| async function getRegistry(scope) { | ||
| if (process.env.COREPACK_NPM_REGISTRY) return process.env.COREPACK_NPM_REGISTRY; | ||
| const registry = await getRegistryFromFile(getNpmrcPaths(), scope); | ||
| if (registry) process.env.COREPACK_NPM_REGISTRY = registry; | ||
| return registry || "https://registry.npmjs.org"; | ||
| } | ||
| async function getRegistryFromFile(paths, scope) { | ||
| for (const npmrcPath of paths) { | ||
| let fd; | ||
| try { | ||
| fd = await fs.promises.open(npmrcPath, "r"); | ||
| if (await fd.stat().then((r) => r.isFile())) { | ||
| const registry = getRegistryFromContent(await fd.readFile("utf-8"), scope); | ||
| if (registry) return registry; | ||
| } | ||
| } catch {} finally { | ||
| await fd?.close(); | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| //#endregion | ||
| export { add_default as default, runCommand$1 as n, selectModulesAutocomplete as t }; |
| import { o as logLevelArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { t as templateNames } from "./names-C5-M0i7H.mjs"; | ||
| import { r as relativeToProcess, t as loadKit } from "./kit-BzPscsEd.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { cancel, intro, outro } from "@clack/prompts"; | ||
| import { existsSync, promises } from "node:fs"; | ||
| import { dirname, extname, resolve } from "pathe"; | ||
| import { camelCase, pascalCase } from "scule"; | ||
| //#region ../nuxi/src/utils/templates/api.ts | ||
| const httpMethods = [ | ||
| "connect", | ||
| "delete", | ||
| "get", | ||
| "head", | ||
| "options", | ||
| "post", | ||
| "put", | ||
| "trace", | ||
| "patch" | ||
| ]; | ||
| const api = ({ name, args, nuxtOptions }) => { | ||
| return { | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, `api/${name}${applySuffix(args, httpMethods, "method")}.ts`), | ||
| contents: ` | ||
| export default defineEventHandler(event => { | ||
| return 'Hello ${name}' | ||
| }) | ||
| ` | ||
| }; | ||
| }; | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/app.ts | ||
| const app = ({ args, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, "app.vue"), | ||
| contents: args.pages ? ` | ||
| <script setup lang="ts"><\/script> | ||
| <template> | ||
| <div> | ||
| <NuxtLayout> | ||
| <NuxtPage/> | ||
| </NuxtLayout> | ||
| </div> | ||
| </template> | ||
| <style scoped></style> | ||
| ` : ` | ||
| <script setup lang="ts"><\/script> | ||
| <template> | ||
| <div> | ||
| <h1>Hello World!</h1> | ||
| </div> | ||
| </template> | ||
| <style scoped></style> | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/app-config.ts | ||
| const appConfig = ({ nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, "app.config.ts"), | ||
| contents: ` | ||
| export default defineAppConfig({}) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/component.ts | ||
| const component = ({ name, args, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, `components/${name}${applySuffix(args, ["client", "server"], "mode")}.vue`), | ||
| contents: ` | ||
| <script setup lang="ts"><\/script> | ||
| <template> | ||
| <div> | ||
| Component: ${name} | ||
| </div> | ||
| </template> | ||
| <style scoped></style> | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/composable.ts | ||
| const USE_PREFIX_RE = /^use-?/; | ||
| const composable = ({ name, nuxtOptions }) => { | ||
| const nameWithUsePrefix = `use${pascalCase(name.replace(USE_PREFIX_RE, ""))}`; | ||
| return { | ||
| path: resolve(nuxtOptions.srcDir, `composables/${name}.ts`), | ||
| contents: ` | ||
| export const ${nameWithUsePrefix} = () => { | ||
| return ref() | ||
| } | ||
| ` | ||
| }; | ||
| }; | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/error.ts | ||
| const error = ({ nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, "error.vue"), | ||
| contents: ` | ||
| <script setup lang="ts"> | ||
| import type { NuxtError } from '#app' | ||
| const props = defineProps({ | ||
| error: Object as () => NuxtError | ||
| }) | ||
| <\/script> | ||
| <template> | ||
| <div> | ||
| <h1>{{ error.statusCode }}</h1> | ||
| <NuxtLink to="/">Go back home</NuxtLink> | ||
| </div> | ||
| </template> | ||
| <style scoped></style> | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/layer.ts | ||
| const layer = ({ name, nuxtOptions }) => { | ||
| return { | ||
| path: resolve(nuxtOptions.rootDir, `layers/${name}/nuxt.config.ts`), | ||
| contents: ` | ||
| export default defineNuxtConfig({}) | ||
| ` | ||
| }; | ||
| }; | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/layout.ts | ||
| const layout = ({ name, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.layouts, `${name}.vue`), | ||
| contents: ` | ||
| <script setup lang="ts"><\/script> | ||
| <template> | ||
| <div> | ||
| Layout: ${name} | ||
| <slot /> | ||
| </div> | ||
| </template> | ||
| <style scoped></style> | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/middleware.ts | ||
| const middleware = ({ name, args, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.middleware, `${name}${applySuffix(args, ["global"])}.ts`), | ||
| contents: ` | ||
| export default defineNuxtRouteMiddleware((to, from) => {}) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/module.ts | ||
| const module = ({ name, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.rootDir, "modules", `${name}.ts`), | ||
| contents: ` | ||
| import { defineNuxtModule } from 'nuxt/kit' | ||
| export default defineNuxtModule({ | ||
| meta: { | ||
| name: '${name}' | ||
| }, | ||
| setup () {} | ||
| }) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/page.ts | ||
| const page = ({ name, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.pages, `${name}.vue`), | ||
| contents: ` | ||
| <script setup lang="ts"><\/script> | ||
| <template> | ||
| <div> | ||
| Page: ${name} | ||
| </div> | ||
| </template> | ||
| <style scoped></style> | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/plugin.ts | ||
| const plugin = ({ name, args, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.plugins, `${name}${applySuffix(args, ["client", "server"], "mode")}.ts`), | ||
| contents: ` | ||
| export default defineNuxtPlugin(nuxtApp => {}) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/server-middleware.ts | ||
| const serverMiddleware = ({ name, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, "middleware", `${name}.ts`), | ||
| contents: ` | ||
| export default defineEventHandler(event => {}) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/server-plugin.ts | ||
| const serverPlugin = ({ name, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, "plugins", `${name}.ts`), | ||
| contents: ` | ||
| export default defineNitroPlugin(nitroApp => {}) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/server-route.ts | ||
| const serverRoute = ({ name, args, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, args.api ? "api" : "routes", `${name}.ts`), | ||
| contents: ` | ||
| export default defineEventHandler(event => {}) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/server-util.ts | ||
| const serverUtil = ({ name, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, "utils", `${name}.ts`), | ||
| contents: ` | ||
| export function ${camelCase(name)}() {} | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/index.ts | ||
| const templates = { | ||
| "api": api, | ||
| "app": app, | ||
| "app-config": appConfig, | ||
| "component": component, | ||
| "composable": composable, | ||
| "error": error, | ||
| "layer": layer, | ||
| "layout": layout, | ||
| "middleware": middleware, | ||
| "module": module, | ||
| "page": page, | ||
| "plugin": plugin, | ||
| "server-middleware": serverMiddleware, | ||
| "server-plugin": serverPlugin, | ||
| "server-route": serverRoute, | ||
| "server-util": serverUtil | ||
| }; | ||
| function applySuffix(args, suffixes, unwrapFrom) { | ||
| let suffix = ""; | ||
| for (const s of suffixes) if (args[s]) suffix += `.${s}`; | ||
| if (unwrapFrom && args[unwrapFrom] && suffixes.includes(args[unwrapFrom])) suffix += `.${args[unwrapFrom]}`; | ||
| return suffix; | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/commands/add-template.ts | ||
| var add_template_default = defineCommand({ | ||
| meta: { | ||
| name: "add-template", | ||
| description: "Create a new template file." | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| force: { | ||
| type: "boolean", | ||
| description: "Force override file if it already exists", | ||
| default: false | ||
| }, | ||
| template: { | ||
| type: "positional", | ||
| required: true, | ||
| valueHint: templateNames.join("|"), | ||
| description: `Specify which template to generate` | ||
| }, | ||
| name: { | ||
| type: "positional", | ||
| required: true, | ||
| description: "Specify name of the generated file" | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| const cwd = resolve(ctx.args.cwd); | ||
| intro(colors.cyan("Adding template...")); | ||
| const templateName = ctx.args.template; | ||
| if (!templateNames.includes(templateName)) { | ||
| const templateNames = Object.keys(templates).map((name) => colors.cyan(name)); | ||
| const lastTemplateName = templateNames.pop(); | ||
| logger.error(`Template ${colors.cyan(templateName)} is not supported.`); | ||
| logger.info(`Possible values are ${templateNames.join(", ")} or ${lastTemplateName}.`); | ||
| process.exit(1); | ||
| } | ||
| const ext = extname(ctx.args.name); | ||
| const name = ext === ".vue" || ext === ".ts" ? ctx.args.name.replace(ext, "") : ctx.args.name; | ||
| if (!name) { | ||
| cancel("name argument is missing!"); | ||
| process.exit(1); | ||
| } | ||
| const config = await (await loadKit(cwd)).loadNuxtConfig({ cwd }); | ||
| const template = templates[templateName]; | ||
| const res = template({ | ||
| name, | ||
| args: ctx.args, | ||
| nuxtOptions: config | ||
| }); | ||
| if (!ctx.args.force && existsSync(res.path)) { | ||
| logger.error(`File exists at ${colors.cyan(relativeToProcess(res.path))}.`); | ||
| logger.info(`Use ${colors.cyan("--force")} to override or use a different name.`); | ||
| process.exit(1); | ||
| } | ||
| const parentDir = dirname(res.path); | ||
| if (!existsSync(parentDir)) { | ||
| logger.step(`Creating directory ${colors.cyan(relativeToProcess(parentDir))}.`); | ||
| if (templateName === "page") logger.info("This enables vue-router functionality!"); | ||
| await promises.mkdir(parentDir, { recursive: true }); | ||
| } | ||
| await promises.writeFile(res.path, `${res.contents.trim()}\n`); | ||
| logger.success(`Created ${colors.cyan(relativeToProcess(res.path))}.`); | ||
| outro(`Generated a new ${colors.cyan(templateName)}!`); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { add_template_default as default }; |
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { t as overrideEnv } from "./env-BfWVBvy7.mjs"; | ||
| import { r as relativeToProcess, t as loadKit } from "./kit-BzPscsEd.mjs"; | ||
| import { n as clearDir } from "./fs-B0HqP3GX.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { intro, note, outro, taskLog } from "@clack/prompts"; | ||
| import { defu as defu$1 } from "defu"; | ||
| import { promises } from "node:fs"; | ||
| import { join, resolve } from "pathe"; | ||
| import { FastResponse, FastURL, serve } from "srvx"; | ||
| //#region ../../node_modules/.pnpm/rou3@0.8.1/node_modules/rou3/dist/index.mjs | ||
| const NullProtoObj = /* @__PURE__ */ (() => { | ||
| const e = function() {}; | ||
| return e.prototype = Object.create(null), Object.freeze(e.prototype), e; | ||
| })(); | ||
| /** | ||
| * Create a new router context. | ||
| */ | ||
| function createRouter() { | ||
| return { | ||
| root: { key: "" }, | ||
| static: new NullProtoObj() | ||
| }; | ||
| } | ||
| function expandGroupDelimiters(path) { | ||
| let i = 0; | ||
| let depth = 0; | ||
| for (; i < path.length; i++) { | ||
| const c = path.charCodeAt(i); | ||
| if (c === 92) { | ||
| i++; | ||
| continue; | ||
| } | ||
| if (c === 40) { | ||
| depth++; | ||
| continue; | ||
| } | ||
| if (c === 41 && depth > 0) { | ||
| depth--; | ||
| continue; | ||
| } | ||
| if (c === 123 && depth === 0) break; | ||
| } | ||
| if (i >= path.length) return; | ||
| let j = i + 1; | ||
| depth = 0; | ||
| for (; j < path.length; j++) { | ||
| const c = path.charCodeAt(j); | ||
| if (c === 92) { | ||
| j++; | ||
| continue; | ||
| } | ||
| if (c === 40) { | ||
| depth++; | ||
| continue; | ||
| } | ||
| if (c === 41 && depth > 0) { | ||
| depth--; | ||
| continue; | ||
| } | ||
| if (c === 125 && depth === 0) break; | ||
| } | ||
| if (j >= path.length) return; | ||
| const mod = path[j + 1]; | ||
| const hasMod = mod === "?" || mod === "+" || mod === "*"; | ||
| const pre = path.slice(0, i); | ||
| const body = path.slice(i + 1, j); | ||
| const suf = path.slice(j + (hasMod ? 2 : 1)); | ||
| if (!hasMod) return [pre + body + suf]; | ||
| if (mod === "?") return [pre + body + suf, pre + suf]; | ||
| if (body.includes("/")) throw new Error("unsupported group repetition across segments"); | ||
| return [`${pre}(?:${body})${mod}${suf}`]; | ||
| } | ||
| const UNNAMED_GROUP_PREFIX = "__rou3_unnamed_"; | ||
| const _unnamedGroupPrefixLength = 15; | ||
| function hasSegmentWildcard(segment) { | ||
| let depth = 0; | ||
| for (let i = 0; i < segment.length; i++) { | ||
| const ch = segment.charCodeAt(i); | ||
| if (ch === 92) { | ||
| i++; | ||
| continue; | ||
| } | ||
| if (ch === 40) { | ||
| depth++; | ||
| continue; | ||
| } | ||
| if (ch === 41 && depth > 0) { | ||
| depth--; | ||
| continue; | ||
| } | ||
| if (ch === 42 && depth === 0) return true; | ||
| } | ||
| return false; | ||
| } | ||
| function replaceSegmentWildcards(segment, unnamedStart, toGroupKey = toUnnamedGroupKey) { | ||
| let depth = 0; | ||
| let nextIndex = unnamedStart; | ||
| let replaced = ""; | ||
| for (let i = 0; i < segment.length; i++) { | ||
| const ch = segment.charCodeAt(i); | ||
| if (ch === 92) { | ||
| replaced += segment[i]; | ||
| if (i + 1 < segment.length) replaced += segment[++i]; | ||
| continue; | ||
| } | ||
| if (ch === 40) { | ||
| depth++; | ||
| replaced += segment[i]; | ||
| continue; | ||
| } | ||
| if (ch === 41 && depth > 0) { | ||
| depth--; | ||
| replaced += segment[i]; | ||
| continue; | ||
| } | ||
| if (ch === 42 && depth === 0) { | ||
| replaced += `(?<${toGroupKey(nextIndex++)}>[^/]*)`; | ||
| continue; | ||
| } | ||
| replaced += segment[i]; | ||
| } | ||
| return [replaced, nextIndex]; | ||
| } | ||
| function toUnnamedGroupKey(index) { | ||
| return `${UNNAMED_GROUP_PREFIX}${index}`; | ||
| } | ||
| function normalizeUnnamedGroupKey(key) { | ||
| return key.startsWith("__rou3_unnamed_") ? key.slice(_unnamedGroupPrefixLength) : key; | ||
| } | ||
| function encodeEscapes(path) { | ||
| return path.replace(/\\:/g, "�A").replace(/\\\(/g, "�B").replace(/\\\)/g, "�C").replace(/\\\{/g, "�D").replace(/\\\}/g, "�E"); | ||
| } | ||
| function decodeEscaped(segment) { | ||
| return segment.replace(/\uFFFD([A-E])/g, (_, c) => c === "A" ? ":" : c === "B" ? "(" : c === "C" ? ")" : c === "D" ? "{" : "}"); | ||
| } | ||
| function expandModifiers(segments) { | ||
| for (let i = 0; i < segments.length; i++) { | ||
| const m = segments[i].match(/^(.*:[\w-]+(?:\([^)]*\))?)([?+*])$/); | ||
| if (!m) continue; | ||
| const pre = segments.slice(0, i); | ||
| const suf = segments.slice(i + 1); | ||
| if (m[2] === "?") return ["/" + pre.concat(m[1]).concat(suf).join("/"), "/" + pre.concat(suf).join("/")]; | ||
| const name = m[1].match(/:([\w-]+)/)?.[1] || "_"; | ||
| const wc = "/" + [ | ||
| ...pre, | ||
| `**:${name}`, | ||
| ...suf | ||
| ].join("/"); | ||
| const without = "/" + [...pre, ...suf].join("/"); | ||
| return m[2] === "+" ? [wc] : [wc, without]; | ||
| } | ||
| } | ||
| function normalizePath(path) { | ||
| if (!path.includes("/.")) return path; | ||
| const r = []; | ||
| for (const s of path.split("/")) if (s === ".") continue; | ||
| else if (s === ".." && r.length > 1) r.pop(); | ||
| else r.push(s); | ||
| return r.join("/") || "/"; | ||
| } | ||
| function splitPath(path) { | ||
| const [_, ...s] = path.split("/"); | ||
| return s[s.length - 1] === "" ? s.slice(0, -1) : s; | ||
| } | ||
| function getMatchParams(segments, paramsMap) { | ||
| const params = new NullProtoObj(); | ||
| for (const [index, name] of paramsMap) { | ||
| const segment = index < 0 ? segments.slice(-(index + 1)).join("/") : segments[index]; | ||
| if (typeof name === "string") params[name] = segment; | ||
| else { | ||
| const match = segment.match(name); | ||
| if (match) for (const key in match.groups) params[normalizeUnnamedGroupKey(key)] = match.groups[key]; | ||
| } | ||
| } | ||
| return params; | ||
| } | ||
| /** | ||
| * Add a route to the router context. | ||
| */ | ||
| function addRoute(ctx, method = "", path, data) { | ||
| method = method.toUpperCase(); | ||
| if (path.charCodeAt(0) !== 47) path = `/${path}`; | ||
| const groupExpanded = expandGroupDelimiters(path); | ||
| if (groupExpanded) { | ||
| for (const expandedPath of groupExpanded) addRoute(ctx, method, expandedPath, data); | ||
| return; | ||
| } | ||
| path = encodeEscapes(path); | ||
| const segments = splitPath(path); | ||
| const expanded = expandModifiers(segments); | ||
| if (expanded) { | ||
| for (const p of expanded) addRoute(ctx, method, p, data); | ||
| return; | ||
| } | ||
| let node = ctx.root; | ||
| let _unnamedParamIndex = 0; | ||
| const paramsMap = []; | ||
| const paramsRegexp = []; | ||
| for (let i = 0; i < segments.length; i++) { | ||
| let segment = segments[i]; | ||
| if (segment.startsWith("**")) { | ||
| if (!node.wildcard) node.wildcard = { key: "**" }; | ||
| node = node.wildcard; | ||
| paramsMap.push([ | ||
| -(i + 1), | ||
| segment.split(":")[1] || "_", | ||
| segment.length === 2 | ||
| ]); | ||
| break; | ||
| } | ||
| if (segment === "*" || segment.includes(":") || segment.includes("(") || hasSegmentWildcard(segment)) { | ||
| if (!node.param) node.param = { key: "*" }; | ||
| node = node.param; | ||
| if (segment === "*") paramsMap.push([ | ||
| i, | ||
| String(_unnamedParamIndex++), | ||
| true | ||
| ]); | ||
| else if (segment.includes(":", 1) || segment.includes("(") || hasSegmentWildcard(segment) || !/^:[\w-]+$/.test(segment)) { | ||
| const [regexp, nextIndex] = getParamRegexp(segment, _unnamedParamIndex); | ||
| _unnamedParamIndex = nextIndex; | ||
| paramsRegexp[i] = regexp; | ||
| node.hasRegexParam = true; | ||
| paramsMap.push([ | ||
| i, | ||
| regexp, | ||
| false | ||
| ]); | ||
| } else paramsMap.push([ | ||
| i, | ||
| segment.slice(1), | ||
| false | ||
| ]); | ||
| continue; | ||
| } | ||
| if (segment === "\\*") segment = segments[i] = "*"; | ||
| else if (segment === "\\*\\*") segment = segments[i] = "**"; | ||
| segment = segments[i] = decodeEscaped(segment); | ||
| const child = node.static?.[segment]; | ||
| if (child) node = child; | ||
| else { | ||
| const staticNode = { key: segment }; | ||
| if (!node.static) node.static = new NullProtoObj(); | ||
| node.static[segment] = staticNode; | ||
| node = staticNode; | ||
| } | ||
| } | ||
| const hasParams = paramsMap.length > 0; | ||
| if (!node.methods) node.methods = new NullProtoObj(); | ||
| node.methods[method] ??= []; | ||
| node.methods[method].push({ | ||
| data: data || null, | ||
| paramsRegexp, | ||
| paramsMap: hasParams ? paramsMap : void 0 | ||
| }); | ||
| if (!hasParams) ctx.static["/" + segments.join("/")] = node; | ||
| } | ||
| function getParamRegexp(segment, unnamedStart = 0) { | ||
| let _i = unnamedStart; | ||
| let _s = "", _d = 0; | ||
| for (let j = 0; j < segment.length; j++) { | ||
| const c = segment.charCodeAt(j); | ||
| if (c === 40) _d++; | ||
| else if (c === 41 && _d > 0) _d--; | ||
| else if (c === 92 && _d === 0 && j + 1 < segment.length) { | ||
| const n = segment[j + 1]; | ||
| if (n !== ":" && n !== "(" && n !== "*" && n !== "\\") { | ||
| _s += "" + n; | ||
| j++; | ||
| continue; | ||
| } | ||
| } | ||
| _s += segment[j]; | ||
| } | ||
| [_s, _i] = replaceSegmentWildcards(_s, _i); | ||
| const regex = _s.replace(/:([\w-]+)(?:\(([^)]*)\))?/g, (_, id, p) => `(?<${id}>${p || "[^/]+"})`).replace(/\((?![?<])/g, () => `(?<${toUnnamedGroupKey(_i++)}>`).replace(/\./g, "\\.").replace(/\uFFFE(.)/g, (_, c) => /[.*+?^${}()|[\]\\]/.test(c) ? `\\${c}` : c); | ||
| return [new RegExp(`^${regex}$`), _i]; | ||
| } | ||
| /** | ||
| * Find a route by path. | ||
| */ | ||
| function findRoute(ctx, method = "", path, opts) { | ||
| if (opts?.normalize) path = normalizePath(path); | ||
| if (path.charCodeAt(path.length - 1) === 47) path = path.slice(0, -1); | ||
| const staticNode = ctx.static[path]; | ||
| if (staticNode && staticNode.methods) { | ||
| const staticMatch = staticNode.methods[method] || staticNode.methods[""]; | ||
| if (staticMatch !== void 0) return staticMatch[0]; | ||
| } | ||
| const segments = splitPath(path); | ||
| const match = _lookupTree(ctx.root, method, segments, 0)?.[0]; | ||
| if (match === void 0) return; | ||
| if (opts?.params === false) return match; | ||
| return { | ||
| data: match.data, | ||
| params: match.paramsMap ? getMatchParams(segments, match.paramsMap) : void 0 | ||
| }; | ||
| } | ||
| function _lookupTree(node, method, segments, index) { | ||
| if (index === segments.length) { | ||
| if (node.methods) { | ||
| const match = node.methods[method] || node.methods[""]; | ||
| if (match) return match; | ||
| } | ||
| if (node.param && node.param.methods) { | ||
| const match = node.param.methods[method] || node.param.methods[""]; | ||
| if (match) { | ||
| const pMap = match[0].paramsMap; | ||
| if (pMap?.[pMap?.length - 1]?.[2]) return match; | ||
| } | ||
| } | ||
| if (node.wildcard && node.wildcard.methods) { | ||
| const match = node.wildcard.methods[method] || node.wildcard.methods[""]; | ||
| if (match) { | ||
| const pMap = match[0].paramsMap; | ||
| if (pMap?.[pMap?.length - 1]?.[2]) return match; | ||
| } | ||
| } | ||
| return; | ||
| } | ||
| const segment = segments[index]; | ||
| if (node.static) { | ||
| const staticChild = node.static[segment]; | ||
| if (staticChild) { | ||
| const match = _lookupTree(staticChild, method, segments, index + 1); | ||
| if (match) return match; | ||
| } | ||
| } | ||
| if (node.param) { | ||
| const match = _lookupTree(node.param, method, segments, index + 1); | ||
| if (match) { | ||
| if (node.param.hasRegexParam) { | ||
| const exactMatch = match.find((m) => m.paramsRegexp[index]?.test(segment)) || match.find((m) => !m.paramsRegexp[index]); | ||
| return exactMatch ? [exactMatch] : void 0; | ||
| } | ||
| return match; | ||
| } | ||
| } | ||
| if (node.wildcard && node.wildcard.methods) return node.wildcard.methods[method] || node.wildcard.methods[""]; | ||
| } | ||
| const _P = ""; | ||
| function replaceEscapesOutsideGroups(segment) { | ||
| let r = "", d = 0; | ||
| for (let i = 0; i < segment.length; i++) { | ||
| const c = segment.charCodeAt(i); | ||
| if (c === 40) d++; | ||
| else if (c === 41 && d > 0) d--; | ||
| else if (c === 92 && d === 0 && i + 1 < segment.length) { | ||
| const n = segment[i + 1]; | ||
| if (n !== ":" && n !== "(" && n !== "*" && n !== "\\") { | ||
| r += _P + n; | ||
| i++; | ||
| continue; | ||
| } | ||
| } | ||
| r += segment[i]; | ||
| } | ||
| return r; | ||
| } | ||
| function resolveEscapePlaceholders(str) { | ||
| return str.replace(/\uFFFE(.)/g, (_, c) => /[.*+?^${}()|[\]\\]/.test(c) ? `\\${c}` : c); | ||
| } | ||
| function routeToRegExp(route = "/") { | ||
| const groupExpanded = expandGroupDelimiters(route); | ||
| if (groupExpanded) { | ||
| const sources = groupExpanded.map((expandedRoute) => routeToRegExp(expandedRoute).source.slice(1, -1)); | ||
| return new RegExp(`^(?:${sources.join("|")})$`); | ||
| } | ||
| return _routeToRegExp(route); | ||
| } | ||
| function _routeToRegExp(route) { | ||
| const reSegments = []; | ||
| let idCtr = 0; | ||
| for (const segment of route.split("/")) { | ||
| if (!segment) continue; | ||
| if (segment === "*") reSegments.push(`(?<${toRegExpUnnamedKey(idCtr++)}>[^/]*)`); | ||
| else if (segment.startsWith("**")) reSegments.push(segment === "**" ? "?(?<_>.*)" : `?(?<${segment.slice(3)}>.+)`); | ||
| else if (segment.includes(":") || /(^|[^\\])\(/.test(segment) || hasSegmentWildcard(segment)) { | ||
| const modMatch = segment.match(/^(.*:[\w-]+(?:\([^)]*\))?)([?+*])$/); | ||
| if (modMatch) { | ||
| const [, base, mod] = modMatch; | ||
| const name = base.match(/:([\w-]+)/)?.[1] || `_${idCtr++}`; | ||
| if (mod === "?") { | ||
| const inner = base.replace(/:([\w-]+)(?:\(([^)]*)\))?/g, (_, id, pattern) => `(?<${id}>${pattern || "[^/]+"})`).replace(/\./g, "\\."); | ||
| if (reSegments.length > 0) { | ||
| const prevQ = reSegments.pop(); | ||
| reSegments.push(`${prevQ}(?:/${inner})?`); | ||
| } else reSegments.push(`?${inner}?`); | ||
| continue; | ||
| } | ||
| const pattern = base.match(/:(\w+)(?:\(([^)]*)\))?/)?.[2]; | ||
| if (reSegments.length > 0) { | ||
| const prevMod = reSegments.pop(); | ||
| if (pattern) { | ||
| const repeated = `${pattern}(?:/${pattern})*`; | ||
| reSegments.push(mod === "+" ? `${prevMod}/(?<${name}>${repeated})` : `${prevMod}(?:/(?<${name}>${repeated}))?`); | ||
| } else reSegments.push(mod === "+" ? `${prevMod}/(?<${name}>.+)` : `${prevMod}(?:/(?<${name}>.*))?`); | ||
| } else if (pattern) { | ||
| const repeated = `${pattern}(?:/${pattern})*`; | ||
| reSegments.push(mod === "+" ? `?(?<${name}>${repeated})` : `?(?<${name}>${repeated})?`); | ||
| } else reSegments.push(mod === "+" ? `?(?<${name}>.+)` : `?(?<${name}>.*)`); | ||
| continue; | ||
| } | ||
| let dynamicSegment = replaceEscapesOutsideGroups(segment); | ||
| [dynamicSegment, idCtr] = replaceSegmentWildcards(dynamicSegment, idCtr, toRegExpUnnamedKey); | ||
| reSegments.push(resolveEscapePlaceholders(dynamicSegment.replace(/:([\w-]+)(?:\(([^)]*)\))?/g, (_, id, pattern) => `(?<${id}>${pattern || "[^/]+"})`).replace(/(^|[^\\])\((?![?<])/g, (_, p) => `${p}(?<${toRegExpUnnamedKey(idCtr++)}>`).replace(/\./g, "\\."))); | ||
| } else reSegments.push(segment.replace(/\\(.)/g, "$1").replace(/[.*+?^${}()|[\]]/g, "\\$&")); | ||
| } | ||
| return new RegExp(`^/${reSegments.join("/")}/?$`); | ||
| } | ||
| function toRegExpUnnamedKey(index) { | ||
| return `_${index}`; | ||
| } | ||
| //#endregion | ||
| //#region ../../node_modules/.pnpm/h3@2.0.1-rc.20_crossws@0.4.5_srvx@0.11.15_/node_modules/h3/dist/h3-Bz4OPZv_.mjs | ||
| function decodePathname(pathname) { | ||
| return decodeURI(pathname.includes("%25") ? pathname.replace(/%25/g, "%2525") : pathname); | ||
| } | ||
| const kEventNS = "h3.internal.event."; | ||
| const kEventRes = /* @__PURE__ */ Symbol.for(`${kEventNS}res`); | ||
| const kEventResHeaders = /* @__PURE__ */ Symbol.for(`${kEventNS}res.headers`); | ||
| const kEventResErrHeaders = /* @__PURE__ */ Symbol.for(`${kEventNS}res.err.headers`); | ||
| var H3Event = class { | ||
| app; | ||
| req; | ||
| url; | ||
| context; | ||
| static __is_event__ = true; | ||
| constructor(req, context, app) { | ||
| this.context = context || req.context || new NullProtoObj(); | ||
| this.req = req; | ||
| this.app = app; | ||
| const _url = req._url; | ||
| const url = _url && _url instanceof URL ? _url : new FastURL(req.url); | ||
| if (url.pathname.includes("%")) url.pathname = decodePathname(url.pathname); | ||
| this.url = url; | ||
| } | ||
| get res() { | ||
| return this[kEventRes] ||= new H3EventResponse(); | ||
| } | ||
| get runtime() { | ||
| return this.req.runtime; | ||
| } | ||
| waitUntil(promise) { | ||
| this.req.waitUntil?.(promise); | ||
| } | ||
| toString() { | ||
| return `[${this.req.method}] ${this.req.url}`; | ||
| } | ||
| toJSON() { | ||
| return this.toString(); | ||
| } | ||
| get node() { | ||
| return this.req.runtime?.node; | ||
| } | ||
| get headers() { | ||
| return this.req.headers; | ||
| } | ||
| get path() { | ||
| return this.url.pathname + this.url.search; | ||
| } | ||
| get method() { | ||
| return this.req.method; | ||
| } | ||
| }; | ||
| var H3EventResponse = class { | ||
| status; | ||
| statusText; | ||
| get headers() { | ||
| return this[kEventResHeaders] ||= new Headers(); | ||
| } | ||
| get errHeaders() { | ||
| return this[kEventResErrHeaders] ||= new Headers(); | ||
| } | ||
| }; | ||
| 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 = +statusCode; | ||
| if (statusCode < 100 || statusCode > 599) return defaultStatusCode; | ||
| return statusCode; | ||
| } | ||
| var HTTPError = class HTTPError extends Error { | ||
| get name() { | ||
| return "HTTPError"; | ||
| } | ||
| status; | ||
| statusText; | ||
| headers; | ||
| cause; | ||
| data; | ||
| body; | ||
| unhandled; | ||
| static isError(input) { | ||
| return input instanceof Error && input?.name === "HTTPError"; | ||
| } | ||
| static status(status, statusText, details) { | ||
| return new HTTPError({ | ||
| ...details, | ||
| statusText, | ||
| status | ||
| }); | ||
| } | ||
| constructor(arg1, arg2) { | ||
| let messageInput; | ||
| let details; | ||
| if (typeof arg1 === "string") { | ||
| messageInput = arg1; | ||
| details = arg2; | ||
| } else details = arg1; | ||
| const status = sanitizeStatusCode(details?.status || details?.statusCode || (details?.cause)?.status || (details?.cause)?.statusCode, 500); | ||
| const statusText = sanitizeStatusMessage(details?.statusText || details?.statusMessage || (details?.cause)?.statusText || (details?.cause)?.statusMessage); | ||
| const message = messageInput || details?.message || (details?.cause)?.message || details?.statusText || details?.statusMessage || [ | ||
| "HTTPError", | ||
| status, | ||
| statusText | ||
| ].filter(Boolean).join(" "); | ||
| super(message, { cause: details }); | ||
| this.cause = details; | ||
| this.status = status; | ||
| this.statusText = statusText || void 0; | ||
| const rawHeaders = details?.headers || (details?.cause)?.headers; | ||
| this.headers = rawHeaders ? new Headers(rawHeaders) : void 0; | ||
| this.unhandled = details?.unhandled ?? (details?.cause)?.unhandled ?? void 0; | ||
| this.data = details?.data; | ||
| this.body = details?.body; | ||
| } | ||
| get statusCode() { | ||
| return this.status; | ||
| } | ||
| get statusMessage() { | ||
| return this.statusText; | ||
| } | ||
| toJSON() { | ||
| const unhandled = this.unhandled; | ||
| return { | ||
| status: this.status, | ||
| statusText: this.statusText, | ||
| unhandled, | ||
| message: unhandled ? "HTTPError" : this.message, | ||
| data: unhandled ? void 0 : this.data, | ||
| ...unhandled ? void 0 : this.body | ||
| }; | ||
| } | ||
| }; | ||
| function isJSONSerializable(value, _type) { | ||
| if (value === null || value === void 0) return true; | ||
| if (_type !== "object") return _type === "boolean" || _type === "number" || _type === "string"; | ||
| if (typeof value.toJSON === "function") return true; | ||
| if (Array.isArray(value)) return true; | ||
| if (typeof value.pipe === "function" || typeof value.pipeTo === "function") return false; | ||
| if (value instanceof NullProtoObj) return true; | ||
| const proto = Object.getPrototypeOf(value); | ||
| return proto === Object.prototype || proto === null; | ||
| } | ||
| const kNotFound = /* @__PURE__ */ Symbol.for("h3.notFound"); | ||
| const kHandled = /* @__PURE__ */ Symbol.for("h3.handled"); | ||
| function toResponse(val, event, config = {}) { | ||
| if (typeof val?.then === "function") return (val.catch?.((error) => error) || Promise.resolve(val)).then((resolvedVal) => toResponse(resolvedVal, event, config)); | ||
| const response = prepareResponse(val, event, config); | ||
| if (typeof response?.then === "function") return toResponse(response, event, config); | ||
| const { onResponse } = config; | ||
| return onResponse ? Promise.resolve(onResponse(response, event)).then(() => response) : response; | ||
| } | ||
| var HTTPResponse = class { | ||
| #headers; | ||
| #init; | ||
| body; | ||
| constructor(body, init) { | ||
| this.body = body; | ||
| this.#init = init; | ||
| } | ||
| get status() { | ||
| return this.#init?.status || 200; | ||
| } | ||
| get statusText() { | ||
| return this.#init?.statusText || "OK"; | ||
| } | ||
| get headers() { | ||
| return this.#headers ||= new Headers(this.#init?.headers); | ||
| } | ||
| }; | ||
| function prepareResponse(val, event, config, nested) { | ||
| if (val === kHandled) return new FastResponse(null); | ||
| if (val === kNotFound) val = new HTTPError({ | ||
| status: 404, | ||
| message: `Cannot find any route matching [${event.req.method}] ${event.url}` | ||
| }); | ||
| if (val && val instanceof Error) { | ||
| const isHTTPError = HTTPError.isError(val); | ||
| const error = isHTTPError ? val : new HTTPError(val); | ||
| if (!isHTTPError) { | ||
| error.unhandled = true; | ||
| if (val?.stack) error.stack = val.stack; | ||
| } | ||
| if (error.unhandled && !config.silent) console.error(error); | ||
| const { onError } = config; | ||
| const errHeaders = event[kEventRes]?.[kEventResErrHeaders]; | ||
| return onError && !nested ? Promise.resolve(onError(error, event)).catch((error) => error).then((newVal) => prepareResponse(newVal ?? val, event, config, true)) : errorResponse(error, config.debug, errHeaders); | ||
| } | ||
| const preparedRes = event[kEventRes]; | ||
| const preparedHeaders = preparedRes?.[kEventResHeaders]; | ||
| event[kEventRes] = void 0; | ||
| if (!(val instanceof Response)) { | ||
| const res = prepareResponseBody(val, event, config); | ||
| const status = res.status || preparedRes?.status; | ||
| return new FastResponse(nullBody(event.req.method, status) ? null : res.body, { | ||
| status, | ||
| statusText: res.statusText || preparedRes?.statusText, | ||
| headers: res.headers && preparedHeaders ? mergeHeaders$1(res.headers, preparedHeaders) : res.headers || preparedHeaders | ||
| }); | ||
| } | ||
| if (!preparedHeaders || nested || !val.ok) return val; | ||
| try { | ||
| mergeHeaders$1(val.headers, preparedHeaders, val.headers); | ||
| return val; | ||
| } catch { | ||
| return new FastResponse(nullBody(event.req.method, val.status) ? null : val.body, { | ||
| status: val.status, | ||
| statusText: val.statusText, | ||
| headers: mergeHeaders$1(val.headers, preparedHeaders) | ||
| }); | ||
| } | ||
| } | ||
| function mergeHeaders$1(base, overrides, target = new Headers(base)) { | ||
| for (const [name, value] of overrides) if (name === "set-cookie") target.append(name, value); | ||
| else target.set(name, value); | ||
| return target; | ||
| } | ||
| const frozen = (name) => (...args) => { | ||
| throw new Error(`Headers are frozen (${name} ${args.join(", ")})`); | ||
| }; | ||
| var FrozenHeaders = class extends Headers { | ||
| set = frozen("set"); | ||
| append = frozen("append"); | ||
| delete = frozen("delete"); | ||
| }; | ||
| const emptyHeaders = /* @__PURE__ */ new FrozenHeaders({ "content-length": "0" }); | ||
| const jsonHeaders = /* @__PURE__ */ new FrozenHeaders({ "content-type": "application/json;charset=UTF-8" }); | ||
| function prepareResponseBody(val, event, config) { | ||
| if (val === null || val === void 0) return { | ||
| body: "", | ||
| headers: emptyHeaders | ||
| }; | ||
| const valType = typeof val; | ||
| if (valType === "string") return { body: val }; | ||
| if (val instanceof Uint8Array) { | ||
| event.res.headers.set("content-length", val.byteLength.toString()); | ||
| return { body: val }; | ||
| } | ||
| if (val instanceof HTTPResponse || val?.constructor?.name === "HTTPResponse") return val; | ||
| if (isJSONSerializable(val, valType)) return { | ||
| body: JSON.stringify(val, void 0, config.debug ? 2 : void 0), | ||
| headers: jsonHeaders | ||
| }; | ||
| if (valType === "bigint") return { | ||
| body: val.toString(), | ||
| headers: jsonHeaders | ||
| }; | ||
| if (val instanceof Blob) { | ||
| const headers = new Headers({ | ||
| "content-type": val.type, | ||
| "content-length": val.size.toString() | ||
| }); | ||
| let filename = val.name; | ||
| if (filename) { | ||
| filename = encodeURIComponent(filename); | ||
| headers.set("content-disposition", `filename="${filename}"; filename*=UTF-8''${filename}`); | ||
| } | ||
| return { | ||
| body: val.stream(), | ||
| headers | ||
| }; | ||
| } | ||
| if (valType === "symbol") return { body: val.toString() }; | ||
| if (valType === "function") return { body: `${val.name}()` }; | ||
| return { body: val }; | ||
| } | ||
| function nullBody(method, status) { | ||
| return method === "HEAD" || status === 100 || status === 101 || status === 102 || status === 204 || status === 205 || status === 304; | ||
| } | ||
| function errorResponse(error, debug, errHeaders) { | ||
| let headers = error.headers ? mergeHeaders$1(jsonHeaders, error.headers) : new Headers(jsonHeaders); | ||
| if (errHeaders) headers = mergeHeaders$1(headers, errHeaders); | ||
| return new FastResponse(JSON.stringify({ | ||
| ...error.toJSON(), | ||
| stack: debug && error.stack ? error.stack.split("\n").map((l) => l.trim()) : void 0 | ||
| }, void 0, debug ? 2 : void 0), { | ||
| status: error.status, | ||
| statusText: error.statusText, | ||
| headers | ||
| }); | ||
| } | ||
| function normalizeMiddleware(input, opts = {}) { | ||
| const matcher = createMatcher(opts); | ||
| if (!matcher && (input.length > 1 || input.constructor?.name === "AsyncFunction")) return input; | ||
| return (event, next) => { | ||
| if (matcher && !matcher(event)) return next(); | ||
| const res = input(event, next); | ||
| return res === void 0 || res === kNotFound ? next() : res; | ||
| }; | ||
| } | ||
| function createMatcher(opts) { | ||
| if (!opts.route && !opts.method && !opts.match) return; | ||
| const routeMatcher = opts.route ? routeToRegExp(opts.route) : void 0; | ||
| const method = opts.method?.toUpperCase(); | ||
| return function _middlewareMatcher(event) { | ||
| if (method && event.req.method !== method) return false; | ||
| if (opts.match && !opts.match(event)) return false; | ||
| if (!routeMatcher) return true; | ||
| const match = event.url.pathname.match(routeMatcher); | ||
| if (!match) return false; | ||
| if (match.groups) event.context.middlewareParams = { | ||
| ...event.context.middlewareParams, | ||
| ...match.groups | ||
| }; | ||
| return true; | ||
| }; | ||
| } | ||
| function callMiddleware(event, middleware, handler, index = 0) { | ||
| if (index === middleware.length) return handler(event); | ||
| const fn = middleware[index]; | ||
| let nextCalled; | ||
| let nextResult; | ||
| const next = () => { | ||
| if (nextCalled) return nextResult; | ||
| nextCalled = true; | ||
| nextResult = callMiddleware(event, middleware, handler, index + 1); | ||
| return nextResult; | ||
| }; | ||
| const ret = fn(event, next); | ||
| return isUnhandledResponse(ret) ? next() : typeof ret?.then === "function" ? ret.then((resolved) => isUnhandledResponse(resolved) ? next() : resolved) : ret; | ||
| } | ||
| function isUnhandledResponse(val) { | ||
| return val === void 0 || val === kNotFound; | ||
| } | ||
| function requestWithURL(req, url) { | ||
| const cache = { url }; | ||
| return new Proxy(req, { get(target, prop) { | ||
| if (prop in cache) return cache[prop]; | ||
| const value = Reflect.get(target, prop); | ||
| cache[prop] = typeof value === "function" ? value.bind(target) : value; | ||
| return cache[prop]; | ||
| } }); | ||
| } | ||
| function requestWithBaseURL(req, base) { | ||
| const url = new URL(req.url); | ||
| url.pathname = decodePathname(url.pathname).slice(base.length) || "/"; | ||
| return requestWithURL(req, url.href); | ||
| } | ||
| function toRequest(input, options) { | ||
| if (typeof input === "string") { | ||
| let url = input; | ||
| if (url[0] === "/") { | ||
| const headers = options?.headers ? new Headers(options.headers) : void 0; | ||
| const host = headers?.get("host") || "localhost"; | ||
| url = `${headers?.get("x-forwarded-proto") === "https" ? "https" : "http"}://${host}${url}`; | ||
| } | ||
| return new Request(url, options); | ||
| } else if (options || input instanceof URL) return new Request(input, options); | ||
| return input; | ||
| } | ||
| function defineHandler(input) { | ||
| if (typeof input === "function") return handlerWithFetch(input); | ||
| const handler = input.handler || (input.fetch ? function _fetchHandler(event) { | ||
| return input.fetch(event.req); | ||
| } : NoHandler); | ||
| return Object.assign(handlerWithFetch(input.middleware?.length ? function _handlerMiddleware(event) { | ||
| return callMiddleware(event, input.middleware, handler); | ||
| } : handler), input); | ||
| } | ||
| function handlerWithFetch(handler) { | ||
| if ("fetch" in handler) return handler; | ||
| return Object.assign(handler, { fetch: (req) => { | ||
| if (typeof req === "string") req = new URL(req, "http://_"); | ||
| if (req instanceof URL) req = new Request(req); | ||
| const event = new H3Event(req); | ||
| try { | ||
| return Promise.resolve(toResponse(handler(event), event)); | ||
| } catch (error) { | ||
| return Promise.resolve(toResponse(error, event)); | ||
| } | ||
| } }); | ||
| } | ||
| function defineLazyEventHandler(loader) { | ||
| let handler; | ||
| let promise; | ||
| return defineHandler(function lazyHandler(event) { | ||
| return handler ? handler(event) : (promise ??= Promise.resolve(loader()).then(function resolveLazyHandler(r) { | ||
| handler = toEventHandler(r) || toEventHandler(r.default); | ||
| if (typeof handler !== "function") throw new TypeError("Invalid lazy handler", { cause: { resolved: r } }); | ||
| return handler; | ||
| })).then((r) => r(event)); | ||
| }); | ||
| } | ||
| function toEventHandler(handler) { | ||
| if (typeof handler === "function") return handler; | ||
| if (typeof handler?.handler === "function") return handler.handler; | ||
| if (typeof handler?.fetch === "function") return function _fetchHandler(event) { | ||
| return handler.fetch(event.req); | ||
| }; | ||
| } | ||
| const NoHandler = () => kNotFound; | ||
| var H3Core = class { | ||
| config; | ||
| "~middleware"; | ||
| "~routes" = []; | ||
| constructor(config = {}) { | ||
| this["~middleware"] = []; | ||
| this.config = config; | ||
| this.fetch = this.fetch.bind(this); | ||
| this.handler = this.handler.bind(this); | ||
| } | ||
| fetch(request) { | ||
| return this["~request"](request); | ||
| } | ||
| handler(event) { | ||
| const route = this["~findRoute"](event); | ||
| if (route) { | ||
| event.context.params = route.params; | ||
| event.context.matchedRoute = route.data; | ||
| } | ||
| const routeHandler = route?.data.handler || NoHandler; | ||
| const middleware = this["~getMiddleware"](event, route); | ||
| return middleware.length > 0 ? callMiddleware(event, middleware, routeHandler) : routeHandler(event); | ||
| } | ||
| "~request"(request, context) { | ||
| const event = new H3Event(request, context, this); | ||
| let handlerRes; | ||
| try { | ||
| if (this.config.onRequest) { | ||
| const hookRes = this.config.onRequest(event); | ||
| handlerRes = typeof hookRes?.then === "function" ? hookRes.then(() => this.handler(event)) : this.handler(event); | ||
| } else handlerRes = this.handler(event); | ||
| } catch (error) { | ||
| handlerRes = Promise.reject(error); | ||
| } | ||
| return toResponse(handlerRes, event, this.config); | ||
| } | ||
| "~findRoute"(_event) {} | ||
| "~addRoute"(_route) { | ||
| this["~routes"].push(_route); | ||
| } | ||
| "~getMiddleware"(_event, route) { | ||
| const routeMiddleware = route?.data.middleware; | ||
| const globalMiddleware = this["~middleware"]; | ||
| return routeMiddleware ? [...globalMiddleware, ...routeMiddleware] : globalMiddleware; | ||
| } | ||
| }; | ||
| const H3 = /* @__PURE__ */ (() => { | ||
| class H3 extends H3Core { | ||
| "~rou3"; | ||
| constructor(config = {}) { | ||
| super(config); | ||
| this["~rou3"] = createRouter(); | ||
| this.request = this.request.bind(this); | ||
| config.plugins?.forEach((plugin) => plugin(this)); | ||
| } | ||
| register(plugin) { | ||
| plugin(this); | ||
| return this; | ||
| } | ||
| request(_req, _init, context) { | ||
| return this["~request"](toRequest(_req, _init), context); | ||
| } | ||
| mount(base, input) { | ||
| if ("handler" in input) { | ||
| if (input["~middleware"].length > 0) this["~middleware"].push((event, next) => { | ||
| const originalPathname = event.url.pathname; | ||
| if (!originalPathname.startsWith(base) || originalPathname.length > base.length && originalPathname[base.length] !== "/") return next(); | ||
| event.url.pathname = event.url.pathname.slice(base.length) || "/"; | ||
| return callMiddleware(event, input["~middleware"], () => { | ||
| event.url.pathname = originalPathname; | ||
| return next(); | ||
| }); | ||
| }); | ||
| for (const r of input["~routes"]) this["~addRoute"]({ | ||
| ...r, | ||
| route: base + r.route | ||
| }); | ||
| } else { | ||
| const fetchHandler = "fetch" in input ? input.fetch : input; | ||
| this.all(`${base}/**`, function _mountedMiddleware(event) { | ||
| return fetchHandler(requestWithBaseURL(event.req, base)); | ||
| }); | ||
| } | ||
| return this; | ||
| } | ||
| on(method, route, handler, opts) { | ||
| const _method = (method || "").toUpperCase(); | ||
| route = new URL(route, "http://_").pathname; | ||
| this["~addRoute"]({ | ||
| method: _method, | ||
| route, | ||
| handler: toEventHandler(handler), | ||
| middleware: opts?.middleware, | ||
| meta: { | ||
| ...handler.meta, | ||
| ...opts?.meta | ||
| } | ||
| }); | ||
| return this; | ||
| } | ||
| all(route, handler, opts) { | ||
| return this.on("", route, handler, opts); | ||
| } | ||
| "~findRoute"(_event) { | ||
| return findRoute(this["~rou3"], _event.req.method, _event.url.pathname); | ||
| } | ||
| "~addRoute"(_route) { | ||
| addRoute(this["~rou3"], _route.method, _route.route, _route); | ||
| super["~addRoute"](_route); | ||
| } | ||
| use(arg1, arg2, arg3) { | ||
| let route; | ||
| let fn; | ||
| let opts; | ||
| if (typeof arg1 === "string") { | ||
| route = arg1; | ||
| fn = arg2; | ||
| opts = arg3; | ||
| } else { | ||
| fn = arg1; | ||
| opts = arg2; | ||
| } | ||
| if (typeof fn !== "function" && "handler" in fn) return this.mount(route || "", fn); | ||
| this["~middleware"].push(normalizeMiddleware(fn, { | ||
| ...opts, | ||
| route | ||
| })); | ||
| return this; | ||
| } | ||
| } | ||
| for (const method of [ | ||
| "GET", | ||
| "POST", | ||
| "PUT", | ||
| "DELETE", | ||
| "PATCH", | ||
| "HEAD", | ||
| "OPTIONS", | ||
| "CONNECT", | ||
| "TRACE" | ||
| ]) H3Core.prototype[method.toLowerCase()] = function(route, handler, opts) { | ||
| return this.on(method, route, handler, opts); | ||
| }; | ||
| return H3; | ||
| })(); | ||
| const lazyEventHandler = defineLazyEventHandler; | ||
| //#endregion | ||
| //#region ../nuxi/src/commands/analyze.ts | ||
| const NON_WORD_RE = /[^\w-]/g; | ||
| const indexHtml = ` | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="utf-8"> | ||
| <title>Nuxt Bundle Stats (experimental)</title> | ||
| </head> | ||
| <h1>Nuxt Bundle Stats (experimental)</h1> | ||
| <ul> | ||
| <li> | ||
| <a href="/nitro">Nitro server bundle stats</a> | ||
| </li> | ||
| <li> | ||
| <a href="/client">Client bundle stats</a> | ||
| </li> | ||
| </ul> | ||
| </html> | ||
| `.trim(); | ||
| var analyze_default = defineCommand({ | ||
| meta: { | ||
| name: "analyze", | ||
| description: "Build Nuxt and analyze production bundle (experimental)" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...legacyRootDirArgs, | ||
| ...dotEnvArgs, | ||
| ...extendsArgs, | ||
| name: { | ||
| type: "string", | ||
| description: "Name of the analysis", | ||
| default: "default", | ||
| valueHint: "name" | ||
| }, | ||
| serve: { | ||
| type: "boolean", | ||
| description: "Serve the analysis results", | ||
| negativeDescription: "Skip serving the analysis results", | ||
| default: true | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| overrideEnv("production"); | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const name = ctx.args.name || "default"; | ||
| const slug = name.trim().replace(NON_WORD_RE, "_"); | ||
| intro(colors.cyan("Analyzing bundle size...")); | ||
| const startTime = Date.now(); | ||
| const { loadNuxt, buildNuxt } = await loadKit(cwd); | ||
| const nuxt = await loadNuxt({ | ||
| cwd, | ||
| dotenv: { | ||
| cwd, | ||
| fileName: ctx.args.dotenv | ||
| }, | ||
| overrides: defu$1(ctx.data?.overrides, { | ||
| ...ctx.args.extends && { extends: ctx.args.extends }, | ||
| build: { analyze: { enabled: true } }, | ||
| vite: { build: { rollupOptions: { output: { | ||
| chunkFileNames: "_nuxt/[name].js", | ||
| entryFileNames: "_nuxt/[name].js" | ||
| } } } }, | ||
| logLevel: ctx.args.logLevel | ||
| }) | ||
| }); | ||
| const analyzeDir = nuxt.options.analyzeDir; | ||
| const buildDir = nuxt.options.buildDir; | ||
| const outDir = nuxt.options.nitro.output?.dir || join(nuxt.options.rootDir, ".output"); | ||
| nuxt.options.build.analyze = defu$1(nuxt.options.build.analyze, { filename: join(analyzeDir, "client.html") }); | ||
| const tasklog = taskLog({ | ||
| title: "Building Nuxt with analysis enabled", | ||
| retainLog: false, | ||
| limit: 1 | ||
| }); | ||
| tasklog.message("Clearing analyze directory..."); | ||
| await clearDir(analyzeDir); | ||
| tasklog.message("Building Nuxt..."); | ||
| await buildNuxt(nuxt); | ||
| tasklog.success("Build complete"); | ||
| const meta = { | ||
| name, | ||
| slug, | ||
| startTime, | ||
| endTime: Date.now(), | ||
| analyzeDir, | ||
| buildDir, | ||
| outDir | ||
| }; | ||
| await nuxt.callHook("build:analyze:done", meta); | ||
| await promises.writeFile(join(analyzeDir, "meta.json"), JSON.stringify(meta, null, 2), "utf-8"); | ||
| note(`${relativeToProcess(analyzeDir)}\n\nDo not deploy analyze results! Use ${colors.cyan("nuxt build")} before deploying.`, "Build location"); | ||
| if (ctx.args.serve !== false && !process.env.CI) { | ||
| const app = new H3(); | ||
| const opts = { headers: { "content-type": "text/html" } }; | ||
| const serveFile = (filePath) => lazyEventHandler(async () => { | ||
| const contents = await promises.readFile(filePath, "utf-8"); | ||
| return () => new Response(contents, opts); | ||
| }); | ||
| logger.step("Starting stats server..."); | ||
| app.use("/client", serveFile(join(analyzeDir, "client.html"))); | ||
| app.use("/nitro", serveFile(join(analyzeDir, "nitro.html"))); | ||
| app.use(() => new Response(indexHtml, opts)); | ||
| await serve(app).serve(); | ||
| } else outro("✨ Analysis build complete!"); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { analyze_default as default }; |
| //#region ../nuxi/src/utils/ascii.ts | ||
| /** | ||
| * Thank you to IndyJoenz for this ASCII art | ||
| * https://bsky.app/profile/durdraw.org/post/3liadod3gv22a | ||
| */ | ||
| const themeColor = "\x1B[38;2;0;220;130m"; | ||
| const nuxtIcon = [ | ||
| ` .d$b.`, | ||
| ` i$$A$$L .d$b`, | ||
| ` .$$F\` \`$$L.$$A$$.`, | ||
| ` j$$' \`4$$:\` \`$$.`, | ||
| ` j$$' .4$: \`$$.`, | ||
| ` j$$\` .$$: \`4$L`, | ||
| ` :$$:____.d$$: _____.:$$:`, | ||
| ` \`4$$$$$$$$P\` .i$$$$$$$$P\`` | ||
| ].map((line) => line.split("").join(themeColor)).join("\n"); | ||
| //#endregion | ||
| export { themeColor as n, nuxtIcon as t }; |
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { n as getPkgJSON, r as getPkgVersion } from "./versions--iBjrFVR.mjs"; | ||
| import { colors } from "consola/utils"; | ||
| //#region ../nuxi/src/utils/banner.ts | ||
| function getBuilder(cwd, builder) { | ||
| switch (builder) { | ||
| case "rspack": | ||
| case "@nuxt/rspack-builder": return { | ||
| name: "Rspack", | ||
| version: getPkgVersion(cwd, "@rspack/core", { via: ["@nuxt/rspack-builder"] }) | ||
| }; | ||
| case "webpack": | ||
| case "@nuxt/webpack-builder": return { | ||
| name: "Webpack", | ||
| version: getPkgVersion(cwd, "webpack", { via: ["@nuxt/webpack-builder"] }) | ||
| }; | ||
| default: { | ||
| const pkgJSON = getPkgJSON(cwd, "vite", { via: ["nuxt", "@nuxt/vite-builder"] }); | ||
| return { | ||
| name: pkgJSON.name.includes("rolldown") ? "Rolldown-Vite" : "Vite", | ||
| version: pkgJSON.version || "unknown" | ||
| }; | ||
| } | ||
| } | ||
| } | ||
| function showBanner(nuxt) { | ||
| const { bold, gray, green } = colors; | ||
| const cwd = nuxt.options.rootDir; | ||
| const nuxtVersion = nuxt._version || getPkgVersion(cwd, "nuxt") || getPkgVersion(cwd, "nuxt-nightly") || getPkgVersion(cwd, "nuxt3") || getPkgVersion(cwd, "nuxt-edge"); | ||
| const nitroVia = { via: ["nuxt", "@nuxt/nitro-server"] }; | ||
| const nitroVersion = getPkgVersion(cwd, "nitropack", nitroVia) || getPkgVersion(cwd, "nitro", nitroVia) || getPkgVersion(cwd, "nitropack-nightly") || getPkgVersion(cwd, "nitropack-edge"); | ||
| const builder = getBuilder(cwd, nuxt.options.builder); | ||
| const vueVersion = getPkgVersion(cwd, "vue", { via: ["nuxt"] }) || null; | ||
| logger.info(green(`Nuxt ${bold(nuxtVersion)}`) + gray(" (with ") + (nitroVersion ? gray(`Nitro ${bold(nitroVersion)}`) : "") + gray(`, ${builder.name} ${bold(builder.version)}`) + (vueVersion ? gray(` and Vue ${bold(vueVersion)}`) : "") + gray(")")); | ||
| } | ||
| //#endregion | ||
| export { showBanner as n, getBuilder as t }; |
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, r as envNameArgs, s as profileArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { t as overrideEnv } from "./env-BfWVBvy7.mjs"; | ||
| import { a as stopCpuProfile, i as startCpuProfile, n as formatLockError, t as acquireLock } from "./lockfile-B0hNFb_C.mjs"; | ||
| import { t as loadKit } from "./kit-BzPscsEd.mjs"; | ||
| import { n as showBanner } from "./banner-CTtM2dxO.mjs"; | ||
| import { t as clearBuildDir } from "./fs-B0HqP3GX.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { intro, outro } from "@clack/prompts"; | ||
| import { relative, resolve } from "pathe"; | ||
| //#region ../nuxi/src/commands/build.ts | ||
| var build_default = defineCommand({ | ||
| meta: { | ||
| name: "build", | ||
| description: "Build Nuxt for production deployment" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| prerender: { | ||
| type: "boolean", | ||
| description: "Build Nuxt and prerender static routes" | ||
| }, | ||
| preset: { | ||
| type: "string", | ||
| description: "Nitro server preset" | ||
| }, | ||
| ...dotEnvArgs, | ||
| ...envNameArgs, | ||
| ...extendsArgs, | ||
| ...profileArgs, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| overrideEnv("production"); | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const profileArg = ctx.args.profile; | ||
| const perfValue = profileArg === "verbose" ? true : profileArg ? "quiet" : void 0; | ||
| if (profileArg) await startCpuProfile(); | ||
| let releaseLock; | ||
| try { | ||
| intro(colors.cyan("Building Nuxt for production...")); | ||
| const kit = await loadKit(cwd); | ||
| const nuxt = await kit.loadNuxt({ | ||
| cwd, | ||
| ready: false, | ||
| dotenv: { | ||
| cwd, | ||
| fileName: ctx.args.dotenv | ||
| }, | ||
| envName: ctx.args.envName, | ||
| overrides: { | ||
| logLevel: ctx.args.logLevel, | ||
| _generate: ctx.args.prerender, | ||
| nitro: { | ||
| static: ctx.args.prerender, | ||
| preset: ctx.args.preset || process.env.NITRO_PRESET || process.env.SERVER_PRESET | ||
| }, | ||
| ...ctx.args.extends && { extends: ctx.args.extends }, | ||
| ...ctx.data?.overrides, | ||
| ...(perfValue || ctx.data?.overrides?.debug) && { debug: { | ||
| ...ctx.data?.overrides?.debug, | ||
| ...perfValue && { perf: perfValue } | ||
| } } | ||
| } | ||
| }); | ||
| showBanner(nuxt); | ||
| await nuxt.ready(); | ||
| const lock = acquireLock(nuxt.options.buildDir, { | ||
| command: "build", | ||
| cwd | ||
| }); | ||
| if (lock.existing) { | ||
| logger.error(formatLockError(lock.existing)); | ||
| throw new Error(`Another Nuxt ${lock.existing.command} is already running (PID ${lock.existing.pid}).`); | ||
| } | ||
| releaseLock = lock.release; | ||
| let nitro; | ||
| try { | ||
| nitro = kit.useNitro?.(); | ||
| if (nitro) logger.info(`Nitro preset: ${colors.cyan(nitro.options.preset)}`); | ||
| } catch {} | ||
| await clearBuildDir(nuxt.options.buildDir); | ||
| await kit.writeTypes(nuxt); | ||
| nuxt.hook("build:error", async (err) => { | ||
| logger.error(`Nuxt build error: ${err}`); | ||
| if (profileArg) await stopCpuProfile(cwd, "build"); | ||
| process.exit(1); | ||
| }); | ||
| await kit.buildNuxt(nuxt); | ||
| if (ctx.args.prerender) { | ||
| if (!nuxt.options.ssr) { | ||
| logger.warn(`HTML content not prerendered because ${colors.cyan("ssr: false")} was set.`); | ||
| logger.info(`You can read more in ${colors.cyan("https://nuxt.com/docs/getting-started/deployment#static-hosting")}.`); | ||
| } | ||
| const dir = nitro?.options.output.publicDir; | ||
| const publicDir = dir ? relative(process.cwd(), dir) : ".output/public"; | ||
| outro(`✨ You can now deploy ${colors.cyan(publicDir)} to any static hosting!`); | ||
| } else outro("✨ Build complete!"); | ||
| } finally { | ||
| releaseLock?.(); | ||
| if (profileArg) await stopCpuProfile(cwd, "build"); | ||
| } | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { build_default as default }; |
| import { a as legacyRootDirArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { t as loadKit } from "./kit-BzPscsEd.mjs"; | ||
| import { t as cleanupNuxtDirs } from "./nuxt-CBsjK3fQ.mjs"; | ||
| import { defineCommand } from "citty"; | ||
| import { resolve } from "pathe"; | ||
| //#region ../nuxi/src/commands/cleanup.ts | ||
| var cleanup_default = defineCommand({ | ||
| meta: { | ||
| name: "cleanup", | ||
| description: "Clean up generated Nuxt files and caches" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const { loadNuxtConfig } = await loadKit(cwd); | ||
| const nuxtOptions = await loadNuxtConfig({ | ||
| cwd, | ||
| overrides: { dev: true } | ||
| }); | ||
| await cleanupNuxtDirs(nuxtOptions.rootDir, nuxtOptions.buildDir); | ||
| logger.success("Cleanup complete!"); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { cleanup_default as default }; |
| import { templates } from "./templates-BNoyKfB8.mjs"; | ||
| import tab from "@bomb.sh/tab/citty"; | ||
| //#region ../nuxi/src/data/nitro-presets.ts | ||
| const nitroPresets = [ | ||
| "alwaysdata", | ||
| "aws-amplify", | ||
| "aws-lambda", | ||
| "azure-functions", | ||
| "azure-swa", | ||
| "bun", | ||
| "cleavr", | ||
| "cli", | ||
| "cloudflare-dev", | ||
| "cloudflare-durable", | ||
| "cloudflare-module", | ||
| "cloudflare-module-legacy", | ||
| "cloudflare-pages", | ||
| "cloudflare-pages-static", | ||
| "cloudflare-worker", | ||
| "deno-deploy", | ||
| "deno-server", | ||
| "deno-server-legacy", | ||
| "digital-ocean", | ||
| "edgio", | ||
| "firebase", | ||
| "firebase-app-hosting", | ||
| "flight-control", | ||
| "genezio", | ||
| "github-pages", | ||
| "gitlab-pages", | ||
| "heroku", | ||
| "iis-handler", | ||
| "iis-node", | ||
| "koyeb", | ||
| "netlify", | ||
| "netlify-builder", | ||
| "netlify-edge", | ||
| "netlify-legacy", | ||
| "netlify-static", | ||
| "node-cluster", | ||
| "node-listener", | ||
| "node-server", | ||
| "platform-sh", | ||
| "render-com", | ||
| "service-worker", | ||
| "static", | ||
| "stormkit", | ||
| "vercel", | ||
| "vercel-edge", | ||
| "vercel-static", | ||
| "winterjs", | ||
| "zeabur", | ||
| "zeabur-static", | ||
| "zerops", | ||
| "zerops-static" | ||
| ]; | ||
| //#endregion | ||
| //#region ../nuxi/src/completions.ts | ||
| async function initCompletions(command) { | ||
| const completion = await tab(command); | ||
| const devCommand = completion.commands.get("dev"); | ||
| if (devCommand) { | ||
| const portOption = devCommand.options.get("port"); | ||
| if (portOption) portOption.handler = (complete) => { | ||
| complete("3000", "Default development port"); | ||
| complete("3001", "Alternative port"); | ||
| complete("8080", "Common alternative port"); | ||
| }; | ||
| const hostOption = devCommand.options.get("host"); | ||
| if (hostOption) hostOption.handler = (complete) => { | ||
| complete("localhost", "Local development"); | ||
| complete("0.0.0.0", "Listen on all interfaces"); | ||
| complete("127.0.0.1", "Loopback address"); | ||
| }; | ||
| } | ||
| const buildCommand = completion.commands.get("build"); | ||
| if (buildCommand) { | ||
| const presetOption = buildCommand.options.get("preset"); | ||
| if (presetOption) presetOption.handler = (complete) => { | ||
| for (const preset of nitroPresets) complete(preset, ""); | ||
| }; | ||
| } | ||
| const initCommand = completion.commands.get("init"); | ||
| if (initCommand) { | ||
| const templateOption = initCommand.options.get("template"); | ||
| if (templateOption) templateOption.handler = (complete) => { | ||
| for (const template in templates) complete(template, templates[template]?.description || ""); | ||
| }; | ||
| } | ||
| const addCommand = completion.commands.get("add"); | ||
| if (addCommand) { | ||
| const cwdOption = addCommand.options.get("cwd"); | ||
| if (cwdOption) cwdOption.handler = (complete) => { | ||
| complete(".", "Current directory"); | ||
| }; | ||
| } | ||
| for (const cmdName of [ | ||
| "dev", | ||
| "build", | ||
| "generate", | ||
| "preview", | ||
| "prepare", | ||
| "init" | ||
| ]) { | ||
| const cmd = completion.commands.get(cmdName); | ||
| if (cmd) { | ||
| const logLevelOption = cmd.options.get("logLevel"); | ||
| if (logLevelOption) logLevelOption.handler = (complete) => { | ||
| complete("silent", "No logs"); | ||
| complete("info", "Standard logging"); | ||
| complete("verbose", "Detailed logging"); | ||
| }; | ||
| } | ||
| } | ||
| return completion; | ||
| } | ||
| //#endregion | ||
| export { initCompletions }; |
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, r as envNameArgs, s as profileArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger, t as debug } from "./logger-C1qVsppt.mjs"; | ||
| import { n as initialize } from "./dev-Cr4PgS_f.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { isBun, isDeno, isTest } from "std-env"; | ||
| import { resolve } from "pathe"; | ||
| import { satisfies } from "semver"; | ||
| import { getArgs, parseArgs } from "listhen/cli"; | ||
| import { fork } from "node:child_process"; | ||
| //#region ../nuxi/src/dev/pool.ts | ||
| var ForkPool = class { | ||
| pool = []; | ||
| poolSize; | ||
| rawArgs; | ||
| listenOverrides; | ||
| warming = false; | ||
| constructor(options) { | ||
| this.rawArgs = options.rawArgs; | ||
| this.poolSize = options.poolSize ?? 2; | ||
| this.listenOverrides = options.listenOverrides; | ||
| for (const signal of [ | ||
| "exit", | ||
| "SIGTERM", | ||
| "SIGINT", | ||
| "SIGQUIT" | ||
| ]) process.once(signal, () => { | ||
| this.killAll(signal === "exit" ? 0 : signal); | ||
| }); | ||
| } | ||
| startWarming() { | ||
| if (this.warming) return; | ||
| this.warming = true; | ||
| for (let i = 0; i < this.poolSize; i++) this.warmFork(); | ||
| } | ||
| async getFork(context, onMessage) { | ||
| const readyFork = this.pool.find((f) => f.state === "ready"); | ||
| if (readyFork) { | ||
| readyFork.state = "active"; | ||
| if (onMessage) this.attachMessageHandler(readyFork.process, onMessage); | ||
| await this.sendContext(readyFork.process, context); | ||
| if (this.warming) this.warmFork(); | ||
| return () => this.killFork(readyFork); | ||
| } | ||
| const warmingFork = this.pool.find((f) => f.state === "warming"); | ||
| if (warmingFork) { | ||
| await warmingFork.ready; | ||
| warmingFork.state = "active"; | ||
| if (onMessage) this.attachMessageHandler(warmingFork.process, onMessage); | ||
| await this.sendContext(warmingFork.process, context); | ||
| if (this.warming) this.warmFork(); | ||
| return () => this.killFork(warmingFork); | ||
| } | ||
| debug("No pre-warmed forks available, starting cold fork"); | ||
| const coldFork = this.createFork(); | ||
| await coldFork.ready; | ||
| coldFork.state = "active"; | ||
| if (onMessage) this.attachMessageHandler(coldFork.process, onMessage); | ||
| await this.sendContext(coldFork.process, context); | ||
| return () => this.killFork(coldFork); | ||
| } | ||
| attachMessageHandler(childProc, onMessage) { | ||
| childProc.on("message", (message) => { | ||
| if (message.type !== "nuxt:internal:dev:fork-ready") onMessage(message); | ||
| }); | ||
| } | ||
| warmFork() { | ||
| const fork = this.createFork(); | ||
| fork.ready.then(() => { | ||
| if (fork.state === "warming") fork.state = "ready"; | ||
| }).catch(() => { | ||
| this.removeFork(fork); | ||
| }); | ||
| this.pool.push(fork); | ||
| } | ||
| createFork() { | ||
| const childProc = fork(globalThis.__nuxt_cli__.devEntry, this.rawArgs, { | ||
| execArgv: ["--enable-source-maps", process.argv.find((a) => a.includes("--inspect"))].filter(Boolean), | ||
| env: { | ||
| ...process.env, | ||
| __NUXT__FORK: "true" | ||
| } | ||
| }); | ||
| let readyResolve; | ||
| let readyReject; | ||
| const pooledFork = { | ||
| process: childProc, | ||
| ready: new Promise((resolve, reject) => { | ||
| readyResolve = resolve; | ||
| readyReject = reject; | ||
| }), | ||
| state: "warming" | ||
| }; | ||
| childProc.on("message", (message) => { | ||
| if (message.type === "nuxt:internal:dev:fork-ready") readyResolve(); | ||
| }); | ||
| childProc.on("error", (err) => { | ||
| readyReject(err); | ||
| this.removeFork(pooledFork); | ||
| }); | ||
| childProc.on("close", (errorCode) => { | ||
| if (pooledFork.state === "active" && errorCode) process.exit(errorCode); | ||
| this.removeFork(pooledFork); | ||
| }); | ||
| return pooledFork; | ||
| } | ||
| async sendContext(childProc, context) { | ||
| childProc.send({ | ||
| type: "nuxt:internal:dev:context", | ||
| listenOverrides: this.listenOverrides, | ||
| context | ||
| }); | ||
| } | ||
| killFork(fork, signal = "SIGTERM") { | ||
| fork.state = "dead"; | ||
| if (fork.process) fork.process.kill(signal === 0 && isDeno ? "SIGTERM" : signal); | ||
| this.removeFork(fork); | ||
| } | ||
| removeFork(fork) { | ||
| const index = this.pool.indexOf(fork); | ||
| if (index > -1) this.pool.splice(index, 1); | ||
| } | ||
| killAll(signal) { | ||
| for (const fork of this.pool) this.killFork(fork, signal); | ||
| } | ||
| getStats() { | ||
| return { | ||
| total: this.pool.length, | ||
| warming: this.pool.filter((f) => f.state === "warming").length, | ||
| ready: this.pool.filter((f) => f.state === "ready").length, | ||
| active: this.pool.filter((f) => f.state === "active").length | ||
| }; | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region ../nuxi/src/commands/dev.ts | ||
| const startTime = Date.now(); | ||
| const forkSupported = !isTest && (!isBun || isBunForkSupported()); | ||
| const listhenArgs = getArgs(); | ||
| const command = defineCommand({ | ||
| meta: { | ||
| name: "dev", | ||
| description: "Run Nuxt development server" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...dotEnvArgs, | ||
| ...legacyRootDirArgs, | ||
| ...envNameArgs, | ||
| ...extendsArgs, | ||
| clear: { | ||
| type: "boolean", | ||
| description: "Clear console on restart", | ||
| default: false | ||
| }, | ||
| fork: { | ||
| type: "boolean", | ||
| description: forkSupported ? "Disable forked mode" : "Enable forked mode", | ||
| negativeDescription: "Disable forked mode", | ||
| default: forkSupported, | ||
| alias: ["f"] | ||
| }, | ||
| ...listhenArgs, | ||
| port: { | ||
| ...listhenArgs.port, | ||
| description: "Port to listen on (default: `NUXT_PORT || NITRO_PORT || PORT || nuxtOptions.devServer.port`)", | ||
| alias: ["p"] | ||
| }, | ||
| open: { | ||
| ...listhenArgs.open, | ||
| alias: ["o"], | ||
| default: false | ||
| }, | ||
| host: { | ||
| ...listhenArgs.host, | ||
| alias: ["h"], | ||
| description: "Host to listen on (default: `NUXT_HOST || NITRO_HOST || HOST || nuxtOptions.devServer?.host`)" | ||
| }, | ||
| clipboard: { | ||
| ...listhenArgs.clipboard, | ||
| default: false | ||
| }, | ||
| ...profileArgs, | ||
| sslCert: { | ||
| type: "string", | ||
| description: "(DEPRECATED) Use `--https.cert` instead." | ||
| }, | ||
| sslKey: { | ||
| type: "string", | ||
| description: "(DEPRECATED) Use `--https.key` instead." | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const listenOverrides = resolveListenOverrides(ctx.args); | ||
| const { listener, close, onRestart, onReady } = await initialize({ | ||
| cwd, | ||
| args: ctx.args | ||
| }, { | ||
| data: ctx.data, | ||
| listenOverrides, | ||
| showBanner: true | ||
| }); | ||
| if (!ctx.args.fork || ctx.args.profile) return { | ||
| listener, | ||
| close | ||
| }; | ||
| const pool = new ForkPool({ | ||
| rawArgs: ctx.rawArgs, | ||
| poolSize: 2, | ||
| listenOverrides | ||
| }); | ||
| onReady((_address) => { | ||
| pool.startWarming(); | ||
| if (startTime) debug(`Dev server ready for connections in ${Date.now() - startTime}ms`); | ||
| }); | ||
| let cleanupCurrentFork; | ||
| async function restartWithFork() { | ||
| const context = { | ||
| cwd, | ||
| args: ctx.args | ||
| }; | ||
| cleanupCurrentFork?.(); | ||
| cleanupCurrentFork = await pool.getFork(context, (message) => { | ||
| if (message.type === "nuxt:internal:dev:ready") { | ||
| if (startTime) debug(`Dev server ready for connections in ${Date.now() - startTime}ms`); | ||
| } else if (message.type === "nuxt:internal:dev:restart") restartWithFork(); | ||
| else if (message.type === "nuxt:internal:dev:rejection") { | ||
| logger.info(`Restarting Nuxt due to error: ${colors.cyan(message.message)}`); | ||
| restartWithFork(); | ||
| } | ||
| }); | ||
| } | ||
| onRestart(async () => { | ||
| await close(); | ||
| await restartWithFork(); | ||
| }); | ||
| return { async close() { | ||
| cleanupCurrentFork?.(); | ||
| await Promise.all([listener.close(), close()]); | ||
| } }; | ||
| } | ||
| }); | ||
| function resolveListenOverrides(args) { | ||
| if (process.env._PORT) return { | ||
| port: process.env._PORT || 0, | ||
| hostname: "127.0.0.1", | ||
| showURL: false | ||
| }; | ||
| const options = parseArgs({ | ||
| ...args, | ||
| "host": args.host || process.env.NUXT_HOST || process.env.NITRO_HOST || process.env.HOST, | ||
| "port": args.port || process.env.NUXT_PORT || process.env.NITRO_PORT || process.env.PORT, | ||
| "https": args.https !== false && args.https !== "false", | ||
| "https.cert": args["https.cert"] || args.sslCert || process.env.NUXT_SSL_CERT || process.env.NITRO_SSL_CERT, | ||
| "https.key": args["https.key"] || args.sslKey || process.env.NUXT_SSL_KEY || process.env.NITRO_SSL_KEY | ||
| }); | ||
| return { | ||
| ...options, | ||
| _https: args.https, | ||
| get https() { | ||
| const httpsArg = this._https; | ||
| if (httpsArg === false || httpsArg === "false") return false; | ||
| return httpsArg ? options.https : false; | ||
| } | ||
| }; | ||
| } | ||
| function isBunForkSupported() { | ||
| const bunVersion = globalThis.Bun.version; | ||
| return satisfies(bunVersion, ">=1.2"); | ||
| } | ||
| //#endregion | ||
| export { command as default }; |
| import { a as legacyRootDirArgs, n as dotEnvArgs, o as logLevelArgs, r as envNameArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { isTest } from "std-env"; | ||
| import { resolve } from "pathe"; | ||
| //#region ../nuxi/src/commands/dev-child.ts | ||
| var dev_child_default = defineCommand({ | ||
| meta: { | ||
| name: "_dev", | ||
| description: "Run Nuxt development server (internal command to start child process)" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...envNameArgs, | ||
| ...dotEnvArgs, | ||
| ...legacyRootDirArgs, | ||
| clear: { | ||
| type: "boolean", | ||
| description: "Clear console on restart", | ||
| negativeDescription: "Disable clear console on restart" | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| if (!process.send && !isTest) console.warn("`nuxi _dev` is an internal command and should not be used directly. Please use `nuxi dev` instead."); | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const { initialize } = await import("./dev-Cr4PgS_f.mjs").then((n) => n.t); | ||
| await initialize({ | ||
| cwd, | ||
| args: ctx.args | ||
| }, ctx); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { dev_child_default as default }; |
| import { t as __exportAll } from "./rolldown-runtime-wcPFST8Q.mjs"; | ||
| import { t as overrideEnv } from "./env-BfWVBvy7.mjs"; | ||
| import { a as stopCpuProfile, i as startCpuProfile, n as formatLockError, r as updateLock, t as acquireLock } from "./lockfile-B0hNFb_C.mjs"; | ||
| import { i as withNodePath, t as loadKit } from "./kit-BzPscsEd.mjs"; | ||
| import { n as showBanner } from "./banner-CTtM2dxO.mjs"; | ||
| import { t as clearBuildDir } from "./fs-B0HqP3GX.mjs"; | ||
| import { a as writeNuxtManifest, i as resolveNuxtManifest, n as loadNuxtManifest } from "./nuxt-CBsjK3fQ.mjs"; | ||
| import process from "node:process"; | ||
| import { provider } from "std-env"; | ||
| import { pathToFileURL } from "node:url"; | ||
| import defu from "defu"; | ||
| import { existsSync, readdirSync, statSync, watch } from "node:fs"; | ||
| import { join, resolve } from "pathe"; | ||
| import EventEmitter from "node:events"; | ||
| import { mkdir } from "node:fs/promises"; | ||
| import { resolveModulePath } from "exsolve"; | ||
| import { joinURL } from "ufo"; | ||
| import { listen } from "listhen"; | ||
| import { debounce } from "perfect-debounce"; | ||
| import { toNodeHandler } from "srvx/node"; | ||
| import { Youch } from "youch"; | ||
| //#region ../../node_modules/.pnpm/h3@1.15.11/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 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; | ||
| 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 = 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, lastComma)); | ||
| start = pos; | ||
| } else pos = lastComma + 1; | ||
| } else pos += 1; | ||
| } | ||
| if (!cookiesSeparatorFound || pos >= cookiesString.length) cookiesStrings.push(cookiesString.slice(start)); | ||
| } | ||
| 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, reject) => { | ||
| stream.pipe(event.node.res); | ||
| if (stream.on) { | ||
| stream.on("end", () => { | ||
| event.node.res.end(); | ||
| resolve(); | ||
| }); | ||
| 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; | ||
| } | ||
| globalThis.Headers; | ||
| 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]+)$/; | ||
| const TRAILING_SLASH_RE = /\/$/; | ||
| 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(); | ||
| #lockCleanup; | ||
| #lockedBuildDir; | ||
| loadDebounced; | ||
| handler; | ||
| listener; | ||
| constructor(options) { | ||
| super(); | ||
| this.options = options; | ||
| this.loadDebounced = debounce(this.load); | ||
| let _initResolve; | ||
| const _initPromise = new Promise((resolve) => { | ||
| _initResolve = resolve; | ||
| }); | ||
| 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() { | ||
| const action = "Starting"; | ||
| this.#loadingMessage = `${action} Nuxt...`; | ||
| this.#handler = void 0; | ||
| this.emit("loading", this.#loadingMessage); | ||
| await this.#loadNuxtInstance(); | ||
| this.#acquireDevLock(this.#currentNuxt.options.buildDir); | ||
| if (this.options.showBanner) showBanner(this.#currentNuxt); | ||
| 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) => r.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 ("handler" in this.#currentNuxt.server) this.#handler = this.#currentNuxt.server.handler; | ||
| else if ("fetch" in this.#currentNuxt.server) this.#handler = toNodeHandler(this.#currentNuxt.server.fetch); | ||
| else this.#handler = toNodeListener(this.#currentNuxt.server.app); | ||
| const serverUrl = getAddressURL(addr, !!this.listener.https).replace(TRAILING_SLASH_RE, ""); | ||
| const currentBuildDir = this.#currentNuxt.options.buildDir; | ||
| if (this.#lockedBuildDir !== currentBuildDir) this.#acquireDevLock(currentBuildDir); | ||
| updateLock(currentBuildDir, { | ||
| command: "dev", | ||
| cwd: this.options.cwd, | ||
| port: addr.port, | ||
| hostname: addr.address, | ||
| url: serverUrl | ||
| }); | ||
| this.emit("ready", serverUrl); | ||
| } | ||
| async close() { | ||
| if (this.#currentNuxt) await this.#currentNuxt.close(); | ||
| } | ||
| /** Release the lock file. Call only on final shutdown, not during reloads. */ | ||
| releaseLock() { | ||
| this.#lockCleanup?.(); | ||
| this.#lockCleanup = void 0; | ||
| this.#lockedBuildDir = void 0; | ||
| } | ||
| #acquireDevLock(buildDir) { | ||
| const lock = acquireLock(buildDir, { | ||
| command: "dev", | ||
| cwd: this.options.cwd | ||
| }); | ||
| if (lock.existing) { | ||
| console.error(formatLockError(lock.existing)); | ||
| throw new Error(`Another Nuxt ${lock.existing.command} is already running (PID ${lock.existing.pid}).`); | ||
| } | ||
| const previousRelease = this.#lockCleanup; | ||
| this.#lockCleanup = lock.release; | ||
| this.#lockedBuildDir = buildDir; | ||
| previousRelease?.(); | ||
| } | ||
| #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) => r.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) => `<h2>${params.loading}</h2>`); | ||
| } | ||
| function isPublicHostname(hostname) { | ||
| return !!hostname && ![ | ||
| "localhost", | ||
| "127.0.0.1", | ||
| "::1" | ||
| ].includes(hostname); | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/dev/index.ts | ||
| var dev_exports = /* @__PURE__ */ __exportAll({ initialize: () => initialize }); | ||
| const start = Date.now(); | ||
| var IPC = class { | ||
| enabled = !!process.send && !process.title?.includes("vitest") && process.env.__NUXT__FORK; | ||
| constructor() { | ||
| if (this.enabled) process.once("unhandledRejection", (reason) => { | ||
| this.send({ | ||
| type: "nuxt:internal:dev:rejection", | ||
| message: reason instanceof Error ? reason.toString() : "Unhandled Rejection" | ||
| }); | ||
| process.exit(); | ||
| }); | ||
| process.on("message", (message) => { | ||
| if (message.type === "nuxt:internal:dev:context") initialize(message.context, { listenOverrides: message.listenOverrides }); | ||
| }); | ||
| this.send({ type: "nuxt:internal:dev:fork-ready" }); | ||
| } | ||
| send(message) { | ||
| if (this.enabled) process.send?.(message); | ||
| } | ||
| }; | ||
| const ipc = new IPC(); | ||
| async function initialize(devContext, ctx = {}) { | ||
| overrideEnv("development"); | ||
| const profileArg = devContext.args.profile; | ||
| const perfValue = profileArg === "verbose" ? true : profileArg ? "quiet" : void 0; | ||
| const perfOverrides = perfValue ? { debug: { perf: perfValue } } : {}; | ||
| if (profileArg) await startCpuProfile(); | ||
| const devServer = new NuxtDevServer({ | ||
| cwd: devContext.cwd, | ||
| overrides: defu(ctx.data?.overrides, { extends: devContext.args.extends }, perfOverrides), | ||
| logLevel: devContext.args.logLevel, | ||
| clear: devContext.args.clear, | ||
| dotenv: { | ||
| cwd: devContext.cwd, | ||
| fileName: devContext.args.dotenv | ||
| }, | ||
| envName: devContext.args.envName, | ||
| showBanner: ctx.showBanner !== false && !ipc.enabled, | ||
| listenOverrides: ctx.listenOverrides | ||
| }); | ||
| let address; | ||
| if (ipc.enabled) { | ||
| devServer.on("loading:error", (_error) => { | ||
| ipc.send({ | ||
| type: "nuxt:internal:dev:loading:error", | ||
| error: { | ||
| message: _error.message, | ||
| stack: _error.stack, | ||
| name: _error.name, | ||
| code: "code" in _error ? _error.code : void 0 | ||
| } | ||
| }); | ||
| }); | ||
| devServer.on("loading", (message) => { | ||
| ipc.send({ | ||
| type: "nuxt:internal:dev:loading", | ||
| message | ||
| }); | ||
| }); | ||
| devServer.on("restart", () => { | ||
| ipc.send({ type: "nuxt:internal:dev:restart" }); | ||
| }); | ||
| devServer.on("ready", (payload) => { | ||
| ipc.send({ | ||
| type: "nuxt:internal:dev:ready", | ||
| address: payload | ||
| }); | ||
| }); | ||
| } else devServer.on("ready", (payload) => { | ||
| address = payload; | ||
| }); | ||
| await devServer.init(); | ||
| if (process.env.DEBUG) console.debug(`Dev server (internal) initialized in ${Date.now() - start}ms`); | ||
| if (profileArg) for (const signal of [ | ||
| "exit", | ||
| "SIGTERM", | ||
| "SIGINT", | ||
| "SIGQUIT" | ||
| ]) process.once(signal, () => stopCpuProfile(devContext.cwd, "dev")); | ||
| return { | ||
| listener: devServer.listener, | ||
| close: async () => { | ||
| devServer.closeWatchers(); | ||
| await Promise.all([devServer.listener.close(), devServer.close()]); | ||
| devServer.releaseLock(); | ||
| }, | ||
| onReady: (callback) => { | ||
| if (address) callback(address); | ||
| else devServer.once("ready", (payload) => callback(payload)); | ||
| }, | ||
| onRestart: (callback) => { | ||
| let restarted = false; | ||
| function restart() { | ||
| if (!restarted) { | ||
| restarted = true; | ||
| callback(devServer); | ||
| } | ||
| } | ||
| devServer.once("restart", restart); | ||
| process.once("uncaughtException", restart); | ||
| process.once("unhandledRejection", restart); | ||
| } | ||
| }; | ||
| } | ||
| //#endregion | ||
| export { initialize as n, dev_exports as t }; |
| import { a as legacyRootDirArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { resolve } from "pathe"; | ||
| import { x } from "tinyexec"; | ||
| //#region ../nuxi/src/commands/devtools.ts | ||
| var devtools_default = defineCommand({ | ||
| meta: { | ||
| name: "devtools", | ||
| description: "Enable or disable devtools in a Nuxt project" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| command: { | ||
| type: "positional", | ||
| description: "Command to run", | ||
| valueHint: "enable|disable" | ||
| }, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const command = ctx.args.command; | ||
| if (!command || !["enable", "disable"].includes(command)) { | ||
| logger.error(`Unknown command ${colors.cyan(command || "")}.`); | ||
| process.exit(1); | ||
| } | ||
| await x("npx", [ | ||
| "@nuxt/devtools-wizard@latest", | ||
| command, | ||
| cwd | ||
| ], { | ||
| throwOnError: true, | ||
| nodeOptions: { | ||
| stdio: "inherit", | ||
| cwd | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { devtools_default as default }; |
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import process from "node:process"; | ||
| import { colors } from "consola/utils"; | ||
| //#region ../nuxi/src/utils/env.ts | ||
| function overrideEnv(targetEnv) { | ||
| const currentEnv = process.env.NODE_ENV; | ||
| if (currentEnv && currentEnv !== targetEnv) logger.warn(`Changing ${colors.cyan("NODE_ENV")} from ${colors.cyan(currentEnv)} to ${colors.cyan(targetEnv)}, to avoid unintended behavior.`); | ||
| process.env.NODE_ENV = targetEnv; | ||
| } | ||
| //#endregion | ||
| export { overrideEnv as t }; |
| import process from "node:process"; | ||
| import { colors } from "consola/utils"; | ||
| import { stripVTControlCharacters } from "node:util"; | ||
| //#region ../nuxi/src/utils/formatting.ts | ||
| const AT_MENTION_RE = /\b@([^, ]+)/g; | ||
| const BACKTICK_RE = /`([^`]*)`/g; | ||
| function getStringWidth(str) { | ||
| const stripped = stripVTControlCharacters(str); | ||
| let width = 0; | ||
| for (const char of stripped) { | ||
| const code = char.codePointAt(0); | ||
| if (!code) continue; | ||
| if (code >= 65024 && code <= 65039) continue; | ||
| if (code >= 127744 && code <= 129535 || code >= 128512 && code <= 128591 || code >= 128640 && code <= 128767 || code >= 9728 && code <= 9983 || code >= 9984 && code <= 10175 || code >= 129280 && code <= 129535 || code >= 129648 && code <= 129791) width += 2; | ||
| else width += 1; | ||
| } | ||
| return width; | ||
| } | ||
| function formatInfoBox(infoObj) { | ||
| let firstColumnLength = 0; | ||
| let ansiFirstColumnLength = 0; | ||
| const entries = Object.entries(infoObj).map(([label, val]) => { | ||
| if (label.length > firstColumnLength) { | ||
| ansiFirstColumnLength = colors.bold(colors.whiteBright(label)).length + 6; | ||
| firstColumnLength = label.length + 6; | ||
| } | ||
| return [label, val || "-"]; | ||
| }); | ||
| const terminalWidth = Math.max(process.stdout.columns || 80, firstColumnLength) - 8; | ||
| let boxStr = ""; | ||
| for (const [label, value] of entries) { | ||
| const formattedValue = value.replace(AT_MENTION_RE, (_, r) => colors.gray(` ${r}`)).replace(BACKTICK_RE, (_, r) => r); | ||
| boxStr += `${colors.bold(colors.whiteBright(label))}`.padEnd(ansiFirstColumnLength); | ||
| let boxRowLength = firstColumnLength; | ||
| const words = formattedValue.split(" "); | ||
| let currentLine = ""; | ||
| for (const word of words) { | ||
| const wordLength = getStringWidth(word); | ||
| const spaceLength = currentLine ? 1 : 0; | ||
| if (boxRowLength + wordLength + spaceLength > terminalWidth) { | ||
| if (currentLine) boxStr += colors.cyan(currentLine); | ||
| boxStr += `\n${" ".repeat(firstColumnLength)}`; | ||
| currentLine = word; | ||
| boxRowLength = firstColumnLength + wordLength; | ||
| } else { | ||
| currentLine += (currentLine ? " " : "") + word; | ||
| boxRowLength += wordLength + spaceLength; | ||
| } | ||
| } | ||
| if (currentLine) boxStr += colors.cyan(currentLine); | ||
| boxStr += "\n"; | ||
| } | ||
| return boxStr; | ||
| } | ||
| //#endregion | ||
| export { formatInfoBox as t }; |
| import { t as debug } from "./logger-C1qVsppt.mjs"; | ||
| import { existsSync, promises } from "node:fs"; | ||
| import { join } from "pathe"; | ||
| //#region ../nuxi/src/utils/fs.ts | ||
| async function clearDir(path, exclude) { | ||
| if (!exclude) await promises.rm(path, { | ||
| recursive: true, | ||
| force: true | ||
| }); | ||
| else if (existsSync(path)) { | ||
| const files = await promises.readdir(path); | ||
| await Promise.all(files.map(async (name) => { | ||
| if (!exclude.includes(name)) await promises.rm(join(path, name), { | ||
| recursive: true, | ||
| force: true | ||
| }); | ||
| })); | ||
| } | ||
| await promises.mkdir(path, { recursive: true }); | ||
| } | ||
| function clearBuildDir(path) { | ||
| return clearDir(path, [ | ||
| "cache", | ||
| "analyze", | ||
| "nuxt.json", | ||
| "nuxt.lock" | ||
| ]); | ||
| } | ||
| async function rmRecursive(paths) { | ||
| await Promise.all(paths.filter((p) => typeof p === "string").map(async (path) => { | ||
| debug(`Removing recursive path: ${path}`); | ||
| await promises.rm(path, { | ||
| recursive: true, | ||
| force: true | ||
| }).catch(() => {}); | ||
| })); | ||
| } | ||
| //#endregion | ||
| export { clearDir as n, rmRecursive as r, clearBuildDir as t }; |
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, r as envNameArgs, s as profileArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import build_default from "./build-BPupc27P.mjs"; | ||
| import { defineCommand } from "citty"; | ||
| //#region ../nuxi/src/commands/generate.ts | ||
| var generate_default = defineCommand({ | ||
| meta: { | ||
| name: "generate", | ||
| description: "Build Nuxt and prerender all routes" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| preset: { | ||
| type: "string", | ||
| description: "Nitro server preset" | ||
| }, | ||
| ...dotEnvArgs, | ||
| ...envNameArgs, | ||
| ...extendsArgs, | ||
| ...profileArgs, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| ctx.args.prerender = true; | ||
| await build_default.run(ctx); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { generate_default as default }; |
| import { a as legacyRootDirArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { n as tryResolveNuxt } from "./kit-BzPscsEd.mjs"; | ||
| import { t as getBuilder } from "./banner-CTtM2dxO.mjs"; | ||
| import { t as formatInfoBox } from "./formatting-BobJCzk9.mjs"; | ||
| import { t as getPackageManagerVersion } from "./packageManagers-Y5z0Pi7r.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { isBun, isDeno, isMinimal } from "std-env"; | ||
| import { box } from "@clack/prompts"; | ||
| import { resolve } from "pathe"; | ||
| import { readPackageJSON } from "pkg-types"; | ||
| import os from "node:os"; | ||
| import { detectPackageManager } from "nypm"; | ||
| import { writeText } from "tinyclip"; | ||
| //#region ../nuxi/package.json | ||
| var version = "3.35.0"; | ||
| //#endregion | ||
| //#region ../nuxi/src/commands/info.ts | ||
| const LEADING_SLASH_RE = /^\//; | ||
| var info_default = defineCommand({ | ||
| meta: { | ||
| name: "info", | ||
| description: "Get information about Nuxt project" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const nuxtConfig = await getNuxtConfig(cwd); | ||
| const { dependencies = {}, devDependencies = {} } = await readPackageJSON(cwd).catch(() => ({})); | ||
| const nuxtPath = tryResolveNuxt(cwd); | ||
| async function getDepVersion(name) { | ||
| for (const url of [cwd, nuxtPath]) { | ||
| if (!url) continue; | ||
| const pkg = await readPackageJSON(name, { url }).catch(() => null); | ||
| if (pkg) return pkg.version; | ||
| } | ||
| return dependencies[name] || devDependencies[name]; | ||
| } | ||
| async function listModules(arr = []) { | ||
| const info = []; | ||
| for (let m of arr) { | ||
| if (Array.isArray(m)) m = m[0]; | ||
| const name = normalizeConfigModule(m, cwd); | ||
| if (name) { | ||
| const v = await getDepVersion(name.split("/").splice(0, 2).join("/")); | ||
| info.push(`\`${v ? `${name}@${v}` : name}\``); | ||
| } | ||
| } | ||
| return info.join(", "); | ||
| } | ||
| const nuxtVersion = await getDepVersion("nuxt") || await getDepVersion("nuxt-nightly") || await getDepVersion("nuxt-edge") || await getDepVersion("nuxt3") || "-"; | ||
| const isLegacy = nuxtVersion.startsWith("2"); | ||
| const builder = !isLegacy ? nuxtConfig.builder || "vite" : nuxtConfig.bridge?.vite ? "vite" : nuxtConfig.buildModules?.includes("nuxt-vite") ? "vite" : "webpack"; | ||
| let packageManager = (await detectPackageManager(cwd))?.name; | ||
| if (packageManager) packageManager += `@${getPackageManagerVersion(packageManager)}`; | ||
| const osType = os.type(); | ||
| const builderInfo = typeof builder === "string" ? getBuilder(cwd, builder) : { | ||
| name: "custom", | ||
| version: "0.0.0" | ||
| }; | ||
| const infoObj = { | ||
| "Operating system": osType === "Darwin" ? `macOS ${os.release()}` : osType === "Windows_NT" ? `Windows ${os.release()}` : `${osType} ${os.release()}`, | ||
| "CPU": `${os.cpus()[0]?.model || "unknown"} (${os.cpus().length} cores)`, | ||
| ...isBun ? { "Bun version": Bun?.version } : isDeno ? { "Deno version": Deno?.version.deno } : { "Node.js version": process.version }, | ||
| "nuxt/cli version": version, | ||
| "Package manager": packageManager ?? "unknown", | ||
| "Nuxt version": nuxtVersion, | ||
| "Nitro version": await getDepVersion("nitropack") || await getDepVersion("nitro"), | ||
| "Builder": builderInfo.name === "custom" ? "custom" : `${builderInfo.name.toLowerCase()}@${builderInfo.version}`, | ||
| "Config": Object.keys(nuxtConfig).map((key) => `\`${key}\``).sort().join(", "), | ||
| "Modules": await listModules(nuxtConfig.modules), | ||
| ...isLegacy ? { "Build modules": await listModules(nuxtConfig.buildModules || []) } : {} | ||
| }; | ||
| logger.info(`Nuxt root directory: ${colors.cyan(nuxtConfig.rootDir || cwd)}\n`); | ||
| const boxStr = formatInfoBox(infoObj); | ||
| let firstColumnLength = 0; | ||
| let secondColumnLength = 0; | ||
| const entries = Object.entries(infoObj).map(([label, val]) => { | ||
| if (label.length > firstColumnLength) firstColumnLength = label.length + 4; | ||
| if ((val || "").length > secondColumnLength) secondColumnLength = (val || "").length + 2; | ||
| return [label, val || "-"]; | ||
| }); | ||
| let copyStr = `| ${" ".repeat(firstColumnLength)} | ${" ".repeat(secondColumnLength)} |\n| ${"-".repeat(firstColumnLength)} | ${"-".repeat(secondColumnLength)} |\n`; | ||
| for (const [label, value] of entries) if (!isMinimal) copyStr += `| ${`**${label}**`.padEnd(firstColumnLength)} | ${(value.includes("`") ? value : `\`${value}\``).padEnd(secondColumnLength)} |\n`; | ||
| if (!isMinimal && await writeText(copyStr).then(() => true).catch(() => false)) box(`\n${boxStr}`, ` Nuxt project info ${colors.gray("(copied to clipboard) ")}`, { | ||
| contentAlign: "left", | ||
| titleAlign: "left", | ||
| width: "auto", | ||
| titlePadding: 2, | ||
| contentPadding: 2, | ||
| rounded: true | ||
| }); | ||
| else logger.info(`Nuxt project info:\n${copyStr}`, { withGuide: false }); | ||
| const isNuxt3 = !isLegacy; | ||
| const isBridge = !isNuxt3 && infoObj["Build modules"]?.includes("bridge"); | ||
| const repo = isBridge ? "nuxt/bridge" : "nuxt/nuxt"; | ||
| const docsURL = isNuxt3 || isBridge ? "https://nuxt.com" : "https://v2.nuxt.com"; | ||
| logger.info(`👉 Read documentation: ${colors.cyan(docsURL)}`); | ||
| if (isNuxt3 || isBridge) { | ||
| logger.info(`👉 Report an issue: ${colors.cyan(`https://github.com/${repo}/issues/new?template=bug-report.yml`)}`, { spacing: 0 }); | ||
| logger.info(`👉 Suggest an improvement: ${colors.cyan(`https://github.com/${repo}/discussions/new`)}`, { spacing: 0 }); | ||
| } | ||
| } | ||
| }); | ||
| function normalizeConfigModule(module, rootDir) { | ||
| if (!module) return null; | ||
| if (typeof module === "string") return module.split(rootDir).pop().split("node_modules").pop().replace(LEADING_SLASH_RE, ""); | ||
| if (typeof module === "function") return `${module.name}()`; | ||
| if (Array.isArray(module)) return normalizeConfigModule(module[0], rootDir); | ||
| return null; | ||
| } | ||
| async function getNuxtConfig(rootDir) { | ||
| try { | ||
| const { createJiti } = await import("jiti"); | ||
| const jiti = createJiti(rootDir, { | ||
| interopDefault: true, | ||
| alias: { | ||
| "~": rootDir, | ||
| "@": rootDir | ||
| } | ||
| }); | ||
| globalThis.defineNuxtConfig = (c) => c; | ||
| const result = await jiti.import("./nuxt.config", { default: true }); | ||
| delete globalThis.defineNuxtConfig; | ||
| return result; | ||
| } catch { | ||
| return {}; | ||
| } | ||
| } | ||
| //#endregion | ||
| export { info_default as default }; |
| import { o as logLevelArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { n as themeColor, t as nuxtIcon } from "./ascii-B6JJ3B2W.mjs"; | ||
| import { r as relativeToProcess } from "./kit-BzPscsEd.mjs"; | ||
| import { t as getNuxtVersion } from "./versions--iBjrFVR.mjs"; | ||
| import { n as fetchModules, t as checkNuxtCompatibility } from "./_utils-D57pBv3m.mjs"; | ||
| import add_default, { n as runCommand$1, t as selectModulesAutocomplete } from "./add-DY-72t8C.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { hasTTY } from "std-env"; | ||
| import { box, cancel, confirm, intro, isCancel, outro, select, spinner, tasks, text } from "@clack/prompts"; | ||
| import { existsSync } from "node:fs"; | ||
| import { basename, join, relative, resolve } from "pathe"; | ||
| import { findFile, readPackageJSON, writePackageJSON } from "pkg-types"; | ||
| import { x } from "tinyexec"; | ||
| import { installDependencies } from "nypm"; | ||
| import { downloadTemplate, startShell } from "giget"; | ||
| import { $fetch } from "ofetch"; | ||
| //#region ../nuxi/src/utils/starter-templates.ts | ||
| const hiddenTemplates = [ | ||
| "doc-driven", | ||
| "v4", | ||
| "v4-compat", | ||
| "v2-bridge", | ||
| "v3", | ||
| "ui-vue", | ||
| "module-devtools", | ||
| "layer", | ||
| "hub" | ||
| ]; | ||
| const fetchOptions = { | ||
| timeout: 3e3, | ||
| responseType: "json", | ||
| headers: { | ||
| "user-agent": "@nuxt/cli", | ||
| ...process.env.GITHUB_TOKEN ? { authorization: `token ${process.env.GITHUB_TOKEN}` } : {} | ||
| } | ||
| }; | ||
| let templatesCache = null; | ||
| async function getTemplates() { | ||
| templatesCache ||= fetchTemplates(); | ||
| return templatesCache; | ||
| } | ||
| async function fetchTemplates() { | ||
| const templates = {}; | ||
| const files = await $fetch("https://api.github.com/repos/nuxt/starter/contents/templates?ref=templates", fetchOptions); | ||
| await Promise.all(files.map(async (file) => { | ||
| if (!file.download_url || file.type !== "file" || !file.name.endsWith(".json")) return; | ||
| const templateName = file.name.replace(".json", ""); | ||
| if (hiddenTemplates.includes(templateName)) return; | ||
| templates[templateName] = void 0; | ||
| templates[templateName] = await $fetch(file.download_url, fetchOptions); | ||
| })); | ||
| return templates; | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/commands/init.ts | ||
| const NON_WORD_RE = /[^\w-]/g; | ||
| const MULTI_DASH_RE = /-{2,}/g; | ||
| const LEADING_TRAILING_DASH_RE = /^-|-$/g; | ||
| const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/nuxt/starter/templates/templates"; | ||
| const DEFAULT_TEMPLATE_NAME = "minimal"; | ||
| const packageManagerOptions = Object.keys({ | ||
| npm: void 0, | ||
| pnpm: void 0, | ||
| yarn: void 0, | ||
| bun: void 0, | ||
| deno: void 0 | ||
| }); | ||
| var init_default = defineCommand({ | ||
| meta: { | ||
| name: "init", | ||
| description: "Initialize a fresh project" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| dir: { | ||
| type: "positional", | ||
| description: "Project directory", | ||
| default: "" | ||
| }, | ||
| template: { | ||
| type: "string", | ||
| alias: "t", | ||
| description: "Template name" | ||
| }, | ||
| force: { | ||
| type: "boolean", | ||
| alias: "f", | ||
| description: "Override existing directory" | ||
| }, | ||
| offline: { | ||
| type: "boolean", | ||
| description: "Force offline mode" | ||
| }, | ||
| preferOffline: { | ||
| type: "boolean", | ||
| description: "Prefer offline mode" | ||
| }, | ||
| install: { | ||
| type: "boolean", | ||
| default: true, | ||
| description: "Skip installing dependencies" | ||
| }, | ||
| gitInit: { | ||
| type: "boolean", | ||
| description: "Initialize git repository" | ||
| }, | ||
| shell: { | ||
| type: "boolean", | ||
| description: "Start shell after installation in project directory" | ||
| }, | ||
| packageManager: { | ||
| type: "string", | ||
| description: "Package manager choice (npm, pnpm, yarn, bun)" | ||
| }, | ||
| modules: { | ||
| type: "string", | ||
| required: false, | ||
| description: "Nuxt modules to install (comma separated without spaces)", | ||
| negativeDescription: "Skip module installation prompt", | ||
| alias: "M" | ||
| }, | ||
| nightly: { | ||
| type: "string", | ||
| description: "Use Nuxt nightly release channel (3x or latest)" | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| if (!ctx.args.offline && !ctx.args.preferOffline && !ctx.args.template) getTemplates().catch(() => null); | ||
| if (hasTTY) process.stdout.write(`\n${nuxtIcon}\n\n`); | ||
| intro(colors.bold(`Welcome to Nuxt!`.split("").map((m) => `${themeColor}${m}`).join(""))); | ||
| let availableTemplates = {}; | ||
| if (!ctx.args.template || !ctx.args.dir) { | ||
| const defaultTemplates = await import("./templates-BNoyKfB8.mjs").then((r) => r.templates); | ||
| if (ctx.args.offline || ctx.args.preferOffline) availableTemplates = defaultTemplates; | ||
| else { | ||
| const templatesSpinner = spinner(); | ||
| templatesSpinner.start("Loading available templates"); | ||
| try { | ||
| availableTemplates = await getTemplates(); | ||
| templatesSpinner.stop("Templates loaded"); | ||
| } catch { | ||
| availableTemplates = defaultTemplates; | ||
| templatesSpinner.stop("Templates loaded from cache"); | ||
| } | ||
| } | ||
| } | ||
| let templateName = ctx.args.template; | ||
| if (!templateName) { | ||
| const result = await select({ | ||
| message: "Which template would you like to use?", | ||
| options: Object.entries(availableTemplates).map(([name, data]) => { | ||
| return { | ||
| value: name, | ||
| label: data ? `${colors.whiteBright(name)} – ${data.description}` : name, | ||
| hint: name === DEFAULT_TEMPLATE_NAME ? "recommended" : void 0 | ||
| }; | ||
| }), | ||
| initialValue: DEFAULT_TEMPLATE_NAME | ||
| }); | ||
| if (isCancel(result)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| templateName = result; | ||
| } | ||
| templateName ||= DEFAULT_TEMPLATE_NAME; | ||
| if (typeof templateName !== "string") { | ||
| logger.error("Please specify a template!"); | ||
| process.exit(1); | ||
| } | ||
| let dir = ctx.args.dir; | ||
| if (dir === "") { | ||
| const defaultDir = availableTemplates[templateName]?.defaultDir || "nuxt-app"; | ||
| const result = await text({ | ||
| message: "Where would you like to create your project?", | ||
| placeholder: `./${defaultDir}`, | ||
| defaultValue: defaultDir | ||
| }); | ||
| if (isCancel(result)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| dir = result; | ||
| } | ||
| const cwd = resolve(ctx.args.cwd); | ||
| let templateDownloadPath = resolve(cwd, dir); | ||
| logger.step(`Creating project in ${colors.cyan(relativeToProcess(templateDownloadPath))}`); | ||
| let shouldForce = Boolean(ctx.args.force); | ||
| if (!shouldForce && existsSync(templateDownloadPath)) { | ||
| const selectedAction = await select({ | ||
| message: `The directory ${colors.cyan(relativeToProcess(templateDownloadPath))} already exists. What would you like to do?`, | ||
| options: [ | ||
| { | ||
| value: "override", | ||
| label: "Override its contents" | ||
| }, | ||
| { | ||
| value: "different", | ||
| label: "Select different directory" | ||
| }, | ||
| { | ||
| value: "abort", | ||
| label: "Abort" | ||
| } | ||
| ] | ||
| }); | ||
| if (isCancel(selectedAction)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| switch (selectedAction) { | ||
| case "override": | ||
| shouldForce = true; | ||
| break; | ||
| case "different": { | ||
| const result = await text({ message: "Please specify a different directory:" }); | ||
| if (isCancel(result)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| templateDownloadPath = resolve(cwd, result); | ||
| break; | ||
| } | ||
| default: process.exit(1); | ||
| } | ||
| } | ||
| let template; | ||
| const downloadSpinner = spinner(); | ||
| downloadSpinner.start(`Downloading ${colors.cyan(templateName)} template`); | ||
| try { | ||
| template = await downloadTemplate(templateName, { | ||
| dir: templateDownloadPath, | ||
| force: shouldForce, | ||
| offline: Boolean(ctx.args.offline), | ||
| preferOffline: Boolean(ctx.args.preferOffline), | ||
| registry: process.env.NUXI_INIT_REGISTRY || DEFAULT_REGISTRY | ||
| }); | ||
| if (dir.length > 0) { | ||
| const path = await findFile("package.json", { | ||
| startingFrom: join(templateDownloadPath, "package.json"), | ||
| reverse: true | ||
| }); | ||
| if (path) { | ||
| const pkg = await readPackageJSON(path, { try: true }); | ||
| if (pkg && pkg.name) { | ||
| const slug = basename(templateDownloadPath).replace(NON_WORD_RE, "-").replace(MULTI_DASH_RE, "-").replace(LEADING_TRAILING_DASH_RE, ""); | ||
| if (slug) { | ||
| pkg.name = slug; | ||
| await writePackageJSON(path, pkg); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| downloadSpinner.stop(`Downloaded ${colors.cyan(template.name)} template`); | ||
| } catch (err) { | ||
| downloadSpinner.error("Template download failed"); | ||
| if (process.env.DEBUG) throw err; | ||
| logger.error(err.toString()); | ||
| process.exit(1); | ||
| } | ||
| if (ctx.args.nightly !== void 0 && !ctx.args.offline && !ctx.args.preferOffline) { | ||
| const nightlySpinner = spinner(); | ||
| nightlySpinner.start("Fetching nightly version info"); | ||
| const response = await $fetch("https://registry.npmjs.org/nuxt-nightly"); | ||
| const nightlyChannelTag = ctx.args.nightly || "latest"; | ||
| if (!nightlyChannelTag) { | ||
| nightlySpinner.error("Failed to get nightly channel tag"); | ||
| logger.error(`Error getting nightly channel tag.`); | ||
| process.exit(1); | ||
| } | ||
| const nightlyChannelVersion = response["dist-tags"][nightlyChannelTag]; | ||
| if (!nightlyChannelVersion) { | ||
| nightlySpinner.error("Nightly version not found"); | ||
| logger.error(`Nightly channel version for tag ${colors.cyan(nightlyChannelTag)} not found.`); | ||
| process.exit(1); | ||
| } | ||
| const nightlyNuxtPackageJsonVersion = `npm:nuxt-nightly@${nightlyChannelVersion}`; | ||
| const packageJsonPath = resolve(cwd, dir); | ||
| const packageJson = await readPackageJSON(packageJsonPath); | ||
| if (packageJson.dependencies && "nuxt" in packageJson.dependencies) packageJson.dependencies.nuxt = nightlyNuxtPackageJsonVersion; | ||
| else if (packageJson.devDependencies && "nuxt" in packageJson.devDependencies) packageJson.devDependencies.nuxt = nightlyNuxtPackageJsonVersion; | ||
| await writePackageJSON(join(packageJsonPath, "package.json"), packageJson); | ||
| nightlySpinner.stop(`Updated to nightly version ${colors.cyan(nightlyChannelVersion)}`); | ||
| } | ||
| const currentPackageManager = detectCurrentPackageManager(); | ||
| const packageManagerArg = ctx.args.packageManager; | ||
| const packageManagerSelectOptions = packageManagerOptions.map((pm) => ({ | ||
| label: pm, | ||
| value: pm, | ||
| hint: currentPackageManager === pm ? "current" : void 0 | ||
| })); | ||
| let selectedPackageManager; | ||
| if (packageManagerOptions.includes(packageManagerArg)) selectedPackageManager = packageManagerArg; | ||
| else { | ||
| const result = await select({ | ||
| message: "Which package manager would you like to use?", | ||
| options: packageManagerSelectOptions, | ||
| initialValue: currentPackageManager | ||
| }); | ||
| if (isCancel(result)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| selectedPackageManager = result; | ||
| } | ||
| let gitInit = ctx.args.gitInit === "false" ? false : ctx.args.gitInit; | ||
| if (gitInit === void 0) { | ||
| const result = await confirm({ message: "Initialize git repository?" }); | ||
| if (isCancel(result)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| gitInit = result; | ||
| } | ||
| if (ctx.args.install === false || ctx.args.install === "false") logger.info("Skipping install dependencies step."); | ||
| else { | ||
| const setupTasks = [{ | ||
| title: `Installing dependencies with ${colors.cyan(selectedPackageManager)}`, | ||
| task: async () => { | ||
| await installDependencies({ | ||
| cwd: template.dir, | ||
| packageManager: { | ||
| name: selectedPackageManager, | ||
| command: selectedPackageManager | ||
| }, | ||
| silent: true | ||
| }); | ||
| return "Dependencies installed"; | ||
| } | ||
| }]; | ||
| if (gitInit) setupTasks.push({ | ||
| title: "Initializing git repository", | ||
| task: async () => { | ||
| try { | ||
| await x("git", ["init", template.dir], { | ||
| throwOnError: true, | ||
| nodeOptions: { stdio: "inherit" } | ||
| }); | ||
| return "Git repository initialized"; | ||
| } catch (err) { | ||
| return `Git initialization failed: ${err}`; | ||
| } | ||
| } | ||
| }); | ||
| try { | ||
| await tasks(setupTasks); | ||
| } catch (err) { | ||
| if (process.env.DEBUG) throw err; | ||
| logger.error(err.toString()); | ||
| process.exit(1); | ||
| } | ||
| } | ||
| const modulesToAdd = []; | ||
| if (ctx.args.modules !== void 0) for (const segment of (ctx.args.modules || "").split(",")) { | ||
| const mod = segment.trim(); | ||
| if (mod) modulesToAdd.push(mod); | ||
| } | ||
| else if (!ctx.args.offline && !ctx.args.preferOffline) { | ||
| const modulesPromise = fetchModules(); | ||
| const wantsUserModules = await confirm({ | ||
| message: `Would you like to browse and install modules?`, | ||
| initialValue: false | ||
| }); | ||
| if (isCancel(wantsUserModules)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| if (wantsUserModules) { | ||
| const modulesSpinner = spinner(); | ||
| modulesSpinner.start("Fetching available modules"); | ||
| const [response, templateDeps, nuxtVersion] = await Promise.all([ | ||
| modulesPromise, | ||
| getTemplateDependencies(template.dir), | ||
| getNuxtVersion(template.dir) | ||
| ]); | ||
| modulesSpinner.stop("Modules loaded"); | ||
| const allModules = response.filter((module) => module.npm !== "@nuxt/devtools" && !templateDeps.includes(module.npm) && (!module.compatibility.nuxt || checkNuxtCompatibility(module, nuxtVersion))); | ||
| if (allModules.length === 0) logger.info("All modules are already included in this template."); | ||
| else { | ||
| const result = await selectModulesAutocomplete({ modules: allModules }); | ||
| if (result.selected.length > 0) { | ||
| const modules = result.selected; | ||
| const { toInstall, skipped } = filterModules(modules, Object.fromEntries(await Promise.all(modules.map(async (module) => [module, await getModuleDependencies(module)])))); | ||
| if (skipped.length) logger.info(`The following modules are already included as dependencies of another module and will not be installed: ${skipped.map((m) => colors.cyan(m)).join(", ")}`); | ||
| modulesToAdd.push(...toInstall); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| if (modulesToAdd.length > 0) await runCommand$1(add_default, [ | ||
| ...modulesToAdd, | ||
| `--cwd=${templateDownloadPath}`, | ||
| ctx.args.install ? "" : "--skipInstall", | ||
| ctx.args.logLevel ? `--logLevel=${ctx.args.logLevel}` : "" | ||
| ].filter(Boolean)); | ||
| outro(`✨ Nuxt project has been created with the ${colors.cyan(template.name)} template.`); | ||
| const relativeTemplateDir = relative(process.cwd(), template.dir) || "."; | ||
| const runCmd = selectedPackageManager === "deno" ? "task" : "run"; | ||
| box(`\n${[!ctx.args.shell && relativeTemplateDir.length > 1 && colors.cyan(`cd ${relativeTemplateDir}`), colors.cyan(`${selectedPackageManager} ${runCmd} dev`)].filter(Boolean).map((step) => ` › ${step}`).join("\n")}\n`, ` 👉 Next steps `, { | ||
| contentAlign: "left", | ||
| titleAlign: "left", | ||
| width: "auto", | ||
| titlePadding: 2, | ||
| contentPadding: 2, | ||
| rounded: true, | ||
| withGuide: false, | ||
| formatBorder: (text) => `${themeColor + text}\x1B[0m` | ||
| }); | ||
| if (ctx.args.shell) startShell(template.dir); | ||
| } | ||
| }); | ||
| async function getModuleDependencies(moduleName) { | ||
| try { | ||
| const dependencies = (await $fetch(`https://registry.npmjs.org/${moduleName}/latest`)).dependencies || {}; | ||
| return Object.keys(dependencies); | ||
| } catch (err) { | ||
| logger.warn(`Could not get dependencies for ${colors.cyan(moduleName)}: ${err}`); | ||
| return []; | ||
| } | ||
| } | ||
| function filterModules(modules, allDependencies) { | ||
| const result = { | ||
| toInstall: [], | ||
| skipped: [] | ||
| }; | ||
| for (const module of modules) if (modules.some((otherModule) => { | ||
| if (otherModule === module) return false; | ||
| return (allDependencies[otherModule] || []).includes(module); | ||
| })) result.skipped.push(module); | ||
| else result.toInstall.push(module); | ||
| return result; | ||
| } | ||
| async function getTemplateDependencies(templateDir) { | ||
| try { | ||
| const packageJsonPath = join(templateDir, "package.json"); | ||
| if (!existsSync(packageJsonPath)) return []; | ||
| const packageJson = await readPackageJSON(packageJsonPath); | ||
| const directDeps = { | ||
| ...packageJson.dependencies, | ||
| ...packageJson.devDependencies | ||
| }; | ||
| const directDepNames = Object.keys(directDeps); | ||
| const allDeps = new Set(directDepNames); | ||
| (await Promise.all(directDepNames.map((dep) => getModuleDependencies(dep)))).forEach((deps) => { | ||
| deps.forEach((dep) => allDeps.add(dep)); | ||
| }); | ||
| return [...allDeps]; | ||
| } catch (err) { | ||
| logger.warn(`Could not read template dependencies: ${err}`); | ||
| return []; | ||
| } | ||
| } | ||
| function detectCurrentPackageManager() { | ||
| const userAgent = process.env.npm_config_user_agent; | ||
| if (!userAgent) return; | ||
| const [name] = userAgent.split("/"); | ||
| if (packageManagerOptions.includes(name)) return name; | ||
| } | ||
| //#endregion | ||
| export { init_default as default }; |
| import process from "node:process"; | ||
| import { pathToFileURL } from "node:url"; | ||
| import { relative } from "pathe"; | ||
| import { resolveModulePath } from "exsolve"; | ||
| //#region ../nuxi/src/utils/paths.ts | ||
| const cwd = process.cwd(); | ||
| function relativeToProcess(path) { | ||
| return relative(cwd, path) || path; | ||
| } | ||
| function withNodePath(path) { | ||
| return [path, ...process.env.NODE_PATH?.split(":") || []]; | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/kit.ts | ||
| async function loadKit(rootDir) { | ||
| try { | ||
| let kit = await import(pathToFileURL(resolveModulePath("@nuxt/kit", { from: tryResolveNuxt(rootDir) || rootDir })).href); | ||
| if (!kit.writeTypes) kit = { | ||
| ...kit, | ||
| writeTypes: () => { | ||
| throw new Error("`writeTypes` is not available in this version of `@nuxt/kit`. Please upgrade to v3.7 or newer."); | ||
| } | ||
| }; | ||
| return kit; | ||
| } catch (e) { | ||
| if (e.toString().includes("Cannot find module '@nuxt/kit'")) throw new Error("nuxi requires `@nuxt/kit` to be installed in your project. Try installing `nuxt` v3+ or `@nuxt/bridge` first."); | ||
| throw e; | ||
| } | ||
| } | ||
| function tryResolveNuxt(rootDir) { | ||
| for (const pkg of [ | ||
| "nuxt-nightly", | ||
| "nuxt", | ||
| "nuxt3", | ||
| "nuxt-edge" | ||
| ]) { | ||
| const path = resolveModulePath(pkg, { | ||
| from: withNodePath(rootDir), | ||
| try: true | ||
| }); | ||
| if (path) return path; | ||
| } | ||
| return null; | ||
| } | ||
| //#endregion | ||
| export { withNodePath as i, tryResolveNuxt as n, relativeToProcess as r, loadKit as t }; |
| import { n as themeColor } from "./ascii-B6JJ3B2W.mjs"; | ||
| import process from "node:process"; | ||
| import { colors } from "consola/utils"; | ||
| import { isAgent } from "std-env"; | ||
| import { box } from "@clack/prompts"; | ||
| import { mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs"; | ||
| import { join, relative } from "pathe"; | ||
| //#region ../nuxi/src/utils/profile.ts | ||
| const RELATIVE_PATH_RE = /^(?![^.]{1,2}\/)/; | ||
| let session; | ||
| let profileCount = 0; | ||
| async function startCpuProfile() { | ||
| const cli = globalThis.__nuxt_cli__; | ||
| if (cli?.cpuProfileSession) { | ||
| session = cli.cpuProfileSession; | ||
| delete cli.cpuProfileSession; | ||
| return; | ||
| } | ||
| session = new (await (import("node:inspector"))).Session(); | ||
| session.connect(); | ||
| try { | ||
| await new Promise((res, rej) => { | ||
| session.post("Profiler.enable", (err) => { | ||
| if (err) return rej(err); | ||
| session.post("Profiler.start", (err) => { | ||
| if (err) return rej(err); | ||
| res(); | ||
| }); | ||
| }); | ||
| }); | ||
| } catch (err) { | ||
| session.disconnect(); | ||
| session = void 0; | ||
| throw err; | ||
| } | ||
| } | ||
| async function stopCpuProfile(outDir, command) { | ||
| if (!session) return; | ||
| const s = session; | ||
| session = void 0; | ||
| const count = profileCount++; | ||
| const outPath = join(outDir, `nuxt-${command}${count ? `-${count}` : ""}.cpuprofile`); | ||
| const relativeOutPath = relative(process.cwd(), outPath).replace(RELATIVE_PATH_RE, "./"); | ||
| try { | ||
| await new Promise((resolve, reject) => { | ||
| s.post("Profiler.stop", (err, params) => { | ||
| if (err) return reject(err); | ||
| if (!params?.profile) return resolve(params); | ||
| try { | ||
| mkdirSync(outDir, { recursive: true }); | ||
| writeFileSync(outPath, JSON.stringify(params.profile)); | ||
| box(`\n${[`CPU profile written to ${colors.cyan(relativeOutPath)}.`, `Open it in a CPU profile viewer like your IDE, or ${colors.cyan("https://discoveryjs.github.io/cpupro")}.`].map((step) => ` › ${step}`).join("\n")}\n`, "", { | ||
| contentAlign: "left", | ||
| titleAlign: "left", | ||
| width: "auto", | ||
| titlePadding: 2, | ||
| contentPadding: 2, | ||
| rounded: true, | ||
| withGuide: false, | ||
| formatBorder: (text) => `${themeColor + text}\x1B[0m` | ||
| }); | ||
| } catch {} | ||
| resolve(params); | ||
| }); | ||
| }); | ||
| } finally { | ||
| s.disconnect(); | ||
| } | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/lockfile.ts | ||
| const LOCK_FILENAME = "nuxt.lock"; | ||
| const MAX_LOCK_AGE_MS = 1440 * 60 * 1e3; | ||
| function isProcessAlive(pid) { | ||
| try { | ||
| process.kill(pid, 0); | ||
| return true; | ||
| } catch (err) { | ||
| return err.code === "EPERM"; | ||
| } | ||
| } | ||
| function readLockFile(lockPath) { | ||
| try { | ||
| return JSON.parse(readFileSync(lockPath, "utf-8")); | ||
| } catch { | ||
| return; | ||
| } | ||
| } | ||
| function tryUnlink(lockPath) { | ||
| try { | ||
| unlinkSync(lockPath); | ||
| } catch {} | ||
| } | ||
| function isLockActive(info) { | ||
| if (info.pid === process.pid) return false; | ||
| if (!isProcessAlive(info.pid)) return false; | ||
| if (Date.now() - info.startedAt > MAX_LOCK_AGE_MS) return false; | ||
| return true; | ||
| } | ||
| /** | ||
| * Locking is enabled for agents by default. `NUXT_LOCK=1` forces it on for | ||
| * non-agents; `NUXT_IGNORE_LOCK=1` forces it off. | ||
| */ | ||
| function isLockEnabled() { | ||
| if (process.env.NUXT_IGNORE_LOCK) return false; | ||
| if (process.env.NUXT_LOCK === "1" || process.env.NUXT_LOCK === "true") return true; | ||
| return isAgent; | ||
| } | ||
| /** | ||
| * Atomically acquire a build/dev lock. | ||
| * Returns `{ existing }` if another live process holds the lock, otherwise | ||
| * `{ release }` to be invoked on shutdown. No-op when locking is disabled. | ||
| */ | ||
| function acquireLock(buildDir, info) { | ||
| if (!isLockEnabled()) return { release: () => {} }; | ||
| const lockPath = join(buildDir, LOCK_FILENAME); | ||
| const fullInfo = { | ||
| pid: process.pid, | ||
| startedAt: Date.now(), | ||
| ...info | ||
| }; | ||
| for (let attempt = 0; attempt < 2; attempt++) try { | ||
| writeFileSync(lockPath, JSON.stringify(fullInfo, null, 2), { flag: "wx" }); | ||
| return { release: makeRelease(lockPath) }; | ||
| } catch (err) { | ||
| if (err.code !== "EEXIST") throw err; | ||
| const existing = readLockFile(lockPath); | ||
| if (existing && isLockActive(existing)) return { existing }; | ||
| tryUnlink(lockPath); | ||
| } | ||
| const existing = readLockFile(lockPath); | ||
| if (existing && isLockActive(existing)) return { existing }; | ||
| return { release: () => {} }; | ||
| } | ||
| /** | ||
| * Overwrite an existing lock we already own with updated metadata (e.g. port | ||
| * information learned after the listener binds). Callers must hold the lock | ||
| * via a prior successful `acquireLock`. Does nothing when locking is disabled. | ||
| */ | ||
| function updateLock(buildDir, info) { | ||
| if (!isLockEnabled()) return; | ||
| const lockPath = join(buildDir, LOCK_FILENAME); | ||
| const current = readLockFile(lockPath); | ||
| if (current && current.pid !== process.pid) return; | ||
| const next = { | ||
| pid: process.pid, | ||
| startedAt: current?.startedAt ?? Date.now(), | ||
| ...info | ||
| }; | ||
| try { | ||
| writeFileSync(lockPath, JSON.stringify(next, null, 2)); | ||
| } catch {} | ||
| } | ||
| function makeRelease(lockPath) { | ||
| let released = false; | ||
| function release() { | ||
| if (released) return; | ||
| released = true; | ||
| process.off("exit", release); | ||
| const current = readLockFile(lockPath); | ||
| if (!current || current.pid === process.pid) tryUnlink(lockPath); | ||
| } | ||
| process.on("exit", release); | ||
| return release; | ||
| } | ||
| /** | ||
| * Format an error message when a Nuxt process is already running. | ||
| * Designed to be actionable for both humans and LLM agents. | ||
| */ | ||
| function formatLockError(info) { | ||
| const killCmd = process.platform === "win32" ? `taskkill /PID ${info.pid} /F` : `kill ${info.pid}`; | ||
| const lines = [ | ||
| "", | ||
| `Another Nuxt ${info.command === "dev" ? "dev server" : "build"} is already running:`, | ||
| "" | ||
| ]; | ||
| if (info.url) lines.push(` URL: ${info.url}`); | ||
| lines.push(` PID: ${info.pid}`); | ||
| lines.push(` Dir: ${info.cwd}`); | ||
| lines.push(` Started: ${new Date(info.startedAt).toLocaleString()}`); | ||
| lines.push(""); | ||
| if (info.command === "dev" && info.url) lines.push(`Run \`${killCmd}\` to stop it, or connect to ${info.url}`); | ||
| else lines.push(`Run \`${killCmd}\` to stop it.`); | ||
| lines.push(`Set NUXT_IGNORE_LOCK=1 to bypass this check.`); | ||
| lines.push(""); | ||
| return lines.join("\n"); | ||
| } | ||
| //#endregion | ||
| export { stopCpuProfile as a, startCpuProfile as i, formatLockError as n, updateLock as r, acquireLock as t }; |
| import { log } from "@clack/prompts"; | ||
| import createDebug from "debug"; | ||
| //#region ../nuxi/src/utils/logger.ts | ||
| const logger = log; | ||
| const debug = createDebug("nuxi"); | ||
| //#endregion | ||
| export { logger as n, debug as t }; |
| import { defineCommand } from "citty"; | ||
| //#region ../nuxi/src/commands/module/index.ts | ||
| var module_default = defineCommand({ | ||
| meta: { | ||
| name: "module", | ||
| description: "Manage Nuxt modules" | ||
| }, | ||
| args: {}, | ||
| subCommands: { | ||
| add: () => import("./add-DY-72t8C.mjs").then((r) => r.default || r), | ||
| search: () => import("./search-8g9NTd4j.mjs").then((r) => r.default || r) | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { module_default as default }; |
| //#region ../nuxi/src/utils/templates/names.ts | ||
| /** | ||
| * List of available template names for `nuxi add-template`. | ||
| * | ||
| * This is a separate module so that `main.ts` can import just the names | ||
| * without pulling in all 16 template implementation modules. | ||
| */ | ||
| const templateNames = [ | ||
| "api", | ||
| "app", | ||
| "app-config", | ||
| "component", | ||
| "composable", | ||
| "error", | ||
| "layer", | ||
| "layout", | ||
| "middleware", | ||
| "module", | ||
| "page", | ||
| "plugin", | ||
| "server-middleware", | ||
| "server-plugin", | ||
| "server-route", | ||
| "server-util" | ||
| ]; | ||
| //#endregion | ||
| export { templateNames as t }; |
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { r as rmRecursive } from "./fs-B0HqP3GX.mjs"; | ||
| import { promises } from "node:fs"; | ||
| import { dirname, resolve } from "pathe"; | ||
| import { hash } from "ohash"; | ||
| //#region ../nuxi/src/utils/nuxt.ts | ||
| const GIT_ID_RE = /\.([0-9a-f]{7,8})$/; | ||
| async function cleanupNuxtDirs(rootDir, buildDir) { | ||
| logger.info("Cleaning up generated Nuxt files and caches..."); | ||
| await rmRecursive([ | ||
| buildDir, | ||
| ".output", | ||
| "dist", | ||
| "node_modules/.vite", | ||
| "node_modules/.cache" | ||
| ].map((dir) => resolve(rootDir, dir))); | ||
| } | ||
| function nuxtVersionToGitIdentifier(version) { | ||
| const id = GIT_ID_RE.exec(version); | ||
| if (id?.[1]) return id[1]; | ||
| return `v${version}`; | ||
| } | ||
| function resolveNuxtManifest(nuxt) { | ||
| const manifest = { | ||
| _hash: null, | ||
| project: { rootDir: nuxt.options.rootDir }, | ||
| versions: { nuxt: nuxt._version } | ||
| }; | ||
| manifest._hash = hash(manifest); | ||
| return manifest; | ||
| } | ||
| async function writeNuxtManifest(nuxt, manifest = resolveNuxtManifest(nuxt)) { | ||
| const manifestPath = resolve(nuxt.options.buildDir, "nuxt.json"); | ||
| await promises.mkdir(dirname(manifestPath), { recursive: true }); | ||
| await promises.writeFile(manifestPath, JSON.stringify(manifest, null, 2), "utf-8"); | ||
| return manifest; | ||
| } | ||
| async function loadNuxtManifest(buildDir) { | ||
| const manifestPath = resolve(buildDir, "nuxt.json"); | ||
| return await promises.readFile(manifestPath, "utf-8").then((data) => JSON.parse(data)).catch(() => null); | ||
| } | ||
| //#endregion | ||
| export { writeNuxtManifest as a, resolveNuxtManifest as i, loadNuxtManifest as n, nuxtVersionToGitIdentifier as r, cleanupNuxtDirs as t }; |
| import { execSync } from "node:child_process"; | ||
| //#region ../nuxi/src/utils/packageManagers.ts | ||
| function getPackageManagerVersion(name) { | ||
| return execSync(`${name} --version`).toString("utf8").trim(); | ||
| } | ||
| //#endregion | ||
| export { getPackageManagerVersion as t }; |
| import { t as __exportAll } from "./rolldown-runtime-wcPFST8Q.mjs"; | ||
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, r as envNameArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { r as relativeToProcess, t as loadKit } from "./kit-BzPscsEd.mjs"; | ||
| import { t as clearBuildDir } from "./fs-B0HqP3GX.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { resolve } from "pathe"; | ||
| //#region ../nuxi/src/commands/prepare.ts | ||
| var prepare_exports = /* @__PURE__ */ __exportAll({ default: () => prepare_default }); | ||
| var prepare_default = defineCommand({ | ||
| meta: { | ||
| name: "prepare", | ||
| description: "Prepare Nuxt for development/build" | ||
| }, | ||
| args: { | ||
| ...dotEnvArgs, | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...envNameArgs, | ||
| ...extendsArgs, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| process.env.NODE_ENV = process.env.NODE_ENV || "production"; | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const { loadNuxt, buildNuxt, writeTypes } = await loadKit(cwd); | ||
| const nuxt = await loadNuxt({ | ||
| cwd, | ||
| dotenv: { | ||
| cwd, | ||
| fileName: ctx.args.dotenv | ||
| }, | ||
| envName: ctx.args.envName, | ||
| overrides: { | ||
| _prepare: true, | ||
| logLevel: ctx.args.logLevel, | ||
| ...ctx.args.extends && { extends: ctx.args.extends }, | ||
| ...ctx.data?.overrides | ||
| } | ||
| }); | ||
| await clearBuildDir(nuxt.options.buildDir); | ||
| await buildNuxt(nuxt); | ||
| await writeTypes(nuxt); | ||
| logger.success(`Types generated in ${colors.cyan(relativeToProcess(nuxt.options.buildDir))}.`); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { prepare_exports as n, prepare_default as t }; |
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, r as envNameArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { r as relativeToProcess, t as loadKit } from "./kit-BzPscsEd.mjs"; | ||
| import { dirname } from "node:path"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { box, outro } from "@clack/prompts"; | ||
| import { existsSync, promises } from "node:fs"; | ||
| import { resolve as resolve$1 } from "pathe"; | ||
| import { x } from "tinyexec"; | ||
| import { setupDotenv } from "c12"; | ||
| //#region ../nuxi/src/commands/preview.ts | ||
| const command = defineCommand({ | ||
| meta: { | ||
| name: "preview", | ||
| description: "Launches Nitro server for local testing after `nuxi build`." | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...envNameArgs, | ||
| ...extendsArgs, | ||
| ...legacyRootDirArgs, | ||
| port: { | ||
| type: "string", | ||
| description: "Port to listen on", | ||
| alias: ["p"] | ||
| }, | ||
| ...dotEnvArgs | ||
| }, | ||
| async run(ctx) { | ||
| process.env.NODE_ENV = process.env.NODE_ENV || "production"; | ||
| const cwd = resolve$1(ctx.args.cwd || ctx.args.rootDir); | ||
| const { loadNuxt } = await loadKit(cwd); | ||
| const nitroJSONPaths = [await new Promise((res) => { | ||
| loadNuxt({ | ||
| cwd, | ||
| dotenv: { | ||
| cwd, | ||
| fileName: ctx.args.dotenv | ||
| }, | ||
| envName: ctx.args.envName, | ||
| ready: true, | ||
| overrides: { | ||
| ...ctx.args.extends && { extends: ctx.args.extends }, | ||
| modules: [function(_, nuxt) { | ||
| nuxt.hook("nitro:init", (nitro) => { | ||
| res(resolve$1(nuxt.options.srcDir || cwd, nitro.options.output.dir || ".output", "nitro.json")); | ||
| }); | ||
| }] | ||
| } | ||
| }).then((nuxt) => nuxt.close()).catch(() => ""); | ||
| }), resolve$1(cwd, ".output", "nitro.json")].filter(Boolean); | ||
| const nitroJSONPath = nitroJSONPaths.find((p) => existsSync(p)); | ||
| if (!nitroJSONPath) { | ||
| logger.error(`Cannot find ${colors.cyan("nitro.json")}. Did you run ${colors.cyan("nuxi build")} first? Search path:\n${nitroJSONPaths.join("\n")}`); | ||
| process.exit(1); | ||
| } | ||
| const outputPath = dirname(nitroJSONPath); | ||
| const nitroJSON = JSON.parse(await promises.readFile(nitroJSONPath, "utf-8")); | ||
| if (!nitroJSON.commands.preview) { | ||
| logger.error("Preview is not supported for this build."); | ||
| process.exit(1); | ||
| } | ||
| const info = [ | ||
| ["Node.js:", `v${process.versions.node}`], | ||
| ["Nitro preset:", nitroJSON.preset], | ||
| ["Working directory:", relativeToProcess(outputPath)] | ||
| ]; | ||
| const _infoKeyLen = Math.max(...info.map(([label]) => label.length)); | ||
| logger.message(""); | ||
| box([ | ||
| "", | ||
| "You are previewing a Nuxt app. In production, do not use this CLI. ", | ||
| `Instead, run ${colors.cyan(nitroJSON.commands.preview)} directly.`, | ||
| "", | ||
| ...info.map(([label, value]) => `${label.padEnd(_infoKeyLen, " ")} ${colors.cyan(value)}`), | ||
| "" | ||
| ].join("\n"), colors.yellow(" Previewing Nuxt app "), { | ||
| contentAlign: "left", | ||
| titleAlign: "left", | ||
| width: "auto", | ||
| titlePadding: 2, | ||
| contentPadding: 2, | ||
| rounded: true, | ||
| withGuide: true, | ||
| formatBorder: (text) => colors.yellow(text) | ||
| }); | ||
| const envFileName = ctx.args.dotenv || ".env"; | ||
| if (existsSync(resolve$1(cwd, envFileName))) { | ||
| logger.info(`Loading ${colors.cyan(envFileName)}. This will not be loaded when running the server in production.`); | ||
| await setupDotenv({ | ||
| cwd, | ||
| fileName: envFileName | ||
| }); | ||
| } else if (ctx.args.dotenv) logger.error(`Cannot find ${colors.cyan(envFileName)}.`); | ||
| const port = ctx.args.port ?? process.env.NUXT_PORT ?? process.env.NITRO_PORT ?? process.env.PORT; | ||
| outro(`Running ${colors.cyan(nitroJSON.commands.preview)} in ${colors.cyan(relativeToProcess(outputPath))}`); | ||
| const [command, ...commandArgs] = nitroJSON.commands.preview.split(" "); | ||
| await x(command, commandArgs, { | ||
| throwOnError: true, | ||
| nodeOptions: { | ||
| stdio: "inherit", | ||
| cwd: outputPath, | ||
| env: { | ||
| ...process.env, | ||
| NUXT_PORT: port, | ||
| NITRO_PORT: port | ||
| } | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { command as default }; |
| //#region \0rolldown/runtime.js | ||
| var __defProp = Object.defineProperty; | ||
| var __exportAll = (all, no_symbols) => { | ||
| let target = {}; | ||
| for (var name in all) __defProp(target, name, { | ||
| get: all[name], | ||
| enumerable: true | ||
| }); | ||
| if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" }); | ||
| return target; | ||
| }; | ||
| //#endregion | ||
| export { __exportAll as t }; |
| import { t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { t as getNuxtVersion } from "./versions--iBjrFVR.mjs"; | ||
| import { t as formatInfoBox } from "./formatting-BobJCzk9.mjs"; | ||
| import { n as fetchModules, t as checkNuxtCompatibility } from "./_utils-D57pBv3m.mjs"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { box } from "@clack/prompts"; | ||
| import { kebabCase, upperFirst } from "scule"; | ||
| import Fuse from "fuse.js"; | ||
| //#region ../nuxi/src/commands/module/search.ts | ||
| const DASH_RE = /-/g; | ||
| const { format: formatNumber } = Intl.NumberFormat("en-GB", { | ||
| notation: "compact", | ||
| maximumFractionDigits: 1 | ||
| }); | ||
| var search_default = defineCommand({ | ||
| meta: { | ||
| name: "search", | ||
| description: "Search in Nuxt modules" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| query: { | ||
| type: "positional", | ||
| description: "keywords to search for", | ||
| required: true | ||
| }, | ||
| nuxtVersion: { | ||
| type: "string", | ||
| description: "Filter by Nuxt version and list compatible modules only (auto detected by default)", | ||
| required: false, | ||
| valueHint: "2|3" | ||
| } | ||
| }, | ||
| async setup(ctx) { | ||
| const nuxtVersion = await getNuxtVersion(ctx.args.cwd); | ||
| return findModuleByKeywords(ctx.args._.join(" "), nuxtVersion); | ||
| } | ||
| }); | ||
| async function findModuleByKeywords(query, nuxtVersion) { | ||
| const results = new Fuse((await fetchModules()).filter((m) => checkNuxtCompatibility(m, nuxtVersion)), { | ||
| threshold: .1, | ||
| keys: [ | ||
| { | ||
| name: "name", | ||
| weight: 1 | ||
| }, | ||
| { | ||
| name: "npm", | ||
| weight: 1 | ||
| }, | ||
| { | ||
| name: "repo", | ||
| weight: 1 | ||
| }, | ||
| { | ||
| name: "tags", | ||
| weight: 1 | ||
| }, | ||
| { | ||
| name: "category", | ||
| weight: 1 | ||
| }, | ||
| { | ||
| name: "description", | ||
| weight: .5 | ||
| }, | ||
| { | ||
| name: "maintainers.name", | ||
| weight: .5 | ||
| }, | ||
| { | ||
| name: "maintainers.github", | ||
| weight: .5 | ||
| } | ||
| ] | ||
| }).search(query).map((result) => { | ||
| const res = { | ||
| name: result.item.name, | ||
| package: result.item.npm, | ||
| homepage: colors.cyan(result.item.website), | ||
| compatibility: `nuxt: ${result.item.compatibility?.nuxt || "*"}`, | ||
| repository: result.item.github, | ||
| description: result.item.description, | ||
| install: `npx nuxt add ${result.item.name}`, | ||
| stars: colors.yellow(formatNumber(result.item.stats.stars)), | ||
| monthlyDownloads: colors.yellow(formatNumber(result.item.stats.downloads)) | ||
| }; | ||
| if (result.item.github === result.item.website) delete res.homepage; | ||
| if (result.item.name === result.item.npm) delete res.packageName; | ||
| return res; | ||
| }); | ||
| if (!results.length) { | ||
| logger.info(`No Nuxt modules found matching query ${colors.magenta(query)} for Nuxt ${colors.cyan(nuxtVersion)}`); | ||
| return; | ||
| } | ||
| logger.success(`Found ${results.length} Nuxt ${results.length > 1 ? "modules" : "module"} matching ${colors.cyan(query)} ${nuxtVersion ? `for Nuxt ${colors.cyan(nuxtVersion)}` : ""}:\n`); | ||
| for (const foundModule of results) { | ||
| const formattedModule = {}; | ||
| for (const [key, val] of Object.entries(foundModule)) { | ||
| const label = upperFirst(kebabCase(key)).replace(DASH_RE, " "); | ||
| formattedModule[label] = val; | ||
| } | ||
| const title = formattedModule.Name || formattedModule.Package; | ||
| delete formattedModule.Name; | ||
| box(`\n${formatInfoBox(formattedModule)}`, ` ${title} `, { | ||
| contentAlign: "left", | ||
| titleAlign: "left", | ||
| width: "auto", | ||
| titlePadding: 2, | ||
| contentPadding: 2, | ||
| rounded: true | ||
| }); | ||
| } | ||
| } | ||
| //#endregion | ||
| export { search_default as default }; |
| //#region ../nuxi/src/data/templates.ts | ||
| const templates = { | ||
| "content": { | ||
| "name": "content", | ||
| "description": "Content-driven website", | ||
| "defaultDir": "nuxt-app", | ||
| "url": "https://content.nuxt.com", | ||
| "tar": "https://codeload.github.com/nuxt/starter/tar.gz/refs/heads/content" | ||
| }, | ||
| "minimal": { | ||
| "name": "minimal", | ||
| "description": "Minimal setup for Nuxt 4", | ||
| "defaultDir": "nuxt-app", | ||
| "url": "https://nuxt.com", | ||
| "tar": "https://codeload.github.com/nuxt/starter/tar.gz/refs/heads/v4" | ||
| }, | ||
| "module": { | ||
| "name": "module", | ||
| "description": "Nuxt module", | ||
| "defaultDir": "nuxt-module", | ||
| "url": "https://nuxt.com", | ||
| "tar": "https://codeload.github.com/nuxt/starter/tar.gz/refs/heads/module" | ||
| }, | ||
| "ui": { | ||
| "name": "ui", | ||
| "description": "App using Nuxt UI", | ||
| "defaultDir": "nuxt-app", | ||
| "url": "https://ui.nuxt.com", | ||
| "tar": "https://codeload.github.com/nuxt-ui-templates/starter/tar.gz/refs/heads/main" | ||
| } | ||
| }; | ||
| //#endregion | ||
| export { templates }; |
| import { a as legacyRootDirArgs, o as logLevelArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { resolve } from "pathe"; | ||
| //#region ../nuxi/src/commands/test.ts | ||
| var test_default = defineCommand({ | ||
| meta: { | ||
| name: "test", | ||
| description: "Run tests" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...legacyRootDirArgs, | ||
| dev: { | ||
| type: "boolean", | ||
| description: "Run in dev mode" | ||
| }, | ||
| watch: { | ||
| type: "boolean", | ||
| description: "Watch mode" | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| process.env.NODE_ENV = process.env.NODE_ENV || "test"; | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const { runTests } = await importTestUtils(); | ||
| await runTests({ | ||
| rootDir: cwd, | ||
| dev: ctx.args.dev, | ||
| watch: ctx.args.watch | ||
| }); | ||
| } | ||
| }); | ||
| async function importTestUtils() { | ||
| let err; | ||
| for (const pkg of [ | ||
| "@nuxt/test-utils-nightly", | ||
| "@nuxt/test-utils-edge", | ||
| "@nuxt/test-utils" | ||
| ]) try { | ||
| const exports = await import(pkg); | ||
| if (!exports.runTests) throw new Error("Invalid version of `@nuxt/test-utils` is installed!"); | ||
| return exports; | ||
| } catch (_err) { | ||
| err = _err; | ||
| } | ||
| logger.error(String(err)); | ||
| throw new Error("`@nuxt/test-utils` seems missing. Run `npm i -D @nuxt/test-utils` or `yarn add -D @nuxt/test-utils` to install."); | ||
| } | ||
| //#endregion | ||
| export { test_default as default }; |
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { t as loadKit } from "./kit-BzPscsEd.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { isBun } from "std-env"; | ||
| import { resolve } from "pathe"; | ||
| import { resolveModulePath } from "exsolve"; | ||
| import { readTSConfig } from "pkg-types"; | ||
| import { x } from "tinyexec"; | ||
| //#region ../nuxi/src/commands/typecheck.ts | ||
| var typecheck_default = defineCommand({ | ||
| meta: { | ||
| name: "typecheck", | ||
| description: "Runs `vue-tsc` to check types throughout your app." | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...dotEnvArgs, | ||
| ...extendsArgs, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| process.env.NODE_ENV = process.env.NODE_ENV || "production"; | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const [supportsProjects, resolvedTypeScript, resolvedVueTsc] = await Promise.all([ | ||
| readTSConfig(cwd).then((r) => !!r.references?.length), | ||
| resolveModulePath("typescript", { try: true }), | ||
| resolveModulePath("vue-tsc/bin/vue-tsc.js", { try: true }), | ||
| writeTypes(cwd, ctx.args.dotenv, ctx.args.logLevel, { | ||
| ...ctx.data?.overrides, | ||
| ...ctx.args.extends && { extends: ctx.args.extends } | ||
| }) | ||
| ]); | ||
| const typeCheckArgs = supportsProjects ? ["-b", "--noEmit"] : ["--noEmit"]; | ||
| if (resolvedTypeScript && resolvedVueTsc) return await x(resolvedVueTsc, typeCheckArgs, { | ||
| throwOnError: true, | ||
| nodeOptions: { | ||
| stdio: "inherit", | ||
| cwd | ||
| } | ||
| }); | ||
| if (isBun) { | ||
| await x("bun", [ | ||
| "install", | ||
| "typescript", | ||
| "vue-tsc", | ||
| "--global", | ||
| "--silent" | ||
| ], { | ||
| throwOnError: true, | ||
| nodeOptions: { | ||
| stdio: "inherit", | ||
| cwd | ||
| } | ||
| }); | ||
| return await x("bunx", ["vue-tsc", ...typeCheckArgs], { | ||
| throwOnError: true, | ||
| nodeOptions: { | ||
| stdio: "inherit", | ||
| cwd | ||
| } | ||
| }); | ||
| } | ||
| await x("npx", [ | ||
| "-p", | ||
| "vue-tsc", | ||
| "-p", | ||
| "typescript", | ||
| "vue-tsc", | ||
| ...typeCheckArgs | ||
| ], { | ||
| throwOnError: true, | ||
| nodeOptions: { | ||
| stdio: "inherit", | ||
| cwd | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
| async function writeTypes(cwd, dotenv, logLevel, overrides) { | ||
| const { loadNuxt, buildNuxt, writeTypes } = await loadKit(cwd); | ||
| const nuxt = await loadNuxt({ | ||
| cwd, | ||
| dotenv: { | ||
| cwd, | ||
| fileName: dotenv | ||
| }, | ||
| overrides: { | ||
| _prepare: true, | ||
| logLevel, | ||
| ...overrides | ||
| } | ||
| }); | ||
| await writeTypes(nuxt); | ||
| await buildNuxt(nuxt); | ||
| await nuxt.close(); | ||
| } | ||
| //#endregion | ||
| export { typecheck_default as default }; |
| import { a as legacyRootDirArgs, o as logLevelArgs, t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { r as relativeToProcess, t as loadKit } from "./kit-BzPscsEd.mjs"; | ||
| import { t as getNuxtVersion } from "./versions--iBjrFVR.mjs"; | ||
| import { r as nuxtVersionToGitIdentifier, t as cleanupNuxtDirs } from "./nuxt-CBsjK3fQ.mjs"; | ||
| import { t as getPackageManagerVersion } from "./packageManagers-Y5z0Pi7r.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { cancel, intro, isCancel, note, outro, select, spinner, tasks } from "@clack/prompts"; | ||
| import { existsSync } from "node:fs"; | ||
| import { resolve } from "pathe"; | ||
| import { findWorkspaceDir, readPackageJSON } from "pkg-types"; | ||
| import { addDependency, dedupeDependencies, detectPackageManager } from "nypm"; | ||
| //#region ../nuxi/src/commands/upgrade.ts | ||
| function checkNuxtDependencyType(pkg) { | ||
| if (pkg.dependencies?.nuxt) return "dependencies"; | ||
| if (pkg.devDependencies?.nuxt) return "devDependencies"; | ||
| return "dependencies"; | ||
| } | ||
| const nuxtVersionTags = { | ||
| "3.x": "3x", | ||
| "4.x": "latest" | ||
| }; | ||
| function getNightlyDependency(dep, nuxtVersion) { | ||
| return `${dep}@npm:${dep}-nightly@${nuxtVersionTags[nuxtVersion]}`; | ||
| } | ||
| async function getNightlyVersion(packageNames) { | ||
| const nuxtVersion = await select({ | ||
| message: "Which nightly Nuxt release channel do you want to install?", | ||
| options: [{ | ||
| value: "3.x", | ||
| label: "3.x" | ||
| }, { | ||
| value: "4.x", | ||
| label: "4.x" | ||
| }], | ||
| initialValue: "4.x" | ||
| }); | ||
| if (isCancel(nuxtVersion)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| return { | ||
| npmPackages: packageNames.map((p) => getNightlyDependency(p, nuxtVersion)), | ||
| nuxtVersion | ||
| }; | ||
| } | ||
| async function getRequiredNewVersion(packageNames, channel) { | ||
| switch (channel) { | ||
| case "nightly": return getNightlyVersion(packageNames); | ||
| case "v3": return { | ||
| npmPackages: packageNames.map((p) => `${p}@3`), | ||
| nuxtVersion: "3.x" | ||
| }; | ||
| case "v3-nightly": return { | ||
| npmPackages: packageNames.map((p) => getNightlyDependency(p, "3.x")), | ||
| nuxtVersion: "3.x" | ||
| }; | ||
| case "v4": return { | ||
| npmPackages: packageNames.map((p) => `${p}@4`), | ||
| nuxtVersion: "4.x" | ||
| }; | ||
| case "v4-nightly": return { | ||
| npmPackages: packageNames.map((p) => getNightlyDependency(p, "4.x")), | ||
| nuxtVersion: "4.x" | ||
| }; | ||
| default: return { | ||
| npmPackages: packageNames.map((p) => `${p}@latest`), | ||
| nuxtVersion: "4.x" | ||
| }; | ||
| } | ||
| } | ||
| var upgrade_default = defineCommand({ | ||
| meta: { | ||
| name: "upgrade", | ||
| description: "Upgrade Nuxt" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...legacyRootDirArgs, | ||
| dedupe: { | ||
| type: "boolean", | ||
| description: "Dedupe dependencies after upgrading" | ||
| }, | ||
| force: { | ||
| type: "boolean", | ||
| alias: "f", | ||
| description: "Force upgrade to recreate lockfile and node_modules" | ||
| }, | ||
| channel: { | ||
| type: "string", | ||
| alias: "ch", | ||
| default: "stable", | ||
| description: "Specify a channel to install from (default: stable)", | ||
| valueHint: "stable|nightly|v3|v4|v4-nightly|v3-nightly" | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| intro(colors.cyan("Upgrading Nuxt ...")); | ||
| const [packageManager, workspaceDir = cwd] = await Promise.all([detectPackageManager(cwd), findWorkspaceDir(cwd, { try: true })]); | ||
| if (!packageManager) { | ||
| logger.error(`Unable to determine the package manager used by this project.\n\nNo lock files found in ${colors.cyan(relativeToProcess(cwd))}, and no ${colors.cyan("packageManager")} field specified in ${colors.cyan("package.json")}.`); | ||
| logger.info(`Please either add the ${colors.cyan("packageManager")} field to ${colors.cyan("package.json")} or execute the installation command for your package manager. For example, you can use ${colors.cyan("pnpm i")}, ${colors.cyan("npm i")}, ${colors.cyan("bun i")}, or ${colors.cyan("yarn i")}, and then try again.`); | ||
| process.exit(1); | ||
| } | ||
| const { name: packageManagerName, lockFile: lockFileCandidates } = packageManager; | ||
| const packageManagerVersion = getPackageManagerVersion(packageManagerName); | ||
| logger.step(`Package manager: ${colors.cyan(packageManagerName)} ${packageManagerVersion}`); | ||
| const currentVersion = await getNuxtVersion(cwd, false) || "[unknown]"; | ||
| logger.step(`Current Nuxt version: ${colors.cyan(currentVersion)}`); | ||
| const pkg = await readPackageJSON(cwd).catch(() => null); | ||
| const nuxtDependencyType = pkg ? checkNuxtDependencyType(pkg) : "dependencies"; | ||
| const { npmPackages, nuxtVersion } = await getRequiredNewVersion(["nuxt", ...pkg ? [ | ||
| "@nuxt/kit", | ||
| "@nuxt/schema", | ||
| "@nuxt/vite-builder", | ||
| "@nuxt/webpack-builder", | ||
| "@nuxt/rspack-builder" | ||
| ].filter((p) => pkg.dependencies?.[p] || pkg.devDependencies?.[p]) : []], ctx.args.channel); | ||
| const toRemove = ["node_modules"]; | ||
| const lockFile = normaliseLockFile(workspaceDir, lockFileCandidates); | ||
| if (lockFile) toRemove.push(lockFile); | ||
| const forceRemovals = toRemove.map((p) => colors.cyan(p)).join(" and "); | ||
| let method = ctx.args.force ? "force" : ctx.args.dedupe ? "dedupe" : void 0; | ||
| if (!method) { | ||
| const result = await select({ | ||
| message: `Would you like to dedupe your lockfile, or recreate ${forceRemovals}? This can fix problems with hoisted dependency versions and ensure you have the most up-to-date dependencies.`, | ||
| options: [ | ||
| { | ||
| label: "dedupe lockfile", | ||
| value: "dedupe", | ||
| hint: "recommended" | ||
| }, | ||
| { | ||
| label: `recreate ${forceRemovals}`, | ||
| value: "force" | ||
| }, | ||
| { | ||
| label: "skip", | ||
| value: "skip" | ||
| } | ||
| ], | ||
| initialValue: "dedupe" | ||
| }); | ||
| if (isCancel(result)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| method = result; | ||
| } | ||
| const versionType = ctx.args.channel === "nightly" ? "nightly" : `latest ${ctx.args.channel}`; | ||
| const spin = spinner(); | ||
| spin.start("Upgrading Nuxt"); | ||
| await tasks([ | ||
| { | ||
| title: `Installing ${versionType} Nuxt ${nuxtVersion} release`, | ||
| task: async () => { | ||
| await addDependency(npmPackages, { | ||
| cwd, | ||
| packageManager, | ||
| dev: nuxtDependencyType === "devDependencies", | ||
| workspace: packageManager?.name === "pnpm" && existsSync(resolve(cwd, "pnpm-workspace.yaml")) | ||
| }); | ||
| return "Nuxt packages installed"; | ||
| } | ||
| }, | ||
| ...method === "force" ? [{ | ||
| title: `Recreating ${forceRemovals}`, | ||
| task: async () => { | ||
| await dedupeDependencies({ recreateLockfile: true }); | ||
| return "Lockfile recreated"; | ||
| } | ||
| }] : [], | ||
| ...method === "dedupe" ? [{ | ||
| title: "Deduping dependencies", | ||
| task: async () => { | ||
| await dedupeDependencies(); | ||
| return "Dependencies deduped"; | ||
| } | ||
| }] : [], | ||
| { | ||
| title: "Cleaning up build directories", | ||
| task: async () => { | ||
| let buildDir = ".nuxt"; | ||
| try { | ||
| const { loadNuxtConfig } = await loadKit(cwd); | ||
| buildDir = (await loadNuxtConfig({ cwd })).buildDir; | ||
| } catch {} | ||
| await cleanupNuxtDirs(cwd, buildDir); | ||
| return "Build directories cleaned"; | ||
| } | ||
| } | ||
| ]); | ||
| spin.stop(); | ||
| if (method === "force") logger.info(`If you encounter any issues, revert the changes and try with ${colors.cyan("--no-force")}`); | ||
| const upgradedVersion = await getNuxtVersion(cwd, false) || "[unknown]"; | ||
| if (upgradedVersion === "[unknown]") return; | ||
| if (upgradedVersion === currentVersion) outro(`You were already using the latest version of Nuxt (${colors.green(currentVersion)})`); | ||
| else { | ||
| logger.success(`Successfully upgraded Nuxt from ${colors.cyan(currentVersion)} to ${colors.green(upgradedVersion)}`); | ||
| if (currentVersion === "[unknown]") return; | ||
| const commitA = nuxtVersionToGitIdentifier(currentVersion); | ||
| const commitB = nuxtVersionToGitIdentifier(upgradedVersion); | ||
| if (commitA && commitB) note(`https://github.com/nuxt/nuxt/compare/${commitA}...${commitB}`, "Changelog"); | ||
| outro("✨ Upgrade complete!"); | ||
| } | ||
| } | ||
| }); | ||
| function normaliseLockFile(cwd, lockFiles) { | ||
| if (typeof lockFiles === "string") lockFiles = [lockFiles]; | ||
| const lockFile = lockFiles?.find((file) => existsSync(resolve(cwd, file))); | ||
| if (lockFile === void 0) { | ||
| logger.error(`Unable to find any lock files in ${colors.cyan(relativeToProcess(cwd))}.`); | ||
| return; | ||
| } | ||
| return lockFile; | ||
| } | ||
| //#endregion | ||
| export { upgrade_default as default }; |
| import { n as tryResolveNuxt } from "./kit-BzPscsEd.mjs"; | ||
| import { readFileSync } from "node:fs"; | ||
| import { resolveModulePath } from "exsolve"; | ||
| import { readPackageJSON } from "pkg-types"; | ||
| import { coerce } from "semver"; | ||
| //#region ../nuxi/src/utils/versions.ts | ||
| async function getNuxtVersion(cwd, cache = true) { | ||
| const nuxtPkg = await readPackageJSON("nuxt", { | ||
| url: cwd, | ||
| try: true, | ||
| cache | ||
| }); | ||
| if (nuxtPkg) return nuxtPkg.version; | ||
| const pkg = await readPackageJSON(cwd); | ||
| const pkgDep = pkg?.dependencies?.nuxt || pkg?.devDependencies?.nuxt; | ||
| return pkgDep && coerce(pkgDep)?.version || "3.0.0"; | ||
| } | ||
| function getPkgVersion(cwd, pkg, options) { | ||
| return getPkgJSON(cwd, pkg, options)?.version ?? ""; | ||
| } | ||
| /** | ||
| * Resolve a package.json, optionally walking a dependency chain. | ||
| * | ||
| * `via` is an array of `[startingPoint, ...intermediates]` describing | ||
| * the dependency path to walk before resolving `pkg`. For example: | ||
| * | ||
| * // vite is a dep of @nuxt/vite-builder, which is a dep of nuxt | ||
| * getPkgJSON(cwd, 'vite', { via: ['nuxt', '@nuxt/vite-builder'] }) | ||
| * | ||
| * // webpack is a dep of @nuxt/webpack-builder, which the user installs | ||
| * getPkgJSON(cwd, 'webpack', { via: ['@nuxt/webpack-builder'] }) | ||
| * | ||
| * Each entry is resolved from the location of the previous one, | ||
| * starting from cwd. Falls back to direct resolution from cwd/nuxt. | ||
| */ | ||
| function getPkgJSON(cwd, pkg, options) { | ||
| const roots = []; | ||
| if (options?.via && options.via.length > 0) { | ||
| let from = cwd; | ||
| for (const step of options.via) { | ||
| from = resolveModulePath(step, { | ||
| from, | ||
| try: true | ||
| }) ?? void 0; | ||
| if (!from) break; | ||
| } | ||
| if (from) roots.push(from); | ||
| } | ||
| roots.push(cwd); | ||
| const nuxtPath = tryResolveNuxt(cwd); | ||
| if (nuxtPath) roots.push(nuxtPath); | ||
| for (const root of roots) { | ||
| const p = resolveModulePath(`${pkg}/package.json`, { | ||
| from: root, | ||
| try: true | ||
| }); | ||
| if (p) return JSON.parse(readFileSync(p, "utf-8")); | ||
| } | ||
| return null; | ||
| } | ||
| //#endregion | ||
| export { getPkgJSON as n, getPkgVersion as r, getNuxtVersion as t }; |
@@ -45,3 +45,3 @@ import EventEmitter from "node:events"; | ||
| handler: RequestListener; | ||
| listener: Listener; | ||
| listener!: Listener; | ||
| constructor(options: NuxtDevServerOptions); | ||
@@ -52,2 +52,4 @@ init(): Promise<void>; | ||
| close(): Promise<void>; | ||
| /** Release the lock file. Call only on final shutdown, not during reloads. */ | ||
| releaseLock(): void; | ||
| } | ||
@@ -54,0 +56,0 @@ //#endregion |
+2
-12
@@ -1,12 +0,2 @@ | ||
| import "../logger-B4ge7MhP.mjs"; | ||
| import "../env-BRiVSJMz.mjs"; | ||
| import "../ascii-AoH-yOf6.mjs"; | ||
| import "../profile-q-JV7Qxl.mjs"; | ||
| import { t as initialize } from "../dev-D5McAnmo.mjs"; | ||
| import "../kit-DUlGqV3Z.mjs"; | ||
| import "../versions-Bg99eDSc.mjs"; | ||
| import "../banner-C2vxTb-6.mjs"; | ||
| import "../fs-B8DrLsZ2.mjs"; | ||
| import "../nuxt-CsZm8Jhw.mjs"; | ||
| export { initialize }; | ||
| import { n as initialize } from "../dev-Cr4PgS_f.mjs"; | ||
| export { initialize }; |
+28
-154
@@ -1,5 +0,4 @@ | ||
| import { t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import { t as templateNames } from "./templates-wxuD_F_w.mjs"; | ||
| import { t as templates } from "./templates-BQDUIkuM.mjs"; | ||
| import { t as cwdArgs } from "./_shared-B6XhZQ-m.mjs"; | ||
| import { n as logger } from "./logger-C1qVsppt.mjs"; | ||
| import { t as templateNames } from "./names-C5-M0i7H.mjs"; | ||
| import { resolve } from "node:path"; | ||
@@ -12,27 +11,24 @@ import process from "node:process"; | ||
| import { fileURLToPath } from "node:url"; | ||
| import tab from "@bomb.sh/tab/citty"; | ||
| //#region ../nuxi/src/commands/index.ts | ||
| const _rDefault = (r) => r.default || r; | ||
| const commands = { | ||
| "add": () => import("./add-D-RRzz1Y.mjs").then((n) => n.n).then(_rDefault), | ||
| "add-template": () => import("./add-template-B0_8lFIJ.mjs").then(_rDefault), | ||
| "analyze": () => import("./analyze-C512gBX4.mjs").then(_rDefault), | ||
| "build": () => import("./build-CIg9T7rh.mjs").then(_rDefault), | ||
| "cleanup": () => import("./cleanup-B1pvEjaJ.mjs").then(_rDefault), | ||
| "_dev": () => import("./dev-child-BTslI2Ui.mjs").then(_rDefault), | ||
| "dev": () => import("./dev-CY-a7lb7.mjs").then(_rDefault), | ||
| "devtools": () => import("./devtools-BFJLyinx.mjs").then(_rDefault), | ||
| "generate": () => import("./generate-Bs-I-Nn8.mjs").then(_rDefault), | ||
| "info": () => import("./info-C2RRE7Hj.mjs").then(_rDefault), | ||
| "init": () => import("./init-3K6qv8Y1.mjs").then(_rDefault), | ||
| "module": () => import("./module-BOwFh5iR.mjs").then(_rDefault), | ||
| "prepare": () => import("./prepare-etx17Cow.mjs").then((n) => n.n).then(_rDefault), | ||
| "preview": () => import("./preview-Dpml-raz.mjs").then(_rDefault), | ||
| "start": () => import("./preview-Dpml-raz.mjs").then(_rDefault), | ||
| "test": () => import("./test-3ArLMqkP.mjs").then(_rDefault), | ||
| "typecheck": () => import("./typecheck-DzNAMeid.mjs").then(_rDefault), | ||
| "upgrade": () => import("./upgrade-CUwAlsGk.mjs").then(_rDefault) | ||
| "add": () => import("./add-DY-72t8C.mjs").then(_rDefault), | ||
| "add-template": () => import("./add-template-cTcq62Qd.mjs").then(_rDefault), | ||
| "analyze": () => import("./analyze-DDeJFzIp.mjs").then(_rDefault), | ||
| "build": () => import("./build-BPupc27P.mjs").then(_rDefault), | ||
| "cleanup": () => import("./cleanup-2TBoIdxA.mjs").then(_rDefault), | ||
| "_dev": () => import("./dev-child-BXXy_yXk.mjs").then(_rDefault), | ||
| "dev": () => import("./dev--5SloLZS.mjs").then(_rDefault), | ||
| "devtools": () => import("./devtools-DisdwL4R.mjs").then(_rDefault), | ||
| "generate": () => import("./generate-DxFBnyuA.mjs").then(_rDefault), | ||
| "info": () => import("./info-BZyQLUOt.mjs").then(_rDefault), | ||
| "init": () => import("./init-GY9-KoBe.mjs").then(_rDefault), | ||
| "module": () => import("./module-DSnyWgzL.mjs").then(_rDefault), | ||
| "prepare": () => import("./prepare-DZj9Ie1E.mjs").then((n) => n.n).then(_rDefault), | ||
| "preview": () => import("./preview-CChFHZ1m.mjs").then(_rDefault), | ||
| "start": () => import("./preview-CChFHZ1m.mjs").then(_rDefault), | ||
| "test": () => import("./test-CgyrXjYL.mjs").then(_rDefault), | ||
| "typecheck": () => import("./typecheck-DQJUWomH.mjs").then(_rDefault), | ||
| "upgrade": () => import("./upgrade-ikuDz1tn.mjs").then(_rDefault) | ||
| }; | ||
| //#endregion | ||
@@ -59,3 +55,2 @@ //#region ../nuxi/src/utils/console.ts | ||
| } | ||
| //#endregion | ||
@@ -69,127 +64,8 @@ //#region ../nuxi/src/utils/engines.ts | ||
| } | ||
| //#endregion | ||
| //#region package.json | ||
| var name = "@nuxt/cli"; | ||
| var version = "3.34.0"; | ||
| var version = "3.35.0"; | ||
| var description = "Nuxt CLI"; | ||
| //#endregion | ||
| //#region ../nuxi/src/data/nitro-presets.ts | ||
| const nitroPresets = [ | ||
| "alwaysdata", | ||
| "aws-amplify", | ||
| "aws-lambda", | ||
| "azure-functions", | ||
| "azure-swa", | ||
| "bun", | ||
| "cleavr", | ||
| "cli", | ||
| "cloudflare-dev", | ||
| "cloudflare-durable", | ||
| "cloudflare-module", | ||
| "cloudflare-module-legacy", | ||
| "cloudflare-pages", | ||
| "cloudflare-pages-static", | ||
| "cloudflare-worker", | ||
| "deno-deploy", | ||
| "deno-server", | ||
| "deno-server-legacy", | ||
| "digital-ocean", | ||
| "edgio", | ||
| "firebase", | ||
| "firebase-app-hosting", | ||
| "flight-control", | ||
| "genezio", | ||
| "github-pages", | ||
| "gitlab-pages", | ||
| "heroku", | ||
| "iis-handler", | ||
| "iis-node", | ||
| "koyeb", | ||
| "netlify", | ||
| "netlify-builder", | ||
| "netlify-edge", | ||
| "netlify-legacy", | ||
| "netlify-static", | ||
| "node-cluster", | ||
| "node-listener", | ||
| "node-server", | ||
| "platform-sh", | ||
| "render-com", | ||
| "service-worker", | ||
| "static", | ||
| "stormkit", | ||
| "vercel", | ||
| "vercel-edge", | ||
| "vercel-static", | ||
| "winterjs", | ||
| "zeabur", | ||
| "zeabur-static", | ||
| "zerops", | ||
| "zerops-static" | ||
| ]; | ||
| //#endregion | ||
| //#region ../nuxi/src/completions.ts | ||
| async function initCompletions(command) { | ||
| const completion = await tab(command); | ||
| const devCommand = completion.commands.get("dev"); | ||
| if (devCommand) { | ||
| const portOption = devCommand.options.get("port"); | ||
| if (portOption) portOption.handler = (complete) => { | ||
| complete("3000", "Default development port"); | ||
| complete("3001", "Alternative port"); | ||
| complete("8080", "Common alternative port"); | ||
| }; | ||
| const hostOption = devCommand.options.get("host"); | ||
| if (hostOption) hostOption.handler = (complete) => { | ||
| complete("localhost", "Local development"); | ||
| complete("0.0.0.0", "Listen on all interfaces"); | ||
| complete("127.0.0.1", "Loopback address"); | ||
| }; | ||
| } | ||
| const buildCommand = completion.commands.get("build"); | ||
| if (buildCommand) { | ||
| const presetOption = buildCommand.options.get("preset"); | ||
| if (presetOption) presetOption.handler = (complete) => { | ||
| for (const preset of nitroPresets) complete(preset, ""); | ||
| }; | ||
| } | ||
| const initCommand = completion.commands.get("init"); | ||
| if (initCommand) { | ||
| const templateOption = initCommand.options.get("template"); | ||
| if (templateOption) templateOption.handler = (complete) => { | ||
| for (const template in templates) complete(template, templates[template]?.description || ""); | ||
| }; | ||
| } | ||
| const addCommand = completion.commands.get("add"); | ||
| if (addCommand) { | ||
| const cwdOption = addCommand.options.get("cwd"); | ||
| if (cwdOption) cwdOption.handler = (complete) => { | ||
| complete(".", "Current directory"); | ||
| }; | ||
| } | ||
| for (const cmdName of [ | ||
| "dev", | ||
| "build", | ||
| "generate", | ||
| "preview", | ||
| "prepare", | ||
| "init" | ||
| ]) { | ||
| const cmd = completion.commands.get(cmdName); | ||
| if (cmd) { | ||
| const logLevelOption = cmd.options.get("logLevel"); | ||
| if (logLevelOption) logLevelOption.handler = (complete) => { | ||
| complete("silent", "No logs"); | ||
| complete("info", "Standard logging"); | ||
| complete("verbose", "Detailed logging"); | ||
| }; | ||
| } | ||
| } | ||
| return completion; | ||
| } | ||
| //#endregion | ||
| //#region src/run.ts | ||
@@ -202,3 +78,6 @@ globalThis.__nuxt_cli__ = globalThis.__nuxt_cli__ || { | ||
| async function runMain() { | ||
| await initCompletions(main); | ||
| if (process.argv[2] === "complete") { | ||
| const { initCompletions } = await import("./completions-Cv4Rwd1E.mjs"); | ||
| await initCompletions(main); | ||
| } | ||
| return runMain$1(main); | ||
@@ -214,6 +93,3 @@ } | ||
| } | ||
| //#endregion | ||
| //#region src/main.ts | ||
| const _main = defineCommand({ | ||
| const main = defineCommand({ | ||
| meta: { | ||
@@ -265,5 +141,3 @@ name: name.endsWith("nightly") ? name : "nuxi", | ||
| }); | ||
| const main = _main; | ||
| //#endregion | ||
| export { main, runCommand, runMain }; | ||
| export { main, runCommand, runMain }; |
+27
-27
| { | ||
| "name": "@nuxt/cli", | ||
| "type": "module", | ||
| "version": "3.34.0", | ||
| "version": "3.35.0", | ||
| "description": "Nuxt CLI", | ||
@@ -36,3 +36,3 @@ "license": "MIT", | ||
| "peerDependencies": { | ||
| "@nuxt/schema": "^4.3.1" | ||
| "@nuxt/schema": "^4.4.2" | ||
| }, | ||
@@ -46,16 +46,16 @@ "peerDependenciesMeta": { | ||
| "@bomb.sh/tab": "^0.0.14", | ||
| "@clack/prompts": "^1.1.0", | ||
| "c12": "^3.3.3", | ||
| "citty": "^0.2.1", | ||
| "@clack/prompts": "^1.2.0", | ||
| "c12": "^3.3.4", | ||
| "citty": "^0.2.2", | ||
| "confbox": "^0.2.4", | ||
| "consola": "^3.4.2", | ||
| "debug": "^4.4.3", | ||
| "defu": "^6.1.4", | ||
| "defu": "^6.1.7", | ||
| "exsolve": "^1.0.8", | ||
| "fuse.js": "^7.1.0", | ||
| "fuse.js": "^7.3.0", | ||
| "fzf": "^0.5.2", | ||
| "giget": "^3.1.2", | ||
| "giget": "^3.2.0", | ||
| "jiti": "^2.6.1", | ||
| "listhen": "^1.9.0", | ||
| "nypm": "^0.6.5", | ||
| "listhen": "^1.9.1", | ||
| "nypm": "^0.6.6", | ||
| "ofetch": "^1.5.1", | ||
@@ -68,28 +68,28 @@ "ohash": "^2.0.11", | ||
| "semver": "^7.7.4", | ||
| "srvx": "^0.11.9", | ||
| "std-env": "^3.10.0", | ||
| "srvx": "^0.11.15", | ||
| "std-env": "^4.1.0", | ||
| "tinyclip": "^0.1.12", | ||
| "tinyexec": "^1.0.2", | ||
| "tinyexec": "^1.1.1", | ||
| "ufo": "^1.6.3", | ||
| "youch": "^4.1.0" | ||
| "youch": "^4.1.1" | ||
| }, | ||
| "devDependencies": { | ||
| "@nuxt/kit": "^4.3.1", | ||
| "@nuxt/schema": "^4.3.1", | ||
| "@types/debug": "^4.1.12", | ||
| "@types/node": "^24.12.0", | ||
| "@nuxt/kit": "^4.4.2", | ||
| "@nuxt/schema": "^4.4.2", | ||
| "@types/debug": "^4.1.13", | ||
| "@types/node": "^24.12.2", | ||
| "get-port-please": "^3.2.0", | ||
| "h3": "^1.15.6", | ||
| "h3-next": "npm:h3@^2.0.1-rc.16", | ||
| "h3": "^1.15.11", | ||
| "h3-next": "npm:h3@^2.0.1-rc.20", | ||
| "nitro": "^3.0.1-alpha.2", | ||
| "nitropack": "^2.13.1", | ||
| "rollup": "^4.59.0", | ||
| "nitropack": "^2.13.3", | ||
| "rollup": "^4.60.2", | ||
| "rollup-plugin-visualizer": "^7.0.1", | ||
| "tsdown": "^0.20.3", | ||
| "typescript": "^5.9.3", | ||
| "undici": "^7.22.0", | ||
| "tsdown": "^0.21.10", | ||
| "typescript": "^6.0.3", | ||
| "undici": "^8.1.0", | ||
| "unplugin-purge-polyfills": "^0.1.0", | ||
| "vitest": "^4.0.18", | ||
| "youch": "^4.1.0" | ||
| "vitest": "^4.1.5", | ||
| "youch": "^4.1.1" | ||
| } | ||
| } |
| //#region ../nuxi/src/commands/_shared.ts | ||
| const cwdArgs = { cwd: { | ||
| type: "string", | ||
| description: "Specify the working directory", | ||
| valueHint: "directory", | ||
| default: "." | ||
| } }; | ||
| const logLevelArgs = { logLevel: { | ||
| type: "string", | ||
| description: "Specify build-time log level", | ||
| valueHint: "silent|info|verbose" | ||
| } }; | ||
| const envNameArgs = { envName: { | ||
| type: "string", | ||
| description: "The environment to use when resolving configuration overrides (default is `production` when building, and `development` when running the dev server)" | ||
| } }; | ||
| const dotEnvArgs = { dotenv: { | ||
| type: "string", | ||
| description: "Path to `.env` file to load, relative to the root directory" | ||
| } }; | ||
| const extendsArgs = { extends: { | ||
| type: "string", | ||
| description: "Extend from a Nuxt layer", | ||
| valueHint: "layer-name", | ||
| alias: ["e"] | ||
| } }; | ||
| const profileArgs = { profile: { | ||
| type: "string", | ||
| description: "Profile performance. Use --profile for CPU only, --profile=verbose for full report.", | ||
| default: void 0, | ||
| valueHint: "verbose" | ||
| } }; | ||
| const legacyRootDirArgs = { | ||
| cwd: { | ||
| ...cwdArgs.cwd, | ||
| description: "Specify the working directory, this takes precedence over ROOTDIR (default: `.`)", | ||
| default: void 0 | ||
| }, | ||
| rootDir: { | ||
| type: "positional", | ||
| description: "Specifies the working directory (default: `.`)", | ||
| required: false, | ||
| default: "." | ||
| } | ||
| }; | ||
| //#endregion | ||
| export { legacyRootDirArgs as a, extendsArgs as i, dotEnvArgs as n, logLevelArgs as o, envNameArgs as r, profileArgs as s, cwdArgs as t }; |
| import { satisfies } from "semver"; | ||
| import { $fetch } from "ofetch"; | ||
| import { parseINI } from "confbox"; | ||
| //#region ../nuxi/src/commands/module/_utils.ts | ||
| async function fetchModules() { | ||
| const { modules } = await $fetch(`https://api.nuxt.com/modules?version=all`); | ||
| return modules; | ||
| } | ||
| function checkNuxtCompatibility(module, nuxtVersion) { | ||
| if (!module.compatibility?.nuxt) return true; | ||
| return satisfies(nuxtVersion, module.compatibility.nuxt, { includePrerelease: true }); | ||
| } | ||
| function getRegistryFromContent(content, scope) { | ||
| try { | ||
| const npmConfig = parseINI(content); | ||
| if (scope) { | ||
| const scopeKey = `${scope}:registry`; | ||
| if (npmConfig[scopeKey]) return npmConfig[scopeKey].trim(); | ||
| } | ||
| if (npmConfig.registry) return npmConfig.registry.trim(); | ||
| return null; | ||
| } catch { | ||
| return null; | ||
| } | ||
| } | ||
| //#endregion | ||
| export { fetchModules as n, getRegistryFromContent as r, checkNuxtCompatibility as t }; |
| import { t as __exportAll } from "./rolldown-runtime-95iHPtFO.mjs"; | ||
| import { o as logLevelArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import { r as relativeToProcess } from "./kit-DUlGqV3Z.mjs"; | ||
| import { t as getNuxtVersion } from "./versions-Bg99eDSc.mjs"; | ||
| import { n as fetchModules, r as getRegistryFromContent, t as checkNuxtCompatibility } from "./_utils-Co1L4CHe.mjs"; | ||
| import { t as prepare_default } from "./prepare-etx17Cow.mjs"; | ||
| import { join } from "node:path"; | ||
| import process from "node:process"; | ||
| import { defineCommand, runCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { hasTTY } from "std-env"; | ||
| import { autocompleteMultiselect, cancel, confirm, isCancel, select, spinner } from "@clack/prompts"; | ||
| import { resolve as resolve$1 } from "pathe"; | ||
| import { fileURLToPath } from "node:url"; | ||
| import * as fs from "node:fs"; | ||
| import { existsSync } from "node:fs"; | ||
| import { joinURL } from "ufo"; | ||
| import { readPackageJSON } from "pkg-types"; | ||
| import { satisfies } from "semver"; | ||
| import { homedir } from "node:os"; | ||
| import { addDependency, detectPackageManager } from "nypm"; | ||
| import { $fetch } from "ofetch"; | ||
| import { Fzf, byLengthAsc } from "fzf"; | ||
| import { updateConfig } from "c12/update"; | ||
| //#region ../nuxi/src/commands/_utils.ts | ||
| const nuxiCommands = [ | ||
| "add", | ||
| "add-template", | ||
| "analyze", | ||
| "build", | ||
| "cleanup", | ||
| "_dev", | ||
| "dev", | ||
| "devtools", | ||
| "generate", | ||
| "info", | ||
| "init", | ||
| "module", | ||
| "prepare", | ||
| "preview", | ||
| "start", | ||
| "test", | ||
| "typecheck", | ||
| "upgrade" | ||
| ]; | ||
| function isNuxiCommand(command) { | ||
| return nuxiCommands.includes(command); | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/run.ts | ||
| globalThis.__nuxt_cli__ = globalThis.__nuxt_cli__ || { | ||
| startTime: Date.now(), | ||
| entry: fileURLToPath(new URL("../../bin/nuxi.mjs", import.meta.url)), | ||
| devEntry: fileURLToPath(new URL("../dev/index.mjs", import.meta.url)) | ||
| }; | ||
| async function runCommand$1(command, argv = process.argv.slice(2), data = {}) { | ||
| argv.push("--no-clear"); | ||
| if (command.meta && "name" in command.meta && typeof command.meta.name === "string") { | ||
| const name = command.meta.name; | ||
| if (!isNuxiCommand(name)) throw new Error(`Invalid command ${name}`); | ||
| } else throw new Error(`Invalid command, must be named`); | ||
| return await runCommand(command, { | ||
| rawArgs: argv, | ||
| data: { overrides: data.overrides || {} } | ||
| }); | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/commands/module/_autocomplete.ts | ||
| const TRAILING_DOT_RE = /\.$/; | ||
| /** | ||
| * Interactive fuzzy search for selecting Nuxt modules | ||
| * Returns object with selected module npm package names and cancellation status | ||
| */ | ||
| async function selectModulesAutocomplete(options) { | ||
| const { modules, message = "Search and select modules:" } = options; | ||
| if (!hasTTY) { | ||
| logger.warn("Interactive module selection requires a TTY. Skipping."); | ||
| return { | ||
| selected: [], | ||
| cancelled: false | ||
| }; | ||
| } | ||
| const sortedModules = modules.toSorted((a, b) => { | ||
| if (a.type === "official" && b.type !== "official") return -1; | ||
| if (a.type !== "official" && b.type === "official") return 1; | ||
| return a.npm.localeCompare(b.npm); | ||
| }); | ||
| const fzf = new Fzf(sortedModules, { | ||
| selector: (m) => `${m.npm} ${m.name} ${m.category}`, | ||
| casing: "case-insensitive", | ||
| tiebreakers: [byLengthAsc] | ||
| }); | ||
| const clackOptions = sortedModules.map((m) => ({ | ||
| value: m.npm, | ||
| label: m.npm, | ||
| hint: m.description.replace(TRAILING_DOT_RE, "") | ||
| })); | ||
| const filter = (search, option) => { | ||
| if (!search) return true; | ||
| return fzf.find(search).some((r) => r.item.npm === option.value); | ||
| }; | ||
| const result = await autocompleteMultiselect({ | ||
| message, | ||
| options: clackOptions, | ||
| filter, | ||
| required: false | ||
| }); | ||
| if (isCancel(result)) return { | ||
| selected: [], | ||
| cancelled: true | ||
| }; | ||
| return { | ||
| selected: result, | ||
| cancelled: false | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/commands/module/add.ts | ||
| var add_exports = /* @__PURE__ */ __exportAll({ default: () => add_default }); | ||
| const PROTOCOL_RE = /^https?:\/\//; | ||
| const TRAILING_SLASH_RE = /\/$/; | ||
| const REGEX_SPECIAL_RE = /[.*+?^${}()|[\]\\]/g; | ||
| var add_default = defineCommand({ | ||
| meta: { | ||
| name: "add", | ||
| description: "Add Nuxt modules" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| moduleName: { | ||
| type: "positional", | ||
| description: "Specify one or more modules to install by name, separated by spaces" | ||
| }, | ||
| skipInstall: { | ||
| type: "boolean", | ||
| description: "Skip npm install" | ||
| }, | ||
| skipConfig: { | ||
| type: "boolean", | ||
| description: "Skip nuxt.config.ts update" | ||
| }, | ||
| dev: { | ||
| type: "boolean", | ||
| description: "Install modules as dev dependencies" | ||
| } | ||
| }, | ||
| async setup(ctx) { | ||
| const cwd = resolve$1(ctx.args.cwd); | ||
| let modules = ctx.args._.map((e) => e.trim()).filter(Boolean); | ||
| const projectPkg = await readPackageJSON(cwd).catch(() => ({})); | ||
| if (!projectPkg.dependencies?.nuxt && !projectPkg.devDependencies?.nuxt) { | ||
| logger.warn(`No ${colors.cyan("nuxt")} dependency detected in ${colors.cyan(relativeToProcess(cwd))}.`); | ||
| const shouldContinue = await confirm({ | ||
| message: `Do you want to continue anyway?`, | ||
| initialValue: false | ||
| }); | ||
| if (isCancel(shouldContinue) || shouldContinue !== true) process.exit(1); | ||
| } | ||
| if (modules.length === 0) { | ||
| const modulesSpinner = spinner(); | ||
| modulesSpinner.start("Fetching available modules"); | ||
| const [allModules, nuxtVersion] = await Promise.all([fetchModules(), getNuxtVersion(cwd)]); | ||
| const compatibleModules = allModules.filter((m) => !m.compatibility.nuxt || checkNuxtCompatibility(m, nuxtVersion)); | ||
| modulesSpinner.stop("Modules loaded"); | ||
| const result = await selectModulesAutocomplete({ | ||
| modules: compatibleModules, | ||
| message: "Search modules to add (Esc to finish):" | ||
| }); | ||
| if (result.selected.length === 0) { | ||
| cancel("No modules selected."); | ||
| process.exit(0); | ||
| } | ||
| modules = result.selected; | ||
| } | ||
| const resolvedModules = []; | ||
| for (const moduleName of modules) { | ||
| const resolvedModule = await resolveModule(moduleName, cwd); | ||
| if (resolvedModule) resolvedModules.push(resolvedModule); | ||
| } | ||
| if (resolvedModules.length === 0) { | ||
| cancel("No modules to add."); | ||
| process.exit(1); | ||
| } | ||
| logger.info(`Resolved ${resolvedModules.map((x) => colors.cyan(x.pkgName)).join(", ")}, adding module${resolvedModules.length > 1 ? "s" : ""}...`); | ||
| await addModules(resolvedModules, { | ||
| ...ctx.args, | ||
| cwd | ||
| }, projectPkg); | ||
| if (!ctx.args.skipInstall) await runCommand$1(prepare_default, Object.entries(ctx.args).filter(([k]) => k in cwdArgs || k in logLevelArgs).map(([k, v]) => `--${k}=${v}`)); | ||
| } | ||
| }); | ||
| async function addModules(modules, { skipInstall = false, skipConfig = false, cwd, dev = false }, projectPkg) { | ||
| if (!skipInstall) { | ||
| const installedModules = []; | ||
| const notInstalledModules = []; | ||
| const dependencies = new Set([...Object.keys(projectPkg.dependencies || {}), ...Object.keys(projectPkg.devDependencies || {})]); | ||
| for (const module of modules) if (dependencies.has(module.pkgName)) installedModules.push(module); | ||
| else notInstalledModules.push(module); | ||
| if (installedModules.length > 0) { | ||
| const installedModulesList = installedModules.map((module) => colors.cyan(module.pkgName)).join(", "); | ||
| const are = installedModules.length > 1 ? "are" : "is"; | ||
| logger.info(`${installedModulesList} ${are} already installed`); | ||
| } | ||
| if (notInstalledModules.length > 0) { | ||
| const isDev = Boolean(projectPkg.devDependencies?.nuxt) || dev; | ||
| const notInstalledModulesList = notInstalledModules.map((module) => colors.cyan(module.pkg)).join(", "); | ||
| const dependency = notInstalledModules.length > 1 ? "dependencies" : "dependency"; | ||
| const a = notInstalledModules.length > 1 ? "" : " a"; | ||
| logger.info(`Installing ${notInstalledModulesList} as${a}${isDev ? " development" : ""} ${dependency}`); | ||
| const packageManager = await detectPackageManager(cwd); | ||
| if (await addDependency(notInstalledModules.map((module) => module.pkg), { | ||
| cwd, | ||
| dev: isDev, | ||
| installPeerDependencies: true, | ||
| packageManager, | ||
| workspace: packageManager?.name === "pnpm" && existsSync(resolve$1(cwd, "pnpm-workspace.yaml")) | ||
| }).then(() => true).catch(async (error) => { | ||
| logger.error(String(error)); | ||
| const result = await confirm({ | ||
| message: `Install failed for ${notInstalledModules.map((module) => colors.cyan(module.pkg)).join(", ")}. Do you want to continue adding the module${notInstalledModules.length > 1 ? "s" : ""} to ${colors.cyan("nuxt.config")}?`, | ||
| initialValue: false | ||
| }); | ||
| if (isCancel(result)) return false; | ||
| return result; | ||
| }) !== true) return; | ||
| } | ||
| } | ||
| if (!skipConfig) await updateConfig({ | ||
| cwd, | ||
| configFile: "nuxt.config", | ||
| async onCreate() { | ||
| logger.info(`Creating ${colors.cyan("nuxt.config.ts")}`); | ||
| return getDefaultNuxtConfig(); | ||
| }, | ||
| async onUpdate(config) { | ||
| if (!config.modules) config.modules = []; | ||
| for (const resolved of modules) { | ||
| if (config.modules.includes(resolved.pkgName)) { | ||
| logger.info(`${colors.cyan(resolved.pkgName)} is already in the ${colors.cyan("modules")}`); | ||
| continue; | ||
| } | ||
| logger.info(`Adding ${colors.cyan(resolved.pkgName)} to the ${colors.cyan("modules")}`); | ||
| config.modules.push(resolved.pkgName); | ||
| } | ||
| } | ||
| }).catch((error) => { | ||
| logger.error(`Failed to update ${colors.cyan("nuxt.config")}: ${error.message}`); | ||
| logger.error(`Please manually add ${colors.cyan(modules.map((module) => module.pkgName).join(", "))} to the ${colors.cyan("modules")} in ${colors.cyan("nuxt.config.ts")}`); | ||
| return null; | ||
| }); | ||
| } | ||
| function getDefaultNuxtConfig() { | ||
| return ` | ||
| // https://nuxt.com/docs/api/configuration/nuxt-config | ||
| export default defineNuxtConfig({ | ||
| modules: [] | ||
| })`; | ||
| } | ||
| const packageRegex = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?([a-z0-9-~][a-z0-9-._~]*)(@[^@]+)?$/; | ||
| async function resolveModule(moduleName, cwd) { | ||
| let pkgName = moduleName; | ||
| let pkgVersion; | ||
| const reMatch = moduleName.match(packageRegex); | ||
| if (reMatch) { | ||
| if (reMatch[3]) { | ||
| pkgName = `${reMatch[1] || ""}${reMatch[2] || ""}`; | ||
| pkgVersion = reMatch[3].slice(1); | ||
| } | ||
| } else { | ||
| logger.error(`Invalid package name ${colors.cyan(pkgName)}.`); | ||
| return false; | ||
| } | ||
| const matchedModule = (await fetchModules().catch((err) => { | ||
| logger.warn(`Cannot search in the Nuxt Modules database: ${err}`); | ||
| return []; | ||
| })).find((module) => module.name === moduleName || pkgVersion && module.name === pkgName || module.npm === pkgName || module.aliases?.includes(pkgName)); | ||
| if (matchedModule?.npm) pkgName = matchedModule.npm; | ||
| if (matchedModule && matchedModule.compatibility.nuxt) { | ||
| const nuxtVersion = await getNuxtVersion(cwd); | ||
| if (!checkNuxtCompatibility(matchedModule, nuxtVersion)) { | ||
| logger.warn(`The module ${colors.cyan(pkgName)} is not compatible with Nuxt ${colors.cyan(nuxtVersion)} (requires ${colors.cyan(matchedModule.compatibility.nuxt)})`); | ||
| const shouldContinue = await confirm({ | ||
| message: "Do you want to continue installing incompatible version?", | ||
| initialValue: false | ||
| }); | ||
| if (isCancel(shouldContinue) || !shouldContinue) return false; | ||
| } | ||
| const versionMap = matchedModule.compatibility.versionMap; | ||
| if (versionMap) { | ||
| for (const [_nuxtVersion, _moduleVersion] of Object.entries(versionMap)) if (satisfies(nuxtVersion, _nuxtVersion)) { | ||
| if (!pkgVersion) pkgVersion = _moduleVersion; | ||
| else { | ||
| logger.warn(`Recommended version of ${colors.cyan(pkgName)} for Nuxt ${colors.cyan(nuxtVersion)} is ${colors.cyan(_moduleVersion)} but you have requested ${colors.cyan(pkgVersion)}.`); | ||
| const result = await select({ | ||
| message: "Choose a version:", | ||
| options: [{ | ||
| value: _moduleVersion, | ||
| label: _moduleVersion | ||
| }, { | ||
| value: pkgVersion, | ||
| label: pkgVersion | ||
| }] | ||
| }); | ||
| if (isCancel(result)) return false; | ||
| pkgVersion = result; | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| let version = pkgVersion || "latest"; | ||
| const meta = await detectNpmRegistry(pkgName.startsWith("@") ? pkgName.split("/")[0] : null); | ||
| const headers = {}; | ||
| if (meta.authToken) headers.Authorization = `Bearer ${meta.authToken}`; | ||
| const pkgDetails = await $fetch(joinURL(meta.registry, `${pkgName}`), { headers }).catch(() => null); | ||
| if (!pkgDetails) { | ||
| logger.error(`Failed to fetch package details for ${colors.cyan(pkgName)}.`); | ||
| return false; | ||
| } | ||
| if (pkgDetails["dist-tags"]?.[version]) version = pkgDetails["dist-tags"][version]; | ||
| else version = Object.keys(pkgDetails.versions)?.findLast((v) => satisfies(v, version)) || version; | ||
| const pkg = pkgDetails.versions[version] || {}; | ||
| const pkgDependencies = Object.assign(pkg.dependencies || {}, pkg.devDependencies || {}); | ||
| if (!pkgDependencies.nuxt && !pkgDependencies["nuxt-edge"] && !pkgDependencies["@nuxt/kit"]) { | ||
| logger.warn(`It seems that ${colors.cyan(pkgName)} is not a Nuxt module.`); | ||
| const shouldContinue = await confirm({ | ||
| message: `Do you want to continue installing ${colors.cyan(pkgName)} anyway?`, | ||
| initialValue: false | ||
| }); | ||
| if (isCancel(shouldContinue) || !shouldContinue) return false; | ||
| } | ||
| return { | ||
| nuxtModule: matchedModule, | ||
| pkg: `${pkgName}@${version}`, | ||
| pkgName, | ||
| pkgVersion: version | ||
| }; | ||
| } | ||
| function getNpmrcPaths() { | ||
| const userNpmrcPath = join(homedir(), ".npmrc"); | ||
| return [join(process.cwd(), ".npmrc"), userNpmrcPath]; | ||
| } | ||
| async function getAuthToken(registry) { | ||
| const paths = getNpmrcPaths(); | ||
| const registryHost = registry.replace(PROTOCOL_RE, "").replace(TRAILING_SLASH_RE, "").replace(REGEX_SPECIAL_RE, "\\$&"); | ||
| const authTokenRegex = new RegExp(`^//${registryHost}/:_authToken=(.+)$`, "m"); | ||
| for (const npmrcPath of paths) { | ||
| let fd; | ||
| try { | ||
| fd = await fs.promises.open(npmrcPath, "r"); | ||
| if (await fd.stat().then((r) => r.isFile())) { | ||
| const authTokenMatch = (await fd.readFile("utf-8")).match(authTokenRegex)?.[1]; | ||
| if (authTokenMatch) return authTokenMatch.trim(); | ||
| } | ||
| } catch {} finally { | ||
| await fd?.close(); | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| async function detectNpmRegistry(scope) { | ||
| const registry = await getRegistry(scope); | ||
| return { | ||
| registry, | ||
| authToken: await getAuthToken(registry) | ||
| }; | ||
| } | ||
| async function getRegistry(scope) { | ||
| if (process.env.COREPACK_NPM_REGISTRY) return process.env.COREPACK_NPM_REGISTRY; | ||
| const registry = await getRegistryFromFile(getNpmrcPaths(), scope); | ||
| if (registry) process.env.COREPACK_NPM_REGISTRY = registry; | ||
| return registry || "https://registry.npmjs.org"; | ||
| } | ||
| async function getRegistryFromFile(paths, scope) { | ||
| for (const npmrcPath of paths) { | ||
| let fd; | ||
| try { | ||
| fd = await fs.promises.open(npmrcPath, "r"); | ||
| if (await fd.stat().then((r) => r.isFile())) { | ||
| const registry = getRegistryFromContent(await fd.readFile("utf-8"), scope); | ||
| if (registry) return registry; | ||
| } | ||
| } catch {} finally { | ||
| await fd?.close(); | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| //#endregion | ||
| export { runCommand$1 as i, add_exports as n, selectModulesAutocomplete as r, add_default as t }; |
| import { o as logLevelArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import { n as templates, t as templateNames } from "./templates-wxuD_F_w.mjs"; | ||
| import { r as relativeToProcess, t as loadKit } from "./kit-DUlGqV3Z.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { cancel, intro, outro } from "@clack/prompts"; | ||
| import { dirname, extname, resolve } from "pathe"; | ||
| import { existsSync, promises } from "node:fs"; | ||
| //#region ../nuxi/src/commands/add-template.ts | ||
| var add_template_default = defineCommand({ | ||
| meta: { | ||
| name: "add-template", | ||
| description: "Create a new template file." | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| force: { | ||
| type: "boolean", | ||
| description: "Force override file if it already exists", | ||
| default: false | ||
| }, | ||
| template: { | ||
| type: "positional", | ||
| required: true, | ||
| valueHint: templateNames.join("|"), | ||
| description: `Specify which template to generate` | ||
| }, | ||
| name: { | ||
| type: "positional", | ||
| required: true, | ||
| description: "Specify name of the generated file" | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| const cwd = resolve(ctx.args.cwd); | ||
| intro(colors.cyan("Adding template...")); | ||
| const templateName = ctx.args.template; | ||
| if (!templateNames.includes(templateName)) { | ||
| const templateNames = Object.keys(templates).map((name) => colors.cyan(name)); | ||
| const lastTemplateName = templateNames.pop(); | ||
| logger.error(`Template ${colors.cyan(templateName)} is not supported.`); | ||
| logger.info(`Possible values are ${templateNames.join(", ")} or ${lastTemplateName}.`); | ||
| process.exit(1); | ||
| } | ||
| const ext = extname(ctx.args.name); | ||
| const name = ext === ".vue" || ext === ".ts" ? ctx.args.name.replace(ext, "") : ctx.args.name; | ||
| if (!name) { | ||
| cancel("name argument is missing!"); | ||
| process.exit(1); | ||
| } | ||
| const config = await (await loadKit(cwd)).loadNuxtConfig({ cwd }); | ||
| const template = templates[templateName]; | ||
| const res = template({ | ||
| name, | ||
| args: ctx.args, | ||
| nuxtOptions: config | ||
| }); | ||
| if (!ctx.args.force && existsSync(res.path)) { | ||
| logger.error(`File exists at ${colors.cyan(relativeToProcess(res.path))}.`); | ||
| logger.info(`Use ${colors.cyan("--force")} to override or use a different name.`); | ||
| process.exit(1); | ||
| } | ||
| const parentDir = dirname(res.path); | ||
| if (!existsSync(parentDir)) { | ||
| logger.step(`Creating directory ${colors.cyan(relativeToProcess(parentDir))}.`); | ||
| if (templateName === "page") logger.info("This enables vue-router functionality!"); | ||
| await promises.mkdir(parentDir, { recursive: true }); | ||
| } | ||
| await promises.writeFile(res.path, `${res.contents.trim()}\n`); | ||
| logger.success(`Created ${colors.cyan(relativeToProcess(res.path))}.`); | ||
| outro(`Generated a new ${colors.cyan(templateName)}!`); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { add_template_default as default }; |
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import { t as overrideEnv } from "./env-BRiVSJMz.mjs"; | ||
| import { r as relativeToProcess, t as loadKit } from "./kit-DUlGqV3Z.mjs"; | ||
| import { n as clearDir } from "./fs-B8DrLsZ2.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { intro, note, outro, taskLog } from "@clack/prompts"; | ||
| import { join, resolve } from "pathe"; | ||
| import { defu as defu$1 } from "defu"; | ||
| import { promises } from "node:fs"; | ||
| import { FastResponse, FastURL, serve } from "srvx"; | ||
| //#region ../../node_modules/.pnpm/rou3@0.8.1/node_modules/rou3/dist/index.mjs | ||
| const NullProtoObj = /* @__PURE__ */ (() => { | ||
| const e = function() {}; | ||
| return e.prototype = Object.create(null), Object.freeze(e.prototype), e; | ||
| })(); | ||
| /** | ||
| * Create a new router context. | ||
| */ | ||
| function createRouter() { | ||
| return { | ||
| root: { key: "" }, | ||
| static: new NullProtoObj() | ||
| }; | ||
| } | ||
| function expandGroupDelimiters(path) { | ||
| let i = 0; | ||
| let depth = 0; | ||
| for (; i < path.length; i++) { | ||
| const c = path.charCodeAt(i); | ||
| if (c === 92) { | ||
| i++; | ||
| continue; | ||
| } | ||
| if (c === 40) { | ||
| depth++; | ||
| continue; | ||
| } | ||
| if (c === 41 && depth > 0) { | ||
| depth--; | ||
| continue; | ||
| } | ||
| if (c === 123 && depth === 0) break; | ||
| } | ||
| if (i >= path.length) return; | ||
| let j = i + 1; | ||
| depth = 0; | ||
| for (; j < path.length; j++) { | ||
| const c = path.charCodeAt(j); | ||
| if (c === 92) { | ||
| j++; | ||
| continue; | ||
| } | ||
| if (c === 40) { | ||
| depth++; | ||
| continue; | ||
| } | ||
| if (c === 41 && depth > 0) { | ||
| depth--; | ||
| continue; | ||
| } | ||
| if (c === 125 && depth === 0) break; | ||
| } | ||
| if (j >= path.length) return; | ||
| const mod = path[j + 1]; | ||
| const hasMod = mod === "?" || mod === "+" || mod === "*"; | ||
| const pre = path.slice(0, i); | ||
| const body = path.slice(i + 1, j); | ||
| const suf = path.slice(j + (hasMod ? 2 : 1)); | ||
| if (!hasMod) return [pre + body + suf]; | ||
| if (mod === "?") return [pre + body + suf, pre + suf]; | ||
| if (body.includes("/")) throw new Error("unsupported group repetition across segments"); | ||
| return [`${pre}(?:${body})${mod}${suf}`]; | ||
| } | ||
| const UNNAMED_GROUP_PREFIX = "__rou3_unnamed_"; | ||
| const _unnamedGroupPrefixLength = 15; | ||
| function hasSegmentWildcard(segment) { | ||
| let depth = 0; | ||
| for (let i = 0; i < segment.length; i++) { | ||
| const ch = segment.charCodeAt(i); | ||
| if (ch === 92) { | ||
| i++; | ||
| continue; | ||
| } | ||
| if (ch === 40) { | ||
| depth++; | ||
| continue; | ||
| } | ||
| if (ch === 41 && depth > 0) { | ||
| depth--; | ||
| continue; | ||
| } | ||
| if (ch === 42 && depth === 0) return true; | ||
| } | ||
| return false; | ||
| } | ||
| function replaceSegmentWildcards(segment, unnamedStart, toGroupKey = toUnnamedGroupKey) { | ||
| let depth = 0; | ||
| let nextIndex = unnamedStart; | ||
| let replaced = ""; | ||
| for (let i = 0; i < segment.length; i++) { | ||
| const ch = segment.charCodeAt(i); | ||
| if (ch === 92) { | ||
| replaced += segment[i]; | ||
| if (i + 1 < segment.length) replaced += segment[++i]; | ||
| continue; | ||
| } | ||
| if (ch === 40) { | ||
| depth++; | ||
| replaced += segment[i]; | ||
| continue; | ||
| } | ||
| if (ch === 41 && depth > 0) { | ||
| depth--; | ||
| replaced += segment[i]; | ||
| continue; | ||
| } | ||
| if (ch === 42 && depth === 0) { | ||
| replaced += `(?<${toGroupKey(nextIndex++)}>[^/]*)`; | ||
| continue; | ||
| } | ||
| replaced += segment[i]; | ||
| } | ||
| return [replaced, nextIndex]; | ||
| } | ||
| function toUnnamedGroupKey(index) { | ||
| return `${UNNAMED_GROUP_PREFIX}${index}`; | ||
| } | ||
| function normalizeUnnamedGroupKey(key) { | ||
| return key.startsWith("__rou3_unnamed_") ? key.slice(_unnamedGroupPrefixLength) : key; | ||
| } | ||
| function encodeEscapes(path) { | ||
| return path.replace(/\\:/g, "�A").replace(/\\\(/g, "�B").replace(/\\\)/g, "�C").replace(/\\\{/g, "�D").replace(/\\\}/g, "�E"); | ||
| } | ||
| function decodeEscaped(segment) { | ||
| return segment.replace(/\uFFFD([A-E])/g, (_, c) => c === "A" ? ":" : c === "B" ? "(" : c === "C" ? ")" : c === "D" ? "{" : "}"); | ||
| } | ||
| function expandModifiers(segments) { | ||
| for (let i = 0; i < segments.length; i++) { | ||
| const m = segments[i].match(/^(.*:[\w-]+(?:\([^)]*\))?)([?+*])$/); | ||
| if (!m) continue; | ||
| const pre = segments.slice(0, i); | ||
| const suf = segments.slice(i + 1); | ||
| if (m[2] === "?") return ["/" + pre.concat(m[1]).concat(suf).join("/"), "/" + pre.concat(suf).join("/")]; | ||
| const name = m[1].match(/:([\w-]+)/)?.[1] || "_"; | ||
| const wc = "/" + [ | ||
| ...pre, | ||
| `**:${name}`, | ||
| ...suf | ||
| ].join("/"); | ||
| const without = "/" + [...pre, ...suf].join("/"); | ||
| return m[2] === "+" ? [wc] : [wc, without]; | ||
| } | ||
| } | ||
| function normalizePath(path) { | ||
| if (!path.includes("/.")) return path; | ||
| const r = []; | ||
| for (const s of path.split("/")) if (s === ".") continue; | ||
| else if (s === ".." && r.length > 1) r.pop(); | ||
| else r.push(s); | ||
| return r.join("/") || "/"; | ||
| } | ||
| function splitPath(path) { | ||
| const [_, ...s] = path.split("/"); | ||
| return s[s.length - 1] === "" ? s.slice(0, -1) : s; | ||
| } | ||
| function getMatchParams(segments, paramsMap) { | ||
| const params = new NullProtoObj(); | ||
| for (const [index, name] of paramsMap) { | ||
| const segment = index < 0 ? segments.slice(-(index + 1)).join("/") : segments[index]; | ||
| if (typeof name === "string") params[name] = segment; | ||
| else { | ||
| const match = segment.match(name); | ||
| if (match) for (const key in match.groups) params[normalizeUnnamedGroupKey(key)] = match.groups[key]; | ||
| } | ||
| } | ||
| return params; | ||
| } | ||
| /** | ||
| * Add a route to the router context. | ||
| */ | ||
| function addRoute(ctx, method = "", path, data) { | ||
| method = method.toUpperCase(); | ||
| if (path.charCodeAt(0) !== 47) path = `/${path}`; | ||
| const groupExpanded = expandGroupDelimiters(path); | ||
| if (groupExpanded) { | ||
| for (const expandedPath of groupExpanded) addRoute(ctx, method, expandedPath, data); | ||
| return; | ||
| } | ||
| path = encodeEscapes(path); | ||
| const segments = splitPath(path); | ||
| const expanded = expandModifiers(segments); | ||
| if (expanded) { | ||
| for (const p of expanded) addRoute(ctx, method, p, data); | ||
| return; | ||
| } | ||
| let node = ctx.root; | ||
| let _unnamedParamIndex = 0; | ||
| const paramsMap = []; | ||
| const paramsRegexp = []; | ||
| for (let i = 0; i < segments.length; i++) { | ||
| let segment = segments[i]; | ||
| if (segment.startsWith("**")) { | ||
| if (!node.wildcard) node.wildcard = { key: "**" }; | ||
| node = node.wildcard; | ||
| paramsMap.push([ | ||
| -(i + 1), | ||
| segment.split(":")[1] || "_", | ||
| segment.length === 2 | ||
| ]); | ||
| break; | ||
| } | ||
| if (segment === "*" || segment.includes(":") || segment.includes("(") || hasSegmentWildcard(segment)) { | ||
| if (!node.param) node.param = { key: "*" }; | ||
| node = node.param; | ||
| if (segment === "*") paramsMap.push([ | ||
| i, | ||
| String(_unnamedParamIndex++), | ||
| true | ||
| ]); | ||
| else if (segment.includes(":", 1) || segment.includes("(") || hasSegmentWildcard(segment) || !/^:[\w-]+$/.test(segment)) { | ||
| const [regexp, nextIndex] = getParamRegexp(segment, _unnamedParamIndex); | ||
| _unnamedParamIndex = nextIndex; | ||
| paramsRegexp[i] = regexp; | ||
| node.hasRegexParam = true; | ||
| paramsMap.push([ | ||
| i, | ||
| regexp, | ||
| false | ||
| ]); | ||
| } else paramsMap.push([ | ||
| i, | ||
| segment.slice(1), | ||
| false | ||
| ]); | ||
| continue; | ||
| } | ||
| if (segment === "\\*") segment = segments[i] = "*"; | ||
| else if (segment === "\\*\\*") segment = segments[i] = "**"; | ||
| segment = segments[i] = decodeEscaped(segment); | ||
| const child = node.static?.[segment]; | ||
| if (child) node = child; | ||
| else { | ||
| const staticNode = { key: segment }; | ||
| if (!node.static) node.static = new NullProtoObj(); | ||
| node.static[segment] = staticNode; | ||
| node = staticNode; | ||
| } | ||
| } | ||
| const hasParams = paramsMap.length > 0; | ||
| if (!node.methods) node.methods = new NullProtoObj(); | ||
| node.methods[method] ??= []; | ||
| node.methods[method].push({ | ||
| data: data || null, | ||
| paramsRegexp, | ||
| paramsMap: hasParams ? paramsMap : void 0 | ||
| }); | ||
| if (!hasParams) ctx.static["/" + segments.join("/")] = node; | ||
| } | ||
| function getParamRegexp(segment, unnamedStart = 0) { | ||
| let _i = unnamedStart; | ||
| let _s = "", _d = 0; | ||
| for (let j = 0; j < segment.length; j++) { | ||
| const c = segment.charCodeAt(j); | ||
| if (c === 40) _d++; | ||
| else if (c === 41 && _d > 0) _d--; | ||
| else if (c === 92 && _d === 0 && j + 1 < segment.length) { | ||
| const n = segment[j + 1]; | ||
| if (n !== ":" && n !== "(" && n !== "*" && n !== "\\") { | ||
| _s += "" + n; | ||
| j++; | ||
| continue; | ||
| } | ||
| } | ||
| _s += segment[j]; | ||
| } | ||
| [_s, _i] = replaceSegmentWildcards(_s, _i); | ||
| const regex = _s.replace(/:([\w-]+)(?:\(([^)]*)\))?/g, (_, id, p) => `(?<${id}>${p || "[^/]+"})`).replace(/\((?![?<])/g, () => `(?<${toUnnamedGroupKey(_i++)}>`).replace(/\./g, "\\.").replace(/\uFFFE(.)/g, (_, c) => /[.*+?^${}()|[\]\\]/.test(c) ? `\\${c}` : c); | ||
| return [new RegExp(`^${regex}$`), _i]; | ||
| } | ||
| /** | ||
| * Find a route by path. | ||
| */ | ||
| function findRoute(ctx, method = "", path, opts) { | ||
| if (opts?.normalize) path = normalizePath(path); | ||
| if (path.charCodeAt(path.length - 1) === 47) path = path.slice(0, -1); | ||
| const staticNode = ctx.static[path]; | ||
| if (staticNode && staticNode.methods) { | ||
| const staticMatch = staticNode.methods[method] || staticNode.methods[""]; | ||
| if (staticMatch !== void 0) return staticMatch[0]; | ||
| } | ||
| const segments = splitPath(path); | ||
| const match = _lookupTree(ctx.root, method, segments, 0)?.[0]; | ||
| if (match === void 0) return; | ||
| if (opts?.params === false) return match; | ||
| return { | ||
| data: match.data, | ||
| params: match.paramsMap ? getMatchParams(segments, match.paramsMap) : void 0 | ||
| }; | ||
| } | ||
| function _lookupTree(node, method, segments, index) { | ||
| if (index === segments.length) { | ||
| if (node.methods) { | ||
| const match = node.methods[method] || node.methods[""]; | ||
| if (match) return match; | ||
| } | ||
| if (node.param && node.param.methods) { | ||
| const match = node.param.methods[method] || node.param.methods[""]; | ||
| if (match) { | ||
| const pMap = match[0].paramsMap; | ||
| if (pMap?.[pMap?.length - 1]?.[2]) return match; | ||
| } | ||
| } | ||
| if (node.wildcard && node.wildcard.methods) { | ||
| const match = node.wildcard.methods[method] || node.wildcard.methods[""]; | ||
| if (match) { | ||
| const pMap = match[0].paramsMap; | ||
| if (pMap?.[pMap?.length - 1]?.[2]) return match; | ||
| } | ||
| } | ||
| return; | ||
| } | ||
| const segment = segments[index]; | ||
| if (node.static) { | ||
| const staticChild = node.static[segment]; | ||
| if (staticChild) { | ||
| const match = _lookupTree(staticChild, method, segments, index + 1); | ||
| if (match) return match; | ||
| } | ||
| } | ||
| if (node.param) { | ||
| const match = _lookupTree(node.param, method, segments, index + 1); | ||
| if (match) { | ||
| if (node.param.hasRegexParam) { | ||
| const exactMatch = match.find((m) => m.paramsRegexp[index]?.test(segment)) || match.find((m) => !m.paramsRegexp[index]); | ||
| return exactMatch ? [exactMatch] : void 0; | ||
| } | ||
| return match; | ||
| } | ||
| } | ||
| if (node.wildcard && node.wildcard.methods) return node.wildcard.methods[method] || node.wildcard.methods[""]; | ||
| } | ||
| const _P = ""; | ||
| function replaceEscapesOutsideGroups(segment) { | ||
| let r = "", d = 0; | ||
| for (let i = 0; i < segment.length; i++) { | ||
| const c = segment.charCodeAt(i); | ||
| if (c === 40) d++; | ||
| else if (c === 41 && d > 0) d--; | ||
| else if (c === 92 && d === 0 && i + 1 < segment.length) { | ||
| const n = segment[i + 1]; | ||
| if (n !== ":" && n !== "(" && n !== "*" && n !== "\\") { | ||
| r += _P + n; | ||
| i++; | ||
| continue; | ||
| } | ||
| } | ||
| r += segment[i]; | ||
| } | ||
| return r; | ||
| } | ||
| function resolveEscapePlaceholders(str) { | ||
| return str.replace(/\uFFFE(.)/g, (_, c) => /[.*+?^${}()|[\]\\]/.test(c) ? `\\${c}` : c); | ||
| } | ||
| function routeToRegExp(route = "/") { | ||
| const groupExpanded = expandGroupDelimiters(route); | ||
| if (groupExpanded) { | ||
| const sources = groupExpanded.map((expandedRoute) => routeToRegExp(expandedRoute).source.slice(1, -1)); | ||
| return new RegExp(`^(?:${sources.join("|")})$`); | ||
| } | ||
| return _routeToRegExp(route); | ||
| } | ||
| function _routeToRegExp(route) { | ||
| const reSegments = []; | ||
| let idCtr = 0; | ||
| for (const segment of route.split("/")) { | ||
| if (!segment) continue; | ||
| if (segment === "*") reSegments.push(`(?<${toRegExpUnnamedKey(idCtr++)}>[^/]*)`); | ||
| else if (segment.startsWith("**")) reSegments.push(segment === "**" ? "?(?<_>.*)" : `?(?<${segment.slice(3)}>.+)`); | ||
| else if (segment.includes(":") || /(^|[^\\])\(/.test(segment) || hasSegmentWildcard(segment)) { | ||
| const modMatch = segment.match(/^(.*:[\w-]+(?:\([^)]*\))?)([?+*])$/); | ||
| if (modMatch) { | ||
| const [, base, mod] = modMatch; | ||
| const name = base.match(/:([\w-]+)/)?.[1] || `_${idCtr++}`; | ||
| if (mod === "?") { | ||
| const inner = base.replace(/:([\w-]+)(?:\(([^)]*)\))?/g, (_, id, pattern) => `(?<${id}>${pattern || "[^/]+"})`).replace(/\./g, "\\."); | ||
| if (reSegments.length > 0) { | ||
| const prevQ = reSegments.pop(); | ||
| reSegments.push(`${prevQ}(?:/${inner})?`); | ||
| } else reSegments.push(`?${inner}?`); | ||
| continue; | ||
| } | ||
| const pattern = base.match(/:(\w+)(?:\(([^)]*)\))?/)?.[2]; | ||
| if (reSegments.length > 0) { | ||
| const prevMod = reSegments.pop(); | ||
| if (pattern) { | ||
| const repeated = `${pattern}(?:/${pattern})*`; | ||
| reSegments.push(mod === "+" ? `${prevMod}/(?<${name}>${repeated})` : `${prevMod}(?:/(?<${name}>${repeated}))?`); | ||
| } else reSegments.push(mod === "+" ? `${prevMod}/(?<${name}>.+)` : `${prevMod}(?:/(?<${name}>.*))?`); | ||
| } else if (pattern) { | ||
| const repeated = `${pattern}(?:/${pattern})*`; | ||
| reSegments.push(mod === "+" ? `?(?<${name}>${repeated})` : `?(?<${name}>${repeated})?`); | ||
| } else reSegments.push(mod === "+" ? `?(?<${name}>.+)` : `?(?<${name}>.*)`); | ||
| continue; | ||
| } | ||
| let dynamicSegment = replaceEscapesOutsideGroups(segment); | ||
| [dynamicSegment, idCtr] = replaceSegmentWildcards(dynamicSegment, idCtr, toRegExpUnnamedKey); | ||
| reSegments.push(resolveEscapePlaceholders(dynamicSegment.replace(/:([\w-]+)(?:\(([^)]*)\))?/g, (_, id, pattern) => `(?<${id}>${pattern || "[^/]+"})`).replace(/(^|[^\\])\((?![?<])/g, (_, p) => `${p}(?<${toRegExpUnnamedKey(idCtr++)}>`).replace(/\./g, "\\."))); | ||
| } else reSegments.push(segment.replace(/\\(.)/g, "$1").replace(/[.*+?^${}()|[\]]/g, "\\$&")); | ||
| } | ||
| return new RegExp(`^/${reSegments.join("/")}/?$`); | ||
| } | ||
| function toRegExpUnnamedKey(index) { | ||
| return `_${index}`; | ||
| } | ||
| //#endregion | ||
| //#region ../../node_modules/.pnpm/h3@2.0.1-rc.16_crossws@0.4.4_srvx@0.11.9_/node_modules/h3/dist/h3-ByfIX5Jk.mjs | ||
| const kEventNS = "h3.internal.event."; | ||
| const kEventRes = /* @__PURE__ */ Symbol.for(`${kEventNS}res`); | ||
| const kEventResHeaders = /* @__PURE__ */ Symbol.for(`${kEventNS}res.headers`); | ||
| var H3Event = class { | ||
| app; | ||
| req; | ||
| url; | ||
| context; | ||
| static __is_event__ = true; | ||
| constructor(req, context, app) { | ||
| this.context = context || req.context || new NullProtoObj(); | ||
| this.req = req; | ||
| this.app = app; | ||
| const _url = req._url; | ||
| this.url = _url && _url instanceof URL ? _url : new FastURL(req.url); | ||
| } | ||
| get res() { | ||
| return this[kEventRes] ||= new H3EventResponse(); | ||
| } | ||
| get runtime() { | ||
| return this.req.runtime; | ||
| } | ||
| waitUntil(promise) { | ||
| this.req.waitUntil?.(promise); | ||
| } | ||
| toString() { | ||
| return `[${this.req.method}] ${this.req.url}`; | ||
| } | ||
| toJSON() { | ||
| return this.toString(); | ||
| } | ||
| get node() { | ||
| return this.req.runtime?.node; | ||
| } | ||
| get headers() { | ||
| return this.req.headers; | ||
| } | ||
| get path() { | ||
| return this.url.pathname + this.url.search; | ||
| } | ||
| get method() { | ||
| return this.req.method; | ||
| } | ||
| }; | ||
| var H3EventResponse = class { | ||
| status; | ||
| statusText; | ||
| get headers() { | ||
| return this[kEventResHeaders] ||= new Headers(); | ||
| } | ||
| }; | ||
| 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 = +statusCode; | ||
| if (statusCode < 100 || statusCode > 599) return defaultStatusCode; | ||
| return statusCode; | ||
| } | ||
| var HTTPError = class HTTPError extends Error { | ||
| get name() { | ||
| return "HTTPError"; | ||
| } | ||
| status; | ||
| statusText; | ||
| headers; | ||
| cause; | ||
| data; | ||
| body; | ||
| unhandled; | ||
| static isError(input) { | ||
| return input instanceof Error && input?.name === "HTTPError"; | ||
| } | ||
| static status(status, statusText, details) { | ||
| return new HTTPError({ | ||
| ...details, | ||
| statusText, | ||
| status | ||
| }); | ||
| } | ||
| constructor(arg1, arg2) { | ||
| let messageInput; | ||
| let details; | ||
| if (typeof arg1 === "string") { | ||
| messageInput = arg1; | ||
| details = arg2; | ||
| } else details = arg1; | ||
| const status = sanitizeStatusCode(details?.status || (details?.cause)?.status || details?.status || details?.statusCode, 500); | ||
| const statusText = sanitizeStatusMessage(details?.statusText || (details?.cause)?.statusText || details?.statusText || details?.statusMessage); | ||
| const message = messageInput || details?.message || (details?.cause)?.message || details?.statusText || details?.statusMessage || [ | ||
| "HTTPError", | ||
| status, | ||
| statusText | ||
| ].filter(Boolean).join(" "); | ||
| super(message, { cause: details }); | ||
| this.cause = details; | ||
| this.status = status; | ||
| this.statusText = statusText || void 0; | ||
| const rawHeaders = details?.headers || (details?.cause)?.headers; | ||
| this.headers = rawHeaders ? new Headers(rawHeaders) : void 0; | ||
| this.unhandled = details?.unhandled ?? (details?.cause)?.unhandled ?? void 0; | ||
| this.data = details?.data; | ||
| this.body = details?.body; | ||
| } | ||
| get statusCode() { | ||
| return this.status; | ||
| } | ||
| get statusMessage() { | ||
| return this.statusText; | ||
| } | ||
| toJSON() { | ||
| const unhandled = this.unhandled; | ||
| return { | ||
| status: this.status, | ||
| statusText: this.statusText, | ||
| unhandled, | ||
| message: unhandled ? "HTTPError" : this.message, | ||
| data: unhandled ? void 0 : this.data, | ||
| ...unhandled ? void 0 : this.body | ||
| }; | ||
| } | ||
| }; | ||
| function isJSONSerializable(value, _type) { | ||
| if (value === null || value === void 0) return true; | ||
| if (_type !== "object") return _type === "boolean" || _type === "number" || _type === "string"; | ||
| if (typeof value.toJSON === "function") return true; | ||
| if (Array.isArray(value)) return true; | ||
| if (typeof value.pipe === "function" || typeof value.pipeTo === "function") return false; | ||
| if (value instanceof NullProtoObj) return true; | ||
| const proto = Object.getPrototypeOf(value); | ||
| return proto === Object.prototype || proto === null; | ||
| } | ||
| const kNotFound = /* @__PURE__ */ Symbol.for("h3.notFound"); | ||
| const kHandled = /* @__PURE__ */ Symbol.for("h3.handled"); | ||
| function toResponse(val, event, config = {}) { | ||
| if (typeof val?.then === "function") return (val.catch?.((error) => error) || Promise.resolve(val)).then((resolvedVal) => toResponse(resolvedVal, event, config)); | ||
| const response = prepareResponse(val, event, config); | ||
| if (typeof response?.then === "function") return toResponse(response, event, config); | ||
| const { onResponse } = config; | ||
| return onResponse ? Promise.resolve(onResponse(response, event)).then(() => response) : response; | ||
| } | ||
| var HTTPResponse = class { | ||
| #headers; | ||
| #init; | ||
| body; | ||
| constructor(body, init) { | ||
| this.body = body; | ||
| this.#init = init; | ||
| } | ||
| get status() { | ||
| return this.#init?.status || 200; | ||
| } | ||
| get statusText() { | ||
| return this.#init?.statusText || "OK"; | ||
| } | ||
| get headers() { | ||
| return this.#headers ||= new Headers(this.#init?.headers); | ||
| } | ||
| }; | ||
| function prepareResponse(val, event, config, nested) { | ||
| if (val === kHandled) return new FastResponse(null); | ||
| if (val === kNotFound) val = new HTTPError({ | ||
| status: 404, | ||
| message: `Cannot find any route matching [${event.req.method}] ${event.url}` | ||
| }); | ||
| if (val && val instanceof Error) { | ||
| const isHTTPError = HTTPError.isError(val); | ||
| const error = isHTTPError ? val : new HTTPError(val); | ||
| if (!isHTTPError) { | ||
| error.unhandled = true; | ||
| if (val?.stack) error.stack = val.stack; | ||
| } | ||
| if (error.unhandled && !config.silent) console.error(error); | ||
| const { onError } = config; | ||
| return onError && !nested ? Promise.resolve(onError(error, event)).catch((error) => error).then((newVal) => prepareResponse(newVal ?? val, event, config, true)) : errorResponse(error, config.debug); | ||
| } | ||
| const preparedRes = event[kEventRes]; | ||
| const preparedHeaders = preparedRes?.[kEventResHeaders]; | ||
| event[kEventRes] = void 0; | ||
| if (!(val instanceof Response)) { | ||
| const res = prepareResponseBody(val, event, config); | ||
| const status = res.status || preparedRes?.status; | ||
| return new FastResponse(nullBody(event.req.method, status) ? null : res.body, { | ||
| status, | ||
| statusText: res.statusText || preparedRes?.statusText, | ||
| headers: res.headers && preparedHeaders ? mergeHeaders$1(res.headers, preparedHeaders) : res.headers || preparedHeaders | ||
| }); | ||
| } | ||
| if (!preparedHeaders || nested || !val.ok) return val; | ||
| try { | ||
| mergeHeaders$1(val.headers, preparedHeaders, val.headers); | ||
| return val; | ||
| } catch { | ||
| return new FastResponse(nullBody(event.req.method, val.status) ? null : val.body, { | ||
| status: val.status, | ||
| statusText: val.statusText, | ||
| headers: mergeHeaders$1(val.headers, preparedHeaders) | ||
| }); | ||
| } | ||
| } | ||
| function mergeHeaders$1(base, overrides, target = new Headers(base)) { | ||
| for (const [name, value] of overrides) if (name === "set-cookie") target.append(name, value); | ||
| else target.set(name, value); | ||
| return target; | ||
| } | ||
| const frozen = (name) => (...args) => { | ||
| throw new Error(`Headers are frozen (${name} ${args.join(", ")})`); | ||
| }; | ||
| var FrozenHeaders = class extends Headers { | ||
| set = frozen("set"); | ||
| append = frozen("append"); | ||
| delete = frozen("delete"); | ||
| }; | ||
| const emptyHeaders = /* @__PURE__ */ new FrozenHeaders({ "content-length": "0" }); | ||
| const jsonHeaders = /* @__PURE__ */ new FrozenHeaders({ "content-type": "application/json;charset=UTF-8" }); | ||
| function prepareResponseBody(val, event, config) { | ||
| if (val === null || val === void 0) return { | ||
| body: "", | ||
| headers: emptyHeaders | ||
| }; | ||
| const valType = typeof val; | ||
| if (valType === "string") return { body: val }; | ||
| if (val instanceof Uint8Array) { | ||
| event.res.headers.set("content-length", val.byteLength.toString()); | ||
| return { body: val }; | ||
| } | ||
| if (val instanceof HTTPResponse || val?.constructor?.name === "HTTPResponse") return val; | ||
| if (isJSONSerializable(val, valType)) return { | ||
| body: JSON.stringify(val, void 0, config.debug ? 2 : void 0), | ||
| headers: jsonHeaders | ||
| }; | ||
| if (valType === "bigint") return { | ||
| body: val.toString(), | ||
| headers: jsonHeaders | ||
| }; | ||
| if (val instanceof Blob) { | ||
| const headers = new Headers({ | ||
| "content-type": val.type, | ||
| "content-length": val.size.toString() | ||
| }); | ||
| let filename = val.name; | ||
| if (filename) { | ||
| filename = encodeURIComponent(filename); | ||
| headers.set("content-disposition", `filename="${filename}"; filename*=UTF-8''${filename}`); | ||
| } | ||
| return { | ||
| body: val.stream(), | ||
| headers | ||
| }; | ||
| } | ||
| if (valType === "symbol") return { body: val.toString() }; | ||
| if (valType === "function") return { body: `${val.name}()` }; | ||
| return { body: val }; | ||
| } | ||
| function nullBody(method, status) { | ||
| return method === "HEAD" || status === 100 || status === 101 || status === 102 || status === 204 || status === 205 || status === 304; | ||
| } | ||
| function errorResponse(error, debug) { | ||
| return new FastResponse(JSON.stringify({ | ||
| ...error.toJSON(), | ||
| stack: debug && error.stack ? error.stack.split("\n").map((l) => l.trim()) : void 0 | ||
| }, void 0, debug ? 2 : void 0), { | ||
| status: error.status, | ||
| statusText: error.statusText, | ||
| headers: error.headers ? mergeHeaders$1(jsonHeaders, error.headers) : new Headers(jsonHeaders) | ||
| }); | ||
| } | ||
| function normalizeMiddleware(input, opts = {}) { | ||
| const matcher = createMatcher(opts); | ||
| if (!matcher && (input.length > 1 || input.constructor?.name === "AsyncFunction")) return input; | ||
| return (event, next) => { | ||
| if (matcher && !matcher(event)) return next(); | ||
| const res = input(event, next); | ||
| return res === void 0 || res === kNotFound ? next() : res; | ||
| }; | ||
| } | ||
| function createMatcher(opts) { | ||
| if (!opts.route && !opts.method && !opts.match) return; | ||
| const routeMatcher = opts.route ? routeToRegExp(opts.route) : void 0; | ||
| const method = opts.method?.toUpperCase(); | ||
| return function _middlewareMatcher(event) { | ||
| if (method && event.req.method !== method) return false; | ||
| if (opts.match && !opts.match(event)) return false; | ||
| if (!routeMatcher) return true; | ||
| const match = event.url.pathname.match(routeMatcher); | ||
| if (!match) return false; | ||
| if (match.groups) event.context.middlewareParams = { | ||
| ...event.context.middlewareParams, | ||
| ...match.groups | ||
| }; | ||
| return true; | ||
| }; | ||
| } | ||
| function callMiddleware(event, middleware, handler, index = 0) { | ||
| if (index === middleware.length) return handler(event); | ||
| const fn = middleware[index]; | ||
| let nextCalled; | ||
| let nextResult; | ||
| const next = () => { | ||
| if (nextCalled) return nextResult; | ||
| nextCalled = true; | ||
| nextResult = callMiddleware(event, middleware, handler, index + 1); | ||
| return nextResult; | ||
| }; | ||
| const ret = fn(event, next); | ||
| return isUnhandledResponse(ret) ? next() : typeof ret?.then === "function" ? ret.then((resolved) => isUnhandledResponse(resolved) ? next() : resolved) : ret; | ||
| } | ||
| function isUnhandledResponse(val) { | ||
| return val === void 0 || val === kNotFound; | ||
| } | ||
| function toRequest(input, options) { | ||
| if (typeof input === "string") { | ||
| let url = input; | ||
| if (url[0] === "/") { | ||
| const headers = options?.headers ? new Headers(options.headers) : void 0; | ||
| const host = headers?.get("host") || "localhost"; | ||
| url = `${headers?.get("x-forwarded-proto") === "https" ? "https" : "http"}://${host}${url}`; | ||
| } | ||
| return new Request(url, options); | ||
| } else if (options || input instanceof URL) return new Request(input, options); | ||
| return input; | ||
| } | ||
| function defineHandler(input) { | ||
| if (typeof input === "function") return handlerWithFetch(input); | ||
| const handler = input.handler || (input.fetch ? function _fetchHandler(event) { | ||
| return input.fetch(event.req); | ||
| } : NoHandler); | ||
| return Object.assign(handlerWithFetch(input.middleware?.length ? function _handlerMiddleware(event) { | ||
| return callMiddleware(event, input.middleware, handler); | ||
| } : handler), input); | ||
| } | ||
| function handlerWithFetch(handler) { | ||
| if ("fetch" in handler) return handler; | ||
| return Object.assign(handler, { fetch: (req) => { | ||
| if (typeof req === "string") req = new URL(req, "http://_"); | ||
| if (req instanceof URL) req = new Request(req); | ||
| const event = new H3Event(req); | ||
| try { | ||
| return Promise.resolve(toResponse(handler(event), event)); | ||
| } catch (error) { | ||
| return Promise.resolve(toResponse(error, event)); | ||
| } | ||
| } }); | ||
| } | ||
| function defineLazyEventHandler(loader) { | ||
| let handler; | ||
| let promise; | ||
| return defineHandler(function lazyHandler(event) { | ||
| return handler ? handler(event) : (promise ??= Promise.resolve(loader()).then(function resolveLazyHandler(r) { | ||
| handler = toEventHandler(r) || toEventHandler(r.default); | ||
| if (typeof handler !== "function") throw new TypeError("Invalid lazy handler", { cause: { resolved: r } }); | ||
| return handler; | ||
| })).then((r) => r(event)); | ||
| }); | ||
| } | ||
| function toEventHandler(handler) { | ||
| if (typeof handler === "function") return handler; | ||
| if (typeof handler?.handler === "function") return handler.handler; | ||
| if (typeof handler?.fetch === "function") return function _fetchHandler(event) { | ||
| return handler.fetch(event.req); | ||
| }; | ||
| } | ||
| const NoHandler = () => kNotFound; | ||
| var H3Core = class { | ||
| config; | ||
| "~middleware"; | ||
| "~routes" = []; | ||
| constructor(config = {}) { | ||
| this["~middleware"] = []; | ||
| this.config = config; | ||
| this.fetch = this.fetch.bind(this); | ||
| this.handler = this.handler.bind(this); | ||
| } | ||
| fetch(request) { | ||
| return this["~request"](request); | ||
| } | ||
| handler(event) { | ||
| const route = this["~findRoute"](event); | ||
| if (route) { | ||
| event.context.params = route.params; | ||
| event.context.matchedRoute = route.data; | ||
| } | ||
| const routeHandler = route?.data.handler || NoHandler; | ||
| const middleware = this["~getMiddleware"](event, route); | ||
| return middleware.length > 0 ? callMiddleware(event, middleware, routeHandler) : routeHandler(event); | ||
| } | ||
| "~request"(request, context) { | ||
| const event = new H3Event(request, context, this); | ||
| let handlerRes; | ||
| try { | ||
| if (this.config.onRequest) { | ||
| const hookRes = this.config.onRequest(event); | ||
| handlerRes = typeof hookRes?.then === "function" ? hookRes.then(() => this.handler(event)) : this.handler(event); | ||
| } else handlerRes = this.handler(event); | ||
| } catch (error) { | ||
| handlerRes = Promise.reject(error); | ||
| } | ||
| return toResponse(handlerRes, event, this.config); | ||
| } | ||
| "~findRoute"(_event) {} | ||
| "~addRoute"(_route) { | ||
| this["~routes"].push(_route); | ||
| } | ||
| "~getMiddleware"(_event, route) { | ||
| const routeMiddleware = route?.data.middleware; | ||
| const globalMiddleware = this["~middleware"]; | ||
| return routeMiddleware ? [...globalMiddleware, ...routeMiddleware] : globalMiddleware; | ||
| } | ||
| }; | ||
| const H3 = /* @__PURE__ */ (() => { | ||
| class H3 extends H3Core { | ||
| "~rou3"; | ||
| constructor(config = {}) { | ||
| super(config); | ||
| this["~rou3"] = createRouter(); | ||
| this.request = this.request.bind(this); | ||
| config.plugins?.forEach((plugin) => plugin(this)); | ||
| } | ||
| register(plugin) { | ||
| plugin(this); | ||
| return this; | ||
| } | ||
| request(_req, _init, context) { | ||
| return this["~request"](toRequest(_req, _init), context); | ||
| } | ||
| mount(base, input) { | ||
| if ("handler" in input) { | ||
| if (input["~middleware"].length > 0) this["~middleware"].push((event, next) => { | ||
| const originalPathname = event.url.pathname; | ||
| if (!originalPathname.startsWith(base)) return next(); | ||
| event.url.pathname = event.url.pathname.slice(base.length) || "/"; | ||
| return callMiddleware(event, input["~middleware"], () => { | ||
| event.url.pathname = originalPathname; | ||
| return next(); | ||
| }); | ||
| }); | ||
| for (const r of input["~routes"]) this["~addRoute"]({ | ||
| ...r, | ||
| route: base + r.route | ||
| }); | ||
| } else { | ||
| const fetchHandler = "fetch" in input ? input.fetch : input; | ||
| this.all(`${base}/**`, function _mountedMiddleware(event) { | ||
| const url = new URL(event.url); | ||
| url.pathname = url.pathname.slice(base.length) || "/"; | ||
| return fetchHandler(new Request(url, event.req)); | ||
| }); | ||
| } | ||
| return this; | ||
| } | ||
| on(method, route, handler, opts) { | ||
| const _method = (method || "").toUpperCase(); | ||
| route = new URL(route, "http://_").pathname; | ||
| this["~addRoute"]({ | ||
| method: _method, | ||
| route, | ||
| handler: toEventHandler(handler), | ||
| middleware: opts?.middleware, | ||
| meta: { | ||
| ...handler.meta, | ||
| ...opts?.meta | ||
| } | ||
| }); | ||
| return this; | ||
| } | ||
| all(route, handler, opts) { | ||
| return this.on("", route, handler, opts); | ||
| } | ||
| "~findRoute"(_event) { | ||
| return findRoute(this["~rou3"], _event.req.method, _event.url.pathname); | ||
| } | ||
| "~addRoute"(_route) { | ||
| addRoute(this["~rou3"], _route.method, _route.route, _route); | ||
| super["~addRoute"](_route); | ||
| } | ||
| use(arg1, arg2, arg3) { | ||
| let route; | ||
| let fn; | ||
| let opts; | ||
| if (typeof arg1 === "string") { | ||
| route = arg1; | ||
| fn = arg2; | ||
| opts = arg3; | ||
| } else { | ||
| fn = arg1; | ||
| opts = arg2; | ||
| } | ||
| this["~middleware"].push(normalizeMiddleware(fn, { | ||
| ...opts, | ||
| route | ||
| })); | ||
| return this; | ||
| } | ||
| } | ||
| for (const method of [ | ||
| "GET", | ||
| "POST", | ||
| "PUT", | ||
| "DELETE", | ||
| "PATCH", | ||
| "HEAD", | ||
| "OPTIONS", | ||
| "CONNECT", | ||
| "TRACE" | ||
| ]) H3Core.prototype[method.toLowerCase()] = function(route, handler, opts) { | ||
| return this.on(method, route, handler, opts); | ||
| }; | ||
| return H3; | ||
| })(); | ||
| const _textEncoder = new TextEncoder(); | ||
| const lazyEventHandler = defineLazyEventHandler; | ||
| //#endregion | ||
| //#region ../nuxi/src/commands/analyze.ts | ||
| const NON_WORD_RE = /[^\w-]/g; | ||
| const indexHtml = ` | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="utf-8"> | ||
| <title>Nuxt Bundle Stats (experimental)</title> | ||
| </head> | ||
| <h1>Nuxt Bundle Stats (experimental)</h1> | ||
| <ul> | ||
| <li> | ||
| <a href="/nitro">Nitro server bundle stats</a> | ||
| </li> | ||
| <li> | ||
| <a href="/client">Client bundle stats</a> | ||
| </li> | ||
| </ul> | ||
| </html> | ||
| `.trim(); | ||
| var analyze_default = defineCommand({ | ||
| meta: { | ||
| name: "analyze", | ||
| description: "Build Nuxt and analyze production bundle (experimental)" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...legacyRootDirArgs, | ||
| ...dotEnvArgs, | ||
| ...extendsArgs, | ||
| name: { | ||
| type: "string", | ||
| description: "Name of the analysis", | ||
| default: "default", | ||
| valueHint: "name" | ||
| }, | ||
| serve: { | ||
| type: "boolean", | ||
| description: "Serve the analysis results", | ||
| negativeDescription: "Skip serving the analysis results", | ||
| default: true | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| overrideEnv("production"); | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const name = ctx.args.name || "default"; | ||
| const slug = name.trim().replace(NON_WORD_RE, "_"); | ||
| intro(colors.cyan("Analyzing bundle size...")); | ||
| const startTime = Date.now(); | ||
| const { loadNuxt, buildNuxt } = await loadKit(cwd); | ||
| const nuxt = await loadNuxt({ | ||
| cwd, | ||
| dotenv: { | ||
| cwd, | ||
| fileName: ctx.args.dotenv | ||
| }, | ||
| overrides: defu$1(ctx.data?.overrides, { | ||
| ...ctx.args.extends && { extends: ctx.args.extends }, | ||
| build: { analyze: { enabled: true } }, | ||
| vite: { build: { rollupOptions: { output: { | ||
| chunkFileNames: "_nuxt/[name].js", | ||
| entryFileNames: "_nuxt/[name].js" | ||
| } } } }, | ||
| logLevel: ctx.args.logLevel | ||
| }) | ||
| }); | ||
| const analyzeDir = nuxt.options.analyzeDir; | ||
| const buildDir = nuxt.options.buildDir; | ||
| const outDir = nuxt.options.nitro.output?.dir || join(nuxt.options.rootDir, ".output"); | ||
| nuxt.options.build.analyze = defu$1(nuxt.options.build.analyze, { filename: join(analyzeDir, "client.html") }); | ||
| const tasklog = taskLog({ | ||
| title: "Building Nuxt with analysis enabled", | ||
| retainLog: false, | ||
| limit: 1 | ||
| }); | ||
| tasklog.message("Clearing analyze directory..."); | ||
| await clearDir(analyzeDir); | ||
| tasklog.message("Building Nuxt..."); | ||
| await buildNuxt(nuxt); | ||
| tasklog.success("Build complete"); | ||
| const meta = { | ||
| name, | ||
| slug, | ||
| startTime, | ||
| endTime: Date.now(), | ||
| analyzeDir, | ||
| buildDir, | ||
| outDir | ||
| }; | ||
| await nuxt.callHook("build:analyze:done", meta); | ||
| await promises.writeFile(join(analyzeDir, "meta.json"), JSON.stringify(meta, null, 2), "utf-8"); | ||
| note(`${relativeToProcess(analyzeDir)}\n\nDo not deploy analyze results! Use ${colors.cyan("nuxt build")} before deploying.`, "Build location"); | ||
| if (ctx.args.serve !== false && !process.env.CI) { | ||
| const app = new H3(); | ||
| const opts = { headers: { "content-type": "text/html" } }; | ||
| const serveFile = (filePath) => lazyEventHandler(async () => { | ||
| const contents = await promises.readFile(filePath, "utf-8"); | ||
| return () => new Response(contents, opts); | ||
| }); | ||
| logger.step("Starting stats server..."); | ||
| app.use("/client", serveFile(join(analyzeDir, "client.html"))); | ||
| app.use("/nitro", serveFile(join(analyzeDir, "nitro.html"))); | ||
| app.use(() => new Response(indexHtml, opts)); | ||
| await serve(app).serve(); | ||
| } else outro("✨ Analysis build complete!"); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { analyze_default as default }; |
| //#region ../nuxi/src/utils/ascii.ts | ||
| /** | ||
| * Thank you to IndyJoenz for this ASCII art | ||
| * https://bsky.app/profile/durdraw.org/post/3liadod3gv22a | ||
| */ | ||
| const themeColor = "\x1B[38;2;0;220;130m"; | ||
| const icon = [ | ||
| ` .d$b.`, | ||
| ` i$$A$$L .d$b`, | ||
| ` .$$F\` \`$$L.$$A$$.`, | ||
| ` j$$' \`4$$:\` \`$$.`, | ||
| ` j$$' .4$: \`$$.`, | ||
| ` j$$\` .$$: \`4$L`, | ||
| ` :$$:____.d$$: _____.:$$:`, | ||
| ` \`4$$$$$$$$P\` .i$$$$$$$$P\`` | ||
| ]; | ||
| const nuxtIcon = icon.map((line) => line.split("").join(themeColor)).join("\n"); | ||
| //#endregion | ||
| export { themeColor as n, nuxtIcon as t }; |
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import { n as getPkgJSON, r as getPkgVersion } from "./versions-Bg99eDSc.mjs"; | ||
| import { colors } from "consola/utils"; | ||
| //#region ../nuxi/src/utils/banner.ts | ||
| function getBuilder(cwd, builder) { | ||
| switch (builder) { | ||
| case "rspack": | ||
| case "@nuxt/rspack-builder": return { | ||
| name: "Rspack", | ||
| version: getPkgVersion(cwd, "@rspack/core") | ||
| }; | ||
| case "webpack": | ||
| case "@nuxt/webpack-builder": return { | ||
| name: "Webpack", | ||
| version: getPkgVersion(cwd, "webpack") | ||
| }; | ||
| default: { | ||
| const pkgJSON = getPkgJSON(cwd, "vite"); | ||
| return { | ||
| name: pkgJSON.name.includes("rolldown") ? "Rolldown-Vite" : "Vite", | ||
| version: pkgJSON.version | ||
| }; | ||
| } | ||
| } | ||
| } | ||
| function showVersionsFromConfig(cwd, config) { | ||
| const { bold, gray, green } = colors; | ||
| const nuxtVersion = getPkgVersion(cwd, "nuxt") || getPkgVersion(cwd, "nuxt-nightly") || getPkgVersion(cwd, "nuxt3") || getPkgVersion(cwd, "nuxt-edge"); | ||
| const nitroVersion = getPkgVersion(cwd, "nitropack") || getPkgVersion(cwd, "nitro") || getPkgVersion(cwd, "nitropack-nightly") || getPkgVersion(cwd, "nitropack-edge"); | ||
| const builder = getBuilder(cwd, config.builder); | ||
| const vueVersion = getPkgVersion(cwd, "vue") || null; | ||
| logger.info(green(`Nuxt ${bold(nuxtVersion)}`) + gray(" (with ") + (nitroVersion ? gray(`Nitro ${bold(nitroVersion)}`) : "") + gray(`, ${builder.name} ${bold(builder.version)}`) + (vueVersion ? gray(` and Vue ${bold(vueVersion)}`) : "") + gray(")")); | ||
| } | ||
| async function showVersions(cwd, kit, dotenv) { | ||
| return showVersionsFromConfig(cwd, await kit.loadNuxtConfig({ | ||
| cwd, | ||
| dotenv: dotenv ? { | ||
| cwd, | ||
| fileName: dotenv | ||
| } : void 0 | ||
| })); | ||
| } | ||
| //#endregion | ||
| export { showVersions as n, showVersionsFromConfig as r, getBuilder as t }; |
| import "./_shared-BsGoKfo3.mjs"; | ||
| import "./logger-B4ge7MhP.mjs"; | ||
| import "./env-BRiVSJMz.mjs"; | ||
| import "./ascii-AoH-yOf6.mjs"; | ||
| import "./profile-q-JV7Qxl.mjs"; | ||
| import "./kit-DUlGqV3Z.mjs"; | ||
| import "./versions-Bg99eDSc.mjs"; | ||
| import "./banner-C2vxTb-6.mjs"; | ||
| import "./fs-B8DrLsZ2.mjs"; | ||
| import { t as build_default } from "./dev-DmuOeJjt.mjs"; | ||
| export { build_default as default }; |
| import { a as legacyRootDirArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import { t as loadKit } from "./kit-DUlGqV3Z.mjs"; | ||
| import "./fs-B8DrLsZ2.mjs"; | ||
| import { t as cleanupNuxtDirs } from "./nuxt-CsZm8Jhw.mjs"; | ||
| import { defineCommand } from "citty"; | ||
| import { resolve } from "pathe"; | ||
| //#region ../nuxi/src/commands/cleanup.ts | ||
| var cleanup_default = defineCommand({ | ||
| meta: { | ||
| name: "cleanup", | ||
| description: "Clean up generated Nuxt files and caches" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const { loadNuxtConfig } = await loadKit(cwd); | ||
| const nuxtOptions = await loadNuxtConfig({ | ||
| cwd, | ||
| overrides: { dev: true } | ||
| }); | ||
| await cleanupNuxtDirs(nuxtOptions.rootDir, nuxtOptions.buildDir); | ||
| logger.success("Cleanup complete!"); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { cleanup_default as default }; |
| import { a as legacyRootDirArgs, n as dotEnvArgs, o as logLevelArgs, r as envNameArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { isTest } from "std-env"; | ||
| import { resolve } from "pathe"; | ||
| //#region ../nuxi/src/commands/dev-child.ts | ||
| var dev_child_default = defineCommand({ | ||
| meta: { | ||
| name: "_dev", | ||
| description: "Run Nuxt development server (internal command to start child process)" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...envNameArgs, | ||
| ...dotEnvArgs, | ||
| ...legacyRootDirArgs, | ||
| clear: { | ||
| type: "boolean", | ||
| description: "Clear console on restart", | ||
| negativeDescription: "Disable clear console on restart" | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| if (!process.send && !isTest) console.warn("`nuxi _dev` is an internal command and should not be used directly. Please use `nuxi dev` instead."); | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const { initialize } = await import("./dev-DmuOeJjt.mjs"); | ||
| await initialize({ | ||
| cwd, | ||
| args: ctx.args | ||
| }, ctx); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { dev_child_default as default }; |
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, r as envNameArgs, s as profileArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger, t as debug } from "./logger-B4ge7MhP.mjs"; | ||
| import "./env-BRiVSJMz.mjs"; | ||
| import "./ascii-AoH-yOf6.mjs"; | ||
| import "./profile-q-JV7Qxl.mjs"; | ||
| import { t as initialize } from "./dev-D5McAnmo.mjs"; | ||
| import "./kit-DUlGqV3Z.mjs"; | ||
| import "./versions-Bg99eDSc.mjs"; | ||
| import "./banner-C2vxTb-6.mjs"; | ||
| import "./fs-B8DrLsZ2.mjs"; | ||
| import "./nuxt-CsZm8Jhw.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { isBun, isDeno, isTest } from "std-env"; | ||
| import { resolve } from "pathe"; | ||
| import { satisfies } from "semver"; | ||
| import { getArgs, parseArgs } from "listhen/cli"; | ||
| import { fork } from "node:child_process"; | ||
| //#region ../nuxi/src/dev/pool.ts | ||
| var ForkPool = class { | ||
| pool = []; | ||
| poolSize; | ||
| rawArgs; | ||
| listenOverrides; | ||
| warming = false; | ||
| constructor(options) { | ||
| this.rawArgs = options.rawArgs; | ||
| this.poolSize = options.poolSize ?? 2; | ||
| this.listenOverrides = options.listenOverrides; | ||
| for (const signal of [ | ||
| "exit", | ||
| "SIGTERM", | ||
| "SIGINT", | ||
| "SIGQUIT" | ||
| ]) process.once(signal, () => { | ||
| this.killAll(signal === "exit" ? 0 : signal); | ||
| }); | ||
| } | ||
| startWarming() { | ||
| if (this.warming) return; | ||
| this.warming = true; | ||
| for (let i = 0; i < this.poolSize; i++) this.warmFork(); | ||
| } | ||
| async getFork(context, onMessage) { | ||
| const readyFork = this.pool.find((f) => f.state === "ready"); | ||
| if (readyFork) { | ||
| readyFork.state = "active"; | ||
| if (onMessage) this.attachMessageHandler(readyFork.process, onMessage); | ||
| await this.sendContext(readyFork.process, context); | ||
| if (this.warming) this.warmFork(); | ||
| return () => this.killFork(readyFork); | ||
| } | ||
| const warmingFork = this.pool.find((f) => f.state === "warming"); | ||
| if (warmingFork) { | ||
| await warmingFork.ready; | ||
| warmingFork.state = "active"; | ||
| if (onMessage) this.attachMessageHandler(warmingFork.process, onMessage); | ||
| await this.sendContext(warmingFork.process, context); | ||
| if (this.warming) this.warmFork(); | ||
| return () => this.killFork(warmingFork); | ||
| } | ||
| debug("No pre-warmed forks available, starting cold fork"); | ||
| const coldFork = this.createFork(); | ||
| await coldFork.ready; | ||
| coldFork.state = "active"; | ||
| if (onMessage) this.attachMessageHandler(coldFork.process, onMessage); | ||
| await this.sendContext(coldFork.process, context); | ||
| return () => this.killFork(coldFork); | ||
| } | ||
| attachMessageHandler(childProc, onMessage) { | ||
| childProc.on("message", (message) => { | ||
| if (message.type !== "nuxt:internal:dev:fork-ready") onMessage(message); | ||
| }); | ||
| } | ||
| warmFork() { | ||
| const fork = this.createFork(); | ||
| fork.ready.then(() => { | ||
| if (fork.state === "warming") fork.state = "ready"; | ||
| }).catch(() => { | ||
| this.removeFork(fork); | ||
| }); | ||
| this.pool.push(fork); | ||
| } | ||
| createFork() { | ||
| const childProc = fork(globalThis.__nuxt_cli__.devEntry, this.rawArgs, { | ||
| execArgv: ["--enable-source-maps", process.argv.find((a) => a.includes("--inspect"))].filter(Boolean), | ||
| env: { | ||
| ...process.env, | ||
| __NUXT__FORK: "true" | ||
| } | ||
| }); | ||
| let readyResolve; | ||
| let readyReject; | ||
| const pooledFork = { | ||
| process: childProc, | ||
| ready: new Promise((resolve, reject) => { | ||
| readyResolve = resolve; | ||
| readyReject = reject; | ||
| }), | ||
| state: "warming" | ||
| }; | ||
| childProc.on("message", (message) => { | ||
| if (message.type === "nuxt:internal:dev:fork-ready") readyResolve(); | ||
| }); | ||
| childProc.on("error", (err) => { | ||
| readyReject(err); | ||
| this.removeFork(pooledFork); | ||
| }); | ||
| childProc.on("close", (errorCode) => { | ||
| if (pooledFork.state === "active" && errorCode) process.exit(errorCode); | ||
| this.removeFork(pooledFork); | ||
| }); | ||
| return pooledFork; | ||
| } | ||
| async sendContext(childProc, context) { | ||
| childProc.send({ | ||
| type: "nuxt:internal:dev:context", | ||
| listenOverrides: this.listenOverrides, | ||
| context | ||
| }); | ||
| } | ||
| killFork(fork, signal = "SIGTERM") { | ||
| fork.state = "dead"; | ||
| if (fork.process) fork.process.kill(signal === 0 && isDeno ? "SIGTERM" : signal); | ||
| this.removeFork(fork); | ||
| } | ||
| removeFork(fork) { | ||
| const index = this.pool.indexOf(fork); | ||
| if (index > -1) this.pool.splice(index, 1); | ||
| } | ||
| killAll(signal) { | ||
| for (const fork of this.pool) this.killFork(fork, signal); | ||
| } | ||
| getStats() { | ||
| return { | ||
| total: this.pool.length, | ||
| warming: this.pool.filter((f) => f.state === "warming").length, | ||
| ready: this.pool.filter((f) => f.state === "ready").length, | ||
| active: this.pool.filter((f) => f.state === "active").length | ||
| }; | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region ../nuxi/src/commands/dev.ts | ||
| const startTime = Date.now(); | ||
| const forkSupported = !isTest && (!isBun || isBunForkSupported()); | ||
| const listhenArgs = getArgs(); | ||
| const command = defineCommand({ | ||
| meta: { | ||
| name: "dev", | ||
| description: "Run Nuxt development server" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...dotEnvArgs, | ||
| ...legacyRootDirArgs, | ||
| ...envNameArgs, | ||
| ...extendsArgs, | ||
| clear: { | ||
| type: "boolean", | ||
| description: "Clear console on restart", | ||
| default: false | ||
| }, | ||
| fork: { | ||
| type: "boolean", | ||
| description: forkSupported ? "Disable forked mode" : "Enable forked mode", | ||
| negativeDescription: "Disable forked mode", | ||
| default: forkSupported, | ||
| alias: ["f"] | ||
| }, | ||
| ...listhenArgs, | ||
| port: { | ||
| ...listhenArgs.port, | ||
| description: "Port to listen on (default: `NUXT_PORT || NITRO_PORT || PORT || nuxtOptions.devServer.port`)", | ||
| alias: ["p"] | ||
| }, | ||
| open: { | ||
| ...listhenArgs.open, | ||
| alias: ["o"], | ||
| default: false | ||
| }, | ||
| host: { | ||
| ...listhenArgs.host, | ||
| alias: ["h"], | ||
| description: "Host to listen on (default: `NUXT_HOST || NITRO_HOST || HOST || nuxtOptions.devServer?.host`)" | ||
| }, | ||
| clipboard: { | ||
| ...listhenArgs.clipboard, | ||
| default: false | ||
| }, | ||
| ...profileArgs, | ||
| sslCert: { | ||
| type: "string", | ||
| description: "(DEPRECATED) Use `--https.cert` instead." | ||
| }, | ||
| sslKey: { | ||
| type: "string", | ||
| description: "(DEPRECATED) Use `--https.key` instead." | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const listenOverrides = resolveListenOverrides(ctx.args); | ||
| const { listener, close, onRestart, onReady } = await initialize({ | ||
| cwd, | ||
| args: ctx.args | ||
| }, { | ||
| data: ctx.data, | ||
| listenOverrides, | ||
| showBanner: true | ||
| }); | ||
| if (!ctx.args.fork || ctx.args.profile) return { | ||
| listener, | ||
| close | ||
| }; | ||
| const pool = new ForkPool({ | ||
| rawArgs: ctx.rawArgs, | ||
| poolSize: 2, | ||
| listenOverrides | ||
| }); | ||
| onReady((_address) => { | ||
| pool.startWarming(); | ||
| if (startTime) debug(`Dev server ready for connections in ${Date.now() - startTime}ms`); | ||
| }); | ||
| let cleanupCurrentFork; | ||
| async function restartWithFork() { | ||
| const context = { | ||
| cwd, | ||
| args: ctx.args | ||
| }; | ||
| cleanupCurrentFork?.(); | ||
| cleanupCurrentFork = await pool.getFork(context, (message) => { | ||
| if (message.type === "nuxt:internal:dev:ready") { | ||
| if (startTime) debug(`Dev server ready for connections in ${Date.now() - startTime}ms`); | ||
| } else if (message.type === "nuxt:internal:dev:restart") restartWithFork(); | ||
| else if (message.type === "nuxt:internal:dev:rejection") { | ||
| logger.info(`Restarting Nuxt due to error: ${colors.cyan(message.message)}`); | ||
| restartWithFork(); | ||
| } | ||
| }); | ||
| } | ||
| onRestart(async () => { | ||
| await close(); | ||
| await restartWithFork(); | ||
| }); | ||
| return { async close() { | ||
| cleanupCurrentFork?.(); | ||
| await Promise.all([listener.close(), close()]); | ||
| } }; | ||
| } | ||
| }); | ||
| function resolveListenOverrides(args) { | ||
| if (process.env._PORT) return { | ||
| port: process.env._PORT || 0, | ||
| hostname: "127.0.0.1", | ||
| showURL: false | ||
| }; | ||
| const options = parseArgs({ | ||
| ...args, | ||
| "host": args.host || process.env.NUXT_HOST || process.env.NITRO_HOST || process.env.HOST, | ||
| "port": args.port || process.env.NUXT_PORT || process.env.NITRO_PORT || process.env.PORT, | ||
| "https": args.https !== false && args.https !== "false", | ||
| "https.cert": args["https.cert"] || args.sslCert || process.env.NUXT_SSL_CERT || process.env.NITRO_SSL_CERT, | ||
| "https.key": args["https.key"] || args.sslKey || process.env.NUXT_SSL_KEY || process.env.NITRO_SSL_KEY | ||
| }); | ||
| return { | ||
| ...options, | ||
| _https: args.https, | ||
| get https() { | ||
| const httpsArg = this._https; | ||
| if (httpsArg === false || httpsArg === "false") return false; | ||
| return httpsArg ? options.https : false; | ||
| } | ||
| }; | ||
| } | ||
| function isBunForkSupported() { | ||
| const bunVersion = globalThis.Bun.version; | ||
| return satisfies(bunVersion, ">=1.2"); | ||
| } | ||
| //#endregion | ||
| export { command as default }; |
| import { t as overrideEnv } from "./env-BRiVSJMz.mjs"; | ||
| import { n as stopCpuProfile, t as startCpuProfile } from "./profile-q-JV7Qxl.mjs"; | ||
| import { i as withNodePath, t as loadKit } from "./kit-DUlGqV3Z.mjs"; | ||
| import { r as showVersionsFromConfig } from "./banner-C2vxTb-6.mjs"; | ||
| import { t as clearBuildDir } from "./fs-B8DrLsZ2.mjs"; | ||
| import { a as writeNuxtManifest, i as resolveNuxtManifest, n as loadNuxtManifest } from "./nuxt-CsZm8Jhw.mjs"; | ||
| import process from "node:process"; | ||
| import { provider } from "std-env"; | ||
| import { join, resolve } from "pathe"; | ||
| import { pathToFileURL } from "node:url"; | ||
| import defu, { defu as defu$1 } from "defu"; | ||
| import { existsSync, readdirSync, statSync, watch } from "node:fs"; | ||
| import EventEmitter from "node:events"; | ||
| import { mkdir } from "node:fs/promises"; | ||
| import { resolveModulePath } from "exsolve"; | ||
| import { joinURL } from "ufo"; | ||
| import { listen } from "listhen"; | ||
| import { debounce } from "perfect-debounce"; | ||
| import { toNodeHandler } from "srvx/node"; | ||
| import { Youch } from "youch"; | ||
| //#region ../../node_modules/.pnpm/h3@1.15.6/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; | ||
| 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 = 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, lastComma)); | ||
| start = pos; | ||
| } else pos = lastComma + 1; | ||
| } else pos += 1; | ||
| } | ||
| if (!cookiesSeparatorFound || pos >= cookiesString.length) cookiesStrings.push(cookiesString.slice(start)); | ||
| } | ||
| 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, reject) => { | ||
| stream.pipe(event.node.res); | ||
| if (stream.on) { | ||
| stream.on("end", () => { | ||
| event.node.res.end(); | ||
| resolve(); | ||
| }); | ||
| 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) => { | ||
| _initResolve = resolve; | ||
| }); | ||
| 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) => r.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) => r.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) => `<h2>${params.loading}</h2>`); | ||
| } | ||
| function isPublicHostname(hostname) { | ||
| return !!hostname && ![ | ||
| "localhost", | ||
| "127.0.0.1", | ||
| "::1" | ||
| ].includes(hostname); | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/dev/index.ts | ||
| const start = Date.now(); | ||
| var IPC = class { | ||
| enabled = !!process.send && !process.title?.includes("vitest") && process.env.__NUXT__FORK; | ||
| constructor() { | ||
| if (this.enabled) process.once("unhandledRejection", (reason) => { | ||
| this.send({ | ||
| type: "nuxt:internal:dev:rejection", | ||
| message: reason instanceof Error ? reason.toString() : "Unhandled Rejection" | ||
| }); | ||
| process.exit(); | ||
| }); | ||
| process.on("message", (message) => { | ||
| if (message.type === "nuxt:internal:dev:context") initialize(message.context, { listenOverrides: message.listenOverrides }); | ||
| }); | ||
| this.send({ type: "nuxt:internal:dev:fork-ready" }); | ||
| } | ||
| send(message) { | ||
| if (this.enabled) process.send?.(message); | ||
| } | ||
| }; | ||
| const ipc = new IPC(); | ||
| async function initialize(devContext, ctx = {}) { | ||
| overrideEnv("development"); | ||
| const profileArg = devContext.args.profile; | ||
| const perfValue = profileArg === "verbose" ? true : profileArg ? "quiet" : void 0; | ||
| const perfOverrides = perfValue ? { debug: { perf: perfValue } } : {}; | ||
| if (profileArg) await startCpuProfile(); | ||
| const devServer = new NuxtDevServer({ | ||
| cwd: devContext.cwd, | ||
| overrides: defu(ctx.data?.overrides, { extends: devContext.args.extends }, perfOverrides), | ||
| logLevel: devContext.args.logLevel, | ||
| clear: devContext.args.clear, | ||
| dotenv: { | ||
| cwd: devContext.cwd, | ||
| fileName: devContext.args.dotenv | ||
| }, | ||
| envName: devContext.args.envName, | ||
| showBanner: ctx.showBanner !== false && !ipc.enabled, | ||
| listenOverrides: ctx.listenOverrides | ||
| }); | ||
| let address; | ||
| if (ipc.enabled) { | ||
| devServer.on("loading:error", (_error) => { | ||
| ipc.send({ | ||
| type: "nuxt:internal:dev:loading:error", | ||
| error: { | ||
| message: _error.message, | ||
| stack: _error.stack, | ||
| name: _error.name, | ||
| code: "code" in _error ? _error.code : void 0 | ||
| } | ||
| }); | ||
| }); | ||
| devServer.on("loading", (message) => { | ||
| ipc.send({ | ||
| type: "nuxt:internal:dev:loading", | ||
| message | ||
| }); | ||
| }); | ||
| devServer.on("restart", () => { | ||
| ipc.send({ type: "nuxt:internal:dev:restart" }); | ||
| }); | ||
| devServer.on("ready", (payload) => { | ||
| ipc.send({ | ||
| type: "nuxt:internal:dev:ready", | ||
| address: payload | ||
| }); | ||
| }); | ||
| } else devServer.on("ready", (payload) => { | ||
| address = payload; | ||
| }); | ||
| await devServer.init(); | ||
| if (process.env.DEBUG) console.debug(`Dev server (internal) initialized in ${Date.now() - start}ms`); | ||
| if (profileArg) for (const signal of [ | ||
| "exit", | ||
| "SIGTERM", | ||
| "SIGINT", | ||
| "SIGQUIT" | ||
| ]) process.once(signal, () => stopCpuProfile(devContext.cwd, "dev")); | ||
| return { | ||
| listener: devServer.listener, | ||
| close: async () => { | ||
| devServer.closeWatchers(); | ||
| await Promise.all([devServer.listener.close(), devServer.close()]); | ||
| }, | ||
| onReady: (callback) => { | ||
| if (address) callback(address); | ||
| else devServer.once("ready", (payload) => callback(payload)); | ||
| }, | ||
| onRestart: (callback) => { | ||
| let restarted = false; | ||
| function restart() { | ||
| if (!restarted) { | ||
| restarted = true; | ||
| callback(devServer); | ||
| } | ||
| } | ||
| devServer.once("restart", restart); | ||
| process.once("uncaughtException", restart); | ||
| process.once("unhandledRejection", restart); | ||
| } | ||
| }; | ||
| } | ||
| //#endregion | ||
| export { initialize as t }; |
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, r as envNameArgs, s as profileArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import { t as overrideEnv } from "./env-BRiVSJMz.mjs"; | ||
| import "./ascii-AoH-yOf6.mjs"; | ||
| import { n as stopCpuProfile, t as startCpuProfile } from "./profile-q-JV7Qxl.mjs"; | ||
| import { t as initialize } from "./dev-D5McAnmo.mjs"; | ||
| import { t as loadKit } from "./kit-DUlGqV3Z.mjs"; | ||
| import "./versions-Bg99eDSc.mjs"; | ||
| import { n as showVersions } from "./banner-C2vxTb-6.mjs"; | ||
| import { t as clearBuildDir } from "./fs-B8DrLsZ2.mjs"; | ||
| import "./nuxt-CsZm8Jhw.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { intro, outro } from "@clack/prompts"; | ||
| import { relative, resolve } from "pathe"; | ||
| //#region ../nuxi/src/commands/build.ts | ||
| var build_default = defineCommand({ | ||
| meta: { | ||
| name: "build", | ||
| description: "Build Nuxt for production deployment" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| prerender: { | ||
| type: "boolean", | ||
| description: "Build Nuxt and prerender static routes" | ||
| }, | ||
| preset: { | ||
| type: "string", | ||
| description: "Nitro server preset" | ||
| }, | ||
| ...dotEnvArgs, | ||
| ...envNameArgs, | ||
| ...extendsArgs, | ||
| ...profileArgs, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| overrideEnv("production"); | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const profileArg = ctx.args.profile; | ||
| const perfValue = profileArg === "verbose" ? true : profileArg ? "quiet" : void 0; | ||
| if (profileArg) await startCpuProfile(); | ||
| try { | ||
| intro(colors.cyan("Building Nuxt for production...")); | ||
| const kit = await loadKit(cwd); | ||
| await showVersions(cwd, kit, ctx.args.dotenv); | ||
| const nuxt = await kit.loadNuxt({ | ||
| cwd, | ||
| dotenv: { | ||
| cwd, | ||
| fileName: ctx.args.dotenv | ||
| }, | ||
| envName: ctx.args.envName, | ||
| overrides: { | ||
| logLevel: ctx.args.logLevel, | ||
| _generate: ctx.args.prerender, | ||
| nitro: { | ||
| static: ctx.args.prerender, | ||
| preset: ctx.args.preset || process.env.NITRO_PRESET || process.env.SERVER_PRESET | ||
| }, | ||
| ...ctx.args.extends && { extends: ctx.args.extends }, | ||
| ...ctx.data?.overrides, | ||
| ...(perfValue || ctx.data?.overrides?.debug) && { debug: { | ||
| ...ctx.data?.overrides?.debug, | ||
| ...perfValue && { perf: perfValue } | ||
| } } | ||
| } | ||
| }); | ||
| let nitro; | ||
| try { | ||
| nitro = kit.useNitro?.(); | ||
| if (nitro) logger.info(`Nitro preset: ${colors.cyan(nitro.options.preset)}`); | ||
| } catch {} | ||
| await clearBuildDir(nuxt.options.buildDir); | ||
| await kit.writeTypes(nuxt); | ||
| nuxt.hook("build:error", async (err) => { | ||
| logger.error(`Nuxt build error: ${err}`); | ||
| if (profileArg) await stopCpuProfile(cwd, "build"); | ||
| process.exit(1); | ||
| }); | ||
| await kit.buildNuxt(nuxt); | ||
| if (ctx.args.prerender) { | ||
| if (!nuxt.options.ssr) { | ||
| logger.warn(`HTML content not prerendered because ${colors.cyan("ssr: false")} was set.`); | ||
| logger.info(`You can read more in ${colors.cyan("https://nuxt.com/docs/getting-started/deployment#static-hosting")}.`); | ||
| } | ||
| const dir = nitro?.options.output.publicDir; | ||
| const publicDir = dir ? relative(process.cwd(), dir) : ".output/public"; | ||
| outro(`✨ You can now deploy ${colors.cyan(publicDir)} to any static hosting!`); | ||
| } else outro("✨ Build complete!"); | ||
| } finally { | ||
| if (profileArg) await stopCpuProfile(cwd, "build"); | ||
| } | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { initialize, build_default as t }; |
| import { a as legacyRootDirArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { resolve } from "pathe"; | ||
| import { x } from "tinyexec"; | ||
| //#region ../nuxi/src/commands/devtools.ts | ||
| var devtools_default = defineCommand({ | ||
| meta: { | ||
| name: "devtools", | ||
| description: "Enable or disable devtools in a Nuxt project" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| command: { | ||
| type: "positional", | ||
| description: "Command to run", | ||
| valueHint: "enable|disable" | ||
| }, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const command = ctx.args.command; | ||
| if (!command || !["enable", "disable"].includes(command)) { | ||
| logger.error(`Unknown command ${colors.cyan(command || "")}.`); | ||
| process.exit(1); | ||
| } | ||
| await x("npx", [ | ||
| "@nuxt/devtools-wizard@latest", | ||
| command, | ||
| cwd | ||
| ], { | ||
| throwOnError: true, | ||
| nodeOptions: { | ||
| stdio: "inherit", | ||
| cwd | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { devtools_default as default }; |
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import process from "node:process"; | ||
| import { colors } from "consola/utils"; | ||
| //#region ../nuxi/src/utils/env.ts | ||
| function overrideEnv(targetEnv) { | ||
| const currentEnv = process.env.NODE_ENV; | ||
| if (currentEnv && currentEnv !== targetEnv) logger.warn(`Changing ${colors.cyan("NODE_ENV")} from ${colors.cyan(currentEnv)} to ${colors.cyan(targetEnv)}, to avoid unintended behavior.`); | ||
| process.env.NODE_ENV = targetEnv; | ||
| } | ||
| //#endregion | ||
| export { overrideEnv as t }; |
| import process from "node:process"; | ||
| import { colors } from "consola/utils"; | ||
| import { stripVTControlCharacters } from "node:util"; | ||
| //#region ../nuxi/src/utils/formatting.ts | ||
| const AT_MENTION_RE = /\b@([^, ]+)/g; | ||
| const BACKTICK_RE = /`([^`]*)`/g; | ||
| function getStringWidth(str) { | ||
| const stripped = stripVTControlCharacters(str); | ||
| let width = 0; | ||
| for (const char of stripped) { | ||
| const code = char.codePointAt(0); | ||
| if (!code) continue; | ||
| if (code >= 65024 && code <= 65039) continue; | ||
| if (code >= 127744 && code <= 129535 || code >= 128512 && code <= 128591 || code >= 128640 && code <= 128767 || code >= 9728 && code <= 9983 || code >= 9984 && code <= 10175 || code >= 129280 && code <= 129535 || code >= 129648 && code <= 129791) width += 2; | ||
| else width += 1; | ||
| } | ||
| return width; | ||
| } | ||
| function formatInfoBox(infoObj) { | ||
| let firstColumnLength = 0; | ||
| let ansiFirstColumnLength = 0; | ||
| const entries = Object.entries(infoObj).map(([label, val]) => { | ||
| if (label.length > firstColumnLength) { | ||
| ansiFirstColumnLength = colors.bold(colors.whiteBright(label)).length + 6; | ||
| firstColumnLength = label.length + 6; | ||
| } | ||
| return [label, val || "-"]; | ||
| }); | ||
| const terminalWidth = Math.max(process.stdout.columns || 80, firstColumnLength) - 8; | ||
| let boxStr = ""; | ||
| for (const [label, value] of entries) { | ||
| const formattedValue = value.replace(AT_MENTION_RE, (_, r) => colors.gray(` ${r}`)).replace(BACKTICK_RE, (_, r) => r); | ||
| boxStr += `${colors.bold(colors.whiteBright(label))}`.padEnd(ansiFirstColumnLength); | ||
| let boxRowLength = firstColumnLength; | ||
| const words = formattedValue.split(" "); | ||
| let currentLine = ""; | ||
| for (const word of words) { | ||
| const wordLength = getStringWidth(word); | ||
| const spaceLength = currentLine ? 1 : 0; | ||
| if (boxRowLength + wordLength + spaceLength > terminalWidth) { | ||
| if (currentLine) boxStr += colors.cyan(currentLine); | ||
| boxStr += `\n${" ".repeat(firstColumnLength)}`; | ||
| currentLine = word; | ||
| boxRowLength = firstColumnLength + wordLength; | ||
| } else { | ||
| currentLine += (currentLine ? " " : "") + word; | ||
| boxRowLength += wordLength + spaceLength; | ||
| } | ||
| } | ||
| if (currentLine) boxStr += colors.cyan(currentLine); | ||
| boxStr += "\n"; | ||
| } | ||
| return boxStr; | ||
| } | ||
| //#endregion | ||
| export { formatInfoBox as t }; |
| import { t as debug } from "./logger-B4ge7MhP.mjs"; | ||
| import { join } from "pathe"; | ||
| import { existsSync, promises } from "node:fs"; | ||
| //#region ../nuxi/src/utils/fs.ts | ||
| async function clearDir(path, exclude) { | ||
| if (!exclude) await promises.rm(path, { | ||
| recursive: true, | ||
| force: true | ||
| }); | ||
| else if (existsSync(path)) { | ||
| const files = await promises.readdir(path); | ||
| await Promise.all(files.map(async (name) => { | ||
| if (!exclude.includes(name)) await promises.rm(join(path, name), { | ||
| recursive: true, | ||
| force: true | ||
| }); | ||
| })); | ||
| } | ||
| await promises.mkdir(path, { recursive: true }); | ||
| } | ||
| function clearBuildDir(path) { | ||
| return clearDir(path, [ | ||
| "cache", | ||
| "analyze", | ||
| "nuxt.json" | ||
| ]); | ||
| } | ||
| async function rmRecursive(paths) { | ||
| await Promise.all(paths.filter((p) => typeof p === "string").map(async (path) => { | ||
| debug(`Removing recursive path: ${path}`); | ||
| await promises.rm(path, { | ||
| recursive: true, | ||
| force: true | ||
| }).catch(() => {}); | ||
| })); | ||
| } | ||
| //#endregion | ||
| export { clearDir as n, rmRecursive as r, clearBuildDir as t }; |
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, r as envNameArgs, s as profileArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import "./logger-B4ge7MhP.mjs"; | ||
| import "./env-BRiVSJMz.mjs"; | ||
| import "./ascii-AoH-yOf6.mjs"; | ||
| import "./profile-q-JV7Qxl.mjs"; | ||
| import "./kit-DUlGqV3Z.mjs"; | ||
| import "./versions-Bg99eDSc.mjs"; | ||
| import "./banner-C2vxTb-6.mjs"; | ||
| import "./fs-B8DrLsZ2.mjs"; | ||
| import { t as build_default } from "./dev-DmuOeJjt.mjs"; | ||
| import { defineCommand } from "citty"; | ||
| //#region ../nuxi/src/commands/generate.ts | ||
| var generate_default = defineCommand({ | ||
| meta: { | ||
| name: "generate", | ||
| description: "Build Nuxt and prerender all routes" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| preset: { | ||
| type: "string", | ||
| description: "Nitro server preset" | ||
| }, | ||
| ...dotEnvArgs, | ||
| ...envNameArgs, | ||
| ...extendsArgs, | ||
| ...profileArgs, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| ctx.args.prerender = true; | ||
| await build_default.run(ctx); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { generate_default as default }; |
| import { a as legacyRootDirArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import { n as tryResolveNuxt } from "./kit-DUlGqV3Z.mjs"; | ||
| import "./versions-Bg99eDSc.mjs"; | ||
| import { t as getBuilder } from "./banner-C2vxTb-6.mjs"; | ||
| import { t as formatInfoBox } from "./formatting-BVTBOej7.mjs"; | ||
| import { t as getPackageManagerVersion } from "./packageManagers-BadBU-Pz.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { isBun, isDeno, isMinimal } from "std-env"; | ||
| import { box } from "@clack/prompts"; | ||
| import { resolve } from "pathe"; | ||
| import { readPackageJSON } from "pkg-types"; | ||
| import os from "node:os"; | ||
| import { detectPackageManager } from "nypm"; | ||
| import { writeText } from "tinyclip"; | ||
| //#region ../nuxi/package.json | ||
| var version = "3.34.0"; | ||
| //#endregion | ||
| //#region ../nuxi/src/commands/info.ts | ||
| const LEADING_SLASH_RE = /^\//; | ||
| var info_default = defineCommand({ | ||
| meta: { | ||
| name: "info", | ||
| description: "Get information about Nuxt project" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const nuxtConfig = await getNuxtConfig(cwd); | ||
| const { dependencies = {}, devDependencies = {} } = await readPackageJSON(cwd).catch(() => ({})); | ||
| const nuxtPath = tryResolveNuxt(cwd); | ||
| async function getDepVersion(name) { | ||
| for (const url of [cwd, nuxtPath]) { | ||
| if (!url) continue; | ||
| const pkg = await readPackageJSON(name, { url }).catch(() => null); | ||
| if (pkg) return pkg.version; | ||
| } | ||
| return dependencies[name] || devDependencies[name]; | ||
| } | ||
| async function listModules(arr = []) { | ||
| const info = []; | ||
| for (let m of arr) { | ||
| if (Array.isArray(m)) m = m[0]; | ||
| const name = normalizeConfigModule(m, cwd); | ||
| if (name) { | ||
| const v = await getDepVersion(name.split("/").splice(0, 2).join("/")); | ||
| info.push(`\`${v ? `${name}@${v}` : name}\``); | ||
| } | ||
| } | ||
| return info.join(", "); | ||
| } | ||
| const nuxtVersion = await getDepVersion("nuxt") || await getDepVersion("nuxt-nightly") || await getDepVersion("nuxt-edge") || await getDepVersion("nuxt3") || "-"; | ||
| const isLegacy = nuxtVersion.startsWith("2"); | ||
| const builder = !isLegacy ? nuxtConfig.builder || "vite" : nuxtConfig.bridge?.vite ? "vite" : nuxtConfig.buildModules?.includes("nuxt-vite") ? "vite" : "webpack"; | ||
| let packageManager = (await detectPackageManager(cwd))?.name; | ||
| if (packageManager) packageManager += `@${getPackageManagerVersion(packageManager)}`; | ||
| const osType = os.type(); | ||
| const builderInfo = typeof builder === "string" ? getBuilder(cwd, builder) : { | ||
| name: "custom", | ||
| version: "0.0.0" | ||
| }; | ||
| const infoObj = { | ||
| "Operating system": osType === "Darwin" ? `macOS ${os.release()}` : osType === "Windows_NT" ? `Windows ${os.release()}` : `${osType} ${os.release()}`, | ||
| "CPU": `${os.cpus()[0]?.model || "unknown"} (${os.cpus().length} cores)`, | ||
| ...isBun ? { "Bun version": Bun?.version } : isDeno ? { "Deno version": Deno?.version.deno } : { "Node.js version": process.version }, | ||
| "nuxt/cli version": version, | ||
| "Package manager": packageManager ?? "unknown", | ||
| "Nuxt version": nuxtVersion, | ||
| "Nitro version": await getDepVersion("nitropack") || await getDepVersion("nitro"), | ||
| "Builder": builderInfo.name === "custom" ? "custom" : `${builderInfo.name.toLowerCase()}@${builderInfo.version}`, | ||
| "Config": Object.keys(nuxtConfig).map((key) => `\`${key}\``).sort().join(", "), | ||
| "Modules": await listModules(nuxtConfig.modules), | ||
| ...isLegacy ? { "Build modules": await listModules(nuxtConfig.buildModules || []) } : {} | ||
| }; | ||
| logger.info(`Nuxt root directory: ${colors.cyan(nuxtConfig.rootDir || cwd)}\n`); | ||
| const boxStr = formatInfoBox(infoObj); | ||
| let firstColumnLength = 0; | ||
| let secondColumnLength = 0; | ||
| const entries = Object.entries(infoObj).map(([label, val]) => { | ||
| if (label.length > firstColumnLength) firstColumnLength = label.length + 4; | ||
| if ((val || "").length > secondColumnLength) secondColumnLength = (val || "").length + 2; | ||
| return [label, val || "-"]; | ||
| }); | ||
| let copyStr = `| ${" ".repeat(firstColumnLength)} | ${" ".repeat(secondColumnLength)} |\n| ${"-".repeat(firstColumnLength)} | ${"-".repeat(secondColumnLength)} |\n`; | ||
| for (const [label, value] of entries) if (!isMinimal) copyStr += `| ${`**${label}**`.padEnd(firstColumnLength)} | ${(value.includes("`") ? value : `\`${value}\``).padEnd(secondColumnLength)} |\n`; | ||
| if (!isMinimal && await writeText(copyStr).then(() => true).catch(() => false)) box(`\n${boxStr}`, ` Nuxt project info ${colors.gray("(copied to clipboard) ")}`, { | ||
| contentAlign: "left", | ||
| titleAlign: "left", | ||
| width: "auto", | ||
| titlePadding: 2, | ||
| contentPadding: 2, | ||
| rounded: true | ||
| }); | ||
| else logger.info(`Nuxt project info:\n${copyStr}`, { withGuide: false }); | ||
| const isNuxt3 = !isLegacy; | ||
| const isBridge = !isNuxt3 && infoObj["Build modules"]?.includes("bridge"); | ||
| const repo = isBridge ? "nuxt/bridge" : "nuxt/nuxt"; | ||
| const docsURL = isNuxt3 || isBridge ? "https://nuxt.com" : "https://v2.nuxt.com"; | ||
| logger.info(`👉 Read documentation: ${colors.cyan(docsURL)}`); | ||
| if (isNuxt3 || isBridge) { | ||
| logger.info(`👉 Report an issue: ${colors.cyan(`https://github.com/${repo}/issues/new?template=bug-report.yml`)}`, { spacing: 0 }); | ||
| logger.info(`👉 Suggest an improvement: ${colors.cyan(`https://github.com/${repo}/discussions/new`)}`, { spacing: 0 }); | ||
| } | ||
| } | ||
| }); | ||
| function normalizeConfigModule(module, rootDir) { | ||
| if (!module) return null; | ||
| if (typeof module === "string") return module.split(rootDir).pop().split("node_modules").pop().replace(LEADING_SLASH_RE, ""); | ||
| if (typeof module === "function") return `${module.name}()`; | ||
| if (Array.isArray(module)) return normalizeConfigModule(module[0], rootDir); | ||
| return null; | ||
| } | ||
| async function getNuxtConfig(rootDir) { | ||
| try { | ||
| const { createJiti } = await import("jiti"); | ||
| const jiti = createJiti(rootDir, { | ||
| interopDefault: true, | ||
| alias: { | ||
| "~": rootDir, | ||
| "@": rootDir | ||
| } | ||
| }); | ||
| globalThis.defineNuxtConfig = (c) => c; | ||
| const result = await jiti.import("./nuxt.config", { default: true }); | ||
| delete globalThis.defineNuxtConfig; | ||
| return result; | ||
| } catch { | ||
| return {}; | ||
| } | ||
| } | ||
| //#endregion | ||
| export { info_default as default }; |
| import { o as logLevelArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import { n as themeColor, t as nuxtIcon } from "./ascii-AoH-yOf6.mjs"; | ||
| import { r as relativeToProcess } from "./kit-DUlGqV3Z.mjs"; | ||
| import { t as getNuxtVersion } from "./versions-Bg99eDSc.mjs"; | ||
| import "./fs-B8DrLsZ2.mjs"; | ||
| import { i as runCommand$1, r as selectModulesAutocomplete, t as add_default } from "./add-D-RRzz1Y.mjs"; | ||
| import { n as fetchModules, t as checkNuxtCompatibility } from "./_utils-Co1L4CHe.mjs"; | ||
| import "./prepare-etx17Cow.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { hasTTY } from "std-env"; | ||
| import { box, cancel, confirm, intro, isCancel, outro, select, spinner, tasks, text } from "@clack/prompts"; | ||
| import { basename, join, relative, resolve } from "pathe"; | ||
| import { existsSync } from "node:fs"; | ||
| import { findFile, readPackageJSON, writePackageJSON } from "pkg-types"; | ||
| import { x } from "tinyexec"; | ||
| import { installDependencies } from "nypm"; | ||
| import { downloadTemplate, startShell } from "giget"; | ||
| import { $fetch } from "ofetch"; | ||
| //#region ../nuxi/src/utils/starter-templates.ts | ||
| const hiddenTemplates = [ | ||
| "doc-driven", | ||
| "v4", | ||
| "v4-compat", | ||
| "v2-bridge", | ||
| "v3", | ||
| "ui-vue", | ||
| "module-devtools", | ||
| "layer", | ||
| "hub" | ||
| ]; | ||
| const fetchOptions = { | ||
| timeout: 3e3, | ||
| responseType: "json", | ||
| headers: { | ||
| "user-agent": "@nuxt/cli", | ||
| ...process.env.GITHUB_TOKEN ? { authorization: `token ${process.env.GITHUB_TOKEN}` } : {} | ||
| } | ||
| }; | ||
| let templatesCache = null; | ||
| async function getTemplates() { | ||
| templatesCache ||= fetchTemplates(); | ||
| return templatesCache; | ||
| } | ||
| async function fetchTemplates() { | ||
| const templates = {}; | ||
| const files = await $fetch("https://api.github.com/repos/nuxt/starter/contents/templates?ref=templates", fetchOptions); | ||
| await Promise.all(files.map(async (file) => { | ||
| if (!file.download_url || file.type !== "file" || !file.name.endsWith(".json")) return; | ||
| const templateName = file.name.replace(".json", ""); | ||
| if (hiddenTemplates.includes(templateName)) return; | ||
| templates[templateName] = void 0; | ||
| templates[templateName] = await $fetch(file.download_url, fetchOptions); | ||
| })); | ||
| return templates; | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/commands/init.ts | ||
| const NON_WORD_RE = /[^\w-]/g; | ||
| const MULTI_DASH_RE = /-{2,}/g; | ||
| const LEADING_TRAILING_DASH_RE = /^-|-$/g; | ||
| const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/nuxt/starter/templates/templates"; | ||
| const DEFAULT_TEMPLATE_NAME = "minimal"; | ||
| const packageManagerOptions = Object.keys({ | ||
| npm: void 0, | ||
| pnpm: void 0, | ||
| yarn: void 0, | ||
| bun: void 0, | ||
| deno: void 0 | ||
| }); | ||
| var init_default = defineCommand({ | ||
| meta: { | ||
| name: "init", | ||
| description: "Initialize a fresh project" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| dir: { | ||
| type: "positional", | ||
| description: "Project directory", | ||
| default: "" | ||
| }, | ||
| template: { | ||
| type: "string", | ||
| alias: "t", | ||
| description: "Template name" | ||
| }, | ||
| force: { | ||
| type: "boolean", | ||
| alias: "f", | ||
| description: "Override existing directory" | ||
| }, | ||
| offline: { | ||
| type: "boolean", | ||
| description: "Force offline mode" | ||
| }, | ||
| preferOffline: { | ||
| type: "boolean", | ||
| description: "Prefer offline mode" | ||
| }, | ||
| install: { | ||
| type: "boolean", | ||
| default: true, | ||
| description: "Skip installing dependencies" | ||
| }, | ||
| gitInit: { | ||
| type: "boolean", | ||
| description: "Initialize git repository" | ||
| }, | ||
| shell: { | ||
| type: "boolean", | ||
| description: "Start shell after installation in project directory" | ||
| }, | ||
| packageManager: { | ||
| type: "string", | ||
| description: "Package manager choice (npm, pnpm, yarn, bun)" | ||
| }, | ||
| modules: { | ||
| type: "string", | ||
| required: false, | ||
| description: "Nuxt modules to install (comma separated without spaces)", | ||
| negativeDescription: "Skip module installation prompt", | ||
| alias: "M" | ||
| }, | ||
| nightly: { | ||
| type: "string", | ||
| description: "Use Nuxt nightly release channel (3x or latest)" | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| if (!ctx.args.offline && !ctx.args.preferOffline && !ctx.args.template) getTemplates().catch(() => null); | ||
| if (hasTTY) process.stdout.write(`\n${nuxtIcon}\n\n`); | ||
| intro(colors.bold(`Welcome to Nuxt!`.split("").map((m) => `${themeColor}${m}`).join(""))); | ||
| let availableTemplates = {}; | ||
| if (!ctx.args.template || !ctx.args.dir) { | ||
| const defaultTemplates = await import("./templates-BQDUIkuM.mjs").then((n) => n.n).then((r) => r.templates); | ||
| if (ctx.args.offline || ctx.args.preferOffline) availableTemplates = defaultTemplates; | ||
| else { | ||
| const templatesSpinner = spinner(); | ||
| templatesSpinner.start("Loading available templates"); | ||
| try { | ||
| availableTemplates = await getTemplates(); | ||
| templatesSpinner.stop("Templates loaded"); | ||
| } catch { | ||
| availableTemplates = defaultTemplates; | ||
| templatesSpinner.stop("Templates loaded from cache"); | ||
| } | ||
| } | ||
| } | ||
| let templateName = ctx.args.template; | ||
| if (!templateName) { | ||
| const result = await select({ | ||
| message: "Which template would you like to use?", | ||
| options: Object.entries(availableTemplates).map(([name, data]) => { | ||
| return { | ||
| value: name, | ||
| label: data ? `${colors.whiteBright(name)} – ${data.description}` : name, | ||
| hint: name === DEFAULT_TEMPLATE_NAME ? "recommended" : void 0 | ||
| }; | ||
| }), | ||
| initialValue: DEFAULT_TEMPLATE_NAME | ||
| }); | ||
| if (isCancel(result)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| templateName = result; | ||
| } | ||
| templateName ||= DEFAULT_TEMPLATE_NAME; | ||
| if (typeof templateName !== "string") { | ||
| logger.error("Please specify a template!"); | ||
| process.exit(1); | ||
| } | ||
| let dir = ctx.args.dir; | ||
| if (dir === "") { | ||
| const defaultDir = availableTemplates[templateName]?.defaultDir || "nuxt-app"; | ||
| const result = await text({ | ||
| message: "Where would you like to create your project?", | ||
| placeholder: `./${defaultDir}`, | ||
| defaultValue: defaultDir | ||
| }); | ||
| if (isCancel(result)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| dir = result; | ||
| } | ||
| const cwd = resolve(ctx.args.cwd); | ||
| let templateDownloadPath = resolve(cwd, dir); | ||
| logger.step(`Creating project in ${colors.cyan(relativeToProcess(templateDownloadPath))}`); | ||
| let shouldForce = Boolean(ctx.args.force); | ||
| if (!shouldForce && existsSync(templateDownloadPath)) { | ||
| const selectedAction = await select({ | ||
| message: `The directory ${colors.cyan(relativeToProcess(templateDownloadPath))} already exists. What would you like to do?`, | ||
| options: [ | ||
| { | ||
| value: "override", | ||
| label: "Override its contents" | ||
| }, | ||
| { | ||
| value: "different", | ||
| label: "Select different directory" | ||
| }, | ||
| { | ||
| value: "abort", | ||
| label: "Abort" | ||
| } | ||
| ] | ||
| }); | ||
| if (isCancel(selectedAction)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| switch (selectedAction) { | ||
| case "override": | ||
| shouldForce = true; | ||
| break; | ||
| case "different": { | ||
| const result = await text({ message: "Please specify a different directory:" }); | ||
| if (isCancel(result)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| templateDownloadPath = resolve(cwd, result); | ||
| break; | ||
| } | ||
| default: process.exit(1); | ||
| } | ||
| } | ||
| let template; | ||
| const downloadSpinner = spinner(); | ||
| downloadSpinner.start(`Downloading ${colors.cyan(templateName)} template`); | ||
| try { | ||
| template = await downloadTemplate(templateName, { | ||
| dir: templateDownloadPath, | ||
| force: shouldForce, | ||
| offline: Boolean(ctx.args.offline), | ||
| preferOffline: Boolean(ctx.args.preferOffline), | ||
| registry: process.env.NUXI_INIT_REGISTRY || DEFAULT_REGISTRY | ||
| }); | ||
| if (dir.length > 0) { | ||
| const path = await findFile("package.json", { | ||
| startingFrom: join(templateDownloadPath, "package.json"), | ||
| reverse: true | ||
| }); | ||
| if (path) { | ||
| const pkg = await readPackageJSON(path, { try: true }); | ||
| if (pkg && pkg.name) { | ||
| const slug = basename(templateDownloadPath).replace(NON_WORD_RE, "-").replace(MULTI_DASH_RE, "-").replace(LEADING_TRAILING_DASH_RE, ""); | ||
| if (slug) { | ||
| pkg.name = slug; | ||
| await writePackageJSON(path, pkg); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| downloadSpinner.stop(`Downloaded ${colors.cyan(template.name)} template`); | ||
| } catch (err) { | ||
| downloadSpinner.error("Template download failed"); | ||
| if (process.env.DEBUG) throw err; | ||
| logger.error(err.toString()); | ||
| process.exit(1); | ||
| } | ||
| if (ctx.args.nightly !== void 0 && !ctx.args.offline && !ctx.args.preferOffline) { | ||
| const nightlySpinner = spinner(); | ||
| nightlySpinner.start("Fetching nightly version info"); | ||
| const response = await $fetch("https://registry.npmjs.org/nuxt-nightly"); | ||
| const nightlyChannelTag = ctx.args.nightly || "latest"; | ||
| if (!nightlyChannelTag) { | ||
| nightlySpinner.error("Failed to get nightly channel tag"); | ||
| logger.error(`Error getting nightly channel tag.`); | ||
| process.exit(1); | ||
| } | ||
| const nightlyChannelVersion = response["dist-tags"][nightlyChannelTag]; | ||
| if (!nightlyChannelVersion) { | ||
| nightlySpinner.error("Nightly version not found"); | ||
| logger.error(`Nightly channel version for tag ${colors.cyan(nightlyChannelTag)} not found.`); | ||
| process.exit(1); | ||
| } | ||
| const nightlyNuxtPackageJsonVersion = `npm:nuxt-nightly@${nightlyChannelVersion}`; | ||
| const packageJsonPath = resolve(cwd, dir); | ||
| const packageJson = await readPackageJSON(packageJsonPath); | ||
| if (packageJson.dependencies && "nuxt" in packageJson.dependencies) packageJson.dependencies.nuxt = nightlyNuxtPackageJsonVersion; | ||
| else if (packageJson.devDependencies && "nuxt" in packageJson.devDependencies) packageJson.devDependencies.nuxt = nightlyNuxtPackageJsonVersion; | ||
| await writePackageJSON(join(packageJsonPath, "package.json"), packageJson); | ||
| nightlySpinner.stop(`Updated to nightly version ${colors.cyan(nightlyChannelVersion)}`); | ||
| } | ||
| const currentPackageManager = detectCurrentPackageManager(); | ||
| const packageManagerArg = ctx.args.packageManager; | ||
| const packageManagerSelectOptions = packageManagerOptions.map((pm) => ({ | ||
| label: pm, | ||
| value: pm, | ||
| hint: currentPackageManager === pm ? "current" : void 0 | ||
| })); | ||
| let selectedPackageManager; | ||
| if (packageManagerOptions.includes(packageManagerArg)) selectedPackageManager = packageManagerArg; | ||
| else { | ||
| const result = await select({ | ||
| message: "Which package manager would you like to use?", | ||
| options: packageManagerSelectOptions, | ||
| initialValue: currentPackageManager | ||
| }); | ||
| if (isCancel(result)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| selectedPackageManager = result; | ||
| } | ||
| let gitInit = ctx.args.gitInit === "false" ? false : ctx.args.gitInit; | ||
| if (gitInit === void 0) { | ||
| const result = await confirm({ message: "Initialize git repository?" }); | ||
| if (isCancel(result)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| gitInit = result; | ||
| } | ||
| if (ctx.args.install === false || ctx.args.install === "false") logger.info("Skipping install dependencies step."); | ||
| else { | ||
| const setupTasks = [{ | ||
| title: `Installing dependencies with ${colors.cyan(selectedPackageManager)}`, | ||
| task: async () => { | ||
| await installDependencies({ | ||
| cwd: template.dir, | ||
| packageManager: { | ||
| name: selectedPackageManager, | ||
| command: selectedPackageManager | ||
| }, | ||
| silent: true | ||
| }); | ||
| return "Dependencies installed"; | ||
| } | ||
| }]; | ||
| if (gitInit) setupTasks.push({ | ||
| title: "Initializing git repository", | ||
| task: async () => { | ||
| try { | ||
| await x("git", ["init", template.dir], { | ||
| throwOnError: true, | ||
| nodeOptions: { stdio: "inherit" } | ||
| }); | ||
| return "Git repository initialized"; | ||
| } catch (err) { | ||
| return `Git initialization failed: ${err}`; | ||
| } | ||
| } | ||
| }); | ||
| try { | ||
| await tasks(setupTasks); | ||
| } catch (err) { | ||
| if (process.env.DEBUG) throw err; | ||
| logger.error(err.toString()); | ||
| process.exit(1); | ||
| } | ||
| } | ||
| const modulesToAdd = []; | ||
| if (ctx.args.modules !== void 0) for (const segment of (ctx.args.modules || "").split(",")) { | ||
| const mod = segment.trim(); | ||
| if (mod) modulesToAdd.push(mod); | ||
| } | ||
| else if (!ctx.args.offline && !ctx.args.preferOffline) { | ||
| const modulesPromise = fetchModules(); | ||
| const wantsUserModules = await confirm({ | ||
| message: `Would you like to browse and install modules?`, | ||
| initialValue: false | ||
| }); | ||
| if (isCancel(wantsUserModules)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| if (wantsUserModules) { | ||
| const modulesSpinner = spinner(); | ||
| modulesSpinner.start("Fetching available modules"); | ||
| const [response, templateDeps, nuxtVersion] = await Promise.all([ | ||
| modulesPromise, | ||
| getTemplateDependencies(template.dir), | ||
| getNuxtVersion(template.dir) | ||
| ]); | ||
| modulesSpinner.stop("Modules loaded"); | ||
| const allModules = response.filter((module) => module.npm !== "@nuxt/devtools" && !templateDeps.includes(module.npm) && (!module.compatibility.nuxt || checkNuxtCompatibility(module, nuxtVersion))); | ||
| if (allModules.length === 0) logger.info("All modules are already included in this template."); | ||
| else { | ||
| const result = await selectModulesAutocomplete({ modules: allModules }); | ||
| if (result.selected.length > 0) { | ||
| const modules = result.selected; | ||
| const { toInstall, skipped } = filterModules(modules, Object.fromEntries(await Promise.all(modules.map(async (module) => [module, await getModuleDependencies(module)])))); | ||
| if (skipped.length) logger.info(`The following modules are already included as dependencies of another module and will not be installed: ${skipped.map((m) => colors.cyan(m)).join(", ")}`); | ||
| modulesToAdd.push(...toInstall); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| if (modulesToAdd.length > 0) await runCommand$1(add_default, [ | ||
| ...modulesToAdd, | ||
| `--cwd=${templateDownloadPath}`, | ||
| ctx.args.install ? "" : "--skipInstall", | ||
| ctx.args.logLevel ? `--logLevel=${ctx.args.logLevel}` : "" | ||
| ].filter(Boolean)); | ||
| outro(`✨ Nuxt project has been created with the ${colors.cyan(template.name)} template.`); | ||
| const relativeTemplateDir = relative(process.cwd(), template.dir) || "."; | ||
| const runCmd = selectedPackageManager === "deno" ? "task" : "run"; | ||
| box(`\n${[!ctx.args.shell && relativeTemplateDir.length > 1 && colors.cyan(`cd ${relativeTemplateDir}`), colors.cyan(`${selectedPackageManager} ${runCmd} dev`)].filter(Boolean).map((step) => ` › ${step}`).join("\n")}\n`, ` 👉 Next steps `, { | ||
| contentAlign: "left", | ||
| titleAlign: "left", | ||
| width: "auto", | ||
| titlePadding: 2, | ||
| contentPadding: 2, | ||
| rounded: true, | ||
| withGuide: false, | ||
| formatBorder: (text) => `${themeColor + text}\x1B[0m` | ||
| }); | ||
| if (ctx.args.shell) startShell(template.dir); | ||
| } | ||
| }); | ||
| async function getModuleDependencies(moduleName) { | ||
| try { | ||
| const dependencies = (await $fetch(`https://registry.npmjs.org/${moduleName}/latest`)).dependencies || {}; | ||
| return Object.keys(dependencies); | ||
| } catch (err) { | ||
| logger.warn(`Could not get dependencies for ${colors.cyan(moduleName)}: ${err}`); | ||
| return []; | ||
| } | ||
| } | ||
| function filterModules(modules, allDependencies) { | ||
| const result = { | ||
| toInstall: [], | ||
| skipped: [] | ||
| }; | ||
| for (const module of modules) if (modules.some((otherModule) => { | ||
| if (otherModule === module) return false; | ||
| return (allDependencies[otherModule] || []).includes(module); | ||
| })) result.skipped.push(module); | ||
| else result.toInstall.push(module); | ||
| return result; | ||
| } | ||
| async function getTemplateDependencies(templateDir) { | ||
| try { | ||
| const packageJsonPath = join(templateDir, "package.json"); | ||
| if (!existsSync(packageJsonPath)) return []; | ||
| const packageJson = await readPackageJSON(packageJsonPath); | ||
| const directDeps = { | ||
| ...packageJson.dependencies, | ||
| ...packageJson.devDependencies | ||
| }; | ||
| const directDepNames = Object.keys(directDeps); | ||
| const allDeps = new Set(directDepNames); | ||
| (await Promise.all(directDepNames.map((dep) => getModuleDependencies(dep)))).forEach((deps) => { | ||
| deps.forEach((dep) => allDeps.add(dep)); | ||
| }); | ||
| return [...allDeps]; | ||
| } catch (err) { | ||
| logger.warn(`Could not read template dependencies: ${err}`); | ||
| return []; | ||
| } | ||
| } | ||
| function detectCurrentPackageManager() { | ||
| const userAgent = process.env.npm_config_user_agent; | ||
| if (!userAgent) return; | ||
| const [name] = userAgent.split("/"); | ||
| if (packageManagerOptions.includes(name)) return name; | ||
| } | ||
| //#endregion | ||
| export { init_default as default }; |
| import process from "node:process"; | ||
| import { relative } from "pathe"; | ||
| import { pathToFileURL } from "node:url"; | ||
| import { resolveModulePath } from "exsolve"; | ||
| //#region ../nuxi/src/utils/paths.ts | ||
| const cwd = process.cwd(); | ||
| function relativeToProcess(path) { | ||
| return relative(cwd, path) || path; | ||
| } | ||
| function withNodePath(path) { | ||
| return [path, process.env.NODE_PATH].filter((i) => !!i); | ||
| } | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/kit.ts | ||
| async function loadKit(rootDir) { | ||
| try { | ||
| let kit = await import(pathToFileURL(resolveModulePath("@nuxt/kit", { from: tryResolveNuxt(rootDir) || rootDir })).href); | ||
| if (!kit.writeTypes) kit = { | ||
| ...kit, | ||
| writeTypes: () => { | ||
| throw new Error("`writeTypes` is not available in this version of `@nuxt/kit`. Please upgrade to v3.7 or newer."); | ||
| } | ||
| }; | ||
| return kit; | ||
| } catch (e) { | ||
| if (e.toString().includes("Cannot find module '@nuxt/kit'")) throw new Error("nuxi requires `@nuxt/kit` to be installed in your project. Try installing `nuxt` v3+ or `@nuxt/bridge` first."); | ||
| throw e; | ||
| } | ||
| } | ||
| function tryResolveNuxt(rootDir) { | ||
| for (const pkg of [ | ||
| "nuxt-nightly", | ||
| "nuxt", | ||
| "nuxt3", | ||
| "nuxt-edge" | ||
| ]) { | ||
| const path = resolveModulePath(pkg, { | ||
| from: withNodePath(rootDir), | ||
| try: true | ||
| }); | ||
| if (path) return path; | ||
| } | ||
| return null; | ||
| } | ||
| //#endregion | ||
| export { withNodePath as i, tryResolveNuxt as n, relativeToProcess as r, loadKit as t }; |
| import { log } from "@clack/prompts"; | ||
| import createDebug from "debug"; | ||
| //#region ../nuxi/src/utils/logger.ts | ||
| const logger = log; | ||
| const debug = createDebug("nuxi"); | ||
| //#endregion | ||
| export { logger as n, debug as t }; |
| import { defineCommand } from "citty"; | ||
| //#region ../nuxi/src/commands/module/index.ts | ||
| var module_default = defineCommand({ | ||
| meta: { | ||
| name: "module", | ||
| description: "Manage Nuxt modules" | ||
| }, | ||
| args: {}, | ||
| subCommands: { | ||
| add: () => import("./add-D-RRzz1Y.mjs").then((n) => n.n).then((r) => r.default || r), | ||
| search: () => import("./search-v4GAIriQ.mjs").then((r) => r.default || r) | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { module_default as default }; |
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import { r as rmRecursive } from "./fs-B8DrLsZ2.mjs"; | ||
| import { dirname, resolve } from "pathe"; | ||
| import { promises } from "node:fs"; | ||
| import { hash } from "ohash"; | ||
| //#region ../nuxi/src/utils/nuxt.ts | ||
| const GIT_ID_RE = /\.([0-9a-f]{7,8})$/; | ||
| async function cleanupNuxtDirs(rootDir, buildDir) { | ||
| logger.info("Cleaning up generated Nuxt files and caches..."); | ||
| await rmRecursive([ | ||
| buildDir, | ||
| ".output", | ||
| "dist", | ||
| "node_modules/.vite", | ||
| "node_modules/.cache" | ||
| ].map((dir) => resolve(rootDir, dir))); | ||
| } | ||
| function nuxtVersionToGitIdentifier(version) { | ||
| const id = GIT_ID_RE.exec(version); | ||
| if (id?.[1]) return id[1]; | ||
| return `v${version}`; | ||
| } | ||
| function resolveNuxtManifest(nuxt) { | ||
| const manifest = { | ||
| _hash: null, | ||
| project: { rootDir: nuxt.options.rootDir }, | ||
| versions: { nuxt: nuxt._version } | ||
| }; | ||
| manifest._hash = hash(manifest); | ||
| return manifest; | ||
| } | ||
| async function writeNuxtManifest(nuxt, manifest = resolveNuxtManifest(nuxt)) { | ||
| const manifestPath = resolve(nuxt.options.buildDir, "nuxt.json"); | ||
| await promises.mkdir(dirname(manifestPath), { recursive: true }); | ||
| await promises.writeFile(manifestPath, JSON.stringify(manifest, null, 2), "utf-8"); | ||
| return manifest; | ||
| } | ||
| async function loadNuxtManifest(buildDir) { | ||
| const manifestPath = resolve(buildDir, "nuxt.json"); | ||
| return await promises.readFile(manifestPath, "utf-8").then((data) => JSON.parse(data)).catch(() => null); | ||
| } | ||
| //#endregion | ||
| export { writeNuxtManifest as a, resolveNuxtManifest as i, loadNuxtManifest as n, nuxtVersionToGitIdentifier as r, cleanupNuxtDirs as t }; |
| import { execSync } from "node:child_process"; | ||
| //#region ../nuxi/src/utils/packageManagers.ts | ||
| function getPackageManagerVersion(name) { | ||
| return execSync(`${name} --version`).toString("utf8").trim(); | ||
| } | ||
| //#endregion | ||
| export { getPackageManagerVersion as t }; |
| import { t as __exportAll } from "./rolldown-runtime-95iHPtFO.mjs"; | ||
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, r as envNameArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import { r as relativeToProcess, t as loadKit } from "./kit-DUlGqV3Z.mjs"; | ||
| import { t as clearBuildDir } from "./fs-B8DrLsZ2.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { resolve } from "pathe"; | ||
| //#region ../nuxi/src/commands/prepare.ts | ||
| var prepare_exports = /* @__PURE__ */ __exportAll({ default: () => prepare_default }); | ||
| var prepare_default = defineCommand({ | ||
| meta: { | ||
| name: "prepare", | ||
| description: "Prepare Nuxt for development/build" | ||
| }, | ||
| args: { | ||
| ...dotEnvArgs, | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...envNameArgs, | ||
| ...extendsArgs, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| process.env.NODE_ENV = process.env.NODE_ENV || "production"; | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const { loadNuxt, buildNuxt, writeTypes } = await loadKit(cwd); | ||
| const nuxt = await loadNuxt({ | ||
| cwd, | ||
| dotenv: { | ||
| cwd, | ||
| fileName: ctx.args.dotenv | ||
| }, | ||
| envName: ctx.args.envName, | ||
| overrides: { | ||
| _prepare: true, | ||
| logLevel: ctx.args.logLevel, | ||
| ...ctx.args.extends && { extends: ctx.args.extends }, | ||
| ...ctx.data?.overrides | ||
| } | ||
| }); | ||
| await clearBuildDir(nuxt.options.buildDir); | ||
| await buildNuxt(nuxt); | ||
| await writeTypes(nuxt); | ||
| logger.success(`Types generated in ${colors.cyan(relativeToProcess(nuxt.options.buildDir))}.`); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { prepare_exports as n, prepare_default as t }; |
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, r as envNameArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import { r as relativeToProcess, t as loadKit } from "./kit-DUlGqV3Z.mjs"; | ||
| import { dirname } from "node:path"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { box, outro } from "@clack/prompts"; | ||
| import { resolve as resolve$1 } from "pathe"; | ||
| import { existsSync, promises } from "node:fs"; | ||
| import { x } from "tinyexec"; | ||
| import { setupDotenv } from "c12"; | ||
| //#region ../nuxi/src/commands/preview.ts | ||
| const command = defineCommand({ | ||
| meta: { | ||
| name: "preview", | ||
| description: "Launches Nitro server for local testing after `nuxi build`." | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...envNameArgs, | ||
| ...extendsArgs, | ||
| ...legacyRootDirArgs, | ||
| port: { | ||
| type: "string", | ||
| description: "Port to listen on", | ||
| alias: ["p"] | ||
| }, | ||
| ...dotEnvArgs | ||
| }, | ||
| async run(ctx) { | ||
| process.env.NODE_ENV = process.env.NODE_ENV || "production"; | ||
| const cwd = resolve$1(ctx.args.cwd || ctx.args.rootDir); | ||
| const { loadNuxt } = await loadKit(cwd); | ||
| const nitroJSONPaths = [await new Promise((res) => { | ||
| loadNuxt({ | ||
| cwd, | ||
| dotenv: { | ||
| cwd, | ||
| fileName: ctx.args.dotenv | ||
| }, | ||
| envName: ctx.args.envName, | ||
| ready: true, | ||
| overrides: { | ||
| ...ctx.args.extends && { extends: ctx.args.extends }, | ||
| modules: [function(_, nuxt) { | ||
| nuxt.hook("nitro:init", (nitro) => { | ||
| res(resolve$1(nuxt.options.srcDir || cwd, nitro.options.output.dir || ".output", "nitro.json")); | ||
| }); | ||
| }] | ||
| } | ||
| }).then((nuxt) => nuxt.close()).catch(() => ""); | ||
| }), resolve$1(cwd, ".output", "nitro.json")].filter(Boolean); | ||
| const nitroJSONPath = nitroJSONPaths.find((p) => existsSync(p)); | ||
| if (!nitroJSONPath) { | ||
| logger.error(`Cannot find ${colors.cyan("nitro.json")}. Did you run ${colors.cyan("nuxi build")} first? Search path:\n${nitroJSONPaths.join("\n")}`); | ||
| process.exit(1); | ||
| } | ||
| const outputPath = dirname(nitroJSONPath); | ||
| const nitroJSON = JSON.parse(await promises.readFile(nitroJSONPath, "utf-8")); | ||
| if (!nitroJSON.commands.preview) { | ||
| logger.error("Preview is not supported for this build."); | ||
| process.exit(1); | ||
| } | ||
| const info = [ | ||
| ["Node.js:", `v${process.versions.node}`], | ||
| ["Nitro preset:", nitroJSON.preset], | ||
| ["Working directory:", relativeToProcess(outputPath)] | ||
| ]; | ||
| const _infoKeyLen = Math.max(...info.map(([label]) => label.length)); | ||
| logger.message(""); | ||
| box([ | ||
| "", | ||
| "You are previewing a Nuxt app. In production, do not use this CLI. ", | ||
| `Instead, run ${colors.cyan(nitroJSON.commands.preview)} directly.`, | ||
| "", | ||
| ...info.map(([label, value]) => `${label.padEnd(_infoKeyLen, " ")} ${colors.cyan(value)}`), | ||
| "" | ||
| ].join("\n"), colors.yellow(" Previewing Nuxt app "), { | ||
| contentAlign: "left", | ||
| titleAlign: "left", | ||
| width: "auto", | ||
| titlePadding: 2, | ||
| contentPadding: 2, | ||
| rounded: true, | ||
| withGuide: true, | ||
| formatBorder: (text) => colors.yellow(text) | ||
| }); | ||
| const envFileName = ctx.args.dotenv || ".env"; | ||
| if (existsSync(resolve$1(cwd, envFileName))) { | ||
| logger.info(`Loading ${colors.cyan(envFileName)}. This will not be loaded when running the server in production.`); | ||
| await setupDotenv({ | ||
| cwd, | ||
| fileName: envFileName | ||
| }); | ||
| } else if (ctx.args.dotenv) logger.error(`Cannot find ${colors.cyan(envFileName)}.`); | ||
| const port = ctx.args.port ?? process.env.NUXT_PORT ?? process.env.NITRO_PORT ?? process.env.PORT; | ||
| outro(`Running ${colors.cyan(nitroJSON.commands.preview)} in ${colors.cyan(relativeToProcess(outputPath))}`); | ||
| const [command, ...commandArgs] = nitroJSON.commands.preview.split(" "); | ||
| await x(command, commandArgs, { | ||
| throwOnError: true, | ||
| nodeOptions: { | ||
| stdio: "inherit", | ||
| cwd: outputPath, | ||
| env: { | ||
| ...process.env, | ||
| NUXT_PORT: port, | ||
| NITRO_PORT: port | ||
| } | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
| //#endregion | ||
| export { command as default }; |
| import { n as themeColor } from "./ascii-AoH-yOf6.mjs"; | ||
| import process from "node:process"; | ||
| import { colors } from "consola/utils"; | ||
| import { box } from "@clack/prompts"; | ||
| import { join, relative } from "pathe"; | ||
| import { mkdirSync, writeFileSync } from "node:fs"; | ||
| //#region ../nuxi/src/utils/profile.ts | ||
| const RELATIVE_PATH_RE = /^(?![^.]{1,2}\/)/; | ||
| let session; | ||
| let profileCount = 0; | ||
| async function startCpuProfile() { | ||
| const cli = globalThis.__nuxt_cli__; | ||
| if (cli?.cpuProfileSession) { | ||
| session = cli.cpuProfileSession; | ||
| delete cli.cpuProfileSession; | ||
| return; | ||
| } | ||
| session = new (await (import("node:inspector"))).Session(); | ||
| session.connect(); | ||
| try { | ||
| await new Promise((res, rej) => { | ||
| session.post("Profiler.enable", (err) => { | ||
| if (err) return rej(err); | ||
| session.post("Profiler.start", (err) => { | ||
| if (err) return rej(err); | ||
| res(); | ||
| }); | ||
| }); | ||
| }); | ||
| } catch (err) { | ||
| session.disconnect(); | ||
| session = void 0; | ||
| throw err; | ||
| } | ||
| } | ||
| async function stopCpuProfile(outDir, command) { | ||
| if (!session) return; | ||
| const s = session; | ||
| session = void 0; | ||
| const count = profileCount++; | ||
| const outPath = join(outDir, `nuxt-${command}${count ? `-${count}` : ""}.cpuprofile`); | ||
| const relativeOutPath = relative(process.cwd(), outPath).replace(RELATIVE_PATH_RE, "./"); | ||
| try { | ||
| await new Promise((resolve, reject) => { | ||
| s.post("Profiler.stop", (err, params) => { | ||
| if (err) return reject(err); | ||
| if (!params?.profile) return resolve(params); | ||
| try { | ||
| mkdirSync(outDir, { recursive: true }); | ||
| writeFileSync(outPath, JSON.stringify(params.profile)); | ||
| box(`\n${[`CPU profile written to ${colors.cyan(relativeOutPath)}.`, `Open it in a CPU profile viewer like your IDE, or ${colors.cyan("https://discoveryjs.github.io/cpupro")}.`].map((step) => ` › ${step}`).join("\n")}\n`, "", { | ||
| contentAlign: "left", | ||
| titleAlign: "left", | ||
| width: "auto", | ||
| titlePadding: 2, | ||
| contentPadding: 2, | ||
| rounded: true, | ||
| withGuide: false, | ||
| formatBorder: (text) => `${themeColor + text}\x1B[0m` | ||
| }); | ||
| } catch {} | ||
| resolve(params); | ||
| }); | ||
| }); | ||
| } finally { | ||
| s.disconnect(); | ||
| } | ||
| } | ||
| //#endregion | ||
| export { stopCpuProfile as n, startCpuProfile as t }; |
| //#region \0rolldown/runtime.js | ||
| var __defProp = Object.defineProperty; | ||
| var __exportAll = (all, no_symbols) => { | ||
| let target = {}; | ||
| for (var name in all) { | ||
| __defProp(target, name, { | ||
| get: all[name], | ||
| enumerable: true | ||
| }); | ||
| } | ||
| if (!no_symbols) { | ||
| __defProp(target, Symbol.toStringTag, { value: "Module" }); | ||
| } | ||
| return target; | ||
| }; | ||
| //#endregion | ||
| export { __exportAll as t }; |
| import { t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import "./kit-DUlGqV3Z.mjs"; | ||
| import { t as getNuxtVersion } from "./versions-Bg99eDSc.mjs"; | ||
| import { t as formatInfoBox } from "./formatting-BVTBOej7.mjs"; | ||
| import { n as fetchModules, t as checkNuxtCompatibility } from "./_utils-Co1L4CHe.mjs"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { box } from "@clack/prompts"; | ||
| import { kebabCase, upperFirst } from "scule"; | ||
| import Fuse from "fuse.js"; | ||
| //#region ../nuxi/src/commands/module/search.ts | ||
| const DASH_RE = /-/g; | ||
| const { format: formatNumber } = Intl.NumberFormat("en-GB", { | ||
| notation: "compact", | ||
| maximumFractionDigits: 1 | ||
| }); | ||
| var search_default = defineCommand({ | ||
| meta: { | ||
| name: "search", | ||
| description: "Search in Nuxt modules" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| query: { | ||
| type: "positional", | ||
| description: "keywords to search for", | ||
| required: true | ||
| }, | ||
| nuxtVersion: { | ||
| type: "string", | ||
| description: "Filter by Nuxt version and list compatible modules only (auto detected by default)", | ||
| required: false, | ||
| valueHint: "2|3" | ||
| } | ||
| }, | ||
| async setup(ctx) { | ||
| const nuxtVersion = await getNuxtVersion(ctx.args.cwd); | ||
| return findModuleByKeywords(ctx.args._.join(" "), nuxtVersion); | ||
| } | ||
| }); | ||
| async function findModuleByKeywords(query, nuxtVersion) { | ||
| const results = new Fuse((await fetchModules()).filter((m) => checkNuxtCompatibility(m, nuxtVersion)), { | ||
| threshold: .1, | ||
| keys: [ | ||
| { | ||
| name: "name", | ||
| weight: 1 | ||
| }, | ||
| { | ||
| name: "npm", | ||
| weight: 1 | ||
| }, | ||
| { | ||
| name: "repo", | ||
| weight: 1 | ||
| }, | ||
| { | ||
| name: "tags", | ||
| weight: 1 | ||
| }, | ||
| { | ||
| name: "category", | ||
| weight: 1 | ||
| }, | ||
| { | ||
| name: "description", | ||
| weight: .5 | ||
| }, | ||
| { | ||
| name: "maintainers.name", | ||
| weight: .5 | ||
| }, | ||
| { | ||
| name: "maintainers.github", | ||
| weight: .5 | ||
| } | ||
| ] | ||
| }).search(query).map((result) => { | ||
| const res = { | ||
| name: result.item.name, | ||
| package: result.item.npm, | ||
| homepage: colors.cyan(result.item.website), | ||
| compatibility: `nuxt: ${result.item.compatibility?.nuxt || "*"}`, | ||
| repository: result.item.github, | ||
| description: result.item.description, | ||
| install: `npx nuxt add ${result.item.name}`, | ||
| stars: colors.yellow(formatNumber(result.item.stats.stars)), | ||
| monthlyDownloads: colors.yellow(formatNumber(result.item.stats.downloads)) | ||
| }; | ||
| if (result.item.github === result.item.website) delete res.homepage; | ||
| if (result.item.name === result.item.npm) delete res.packageName; | ||
| return res; | ||
| }); | ||
| if (!results.length) { | ||
| logger.info(`No Nuxt modules found matching query ${colors.magenta(query)} for Nuxt ${colors.cyan(nuxtVersion)}`); | ||
| return; | ||
| } | ||
| logger.success(`Found ${results.length} Nuxt ${results.length > 1 ? "modules" : "module"} matching ${colors.cyan(query)} ${nuxtVersion ? `for Nuxt ${colors.cyan(nuxtVersion)}` : ""}:\n`); | ||
| for (const foundModule of results) { | ||
| const formattedModule = {}; | ||
| for (const [key, val] of Object.entries(foundModule)) { | ||
| const label = upperFirst(kebabCase(key)).replace(DASH_RE, " "); | ||
| formattedModule[label] = val; | ||
| } | ||
| const title = formattedModule.Name || formattedModule.Package; | ||
| delete formattedModule.Name; | ||
| box(`\n${formatInfoBox(formattedModule)}`, ` ${title} `, { | ||
| contentAlign: "left", | ||
| titleAlign: "left", | ||
| width: "auto", | ||
| titlePadding: 2, | ||
| contentPadding: 2, | ||
| rounded: true | ||
| }); | ||
| } | ||
| } | ||
| //#endregion | ||
| export { search_default as default }; |
| import { t as __exportAll } from "./rolldown-runtime-95iHPtFO.mjs"; | ||
| //#region ../nuxi/src/data/templates.ts | ||
| var templates_exports = /* @__PURE__ */ __exportAll({ templates: () => templates }); | ||
| const templates = { | ||
| "content": { | ||
| "name": "content", | ||
| "description": "Content-driven website", | ||
| "defaultDir": "nuxt-app", | ||
| "url": "https://content.nuxt.com", | ||
| "tar": "https://codeload.github.com/nuxt/starter/tar.gz/refs/heads/content" | ||
| }, | ||
| "minimal": { | ||
| "name": "minimal", | ||
| "description": "Minimal setup for Nuxt 4", | ||
| "defaultDir": "nuxt-app", | ||
| "url": "https://nuxt.com", | ||
| "tar": "https://codeload.github.com/nuxt/starter/tar.gz/refs/heads/v4" | ||
| }, | ||
| "module": { | ||
| "name": "module", | ||
| "description": "Nuxt module", | ||
| "defaultDir": "nuxt-module", | ||
| "url": "https://nuxt.com", | ||
| "tar": "https://codeload.github.com/nuxt/starter/tar.gz/refs/heads/module" | ||
| }, | ||
| "ui": { | ||
| "name": "ui", | ||
| "description": "App using Nuxt UI", | ||
| "defaultDir": "nuxt-app", | ||
| "url": "https://ui.nuxt.com", | ||
| "tar": "https://codeload.github.com/nuxt-ui-templates/starter/tar.gz/refs/heads/main" | ||
| } | ||
| }; | ||
| //#endregion | ||
| export { templates_exports as n, templates as t }; |
| import { resolve } from "pathe"; | ||
| import { camelCase, pascalCase } from "scule"; | ||
| //#region ../nuxi/src/utils/templates/api.ts | ||
| const httpMethods = [ | ||
| "connect", | ||
| "delete", | ||
| "get", | ||
| "head", | ||
| "options", | ||
| "post", | ||
| "put", | ||
| "trace", | ||
| "patch" | ||
| ]; | ||
| const api = ({ name, args, nuxtOptions }) => { | ||
| return { | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, `api/${name}${applySuffix(args, httpMethods, "method")}.ts`), | ||
| contents: ` | ||
| export default defineEventHandler(event => { | ||
| return 'Hello ${name}' | ||
| }) | ||
| ` | ||
| }; | ||
| }; | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/app.ts | ||
| const app = ({ args, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, "app.vue"), | ||
| contents: args.pages ? ` | ||
| <script setup lang="ts"><\/script> | ||
| <template> | ||
| <div> | ||
| <NuxtLayout> | ||
| <NuxtPage/> | ||
| </NuxtLayout> | ||
| </div> | ||
| </template> | ||
| <style scoped></style> | ||
| ` : ` | ||
| <script setup lang="ts"><\/script> | ||
| <template> | ||
| <div> | ||
| <h1>Hello World!</h1> | ||
| </div> | ||
| </template> | ||
| <style scoped></style> | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/app-config.ts | ||
| const appConfig = ({ nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, "app.config.ts"), | ||
| contents: ` | ||
| export default defineAppConfig({}) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/component.ts | ||
| const component = ({ name, args, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, `components/${name}${applySuffix(args, ["client", "server"], "mode")}.vue`), | ||
| contents: ` | ||
| <script setup lang="ts"><\/script> | ||
| <template> | ||
| <div> | ||
| Component: ${name} | ||
| </div> | ||
| </template> | ||
| <style scoped></style> | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/composable.ts | ||
| const USE_PREFIX_RE = /^use-?/; | ||
| const composable = ({ name, nuxtOptions }) => { | ||
| const nameWithUsePrefix = `use${pascalCase(name.replace(USE_PREFIX_RE, ""))}`; | ||
| return { | ||
| path: resolve(nuxtOptions.srcDir, `composables/${name}.ts`), | ||
| contents: ` | ||
| export const ${nameWithUsePrefix} = () => { | ||
| return ref() | ||
| } | ||
| ` | ||
| }; | ||
| }; | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/error.ts | ||
| const error = ({ nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, "error.vue"), | ||
| contents: ` | ||
| <script setup lang="ts"> | ||
| import type { NuxtError } from '#app' | ||
| const props = defineProps({ | ||
| error: Object as () => NuxtError | ||
| }) | ||
| <\/script> | ||
| <template> | ||
| <div> | ||
| <h1>{{ error.statusCode }}</h1> | ||
| <NuxtLink to="/">Go back home</NuxtLink> | ||
| </div> | ||
| </template> | ||
| <style scoped></style> | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/layer.ts | ||
| const layer = ({ name, nuxtOptions }) => { | ||
| return { | ||
| path: resolve(nuxtOptions.rootDir, `layers/${name}/nuxt.config.ts`), | ||
| contents: ` | ||
| export default defineNuxtConfig({}) | ||
| ` | ||
| }; | ||
| }; | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/layout.ts | ||
| const layout = ({ name, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.layouts, `${name}.vue`), | ||
| contents: ` | ||
| <script setup lang="ts"><\/script> | ||
| <template> | ||
| <div> | ||
| Layout: ${name} | ||
| <slot /> | ||
| </div> | ||
| </template> | ||
| <style scoped></style> | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/middleware.ts | ||
| const middleware = ({ name, args, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.middleware, `${name}${applySuffix(args, ["global"])}.ts`), | ||
| contents: ` | ||
| export default defineNuxtRouteMiddleware((to, from) => {}) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/module.ts | ||
| const module = ({ name, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.rootDir, "modules", `${name}.ts`), | ||
| contents: ` | ||
| import { defineNuxtModule } from 'nuxt/kit' | ||
| export default defineNuxtModule({ | ||
| meta: { | ||
| name: '${name}' | ||
| }, | ||
| setup () {} | ||
| }) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/page.ts | ||
| const page = ({ name, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.pages, `${name}.vue`), | ||
| contents: ` | ||
| <script setup lang="ts"><\/script> | ||
| <template> | ||
| <div> | ||
| Page: ${name} | ||
| </div> | ||
| </template> | ||
| <style scoped></style> | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/plugin.ts | ||
| const plugin = ({ name, args, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.plugins, `${name}${applySuffix(args, ["client", "server"], "mode")}.ts`), | ||
| contents: ` | ||
| export default defineNuxtPlugin(nuxtApp => {}) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/server-middleware.ts | ||
| const serverMiddleware = ({ name, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, "middleware", `${name}.ts`), | ||
| contents: ` | ||
| export default defineEventHandler(event => {}) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/server-plugin.ts | ||
| const serverPlugin = ({ name, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, "plugins", `${name}.ts`), | ||
| contents: ` | ||
| export default defineNitroPlugin(nitroApp => {}) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/server-route.ts | ||
| const serverRoute = ({ name, args, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, args.api ? "api" : "routes", `${name}.ts`), | ||
| contents: ` | ||
| export default defineEventHandler(event => {}) | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/server-util.ts | ||
| const serverUtil = ({ name, nuxtOptions }) => ({ | ||
| path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, "utils", `${name}.ts`), | ||
| contents: ` | ||
| export function ${camelCase(name)}() {} | ||
| ` | ||
| }); | ||
| //#endregion | ||
| //#region ../nuxi/src/utils/templates/index.ts | ||
| const templates = { | ||
| "api": api, | ||
| "app": app, | ||
| "app-config": appConfig, | ||
| "component": component, | ||
| "composable": composable, | ||
| "error": error, | ||
| "layer": layer, | ||
| "layout": layout, | ||
| "middleware": middleware, | ||
| "module": module, | ||
| "page": page, | ||
| "plugin": plugin, | ||
| "server-middleware": serverMiddleware, | ||
| "server-plugin": serverPlugin, | ||
| "server-route": serverRoute, | ||
| "server-util": serverUtil | ||
| }; | ||
| const _templateNames = { | ||
| "api": void 0, | ||
| "app": void 0, | ||
| "app-config": void 0, | ||
| "component": void 0, | ||
| "composable": void 0, | ||
| "error": void 0, | ||
| "layer": void 0, | ||
| "layout": void 0, | ||
| "middleware": void 0, | ||
| "module": void 0, | ||
| "page": void 0, | ||
| "plugin": void 0, | ||
| "server-middleware": void 0, | ||
| "server-plugin": void 0, | ||
| "server-route": void 0, | ||
| "server-util": void 0 | ||
| }; | ||
| const templateNames = Object.keys(_templateNames); | ||
| function applySuffix(args, suffixes, unwrapFrom) { | ||
| let suffix = ""; | ||
| for (const s of suffixes) if (args[s]) suffix += `.${s}`; | ||
| if (unwrapFrom && args[unwrapFrom] && suffixes.includes(args[unwrapFrom])) suffix += `.${args[unwrapFrom]}`; | ||
| return suffix; | ||
| } | ||
| //#endregion | ||
| export { templates as n, templateNames as t }; |
| import { a as legacyRootDirArgs, o as logLevelArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { resolve } from "pathe"; | ||
| //#region ../nuxi/src/commands/test.ts | ||
| var test_default = defineCommand({ | ||
| meta: { | ||
| name: "test", | ||
| description: "Run tests" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...legacyRootDirArgs, | ||
| dev: { | ||
| type: "boolean", | ||
| description: "Run in dev mode" | ||
| }, | ||
| watch: { | ||
| type: "boolean", | ||
| description: "Watch mode" | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| process.env.NODE_ENV = process.env.NODE_ENV || "test"; | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const { runTests } = await importTestUtils(); | ||
| await runTests({ | ||
| rootDir: cwd, | ||
| dev: ctx.args.dev, | ||
| watch: ctx.args.watch | ||
| }); | ||
| } | ||
| }); | ||
| async function importTestUtils() { | ||
| let err; | ||
| for (const pkg of [ | ||
| "@nuxt/test-utils-nightly", | ||
| "@nuxt/test-utils-edge", | ||
| "@nuxt/test-utils" | ||
| ]) try { | ||
| const exports = await import(pkg); | ||
| if (!exports.runTests) throw new Error("Invalid version of `@nuxt/test-utils` is installed!"); | ||
| return exports; | ||
| } catch (_err) { | ||
| err = _err; | ||
| } | ||
| logger.error(String(err)); | ||
| throw new Error("`@nuxt/test-utils` seems missing. Run `npm i -D @nuxt/test-utils` or `yarn add -D @nuxt/test-utils` to install."); | ||
| } | ||
| //#endregion | ||
| export { test_default as default }; |
| import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { t as loadKit } from "./kit-DUlGqV3Z.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { isBun } from "std-env"; | ||
| import { resolve } from "pathe"; | ||
| import { resolveModulePath } from "exsolve"; | ||
| import { readTSConfig } from "pkg-types"; | ||
| import { x } from "tinyexec"; | ||
| //#region ../nuxi/src/commands/typecheck.ts | ||
| var typecheck_default = defineCommand({ | ||
| meta: { | ||
| name: "typecheck", | ||
| description: "Runs `vue-tsc` to check types throughout your app." | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...dotEnvArgs, | ||
| ...extendsArgs, | ||
| ...legacyRootDirArgs | ||
| }, | ||
| async run(ctx) { | ||
| process.env.NODE_ENV = process.env.NODE_ENV || "production"; | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| const [supportsProjects, resolvedTypeScript, resolvedVueTsc] = await Promise.all([ | ||
| readTSConfig(cwd).then((r) => !!r.references?.length), | ||
| resolveModulePath("typescript", { try: true }), | ||
| resolveModulePath("vue-tsc/bin/vue-tsc.js", { try: true }), | ||
| writeTypes(cwd, ctx.args.dotenv, ctx.args.logLevel, { | ||
| ...ctx.data?.overrides, | ||
| ...ctx.args.extends && { extends: ctx.args.extends } | ||
| }) | ||
| ]); | ||
| const typeCheckArgs = supportsProjects ? ["-b", "--noEmit"] : ["--noEmit"]; | ||
| if (resolvedTypeScript && resolvedVueTsc) return await x(resolvedVueTsc, typeCheckArgs, { | ||
| throwOnError: true, | ||
| nodeOptions: { | ||
| stdio: "inherit", | ||
| cwd | ||
| } | ||
| }); | ||
| if (isBun) { | ||
| await x("bun", [ | ||
| "install", | ||
| "typescript", | ||
| "vue-tsc", | ||
| "--global", | ||
| "--silent" | ||
| ], { | ||
| throwOnError: true, | ||
| nodeOptions: { | ||
| stdio: "inherit", | ||
| cwd | ||
| } | ||
| }); | ||
| return await x("bunx", ["vue-tsc", ...typeCheckArgs], { | ||
| throwOnError: true, | ||
| nodeOptions: { | ||
| stdio: "inherit", | ||
| cwd | ||
| } | ||
| }); | ||
| } | ||
| await x("npx", [ | ||
| "-p", | ||
| "vue-tsc", | ||
| "-p", | ||
| "typescript", | ||
| "vue-tsc", | ||
| ...typeCheckArgs | ||
| ], { | ||
| throwOnError: true, | ||
| nodeOptions: { | ||
| stdio: "inherit", | ||
| cwd | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
| async function writeTypes(cwd, dotenv, logLevel, overrides) { | ||
| const { loadNuxt, buildNuxt, writeTypes } = await loadKit(cwd); | ||
| const nuxt = await loadNuxt({ | ||
| cwd, | ||
| dotenv: { | ||
| cwd, | ||
| fileName: dotenv | ||
| }, | ||
| overrides: { | ||
| _prepare: true, | ||
| logLevel, | ||
| ...overrides | ||
| } | ||
| }); | ||
| await writeTypes(nuxt); | ||
| await buildNuxt(nuxt); | ||
| await nuxt.close(); | ||
| } | ||
| //#endregion | ||
| export { typecheck_default as default }; |
| import { a as legacyRootDirArgs, o as logLevelArgs, t as cwdArgs } from "./_shared-BsGoKfo3.mjs"; | ||
| import { n as logger } from "./logger-B4ge7MhP.mjs"; | ||
| import { r as relativeToProcess, t as loadKit } from "./kit-DUlGqV3Z.mjs"; | ||
| import { t as getNuxtVersion } from "./versions-Bg99eDSc.mjs"; | ||
| import "./fs-B8DrLsZ2.mjs"; | ||
| import { r as nuxtVersionToGitIdentifier, t as cleanupNuxtDirs } from "./nuxt-CsZm8Jhw.mjs"; | ||
| import { t as getPackageManagerVersion } from "./packageManagers-BadBU-Pz.mjs"; | ||
| import process from "node:process"; | ||
| import { defineCommand } from "citty"; | ||
| import { colors } from "consola/utils"; | ||
| import { cancel, intro, isCancel, note, outro, select, spinner, tasks } from "@clack/prompts"; | ||
| import { resolve } from "pathe"; | ||
| import { existsSync } from "node:fs"; | ||
| import { findWorkspaceDir, readPackageJSON } from "pkg-types"; | ||
| import { addDependency, dedupeDependencies, detectPackageManager } from "nypm"; | ||
| //#region ../nuxi/src/commands/upgrade.ts | ||
| function checkNuxtDependencyType(pkg) { | ||
| if (pkg.dependencies?.nuxt) return "dependencies"; | ||
| if (pkg.devDependencies?.nuxt) return "devDependencies"; | ||
| return "dependencies"; | ||
| } | ||
| const nuxtVersionTags = { | ||
| "3.x": "3x", | ||
| "4.x": "latest" | ||
| }; | ||
| function getNightlyDependency(dep, nuxtVersion) { | ||
| return `${dep}@npm:${dep}-nightly@${nuxtVersionTags[nuxtVersion]}`; | ||
| } | ||
| async function getNightlyVersion(packageNames) { | ||
| const nuxtVersion = await select({ | ||
| message: "Which nightly Nuxt release channel do you want to install?", | ||
| options: [{ | ||
| value: "3.x", | ||
| label: "3.x" | ||
| }, { | ||
| value: "4.x", | ||
| label: "4.x" | ||
| }], | ||
| initialValue: "4.x" | ||
| }); | ||
| if (isCancel(nuxtVersion)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| return { | ||
| npmPackages: packageNames.map((p) => getNightlyDependency(p, nuxtVersion)), | ||
| nuxtVersion | ||
| }; | ||
| } | ||
| async function getRequiredNewVersion(packageNames, channel) { | ||
| switch (channel) { | ||
| case "nightly": return getNightlyVersion(packageNames); | ||
| case "v3": return { | ||
| npmPackages: packageNames.map((p) => `${p}@3`), | ||
| nuxtVersion: "3.x" | ||
| }; | ||
| case "v3-nightly": return { | ||
| npmPackages: packageNames.map((p) => getNightlyDependency(p, "3.x")), | ||
| nuxtVersion: "3.x" | ||
| }; | ||
| case "v4": return { | ||
| npmPackages: packageNames.map((p) => `${p}@4`), | ||
| nuxtVersion: "4.x" | ||
| }; | ||
| case "v4-nightly": return { | ||
| npmPackages: packageNames.map((p) => getNightlyDependency(p, "4.x")), | ||
| nuxtVersion: "4.x" | ||
| }; | ||
| default: return { | ||
| npmPackages: packageNames.map((p) => `${p}@latest`), | ||
| nuxtVersion: "4.x" | ||
| }; | ||
| } | ||
| } | ||
| var upgrade_default = defineCommand({ | ||
| meta: { | ||
| name: "upgrade", | ||
| description: "Upgrade Nuxt" | ||
| }, | ||
| args: { | ||
| ...cwdArgs, | ||
| ...logLevelArgs, | ||
| ...legacyRootDirArgs, | ||
| dedupe: { | ||
| type: "boolean", | ||
| description: "Dedupe dependencies after upgrading" | ||
| }, | ||
| force: { | ||
| type: "boolean", | ||
| alias: "f", | ||
| description: "Force upgrade to recreate lockfile and node_modules" | ||
| }, | ||
| channel: { | ||
| type: "string", | ||
| alias: "ch", | ||
| default: "stable", | ||
| description: "Specify a channel to install from (default: stable)", | ||
| valueHint: "stable|nightly|v3|v4|v4-nightly|v3-nightly" | ||
| } | ||
| }, | ||
| async run(ctx) { | ||
| const cwd = resolve(ctx.args.cwd || ctx.args.rootDir); | ||
| intro(colors.cyan("Upgrading Nuxt ...")); | ||
| const [packageManager, workspaceDir = cwd] = await Promise.all([detectPackageManager(cwd), findWorkspaceDir(cwd, { try: true })]); | ||
| if (!packageManager) { | ||
| logger.error(`Unable to determine the package manager used by this project.\n\nNo lock files found in ${colors.cyan(relativeToProcess(cwd))}, and no ${colors.cyan("packageManager")} field specified in ${colors.cyan("package.json")}.`); | ||
| logger.info(`Please either add the ${colors.cyan("packageManager")} field to ${colors.cyan("package.json")} or execute the installation command for your package manager. For example, you can use ${colors.cyan("pnpm i")}, ${colors.cyan("npm i")}, ${colors.cyan("bun i")}, or ${colors.cyan("yarn i")}, and then try again.`); | ||
| process.exit(1); | ||
| } | ||
| const { name: packageManagerName, lockFile: lockFileCandidates } = packageManager; | ||
| const packageManagerVersion = getPackageManagerVersion(packageManagerName); | ||
| logger.step(`Package manager: ${colors.cyan(packageManagerName)} ${packageManagerVersion}`); | ||
| const currentVersion = await getNuxtVersion(cwd, false) || "[unknown]"; | ||
| logger.step(`Current Nuxt version: ${colors.cyan(currentVersion)}`); | ||
| const pkg = await readPackageJSON(cwd).catch(() => null); | ||
| const nuxtDependencyType = pkg ? checkNuxtDependencyType(pkg) : "dependencies"; | ||
| const { npmPackages, nuxtVersion } = await getRequiredNewVersion(["nuxt", ...pkg ? [ | ||
| "@nuxt/kit", | ||
| "@nuxt/schema", | ||
| "@nuxt/vite-builder", | ||
| "@nuxt/webpack-builder", | ||
| "@nuxt/rspack-builder" | ||
| ].filter((p) => pkg.dependencies?.[p] || pkg.devDependencies?.[p]) : []], ctx.args.channel); | ||
| const toRemove = ["node_modules"]; | ||
| const lockFile = normaliseLockFile(workspaceDir, lockFileCandidates); | ||
| if (lockFile) toRemove.push(lockFile); | ||
| const forceRemovals = toRemove.map((p) => colors.cyan(p)).join(" and "); | ||
| let method = ctx.args.force ? "force" : ctx.args.dedupe ? "dedupe" : void 0; | ||
| if (!method) { | ||
| const result = await select({ | ||
| message: `Would you like to dedupe your lockfile, or recreate ${forceRemovals}? This can fix problems with hoisted dependency versions and ensure you have the most up-to-date dependencies.`, | ||
| options: [ | ||
| { | ||
| label: "dedupe lockfile", | ||
| value: "dedupe", | ||
| hint: "recommended" | ||
| }, | ||
| { | ||
| label: `recreate ${forceRemovals}`, | ||
| value: "force" | ||
| }, | ||
| { | ||
| label: "skip", | ||
| value: "skip" | ||
| } | ||
| ], | ||
| initialValue: "dedupe" | ||
| }); | ||
| if (isCancel(result)) { | ||
| cancel("Operation cancelled."); | ||
| process.exit(1); | ||
| } | ||
| method = result; | ||
| } | ||
| const versionType = ctx.args.channel === "nightly" ? "nightly" : `latest ${ctx.args.channel}`; | ||
| const spin = spinner(); | ||
| spin.start("Upgrading Nuxt"); | ||
| await tasks([ | ||
| { | ||
| title: `Installing ${versionType} Nuxt ${nuxtVersion} release`, | ||
| task: async () => { | ||
| await addDependency(npmPackages, { | ||
| cwd, | ||
| packageManager, | ||
| dev: nuxtDependencyType === "devDependencies", | ||
| workspace: packageManager?.name === "pnpm" && existsSync(resolve(cwd, "pnpm-workspace.yaml")) | ||
| }); | ||
| return "Nuxt packages installed"; | ||
| } | ||
| }, | ||
| ...method === "force" ? [{ | ||
| title: `Recreating ${forceRemovals}`, | ||
| task: async () => { | ||
| await dedupeDependencies({ recreateLockfile: true }); | ||
| return "Lockfile recreated"; | ||
| } | ||
| }] : [], | ||
| ...method === "dedupe" ? [{ | ||
| title: "Deduping dependencies", | ||
| task: async () => { | ||
| await dedupeDependencies(); | ||
| return "Dependencies deduped"; | ||
| } | ||
| }] : [], | ||
| { | ||
| title: "Cleaning up build directories", | ||
| task: async () => { | ||
| let buildDir = ".nuxt"; | ||
| try { | ||
| const { loadNuxtConfig } = await loadKit(cwd); | ||
| buildDir = (await loadNuxtConfig({ cwd })).buildDir; | ||
| } catch {} | ||
| await cleanupNuxtDirs(cwd, buildDir); | ||
| return "Build directories cleaned"; | ||
| } | ||
| } | ||
| ]); | ||
| spin.stop(); | ||
| if (method === "force") logger.info(`If you encounter any issues, revert the changes and try with ${colors.cyan("--no-force")}`); | ||
| const upgradedVersion = await getNuxtVersion(cwd, false) || "[unknown]"; | ||
| if (upgradedVersion === "[unknown]") return; | ||
| if (upgradedVersion === currentVersion) outro(`You were already using the latest version of Nuxt (${colors.green(currentVersion)})`); | ||
| else { | ||
| logger.success(`Successfully upgraded Nuxt from ${colors.cyan(currentVersion)} to ${colors.green(upgradedVersion)}`); | ||
| if (currentVersion === "[unknown]") return; | ||
| const commitA = nuxtVersionToGitIdentifier(currentVersion); | ||
| const commitB = nuxtVersionToGitIdentifier(upgradedVersion); | ||
| if (commitA && commitB) note(`https://github.com/nuxt/nuxt/compare/${commitA}...${commitB}`, "Changelog"); | ||
| outro("✨ Upgrade complete!"); | ||
| } | ||
| } | ||
| }); | ||
| function normaliseLockFile(cwd, lockFiles) { | ||
| if (typeof lockFiles === "string") lockFiles = [lockFiles]; | ||
| const lockFile = lockFiles?.find((file) => existsSync(resolve(cwd, file))); | ||
| if (lockFile === void 0) { | ||
| logger.error(`Unable to find any lock files in ${colors.cyan(relativeToProcess(cwd))}.`); | ||
| return; | ||
| } | ||
| return lockFile; | ||
| } | ||
| //#endregion | ||
| export { upgrade_default as default }; |
| import { n as tryResolveNuxt } from "./kit-DUlGqV3Z.mjs"; | ||
| import { readFileSync } from "node:fs"; | ||
| import { resolveModulePath } from "exsolve"; | ||
| import { readPackageJSON } from "pkg-types"; | ||
| import { coerce } from "semver"; | ||
| //#region ../nuxi/src/utils/versions.ts | ||
| async function getNuxtVersion(cwd, cache = true) { | ||
| const nuxtPkg = await readPackageJSON("nuxt", { | ||
| url: cwd, | ||
| try: true, | ||
| cache | ||
| }); | ||
| if (nuxtPkg) return nuxtPkg.version; | ||
| const pkg = await readPackageJSON(cwd); | ||
| const pkgDep = pkg?.dependencies?.nuxt || pkg?.devDependencies?.nuxt; | ||
| return pkgDep && coerce(pkgDep)?.version || "3.0.0"; | ||
| } | ||
| function getPkgVersion(cwd, pkg) { | ||
| return getPkgJSON(cwd, pkg)?.version ?? ""; | ||
| } | ||
| function getPkgJSON(cwd, pkg) { | ||
| for (const url of [cwd, tryResolveNuxt(cwd)]) { | ||
| if (!url) continue; | ||
| const p = resolveModulePath(`${pkg}/package.json`, { | ||
| from: url, | ||
| try: true | ||
| }); | ||
| if (p) return JSON.parse(readFileSync(p, "utf-8")); | ||
| } | ||
| return null; | ||
| } | ||
| //#endregion | ||
| export { getPkgJSON as n, getPkgVersion as r, getNuxtVersion as t }; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 29 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 27 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
181959
3.3%5292
4.03%52
6.12%- Removed
Updated
Updated
Updated
Updated
Updated
Updated
Updated
Updated
Updated
Updated
Updated
Updated