UNPKG

nuxi

Version:
480 lines (479 loc) 17.5 kB
import { i as __require, o as __toESM, t as __commonJSMin } from "./chunk-Vs_PY4HZ.mjs"; import { t as defineCommand } from "./dist-B03QHgrC.mjs"; import { n as colors } from "./consola.DXBYu-KD-qSGefJ79.mjs"; import "./utils-MaFlCoS1.mjs"; import { a as legacyRootDirArgs, i as extendsArgs, n as dotEnvArgs, o as logLevelArgs, r as envNameArgs, t as cwdArgs } from "./_shared-D6pJgr6t.mjs"; import { g as ye, n as logger, p as oe } from "./logger-CtlB9piy.mjs"; import "./defu-C23GdbdT.mjs"; import { c as resolve$1 } from "./pathe.M-eThtNZ-BfnU2wdd.mjs"; import { r as relativeToProcess, t as loadKit } from "./kit-Bx45zdA5.mjs"; import "./jiti-BfsRAE30.mjs"; import { t as V } from "./main-BD07ngkv.mjs"; import { dirname } from "node:path"; import process$1 from "node:process"; import "node:url"; import { existsSync, promises, statSync } from "node:fs"; import "node:os"; import "node:fs/promises"; //#endregion //#region ../../node_modules/.pnpm/c12@3.3.4_magicast@0.5.2/node_modules/c12/dist/index.mjs var import_main = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => { const fs$1 = __require("fs"); const path$1 = __require("path"); const os$1 = __require("os"); const crypto = __require("crypto"); const TIPS = [ "◈ encrypted .env [www.dotenvx.com]", "◈ secrets for agents [www.dotenvx.com]", "⌁ auth for agents [www.vestauth.com]", "⌘ custom filepath { path: '/custom/path/.env' }", "⌘ enable debugging { debug: true }", "⌘ override existing { override: true }", "⌘ suppress logs { quiet: true }", "⌘ multiple files { path: ['.env.local', '.env'] }" ]; function _getRandomTip() { return TIPS[Math.floor(Math.random() * TIPS.length)]; } function parseBoolean(value) { if (typeof value === "string") return ![ "false", "0", "no", "off", "" ].includes(value.toLowerCase()); return Boolean(value); } function supportsAnsi() { return process.stdout.isTTY; } function dim(text) { return supportsAnsi() ? `\x1b[2m${text}\x1b[0m` : text; } const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm; function parse(src) { const obj = {}; let lines = src.toString(); lines = lines.replace(/\r\n?/gm, "\n"); let match; while ((match = LINE.exec(lines)) != null) { const key = match[1]; let value = match[2] || ""; value = value.trim(); const maybeQuote = value[0]; value = value.replace(/^(['"`])([\s\S]*)\1$/gm, "$2"); if (maybeQuote === "\"") { value = value.replace(/\\n/g, "\n"); value = value.replace(/\\r/g, "\r"); } obj[key] = value; } return obj; } function _parseVault(options) { options = options || {}; const vaultPath = _vaultPath(options); options.path = vaultPath; const result = DotenvModule.configDotenv(options); if (!result.parsed) { const err = /* @__PURE__ */ new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`); err.code = "MISSING_DATA"; throw err; } const keys = _dotenvKey(options).split(","); const length = keys.length; let decrypted; for (let i = 0; i < length; i++) try { const attrs = _instructions(result, keys[i].trim()); decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key); break; } catch (error) { if (i + 1 >= length) throw error; } return DotenvModule.parse(decrypted); } function _warn(message) { console.error(`⚠ ${message}`); } function _debug(message) { console.log(`┆ ${message}`); } function _log(message) { console.log(`◇ ${message}`); } function _dotenvKey(options) { if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) return options.DOTENV_KEY; if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) return process.env.DOTENV_KEY; return ""; } function _instructions(result, dotenvKey) { let uri; try { uri = new URL(dotenvKey); } catch (error) { if (error.code === "ERR_INVALID_URL") { const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development"); err.code = "INVALID_DOTENV_KEY"; throw err; } throw error; } const key = uri.password; if (!key) { const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: Missing key part"); err.code = "INVALID_DOTENV_KEY"; throw err; } const environment = uri.searchParams.get("environment"); if (!environment) { const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: Missing environment part"); err.code = "INVALID_DOTENV_KEY"; throw err; } const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`; const ciphertext = result.parsed[environmentKey]; if (!ciphertext) { const err = /* @__PURE__ */ new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`); err.code = "NOT_FOUND_DOTENV_ENVIRONMENT"; throw err; } return { ciphertext, key }; } function _vaultPath(options) { let possibleVaultPath = null; if (options && options.path && options.path.length > 0) if (Array.isArray(options.path)) { for (const filepath of options.path) if (fs$1.existsSync(filepath)) possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`; } else possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`; else possibleVaultPath = path$1.resolve(process.cwd(), ".env.vault"); if (fs$1.existsSync(possibleVaultPath)) return possibleVaultPath; return null; } function _resolveHome(envPath) { return envPath[0] === "~" ? path$1.join(os$1.homedir(), envPath.slice(1)) : envPath; } function _configVault(options) { const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug); const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options && options.quiet); if (debug || !quiet) _log("loading env from encrypted .env.vault"); const parsed = DotenvModule._parseVault(options); let processEnv = process.env; if (options && options.processEnv != null) processEnv = options.processEnv; DotenvModule.populate(processEnv, parsed, options); return { parsed }; } function configDotenv(options) { const dotenvPath = path$1.resolve(process.cwd(), ".env"); let encoding = "utf8"; let processEnv = process.env; if (options && options.processEnv != null) processEnv = options.processEnv; let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options && options.debug); let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options && options.quiet); if (options && options.encoding) encoding = options.encoding; else if (debug) _debug("no encoding is specified (UTF-8 is used by default)"); let optionPaths = [dotenvPath]; if (options && options.path) if (!Array.isArray(options.path)) optionPaths = [_resolveHome(options.path)]; else { optionPaths = []; for (const filepath of options.path) optionPaths.push(_resolveHome(filepath)); } let lastError; const parsedAll = {}; for (const path of optionPaths) try { const parsed = DotenvModule.parse(fs$1.readFileSync(path, { encoding })); DotenvModule.populate(parsedAll, parsed, options); } catch (e) { if (debug) _debug(`failed to load ${path} ${e.message}`); lastError = e; } const populated = DotenvModule.populate(processEnv, parsedAll, options); debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug); quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet); if (debug || !quiet) { const keysCount = Object.keys(populated).length; const shortPaths = []; for (const filePath of optionPaths) try { const relative = path$1.relative(process.cwd(), filePath); shortPaths.push(relative); } catch (e) { if (debug) _debug(`failed to load ${filePath} ${e.message}`); lastError = e; } _log(`injected env (${keysCount}) from ${shortPaths.join(",")} ${dim(`// tip: ${_getRandomTip()}`)}`); } if (lastError) return { parsed: parsedAll, error: lastError }; else return { parsed: parsedAll }; } function config(options) { if (_dotenvKey(options).length === 0) return DotenvModule.configDotenv(options); const vaultPath = _vaultPath(options); if (!vaultPath) { _warn(`you set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}`); return DotenvModule.configDotenv(options); } return DotenvModule._configVault(options); } function decrypt(encrypted, keyStr) { const key = Buffer.from(keyStr.slice(-64), "hex"); let ciphertext = Buffer.from(encrypted, "base64"); const nonce = ciphertext.subarray(0, 12); const authTag = ciphertext.subarray(-16); ciphertext = ciphertext.subarray(12, -16); try { const aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce); aesgcm.setAuthTag(authTag); return `${aesgcm.update(ciphertext)}${aesgcm.final()}`; } catch (error) { const isRange = error instanceof RangeError; const invalidKeyLength = error.message === "Invalid key length"; const decryptionFailed = error.message === "Unsupported state or unable to authenticate data"; if (isRange || invalidKeyLength) { const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)"); err.code = "INVALID_DOTENV_KEY"; throw err; } else if (decryptionFailed) { const err = /* @__PURE__ */ new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY"); err.code = "DECRYPTION_FAILED"; throw err; } else throw error; } } function populate(processEnv, parsed, options = {}) { const debug = Boolean(options && options.debug); const override = Boolean(options && options.override); const populated = {}; if (typeof parsed !== "object") { const err = /* @__PURE__ */ new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate"); err.code = "OBJECT_REQUIRED"; throw err; } for (const key of Object.keys(parsed)) if (Object.prototype.hasOwnProperty.call(processEnv, key)) { if (override === true) { processEnv[key] = parsed[key]; populated[key] = parsed[key]; } if (debug) if (override === true) _debug(`"${key}" is already defined and WAS overwritten`); else _debug(`"${key}" is already defined and was NOT overwritten`); } else { processEnv[key] = parsed[key]; populated[key] = parsed[key]; } return populated; } const DotenvModule = { configDotenv, _configVault, _parseVault, config, decrypt, parse, populate }; module.exports.configDotenv = DotenvModule.configDotenv; module.exports._configVault = DotenvModule._configVault; module.exports._parseVault = DotenvModule._parseVault; module.exports.config = DotenvModule.config; module.exports.decrypt = DotenvModule.decrypt; module.exports.parse = DotenvModule.parse; module.exports.populate = DotenvModule.populate; module.exports = DotenvModule; })))(), 1); /** * Load and interpolate environment variables into `process.env`. * If you need more control (or access to the values), consider using `loadDotenv` instead * */ async function setupDotenv(options) { const targetEnvironment = options.env ?? process.env; const environment = await loadDotenv({ cwd: options.cwd, fileName: options.fileName ?? ".env", env: targetEnvironment, interpolate: options.interpolate ?? true }); const dotenvVars = getDotEnvVars(targetEnvironment); for (const key in environment) { if (key.startsWith("_")) continue; if (targetEnvironment[key] === void 0 || dotenvVars.has(key)) targetEnvironment[key] = environment[key]; } return environment; } /** Load environment variables into an object. */ async function loadDotenv(options) { const environment = Object.create(null); const cwd = resolve$1(options.cwd || "."); const _fileName = options.fileName || ".env"; const dotenvFiles = typeof _fileName === "string" ? [_fileName] : _fileName; const dotenvVars = getDotEnvVars(options.env || {}); Object.assign(environment, options.env); for (const file of dotenvFiles) { const dotenvFile = resolve$1(cwd, file); if (!statSync(dotenvFile, { throwIfNoEntry: false })?.isFile()) continue; const parsed = import_main.parse(await promises.readFile(dotenvFile, "utf8")); for (const key in parsed) { if (key in environment && !dotenvVars.has(key)) continue; environment[key] = parsed[key]; dotenvVars.add(key); } } if (options.interpolate) interpolate(environment); return environment; } function interpolate(target, source = {}, parse = (v) => v) { function getValue(key) { return source[key] === void 0 ? target[key] : source[key]; } function interpolate(value, parents = []) { if (typeof value !== "string") return value; return parse((value.match(/(.?\${?(?:[\w:]+)?}?)/g) || []).reduce((newValue, match) => { const parts = /(.?)\${?([\w:]+)?}?/g.exec(match) || []; const prefix = parts[1]; let value, replacePart; if (prefix === "\\") { replacePart = parts[0] || ""; value = replacePart.replace(String.raw`\$`, "$"); } else { const key = parts[2]; replacePart = (parts[0] || "").slice(prefix.length); if (parents.includes(key)) { console.warn(`Please avoid recursive environment variables ( loop: ${parents.join(" > ")} > ${key} )`); return ""; } value = getValue(key); value = interpolate(value, [...parents, key]); } return value === void 0 ? newValue : newValue.replace(replacePart, value); }, value)); } for (const key in target) target[key] = interpolate(getValue(key)); } function getDotEnvVars(targetEnvironment) { const globalRegistry = globalThis.__c12_dotenv_vars__ ||= /* @__PURE__ */ new Map(); if (!globalRegistry.has(targetEnvironment)) globalRegistry.set(targetEnvironment, /* @__PURE__ */ new Set()); return globalRegistry.get(targetEnvironment); } Object.freeze([ ".js", ".ts", ".mjs", ".cjs", ".mts", ".cts", ".json", ".jsonc", ".json5", ".yaml", ".yml", ".toml" ]); //#endregion //#region src/commands/preview.ts const command = defineCommand({ meta: { name: "preview", description: "Launches Nitro server for local testing after `nuxi build`." }, args: { ...cwdArgs, ...logLevelArgs, ...envNameArgs, ...extendsArgs, ...legacyRootDirArgs, port: { type: "string", description: "Port to listen on", alias: ["p"] }, ...dotEnvArgs }, async run(ctx) { process$1.env.NODE_ENV = process$1.env.NODE_ENV || "production"; const cwd = resolve$1(ctx.args.cwd || ctx.args.rootDir); const { loadNuxt } = await loadKit(cwd); const nitroJSONPaths = [await new Promise((res) => { loadNuxt({ cwd, dotenv: { cwd, fileName: ctx.args.dotenv }, envName: ctx.args.envName, ready: true, overrides: { ...ctx.args.extends && { extends: ctx.args.extends }, modules: [function(_, nuxt) { nuxt.hook("nitro:init", (nitro) => { res(resolve$1(nuxt.options.srcDir || cwd, nitro.options.output.dir || ".output", "nitro.json")); }); }] } }).then((nuxt) => nuxt.close()).catch(() => ""); }), resolve$1(cwd, ".output", "nitro.json")].filter(Boolean); const nitroJSONPath = nitroJSONPaths.find((p) => existsSync(p)); if (!nitroJSONPath) { logger.error(`Cannot find ${colors.cyan("nitro.json")}. Did you run ${colors.cyan("nuxi build")} first? Search path:\n${nitroJSONPaths.join("\n")}`); process$1.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$1.exit(1); } const info = [ ["Node.js:", `v${process$1.versions.node}`], ["Nitro preset:", nitroJSON.preset], ["Working directory:", relativeToProcess(outputPath)] ]; const _infoKeyLen = Math.max(...info.map(([label]) => label.length)); logger.message(""); oe([ "", "You are previewing a Nuxt app. In production, do not use this CLI. ", `Instead, run ${colors.cyan(nitroJSON.commands.preview)} directly.`, "", ...info.map(([label, value]) => `${label.padEnd(_infoKeyLen, " ")} ${colors.cyan(value)}`), "" ].join("\n"), colors.yellow(" Previewing Nuxt app "), { contentAlign: "left", titleAlign: "left", width: "auto", titlePadding: 2, contentPadding: 2, rounded: true, withGuide: true, formatBorder: (text) => colors.yellow(text) }); const envFileName = ctx.args.dotenv || ".env"; if (existsSync(resolve$1(cwd, envFileName))) { logger.info(`Loading ${colors.cyan(envFileName)}. This will not be loaded when running the server in production.`); await setupDotenv({ cwd, fileName: envFileName }); } else if (ctx.args.dotenv) logger.error(`Cannot find ${colors.cyan(envFileName)}.`); const port = ctx.args.port ?? process$1.env.NUXT_PORT ?? process$1.env.NITRO_PORT ?? process$1.env.PORT; ye(`Running ${colors.cyan(nitroJSON.commands.preview)} in ${colors.cyan(relativeToProcess(outputPath))}`); const [command, ...commandArgs] = nitroJSON.commands.preview.split(" "); await V(command, commandArgs, { throwOnError: true, nodeOptions: { stdio: "inherit", cwd: outputPath, env: { ...process$1.env, NUXT_PORT: port, NITRO_PORT: port } } }); } }); //#endregion export { command as default };