penambahan web socket

This commit is contained in:
2025-09-18 19:01:22 +07:00
parent 1d053646a9
commit d7bb2eb5bb
15070 changed files with 2402916 additions and 0 deletions

No files matched your search

@@ -0,0 +1,330 @@
import * as fs from 'node:fs';
import { homedir } from 'node:os';
import { join } from 'node:path';
import process from 'node:process';
import { updateConfig } from 'c12/update';
import { defineCommand } from 'citty';
import { colors } from 'consola/utils';
import { addDependency } from 'nypm';
import { $fetch } from 'ofetch';
import { resolve } from 'pathe';
import { readPackageJSON } from 'pkg-types';
import { satisfies } from 'semver';
import { joinURL } from 'ufo';
import { r as runCommand } from '../shared/cli.vXg4eLNu.mjs';
import { l as logger } from '../shared/cli.B9AmABr3.mjs';
import { g as getNuxtVersion } from '../shared/cli.DHenkA1C.mjs';
import { a as logLevelArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import { f as fetchModules, c as checkNuxtCompatibility, g as getRegistryFromContent } from '../shared/cli.Cr-OCgdO.mjs';
import 'node:url';
import 'node:crypto';
import 'std-env';
import '../shared/cli.DhJ3cH8w.mjs';
import 'consola';
import 'confbox';
const add = 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(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 \`nuxt\` dependency detected in \`${cwd}\`.`);
const shouldContinue = await logger.prompt(
`Do you want to continue anyway?`,
{
type: "confirm",
initial: false,
cancel: "default"
}
);
if (shouldContinue !== true) {
process.exit(1);
}
}
const maybeResolvedModules = await Promise.all(modules.map((moduleName) => resolveModule(moduleName, cwd)));
const resolvedModules = maybeResolvedModules.filter((x) => x != null);
logger.info(`Resolved \`${resolvedModules.map((x) => x.pkgName).join("`, `")}\`, adding module${resolvedModules.length > 1 ? "s" : ""}...`);
await addModules(resolvedModules, { ...ctx.args, cwd }, projectPkg);
if (!ctx.args.skipInstall) {
const args = Object.entries(ctx.args).filter(([k]) => k in cwdArgs || k in logLevelArgs).map(([k, v]) => `--${k}=${v}`);
await runCommand("prepare", args);
}
}
});
async function addModules(modules, { skipInstall, skipConfig, cwd, dev }, projectPkg) {
if (!skipInstall) {
const installedModules = [];
const notInstalledModules = [];
const dependencies = /* @__PURE__ */ 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) => 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) => 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 res = await addDependency(notInstalledModules.map((module) => module.pkg), {
cwd,
dev: isDev,
installPeerDependencies: true
}).then(() => true).catch(
(error) => {
logger.error(error);
const failedModulesList = notInstalledModules.map((module) => colors.cyan(module.pkg)).join("`, `");
const s = notInstalledModules.length > 1 ? "s" : "";
return logger.prompt(`Install failed for \`${failedModulesList}\`. Do you want to continue adding the module${s} to ${colors.cyan("nuxt.config")}?`, {
type: "confirm",
initial: false,
cancel: "default"
});
}
);
if (res !== true) {
return;
}
}
}
if (!skipConfig) {
await updateConfig({
cwd,
configFile: "nuxt.config",
async onCreate() {
logger.info(`Creating \`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(`\`${resolved.pkgName}\` is already in the \`modules\``);
continue;
}
logger.info(`Adding \`${resolved.pkgName}\` to the \`modules\``);
config.modules.push(resolved.pkgName);
}
}
}).catch((error) => {
logger.error(`Failed to update \`nuxt.config\`: ${error.message}`);
logger.error(`Please manually add \`${modules.map((module) => module.pkgName).join("`, `")}\` to the \`modules\` in \`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 \`${pkgName}\`.`);
return false;
}
const modulesDB = await fetchModules().catch((err) => {
logger.warn(`Cannot search in the Nuxt Modules database: ${err}`);
return [];
});
const matchedModule = modulesDB.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 \`${pkgName}\` is not compatible with Nuxt \`${nuxtVersion}\` (requires \`${matchedModule.compatibility.nuxt}\`)`
);
const shouldContinue = await logger.prompt(
"Do you want to continue installing incompatible version?",
{
type: "confirm",
initial: false,
cancel: "default"
}
);
if (!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 \`${pkgName}\` for Nuxt \`${nuxtVersion}\` is \`${_moduleVersion}\` but you have requested \`${pkgVersion}\``
);
pkgVersion = await logger.prompt("Choose a version:", {
type: "select",
options: [_moduleVersion, pkgVersion],
cancel: "undefined"
});
if (!pkgVersion) {
return false;
}
}
break;
}
}
}
}
let version = pkgVersion || "latest";
const pkgScope = pkgName.startsWith("@") ? pkgName.split("/")[0] : null;
const meta = await detectNpmRegistry(pkgScope);
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 \`${pkgName}\` is not a Nuxt module.`);
const shouldContinue = await logger.prompt(
`Do you want to continue installing ${colors.cyan(pkgName)} anyway?`,
{
type: "confirm",
initial: false,
cancel: "default"
}
);
if (!shouldContinue) {
return false;
}
}
return {
nuxtModule: matchedModule,
pkg: `${pkgName}@${version}`,
pkgName,
pkgVersion: version
};
}
function getNpmrcPaths() {
const userNpmrcPath = join(homedir(), ".npmrc");
const cwdNpmrcPath = join(process.cwd(), ".npmrc");
return [cwdNpmrcPath, 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 npmrcContent = await fd.readFile("utf-8");
const authTokenMatch = npmrcContent.match(authTokenRegex)?.[1];
if (authTokenMatch) {
return authTokenMatch.trim();
}
}
} catch {
} finally {
await fd?.close();
}
}
return null;
}
async function detectNpmRegistry(scope) {
const registry = await getRegistry(scope);
const authToken = await getAuthToken(registry);
return {
registry,
authToken
};
}
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 npmrcContent = await fd.readFile("utf-8");
const registry = getRegistryFromContent(npmrcContent, scope);
if (registry) {
return registry;
}
}
} catch {
} finally {
await fd?.close();
}
}
return null;
}
export { add as default };
@@ -0,0 +1,319 @@
import { existsSync, promises } from 'node:fs';
import process from 'node:process';
import { defineCommand } from 'citty';
import { resolve, extname, dirname } from 'pathe';
import { l as loadKit } from '../shared/cli.qKvs7FJ2.mjs';
import { l as logger } from '../shared/cli.B9AmABr3.mjs';
import { pascalCase, camelCase } from 'scule';
import { a as logLevelArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'node:url';
import 'exsolve';
import 'consola';
import 'node:path';
import 'std-env';
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}'
})
`
};
};
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>
`
});
const appConfig = ({ nuxtOptions }) => ({
path: resolve(nuxtOptions.srcDir, "app.config.ts"),
contents: `
export default defineAppConfig({})
`
});
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>
`
});
const composable = ({ name, nuxtOptions }) => {
const nameWithoutUsePrefix = name.replace(/^use-?/, "");
const nameWithUsePrefix = `use${pascalCase(nameWithoutUsePrefix)}`;
return {
path: resolve(nuxtOptions.srcDir, `composables/${name}.ts`),
contents: `
export const ${nameWithUsePrefix} = () => {
return ref()
}
`
};
};
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>
`
});
const layer = ({ name, nuxtOptions }) => {
return {
path: resolve(nuxtOptions.rootDir, `layers/${name}/nuxt.config.ts`),
contents: `
export default defineNuxtConfig({})
`
};
};
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>
`
});
const middleware = ({ name, args, nuxtOptions }) => ({
path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.middleware, `${name}${applySuffix(args, ["global"])}.ts`),
contents: `
export default defineNuxtRouteMiddleware((to, from) => {})
`
});
const module = ({ name, nuxtOptions }) => ({
path: resolve(nuxtOptions.rootDir, "modules", `${name}.ts`),
contents: `
import { defineNuxtModule } from 'nuxt/kit'
export default defineNuxtModule({
meta: {
name: '${name}'
},
setup () {}
})
`
});
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>
`
});
const plugin = ({ name, args, nuxtOptions }) => ({
path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.plugins, `${name}${applySuffix(args, ["client", "server"], "mode")}.ts`),
contents: `
export default defineNuxtPlugin(nuxtApp => {})
`
});
const serverMiddleware = ({ name, nuxtOptions }) => ({
path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, "middleware", `${name}.ts`),
contents: `
export default defineEventHandler(event => {})
`
});
const serverPlugin = ({ name, nuxtOptions }) => ({
path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, "plugins", `${name}.ts`),
contents: `
export default defineNitroPlugin(nitroApp => {})
`
});
const serverRoute = ({ name, args, nuxtOptions }) => ({
path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, args.api ? "api" : "routes", `${name}.ts`),
contents: `
export default defineEventHandler(event => {})
`
});
const serverUtil = ({ name, nuxtOptions }) => ({
path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, "utils", `${name}.ts`),
contents: `
export function ${camelCase(name)}() {}
`
});
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;
}
const templateNames = Object.keys(templates);
const add = defineCommand({
meta: {
name: "add",
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);
const templateName = ctx.args.template;
if (!templateNames.includes(templateName)) {
logger.error(
`Template ${templateName} is not supported. Possible values: ${Object.keys(
templates
).join(", ")}`
);
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) {
logger.error("name argument is missing!");
process.exit(1);
}
const kit = await loadKit(cwd);
const config = await kit.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: ${res.path} . Use --force to override or use a different name.`
);
process.exit(1);
}
const parentDir = dirname(res.path);
if (!existsSync(parentDir)) {
logger.info("Creating directory", 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()}
`);
logger.info(`\u{1FA84} Generated a new ${templateName} in ${res.path}`);
}
});
export { add as default };
@@ -0,0 +1,139 @@
import { promises } from 'node:fs';
import process from 'node:process';
import { defineCommand } from 'citty';
import { defu } from 'defu';
import { createApp, lazyEventHandler, eventHandler, toNodeListener } from 'h3';
import { listen } from 'listhen';
import { resolve, join } from 'pathe';
import { o as overrideEnv } from '../shared/cli.BEUGgaW4.mjs';
import { c as clearDir } from '../shared/cli.pLQ0oPGc.mjs';
import { l as loadKit } from '../shared/cli.qKvs7FJ2.mjs';
import { l as logger } from '../shared/cli.B9AmABr3.mjs';
import { e as extendsArgs, d as dotEnvArgs, l as legacyRootDirArgs, a as logLevelArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'node:url';
import 'exsolve';
import 'consola';
import 'node:path';
import 'std-env';
const analyze = 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(/[^\w-]/g, "_");
const startTime = Date.now();
const { loadNuxt, buildNuxt } = await loadKit(cwd);
const nuxt = await loadNuxt({
cwd,
dotenv: {
cwd,
fileName: ctx.args.dotenv
},
overrides: defu(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(nuxt.options.build.analyze, {
filename: join(analyzeDir, "client.html")
});
await clearDir(analyzeDir);
await buildNuxt(nuxt);
const endTime = Date.now();
const meta = {
name,
slug,
startTime,
endTime,
analyzeDir,
buildDir,
outDir
};
await nuxt.callHook("build:analyze:done", meta);
await promises.writeFile(
join(analyzeDir, "meta.json"),
JSON.stringify(meta, null, 2),
"utf-8"
);
logger.info(`Analyze results are available at: \`${analyzeDir}\``);
logger.warn("Do not deploy analyze results! Use `nuxi build` before deploying.");
if (ctx.args.serve !== false && !process.env.CI) {
const app = createApp();
const serveFile = (filePath) => lazyEventHandler(async () => {
const contents = await promises.readFile(filePath, "utf-8");
return eventHandler((event) => {
event.node.res.end(contents);
});
});
logger.info("Starting stats server...");
app.use("/client", serveFile(join(analyzeDir, "client.html")));
app.use("/nitro", serveFile(join(analyzeDir, "nitro.html")));
app.use(
eventHandler(
() => `<!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>
`
)
);
await listen(toNodeListener(app));
}
}
});
export { analyze as default };
@@ -0,0 +1,92 @@
import process from 'node:process';
import { defineCommand } from 'citty';
import { resolve, relative } from 'pathe';
import { s as showVersions } from '../shared/cli.Dz2be-Ai.mjs';
import { o as overrideEnv } from '../shared/cli.BEUGgaW4.mjs';
import { a as clearBuildDir } from '../shared/cli.pLQ0oPGc.mjs';
import { l as loadKit } from '../shared/cli.qKvs7FJ2.mjs';
import { l as logger } from '../shared/cli.B9AmABr3.mjs';
import { l as legacyRootDirArgs, e as extendsArgs, b as envNameArgs, d as dotEnvArgs, a as logLevelArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'node:fs';
import 'consola/utils';
import 'exsolve';
import 'node:url';
import 'consola';
import 'node:path';
import 'std-env';
const buildCommand = 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,
...legacyRootDirArgs
},
async run(ctx) {
overrideEnv("production");
const cwd = resolve(ctx.args.cwd || ctx.args.rootDir);
showVersions(cwd);
const kit = await loadKit(cwd);
const nuxt = await kit.loadNuxt({
cwd,
dotenv: {
cwd,
fileName: ctx.args.dotenv
},
envName: ctx.args.envName,
// c12 will fall back to NODE_ENV
overrides: {
logLevel: ctx.args.logLevel,
// TODO: remove in 3.8
_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
}
});
let nitro;
try {
nitro = kit.useNitro?.();
logger.info(`Building for Nitro preset: \`${nitro.options.preset}\``);
} catch {
}
await clearBuildDir(nuxt.options.buildDir);
await kit.writeTypes(nuxt);
nuxt.hook("build:error", (err) => {
logger.error("Nuxt Build Error:", err);
process.exit(1);
});
await kit.buildNuxt(nuxt);
if (ctx.args.prerender) {
if (!nuxt.options.ssr) {
logger.warn(
"HTML content not prerendered because `ssr: false` was set. You can read more in `https://nuxt.com/docs/getting-started/deployment#static-hosting`."
);
}
const dir = nitro?.options.output.publicDir;
const publicDir = dir ? relative(process.cwd(), dir) : ".output/public";
logger.success(
`You can now deploy \`${publicDir}\` to any static hosting!`
);
}
}
});
export { buildCommand as default };
@@ -0,0 +1,34 @@
import { defineCommand } from 'citty';
import { resolve } from 'pathe';
import { l as loadKit } from '../shared/cli.qKvs7FJ2.mjs';
import { c as cleanupNuxtDirs } from '../shared/cli.At9IMXtr.mjs';
import { l as legacyRootDirArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'node:url';
import 'exsolve';
import 'node:fs';
import 'ohash';
import '../shared/cli.B9AmABr3.mjs';
import 'consola';
import '../shared/cli.pLQ0oPGc.mjs';
import 'node:path';
import 'node:process';
import 'std-env';
const cleanup = 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);
}
});
export { cleanup as default };
@@ -0,0 +1,38 @@
import process from 'node:process';
import { defineCommand } from 'citty';
import { resolve } from 'pathe';
import { isTest } from 'std-env';
import { l as legacyRootDirArgs, d as dotEnvArgs, b as envNameArgs, a as logLevelArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'node:path';
import 'consola';
import '../shared/cli.B9AmABr3.mjs';
import 'node:url';
const devChild = 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('./index.mjs').then(function (n) { return n.c; });
await initialize({ cwd, args: ctx.args }, ctx);
}
});
export { devChild as default };
@@ -0,0 +1,376 @@
import { fork } from 'node:child_process';
import process from 'node:process';
import { defineCommand } from 'citty';
import { isSocketSupported } from 'get-port-please';
import { createProxyServer } from 'httpxy';
import { listen } from 'listhen';
import { getArgs, parseArgs } from 'listhen/cli';
import { resolve } from 'pathe';
import { satisfies } from 'semver';
import { isTest, isBun, isDeno } from 'std-env';
import { i as initialize, r as resolveLoadingTemplate, a as renderError, b as isSocketURL, p as parseSocketURL } from './index.mjs';
import { s as showVersions } from '../shared/cli.Dz2be-Ai.mjs';
import { o as overrideEnv } from '../shared/cli.BEUGgaW4.mjs';
import { l as loadKit } from '../shared/cli.qKvs7FJ2.mjs';
import { l as logger } from '../shared/cli.B9AmABr3.mjs';
import { e as extendsArgs, b as envNameArgs, l as legacyRootDirArgs, d as dotEnvArgs, a as logLevelArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'defu';
import 'node:http';
import 'node:events';
import 'node:fs';
import 'node:fs/promises';
import 'node:url';
import 'exsolve';
import 'h3';
import 'perfect-debounce';
import 'ufo';
import '../shared/cli.pLQ0oPGc.mjs';
import '../shared/cli.At9IMXtr.mjs';
import 'ohash';
import 'youch';
import 'consola/utils';
import 'consola';
import 'node:path';
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",
negativeDescription: "Disable clear console on restart"
},
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 },
"https.domains": {
...listhenArgs["https.domains"],
description: "Comma separated list of domains and IPs, the autogenerated certificate should be valid for (https: true)"
}
},
sslCert: {
type: "string",
description: "(DEPRECATED) Use `--https.cert` instead."
},
sslKey: {
type: "string",
description: "(DEPRECATED) Use `--https.key` instead."
}
},
async run(ctx) {
overrideEnv("development");
const cwd = resolve(ctx.args.cwd || ctx.args.rootDir);
showVersions(cwd);
const { loadNuxtConfig } = await loadKit(cwd);
const nuxtOptions = await loadNuxtConfig({
cwd,
dotenv: { cwd, fileName: ctx.args.dotenv },
envName: ctx.args.envName,
// c12 will fall back to NODE_ENV
overrides: {
dev: true,
logLevel: ctx.args.logLevel,
...ctx.args.extends && { extends: ctx.args.extends },
...ctx.data?.overrides
}
});
const listenOptions = resolveListenOptions(nuxtOptions, ctx.args);
if (!ctx.args.fork) {
const { listener, close: close2 } = await initialize({
cwd,
args: ctx.args,
hostname: listenOptions.hostname,
public: listenOptions.public,
publicURLs: void 0,
proxy: {
https: listenOptions.https
}
}, { data: ctx.data }, listenOptions);
return {
listener,
async close() {
await close2();
await listener.close();
}
};
}
const devProxy = await createDevProxy(cwd, nuxtOptions, listenOptions);
const nuxtSocketEnv = process.env.NUXT_SOCKET ? process.env.NUXT_SOCKET === "1" : void 0;
const useSocket = nuxtSocketEnv ?? (nuxtOptions._majorVersion === 4 && await isSocketSupported());
const urls = await devProxy.listener.getURLs();
const { onRestart, onReady, close } = await initialize({
cwd,
args: ctx.args,
hostname: listenOptions.hostname,
public: listenOptions.public,
publicURLs: urls.map((r) => r.url),
proxy: {
url: devProxy.listener.url,
urls,
https: devProxy.listener.https,
addr: devProxy.listener.address
}
// if running with nuxt v4 or `NUXT_SOCKET=1`, we use the socket listener
// otherwise pass 'true' to listen on a random port instead
}, {}, useSocket ? void 0 : true);
onReady((address) => devProxy.setAddress(address));
const fork2 = startSubprocess(cwd, ctx.args, ctx.rawArgs, listenOptions);
onRestart(async (devServer) => {
const [subprocess] = await Promise.all([
fork2,
devServer.close().catch(() => {
})
]);
await subprocess.initialize(devProxy, useSocket);
});
return {
listener: devProxy.listener,
async close() {
await close();
const subprocess = await fork2;
subprocess.kill(0);
await devProxy.listener.close();
}
};
}
});
async function createDevProxy(cwd, nuxtOptions, listenOptions) {
let loadingMessage = "Nuxt dev server is starting...";
let error;
let address;
let loadingTemplate = nuxtOptions.devServer.loadingTemplate;
const proxy = createProxyServer({});
proxy.on("proxyReq", (proxyReq, req) => {
if (!proxyReq.hasHeader("x-forwarded-for")) {
const address2 = req.socket.remoteAddress;
if (address2) {
proxyReq.appendHeader("x-forwarded-for", address2);
}
}
if (!proxyReq.hasHeader("x-forwarded-port")) {
const localPort = req?.socket?.localPort;
if (localPort) {
proxyReq.setHeader("x-forwarded-port", req.socket.localPort);
}
}
if (!proxyReq.hasHeader("x-forwarded-Proto")) {
const encrypted = req?.connection?.encrypted;
proxyReq.setHeader("x-forwarded-proto", encrypted ? "https" : "http");
}
});
const listener = await listen((req, res) => {
if (error) {
renderError(req, res, error);
return;
}
if (!address) {
res.statusCode = 503;
res.setHeader("Content-Type", "text/html");
res.setHeader("Cache-Control", "no-store");
if (loadingTemplate) {
res.end(loadingTemplate({ loading: loadingMessage }));
return;
}
async function resolveLoadingMessage() {
loadingTemplate = await resolveLoadingTemplate(cwd);
res.end(loadingTemplate({ loading: loadingMessage }));
}
return resolveLoadingMessage();
}
const target = isSocketURL(address) ? parseSocketURL(address) : address;
proxy.web(req, res, { target });
}, listenOptions);
listener.server.on("upgrade", (req, socket, head) => {
if (!address) {
if (!socket.destroyed) {
socket.end();
}
return;
}
const target = isSocketURL(address) ? parseSocketURL(address) : address;
return proxy.ws(req, socket, { target, xfwd: true }, head).catch(() => {
if (!socket.destroyed) {
socket.end();
}
});
});
return {
listener,
setAddress: (_addr) => {
address = _addr;
},
setLoadingMessage: (_msg) => {
loadingMessage = _msg;
},
setError: (_error) => {
error = _error;
},
clearError() {
error = void 0;
}
};
}
async function startSubprocess(cwd, args, rawArgs, listenOptions) {
let childProc;
let devProxy;
let ready;
const kill = (signal) => {
if (childProc) {
childProc.kill(signal === 0 && isDeno ? "SIGTERM" : signal);
childProc = void 0;
}
};
async function initialize2(proxy, socket) {
devProxy = proxy;
const urls = await devProxy.listener.getURLs();
await ready;
childProc.send({
type: "nuxt:internal:dev:context",
socket,
context: {
cwd,
args,
hostname: listenOptions.hostname,
public: listenOptions.public,
publicURLs: urls.map((r) => r.url),
proxy: {
url: devProxy.listener.url,
urls,
https: devProxy.listener.https
}
}
});
}
async function restart() {
devProxy?.clearError();
if (process.platform === "win32") {
kill("SIGTERM");
} else {
kill("SIGHUP");
}
childProc = fork(globalThis.__nuxt_cli__.devEntry, rawArgs, {
execArgv: ["--enable-source-maps", process.argv.find((a) => a.includes("--inspect"))].filter(Boolean),
env: {
...process.env,
__NUXT__FORK: "true"
}
});
childProc.on("close", (errorCode) => {
if (errorCode) {
process.exit(errorCode);
}
});
ready = new Promise((resolve2, reject) => {
childProc.on("error", reject);
childProc.on("message", (message) => {
if (message.type === "nuxt:internal:dev:fork-ready") {
resolve2();
} else if (message.type === "nuxt:internal:dev:ready") {
devProxy.setAddress(message.address);
if (startTime) {
logger.debug(`Dev server ready for connections in ${Date.now() - startTime}ms`);
}
} else if (message.type === "nuxt:internal:dev:loading") {
devProxy.setAddress(void 0);
devProxy.setLoadingMessage(message.message);
devProxy.clearError();
} else if (message.type === "nuxt:internal:dev:loading:error") {
devProxy.setAddress(void 0);
devProxy.setError(message.error);
} else if (message.type === "nuxt:internal:dev:restart") {
restart();
} else if (message.type === "nuxt:internal:dev:rejection") {
logger.info(`Restarting Nuxt due to error: \`${message.message}\``);
restart();
}
});
});
}
for (const signal of [
"exit",
"SIGTERM",
"SIGINT",
"SIGQUIT"
]) {
process.once(signal, () => {
kill(signal === "exit" ? 0 : signal);
});
}
await restart();
return {
initialize: initialize2,
restart,
kill
};
}
function resolveListenOptions(nuxtOptions, args) {
const _port = args.port ?? args.p ?? process.env.NUXT_PORT ?? process.env.NITRO_PORT ?? process.env.PORT ?? nuxtOptions.devServer.port;
const _hostname = typeof args.host === "string" ? args.host : args.host === true ? "" : process.env.NUXT_HOST ?? process.env.NITRO_HOST ?? process.env.HOST ?? (nuxtOptions.devServer?.host || void 0) ?? void 0;
const _public = args.public ?? (_hostname && !["localhost", "127.0.0.1", "::1"].includes(_hostname)) ? true : void 0;
const _httpsCert = args["https.cert"] || args.sslCert || process.env.NUXT_SSL_CERT || process.env.NITRO_SSL_CERT || typeof nuxtOptions.devServer.https !== "boolean" && nuxtOptions.devServer.https && "cert" in nuxtOptions.devServer.https && nuxtOptions.devServer.https.cert || "";
const _httpsKey = args["https.key"] || args.sslKey || process.env.NUXT_SSL_KEY || process.env.NITRO_SSL_KEY || typeof nuxtOptions.devServer.https !== "boolean" && nuxtOptions.devServer.https && "key" in nuxtOptions.devServer.https && nuxtOptions.devServer.https.key || "";
const _httpsPfx = args["https.pfx"] || typeof nuxtOptions.devServer.https !== "boolean" && nuxtOptions.devServer.https && "pfx" in nuxtOptions.devServer.https && nuxtOptions.devServer.https.pfx || "";
const _httpsPassphrase = args["https.passphrase"] || typeof nuxtOptions.devServer.https !== "boolean" && nuxtOptions.devServer.https && "passphrase" in nuxtOptions.devServer.https && nuxtOptions.devServer.https.passphrase || "";
const httpsEnabled = !!(args.https ?? nuxtOptions.devServer.https);
const _listhenOptions = parseArgs({
...args,
"open": args.o || args.open,
"https": httpsEnabled,
"https.cert": _httpsCert,
"https.key": _httpsKey,
"https.pfx": _httpsPfx,
"https.passphrase": _httpsPassphrase
});
const httpsOptions = httpsEnabled && {
...nuxtOptions.devServer.https,
..._listhenOptions.https
};
return {
..._listhenOptions,
port: _port,
hostname: _hostname,
public: _public,
https: httpsOptions,
baseURL: nuxtOptions.app.baseURL.startsWith("./") ? nuxtOptions.app.baseURL.slice(1) : nuxtOptions.app.baseURL
};
}
function isBunForkSupported() {
const bunVersion = globalThis.Bun.version;
return satisfies(bunVersion, ">=1.2");
}
export { command as default };
@@ -0,0 +1,46 @@
import process from 'node:process';
import { defineCommand } from 'citty';
import { resolve } from 'pathe';
import { x } from 'tinyexec';
import { l as logger } from '../shared/cli.B9AmABr3.mjs';
import { l as legacyRootDirArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'consola';
import 'node:path';
import 'std-env';
import 'node:url';
const devtools = 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);
if (!["enable", "disable"].includes(ctx.args.command)) {
logger.error(`Unknown command \`${ctx.args.command}\`.`);
process.exit(1);
}
await x(
"npx",
["@nuxt/devtools-wizard@latest", ctx.args.command, cwd],
{
throwOnError: true,
nodeOptions: {
stdio: "inherit",
cwd
}
}
);
}
});
export { devtools as default };
@@ -0,0 +1,45 @@
import { defineCommand } from 'citty';
import { l as legacyRootDirArgs, e as extendsArgs, b as envNameArgs, d as dotEnvArgs, a as logLevelArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import buildCommand from './build.mjs';
import 'node:path';
import 'node:process';
import 'std-env';
import 'consola';
import '../shared/cli.B9AmABr3.mjs';
import 'node:url';
import 'pathe';
import '../shared/cli.Dz2be-Ai.mjs';
import 'node:fs';
import 'consola/utils';
import 'exsolve';
import '../shared/cli.qKvs7FJ2.mjs';
import '../shared/cli.BEUGgaW4.mjs';
import '../shared/cli.pLQ0oPGc.mjs';
const generate = defineCommand({
meta: {
name: "generate",
description: "Build Nuxt and prerender all routes"
},
args: {
...cwdArgs,
...logLevelArgs,
preset: {
type: "string",
description: "Nitro server preset"
},
...dotEnvArgs,
...envNameArgs,
...extendsArgs,
...legacyRootDirArgs
},
async run(ctx) {
ctx.args.prerender = true;
await buildCommand.run(
// @ts-expect-error types do not match
ctx
);
}
});
export { generate as default };
@@ -0,0 +1,466 @@
import process from 'node:process';
import defu from 'defu';
import { listen } from 'listhen';
import { Server } from 'node:http';
import { getSocketAddress, cleanSocket } from 'get-port-please';
import EventEmitter from 'node:events';
import { watch, existsSync } from 'node:fs';
import { mkdir } from 'node:fs/promises';
import { pathToFileURL } from 'node:url';
import { resolveModulePath } from 'exsolve';
import { toNodeListener } from 'h3';
import { resolve } from 'pathe';
import { debounce } from 'perfect-debounce';
import { provider } from 'std-env';
import { joinURL } from 'ufo';
import { a as clearBuildDir } from '../shared/cli.pLQ0oPGc.mjs';
import { l as loadKit } from '../shared/cli.qKvs7FJ2.mjs';
import { l as loadNuxtManifest, r as resolveNuxtManifest, w as writeNuxtManifest } from '../shared/cli.At9IMXtr.mjs';
import { Youch } from 'youch';
function formatSocketURL(socketPath, ssl = false) {
const protocol = ssl ? "https" : "http";
const encodedPath = process.platform === "win32" ? encodeURIComponent(socketPath) : socketPath.replace(/\//g, "%2F");
return `${protocol}+unix://${encodedPath}`;
}
function isSocketURL(url) {
return url.startsWith("http+unix://") || url.startsWith("https+unix://");
}
function parseSocketURL(url) {
if (!isSocketURL(url)) {
throw new Error(`Invalid socket URL: ${url}`);
}
const ssl = url.startsWith("https+unix://");
const path = url.slice(ssl ? "https+unix://".length : "http+unix://".length);
const socketPath = decodeURIComponent(path.replace(/%2F/g, "/"));
return { socketPath, protocol: ssl ? "https" : "http" };
}
async function createSocketListener(handler, proxyAddress) {
const socketPath = getSocketAddress({
name: "nuxt-dev",
random: true
});
const server = new Server(handler);
await cleanSocket(socketPath);
await new Promise((resolve) => server.listen({ path: socketPath }, resolve));
const url = formatSocketURL(socketPath);
return {
url,
address: { address: "localhost", port: 3e3, ...proxyAddress, socketPath },
async close() {
try {
server.removeAllListeners();
await new Promise((resolve, reject) => server.close((err) => err ? reject(err) : resolve()));
} finally {
await cleanSocket(socketPath);
}
},
getURLs: async () => [{ url, type: "network" }],
https: false,
server
};
}
async function renderError(req, res, error) {
const youch = new Youch();
res.statusCode = 500;
res.setHeader("Content-Type", "text/html");
const html = await youch.toHTML(error, {
request: {
url: req.url,
method: req.method,
headers: req.headers
}
});
res.end(html);
}
const RESTART_RE = /^(?:nuxt\.config\.[a-z0-9]+|\.nuxtignore|\.nuxtrc|\.config\/nuxt(?:\.config)?\.[a-z0-9]+)$/;
class NuxtDevServer extends EventEmitter {
constructor(options) {
super();
this.options = options;
this.loadDebounced = debounce(this.load);
let _initResolve;
const _initPromise = new Promise((resolve2) => {
_initResolve = resolve2;
});
this.once("ready", () => {
_initResolve();
});
this.cwd = options.cwd;
this.handler = async (req, res) => {
if (this._loadingError) {
this._renderError(req, res);
return;
}
await _initPromise;
if (this._handler) {
this._handler(req, res);
} else {
this._renderLoadingScreen(req, res);
}
};
this.listener = void 0;
}
_handler;
_distWatcher;
_configWatcher;
_currentNuxt;
_loadingMessage;
_loadingError;
cwd;
loadDebounced;
handler;
listener;
_renderError(req, res) {
renderError(req, res, this._loadingError);
}
async _renderLoadingScreen(req, res) {
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() {
await this.load();
this._watchConfig();
}
closeWatchers() {
this._distWatcher?.close();
this._configWatcher?.();
}
async load(reload, reason) {
try {
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);
}
}
async close() {
if (this._currentNuxt) {
await this._currentNuxt.close();
}
}
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 kit = await loadKit(this.options.cwd);
const devServerDefaults = resolveDevServerDefaults({}, await this.listener.getURLs().then((r) => r.map((r2) => r2.url)));
this._currentNuxt = await kit.loadNuxt({
cwd: this.options.cwd,
dev: true,
ready: false,
envName: this.options.envName,
dotenv: {
cwd: this.options.cwd,
fileName: this.options.dotenv.fileName
},
defaults: defu(this.options.defaults, devServerDefaults),
overrides: {
logLevel: this.options.logLevel,
...this.options.overrides,
vite: {
clearScreen: this.options.clear,
...this.options.overrides.vite
}
}
});
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.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);
});
}
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.options.devContext.proxy?.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.");
}
await Promise.all([
kit.writeTypes(this._currentNuxt).catch(console.error),
kit.buildNuxt(this._currentNuxt)
]);
if (!this._currentNuxt.server) {
throw new Error("Nitro server has not been initialized.");
}
const distDir = resolve(this._currentNuxt.options.buildDir, "dist");
await mkdir(distDir, { recursive: true });
this._distWatcher = watch(distDir);
this._distWatcher.on("change", () => {
this.loadDebounced(true, ".nuxt/dist directory has been removed");
});
this._handler = toNodeListener(this._currentNuxt.server.app);
this.emit("ready", "socketPath" in addr ? formatSocketURL(addr.socketPath, !!this.listener.https) : `http://127.0.0.1:${addr.port}`);
}
_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 resolveDevServerOverrides(listenOptions) {
if (listenOptions.public || provider === "codesandbox") {
return {
devServer: { cors: { origin: "*" } },
vite: { server: { allowedHosts: true } }
};
}
return {};
}
function resolveDevServerDefaults(listenOptions, urls = []) {
const defaultConfig = {};
if (urls) {
defaultConfig.vite = {
server: {
allowedHosts: urls.filter((u) => !isSocketURL(u)).map((u) => new URL(u).hostname)
}
};
}
if (listenOptions.hostname) {
const protocol = listenOptions.https ? "https" : "http";
defaultConfig.devServer = { cors: { origin: [`${protocol}://${listenOptions.hostname}`, ...urls] } };
defaultConfig.vite = defu(defaultConfig.vite, { server: { allowedHosts: [listenOptions.hostname] } });
}
return defaultConfig;
}
function createConfigWatcher(cwd, dotenvFileName = ".env", onRestart, onReload) {
const configWatcher = watch(cwd);
let configDirWatcher = existsSync(resolve(cwd, ".config")) ? createConfigDirWatcher(cwd, onReload) : void 0;
const dotenvFileNames = new Set(Array.isArray(dotenvFileName) ? dotenvFileName : [dotenvFileName]);
configWatcher.on("change", (_event, file) => {
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 = resolve(cwd, ".config");
const configDirWatcher = watch(configDir);
configDirWatcher.on("change", (_event, file) => {
if (RESTART_RE.test(file)) {
onReload(file);
}
});
return () => configDirWatcher.close();
}
async function resolveLoadingTemplate(cwd) {
const nuxtPath = resolveModulePath("nuxt", { from: cwd, try: true });
const uiTemplatesPath = resolveModulePath("@nuxt/ui-templates", { from: nuxtPath || cwd });
const r = await import(pathToFileURL(uiTemplatesPath).href);
return r.loading || ((params) => `<h2>${params.loading}</h2>`);
}
const start = Date.now();
process.env.NODE_ENV = "development";
class IPC {
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, {}, message.socket ? void 0 : true);
}
});
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 = {}, _listenOptions) {
const devServerOverrides = resolveDevServerOverrides({
public: devContext.public
});
const devServerDefaults = resolveDevServerDefaults({
hostname: devContext.hostname,
https: devContext.proxy?.https
}, devContext.publicURLs);
const devServer = new NuxtDevServer({
cwd: devContext.cwd,
overrides: defu(
ctx.data?.overrides,
{ extends: devContext.args.extends },
devServerOverrides
),
defaults: devServerDefaults,
logLevel: devContext.args.logLevel,
clear: !!devContext.args.clear,
dotenv: { cwd: devContext.cwd, fileName: devContext.args.dotenv },
envName: devContext.args.envName,
devContext: {
proxy: devContext.proxy
}
});
const listenOptions = _listenOptions === true || process.env._PORT ? { port: process.env._PORT ?? 0, hostname: "127.0.0.1", showURL: false } : _listenOptions;
devServer.listener = listenOptions ? await listen(devServer.handler, listenOptions) : await createSocketListener(devServer.handler, devContext.proxy?.addr);
if (process.env.DEBUG) {
console.debug(`Using ${listenOptions ? "network" : "socket"} listener for Nuxt dev server.`);
}
devServer.listener._url = devServer.listener.url;
if (devContext.proxy?.url) {
devServer.listener.url = devContext.proxy.url;
}
if (devContext.proxy?.urls) {
const _getURLs = devServer.listener.getURLs.bind(devServer.listener);
devServer.listener.getURLs = async () => Array.from(/* @__PURE__ */ new Set([...devContext.proxy?.urls || [], ...await _getURLs()]));
}
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`);
}
return {
listener: devServer.listener,
close: async () => {
devServer.closeWatchers();
await 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);
}
};
}
const index = {
__proto__: null,
initialize: initialize
};
export { renderError as a, isSocketURL as b, index as c, initialize as i, parseSocketURL as p, resolveLoadingTemplate as r };
@@ -0,0 +1,15 @@
import { defineCommand } from 'citty';
const index = defineCommand({
meta: {
name: "module",
description: "Manage Nuxt modules"
},
args: {},
subCommands: {
add: () => import('./add.mjs').then((r) => r.default || r),
search: () => import('./search.mjs').then((r) => r.default || r)
}
});
export { index as default };
@@ -0,0 +1,149 @@
import os from 'node:os';
import process from 'node:process';
import { defineCommand } from 'citty';
import clipboardy from 'clipboardy';
import { detectPackageManager } from 'nypm';
import { resolve } from 'pathe';
import { readPackageJSON } from 'pkg-types';
import { splitByCase } from 'scule';
import { isMinimal } from 'std-env';
import { v as version } from '../shared/cli.DhJ3cH8w.mjs';
import { t as tryResolveNuxt } from '../shared/cli.qKvs7FJ2.mjs';
import { l as logger } from '../shared/cli.B9AmABr3.mjs';
import { g as getPackageManagerVersion } from '../shared/cli.BSm0_9Hr.mjs';
import { l as legacyRootDirArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'node:url';
import 'exsolve';
import 'consola';
import 'node:child_process';
import 'node:path';
const info = 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 npmName = name.split("/").splice(0, 2).join("/");
const v = await getDepVersion(npmName);
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 || "-" : nuxtConfig.bridge?.vite ? "vite" : nuxtConfig.buildModules?.includes("nuxt-vite") ? "vite" : "webpack";
let packageManager = (await detectPackageManager(cwd))?.name;
if (packageManager) {
packageManager += `@${getPackageManagerVersion(packageManager)}`;
}
const infoObj = {
OperatingSystem: os.type(),
NodeVersion: process.version,
NuxtVersion: nuxtVersion,
CLIVersion: version,
NitroVersion: await getDepVersion("nitropack"),
PackageManager: packageManager ?? "unknown",
Builder: typeof builder === "string" ? builder : "custom",
UserConfig: Object.keys(nuxtConfig).map((key) => `\`${key}\``).join(", "),
RuntimeModules: await listModules(nuxtConfig.modules),
BuildModules: await listModules(nuxtConfig.buildModules || [])
};
logger.log("Working directory:", cwd);
let maxLength = 0;
const entries = Object.entries(infoObj).map(([key, val]) => {
const label = splitByCase(key).join(" ");
if (label.length > maxLength) {
maxLength = label.length;
}
return [label, val || "-"];
});
let infoStr = "";
for (const [label, value] of entries) {
infoStr += `- ${`${label}: `.padEnd(maxLength + 2)}${value.includes("`") ? value : `\`${value}\``}
`;
}
const copied = !isMinimal && await clipboardy.write(infoStr).then(() => true).catch(() => false);
const isNuxt3 = !isLegacy;
const isBridge = !isNuxt3 && infoObj.BuildModules.includes("bridge");
const repo = isBridge ? "nuxt/bridge" : "nuxt/nuxt";
const log = [
(isNuxt3 || isBridge) && `\u{1F449} Report an issue: https://github.com/${repo}/issues/new?template=bug-report.yml`,
(isNuxt3 || isBridge) && `\u{1F449} Suggest an improvement: https://github.com/${repo}/discussions/new`,
`\u{1F449} Read documentation: ${isNuxt3 || isBridge ? "https://nuxt.com" : "https://v2.nuxt.com"}`
].filter(Boolean).join("\n");
const splitter = "------------------------------";
logger.log(`Nuxt project info: ${copied ? "(copied to clipboard)" : ""}
${splitter}
${infoStr}${splitter}
${log}
`);
}
});
function normalizeConfigModule(module, rootDir) {
if (!module) {
return null;
}
if (typeof module === "string") {
return module.split(rootDir).pop().split("node_modules").pop().replace(/^\//, "");
}
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,
// allow using `~` and `@` in `nuxt.config`
alias: {
"~": rootDir,
"@": rootDir
}
});
globalThis.defineNuxtConfig = (c) => c;
const result = await jiti.import("./nuxt.config", { default: true });
delete globalThis.defineNuxtConfig;
return result;
} catch {
return {};
}
}
export { info as default };
@@ -0,0 +1,388 @@
import { existsSync } from 'node:fs';
import process from 'node:process';
import { defineCommand } from 'citty';
import { colors } from 'consola/utils';
import { downloadTemplate, startShell } from 'giget';
import { installDependencies } from 'nypm';
import { $fetch } from 'ofetch';
import { resolve, relative, join } from 'pathe';
import { readPackageJSON, writePackageJSON } from 'pkg-types';
import { hasTTY } from 'std-env';
import { x } from 'tinyexec';
import { r as runCommand } from '../shared/cli.vXg4eLNu.mjs';
import { l as logger } from '../shared/cli.B9AmABr3.mjs';
import { a as logLevelArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'node:url';
import 'node:crypto';
import 'node:path';
import '../shared/cli.DhJ3cH8w.mjs';
import 'consola';
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");
const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/nuxt/starter/templates/templates";
const DEFAULT_TEMPLATE_NAME = "v4";
const pms = {
npm: void 0,
pnpm: void 0,
yarn: void 0,
bun: void 0,
deno: void 0
};
const packageManagerOptions = Object.keys(pms);
async function getModuleDependencies(moduleName) {
try {
const response = await $fetch(`https://registry.npmjs.org/${moduleName}/latest`);
const dependencies = response.dependencies || {};
return Object.keys(dependencies);
} catch (err) {
logger.warn(`Could not get dependencies for ${moduleName}: ${err}`);
return [];
}
}
function filterModules(modules, allDependencies) {
const result = {
toInstall: [],
skipped: []
};
for (const module of modules) {
const isDependency = modules.some((otherModule) => {
if (otherModule === module)
return false;
const deps = allDependencies[otherModule] || [];
return deps.includes(module);
});
if (isDependency) {
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 import(packageJsonPath);
const directDeps = {
...packageJson.dependencies,
...packageJson.devDependencies
};
const directDepNames = Object.keys(directDeps);
const allDeps = new Set(directDepNames);
const transitiveDepsResults = await Promise.all(
directDepNames.map((dep) => getModuleDependencies(dep))
);
transitiveDepsResults.forEach((deps) => {
deps.forEach((dep) => allDeps.add(dep));
});
return Array.from(allDeps);
} catch (err) {
logger.warn(`Could not read template dependencies: ${err}`);
return [];
}
}
const init = 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 (hasTTY) {
process.stdout.write(`
${nuxtIcon}
`);
}
logger.info(colors.bold(`Welcome to Nuxt!`.split("").map((m) => `${themeColor}${m}`).join("")));
if (ctx.args.dir === "") {
ctx.args.dir = await logger.prompt("Where would you like to create your project?", {
placeholder: "./nuxt-app",
type: "text",
default: "nuxt-app",
cancel: "reject"
}).catch(() => process.exit(1));
}
const cwd = resolve(ctx.args.cwd);
let templateDownloadPath = resolve(cwd, ctx.args.dir);
logger.info(`Creating a new project in ${colors.cyan(relative(cwd, templateDownloadPath) || templateDownloadPath)}.`);
const templateName = ctx.args.template || DEFAULT_TEMPLATE_NAME;
if (typeof templateName !== "string") {
logger.error("Please specify a template!");
process.exit(1);
}
let shouldForce = Boolean(ctx.args.force);
const shouldVerify = !shouldForce && existsSync(templateDownloadPath);
if (shouldVerify) {
const selectedAction = await logger.prompt(
`The directory ${colors.cyan(templateDownloadPath)} already exists. What would you like to do?`,
{
type: "select",
options: ["Override its contents", "Select different directory", "Abort"]
}
);
switch (selectedAction) {
case "Override its contents":
shouldForce = true;
break;
case "Select different directory": {
templateDownloadPath = resolve(cwd, await logger.prompt("Please specify a different directory:", {
type: "text",
cancel: "reject"
}).catch(() => process.exit(1)));
break;
}
// 'Abort' or Ctrl+C
default:
process.exit(1);
}
}
let 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
});
} catch (err) {
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 response = await $fetch("https://registry.npmjs.org/nuxt-nightly");
const nightlyChannelTag = ctx.args.nightly || "latest";
const nightlyChannelVersion = response["dist-tags"][nightlyChannelTag];
if (!nightlyChannelVersion) {
logger.error(`Nightly channel version for tag '${nightlyChannelTag}' not found.`);
process.exit(1);
}
const nightlyNuxtPackageJsonVersion = `npm:nuxt-nightly@${nightlyChannelVersion}`;
const packageJsonPath = resolve(cwd, ctx.args.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);
}
function detectCurrentPackageManager() {
const userAgent = process.env.npm_config_user_agent;
if (!userAgent) {
return;
}
const [name] = userAgent.split("/");
if (packageManagerOptions.includes(name)) {
return name;
}
}
const currentPackageManager = detectCurrentPackageManager();
const packageManagerArg = ctx.args.packageManager;
const packageManagerSelectOptions = packageManagerOptions.map((pm) => ({
label: pm,
value: pm,
hint: currentPackageManager === pm ? "current" : void 0
}));
const selectedPackageManager = packageManagerOptions.includes(packageManagerArg) ? packageManagerArg : await logger.prompt("Which package manager would you like to use?", {
type: "select",
options: packageManagerSelectOptions,
initial: currentPackageManager,
cancel: "reject"
}).catch(() => process.exit(1));
if (ctx.args.install === false) {
logger.info("Skipping install dependencies step.");
} else {
logger.start("Installing dependencies...");
try {
await installDependencies({
cwd: template.dir,
packageManager: {
name: selectedPackageManager,
command: selectedPackageManager
}
});
} catch (err) {
if (process.env.DEBUG) {
throw err;
}
logger.error(err.toString());
process.exit(1);
}
logger.success("Installation completed.");
}
if (ctx.args.gitInit === void 0) {
ctx.args.gitInit = await logger.prompt("Initialize git repository?", {
type: "confirm",
cancel: "reject"
}).catch(() => process.exit(1));
}
if (ctx.args.gitInit) {
logger.info("Initializing git repository...\n");
try {
await x("git", ["init", template.dir], {
throwOnError: true,
nodeOptions: {
stdio: "inherit"
}
});
} catch (err) {
logger.warn(`Failed to initialize git repository: ${err}`);
}
}
const modulesToAdd = [];
if (ctx.args.modules !== void 0) {
modulesToAdd.push(
...(ctx.args.modules || "").split(",").map((module) => module.trim()).filter(Boolean)
);
} else if (!ctx.args.offline && !ctx.args.preferOffline) {
const modulesPromise = $fetch("https://api.nuxt.com/modules");
const wantsUserModules = await logger.prompt(
`Would you like to install any of the official modules?`,
{
type: "confirm",
cancel: "reject"
}
).catch(() => process.exit(1));
if (wantsUserModules) {
const [response, templateDeps] = await Promise.all([
modulesPromise,
getTemplateDependencies(template.dir)
]);
const officialModules = response.modules.filter((module) => module.type === "official" && module.npm !== "@nuxt/devtools").filter((module) => !templateDeps.includes(module.npm));
if (officialModules.length === 0) {
logger.info("All official modules are already included in this template.");
} else {
const selectedOfficialModules = await logger.prompt(
"Pick the modules to install:",
{
type: "multiselect",
options: officialModules.map((module) => ({
label: `${colors.bold(colors.greenBright(module.npm))} \u2013 ${module.description.replace(/\.$/, "")}`,
value: module.npm
})),
required: false
}
);
if (selectedOfficialModules === void 0) {
process.exit(1);
}
if (selectedOfficialModules.length > 0) {
const modules = selectedOfficialModules;
const allDependencies = Object.fromEntries(
await Promise.all(modules.map(
async (module) => [module, await getModuleDependencies(module)]
))
);
const { toInstall, skipped } = filterModules(modules, allDependencies);
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) {
const args = [
"add",
...modulesToAdd,
`--cwd=${templateDownloadPath}`,
ctx.args.install ? "" : "--skipInstall",
ctx.args.logLevel ? `--logLevel=${ctx.args.logLevel}` : ""
].filter(Boolean);
await runCommand("module", args);
}
logger.log(
`
\u2728 Nuxt project has been created with the \`${template.name}\` template. Next steps:`
);
const relativeTemplateDir = relative(process.cwd(), template.dir) || ".";
const runCmd = selectedPackageManager === "deno" ? "task" : "run";
const nextSteps = [
!ctx.args.shell && relativeTemplateDir.length > 1 && `\`cd ${relativeTemplateDir}\``,
`Start development server with \`${selectedPackageManager} ${runCmd} dev\``
].filter(Boolean);
for (const step of nextSteps) {
logger.log(` \u203A ${step}`);
}
if (ctx.args.shell) {
startShell(template.dir);
}
}
});
export { init as default };
@@ -0,0 +1,57 @@
import process from 'node:process';
import { defineCommand } from 'citty';
import { resolve, relative } from 'pathe';
import { a as clearBuildDir } from '../shared/cli.pLQ0oPGc.mjs';
import { l as loadKit } from '../shared/cli.qKvs7FJ2.mjs';
import { l as logger } from '../shared/cli.B9AmABr3.mjs';
import { l as legacyRootDirArgs, e as extendsArgs, b as envNameArgs, a as logLevelArgs, c as cwdArgs, d as dotEnvArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'node:fs';
import 'node:url';
import 'exsolve';
import 'consola';
import 'node:path';
import 'std-env';
const prepare = 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,
// c12 will fall back to NODE_ENV
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",
relative(process.cwd(), nuxt.options.buildDir)
);
}
});
export { prepare as default };
@@ -0,0 +1,131 @@
import { existsSync, promises } from 'node:fs';
import { dirname, relative } from 'node:path';
import process from 'node:process';
import { setupDotenv } from 'c12';
import { defineCommand } from 'citty';
import { box, colors } from 'consola/utils';
import { getArgs } from 'listhen/cli';
import { resolve } from 'pathe';
import { x } from 'tinyexec';
import { l as loadKit } from '../shared/cli.qKvs7FJ2.mjs';
import { l as logger } from '../shared/cli.B9AmABr3.mjs';
import { d as dotEnvArgs, l as legacyRootDirArgs, e as extendsArgs, b as envNameArgs, a as logLevelArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'node:url';
import 'exsolve';
import 'consola';
import 'std-env';
const command = defineCommand({
meta: {
name: "preview",
description: "Launches Nitro server for local testing after `nuxi build`."
},
args: {
...cwdArgs,
...logLevelArgs,
...envNameArgs,
...extendsArgs,
...legacyRootDirArgs,
port: getArgs().port,
...dotEnvArgs
},
async run(ctx) {
process.env.NODE_ENV = process.env.NODE_ENV || "production";
const cwd = resolve(ctx.args.cwd || ctx.args.rootDir);
const { loadNuxt } = await loadKit(cwd);
const resolvedOutputDir = await new Promise((res) => {
loadNuxt({
cwd,
envName: ctx.args.envName,
// c12 will fall back to NODE_ENV
ready: true,
overrides: {
...ctx.args.extends && { extends: ctx.args.extends },
modules: [
function(_, nuxt) {
nuxt.hook("nitro:init", (nitro) => {
res(resolve(nuxt.options.srcDir || cwd, nitro.options.output.dir || ".output", "nitro.json"));
});
}
]
}
}).then((nuxt) => nuxt.close()).catch(() => "");
});
const defaultOutput = resolve(cwd, ".output", "nitro.json");
const nitroJSONPaths = [resolvedOutputDir, defaultOutput].filter(Boolean);
const nitroJSONPath = nitroJSONPaths.find((p) => existsSync(p));
if (!nitroJSONPath) {
logger.error(
"Cannot find `nitro.json`. Did you run `nuxi build` first? Search path:\n",
nitroJSONPaths
);
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:", relative(process.cwd(), outputPath)]
];
const _infoKeyLen = Math.max(...info.map(([label]) => label.length));
logger.log(
box(
[
"You are running Nuxt production build in preview mode.",
`For production deployments, please directly use ${colors.cyan(
nitroJSON.commands.preview
)} command.`,
"",
...info.map(
([label, value]) => `${label.padEnd(_infoKeyLen, " ")} ${colors.cyan(value)}`
)
].join("\n"),
{
title: colors.yellow("Preview Mode"),
style: {
borderColor: "yellow"
}
}
)
);
const envFileName = ctx.args.dotenv || ".env";
const envExists = existsSync(resolve(cwd, envFileName));
if (envExists) {
logger.info(
`Loading \`${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 \`${envFileName}\`.`);
}
const { port } = _resolveListenOptions(ctx.args);
logger.info(`Starting preview command: \`${nitroJSON.commands.preview}\``);
const [command2, ...commandArgs] = nitroJSON.commands.preview.split(" ");
logger.log("");
await x(command2, commandArgs, {
throwOnError: true,
nodeOptions: {
stdio: "inherit",
cwd: outputPath,
env: {
...process.env,
NUXT_PORT: port,
NITRO_PORT: port
}
}
});
}
});
function _resolveListenOptions(args) {
const _port = args.port ?? args.p ?? process.env.NUXT_PORT ?? process.env.NITRO_PORT ?? process.env.PORT;
return {
port: _port
};
}
export { command as default };
@@ -0,0 +1,114 @@
import { defineCommand } from 'citty';
import { colors } from 'consola/utils';
import Fuse from 'fuse.js';
import { upperFirst, kebabCase } from 'scule';
import { l as logger } from '../shared/cli.B9AmABr3.mjs';
import { g as getNuxtVersion } from '../shared/cli.DHenkA1C.mjs';
import { c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import { f as fetchModules, c as checkNuxtCompatibility } from '../shared/cli.Cr-OCgdO.mjs';
import 'consola';
import 'pkg-types';
import 'semver';
import 'node:path';
import 'node:process';
import 'std-env';
import 'node:url';
import 'confbox';
import 'ofetch';
const { format: formatNumber } = Intl.NumberFormat("en-GB", {
notation: "compact",
maximumFractionDigits: 1
});
const search = 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 allModules = await fetchModules();
const compatibleModules = allModules.filter(
(m) => checkNuxtCompatibility(m, nuxtVersion)
);
const fuse = new Fuse(compatibleModules, {
threshold: 0.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: 0.5 },
{ name: "maintainers.name", weight: 0.5 },
{ name: "maintainers.github", weight: 0.5 }
]
});
const { bold, green, magenta, cyan, gray, yellow } = colors;
const results = fuse.search(query).map((result) => {
const res = {
name: bold(result.item.name),
homepage: cyan(result.item.website),
compatibility: `nuxt: ${result.item.compatibility?.nuxt || "*"}`,
repository: gray(result.item.github),
description: gray(result.item.description),
package: gray(result.item.npm),
install: cyan(`npx nuxi module add ${result.item.name}`),
stars: yellow(formatNumber(result.item.stats.stars)),
monthlyDownloads: 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 ${magenta(query)} for Nuxt ${cyan(nuxtVersion)}`
);
return;
}
logger.success(
`Found ${results.length} Nuxt ${results.length > 1 ? "modules" : "module"} matching ${cyan(query)} ${nuxtVersion ? `for Nuxt ${cyan(nuxtVersion)}` : ""}:
`
);
for (const foundModule of results) {
let maxLength = 0;
const entries = Object.entries(foundModule).map(([key, val]) => {
const label = upperFirst(kebabCase(key)).replace(/-/g, " ");
if (label.length > maxLength) {
maxLength = label.length;
}
return [label, val || "-"];
});
let infoStr = "";
for (const [label, value] of entries) {
infoStr += `${bold(label === "Install" ? "\u2192 " : "- ") + green(label.padEnd(maxLength + 2)) + value}
`;
}
logger.log(infoStr);
}
}
export { search as default };
@@ -0,0 +1,62 @@
import process from 'node:process';
import { defineCommand } from 'citty';
import { resolve } from 'pathe';
import { l as logger } from '../shared/cli.B9AmABr3.mjs';
import { l as legacyRootDirArgs, a as logLevelArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'consola';
import 'node:path';
import 'std-env';
import 'node:url';
const test = 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(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.");
}
export { test as default };
@@ -0,0 +1,85 @@
import process from 'node:process';
import { defineCommand } from 'citty';
import { resolveModulePath } from 'exsolve';
import { resolve } from 'pathe';
import { readTSConfig } from 'pkg-types';
import { isBun } from 'std-env';
import { x } from 'tinyexec';
import { l as loadKit } from '../shared/cli.qKvs7FJ2.mjs';
import { l as legacyRootDirArgs, e as extendsArgs, d as dotEnvArgs, a as logLevelArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'node:url';
import 'node:path';
import 'consola';
import '../shared/cli.B9AmABr3.mjs';
const typecheck = 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),
// Prefer local install if possible
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: writeTypes2 } = await loadKit(cwd);
const nuxt = await loadNuxt({
cwd,
dotenv: { cwd, fileName: dotenv },
overrides: {
_prepare: true,
logLevel,
...overrides
}
});
await writeTypes2(nuxt);
await buildNuxt(nuxt);
await nuxt.close();
}
export { typecheck as default };
@@ -0,0 +1,200 @@
import { existsSync } from 'node:fs';
import process from 'node:process';
import { defineCommand } from 'citty';
import { colors } from 'consola/utils';
import { detectPackageManager, addDependency, dedupeDependencies } from 'nypm';
import { resolve } from 'pathe';
import { readPackageJSON } from 'pkg-types';
import { l as loadKit } from '../shared/cli.qKvs7FJ2.mjs';
import { l as logger } from '../shared/cli.B9AmABr3.mjs';
import { c as cleanupNuxtDirs, n as nuxtVersionToGitIdentifier } from '../shared/cli.At9IMXtr.mjs';
import { g as getPackageManagerVersion } from '../shared/cli.BSm0_9Hr.mjs';
import { g as getNuxtVersion } from '../shared/cli.DHenkA1C.mjs';
import { l as legacyRootDirArgs, a as logLevelArgs, c as cwdArgs } from '../shared/cli.CTXRG5Cu.mjs';
import 'node:url';
import 'exsolve';
import 'consola';
import 'ohash';
import '../shared/cli.pLQ0oPGc.mjs';
import 'node:child_process';
import 'semver';
import 'node:path';
import 'std-env';
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"
};
async function getNightlyVersion(packageNames) {
const nuxtVersion = await logger.prompt(
"Which nightly Nuxt release channel do you want to install? (3.x or 4.x)",
{
type: "select",
options: ["3.x", "4.x"],
default: "4.x",
cancel: "reject"
}
).catch(() => process.exit(1));
const npmPackages = packageNames.map((p) => `${p}@npm:${p}-nightly@${nuxtVersionTags[nuxtVersion]}`);
return { npmPackages, nuxtVersion };
}
async function getRequiredNewVersion(packageNames, channel) {
if (channel === "nightly") {
return getNightlyVersion(packageNames);
}
return { npmPackages: packageNames.map((p) => `${p}@latest`), nuxtVersion: "4" };
}
const upgrade = 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"
}
},
async run(ctx) {
const cwd = resolve(ctx.args.cwd || ctx.args.rootDir);
const packageManager = await detectPackageManager(cwd);
if (!packageManager) {
logger.error(
`Unable to determine the package manager used by this project.
No lock files found in \`${cwd}\`, and no \`packageManager\` field specified in \`package.json\`.
Please either add the \`packageManager\` field to \`package.json\` or execute the installation command for your package manager. For example, you can use \`pnpm i\`, \`npm i\`, \`bun i\`, or \`yarn i\`, and then try again.`
);
process.exit(1);
}
const { name: packageManagerName, lockFile: lockFileCandidates } = packageManager;
const packageManagerVersion = getPackageManagerVersion(packageManagerName);
logger.info("Package manager:", packageManagerName, packageManagerVersion);
const currentVersion = await getNuxtVersion(cwd, false) || "[unknown]";
logger.info("Current Nuxt version:", currentVersion);
const pkg = await readPackageJSON(cwd).catch(() => null);
const nuxtDependencyType = pkg ? checkNuxtDependencyType(pkg) : "dependencies";
const corePackages = ["@nuxt/kit", "@nuxt/schema", "@nuxt/vite-builder", "@nuxt/webpack-builder", "@nuxt/rspack-builder"];
const packagesToUpdate = pkg ? corePackages.filter((p) => pkg.dependencies?.[p] || pkg.devDependencies?.[p]) : [];
const { npmPackages, nuxtVersion } = await getRequiredNewVersion(["nuxt", ...packagesToUpdate], ctx.args.channel);
const toRemove = ["node_modules"];
const lockFile = normaliseLockFile(cwd, 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;
method ||= await logger.prompt(
`Would you like to dedupe your lockfile (recommended) or recreate ${forceRemovals}? This can fix problems with hoisted dependency versions and ensure you have the most up-to-date dependencies.`,
{
type: "select",
initial: "dedupe",
cancel: "reject",
options: [
{
label: "dedupe lockfile",
value: "dedupe",
hint: "recommended"
},
{
label: `recreate ${forceRemovals}`,
value: "force"
},
{
label: "skip",
value: "skip"
}
]
}
).catch(() => process.exit(1));
const versionType = ctx.args.channel === "nightly" ? "nightly" : "latest stable";
logger.info(`Installing ${versionType} Nuxt ${nuxtVersion} release...`);
await addDependency(npmPackages, {
cwd,
packageManager,
dev: nuxtDependencyType === "devDependencies"
});
if (method === "force") {
logger.info(
`Recreating ${forceRemovals}. If you encounter any issues, revert the changes and try with \`--no-force\``
);
await dedupeDependencies({ recreateLockfile: true });
}
if (method === "dedupe") {
logger.info("Try deduping dependencies...");
await dedupeDependencies();
}
let buildDir = ".nuxt";
try {
const { loadNuxtConfig } = await loadKit(cwd);
const nuxtOptions = await loadNuxtConfig({ cwd });
buildDir = nuxtOptions.buildDir;
} catch {
}
await cleanupNuxtDirs(cwd, buildDir);
const upgradedVersion = await getNuxtVersion(cwd, false) || "[unknown]";
logger.info("Upgraded Nuxt version:", upgradedVersion);
if (upgradedVersion === "[unknown]") {
return;
}
if (upgradedVersion === currentVersion) {
logger.success("You're using the latest version of Nuxt.");
} else {
logger.success(
"Successfully upgraded Nuxt from",
currentVersion,
"to",
upgradedVersion
);
if (currentVersion === "[unknown]") {
return;
}
const commitA = nuxtVersionToGitIdentifier(currentVersion);
const commitB = nuxtVersionToGitIdentifier(upgradedVersion);
if (commitA && commitB) {
logger.info(
"Changelog:",
`https://github.com/nuxt/nuxt/compare/${commitA}...${commitB}`
);
}
}
}
});
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 ${cwd}`);
return void 0;
}
return lockFile;
}
export { upgrade as default };