@super-repo/envx 0.2.2 → 0.2.3-b.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto.js +3 -7
- package/dist/auto.js.map +1 -1
- package/dist/bin/dotenvx.d.ts +0 -2
- package/dist/bin/dotenvx.d.ts.map +1 -1
- package/dist/bin/dotenvx.js +0 -4
- package/dist/chunks/commands-CcoGlJ3P.js +354 -0
- package/dist/chunks/commands-CcoGlJ3P.js.map +1 -0
- package/dist/chunks/src-Bu_9Htex.js +0 -0
- package/dist/chunks/src-Bu_9Htex.js.map +1 -0
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +4 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/debug.d.ts +1 -1
- package/dist/commands/decrypt.d.ts +1 -1
- package/dist/commands/encrypt.d.ts +1 -1
- package/dist/commands/expand.d.ts +1 -1
- package/dist/commands/expand.d.ts.map +1 -1
- package/dist/commands/index.d.ts +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +2 -159
- package/dist/commands/print.d.ts +1 -1
- package/dist/commands/run.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +32 -58
- package/dist/index.js.map +1 -1
- package/package.json +13 -6
- package/dist/.tsbuildinfo +0 -1
- package/dist/bin/dotenvx.js.map +0 -1
- package/dist/commands/debug.js +0 -21
- package/dist/commands/debug.js.map +0 -1
- package/dist/commands/decrypt.js +0 -73
- package/dist/commands/decrypt.js.map +0 -1
- package/dist/commands/encrypt.js +0 -82
- package/dist/commands/encrypt.js.map +0 -1
- package/dist/commands/expand.js +0 -83
- package/dist/commands/expand.js.map +0 -1
- package/dist/commands/index.js.map +0 -1
- package/dist/commands/print.js +0 -27
- package/dist/commands/print.js.map +0 -1
- package/dist/commands/run.js +0 -40
- package/dist/commands/run.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"src-Bu_9Htex.js","names":[],"sources":["../../../libs/src/crypto.ts","../../../libs/src/parser.ts","../../../libs/src/keys.ts","../../../libs/src/match.ts","../../../libs/src/encrypt.ts","../../../libs/src/decrypt.ts","../../../libs/src/expand.ts","../../../libs/src/config.ts","../../../common/src/logger.ts","../../../libs/src/env.ts","../../../libs/src/index.ts"],"sourcesContent":["import * as crypto from \"crypto\";\n\n// #region -- Algorithm Parameters --------------------------\n\n/**\n * AES-256-GCM with a random 96-bit nonce. Format on the wire:\n *\n * \"encrypted:\" + base64( nonce(12) ‖ ciphertext ‖ tag(16) )\n *\n * The `encrypted:` prefix matches the visual convention used by\n * upstream dotenvx, so encrypted values are recognizable in diffs even\n * though our crypto scheme is independent.\n */\nconst ALGORITHM = \"aes-256-gcm\" as const;\nconst NONCE_BYTES = 12;\nconst TAG_BYTES = 16;\nconst KEY_BYTES = 32;\nexport const ENCRYPTED_PREFIX = \"encrypted:\";\n\n// #endregion -----------------------------------------------\n\n// #region -- Key Generation --------------------------------\n\n/** Generate a fresh 256-bit private key encoded as 64 hex chars. */\nexport function generatePrivateKey(): string {\n return crypto.randomBytes(KEY_BYTES).toString(\"hex\");\n}\n\nfunction decodeKey(keyHex: string): Buffer {\n const buf = Buffer.from(keyHex, \"hex\");\n if (buf.length !== KEY_BYTES) {\n throw new Error(\n `[INVALID_KEY] private key must decode to ${String(KEY_BYTES)} bytes, got ${String(buf.length)}`,\n );\n }\n return buf;\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- Encrypt / Decrypt -----------------------------\n\n/** Returns true if `value` looks like one of our ciphertext blobs. */\nexport function isEncrypted(value: string): boolean {\n return value.startsWith(ENCRYPTED_PREFIX);\n}\n\n/** AES-256-GCM encrypt; returns the `encrypted:<base64>` form. */\nexport function encryptValue(plaintext: string, keyHex: string): string {\n const key = decodeKey(keyHex);\n const nonce = crypto.randomBytes(NONCE_BYTES);\n const cipher = crypto.createCipheriv(ALGORITHM, key, nonce);\n const ciphertext = Buffer.concat([\n cipher.update(plaintext, \"utf8\"),\n cipher.final(),\n ]);\n const tag = cipher.getAuthTag();\n return ENCRYPTED_PREFIX + Buffer.concat([nonce, ciphertext, tag]).toString(\"base64\");\n}\n\n/**\n * AES-256-GCM decrypt. Throws on a corrupt/truncated blob, an auth-tag\n * mismatch, or a wrong key. Throws Errors with `.code` set so callers\n * can distinguish failure modes.\n */\nexport function decryptValue(blob: string, keyHex: string): string {\n if (!isEncrypted(blob)) {\n throw makeError(\"INVALID_CIPHERTEXT\", `value does not start with \"${ENCRYPTED_PREFIX}\"`);\n }\n const key = decodeKey(keyHex);\n const data = Buffer.from(blob.slice(ENCRYPTED_PREFIX.length), \"base64\");\n if (data.length < NONCE_BYTES + TAG_BYTES) {\n throw makeError(\"INVALID_CIPHERTEXT\", `ciphertext too short (${String(data.length)} bytes)`);\n }\n const nonce = data.subarray(0, NONCE_BYTES);\n const tag = data.subarray(data.length - TAG_BYTES);\n const ciphertext = data.subarray(NONCE_BYTES, data.length - TAG_BYTES);\n const decipher = crypto.createDecipheriv(ALGORITHM, key, nonce);\n decipher.setAuthTag(tag);\n try {\n return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString(\"utf8\");\n } catch (e) {\n const code =\n (e as NodeJS.ErrnoException).code === \"ERR_OSSL_BAD_DECRYPT\" ||\n (e as NodeJS.ErrnoException).code === \"ERR_CRYPTO_INVALID_AUTH_TAG\"\n ? \"DECRYPTION_FAILED\"\n : \"INVALID_CIPHERTEXT\";\n throw makeError(code, \"decryption failed (wrong key or tampered ciphertext)\");\n }\n}\n\ninterface CryptoError extends Error {\n code: string;\n}\n\nfunction makeError(code: string, message: string): CryptoError {\n const e = new Error(message) as CryptoError;\n e.code = code;\n return e;\n}\n\n// #endregion -----------------------------------------------\n","// #region -- Env File Parser -------------------------------\n\n/**\n * Line-preserving env-file parser. We parse to a typed line array\n * rather than a flat key→value map so that round-tripping (encrypt\n * one value, write file back) preserves comments, blank lines, and\n * declaration order — the signal-to-noise ratio of an env file's diff\n * is critical when these files live in version control.\n */\nexport interface KvLine {\n readonly type: \"kv\";\n readonly key: string;\n /** Raw value as it appeared in the file (still quoted if it was). */\n readonly raw: string;\n /** Logical value — quotes stripped, escape sequences resolved. */\n value: string;\n /** Quote style for serialization. Mutable so transforms (e.g. encrypt)\n * can drop quotes when the new value is self-quote-safe (URL-safe base64). */\n quote: '\"' | \"'\" | \"\";\n /** Trailing comment, including the leading '#' and whitespace. */\n readonly trailing: string;\n}\n\nexport interface RawLine {\n readonly type: \"raw\";\n /** Comment lines, blank lines, malformed lines — preserved verbatim. */\n readonly raw: string;\n}\n\nexport type EnvLine = KvLine | RawLine;\n\nconst KV_REGEX = /^\\s*([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(.*?)\\s*$/;\n\n/** Parse a raw env-file string into a line array. */\nexport function parseEnv(content: string): EnvLine[] {\n const lines = content.split(\"\\n\");\n // If the file has a trailing newline, split() leaves a trailing \"\".\n // Drop it so we don't emit an extra blank raw line on round-trip.\n const trailingEmpty = lines.length > 0 && lines[lines.length - 1] === \"\";\n const body = trailingEmpty ? lines.slice(0, -1) : lines;\n\n const out: EnvLine[] = body.map((line) => {\n if (line.trim() === \"\" || line.trim().startsWith(\"#\")) {\n return { type: \"raw\", raw: line };\n }\n const match = KV_REGEX.exec(line);\n if (!match) return { type: \"raw\", raw: line };\n\n const key = match[1]!;\n const rawValueAndComment = match[2]!;\n const { rawValue, trailing } = splitTrailingComment(rawValueAndComment);\n const { value, quote } = unquote(rawValue);\n\n return { type: \"kv\", key, raw: rawValue, value, quote, trailing };\n });\n\n if (trailingEmpty) out.push({ type: \"raw\", raw: \"\" });\n return out;\n}\n\n/** Re-serialize a parsed line array. Round-trip safe for unmodified inputs. */\nexport function serializeEnv(lines: readonly EnvLine[]): string {\n return lines\n .map((line) => {\n if (line.type === \"raw\") return line.raw;\n const valueText = renderValue(line.value, line.quote);\n return `${line.key}=${valueText}${line.trailing}`;\n })\n .join(\"\\n\");\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- Internal helpers ------------------------------\n\nfunction splitTrailingComment(s: string): { rawValue: string; trailing: string } {\n // Quoted values: anything past the closing quote is trailing\n // whitespace + comment, returned verbatim so round-tripping is exact.\n if (s.startsWith('\"') || s.startsWith(\"'\")) {\n const quote = s[0]!;\n let i = 1;\n while (i < s.length) {\n if (s[i] === \"\\\\\") {\n i += 2;\n continue;\n }\n if (s[i] === quote) {\n i += 1;\n break;\n }\n i += 1;\n }\n return { rawValue: s.slice(0, i), trailing: s.slice(i) };\n }\n // Unquoted: # starts a comment when preceded by whitespace.\n const m = /\\s+#.*$/.exec(s);\n if (!m) return { rawValue: s, trailing: \"\" };\n return {\n rawValue: s.slice(0, m.index),\n trailing: s.slice(m.index),\n };\n}\n\nfunction unquote(raw: string): { value: string; quote: '\"' | \"'\" | \"\" } {\n if (raw.length >= 2 && raw.startsWith('\"') && raw.endsWith('\"')) {\n return { value: unescapeDoubleQuoted(raw.slice(1, -1)), quote: '\"' };\n }\n if (raw.length >= 2 && raw.startsWith(\"'\") && raw.endsWith(\"'\")) {\n return { value: raw.slice(1, -1), quote: \"'\" };\n }\n return { value: raw, quote: \"\" };\n}\n\nfunction unescapeDoubleQuoted(s: string): string {\n return s\n .replace(/\\\\\\\\/g, \"\u0000\")\n .replace(/\\\\n/g, \"\\n\")\n .replace(/\\\\r/g, \"\\r\")\n .replace(/\\\\t/g, \"\\t\")\n .replace(/\\\\\"/g, '\"')\n .replace(/\u0000/g, \"\\\\\");\n}\n\nfunction escapeDoubleQuoted(s: string): string {\n return s\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, \"\\\\n\")\n .replace(/\\r/g, \"\\\\r\")\n .replace(/\\t/g, \"\\\\t\");\n}\n\nfunction renderValue(value: string, originalQuote: '\"' | \"'\" | \"\"): string {\n // Decide a safe quote style. If the value contains characters that\n // would break unquoted form (whitespace, $, #, ', \"), force quoting.\n const needsQuotes = /[\\s#$\"'`\\\\]/.test(value) || value === \"\";\n if (originalQuote === \"'\" && !value.includes(\"'\")) {\n return `'${value}'`;\n }\n if (originalQuote === \"'\" && value.includes(\"'\")) {\n // Single quotes can't escape — fall back to double.\n return `\"${escapeDoubleQuoted(value)}\"`;\n }\n if (originalQuote === '\"') {\n return `\"${escapeDoubleQuoted(value)}\"`;\n }\n // No original quotes — keep unquoted unless we have to.\n if (!needsQuotes) return value;\n return `\"${escapeDoubleQuoted(value)}\"`;\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- Convenience -----------------------------------\n\n/** Build a flat key→value map from a parsed line array. Last write wins. */\nexport function toRecord(lines: readonly EnvLine[]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const line of lines) {\n if (line.type === \"kv\") out[line.key] = line.value;\n }\n return out;\n}\n\n// #endregion -----------------------------------------------\n","import * as fs from \"fs\";\nimport * as path from \"path\";\n\nimport { parseEnv, serializeEnv, toRecord } from \"./parser.js\";\n\n// #region -- Per-file Key Naming ---------------------------\n\n/**\n * Canonical (default) prefix for envx private-key variables. Used when\n * encrypt writes a fresh entry to `.env.keys`.\n */\nexport const ENVX_PRIVATE_KEY_PREFIX = \"ENVX_PRIVATE_KEY\";\n\n/**\n * Legacy prefix kept for backwards compatibility with the upstream\n * `dotenvx` convention. envx will read keys stored under this prefix\n * but never *writes* new ones with it.\n */\nexport const LEGACY_PRIVATE_KEY_PREFIX = \"DOTENV_PRIVATE_KEY\";\n\n/**\n * Canonical private-key variable name for an env file:\n * `ENVX_PRIVATE_KEY` for `.env`, `ENVX_PRIVATE_KEY_PROD` for `.env.prod`,\n * etc. This is the name encrypt writes to `.env.keys`.\n *\n * Decrypt accepts both this and the legacy `DOTENV_PRIVATE_KEY*` form\n * — see {@link privateKeyCandidateNamesFor}.\n */\nexport function privateKeyNameFor(envFilePath: string): string {\n return privateKeyNameForWithPrefix(envFilePath, ENVX_PRIVATE_KEY_PREFIX);\n}\n\n/**\n * Both names a `.env.keys` file may use for the given env file's private\n * key, in resolution order:\n *\n * 1. `ENVX_PRIVATE_KEY*` (canonical — written by current envx)\n * 2. `DOTENV_PRIVATE_KEY*` (legacy — written by upstream dotenvx\n * and earlier envx versions)\n *\n * Callers should check each name against the keys map and use the first\n * match. New keys are always written under the canonical name.\n */\nexport function privateKeyCandidateNamesFor(\n envFilePath: string,\n): readonly string[] {\n return [\n privateKeyNameForWithPrefix(envFilePath, ENVX_PRIVATE_KEY_PREFIX),\n privateKeyNameForWithPrefix(envFilePath, LEGACY_PRIVATE_KEY_PREFIX),\n ];\n}\n\nfunction privateKeyNameForWithPrefix(\n envFilePath: string,\n prefix: string,\n): string {\n const basename = path.basename(envFilePath);\n if (basename === \".env\") return prefix;\n const suffix = basename.replace(/^\\.env\\./, \"\");\n return `${prefix}_${normalize(suffix)}`;\n}\n\nfunction normalize(s: string): string {\n return s.toUpperCase().replace(/[^A-Z0-9]/g, \"_\");\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- .env.keys File I/O ----------------------------\n\n/** Read a .env.keys file as a key→value map. Returns an empty map when the file doesn't exist. */\nexport function readKeysFile(keysPath: string): Map<string, string> {\n if (!fs.existsSync(keysPath)) return new Map();\n const lines = parseEnv(fs.readFileSync(keysPath, \"utf8\"));\n return new Map(Object.entries(toRecord(lines)));\n}\n\n/**\n * Persist a key→value map to .env.keys. Overwrites the file. Preserves\n * order from the input map (so consumers get stable diffs).\n */\nexport function writeKeysFile(keysPath: string, keys: Map<string, string>): void {\n // Re-serialize using the parser/serializer so quoting follows the same\n // conventions as the .env files we read/write.\n const linesOut: import(\"./parser.js\").EnvLine[] = [];\n let first = true;\n for (const [key, value] of keys) {\n if (first) first = false;\n linesOut.push({\n type: \"kv\",\n key,\n value,\n raw: value,\n quote: '\"',\n trailing: \"\",\n });\n }\n fs.writeFileSync(keysPath, serializeEnv(linesOut) + \"\\n\");\n}\n\n/**\n * Default location for `.env.keys`: at the caller's cwd, NOT alongside the\n * env file. Keeping the keys file at the project root makes `--dir vault`\n * (or `--env-path vault`) move the env files into a subdirectory while\n * leaving the keys file in a single, predictable spot.\n *\n * Callers can still pass an explicit path via `--env-keys-file` / config's\n * `envKeysFile` to override.\n */\nexport function defaultKeysPath(): string {\n return path.resolve(process.cwd(), \".env.keys\");\n}\n\n/**\n * @deprecated Use `defaultKeysPath()` instead. Kept as a thin re-export so\n * external callers don't break — the `envFilepath` argument is now ignored\n * and the returned path is always `<cwd>/.env.keys`.\n */\nexport function defaultKeysPathFor(_envFilepath: string): string {\n return defaultKeysPath();\n}\n\n// #endregion -----------------------------------------------\n","// #region -- Glob matching ---------------------------------\n\n/**\n * Tiny glob matcher: `*` matches any run of characters within a key\n * name, `?` matches a single character, anything else is literal.\n * Sufficient for the include/exclude key filters; for full picomatch\n * semantics, swap this out — the predicates only consume a string.\n */\nfunction compile(pattern: string): RegExp {\n const escaped = pattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const body = escaped.replace(/\\*/g, \".*\").replace(/\\?/g, \".\");\n return new RegExp(`^${body}$`);\n}\n\nexport function matchesAny(key: string, patterns: readonly string[]): boolean {\n for (const pattern of patterns) {\n if (compile(pattern).test(key)) return true;\n }\n return false;\n}\n\n/**\n * Decide whether to operate on a key given include + exclude filters.\n * Empty includes means \"all keys\". Excludes always win.\n */\nexport function isSelected(\n key: string,\n includes: readonly string[],\n excludes: readonly string[],\n): boolean {\n if (excludes.length > 0 && matchesAny(key, excludes)) return false;\n if (includes.length === 0) return true;\n return matchesAny(key, includes);\n}\n\n// #endregion -----------------------------------------------\n","import * as fs from \"fs\";\nimport * as path from \"path\";\n\nimport {\n ENCRYPTED_PREFIX,\n encryptValue,\n generatePrivateKey,\n isEncrypted,\n} from \"./crypto.js\";\nimport {\n defaultKeysPath,\n privateKeyCandidateNamesFor,\n readKeysFile,\n writeKeysFile,\n} from \"./keys.js\";\nimport { isSelected } from \"./match.js\";\nimport { parseEnv, serializeEnv } from \"./parser.js\";\nimport type { ProcessedEnv, RunOptions, RunResult } from \"./types.js\";\n\n// #region -- encryptFiles ----------------------------------\n\n/**\n * Encrypt selected values across one or more env files. Pure: returns\n * new file contents but does not write to disk. Use {@link writeProcessed}\n * to persist. Will create a private key in `.env.keys` on first run for\n * each file (this is a side effect — the key file is written eagerly so\n * the returned envSrc is decryptable).\n */\nexport function encryptFiles(opts: RunOptions): RunResult {\n const includes = opts.keys ?? [];\n const excludes = opts.excludeKeys ?? [];\n const processedEnvs: ProcessedEnv[] = [];\n const changedFilepaths: string[] = [];\n const unchangedFilepaths: string[] = [];\n\n for (const envFilePath of opts.envFiles) {\n const filepath = path.resolve(envFilePath);\n const keysPath = opts.envKeysFile\n ? path.resolve(opts.envKeysFile)\n : defaultKeysPath();\n\n if (!fs.existsSync(filepath)) {\n processedEnvs.push({\n envFilepath: envFilePath,\n filepath,\n envSrc: \"\",\n changed: false,\n keys: [],\n error: {\n code: \"MISSING_ENV_FILE\",\n message: `env file not found: ${envFilePath}`,\n help: `add one with [echo \"HELLO=World\" > ${envFilePath}] and re-run`,\n },\n });\n continue;\n }\n\n const keysMap = readKeysFile(keysPath);\n // Resolution order: canonical ENVX_PRIVATE_KEY* first, then legacy\n // DOTENV_PRIVATE_KEY* for back-compat with existing `.env.keys` files\n // (upstream dotenvx, or pre-rename envx). If neither is present we\n // generate a fresh key and store it under the canonical name; if the\n // legacy entry exists we *reuse its value* (so values already\n // encrypted with that key continue to round-trip) without renaming\n // the entry — leave migration as an explicit opt-in.\n const candidateNames = privateKeyCandidateNamesFor(envFilePath);\n const canonicalName = candidateNames[0]!;\n let keyName = canonicalName;\n let keyHex: string | undefined;\n for (const name of candidateNames) {\n const v = keysMap.get(name);\n if (v) {\n keyHex = v;\n keyName = name;\n break;\n }\n }\n let privateKeyAdded = false;\n if (!keyHex) {\n keyHex = generatePrivateKey();\n keysMap.set(canonicalName, keyHex);\n keyName = canonicalName;\n writeKeysFile(keysPath, keysMap);\n privateKeyAdded = true;\n }\n\n const lines = parseEnv(fs.readFileSync(filepath, \"utf8\"));\n const fileKeys: string[] = [];\n let changed = false;\n\n for (const line of lines) {\n if (line.type !== \"kv\") continue;\n fileKeys.push(line.key);\n if (isEncrypted(line.value)) continue;\n if (!isSelected(line.key, includes, excludes)) continue;\n line.value = encryptValue(line.value, keyHex);\n // `encrypted:<base64>` is URL-safe — drop any inherited quote style so\n // diffs stay minimal. Decrypt restores the value, render reapplies\n // quotes based on the plaintext's content if needed.\n line.quote = \"\";\n changed = true;\n }\n\n const envSrc = serializeEnv(lines);\n const processed: ProcessedEnv = {\n envFilepath: envFilePath,\n filepath,\n envSrc,\n changed,\n keys: fileKeys,\n ...(privateKeyAdded\n ? { privateKeyAdded: true, privateKeyName: keyName, privateKey: keyHex }\n : {}),\n };\n processedEnvs.push(processed);\n if (changed) changedFilepaths.push(filepath);\n else unchangedFilepaths.push(filepath);\n }\n\n return { processedEnvs, changedFilepaths, unchangedFilepaths };\n}\n\n// Re-export the prefix so callers can detect ciphertext at the consumer level.\nexport { ENCRYPTED_PREFIX };\n\n// #endregion -----------------------------------------------\n","import * as fs from \"fs\";\nimport * as path from \"path\";\n\nimport { decryptValue, isEncrypted } from \"./crypto.js\";\nimport {\n defaultKeysPath,\n privateKeyCandidateNamesFor,\n readKeysFile,\n} from \"./keys.js\";\nimport { isSelected } from \"./match.js\";\nimport { parseEnv, serializeEnv } from \"./parser.js\";\n\nfunction needsQuotes(value: string): boolean {\n return /[\\s#$\"'`\\\\]/.test(value) || value === \"\";\n}\nimport type { ProcessedEnv, ProcessingError, RunOptions, RunResult } from \"./types.js\";\n\n// #region -- decryptFiles ----------------------------------\n\n/**\n * Decrypt selected values across one or more env files. Pure: returns\n * new file contents but does not write to disk. Errors per-file (missing\n * env file, missing private key, bad ciphertext) surface in the\n * `processed.error` field so a single broken file doesn't kill the\n * whole batch.\n */\nexport function decryptFiles(opts: RunOptions): RunResult {\n const includes = opts.keys ?? [];\n const excludes = opts.excludeKeys ?? [];\n const processedEnvs: ProcessedEnv[] = [];\n const changedFilepaths: string[] = [];\n const unchangedFilepaths: string[] = [];\n\n for (const envFilePath of opts.envFiles) {\n const filepath = path.resolve(envFilePath);\n const keysPath = opts.envKeysFile\n ? path.resolve(opts.envKeysFile)\n : defaultKeysPath();\n\n if (!fs.existsSync(filepath)) {\n processedEnvs.push({\n envFilepath: envFilePath,\n filepath,\n envSrc: \"\",\n changed: false,\n keys: [],\n error: {\n code: \"MISSING_ENV_FILE\",\n message: `env file not found: ${envFilePath}`,\n },\n });\n continue;\n }\n\n const keysMap = readKeysFile(keysPath);\n // Try the canonical ENVX_PRIVATE_KEY* name first, then fall back to\n // the legacy DOTENV_PRIVATE_KEY* name (upstream dotenvx convention).\n // Error messages reference the canonical name since that's what new\n // setups should produce.\n const candidateNames = privateKeyCandidateNamesFor(envFilePath);\n const canonicalName = candidateNames[0]!;\n const keyName = canonicalName;\n let keyHex: string | undefined;\n for (const name of candidateNames) {\n const v = keysMap.get(name);\n if (v) {\n keyHex = v;\n break;\n }\n }\n\n const lines = parseEnv(fs.readFileSync(filepath, \"utf8\"));\n const fileKeys: string[] = [];\n let changed = false;\n let decryptError: ProcessingError | undefined;\n\n for (const line of lines) {\n if (line.type !== \"kv\") continue;\n fileKeys.push(line.key);\n if (!isEncrypted(line.value)) continue;\n if (!isSelected(line.key, includes, excludes)) continue;\n if (!keyHex) {\n decryptError = {\n code: \"MISSING_PRIVATE_KEY\",\n message: `no ${keyName} found in ${keysPath}`,\n help: `set ${keyName} in your .env.keys file or pass --env-keys-file`,\n };\n break;\n }\n try {\n line.value = decryptValue(line.value, keyHex);\n // Re-derive a sensible quote style from the decrypted content. We\n // can't recover the user's original quote choice (it was lost when\n // we encrypted), but we can quote whenever the value would be\n // ambiguous unquoted, and use double quotes by default so escape\n // sequences round-trip cleanly.\n line.quote = needsQuotes(line.value) ? '\"' : \"\";\n changed = true;\n } catch (e) {\n decryptError = {\n code:\n (e as { code?: string }).code === \"DECRYPTION_FAILED\"\n ? \"DECRYPTION_FAILED\"\n : \"INVALID_CIPHERTEXT\",\n message: `${envFilePath}: ${(e as Error).message} (key=${line.key})`,\n };\n break;\n }\n }\n\n const envSrc = serializeEnv(lines);\n const processed: ProcessedEnv = {\n envFilepath: envFilePath,\n filepath,\n envSrc: decryptError ? fs.readFileSync(filepath, \"utf8\") : envSrc,\n changed: !decryptError && changed,\n keys: fileKeys,\n ...(decryptError ? { error: decryptError } : {}),\n };\n processedEnvs.push(processed);\n if (processed.changed) changedFilepaths.push(filepath);\n else if (!decryptError) unchangedFilepaths.push(filepath);\n }\n\n return { processedEnvs, changedFilepaths, unchangedFilepaths };\n}\n\n// #endregion -----------------------------------------------\n","import { parseEnv, serializeEnv } from \"./parser.js\";\n\n// #region -- Variable Expansion ----------------------------\n\n/**\n * Expand `${VAR}`, `$VAR`, `${VAR:-default}`, and `${VAR:?error}` references\n * in env-file values. Iterative + cycle-safe: builds a dependency graph,\n * topologically substitutes, and bails with a clear error on cycles.\n *\n * More robust than the bash version in `.github/actions/decrypt-vault`:\n * - Handles `$VAR` (bare) and `${VAR}` syntactically.\n * - Supports `${VAR:-default}` (use default if VAR is unset/empty)\n * and `${VAR:?msg}` (error if unset/empty).\n * - Supports `\\${VAR}` and `\\$VAR` escapes for literal `${VAR}` / `$VAR`.\n * - Detects cycles instead of silently truncating after N passes.\n * - Reports each unresolved variable, doesn't silently leave them.\n */\n\nexport interface ExpandOptions {\n /**\n * Variables to layer in beneath the file's own values. The file's\n * values take precedence; this is the fallback (typically process.env).\n */\n readonly fallback?: Readonly<Record<string, string | undefined>>;\n /**\n * What to do when a `${UNSET_VAR}` reference can't be resolved.\n * - \"leave\" (default): keep the literal `${UNSET_VAR}` in place,\n * and add a warning to the result.\n * - \"empty\": substitute an empty string, add a warning.\n * - \"throw\": throw an Error listing all unresolved refs.\n */\n readonly onMissing?: \"leave\" | \"empty\" | \"throw\";\n}\n\nexport interface ExpandResult {\n /** Expanded key→value map (file-only — fallback is not included). */\n readonly values: Record<string, string>;\n /** Re-serialized env-file content with all values expanded. */\n readonly envSrc: string;\n /** Variables that were referenced but couldn't be resolved. */\n readonly unresolved: string[];\n /** Variables that participated in an unresolvable cycle. */\n readonly cycles: string[][];\n}\n\n/** Expand a key→value record. Returns the expanded record + diagnostics. */\nexport function expandRecord(\n values: Readonly<Record<string, string>>,\n opts: ExpandOptions = {},\n): { values: Record<string, string>; unresolved: string[]; cycles: string[][] } {\n const onMissing = opts.onMissing ?? \"leave\";\n const fallback = opts.fallback ?? {};\n\n // Iterative DFS-based resolution. Cache resolved values; track in-flight\n // keys to detect cycles.\n const resolved: Record<string, string> = {};\n const inFlight = new Set<string>();\n const unresolved = new Set<string>();\n const cycles: string[][] = [];\n\n function isDefined(name: string): boolean {\n if (Object.prototype.hasOwnProperty.call(values, name)) return true;\n if (Object.prototype.hasOwnProperty.call(fallback, name) && fallback[name] !== undefined) {\n return true;\n }\n return false;\n }\n\n function lookup(name: string, stack: string[]): string {\n if (Object.prototype.hasOwnProperty.call(resolved, name)) return resolved[name]!;\n if (inFlight.has(name)) {\n const cycleStart = stack.indexOf(name);\n cycles.push(stack.slice(cycleStart === -1 ? 0 : cycleStart).concat(name));\n return \"\";\n }\n if (Object.prototype.hasOwnProperty.call(values, name)) {\n inFlight.add(name);\n const result = expandString(values[name]!, [...stack, name]);\n inFlight.delete(name);\n resolved[name] = result;\n return result;\n }\n if (Object.prototype.hasOwnProperty.call(fallback, name)) {\n const v = fallback[name];\n if (v !== undefined) {\n resolved[name] = v;\n return v;\n }\n }\n return \"\";\n }\n\n function expandString(input: string, stack: string[]): string {\n return substitute(input, (varName, fallbackForm) => {\n const defined = isDefined(varName);\n\n // Fully unresolved: short-circuit on default/error before touching unresolved set.\n if (!defined) {\n if (fallbackForm?.kind === \"default\") {\n return expandString(fallbackForm.value, stack);\n }\n if (fallbackForm?.kind === \"error\") {\n throw new Error(\n `[${varName}:?] ${fallbackForm.value || \"variable is unset or empty\"}`,\n );\n }\n unresolved.add(varName);\n if (onMissing === \"empty\") return \"\";\n return \"${\" + varName + \"}\";\n }\n\n const v = lookup(varName, stack);\n // Defined but empty → POSIX :- and :? still treat empty as \"unset\".\n if (v === \"\" && fallbackForm?.kind === \"default\") {\n return expandString(fallbackForm.value, stack);\n }\n if (v === \"\" && fallbackForm?.kind === \"error\") {\n throw new Error(\n `[${varName}:?] ${fallbackForm.value || \"variable is unset or empty\"}`,\n );\n }\n return v;\n });\n }\n\n for (const key of Object.keys(values)) {\n if (resolved[key] === undefined && !inFlight.has(key)) {\n inFlight.add(key);\n try {\n resolved[key] = expandString(values[key]!, [key]);\n } finally {\n inFlight.delete(key);\n }\n }\n }\n\n if (onMissing === \"throw\" && (unresolved.size > 0 || cycles.length > 0)) {\n const parts: string[] = [];\n if (unresolved.size > 0) parts.push(`unresolved: ${[...unresolved].join(\", \")}`);\n if (cycles.length > 0) {\n parts.push(`cycles: ${cycles.map((c) => c.join(\" → \")).join(\"; \")}`);\n }\n throw new Error(`expansion failed — ${parts.join(\"; \")}`);\n }\n\n return { values: resolved, unresolved: [...unresolved], cycles };\n}\n\n/**\n * Expand variables in a parsed env file (string in, string out). The\n * file's own values take precedence; `opts.fallback` (default:\n * `process.env`) fills in the rest.\n */\nexport function expandEnvSrc(envSrc: string, opts: ExpandOptions = {}): ExpandResult {\n const lines = parseEnv(envSrc);\n const values: Record<string, string> = {};\n for (const line of lines) {\n if (line.type === \"kv\") values[line.key] = line.value;\n }\n const fallback = opts.fallback ?? process.env;\n const result = expandRecord(values, { ...opts, fallback });\n for (const line of lines) {\n if (line.type === \"kv\") line.value = result.values[line.key] ?? line.value;\n }\n return {\n values: result.values,\n envSrc: serializeEnv(lines),\n unresolved: result.unresolved,\n cycles: result.cycles,\n };\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- Tokenization ----------------------------------\n\ninterface DefaultRef {\n readonly kind: \"default\";\n readonly value: string;\n}\n\ninterface ErrorRef {\n readonly kind: \"error\";\n readonly value: string;\n}\n\ntype FallbackForm = DefaultRef | ErrorRef | undefined;\n\ntype Substituter = (name: string, fallback: FallbackForm) => string;\n\n/**\n * Walk the input character-by-character. Recognizes:\n * - `\\$` — escape, keep literal `$`\n * - `\\${` — escape, keep literal `${`\n * - `${NAME}`, `${NAME:-default}`, `${NAME:?msg}`\n * - `$NAME`\n */\nfunction substitute(input: string, substituter: Substituter): string {\n let out = \"\";\n let i = 0;\n while (i < input.length) {\n const c = input[i]!;\n if (c === \"\\\\\" && (input[i + 1] === \"$\" || input[i + 1] === \"\\\\\")) {\n out += input[i + 1];\n i += 2;\n continue;\n }\n if (c !== \"$\") {\n out += c;\n i += 1;\n continue;\n }\n // Possible $... reference\n const next = input[i + 1];\n if (next === \"{\") {\n const close = findMatchingBrace(input, i + 1);\n if (close === -1) {\n // No closing brace; treat as literal\n out += c;\n i += 1;\n continue;\n }\n const inner = input.slice(i + 2, close);\n const { name, fallback } = parseRef(inner);\n if (!isValidName(name)) {\n out += input.slice(i, close + 1);\n } else {\n out += substituter(name, fallback);\n }\n i = close + 1;\n continue;\n }\n if (next !== undefined && /[A-Za-z_]/.test(next)) {\n let j = i + 1;\n while (j < input.length && /[A-Za-z0-9_]/.test(input[j]!)) j++;\n const name = input.slice(i + 1, j);\n out += substituter(name, undefined);\n i = j;\n continue;\n }\n // Lone $\n out += c;\n i += 1;\n }\n return out;\n}\n\nfunction findMatchingBrace(s: string, openIdx: number): number {\n let depth = 0;\n for (let i = openIdx; i < s.length; i++) {\n if (s[i] === \"{\") depth++;\n else if (s[i] === \"}\") {\n depth--;\n if (depth === 0) return i;\n }\n }\n return -1;\n}\n\nfunction parseRef(inner: string): { name: string; fallback: FallbackForm } {\n // ${NAME:-default}\n let idx = inner.indexOf(\":-\");\n if (idx !== -1) {\n return {\n name: inner.slice(0, idx),\n fallback: { kind: \"default\", value: inner.slice(idx + 2) },\n };\n }\n // ${NAME:?msg}\n idx = inner.indexOf(\":?\");\n if (idx !== -1) {\n return {\n name: inner.slice(0, idx),\n fallback: { kind: \"error\", value: inner.slice(idx + 2) },\n };\n }\n return { name: inner, fallback: undefined };\n}\n\nfunction isValidName(name: string): boolean {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);\n}\n\n// #endregion -----------------------------------------------\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport { createRequire } from \"module\";\nimport { pathToFileURL } from \"url\";\n\n// #region -- Schema ----------------------------------------\n\n/**\n * Mapping shape: per-file allowlist of keys (or globs). Used to decide\n * which env file an inline key belongs in, and to constrain\n * encrypt/decrypt to the right scope.\n *\n * {\n * '.env.shared': ['DATABASE_URL', 'REDIS_URL'],\n * '.env.app': ['APP_*'],\n * }\n */\nexport type EnvFileMapping = Readonly<Record<string, readonly string[]>>;\n\nexport interface DotenvxConfig {\n /** Default env files to load when --env is not supplied. */\n readonly envFiles?: readonly string[];\n /**\n * Subdirectory of the workspace root where env files live (e.g. \"vault\").\n * When set, relative env file paths resolve to `<workspaceRoot>/<envPath>/<file>`\n * instead of `<workspaceRoot>/<file>`. Equivalent to passing `--vault`\n * (which is a shortcut for `envPath: \"vault\"`).\n */\n readonly envPath?: string;\n /** Cascade strategy ('prod', 'dev', etc.) — see loadEnv. */\n readonly cascade?: string;\n /** Path to the keys file. Defaults to .env.keys alongside each env file. */\n readonly envKeysFile?: string;\n /** Per-file allowlist of keys (literal names or globs). */\n readonly mapping?: EnvFileMapping;\n /** Override existing process.env when loading. */\n readonly override?: boolean;\n /** Suppress dotenv-style logging. */\n readonly quiet?: boolean;\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- Loader ----------------------------------------\n\nexport interface LoadConfigOptions {\n /** Explicit config path (highest precedence). */\n readonly configPath?: string;\n /** Where to start the search. Defaults to process.cwd(). */\n readonly cwd?: string;\n}\n\nexport interface LoadedConfig {\n /** Resolved config values. Always present (defaults merged in). */\n readonly config: DotenvxConfig;\n /** Absolute path the config was loaded from, or null if defaults. */\n readonly source: string | null;\n /** Source kind: how the config was discovered. */\n readonly origin: \"explicit\" | \"package.json\" | \"auto\" | \"defaults\";\n}\n\nconst AUTO_NAMES = [\n \"envx.config.ts\",\n \"envx.config.mts\",\n \"envx.config.js\",\n \"envx.config.mjs\",\n \"envx.config.cjs\",\n \"envx.config.json\",\n] as const;\n\n/**\n * Resolve the dotenvx config in this order:\n *\n * 1. `opts.configPath` (typically from `--config <path>`).\n * 2. `package.json` → `dotenvx.config` (string path) — walks upward\n * from `cwd` to find the nearest package.json.\n * 3. The first `dotenvx.config.{ts,js,json,…}` discovered at `cwd`.\n * 4. Built-in defaults (returns `source: null`, `origin: \"defaults\"`).\n */\nexport function loadDotenvxConfig(\n opts: LoadConfigOptions = {},\n): LoadedConfig {\n const cwd = opts.cwd ?? process.cwd();\n\n if (opts.configPath) {\n const resolved = path.resolve(cwd, opts.configPath);\n return {\n config: loadConfigFile(resolved),\n source: resolved,\n origin: \"explicit\",\n };\n }\n\n const fromPackageJson = findInPackageJson(cwd);\n if (fromPackageJson) {\n return {\n config: loadConfigFile(fromPackageJson.path),\n source: fromPackageJson.path,\n origin: \"package.json\",\n };\n }\n\n const fromAuto = findAutoConfig(cwd);\n if (fromAuto) {\n return {\n config: loadConfigFile(fromAuto),\n source: fromAuto,\n origin: \"auto\",\n };\n }\n\n return { config: {}, source: null, origin: \"defaults\" };\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- Discovery ------------------------------------\n\nfunction findInPackageJson(\n startDir: string,\n): { path: string; pkgPath: string } | null {\n let dir = startDir;\n const root = path.parse(dir).root;\n while (true) {\n const pkgPath = path.join(dir, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n try {\n const raw = JSON.parse(fs.readFileSync(pkgPath, \"utf8\")) as {\n envx?: { config?: string };\n // legacy spelling — read but don't write; we'll drop in a major bump.\n dotenvx?: { config?: string };\n };\n const ref = raw.envx?.config ?? raw.dotenvx?.config;\n if (typeof ref === \"string\" && ref.length > 0) {\n return { path: path.resolve(dir, ref), pkgPath };\n }\n } catch {\n // Ignore unreadable/malformed package.json — keep walking up.\n }\n }\n if (dir === root) return null;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\nfunction findAutoConfig(startDir: string): string | null {\n for (const name of AUTO_NAMES) {\n const p = path.join(startDir, name);\n if (fs.existsSync(p)) return p;\n }\n return null;\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- File loading ----------------------------------\n\nconst require_ = createRequire(import.meta.url);\n\nfunction loadConfigFile(filePath: string): DotenvxConfig {\n if (!fs.existsSync(filePath)) {\n throw new Error(`[CONFIG_NOT_FOUND] no config at ${filePath}`);\n }\n const ext = path.extname(filePath).toLowerCase();\n switch (ext) {\n case \".json\":\n return normalize(JSON.parse(fs.readFileSync(filePath, \"utf8\")));\n case \".cjs\":\n return normalize(require_(filePath));\n case \".js\":\n case \".mjs\":\n // .js files require sync loading. CJS works via require; ESM under\n // a \"type\": \"module\" parent doesn't. Try require first; if it\n // throws ERR_REQUIRE_ESM, fall back to dynamic import (caller must\n // be in an async context — we surface the limitation in the docs).\n return normalize(loadJsSync(filePath));\n case \".ts\":\n case \".mts\":\n // TypeScript configs require a runtime transpiler (tsx, ts-node).\n // We try to require via tsx if it's been installed, else throw a\n // clear error.\n return normalize(loadTsSync(filePath));\n default:\n throw new Error(`[CONFIG_BAD_EXT] unsupported config extension: ${ext}`);\n }\n}\n\nfunction loadJsSync(filePath: string): unknown {\n try {\n const mod = require_(filePath);\n return (mod as { default?: unknown }).default ?? mod;\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === \"ERR_REQUIRE_ESM\") {\n throw new Error(\n `[CONFIG_ESM_REQUIRES_ASYNC] ${filePath} is ESM. Either rename it to .cjs, ` +\n `add \"type\": \"commonjs\" to its package.json, or use loadDotenvxConfigAsync.`,\n );\n }\n throw e;\n }\n}\n\nfunction loadTsSync(filePath: string): unknown {\n // tsx registers a require hook when it's loaded. If the consumer has\n // it as a dev dep we'll find it; otherwise tell them how to enable it.\n try {\n require_(\"tsx/cjs\");\n } catch {\n throw new Error(\n `[CONFIG_TS_NEEDS_TSX] loading ${filePath} requires \"tsx\" to be installed. ` +\n `Add it as a devDependency, or use a .js / .json config instead.`,\n );\n }\n const mod = require_(filePath);\n return (mod as { default?: unknown }).default ?? mod;\n}\n\nfunction normalize(raw: unknown): DotenvxConfig {\n if (raw === null || typeof raw !== \"object\") {\n throw new Error(\"[CONFIG_BAD_SHAPE] config must export an object\");\n }\n // Trust but verify — coerce only the bits we touch.\n const r = raw as Record<string, unknown>;\n const out: { -readonly [K in keyof DotenvxConfig]: DotenvxConfig[K] } = {};\n if (Array.isArray(r[\"envFiles\"])) {\n out.envFiles = r[\"envFiles\"].filter((x): x is string => typeof x === \"string\");\n }\n if (typeof r[\"envPath\"] === \"string\") out.envPath = r[\"envPath\"];\n if (typeof r[\"cascade\"] === \"string\") out.cascade = r[\"cascade\"];\n if (typeof r[\"envKeysFile\"] === \"string\") out.envKeysFile = r[\"envKeysFile\"];\n if (typeof r[\"override\"] === \"boolean\") out.override = r[\"override\"];\n if (typeof r[\"quiet\"] === \"boolean\") out.quiet = r[\"quiet\"];\n if (r[\"mapping\"] && typeof r[\"mapping\"] === \"object\") {\n const mapping: Record<string, string[]> = {};\n for (const [file, keys] of Object.entries(r[\"mapping\"] as Record<string, unknown>)) {\n if (Array.isArray(keys)) {\n mapping[file] = keys.filter((x): x is string => typeof x === \"string\");\n }\n }\n out.mapping = mapping;\n }\n return out;\n}\n\n// #endregion -----------------------------------------------\n","// #region -- ANSI Color Codes -----------------------------\n\nconst RESET = '\\x1b[0m'\nconst RED = '\\x1b[31m'\nconst GREEN = '\\x1b[32m'\nconst YELLOW = '\\x1b[33m'\nconst CYAN = '\\x1b[36m'\nconst DIM = '\\x1b[2m'\n\n// #endregion -- ANSI Color Codes --------------------------\n\n// #region -- Logger Interface -----------------------------\n\nexport interface Logger {\n readonly success: (msg: string) => void\n readonly error: (msg: string) => void\n readonly warn: (msg: string) => void\n readonly info: (msg: string) => void\n readonly dim: (msg: string) => void\n}\n\n// #endregion -- Logger Interface --------------------------\n\n// #region -- Logger Implementation ------------------------\n\nexport const log: Logger = {\n success: (msg: string): void => {\n console.log(`${GREEN}${msg}${RESET}`)\n },\n error: (msg: string): void => {\n console.error(`${RED}${msg}${RESET}`)\n },\n warn: (msg: string): void => {\n console.log(`${YELLOW}${msg}${RESET}`)\n },\n info: (msg: string): void => {\n console.log(`${CYAN}${msg}${RESET}`)\n },\n dim: (msg: string): void => {\n console.log(`${DIM}${msg}${RESET}`)\n },\n}\n\n// #endregion -- Logger Implementation ---------------------\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as dotenv from \"@dotenvx/dotenvx\";\n\nimport { log } from \"@honeycluster/common\";\n\n// #region -- Environment Detection -------------------------\n\n/**\n * Detect the deployment environment from well-known platform variables.\n * Order of precedence: Vercel → Netlify → NODE_ENV → 'root'.\n */\nexport function detectEnvironment(): string {\n if (process.env[\"VERCEL\"]) {\n if (process.env[\"VERCEL_ENV\"] === \"production\") return \"prod\";\n return \"dev\";\n }\n\n if (process.env[\"NETLIFY\"]) {\n if (process.env[\"CONTEXT\"] === \"production\") return \"prod\";\n if (\n process.env[\"CONTEXT\"] === \"deploy-preview\" ||\n process.env[\"CONTEXT\"] === \"branch-deploy\"\n ) {\n return \"dev\";\n }\n return \"dev\";\n }\n\n const nodeEnv = process.env[\"NODE_ENV\"];\n if (nodeEnv) {\n switch (nodeEnv.toLowerCase()) {\n case \"production\":\n return \"prod\";\n case \"development\":\n return \"dev\";\n case \"local\":\n return \"local\";\n default:\n return \"root\";\n }\n }\n\n return \"root\";\n}\n\n// #endregion -- Environment Detection ----------------------\n\n// #region -- CLI Variable Parsing --------------------------\n\n/**\n * Parse a `KEY=value` string from `-v KEY=value` into a `[key, value]` tuple.\n * Calls `process.exit(1)` on malformed input.\n */\nexport function validateCmdVariable(param: string): [string, string] {\n const match = param.match(/^(\\w+)=([\\s\\S]+)$/m);\n if (!match) {\n log.error(\n `Invalid variable. Expected '-v variable=value', got: \\`-v ${param}\\`.`,\n );\n process.exit(1);\n }\n const [, key, val] = match;\n if (!key || !val) {\n log.error(\n `Invalid variable. Expected '-v variable=value', got: \\`-v ${param}\\`.`,\n );\n process.exit(1);\n }\n return [key, val];\n}\n\n// #endregion -- CLI Variable Parsing -----------------------\n\n// #region -- Workspace Resolution --------------------------\n\nconst WORKSPACE_INDICATORS = [\n \"pnpm-workspace.yaml\",\n \"lerna.json\",\n \"nx.json\",\n \"rush.json\",\n \"yarn.lock\",\n \"pnpm-lock.yaml\",\n] as const;\n\n/**\n * Walk up from `startDir` looking for a `package.json` that declares\n * `workspaces` (npm/yarn) or `pnpm.workspaces`. Falls back to other\n * monorepo indicators (pnpm-workspace.yaml, nx.json, …). Returns\n * `startDir` if nothing is found.\n */\nexport function findWorkspaceRoot(startDir: string = process.cwd()): string {\n const root = path.parse(startDir).root;\n\n let currentDir = startDir;\n while (currentDir !== root) {\n const packageJsonPath = path.join(currentDir, \"package.json\");\n try {\n const packageJsonContent = fs.readFileSync(packageJsonPath, \"utf8\");\n const packageJson = JSON.parse(packageJsonContent);\n if (packageJson.workspaces || packageJson.pnpm?.workspaces) {\n return currentDir;\n }\n } catch {\n // package.json absent or unreadable — keep walking\n }\n currentDir = path.dirname(currentDir);\n }\n\n currentDir = startDir;\n while (currentDir !== root) {\n for (const indicator of WORKSPACE_INDICATORS) {\n if (fs.existsSync(path.join(currentDir, indicator))) {\n return currentDir;\n }\n }\n currentDir = path.dirname(currentDir);\n }\n\n return startDir;\n}\n\n// #endregion -- Workspace Resolution -----------------------\n\n// #region -- Env File Discovery ----------------------------\n\n/**\n * List every `.env*` file in `dir`, sorted by name. Skips dotfile\n * subdirectories. Returns the basenames (not absolute paths) so callers\n * can hand them straight to `loadEnv` / `encryptFiles` / `decryptFiles`.\n *\n * Used by the CLI when `envPath`/`--vault` is set and `--env` is\n * omitted: the user's intent is \"all of the vault\", not just `.env`.\n */\nexport function listEnvFiles(dir: string): string[] {\n if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) return [];\n return fs\n .readdirSync(dir, { withFileTypes: true })\n .filter((d) => d.isFile())\n .map((d) => d.name)\n .filter((n) => n === \".env\" || n.startsWith(\".env.\"))\n .filter((n) => n !== \".env.keys\") // never operate on the keys file itself\n .sort();\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- Cascade Path Expansion ------------------------\n\n/**\n * Expand env file paths according to the cascade strategy. Order is\n * least- to most-specific so the caller (which loads them in order with\n * later entries overriding earlier ones) ends up with the most specific\n * values winning.\n */\nexport function expandCascadePaths(\n paths: string[],\n cascade: string | boolean,\n): string[] {\n return paths.reduce<string[]>(\n (accumulator, p) =>\n accumulator.concat(\n typeof cascade === \"string\"\n ? [`${p}.${cascade}.local`, `${p}.local`, `${p}.${cascade}`, p]\n : [`${p}.local`, p],\n ),\n [],\n );\n}\n\n// #endregion -- Cascade Path Expansion ---------------------\n\n// #region -- Env Loading -----------------------------------\n\nexport interface ResolveEnvOptions {\n readonly envFiles?: string[] | string;\n readonly cascade?: string | boolean;\n readonly autoDetect?: boolean;\n}\n\n/**\n * Resolve which `.env*` paths to load given the user's options. Handles\n * the auto-detect default (when only `.env` was passed), prefixing\n * bare names with `.env.`, and cascade expansion.\n */\nexport function resolveEnvPaths(opts: ResolveEnvOptions): string[] {\n const { cascade, autoDetect = true } = opts;\n const rawFiles = opts.envFiles ?? [\".env\"];\n const envFiles = Array.isArray(rawFiles) ? [...rawFiles] : [rawFiles];\n\n if (autoDetect && envFiles.length === 1 && envFiles[0] === \".env\") {\n const detected = detectEnvironment();\n if (detected !== \"root\") {\n envFiles[0] = `.env.${detected}`;\n log.dim(\n `Auto-detected environment: ${detected} ` +\n `(NODE_ENV=${process.env[\"NODE_ENV\"] ?? \"undefined\"}, ` +\n `VERCEL=${process.env[\"VERCEL\"] ?? \"undefined\"}, ` +\n `VERCEL_ENV=${process.env[\"VERCEL_ENV\"] ?? \"undefined\"}, ` +\n `NETLIFY=${process.env[\"NETLIFY\"] ?? \"undefined\"}, ` +\n `CONTEXT=${process.env[\"CONTEXT\"] ?? \"undefined\"})`,\n );\n }\n }\n\n let paths = envFiles.map((e) =>\n path.isAbsolute(e) || e.startsWith(\".env\") ? e : `.env.${e}`,\n );\n if (cascade) paths = expandCascadePaths(paths, cascade);\n return paths;\n}\n\nexport interface LoadEnvOptions {\n readonly envFiles?: string[] | string;\n readonly variables?: string[] | string;\n readonly cascade?: string | boolean;\n /**\n * `true` is shorthand for `envPath: \"vault\"`. A string sets the\n * subdirectory explicitly. Either way, relative env files resolve to\n * `<workspaceRoot>/<envPath>/<file>`.\n */\n readonly vault?: boolean;\n /** Subdirectory of the workspace root where env files live. */\n readonly envPath?: string;\n readonly override?: boolean;\n readonly quiet?: boolean;\n}\n\n/**\n * Load env files (resolving relative paths against both the workspace\n * root and CWD) and apply `KEY=value` overrides from `--variables`.\n * Mutates `process.env`.\n */\nexport function loadEnv(opts: LoadEnvOptions): { paths: string[] } {\n const {\n cascade,\n vault = false,\n envPath,\n override = false,\n quiet = true,\n variables,\n } = opts;\n\n if (cascade && override) {\n log.error(\"Invalid arguments. --cascade conflicts with --override.\");\n process.exit(1);\n }\n\n // envPath wins; --vault is a shortcut for \"vault\".\n const subdir = envPath ?? (vault ? \"vault\" : \"\");\n\n const paths = resolveEnvPaths({\n ...(opts.envFiles !== undefined ? { envFiles: opts.envFiles } : {}),\n ...(cascade !== undefined ? { cascade } : {}),\n });\n const workspaceRoot = findWorkspaceRoot();\n\n paths.forEach((env) => {\n if (path.isAbsolute(env)) {\n log.dim(`Loading environment from: ${env}`);\n dotenv.config({ path: env, override, quiet });\n return;\n }\n\n const workspacePath = subdir\n ? path.resolve(workspaceRoot, subdir, env)\n : path.resolve(workspaceRoot, env);\n const workspaceKeysPath = path.resolve(workspaceRoot, \".env.keys\");\n const currentDirPath = subdir\n ? path.resolve(process.cwd(), subdir, env)\n : path.resolve(process.cwd(), env);\n const currentDirKeysPath = path.resolve(process.cwd(), \".env.keys\");\n\n const workspaceExists = fs.existsSync(workspacePath);\n const currentDirExists = fs.existsSync(currentDirPath);\n\n if (workspaceExists) {\n log.dim(`Loading environment from: ${workspacePath}`);\n dotenv.config({\n path: workspacePath,\n envKeysFile: workspaceKeysPath,\n override,\n quiet,\n });\n }\n\n if (currentDirExists) {\n log.dim(`Loading environment from: ${currentDirPath}`);\n dotenv.config({\n path: currentDirPath,\n envKeysFile: currentDirKeysPath,\n override,\n quiet,\n });\n }\n\n if (!workspaceExists && !currentDirExists) {\n log.dim(`Loading environment from: ${workspacePath}`);\n dotenv.config({\n path: workspacePath,\n envKeysFile: workspaceKeysPath,\n override,\n quiet,\n });\n }\n });\n\n if (variables !== undefined) {\n const list = Array.isArray(variables) ? variables : [variables];\n const parsed = Object.fromEntries(list.map(validateCmdVariable));\n Object.assign(process.env, parsed);\n }\n\n return { paths };\n}\n\n// #endregion -- Env Loading --------------------------------\n","// #region -- Public API ------------------------------------\n\nexport type {\n ProcessedEnv,\n ProcessingError,\n ErrorCode,\n RunOptions,\n RunResult,\n} from \"./types.js\";\n\n// Crypto primitives + format constants\nexport {\n ENCRYPTED_PREFIX,\n encryptValue,\n decryptValue,\n generatePrivateKey,\n isEncrypted,\n} from \"./crypto.js\";\n\n// Env-file parsing\nexport {\n parseEnv,\n serializeEnv,\n toRecord,\n type EnvLine,\n type KvLine,\n type RawLine,\n} from \"./parser.js\";\n\n// Key file management\nexport {\n ENVX_PRIVATE_KEY_PREFIX,\n LEGACY_PRIVATE_KEY_PREFIX,\n defaultKeysPath,\n defaultKeysPathFor,\n privateKeyCandidateNamesFor,\n privateKeyNameFor,\n readKeysFile,\n writeKeysFile,\n} from \"./keys.js\";\n\n// Glob filter helpers\nexport { isSelected, matchesAny } from \"./match.js\";\n\n// High-level operations\nexport { encryptFiles } from \"./encrypt.js\";\nexport { decryptFiles } from \"./decrypt.js\";\n\n// Variable expansion\nexport {\n expandRecord,\n expandEnvSrc,\n type ExpandOptions,\n type ExpandResult,\n} from \"./expand.js\";\n\n// Config loading\nexport {\n loadDotenvxConfig,\n type DotenvxConfig,\n type LoadConfigOptions,\n type LoadedConfig,\n} from \"./config.js\";\n\n// Env loading + resolution helpers (originally in core/src/lib)\nexport {\n detectEnvironment,\n validateCmdVariable,\n findWorkspaceRoot,\n expandCascadePaths,\n listEnvFiles,\n resolveEnvPaths,\n loadEnv,\n type ResolveEnvOptions,\n type LoadEnvOptions,\n} from \"./env.js\";\n\n// #endregion -----------------------------------------------\n\n// #region -- Persistence Helper ----------------------------\n\nimport * as fs from \"fs\";\n\nimport type { ProcessedEnv } from \"./types.js\";\n\n/**\n * Persist any changed processedEnvs to disk. Returns the absolute paths\n * that were actually written. Skips entries with errors and entries\n * marked unchanged.\n */\nexport function writeProcessed(\n processed: readonly ProcessedEnv[],\n): { written: string[] } {\n const written: string[] = [];\n for (const p of processed) {\n if (p.error || !p.changed) continue;\n fs.writeFileSync(p.filepath, p.envSrc);\n written.push(p.filepath);\n }\n return { written };\n}\n\n// #endregion -----------------------------------------------\n"],"mappings":"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"}
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { t as createCli } from "./chunks/commands-CcoGlJ3P.js";
|
|
2
3
|
import { hideBin } from "yargs/helpers";
|
|
3
|
-
|
|
4
|
+
//#region src/cli.ts
|
|
4
5
|
createCli(hideBin(process.argv)).parseSync();
|
|
6
|
+
//#endregion
|
|
7
|
+
|
|
5
8
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","
|
|
1
|
+
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["// The `#!/usr/bin/env node` shebang is added at bundle time by the vite\n// build (configs/vite.config.ts → output.banner) — keeping it out of source\n// avoids a vite/esbuild quirk that drops the rest of the file body when a\n// `.ts` file starts with a shebang.\nimport { hideBin } from \"yargs/helpers\";\n\nimport { createCli } from \"./commands/index.js\";\n\ncreateCli(hideBin(process.argv)).parseSync();\n"],"mappings":";;;;AAQA,UAAU,QAAQ,QAAQ,KAAK,CAAC,CAAC,WAAW"}
|
package/dist/commands/debug.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expand.d.ts","sourceRoot":"","sources":["../../src/commands/expand.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAa3C;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"expand.d.ts","sourceRoot":"","sources":["../../src/commands/expand.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAa3C;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,aA+E3B,CAAC"}
|
package/dist/commands/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAoBlC;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAoBlC;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAmJnD"}
|
package/dist/commands/index.js
CHANGED
|
@@ -1,159 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import { findWorkspaceRoot, listEnvFiles, loadDotenvxConfig, } from "@honeycluster/libs";
|
|
4
|
-
import { log } from "@honeycluster/common";
|
|
5
|
-
import { debugCommand } from "./debug.js";
|
|
6
|
-
import { decryptCommand } from "./decrypt.js";
|
|
7
|
-
import { encryptCommand } from "./encrypt.js";
|
|
8
|
-
import { expandCommand } from "./expand.js";
|
|
9
|
-
import { printCommand } from "./print.js";
|
|
10
|
-
import { runCommand } from "./run.js";
|
|
11
|
-
// #region -- CLI Factory -----------------------------------
|
|
12
|
-
/**
|
|
13
|
-
* Build the yargs CLI for `dotenvx-run`. Global options (env, variables,
|
|
14
|
-
* cascade, vault, override, quiet) are registered on the root so every
|
|
15
|
-
* subcommand inherits them.
|
|
16
|
-
*/
|
|
17
|
-
export function createCli(argvInput) {
|
|
18
|
-
return yargs(argvInput)
|
|
19
|
-
.scriptName("envx")
|
|
20
|
-
.usage("$0 <command> [options]")
|
|
21
|
-
.option("config", {
|
|
22
|
-
alias: "c",
|
|
23
|
-
type: "string",
|
|
24
|
-
describe: "Path to an envx config file (default: discovered from package.json `envx.config` or envx.config.{ts,js,json}).",
|
|
25
|
-
})
|
|
26
|
-
.option("env", {
|
|
27
|
-
alias: "e",
|
|
28
|
-
type: "array",
|
|
29
|
-
describe: "Env files to load. Default: [\".env\"] (or `envFiles` from config; or every .env* under --env-path when set). Auto-detects environment when omitted.",
|
|
30
|
-
})
|
|
31
|
-
.option("env-path", {
|
|
32
|
-
type: "string",
|
|
33
|
-
describe: "Subdirectory of the workspace root holding the env files (e.g. `vault`). When set and --env is omitted, every .env* file in that directory is included.",
|
|
34
|
-
})
|
|
35
|
-
.option("variables", {
|
|
36
|
-
alias: "v",
|
|
37
|
-
type: "array",
|
|
38
|
-
describe: "Inline variables in the form name=value (repeatable).",
|
|
39
|
-
default: [],
|
|
40
|
-
})
|
|
41
|
-
.option("cascade", {
|
|
42
|
-
type: "string",
|
|
43
|
-
describe: "Cascade load order: .env, .env.<cascade>, .env.local, .env.<cascade>.local",
|
|
44
|
-
})
|
|
45
|
-
.option("vault", {
|
|
46
|
-
alias: "va",
|
|
47
|
-
type: "boolean",
|
|
48
|
-
describe: "Shortcut for `--env-path vault`.",
|
|
49
|
-
})
|
|
50
|
-
.option("override", {
|
|
51
|
-
alias: "o",
|
|
52
|
-
type: "boolean",
|
|
53
|
-
describe: "Override existing process.env values. Conflicts with --cascade.",
|
|
54
|
-
})
|
|
55
|
-
.option("quiet", {
|
|
56
|
-
alias: "q",
|
|
57
|
-
type: "boolean",
|
|
58
|
-
describe: "Suppress dotenv's own output.",
|
|
59
|
-
})
|
|
60
|
-
.middleware((argv) => {
|
|
61
|
-
const configPath = argv["config"];
|
|
62
|
-
let loaded;
|
|
63
|
-
try {
|
|
64
|
-
loaded = loadDotenvxConfig({
|
|
65
|
-
...(configPath ? { configPath } : {}),
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
catch (e) {
|
|
69
|
-
log.error(`config error: ${e.message}`);
|
|
70
|
-
process.exit(1);
|
|
71
|
-
}
|
|
72
|
-
if (loaded.source) {
|
|
73
|
-
log.dim(`config: ${loaded.source} (${loaded.origin})`);
|
|
74
|
-
}
|
|
75
|
-
const cfg = loaded.config;
|
|
76
|
-
// Apply config defaults only where the CLI didn't supply a value.
|
|
77
|
-
if (argv["cascade"] === undefined && cfg.cascade !== undefined) {
|
|
78
|
-
argv["cascade"] = cfg.cascade;
|
|
79
|
-
}
|
|
80
|
-
if (argv["override"] === undefined) {
|
|
81
|
-
argv["override"] = cfg.override ?? false;
|
|
82
|
-
}
|
|
83
|
-
if (argv["quiet"] === undefined) {
|
|
84
|
-
argv["quiet"] = cfg.quiet ?? true;
|
|
85
|
-
}
|
|
86
|
-
if (argv["vault"] === undefined) {
|
|
87
|
-
argv["vault"] = false;
|
|
88
|
-
}
|
|
89
|
-
if (argv["env-keys-file"] === undefined && cfg.envKeysFile !== undefined) {
|
|
90
|
-
argv["env-keys-file"] = cfg.envKeysFile;
|
|
91
|
-
}
|
|
92
|
-
// env-path: CLI > config > --vault shortcut
|
|
93
|
-
if (argv["env-path"] === undefined) {
|
|
94
|
-
if (cfg.envPath !== undefined)
|
|
95
|
-
argv["env-path"] = cfg.envPath;
|
|
96
|
-
else if (argv["vault"])
|
|
97
|
-
argv["env-path"] = "vault";
|
|
98
|
-
}
|
|
99
|
-
// env files: CLI > config > "all .env* in env-path" > [".env"]
|
|
100
|
-
const userPassedEnv = Array.isArray(argv["env"]) && argv["env"].length > 0;
|
|
101
|
-
let files;
|
|
102
|
-
if (userPassedEnv) {
|
|
103
|
-
files = argv["env"];
|
|
104
|
-
}
|
|
105
|
-
else if (cfg.envFiles && cfg.envFiles.length > 0) {
|
|
106
|
-
files = [...cfg.envFiles];
|
|
107
|
-
}
|
|
108
|
-
else if (typeof argv["env-path"] === "string") {
|
|
109
|
-
// "all files in the env-path are included" — discover them.
|
|
110
|
-
const subdir = argv["env-path"];
|
|
111
|
-
const wsRoot = findWorkspaceRoot();
|
|
112
|
-
const dir = path.resolve(wsRoot, subdir);
|
|
113
|
-
const discovered = listEnvFiles(dir);
|
|
114
|
-
if (discovered.length > 0) {
|
|
115
|
-
files = discovered;
|
|
116
|
-
log.dim(`env-path ${subdir}: discovered ${String(discovered.length)} file(s) — ${discovered.join(", ")}`);
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
files = [".env"];
|
|
120
|
-
log.warn(`env-path ${subdir}: no .env* files found; falling back to [".env"]`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
files = [".env"];
|
|
125
|
-
}
|
|
126
|
-
// When env-path is set, resolve every relative file against that
|
|
127
|
-
// directory up-front. encrypt/decrypt/expand operate on the
|
|
128
|
-
// resulting paths verbatim — no per-command envPath plumbing.
|
|
129
|
-
if (typeof argv["env-path"] === "string") {
|
|
130
|
-
const wsRoot = findWorkspaceRoot();
|
|
131
|
-
const dir = path.resolve(wsRoot, argv["env-path"]);
|
|
132
|
-
files = files.map((f) => (path.isAbsolute(f) ? f : path.join(dir, f)));
|
|
133
|
-
}
|
|
134
|
-
argv["env"] = files;
|
|
135
|
-
})
|
|
136
|
-
.command(runCommand)
|
|
137
|
-
.command(printCommand)
|
|
138
|
-
.command(debugCommand)
|
|
139
|
-
.command(encryptCommand)
|
|
140
|
-
.command(decryptCommand)
|
|
141
|
-
.command(expandCommand)
|
|
142
|
-
.help("h")
|
|
143
|
-
.alias("h", "help")
|
|
144
|
-
.version()
|
|
145
|
-
.strictCommands()
|
|
146
|
-
.demandCommand(0)
|
|
147
|
-
.recommendCommands()
|
|
148
|
-
.epilog("Examples:\n" +
|
|
149
|
-
" envx -- node app.js # load .env (auto-detected) and run\n" +
|
|
150
|
-
" envx --env dev -- pnpm start # load .env.dev\n" +
|
|
151
|
-
" envx print DATABASE_URL # print one variable\n" +
|
|
152
|
-
" envx debug --cascade prod # show resolved paths\n" +
|
|
153
|
-
" envx encrypt -e .env.prod # encrypt values in .env.prod\n" +
|
|
154
|
-
" envx decrypt -e .env.prod -k FOO # decrypt only FOO\n" +
|
|
155
|
-
" envx expand -e vault/.env.prod # decrypt + expand to stdout\n" +
|
|
156
|
-
" envx -c ./my.config.json run -- node app.js");
|
|
157
|
-
}
|
|
158
|
-
// #endregion -----------------------------------------------
|
|
159
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import { t as createCli } from "../chunks/commands-CcoGlJ3P.js";
|
|
2
|
+
export { createCli };
|
package/dist/commands/print.d.ts
CHANGED
package/dist/commands/run.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,61 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { c as loadDotenvxConfig, i as loadEnv } from "./chunks/src-Bu_9Htex.js";
|
|
2
|
+
//#region src/index.ts
|
|
3
3
|
function envx(arg) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
...(arg.cascade !== undefined
|
|
32
|
-
? { cascade: arg.cascade }
|
|
33
|
-
: config.cascade !== undefined
|
|
34
|
-
? { cascade: config.cascade }
|
|
35
|
-
: {}),
|
|
36
|
-
...(arg.envPath !== undefined
|
|
37
|
-
? { envPath: arg.envPath }
|
|
38
|
-
: config.envPath !== undefined
|
|
39
|
-
? { envPath: config.envPath }
|
|
40
|
-
: {}),
|
|
41
|
-
...(arg.vault !== undefined ? { vault: arg.vault } : {}),
|
|
42
|
-
...(arg.variables !== undefined ? { variables: arg.variables } : {}),
|
|
43
|
-
...(arg.override !== undefined
|
|
44
|
-
? { override: arg.override }
|
|
45
|
-
: config.override !== undefined
|
|
46
|
-
? { override: config.override }
|
|
47
|
-
: {}),
|
|
48
|
-
...(arg.quiet !== undefined
|
|
49
|
-
? { quiet: arg.quiet }
|
|
50
|
-
: config.quiet !== undefined
|
|
51
|
-
? { quiet: config.quiet }
|
|
52
|
-
: {}),
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
loadEnv(opts);
|
|
56
|
-
return process.env;
|
|
4
|
+
const { config } = loadDotenvxConfig();
|
|
5
|
+
let opts;
|
|
6
|
+
if (arg === void 0) opts = {
|
|
7
|
+
envFiles: config.envFiles ? [...config.envFiles] : [".env"],
|
|
8
|
+
...config.cascade !== void 0 ? { cascade: config.cascade } : {},
|
|
9
|
+
...config.envPath !== void 0 ? { envPath: config.envPath } : {},
|
|
10
|
+
...config.override !== void 0 ? { override: config.override } : {},
|
|
11
|
+
...config.quiet !== void 0 ? { quiet: config.quiet } : {}
|
|
12
|
+
};
|
|
13
|
+
else if (typeof arg === "string") opts = {
|
|
14
|
+
envFiles: config.envFiles ? [...config.envFiles] : [".env"],
|
|
15
|
+
cascade: arg,
|
|
16
|
+
...config.envPath !== void 0 ? { envPath: config.envPath } : {},
|
|
17
|
+
...config.override !== void 0 ? { override: config.override } : {},
|
|
18
|
+
...config.quiet !== void 0 ? { quiet: config.quiet } : {}
|
|
19
|
+
};
|
|
20
|
+
else opts = {
|
|
21
|
+
envFiles: arg.envFiles ?? (config.envFiles ? [...config.envFiles] : [".env"]),
|
|
22
|
+
...arg.cascade !== void 0 ? { cascade: arg.cascade } : config.cascade !== void 0 ? { cascade: config.cascade } : {},
|
|
23
|
+
...arg.envPath !== void 0 ? { envPath: arg.envPath } : config.envPath !== void 0 ? { envPath: config.envPath } : {},
|
|
24
|
+
...arg.vault !== void 0 ? { vault: arg.vault } : {},
|
|
25
|
+
...arg.variables !== void 0 ? { variables: arg.variables } : {},
|
|
26
|
+
...arg.override !== void 0 ? { override: arg.override } : config.override !== void 0 ? { override: config.override } : {},
|
|
27
|
+
...arg.quiet !== void 0 ? { quiet: arg.quiet } : config.quiet !== void 0 ? { quiet: config.quiet } : {}
|
|
28
|
+
};
|
|
29
|
+
loadEnv(opts);
|
|
30
|
+
return process.env;
|
|
57
31
|
}
|
|
58
|
-
|
|
59
|
-
export { envx };
|
|
60
|
-
|
|
32
|
+
//#endregion
|
|
33
|
+
export { envx as default, envx };
|
|
34
|
+
|
|
61
35
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["// #region -- Programmatic Entry Point ----------------------\n\nimport {\n loadEnv,\n loadDotenvxConfig,\n type LoadEnvOptions,\n} from \"@honeycluster/libs\";\n\n/**\n * Load env files into `process.env` and return it.\n *\n * Modeled after the `dotenv` API but with explicit scoping. Three call\n * shapes:\n *\n * ```ts\n * import envx from \"@honeycluster/envx\";\n *\n * envx(); // load `.env` (auto-detect from NODE_ENV / VERCEL_ENV / NETLIFY)\n * envx(\"prod\"); // load `.env` with cascade=prod (.env, .env.prod, .env.local, .env.prod.local)\n * envx({ envFiles: [\"vault/.env.prod\"], envPath: \"vault\", quiet: false }); // full options\n * ```\n *\n * In all cases `process.env` is mutated and returned for ergonomic\n * destructuring. Config file discovery (`envx.config.{ts,js,json}` /\n * `package.json` `envx.config`) runs automatically; CLI-level options\n * still win when both are passed.\n */\nfunction envx(): NodeJS.ProcessEnv;\nfunction envx(scope: string): NodeJS.ProcessEnv;\nfunction envx(opts: LoadEnvOptions): NodeJS.ProcessEnv;\nfunction envx(arg?: string | LoadEnvOptions): NodeJS.ProcessEnv {\n // Resolve config-file defaults first; CLI/programmatic args override.\n const { config } = loadDotenvxConfig();\n\n let opts: LoadEnvOptions;\n if (arg === undefined) {\n opts = {\n envFiles: config.envFiles ? [...config.envFiles] : [\".env\"],\n ...(config.cascade !== undefined ? { cascade: config.cascade } : {}),\n ...(config.envPath !== undefined ? { envPath: config.envPath } : {}),\n ...(config.override !== undefined ? { override: config.override } : {}),\n ...(config.quiet !== undefined ? { quiet: config.quiet } : {}),\n };\n } else if (typeof arg === \"string\") {\n // String form is a cascade scope shortcut: envx(\"prod\") loads\n // .env, .env.prod, .env.local, .env.prod.local in that order.\n opts = {\n envFiles: config.envFiles ? [...config.envFiles] : [\".env\"],\n cascade: arg,\n ...(config.envPath !== undefined ? { envPath: config.envPath } : {}),\n ...(config.override !== undefined ? { override: config.override } : {}),\n ...(config.quiet !== undefined ? { quiet: config.quiet } : {}),\n };\n } else {\n // Object form: caller's options layered over config defaults.\n opts = {\n envFiles:\n arg.envFiles ?? (config.envFiles ? [...config.envFiles] : [\".env\"]),\n ...(arg.cascade !== undefined\n ? { cascade: arg.cascade }\n : config.cascade !== undefined\n ? { cascade: config.cascade }\n : {}),\n ...(arg.envPath !== undefined\n ? { envPath: arg.envPath }\n : config.envPath !== undefined\n ? { envPath: config.envPath }\n : {}),\n ...(arg.vault !== undefined ? { vault: arg.vault } : {}),\n ...(arg.variables !== undefined ? { variables: arg.variables } : {}),\n ...(arg.override !== undefined\n ? { override: arg.override }\n : config.override !== undefined\n ? { override: config.override }\n : {}),\n ...(arg.quiet !== undefined\n ? { quiet: arg.quiet }\n : config.quiet !== undefined\n ? { quiet: config.quiet }\n : {}),\n };\n }\n\n loadEnv(opts);\n return process.env;\n}\n\nexport default envx;\nexport { envx };\n\n// Re-export the types callers will need to type their own wrappers.\nexport type { LoadEnvOptions };\n\n// #endregion -----------------------------------------------\n"],"mappings":";;AA8BA,SAAS,KAAK,KAAkD;CAE9D,MAAM,EAAE,WAAW,mBAAmB;CAEtC,IAAI;CACJ,IAAI,QAAQ,KAAA,GACV,OAAO;EACL,UAAU,OAAO,WAAW,CAAC,GAAG,OAAO,SAAS,GAAG,CAAC,OAAO;EAC3D,GAAI,OAAO,YAAY,KAAA,IAAY,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;EACnE,GAAI,OAAO,YAAY,KAAA,IAAY,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;EACnE,GAAI,OAAO,aAAa,KAAA,IAAY,EAAE,UAAU,OAAO,UAAU,GAAG,EAAE;EACtE,GAAI,OAAO,UAAU,KAAA,IAAY,EAAE,OAAO,OAAO,OAAO,GAAG,EAAE;EAC9D;MACI,IAAI,OAAO,QAAQ,UAGxB,OAAO;EACL,UAAU,OAAO,WAAW,CAAC,GAAG,OAAO,SAAS,GAAG,CAAC,OAAO;EAC3D,SAAS;EACT,GAAI,OAAO,YAAY,KAAA,IAAY,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;EACnE,GAAI,OAAO,aAAa,KAAA,IAAY,EAAE,UAAU,OAAO,UAAU,GAAG,EAAE;EACtE,GAAI,OAAO,UAAU,KAAA,IAAY,EAAE,OAAO,OAAO,OAAO,GAAG,EAAE;EAC9D;MAGD,OAAO;EACL,UACE,IAAI,aAAa,OAAO,WAAW,CAAC,GAAG,OAAO,SAAS,GAAG,CAAC,OAAO;EACpE,GAAI,IAAI,YAAY,KAAA,IAChB,EAAE,SAAS,IAAI,SAAS,GACxB,OAAO,YAAY,KAAA,IACjB,EAAE,SAAS,OAAO,SAAS,GAC3B,EAAE;EACR,GAAI,IAAI,YAAY,KAAA,IAChB,EAAE,SAAS,IAAI,SAAS,GACxB,OAAO,YAAY,KAAA,IACjB,EAAE,SAAS,OAAO,SAAS,GAC3B,EAAE;EACR,GAAI,IAAI,UAAU,KAAA,IAAY,EAAE,OAAO,IAAI,OAAO,GAAG,EAAE;EACvD,GAAI,IAAI,cAAc,KAAA,IAAY,EAAE,WAAW,IAAI,WAAW,GAAG,EAAE;EACnE,GAAI,IAAI,aAAa,KAAA,IACjB,EAAE,UAAU,IAAI,UAAU,GAC1B,OAAO,aAAa,KAAA,IAClB,EAAE,UAAU,OAAO,UAAU,GAC7B,EAAE;EACR,GAAI,IAAI,UAAU,KAAA,IACd,EAAE,OAAO,IAAI,OAAO,GACpB,OAAO,UAAU,KAAA,IACf,EAAE,OAAO,OAAO,OAAO,GACvB,EAAE;EACT;CAGH,QAAQ,KAAK;CACb,OAAO,QAAQ"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@super-repo/envx",
|
|
3
3
|
"description": "A global executable to run applications with the ENV variables witin a monorepo loaded by dotenvx",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.3-b.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"envx": "./dist/cli.js",
|
|
@@ -36,14 +36,17 @@
|
|
|
36
36
|
],
|
|
37
37
|
"license": "MIT",
|
|
38
38
|
"rune": {
|
|
39
|
-
"
|
|
39
|
+
"extends": "../../../config/rune-envx.config.ts",
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": [
|
|
42
|
+
"vite build -c configs/vite.config.ts"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
40
45
|
},
|
|
41
46
|
"dependencies": {
|
|
42
47
|
"@dotenvx/dotenvx": "^1.49.1",
|
|
43
48
|
"yargs": "^17.7.0",
|
|
44
|
-
"zod": "^3.25.0"
|
|
45
|
-
"@super-repo/envx-common": "0.0.1",
|
|
46
|
-
"@super-repo/envx-libs": "0.0.1"
|
|
49
|
+
"zod": "^3.25.0"
|
|
47
50
|
},
|
|
48
51
|
"devDependencies": {
|
|
49
52
|
"@types/node": "^22.10.0",
|
|
@@ -51,7 +54,11 @@
|
|
|
51
54
|
"tsc-alias": "^1.8.16",
|
|
52
55
|
"tsx": "^4.21.0",
|
|
53
56
|
"typescript": "^6.0.3",
|
|
57
|
+
"vite": "^8.0.11",
|
|
58
|
+
"vite-plugin-dts": "^5.0.0",
|
|
54
59
|
"vitest": "^4.1.5",
|
|
55
|
-
"@super-repo/cli": "0.2.
|
|
60
|
+
"@super-repo/cli": "0.2.3-b.1",
|
|
61
|
+
"@super-repo/envx-libs": "0.0.1",
|
|
62
|
+
"@super-repo/envx-common": "0.0.1"
|
|
56
63
|
}
|
|
57
64
|
}
|