import { o as logLevelArgs, t as cwdArgs } from "./_shared-BCYCnX0T.mjs"; import { n as logger } from "./logger-B4ge7MhP.mjs"; import { r as relativeToProcess } from "./kit-B3S8uoS_.mjs"; import { t as getNuxtVersion } from "./versions-Bly87QYZ.mjs"; import { n as fetchModules, r as getRegistryFromContent, t as checkNuxtCompatibility } from "./_utils-NB3Cn3-G.mjs"; import { t as prepare_default } from "./prepare-CUaf6Joj.mjs"; import { join } from "node:path"; import process from "node:process"; import { defineCommand, runCommand } from "citty"; import { colors } from "consola/utils"; import { confirm, isCancel, select } from "@clack/prompts"; import { fileURLToPath } from "node:url"; import * as fs from "node:fs"; import { existsSync } from "node:fs"; import { joinURL } from "ufo"; import { resolve as resolve$1 } from "pathe"; import { readPackageJSON } from "pkg-types"; import { satisfies } from "semver"; import { homedir } from "node:os"; import { addDependency, detectPackageManager } from "nypm"; import { $fetch } from "ofetch"; import { updateConfig } from "c12/update"; //#region ../nuxi/src/commands/_utils.ts const nuxiCommands = [ "add", "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/add.ts 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); const 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); } const resolvedModules = (await Promise.all(modules.map((moduleName) => resolveModule(moduleName, cwd)))).filter((x) => x != null); 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, skipConfig, cwd, dev }, 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(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 }); 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 authTokenRegex = new RegExp(`^//${registry.replace(/^https?:\/\//, "").replace(/\/$/, "")}/:_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 n, add_default as t };