@super-repo/envx 0.4.0 → 0.4.1-b.2
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/README.md +2 -2
- package/dist/auto.js +1 -1
- package/dist/chunks/auto-preload-CrSuZDg1.js +75 -0
- package/dist/chunks/auto-preload-CrSuZDg1.js.map +1 -0
- package/dist/chunks/aws-DgcXfw-Y.js +54 -0
- package/dist/chunks/aws-DgcXfw-Y.js.map +1 -0
- package/dist/chunks/azure-Cmh5-dPn.js +62 -0
- package/dist/chunks/azure-Cmh5-dPn.js.map +1 -0
- package/dist/chunks/{commands-KUyDszno.js → commands-Br0Z7uUF.js} +2 -2
- package/dist/chunks/commands-Br0Z7uUF.js.map +1 -0
- package/dist/chunks/doppler-BkQsajIp.js +50 -0
- package/dist/chunks/doppler-BkQsajIp.js.map +1 -0
- package/dist/chunks/gcp-Dq7QncPS.js +53 -0
- package/dist/chunks/gcp-Dq7QncPS.js.map +1 -0
- package/dist/chunks/infisical-CO073rdx.js +57 -0
- package/dist/chunks/infisical-CO073rdx.js.map +1 -0
- package/dist/chunks/{src-Ln2uXfYC.js → libs-CqVa6LY9.js} +0 -0
- package/dist/chunks/libs-CqVa6LY9.js.map +1 -0
- package/dist/chunks/op-CG9UWJIj.js +76 -0
- package/dist/chunks/op-CG9UWJIj.js.map +1 -0
- package/dist/chunks/runtime-BIEf_Dgo.js +102 -0
- package/dist/chunks/runtime-BIEf_Dgo.js.map +1 -0
- package/dist/chunks/{src-BM4EdT3z.js → src-ke3h417V.js} +2 -2
- package/dist/chunks/src-ke3h417V.js.map +1 -0
- package/dist/chunks/types-COrFYR0z.js +62 -0
- package/dist/chunks/types-COrFYR0z.js.map +1 -0
- package/dist/chunks/vault-BWdO9DFO.js +54 -0
- package/dist/chunks/vault-BWdO9DFO.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/commands/index.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/libs/audit.d.ts +62 -0
- package/dist/libs/audit.d.ts.map +1 -0
- package/dist/libs/config.d.ts +185 -0
- package/dist/libs/config.d.ts.map +1 -0
- package/dist/libs/crypto.d.ts +34 -0
- package/dist/libs/crypto.d.ts.map +1 -0
- package/dist/libs/decrypt.d.ts +10 -0
- package/dist/libs/decrypt.d.ts.map +1 -0
- package/dist/libs/encrypt.d.ts +21 -0
- package/dist/libs/encrypt.d.ts.map +1 -0
- package/dist/libs/env.d.ts +178 -0
- package/dist/libs/env.d.ts.map +1 -0
- package/dist/libs/expand.d.ts +51 -0
- package/dist/libs/expand.d.ts.map +1 -0
- package/dist/libs/index.d.ts +22 -0
- package/dist/libs/index.d.ts.map +1 -0
- package/dist/libs/index.js +2 -0
- package/dist/libs/keys.d.ts +92 -0
- package/dist/libs/keys.d.ts.map +1 -0
- package/dist/libs/match.d.ts +7 -0
- package/dist/libs/match.d.ts.map +1 -0
- package/dist/libs/parser.d.ts +33 -0
- package/dist/libs/parser.d.ts.map +1 -0
- package/dist/libs/rotate.d.ts +24 -0
- package/dist/libs/rotate.d.ts.map +1 -0
- package/dist/libs/types.d.ts +42 -0
- package/dist/libs/types.d.ts.map +1 -0
- package/dist/plugins/auto-preload.d.ts +50 -0
- package/dist/plugins/auto-preload.d.ts.map +1 -0
- package/dist/plugins/auto-preload.js +2 -0
- package/dist/plugins/aws.d.ts +52 -0
- package/dist/plugins/aws.d.ts.map +1 -0
- package/dist/plugins/aws.js +2 -0
- package/dist/plugins/azure.d.ts +46 -0
- package/dist/plugins/azure.d.ts.map +1 -0
- package/dist/plugins/azure.js +2 -0
- package/dist/plugins/doppler.d.ts +36 -0
- package/dist/plugins/doppler.d.ts.map +1 -0
- package/dist/plugins/doppler.js +2 -0
- package/dist/plugins/gcp.d.ts +48 -0
- package/dist/plugins/gcp.d.ts.map +1 -0
- package/dist/plugins/gcp.js +2 -0
- package/dist/plugins/index.d.ts +11 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +11 -0
- package/dist/plugins/infisical.d.ts +51 -0
- package/dist/plugins/infisical.d.ts.map +1 -0
- package/dist/plugins/infisical.js +2 -0
- package/dist/plugins/op.d.ts +52 -0
- package/dist/plugins/op.d.ts.map +1 -0
- package/dist/plugins/op.js +2 -0
- package/dist/plugins/runtime.d.ts +95 -0
- package/dist/plugins/runtime.d.ts.map +1 -0
- package/dist/plugins/runtime.js +2 -0
- package/dist/plugins/types.d.ts +54 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/vault.d.ts +47 -0
- package/dist/plugins/vault.d.ts.map +1 -0
- package/dist/plugins/vault.js +2 -0
- package/docs/plugins/custom-providers.md +26 -0
- package/docs/plugins/library-api.md +52 -0
- package/docs/plugins/overview.md +96 -0
- package/docs/plugins/providers.md +149 -0
- package/docs/plugins/recipes.md +77 -0
- package/docs/plugins/runtime.md +88 -0
- package/docs/security-models.md +3 -3
- package/package.json +51 -11
- package/dist/bin/dotenvx.d.ts +0 -1
- package/dist/bin/dotenvx.d.ts.map +0 -1
- package/dist/bin/dotenvx.js +0 -2
- package/dist/chunks/commands-KUyDszno.js.map +0 -1
- package/dist/chunks/src-BM4EdT3z.js.map +0 -1
- package/dist/chunks/src-Ln2uXfYC.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands-Br0Z7uUF.js","names":[],"sources":["../../src/commands/audit.ts","../../src/commands/bake.ts","../../src/commands/debug.ts","../../src/commands/decrypt.ts","../../src/commands/diff.ts","../../src/commands/doctor.ts","../../src/commands/encrypt.ts","../../src/commands/expand.ts","../../src/commands/hook.ts","../../src/commands/info.ts","../../src/commands/print.ts","../../src/commands/rotate.ts","../../src/commands/run.ts","../../src/commands/template-ai.ts","../../src/commands/template.ts","../../src/commands/types.ts","../../src/commands/watch.ts","../../src/commands/index.ts"],"sourcesContent":["import { execFileSync } from \"child_process\";\nimport * as path from \"path\";\nimport type { CommandModule } from \"yargs\";\n\nimport { auditFiles, type AuditFinding } from \"../libs/index.js\";\nimport { log } from \"@super-repo/envx-common\";\n\n// #region -- audit command ---------------------------------\n\n/**\n * Walk the repo looking for plaintext secrets — committed AWS keys,\n * GitHub PATs, JWTs, Stripe live keys, OpenAI/Anthropic keys, PEM\n * private-key blocks, etc. Designed to run as a pre-commit / pre-push\n * gate so secrets never reach the remote.\n *\n * Findings are printed with the file path, line number, pattern label,\n * and a redacted snippet (the actual secret payload is not printed —\n * only the first/last 4 chars). Exit 1 when any finding is reported.\n */\nexport const auditCommand: CommandModule = {\n command: \"audit [paths..]\",\n describe:\n \"Scan one or more paths for plaintext secrets. Exit 1 on findings (suitable as a CI / pre-commit gate).\",\n builder: (yargs) =>\n yargs\n .positional(\"paths\", {\n type: \"string\",\n array: true,\n describe: \"Directories to scan. Default: current working directory.\",\n })\n .option(\"ignore\", {\n type: \"array\",\n string: true,\n default: [] as string[],\n describe:\n \"Additional directory or file names to skip (added to the built-in ignore list).\",\n })\n .option(\"max\", {\n type: \"number\",\n default: 50,\n describe: \"Stop after reporting this many findings (0 = unlimited).\",\n })\n .option(\"respect-gitignore\", {\n type: \"boolean\",\n default: true,\n describe:\n \"Skip files and directories matched by .gitignore (and .git/info/exclude). Pass --no-respect-gitignore to scan everything.\",\n })\n .option(\"staged\", {\n type: \"boolean\",\n default: false,\n describe:\n \"Scan only files staged for the next commit (added/copied/modified/renamed). Mutually exclusive with positional paths. Suitable as the body of a pre-commit hook.\",\n })\n .option(\"json\", {\n type: \"boolean\",\n default: false,\n describe: \"Emit findings as JSON for downstream tools.\",\n }),\n handler: (argv): void => {\n // yargs defaults `array` positionals to `[]` (not `undefined`), so an\n // empty array means \"no paths supplied\" — fall back to cwd.\n const rawPaths = argv[\"paths\"] as string[] | undefined;\n const staged = argv[\"staged\"] as boolean;\n const ignore = argv[\"ignore\"] as string[];\n const max = argv[\"max\"] as number;\n const respectGitignore = argv[\"respect-gitignore\"] as boolean;\n const asJson = argv[\"json\"] as boolean;\n\n let roots: string[];\n if (staged) {\n if (rawPaths && rawPaths.length > 0) {\n log.error(\n \"audit: --staged cannot be combined with positional paths (it scans the git-staged set)\",\n );\n process.exit(2);\n }\n const stagedFiles = listStagedFiles();\n if (stagedFiles === null) {\n log.error(\n \"audit: --staged requires a git repository (no .git directory found above cwd)\",\n );\n process.exit(2);\n }\n if (stagedFiles.length === 0) {\n if (asJson) {\n process.stdout.write(\n JSON.stringify({ filesScanned: 0, findings: [] }) + \"\\n\",\n );\n } else {\n log.info(\"audit: no staged files — nothing to scan\");\n }\n return;\n }\n roots = stagedFiles.map((p) => path.resolve(process.cwd(), p));\n } else {\n roots = (rawPaths && rawPaths.length > 0 ? rawPaths : [\".\"]).map(\n (p) => path.resolve(process.cwd(), p),\n );\n }\n\n const { findings, filesScanned } = auditFiles({\n roots,\n ignore,\n max,\n respectGitignore,\n });\n\n if (asJson) {\n process.stdout.write(\n JSON.stringify({ filesScanned, findings }, null, 2) + \"\\n\",\n );\n if (findings.length > 0) process.exit(1);\n return;\n }\n\n log.info(`audit: scanned ${filesScanned} file(s) across ${roots.length} root(s)`);\n if (findings.length === 0) {\n log.success(\"no plaintext secrets found\");\n return;\n }\n\n log.dim(\"─\".repeat(60));\n const grouped = groupByPattern(findings);\n for (const [patternId, items] of grouped) {\n console.log(\"\");\n log.warn(`${items[0]!.label} (${items.length} finding(s), id=${patternId})`);\n for (const f of items) {\n const rel = path.relative(process.cwd(), f.file);\n console.log(` ${rel}:${String(f.line)}`);\n console.log(` ${f.snippet.trim()}`);\n }\n }\n console.log(\"\");\n log.dim(\"─\".repeat(60));\n log.error(`audit: ${findings.length} finding(s) — review and remove`);\n log.dim(\n \"tip: move secrets into encrypted .env files (`envx encrypt`) and reference them via process.env\",\n );\n process.exit(1);\n },\n};\n\n// #endregion -----------------------------------------------\n\n// #region -- helpers ---------------------------------------\n\nfunction groupByPattern(\n findings: readonly AuditFinding[],\n): Array<[string, AuditFinding[]]> {\n const map = new Map<string, AuditFinding[]>();\n for (const f of findings) {\n const arr = map.get(f.patternId);\n if (arr) arr.push(f);\n else map.set(f.patternId, [f]);\n }\n return [...map.entries()];\n}\n\n/**\n * Returns the list of files staged for the next commit (added, copied,\n * modified, or renamed — `--diff-filter=ACMR` excludes deletions). NUL-\n * delimited (`-z`) so paths with spaces or newlines round-trip safely.\n *\n * Returns `null` when not inside a git repo (so the caller can render a\n * nicer error than git's stderr). Empty array means \"in a repo, but\n * nothing staged\" — distinct from the failure case.\n *\n * Exported for unit testing.\n */\nexport function listStagedFiles(): string[] | null {\n try {\n const out = execFileSync(\n \"git\",\n [\"diff\", \"--cached\", \"--name-only\", \"--diff-filter=ACMR\", \"-z\"],\n { stdio: [\"ignore\", \"pipe\", \"pipe\"] },\n ).toString(\"utf8\");\n if (out.length === 0) return [];\n // Trailing NUL after the last entry is conventional; trim it before\n // splitting so we don't end up with an empty string at the tail.\n const trimmed = out.endsWith(\"\\0\") ? out.slice(0, -1) : out;\n return trimmed.split(\"\\0\").filter((p) => p.length > 0);\n } catch {\n return null;\n }\n}\n\n// #endregion -----------------------------------------------\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { CommandModule } from \"yargs\";\n\nimport {\n loadEnv,\n type DotenvxConfig,\n} from \"../libs/index.js\";\nimport { log } from \"@super-repo/envx-common\";\n\n// #region -- bake command ----------------------------------\n\n/**\n * Build-time resolver. Loads env files (decrypts, runs resolvers,\n * applies defaults, expands `${VAR}`, validates against the schema,\n * mirrors public vars), then writes the fully-resolved env to a\n * sealed file the bundler can pick up at compile time.\n *\n * Two output formats:\n * - `.env`-style (default) — `KEY=value\\n` per line, `KEY=` style\n * - JSON (`--json`) — `{ \"KEY\": \"value\", ... }` for tools\n * that prefer structured input\n *\n * The output file is plaintext — the entire point — so it must NEVER\n * be committed. The command writes a `# DO NOT COMMIT` banner at the\n * top and refuses to write under `.git/`.\n */\nexport const bakeCommand: CommandModule = {\n command: \"bake\",\n describe:\n \"Resolve every ref / encrypted value into a sealed file the bundler can pick up at build time. Output is plaintext — never commit it.\",\n builder: (yargs) =>\n yargs\n .option(\"out\", {\n // No `-o` alias — that's already taken by the global `--override`.\n type: \"string\",\n default: \".env.resolved\",\n describe:\n \"Output path (relative to cwd). Default: `.env.resolved`. Use `-` for stdout.\",\n })\n .option(\"json\", {\n type: \"boolean\",\n default: false,\n describe: \"Emit as JSON instead of the .env format.\",\n })\n .option(\"only\", {\n type: \"array\",\n string: true,\n default: [] as string[],\n describe:\n \"Restrict the bake to specific keys (repeatable). Default: every key envx loaded.\",\n })\n .option(\"public-only\", {\n type: \"boolean\",\n default: false,\n describe:\n \"Bake only the keys safe to ship in a client bundle: every PUBLIC_* source key plus its mirrored copies. Server-only secrets are excluded.\",\n }),\n handler: (argv): void => {\n const cfg = (argv[\"__envxConfig\"] as DotenvxConfig | undefined) ?? {};\n const out = argv[\"out\"] as string;\n const asJson = argv[\"json\"] as boolean;\n const only = new Set((argv[\"only\"] as string[]) ?? []);\n const publicOnly = argv[\"public-only\"] as boolean;\n\n // Snapshot pre-load env so we only emit envx's contributions.\n const before = new Set(Object.keys(process.env));\n\n loadEnv({\n envFiles: argv[\"env\"] as string[] | undefined,\n variables: argv[\"variables\"] as string[] | undefined,\n cascade: argv[\"cascade\"] as string | boolean | undefined,\n vault: argv[\"vault\"] as boolean | undefined,\n envPath: argv[\"env-path\"] as string | undefined,\n override: argv[\"override\"] as boolean | undefined,\n quiet: true,\n ...(cfg.autoDetect !== undefined ? { autoDetect: cfg.autoDetect } : {}),\n ...(cfg.nodeEnvMap !== undefined ? { nodeEnvMap: cfg.nodeEnvMap } : {}),\n ...(cfg.required !== undefined ? { required: cfg.required } : {}),\n ...(cfg.expand !== undefined ? { expand: cfg.expand } : {}),\n ...(cfg.defaults !== undefined ? { defaults: cfg.defaults } : {}),\n ...(cfg.workspaceRoot !== undefined ? { workspaceRoot: cfg.workspaceRoot } : {}),\n ...(cfg.schema !== undefined ? { schema: cfg.schema } : {}),\n ...(cfg.resolvers !== undefined ? { resolvers: cfg.resolvers } : {}),\n ...(cfg.publicPrefixes !== undefined\n ? { publicPrefixes: cfg.publicPrefixes }\n : {}),\n ...(cfg.publicSource !== undefined\n ? { publicSource: cfg.publicSource }\n : {}),\n });\n\n // Pick the keys envx contributed (never re-export the parent shell's PATH, HOME, etc.)\n let keys = Object.keys(process.env)\n .filter((k) => !before.has(k))\n .filter((k) => only.size === 0 || only.has(k))\n .sort();\n\n if (publicOnly) {\n const source = cfg.publicSource ?? \"PUBLIC_\";\n const targetPrefixes = cfg.publicPrefixes ?? [];\n keys = keys.filter(\n (k) =>\n k.startsWith(source) ||\n targetPrefixes.some((p) => k.startsWith(p)),\n );\n }\n\n if (keys.length === 0) {\n log.warn(\"bake: nothing to write — no keys matched\");\n process.exit(0);\n }\n\n const values: Record<string, string> = {};\n for (const k of keys) {\n const v = process.env[k];\n if (typeof v === \"string\") values[k] = v;\n }\n\n let rendered: string;\n if (asJson) {\n rendered = JSON.stringify(values, null, 2) + \"\\n\";\n } else {\n const lines: string[] = [];\n lines.push(\"# Generated by `envx bake` — DO NOT COMMIT.\");\n lines.push(\"# This file contains plaintext resolved secrets.\");\n lines.push(\"# Add it to .gitignore.\");\n lines.push(\"\");\n for (const k of keys) {\n lines.push(`${k}=${formatValue(values[k]!)}`);\n }\n rendered = lines.join(\"\\n\") + \"\\n\";\n }\n\n if (out === \"-\") {\n process.stdout.write(rendered);\n return;\n }\n\n const outAbs = path.resolve(process.cwd(), out);\n // Refuse to bake into .git/ — protects against typos that would\n // commit secrets via git's internal storage.\n if (\n outAbs.split(path.sep).includes(\".git\") ||\n outAbs.endsWith(\".git\") ||\n outAbs.includes(`${path.sep}.git${path.sep}`)\n ) {\n log.error(`bake: refusing to write under .git/ — change --out`);\n process.exit(1);\n }\n\n fs.writeFileSync(outAbs, rendered);\n log.success(\n `bake: wrote ${outAbs} (${String(keys.length)} key${keys.length === 1 ? \"\" : \"s\"}, ${asJson ? \"json\" : \"dotenv\"})`,\n );\n log.dim(\"hint: add the path to .gitignore — this file is plaintext\");\n },\n};\n\n// #endregion -----------------------------------------------\n\n// #region -- helpers ---------------------------------------\n\n/**\n * Conservative .env value rendering. Quote whenever the value contains\n * whitespace, `#`, `$`, quotes, or newlines so downstream parsers\n * (including envx itself) round-trip cleanly.\n */\nfunction formatValue(v: string): string {\n if (v === \"\") return '\"\"';\n const needsQuotes = /[\\s#$\"'`\\\\]/.test(v);\n if (!needsQuotes) return v;\n const escaped = v\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, \"\\\\n\")\n .replace(/\\r/g, \"\\\\r\")\n .replace(/\\t/g, \"\\\\t\");\n return `\"${escaped}\"`;\n}\n\n// #endregion -----------------------------------------------\n","import type { CommandModule } from \"yargs\";\n\nimport { resolveEnvPaths, validateCmdVariable } from \"../libs/index.js\";\nimport { log } from \"@super-repo/envx-common\";\n\n// #region -- debug command ---------------------------------\n\nexport const debugCommand: CommandModule = {\n command: \"debug\",\n describe:\n \"Show which env files would be loaded and which variables would be applied, without loading them.\",\n handler: (argv) => {\n const paths = resolveEnvPaths({\n envFiles: argv[\"env\"] as string[] | undefined,\n cascade: argv[\"cascade\"] as string | undefined,\n });\n\n const rawVars = argv[\"variables\"] as string[] | undefined;\n const variables = rawVars\n ? Object.fromEntries(rawVars.map(validateCmdVariable))\n : {};\n\n log.info(`Paths: ${JSON.stringify(paths)}`);\n log.info(`Variables: ${JSON.stringify(variables)}`);\n },\n};\n\n// #endregion -----------------------------------------------\n","import type { CommandModule } from \"yargs\";\n\nimport { decryptFiles, writeProcessed } from \"../libs/index.js\";\n\nimport { log } from \"@super-repo/envx-common\";\n\n// #region -- decrypt command -------------------------------\n\n/** Mirror of `dotenvx decrypt` from upstream — see also encrypt.ts. */\nexport const decryptCommand: CommandModule = {\n command: \"decrypt\",\n describe:\n \"Decrypt the values in one or more .env files in place using the matching private key in .env.keys.\",\n builder: (yargs) =>\n yargs\n .option(\"env-keys-file\", {\n alias: \"fk\",\n type: \"string\",\n describe:\n \"Path to the .env.keys file (default: ./.env.keys at cwd, regardless of --dir / --env-path).\",\n })\n .option(\"key\", {\n alias: \"k\",\n type: \"array\",\n string: true,\n describe:\n \"Specific keys (or picomatch globs) to decrypt. Default: all keys.\",\n })\n .option(\"exclude-key\", {\n alias: \"ek\",\n type: \"array\",\n string: true,\n describe: \"Keys (or picomatch globs) to leave encrypted.\",\n })\n .option(\"stdout\", {\n type: \"boolean\",\n default: false,\n describe:\n \"Write the decrypted env contents to stdout instead of saving in place.\",\n })\n .help(\"h\")\n .alias(\"h\", \"help\"),\n handler: (argv) => {\n const envFiles = (argv[\"env\"] as string[] | undefined) ?? [\".env\"];\n const keys = argv[\"key\"] as string[] | undefined;\n const excludeKeys = argv[\"exclude-key\"] as string[] | undefined;\n const envKeysFile = argv[\"env-keys-file\"] as string | undefined;\n const stdout = (argv[\"stdout\"] as boolean | undefined) ?? false;\n\n const result = decryptFiles({\n envFiles,\n ...(keys ? { keys } : {}),\n ...(excludeKeys ? { excludeKeys } : {}),\n ...(envKeysFile ? { envKeysFile } : {}),\n });\n\n let hadError = false;\n\n for (const processed of result.processedEnvs) {\n if (processed.error) {\n hadError = true;\n log.error(`${processed.envFilepath}: ${processed.error.message}`);\n if (processed.error.help) log.dim(processed.error.help);\n continue;\n }\n if (stdout) {\n process.stdout.write(processed.envSrc);\n }\n }\n\n if (!stdout) {\n const { written } = writeProcessed(result.processedEnvs);\n for (const w of written) log.success(`decrypted ${w}`);\n if (\n written.length === 0 &&\n result.unchangedFilepaths.length > 0 &&\n !hadError\n ) {\n log.dim(`no changes (${result.unchangedFilepaths.join(\", \")})`);\n }\n }\n\n if (hadError) process.exitCode = 1;\n },\n};\n\n// #endregion -----------------------------------------------\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { CommandModule } from \"yargs\";\n\nimport {\n decryptValueAsymmetric,\n isEncrypted,\n parseEnv,\n readKeysFile,\n resolveCwdOrWorkspace,\n toRecord,\n type DotenvxConfig,\n} from \"../libs/index.js\";\nimport { log } from \"@super-repo/envx-common\";\n\n// #region -- diff command ----------------------------------\n\n/**\n * Compare two env files key-by-key. Reports:\n * - keys present only in A\n * - keys present only in B\n * - keys present in both with mismatched values\n *\n * Encrypted values are decrypted with .env.keys when available, so the\n * comparison reflects logical values (not ciphertext). When secrets\n * differ, only the fact that they differ is shown — values are masked.\n *\n * Exit code: 0 when files are equivalent, 1 otherwise. Useful as a CI\n * gate to block prod deploys when staging/prod env shapes diverge.\n */\nexport const diffCommand: CommandModule = {\n command: \"diff <a> <b>\",\n describe:\n \"Compare two env files; report keys-only-in-a, keys-only-in-b, and value mismatches. Exit 1 on differences.\",\n builder: (yargs) =>\n yargs\n .positional(\"a\", {\n type: \"string\",\n demandOption: true,\n describe: \"Path to the first env file.\",\n })\n .positional(\"b\", {\n type: \"string\",\n demandOption: true,\n describe: \"Path to the second env file.\",\n })\n .option(\"show-values\", {\n type: \"boolean\",\n default: false,\n describe:\n \"Show actual differing values (off by default — values are masked since they are usually secrets).\",\n })\n .option(\"ignore-keys\", {\n type: \"array\",\n default: [] as string[],\n describe: \"Keys to ignore (repeatable).\",\n }),\n handler: (argv): void => {\n const cfg = (argv[\"__envxConfig\"] as DotenvxConfig | undefined) ?? {};\n const aPath = argv[\"a\"] as string;\n const bPath = argv[\"b\"] as string;\n const showValues = argv[\"show-values\"] as boolean;\n const ignore = new Set(\n (argv[\"ignore-keys\"] as string[] | undefined) ?? [],\n );\n\n const aResolved = resolveOne(aPath);\n const bResolved = resolveOne(bPath);\n\n if (!fs.existsSync(aResolved)) {\n log.error(`file not found: ${aResolved}`);\n process.exit(1);\n }\n if (!fs.existsSync(bResolved)) {\n log.error(`file not found: ${bResolved}`);\n process.exit(1);\n }\n\n const keysFilePath =\n (cfg.envKeysFile && path.resolve(process.cwd(), cfg.envKeysFile)) ??\n resolveCwdOrWorkspace(\".env.keys\");\n const aMap = loadDecrypted(aResolved, keysFilePath);\n const bMap = loadDecrypted(bResolved, keysFilePath);\n\n const allKeys = new Set([...Object.keys(aMap), ...Object.keys(bMap)]);\n const onlyA: string[] = [];\n const onlyB: string[] = [];\n const mismatched: { key: string; a: string; b: string }[] = [];\n\n for (const k of [...allKeys].sort()) {\n if (ignore.has(k)) continue;\n const inA = k in aMap;\n const inB = k in bMap;\n if (inA && !inB) onlyA.push(k);\n else if (!inA && inB) onlyB.push(k);\n else if (aMap[k] !== bMap[k]) mismatched.push({ key: k, a: aMap[k]!, b: bMap[k]! });\n }\n\n log.info(`diff: ${path.relative(process.cwd(), aResolved)} ⇄ ${path.relative(process.cwd(), bResolved)}`);\n log.dim(\"─\".repeat(60));\n\n if (onlyA.length === 0 && onlyB.length === 0 && mismatched.length === 0) {\n log.success(\"identical (after decryption)\");\n process.exit(0);\n }\n\n if (onlyA.length > 0) {\n console.log(\"\");\n log.warn(`only in a (${onlyA.length}):`);\n for (const k of onlyA) console.log(` - ${k}`);\n }\n if (onlyB.length > 0) {\n console.log(\"\");\n log.warn(`only in b (${onlyB.length}):`);\n for (const k of onlyB) console.log(` + ${k}`);\n }\n if (mismatched.length > 0) {\n console.log(\"\");\n log.warn(`mismatched values (${mismatched.length}):`);\n for (const m of mismatched) {\n if (showValues) {\n console.log(` ~ ${m.key}`);\n console.log(` a = ${m.a}`);\n console.log(` b = ${m.b}`);\n } else {\n console.log(` ~ ${m.key} (values differ — pass --show-values to display)`);\n }\n }\n }\n console.log(\"\");\n log.dim(\"─\".repeat(60));\n log.error(\n `diff: ${onlyA.length} only-in-a, ${onlyB.length} only-in-b, ${mismatched.length} mismatched`,\n );\n process.exit(1);\n },\n};\n\n// #endregion -----------------------------------------------\n\n// #region -- helpers ---------------------------------------\n\nfunction resolveOne(p: string): string {\n if (path.isAbsolute(p)) return p;\n // Try cwd; fall back to workspace root via resolveCwdOrWorkspace.\n const direct = path.resolve(process.cwd(), p);\n if (fs.existsSync(direct)) return direct;\n return resolveCwdOrWorkspace(p);\n}\n\nfunction loadDecrypted(\n filePath: string,\n envKeysFile: string,\n): Record<string, string> {\n const lines = parseEnv(fs.readFileSync(filePath, \"utf8\"));\n const raw = toRecord(lines);\n // Decrypt encrypted values when we can. Failures fall through as-is so\n // diff output flags them as \"differs\" rather than crashing.\n const keys = readKeysFile(envKeysFile);\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(raw)) {\n if (!isEncrypted(v)) {\n out[k] = v;\n continue;\n }\n let decrypted: string | null = null;\n for (const privateKeyHex of keys.values()) {\n try {\n decrypted = decryptValueAsymmetric(v, privateKeyHex);\n break;\n } catch {\n // try next key\n }\n }\n out[k] = decrypted ?? v;\n }\n return out;\n}\n\n// #endregion -----------------------------------------------\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { CommandModule } from \"yargs\";\n\nimport {\n decryptFiles,\n defaultKeysPath,\n expandRecord,\n findWorkspaceRoot,\n isEncrypted,\n loadEnv,\n parseEnv,\n resolveCwdOrWorkspace,\n resolveEnvPaths,\n toRecord,\n type DotenvxConfig,\n} from \"../libs/index.js\";\nimport { log } from \"@super-repo/envx-common\";\n\n// #region -- doctor command --------------------------------\n\n/**\n * Run a battery of health checks against the resolved configuration:\n * 1. Workspace + config visibility\n * 2. Env files exist (at least one)\n * 3. Keys file present when any encrypted values exist\n * 4. Every encrypted value decrypts cleanly\n * 5. `required` keys are filled after a dry load\n * 6. Expansion has no cycles and no unresolved references\n *\n * Each check prints a green tick / red cross / yellow tilde. A non-zero\n * exit indicates at least one hard failure (cross). Warnings (tildes)\n * do not affect the exit code so this is safe to run in CI as a gate.\n */\nexport const doctorCommand: CommandModule = {\n command: \"doctor\",\n describe:\n \"Run health checks: workspace + config, keys file, decryptability, required keys, expand cycles. Exits non-zero on hard failures.\",\n builder: (yargs) =>\n yargs.option(\"ignore-required\", {\n type: \"boolean\",\n default: false,\n describe:\n \"Skip the `required` post-load check. Useful when running in environments where the secrets aren't expected to be present yet.\",\n }),\n handler: (argv): void => {\n const cfg = (argv[\"__envxConfig\"] as DotenvxConfig | undefined) ?? {};\n const cfgSource = argv[\"__envxConfigSource\"] as string | null | undefined;\n const ignoreRequired = argv[\"ignore-required\"] as boolean;\n\n const workspaceRoot = findWorkspaceRoot();\n\n log.info(\"envx doctor\");\n log.dim(\"─\".repeat(60));\n\n let failures = 0;\n let warnings = 0;\n\n // ── 1. Workspace + config ──────────────────────────────\n section(\"Workspace + config\");\n pass(`workspace root: ${workspaceRoot}`);\n if (cfgSource) {\n pass(`config: ${cfgSource}`);\n } else {\n warn(\"config: built-in defaults (no envx.config.* found)\");\n warnings += 1;\n }\n\n // ── 2. Env files exist ─────────────────────────────────\n section(\"Env files\");\n const paths = resolveEnvPaths({\n ...(argv[\"env\"] !== undefined ? { envFiles: argv[\"env\"] as string[] } : {}),\n ...(argv[\"cascade\"] !== undefined\n ? { cascade: argv[\"cascade\"] as string }\n : {}),\n ...(cfg.autoDetect !== undefined ? { autoDetect: cfg.autoDetect } : {}),\n ...(cfg.nodeEnvMap !== undefined ? { nodeEnvMap: cfg.nodeEnvMap } : {}),\n });\n const subdir =\n (argv[\"env-path\"] as string | undefined) ??\n ((argv[\"vault\"] as boolean | undefined) ? \"vault\" : \"\");\n const resolvedPaths = paths.map((p) =>\n path.isAbsolute(p)\n ? p\n : subdir\n ? resolveCwdOrWorkspace(path.join(subdir, p))\n : resolveCwdOrWorkspace(p),\n );\n const existing = resolvedPaths.filter((p) => fs.existsSync(p));\n if (existing.length === 0) {\n fail(`no env files found (looked at ${resolvedPaths.length} candidate(s))`);\n for (const p of resolvedPaths) log.dim(` ✗ ${p}`);\n failures += 1;\n } else {\n pass(`${existing.length} of ${resolvedPaths.length} candidate file(s) exist`);\n for (const p of existing) log.dim(` ✓ ${p}`);\n for (const p of resolvedPaths.filter((rp) => !fs.existsSync(rp))) {\n log.dim(` · ${p} (skipped — not present)`);\n }\n }\n\n // ── 3. Keys file ───────────────────────────────────────\n section(\"Keys file\");\n const keysPath = (cfg.envKeysFile && path.resolve(process.cwd(), cfg.envKeysFile)) ?? defaultKeysPath();\n const hasEncrypted = existing.some((p) => fileHasEncryptedValues(p));\n if (!hasEncrypted) {\n pass(\"no encrypted values present — keys file not required\");\n log.dim(` (would look at ${keysPath})`);\n } else if (fs.existsSync(keysPath)) {\n pass(`keys file present: ${keysPath}`);\n } else {\n fail(`keys file missing: ${keysPath}`);\n log.dim(\" hint: run `envx encrypt` from a machine that has the private key, or restore .env.keys from your secret store\");\n failures += 1;\n }\n\n // ── 4. Decryptability ──────────────────────────────────\n section(\"Decryptability\");\n const filesWithSecrets = existing.filter((p) => fileHasEncryptedValues(p));\n if (filesWithSecrets.length === 0) {\n pass(\"no encrypted values to verify\");\n } else {\n try {\n const result = decryptFiles({\n envFiles: filesWithSecrets,\n envKeysFile: keysPath,\n });\n const failed = result.processedEnvs.filter((p) => p.error);\n if (failed.length === 0) {\n pass(`${filesWithSecrets.length} file(s) decrypt cleanly`);\n } else {\n for (const f of failed) {\n fail(`${f.envFilepath}: ${f.error?.code ?? \"unknown\"} — ${f.error?.message ?? \"\"}`);\n failures += 1;\n }\n }\n } catch (e) {\n fail(`decrypt error: ${(e as Error).message}`);\n failures += 1;\n }\n }\n\n // ── 5. Required keys (dry load) ────────────────────────\n section(\"Required keys\");\n const required = cfg.required ?? [];\n if (ignoreRequired) {\n warn(\"skipped (--ignore-required)\");\n warnings += 1;\n } else if (required.length === 0) {\n pass(\"no `required` keys configured\");\n } else {\n // Dry load: snapshot process.env, run loadEnv (which mutates\n // process.env), then restore. We bypass the `required` exit by\n // checking ourselves rather than letting loadEnv terminate.\n const snapshot = { ...process.env };\n try {\n loadEnv({\n envFiles: argv[\"env\"] as string[] | undefined,\n variables: argv[\"variables\"] as string[] | undefined,\n cascade: argv[\"cascade\"] as string | boolean | undefined,\n vault: argv[\"vault\"] as boolean | undefined,\n envPath: argv[\"env-path\"] as string | undefined,\n override: argv[\"override\"] as boolean | undefined,\n quiet: true,\n ...(cfg.autoDetect !== undefined ? { autoDetect: cfg.autoDetect } : {}),\n ...(cfg.nodeEnvMap !== undefined ? { nodeEnvMap: cfg.nodeEnvMap } : {}),\n ...(cfg.expand !== undefined ? { expand: cfg.expand } : {}),\n ...(cfg.defaults !== undefined ? { defaults: cfg.defaults } : {}),\n ...(cfg.workspaceRoot !== undefined ? { workspaceRoot: cfg.workspaceRoot } : {}),\n // Intentionally omit `required` — we'll inspect the result.\n });\n const missing = required.filter(\n (k) => process.env[k] === undefined || process.env[k] === \"\",\n );\n if (missing.length === 0) {\n pass(`${required.length} key(s) present after load`);\n } else {\n for (const m of missing) fail(`missing: ${m}`);\n failures += missing.length;\n }\n } finally {\n // Restore — doctor is read-only; never leaves process.env mutated.\n for (const k of Object.keys(process.env)) {\n if (!(k in snapshot)) delete process.env[k];\n }\n Object.assign(process.env, snapshot);\n }\n }\n\n // ── 6. Expansion sanity ────────────────────────────────\n section(\"Expansion sanity\");\n const merged: Record<string, string> = {};\n for (const f of existing) {\n const lines = parseEnv(fs.readFileSync(f, \"utf8\"));\n Object.assign(merged, toRecord(lines));\n }\n const { unresolved, cycles } = expandRecord(merged, { onMissing: \"leave\" });\n if (cycles.length === 0 && unresolved.length === 0) {\n pass(\"no cycles, no unresolved ${VAR} references\");\n } else {\n if (cycles.length > 0) {\n for (const c of cycles) fail(`cycle: ${c.join(\" → \")}`);\n failures += cycles.length;\n }\n if (unresolved.length > 0) {\n warn(`unresolved references: ${unresolved.join(\", \")}`);\n warnings += 1;\n }\n }\n\n // ── summary ────────────────────────────────────────────\n log.dim(\"─\".repeat(60));\n if (failures === 0 && warnings === 0) {\n log.success(`doctor: all checks passed`);\n process.exit(0);\n }\n if (failures === 0) {\n log.warn(`doctor: ${warnings} warning(s), 0 failure(s)`);\n process.exit(0);\n }\n log.error(`doctor: ${failures} failure(s), ${warnings} warning(s)`);\n process.exit(1);\n },\n};\n\n// #endregion -----------------------------------------------\n\n// #region -- helpers ---------------------------------------\n\nfunction section(title: string): void {\n console.log(\"\");\n log.info(title);\n}\n\nfunction pass(msg: string): void {\n log.success(` ✓ ${msg}`);\n}\n\nfunction fail(msg: string): void {\n log.error(` ✗ ${msg}`);\n}\n\nfunction warn(msg: string): void {\n log.warn(` ~ ${msg}`);\n}\n\nfunction fileHasEncryptedValues(filePath: string): boolean {\n try {\n const lines = parseEnv(fs.readFileSync(filePath, \"utf8\"));\n return lines.some((l) => l.type === \"kv\" && isEncrypted(l.value));\n } catch {\n return false;\n }\n}\n\n// #endregion -----------------------------------------------\n","import type { CommandModule } from \"yargs\";\n\nimport { encryptFiles, writeProcessed } from \"../libs/index.js\";\n\nimport { log } from \"@super-repo/envx-common\";\n\n// #region -- encrypt command -------------------------------\n\n/**\n * Mirrors the upstream `dotenvx encrypt` flags so existing muscle\n * memory carries over. The `--env` global doubles as the file list\n * (the upstream calls it `--env-file`); this CLI keeps a single\n * canonical name across subcommands.\n */\nexport const encryptCommand: CommandModule = {\n command: \"encrypt\",\n describe:\n \"Encrypt the values in one or more .env files. Generates a private key in .env.keys on first run.\",\n builder: (yargs) =>\n yargs\n .option(\"env-keys-file\", {\n alias: \"fk\",\n type: \"string\",\n describe:\n \"Path to the .env.keys file (default: ./.env.keys at cwd, regardless of --dir / --env-path).\",\n })\n .option(\"key\", {\n alias: \"k\",\n type: \"array\",\n string: true,\n describe:\n \"Specific keys (or picomatch globs) to encrypt. Default: all keys.\",\n })\n .option(\"pattern\", {\n alias: \"p\",\n type: \"array\",\n string: true,\n describe:\n \"Glob pattern(s) selecting which keys to encrypt. Comma-separated values supported (e.g. `--pattern '*_SECRET,*_TOKEN'`). Repeatable. Equivalent to --key but accepts CSV.\",\n })\n .option(\"secrets\", {\n type: \"boolean\",\n default: false,\n describe:\n \"Shorthand for the conventional secret-key globs: *_SECRET, *_TOKEN, *_KEY, *_PASSWORD, PASSWORD*, API_*. Mutually exclusive with --key/--pattern.\",\n })\n .option(\"exclude-key\", {\n alias: \"ek\",\n type: \"array\",\n string: true,\n describe: \"Keys (or picomatch globs) to leave plaintext.\",\n })\n .option(\"stdout\", {\n type: \"boolean\",\n default: false,\n describe:\n \"Write the encrypted env contents to stdout instead of saving in place.\",\n })\n .help(\"h\")\n .alias(\"h\", \"help\"),\n handler: (argv) => {\n const envFiles = (argv[\"env\"] as string[] | undefined) ?? [\".env\"];\n const keys = argv[\"key\"] as string[] | undefined;\n const patterns = argv[\"pattern\"] as string[] | undefined;\n const useSecrets = (argv[\"secrets\"] as boolean | undefined) ?? false;\n const excludeKeys = argv[\"exclude-key\"] as string[] | undefined;\n const envKeysFile = argv[\"env-keys-file\"] as string | undefined;\n const stdout = (argv[\"stdout\"] as boolean | undefined) ?? false;\n\n // Resolve the include-globs from any of: --key, --pattern (CSV), --secrets.\n // Comma-splitting is done once here so libs only ever sees a flat array.\n const SECRET_PRESETS = [\n \"*_SECRET\",\n \"*_TOKEN\",\n \"*_KEY\",\n \"*_PASSWORD\",\n \"PASSWORD*\",\n \"API_*\",\n ];\n const fromPatterns =\n patterns?.flatMap((p) => p.split(\",\").map((s) => s.trim()).filter(Boolean)) ??\n [];\n const include = [\n ...(keys ?? []),\n ...fromPatterns,\n ...(useSecrets ? SECRET_PRESETS : []),\n ];\n if ((keys || patterns) && useSecrets) {\n log.warn(\n \"encrypt: --secrets combined with --key/--pattern; the union of all globs is encrypted\",\n );\n }\n\n const result = encryptFiles({\n envFiles,\n ...(include.length > 0 ? { keys: include } : {}),\n ...(excludeKeys ? { excludeKeys } : {}),\n ...(envKeysFile ? { envKeysFile } : {}),\n });\n\n let hadError = false;\n\n for (const processed of result.processedEnvs) {\n if (processed.error) {\n hadError = true;\n log.error(`${processed.envFilepath}: ${processed.error.message}`);\n if (processed.error.help) log.dim(processed.error.help);\n continue;\n }\n\n if (stdout) {\n process.stdout.write(processed.envSrc);\n continue;\n }\n\n if (processed.privateKeyAdded) {\n log.success(\n `key added to .env.keys (${processed.privateKeyName ?? \"<unknown>\"})`,\n );\n }\n }\n\n if (!stdout) {\n const { written } = writeProcessed(result.processedEnvs);\n for (const w of written) log.success(`encrypted ${w}`);\n if (\n written.length === 0 &&\n result.unchangedFilepaths.length > 0 &&\n !hadError\n ) {\n log.dim(`no changes (${result.unchangedFilepaths.join(\", \")})`);\n }\n }\n\n if (hadError) process.exitCode = 1;\n },\n};\n\n// #endregion -----------------------------------------------\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { CommandModule } from \"yargs\";\n\nimport {\n decryptFiles,\n expandEnvSrc,\n isEncrypted,\n parseEnv,\n} from \"../libs/index.js\";\n\nimport { log } from \"@super-repo/envx-common\";\n\n// #region -- expand command --------------------------------\n\n/**\n * Decrypts (when needed) and expands variable references in an env\n * file. Mirrors the workflow `decrypt-vault` action — but cycle-safe,\n * supports `${VAR:-default}` / `${VAR:?msg}`, and never silently\n * truncates after N passes.\n */\nexport const expandCommand: CommandModule = {\n command: \"expand\",\n describe:\n \"Decrypt (if needed) and expand ${VAR}/$VAR references in an env file. Outputs to stdout by default.\",\n builder: (yargs) =>\n yargs\n .option(\"output\", {\n type: \"string\",\n describe: \"Write the expanded result to this file (default: stdout).\",\n })\n .option(\"env-keys-file\", {\n alias: \"fk\",\n type: \"string\",\n describe:\n \"Path to .env.keys (default: ./.env.keys at cwd, regardless of --dir / --env-path).\",\n })\n .option(\"on-missing\", {\n type: \"string\",\n choices: [\"leave\", \"empty\", \"throw\"] as const,\n default: \"leave\" as const,\n describe:\n \"How to handle ${UNRESOLVED_VAR}: leave it literal, substitute empty, or fail.\",\n })\n .help(\"h\")\n .alias(\"h\", \"help\"),\n handler: (argv) => {\n const envFiles = (argv[\"env\"] as string[] | undefined) ?? [\".env\"];\n if (envFiles.length !== 1) {\n log.error(\n `expand operates on a single env file at a time; got ${String(envFiles.length)}.`,\n );\n process.exit(1);\n }\n const envFile = envFiles[0]!;\n const filepath = path.resolve(envFile);\n if (!fs.existsSync(filepath)) {\n log.error(`env file not found: ${envFile}`);\n process.exit(1);\n }\n\n let envSrc = fs.readFileSync(filepath, \"utf8\");\n const hasEncrypted = parseEnv(envSrc).some(\n (l) => l.type === \"kv\" && isEncrypted(l.value),\n );\n\n if (hasEncrypted) {\n const envKeysFile = argv[\"env-keys-file\"] as string | undefined;\n const dec = decryptFiles({\n envFiles: [envFile],\n ...(envKeysFile ? { envKeysFile } : {}),\n });\n const processed = dec.processedEnvs[0];\n if (processed?.error) {\n log.error(`${envFile}: ${processed.error.message}`);\n if (processed.error.help) log.dim(processed.error.help);\n process.exit(1);\n }\n envSrc = processed!.envSrc;\n }\n\n const onMissing = argv[\"on-missing\"] as \"leave\" | \"empty\" | \"throw\";\n const result = expandEnvSrc(envSrc, { onMissing });\n\n for (const v of result.unresolved) {\n log.warn(`unresolved variable: ${v}`);\n }\n for (const cycle of result.cycles) {\n log.warn(`cycle: ${cycle.join(\" → \")}`);\n }\n\n const output = argv[\"output\"] as string | undefined;\n if (output) {\n fs.writeFileSync(path.resolve(output), result.envSrc);\n log.success(`expanded ${envFile} → ${output}`);\n } else {\n process.stdout.write(result.envSrc);\n if (!result.envSrc.endsWith(\"\\n\")) process.stdout.write(\"\\n\");\n }\n },\n};\n\n// #endregion -----------------------------------------------\n","import type { CommandModule } from \"yargs\";\n\nimport { loadEnv, type DotenvxConfig } from \"../libs/index.js\";\n\n// #region -- hook command ----------------------------------\n\n/**\n * Print eval-able shell exports for every variable loaded from envx's\n * resolved env files. Use to inject the env into the parent shell:\n *\n * eval \"$(envx hook bash)\"\n *\n * Three flavors:\n * - bash / zsh → `export KEY='value'`\n * - fish → `set -x KEY 'value'`\n * - powershell → `$env:KEY = 'value'`\n *\n * Diff against the pre-load process.env so we only emit the keys that\n * envx actually loaded (rather than re-exporting every var that\n * happened to already be set).\n */\nexport const hookCommand: CommandModule = {\n command: \"hook <shell>\",\n describe:\n \"Print shell exports for the loaded env. `eval \\\"$(envx hook bash)\\\"` injects them into the parent shell.\",\n builder: (yargs) =>\n yargs\n .positional(\"shell\", {\n type: \"string\",\n choices: [\"bash\", \"zsh\", \"fish\", \"powershell\", \"pwsh\"],\n demandOption: true,\n describe: \"Target shell flavor.\",\n })\n .option(\"only\", {\n type: \"array\",\n default: [] as string[],\n describe:\n \"Restrict output to specific keys. By default every key envx loaded is exported.\",\n }),\n handler: (argv): void => {\n const cfg = (argv[\"__envxConfig\"] as DotenvxConfig | undefined) ?? {};\n const shell = argv[\"shell\"] as\n | \"bash\"\n | \"zsh\"\n | \"fish\"\n | \"powershell\"\n | \"pwsh\";\n const only = new Set((argv[\"only\"] as string[] | undefined) ?? []);\n\n // Snapshot the pre-load env so we know which keys came from envx.\n const before = new Set(Object.keys(process.env));\n\n loadEnv({\n envFiles: argv[\"env\"] as string[] | undefined,\n variables: argv[\"variables\"] as string[] | undefined,\n cascade: argv[\"cascade\"] as string | boolean | undefined,\n vault: argv[\"vault\"] as boolean | undefined,\n envPath: argv[\"env-path\"] as string | undefined,\n override: argv[\"override\"] as boolean | undefined,\n // Always quiet — output goes to stdout and must be eval-able.\n quiet: true,\n ...(cfg.autoDetect !== undefined ? { autoDetect: cfg.autoDetect } : {}),\n ...(cfg.nodeEnvMap !== undefined ? { nodeEnvMap: cfg.nodeEnvMap } : {}),\n ...(cfg.required !== undefined ? { required: cfg.required } : {}),\n ...(cfg.expand !== undefined ? { expand: cfg.expand } : {}),\n ...(cfg.defaults !== undefined ? { defaults: cfg.defaults } : {}),\n ...(cfg.workspaceRoot !== undefined ? { workspaceRoot: cfg.workspaceRoot } : {}),\n });\n\n const newKeys = Object.keys(process.env)\n .filter((k) => !before.has(k))\n .filter((k) => only.size === 0 || only.has(k))\n .sort();\n\n const lines: string[] = [];\n for (const k of newKeys) {\n const v = process.env[k];\n if (v === undefined) continue;\n lines.push(formatExport(shell, k, v));\n }\n if (lines.length > 0) {\n process.stdout.write(lines.join(\"\\n\") + \"\\n\");\n }\n },\n};\n\n// #endregion -----------------------------------------------\n\n// #region -- shell escaping --------------------------------\n\nfunction formatExport(\n shell: \"bash\" | \"zsh\" | \"fish\" | \"powershell\" | \"pwsh\",\n key: string,\n value: string,\n): string {\n switch (shell) {\n case \"bash\":\n case \"zsh\":\n return `export ${key}=${shellQuote(value)}`;\n case \"fish\":\n return `set -x ${key} ${shellQuote(value)}`;\n case \"powershell\":\n case \"pwsh\":\n return `$env:${key} = ${psQuote(value)}`;\n }\n}\n\n/**\n * POSIX-shell single-quote escaping. Single quotes have no escape inside\n * single-quoted strings, so the trick is `'` → `'\\''`.\n */\nfunction shellQuote(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n\n/** PowerShell single-quote escaping: `'` → `''`. */\nfunction psQuote(s: string): string {\n return `'${s.replace(/'/g, \"''\")}'`;\n}\n\n// #endregion -----------------------------------------------\n","import * as path from \"path\";\nimport type { CommandModule } from \"yargs\";\n\nimport {\n DEFAULT_NODE_ENV_MAP,\n detectEnvironment,\n findWorkspaceRoot,\n resolveCwdOrWorkspace,\n resolveEnvPaths,\n type DotenvxConfig,\n} from \"../libs/index.js\";\nimport { log } from \"@super-repo/envx-common\";\n\n// #region -- info command ----------------------------------\n\n/**\n * Print everything envx knows about the current invocation: which\n * config file it found, the resolved settings, which platform signals\n * are present, what auto-detection produced, the NODE_ENV → suffix\n * map (built-in + user overrides), and the env file paths it would\n * load. Read-only — does not mutate process.env or write any files.\n */\nexport const infoCommand: CommandModule = {\n command: \"info\",\n describe:\n \"Show resolved configuration, auto-detection details, NODE_ENV mappings, and which env files would be loaded.\",\n builder: (yargs) => yargs.help(\"h\").alias(\"h\", \"help\"),\n handler: (argv) => {\n const cfg = (argv[\"__envxConfig\"] as DotenvxConfig | undefined) ?? {};\n const cfgSource = argv[\"__envxConfigSource\"] as string | null | undefined;\n const cfgOrigin = argv[\"__envxConfigOrigin\"] as string | undefined;\n\n const workspaceRoot = findWorkspaceRoot();\n const cwd = process.cwd();\n\n // ── header ─────────────────────────────────────────────\n log.info(\"envx info\");\n log.dim(\"─\".repeat(60));\n\n // ── workspace ──────────────────────────────────────────\n log.info(\"Workspace\");\n line(\"cwd\", cwd);\n line(\"workspace root\", workspaceRoot === cwd ? `${workspaceRoot} (none detected — using cwd)` : workspaceRoot);\n blank();\n\n // ── config source ──────────────────────────────────────\n log.info(\"Config\");\n line(\"source\", cfgSource ?? \"(none — built-in defaults)\");\n line(\"origin\", cfgOrigin ?? \"defaults\");\n blank();\n\n // ── resolved settings ──────────────────────────────────\n log.info(\"Resolved settings\");\n line(\"envFiles\", argv[\"env\"] ?? cfg.envFiles ?? [\".env\"]);\n line(\"envPath\", argv[\"env-path\"] ?? cfg.envPath ?? \"(none)\");\n line(\"cascade\", formatCascade(argv[\"cascade\"] ?? cfg.cascade));\n line(\n \"envKeysFile\",\n formatPath(\n (argv[\"env-keys-file\"] as string | undefined) ?? cfg.envKeysFile,\n cwd,\n workspaceRoot,\n ),\n );\n line(\"override\", argv[\"override\"] ?? cfg.override ?? false);\n line(\"quiet\", argv[\"quiet\"] ?? cfg.quiet ?? true);\n line(\"autoDetect\", cfg.autoDetect ?? true);\n line(\"expand\", cfg.expand ?? false);\n line(\"required\", cfg.required && cfg.required.length > 0 ? cfg.required : \"(none)\");\n line(\n \"defaults\",\n cfg.defaults && Object.keys(cfg.defaults).length > 0 ? cfg.defaults : \"(none)\",\n );\n line(\n \"workspaceRoot (config)\",\n cfg.workspaceRoot ?? \"(auto-detect via findWorkspaceRoot)\",\n );\n line(\n \"schema\",\n cfg.schema ? \"(configured — runs safeParse() after load)\" : \"(none)\",\n );\n line(\n \"resolvers\",\n cfg.resolvers && Object.keys(cfg.resolvers).length > 0\n ? Object.keys(cfg.resolvers).join(\", \")\n : \"(none)\",\n );\n line(\n \"profiles\",\n cfg.profiles && Object.keys(cfg.profiles).length > 0\n ? Object.keys(cfg.profiles).join(\", \")\n : \"(none)\",\n );\n line(\"active profile\", (argv[\"profile\"] as string | undefined) ?? \"(none)\");\n blank();\n\n // ── platform signals ───────────────────────────────────\n log.info(\"Platform signals (process.env)\");\n line(\"VERCEL\", process.env[\"VERCEL\"] ?? \"(unset)\");\n line(\"VERCEL_ENV\", process.env[\"VERCEL_ENV\"] ?? \"(unset)\");\n line(\"NETLIFY\", process.env[\"NETLIFY\"] ?? \"(unset)\");\n line(\"CONTEXT\", process.env[\"CONTEXT\"] ?? \"(unset)\");\n line(\"NODE_ENV\", process.env[\"NODE_ENV\"] ?? \"(unset)\");\n blank();\n\n // ── auto-detection result ──────────────────────────────\n log.info(\"Auto-detection\");\n const autoDetect = cfg.autoDetect ?? true;\n if (!autoDetect) {\n line(\"status\", \"disabled (autoDetect: false)\");\n } else {\n const detected = detectEnvironment({\n ...(cfg.nodeEnvMap !== undefined ? { nodeEnvMap: cfg.nodeEnvMap } : {}),\n });\n const source = pickDetectionSource();\n line(\"source\", source);\n line(\"detected\", detected);\n line(\n \"→ env file\",\n detected === \"root\" ? \".env\" : `.env.${detected}`,\n );\n }\n blank();\n\n // ── NODE_ENV → suffix map ──────────────────────────────\n log.info(\"NODE_ENV → suffix mapping\");\n log.dim(\" (any NODE_ENV value not in this map passes through lowercased,\");\n log.dim(\" so e.g. NODE_ENV=qa loads .env.qa)\");\n const userMap = cfg.nodeEnvMap ?? {};\n const merged = { ...DEFAULT_NODE_ENV_MAP, ...userMap };\n const allKeys = Array.from(new Set([...Object.keys(merged)])).sort();\n for (const k of allKeys) {\n const v = merged[k] ?? \"\";\n const suffix = v === \"\" ? \"(no suffix → .env)\" : `.env.${v}`;\n const origin =\n userMap[k] === undefined\n ? \"default\"\n : DEFAULT_NODE_ENV_MAP[k] === undefined\n ? \"config\"\n : \"config (override)\";\n line(` ${k.padEnd(14)} → ${suffix}`, origin);\n }\n blank();\n\n // ── resolved file paths ────────────────────────────────\n log.info(\"Resolved env file paths (would be loaded in this order)\");\n const paths = resolveEnvPaths({\n ...(argv[\"env\"] !== undefined ? { envFiles: argv[\"env\"] as string[] } : {}),\n ...(argv[\"cascade\"] !== undefined\n ? { cascade: argv[\"cascade\"] as string }\n : {}),\n autoDetect,\n ...(cfg.nodeEnvMap !== undefined ? { nodeEnvMap: cfg.nodeEnvMap } : {}),\n });\n if (paths.length === 0) {\n line(\"(none)\", \"\");\n } else {\n const subdir =\n (argv[\"env-path\"] as string | undefined) ??\n ((argv[\"vault\"] as boolean | undefined) ? \"vault\" : \"\");\n for (const p of paths) {\n if (path.isAbsolute(p)) {\n log.dim(` ${p}`);\n continue;\n }\n const resolved = subdir\n ? resolveCwdOrWorkspace(path.join(subdir, p))\n : resolveCwdOrWorkspace(p);\n log.dim(` ${p} → ${resolved}`);\n }\n }\n },\n};\n\n// #endregion -----------------------------------------------\n\n// #region -- helpers ---------------------------------------\n\nfunction line(key: string, value: unknown, suffix?: string): void {\n const v =\n value === undefined || value === null\n ? \"(unset)\"\n : Array.isArray(value)\n ? value.length === 0\n ? \"[]\"\n : JSON.stringify(value)\n : typeof value === \"object\"\n ? JSON.stringify(value)\n : String(value);\n const tail = suffix ? ` ${dim(`(${suffix})`)}` : \"\";\n log.dim(` ${key.padEnd(14)} ${v}${tail}`);\n}\n\nfunction blank(): void {\n console.log(\"\");\n}\n\nfunction dim(s: string): string {\n return `\\x1b[2m${s}\\x1b[22m`;\n}\n\nfunction formatCascade(cascade: unknown): string {\n if (cascade === undefined || cascade === false) return \"(off)\";\n if (cascade === true) return \"true (uses auto-detected env name)\";\n return String(cascade);\n}\n\nfunction pickDetectionSource(): string {\n if (process.env[\"VERCEL\"]) return \"Vercel (VERCEL_ENV)\";\n if (process.env[\"NETLIFY\"]) return \"Netlify (CONTEXT)\";\n if (process.env[\"NODE_ENV\"]) return \"NODE_ENV\";\n return \"(no signals — fallback to .env)\";\n}\n\nfunction formatPath(\n raw: string | undefined,\n cwd: string,\n wsRoot: string,\n): string {\n if (!raw) {\n // Default keys-file lookup.\n const resolved = resolveCwdOrWorkspace(\".env.keys\", cwd);\n return `${resolved} (default: cwd-first, ws-root fallback)`;\n }\n if (path.isAbsolute(raw)) return `${raw} (absolute)`;\n const cwdResolved = path.resolve(cwd, raw);\n const wsResolved = path.resolve(wsRoot, raw);\n return `${raw} → ${cwdResolved} (or ${wsResolved} if not at cwd)`;\n}\n\n// #endregion -----------------------------------------------\n","import type { CommandModule } from \"yargs\";\n\nimport { loadEnv } from \"../libs/index.js\";\n\n// #region -- print command ---------------------------------\n\nexport const printCommand: CommandModule = {\n command: \"print <variable>\",\n describe: \"Load env files and print the value of a single variable.\",\n builder: (yargs) =>\n yargs.positional(\"variable\", {\n describe: \"Name of the variable to print\",\n type: \"string\",\n demandOption: true,\n }),\n handler: (argv) => {\n loadEnv({\n envFiles: argv[\"env\"] as string[] | undefined,\n variables: argv[\"variables\"] as string[] | undefined,\n cascade: argv[\"cascade\"] as string | undefined,\n vault: argv[\"vault\"] as boolean | undefined,\n envPath: argv[\"env-path\"] as string | undefined,\n override: argv[\"override\"] as boolean | undefined,\n quiet: argv[\"quiet\"] as boolean | undefined,\n });\n\n const name = argv[\"variable\"] as string;\n const value = process.env[name];\n process.stdout.write(value != null ? `${value}\\n` : \"\\n\");\n },\n};\n\n// #endregion -----------------------------------------------\n","import type { CommandModule } from \"yargs\";\n\nimport { rotateFiles, writeProcessed } from \"../libs/index.js\";\nimport { log } from \"@super-repo/envx-common\";\n\n// #region -- rotate command --------------------------------\n\n/**\n * Rotate the asymmetric keypair for one or more env files. Generates a\n * fresh secp256k1 keypair, decrypts existing values with the old\n * private key, re-encrypts with the new public key, and updates both\n * the `ENVX_PUBLIC_KEY*` header in the env file and the\n * `ENVX_PRIVATE_KEY*` entry in `.env.keys`.\n *\n * Files without a public-key header surface an error — run\n * `envx encrypt` against them first to set up the keypair.\n */\nexport const rotateCommand: CommandModule = {\n command: \"rotate\",\n describe: \"Rotate the asymmetric keypair for one or more env files.\",\n builder: (yargs) =>\n yargs\n .option(\"env-keys-file\", {\n alias: \"fk\",\n type: \"string\",\n describe:\n \"Path to the .env.keys file (default: ./.env.keys at cwd). Relative paths resolve against each env file's directory.\",\n })\n .option(\"key\", {\n alias: \"k\",\n type: \"array\",\n string: true,\n describe:\n \"Specific keys (or picomatch globs) to rotate. Default: all encrypted keys.\",\n })\n .option(\"exclude-key\", {\n alias: \"ek\",\n type: \"array\",\n string: true,\n describe: \"Keys (or picomatch globs) to leave with their existing ciphertext.\",\n })\n .help(\"h\")\n .alias(\"h\", \"help\"),\n handler: (argv) => {\n const envFiles = (argv[\"env\"] as string[] | undefined) ?? [\".env\"];\n const keys = argv[\"key\"] as string[] | undefined;\n const excludeKeys = argv[\"exclude-key\"] as string[] | undefined;\n const envKeysFile = argv[\"env-keys-file\"] as string | undefined;\n\n const result = rotateFiles({\n envFiles,\n ...(keys ? { keys } : {}),\n ...(excludeKeys ? { excludeKeys } : {}),\n ...(envKeysFile ? { envKeysFile } : {}),\n });\n\n let hadError = false;\n\n for (const processed of result.processedEnvs) {\n if (processed.error) {\n hadError = true;\n log.error(`${processed.envFilepath}: ${processed.error.message}`);\n if (processed.error.help) log.dim(processed.error.help);\n }\n }\n\n const { written } = writeProcessed(result.processedEnvs);\n for (const w of written) log.success(`rotated ${w}`);\n if (written.length === 0 && result.unchangedFilepaths.length > 0 && !hadError) {\n log.dim(`no changes (${result.unchangedFilepaths.join(\", \")})`);\n }\n\n if (hadError) process.exitCode = 1;\n },\n};\n\n// #endregion -----------------------------------------------\n","import { execSync } from \"child_process\";\nimport type { CommandModule } from \"yargs\";\n\nimport { loadEnv, type DotenvxConfig } from \"../libs/index.js\";\nimport { log } from \"@super-repo/envx-common\";\n\n// #region -- run command -----------------------------------\n\nexport const runCommand: CommandModule = {\n command: \"run [command..]\",\n aliases: [\"$0\"],\n describe:\n \"Load env files into process.env and execute a command. Default subcommand — `dotenvx-run [command]` is equivalent.\",\n builder: (yargs) =>\n yargs.positional(\"command\", {\n describe: \"Command to execute after loading env files\",\n type: \"string\",\n array: true,\n }),\n handler: (argv) => {\n const command = ((argv[\"command\"] as string[] | undefined) ?? []).join(\" \");\n const cfg = (argv[\"__envxConfig\"] as DotenvxConfig | undefined) ?? {};\n\n loadEnv({\n envFiles: argv[\"env\"] as string[] | undefined,\n variables: argv[\"variables\"] as string[] | undefined,\n // CLI passes a string name; config passes a boolean toggle.\n cascade: argv[\"cascade\"] as string | boolean | undefined,\n vault: argv[\"vault\"] as boolean | undefined,\n envPath: argv[\"env-path\"] as string | undefined,\n override: argv[\"override\"] as boolean | undefined,\n quiet: argv[\"quiet\"] as boolean | undefined,\n ...(cfg.autoDetect !== undefined ? { autoDetect: cfg.autoDetect } : {}),\n ...(cfg.nodeEnvMap !== undefined ? { nodeEnvMap: cfg.nodeEnvMap } : {}),\n ...(cfg.required !== undefined ? { required: cfg.required } : {}),\n ...(cfg.expand !== undefined ? { expand: cfg.expand } : {}),\n ...(cfg.defaults !== undefined ? { defaults: cfg.defaults } : {}),\n ...(cfg.workspaceRoot !== undefined ? { workspaceRoot: cfg.workspaceRoot } : {}),\n ...(cfg.schema !== undefined ? { schema: cfg.schema } : {}),\n ...(cfg.resolvers !== undefined ? { resolvers: cfg.resolvers } : {}),\n // CLI override: --public-prefix repeated takes precedence over config.\n ...(Array.isArray(argv[\"public-prefix\"]) && (argv[\"public-prefix\"] as string[]).length > 0\n ? { publicPrefixes: argv[\"public-prefix\"] as string[] }\n : cfg.publicPrefixes !== undefined\n ? { publicPrefixes: cfg.publicPrefixes }\n : {}),\n ...(cfg.publicSource !== undefined ? { publicSource: cfg.publicSource } : {}),\n });\n\n if (!command) return;\n\n log.info(`Running: ${command}`);\n try {\n execSync(command, { stdio: \"inherit\" });\n log.success(`Command completed: ${command}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n log.error(`Command failed: ${msg}`);\n process.exit(1);\n }\n },\n};\n\n// #endregion -----------------------------------------------\n","// #region -- AI client for template example generation ----\n\n// Minimal Anthropic + OpenAI client used by `envx template --ai` to\n// populate example values. Auth lookup mirrors `@super-repo/czar`'s\n// `lookupAnthropicAuth` exactly: configured api-key env → Claude Code\n// OAuth bearer envs (`CLAUDE_CODE_OAUTH_TOKEN`, `ANTHROPIC_AUTH_TOKEN`),\n// with `sk-ant-oat`-prefixed tokens routed via `Authorization: Bearer`\n// + the `oauth-2025-04-20` beta gate. Self-contained so envx core\n// doesn't take a runtime dep on the SDK or on czar.\n\nconst ANTHROPIC_DEFAULT_BASE = \"https://api.anthropic.com\";\n// OpenAI SDK convention: baseUrl already includes `/v1`, the chat\n// completions path is appended at request time. Self-hosted gateways\n// (Ollama at `:11434/v1`, LM Studio at `:1234/v1`) map cleanly.\nconst OPENAI_DEFAULT_BASE = \"https://api.openai.com/v1\";\n// Beta gate required by the Messages API when authenticating with a\n// subscription OAuth bearer token (Claude Pro / Max / Claude Code).\nconst ANTHROPIC_OAUTH_BETA = \"oauth-2025-04-20\";\n// Subscription / Claude-Code-style bearer tokens — read in this order.\n// The configured `apiKeyEnv` (default `ANTHROPIC_API_KEY`) wins over them.\nexport const ANTHROPIC_OAUTH_ENVS: ReadonlyArray<string> = [\n \"CLAUDE_CODE_OAUTH_TOKEN\",\n \"ANTHROPIC_AUTH_TOKEN\",\n];\nconst REQUEST_TIMEOUT_MS = 60_000;\n\nexport interface AiOptions {\n readonly provider?: \"anthropic\" | \"openai\";\n readonly model?: string;\n /**\n * Env var holding the API key. Defaults to `ANTHROPIC_API_KEY` for\n * Anthropic and `OPENAI_API_KEY` for OpenAI.\n */\n readonly apiKeyEnv?: string;\n readonly baseUrl?: string;\n}\n\nexport class AiError extends Error {\n constructor(message: string) {\n super(`envx template ai: ${message}`);\n this.name = \"AiError\";\n }\n}\n\nexport type AnthropicAuthKind = \"api-key\" | \"oauth\";\n\nexport interface AnthropicAuth {\n readonly token: string;\n readonly kind: AnthropicAuthKind;\n readonly sourceEnv: string;\n}\n\n/**\n * Subscription tokens issued via Claude Code's OAuth flow are prefixed\n * `sk-ant-oat...`. Anything else is treated as an API key — being\n * permissive is safe because the server rejects malformed tokens\n * regardless. Matches czar's `classifyAnthropicToken` exactly.\n */\nexport function classifyAnthropicToken(token: string): AnthropicAuthKind {\n return token.startsWith(\"sk-ant-oat\") ? \"oauth\" : \"api-key\";\n}\n\n/**\n * Resolve Anthropic credentials from the env. Returns the configured\n * `apiKeyEnv` value first; falls back to the OAuth bearer envs in\n * declaration order. Returns `undefined` when nothing is set so the\n * caller can render a context-rich error. Mirrors czar's\n * `lookupAnthropicAuth` exactly.\n */\nexport function lookupAnthropicAuth(\n env: NodeJS.ProcessEnv,\n apiKeyEnv: string,\n): AnthropicAuth | undefined {\n const direct = env[apiKeyEnv];\n if (direct) {\n return {\n token: direct,\n kind: classifyAnthropicToken(direct),\n sourceEnv: apiKeyEnv,\n };\n }\n for (const name of ANTHROPIC_OAUTH_ENVS) {\n const v = env[name];\n if (v) {\n return { token: v, kind: classifyAnthropicToken(v), sourceEnv: name };\n }\n }\n return undefined;\n}\n\nfunction mergeBetaHeader(existing: string | undefined, add: string): string {\n if (!existing) return add;\n const parts = existing.split(\",\").map((s) => s.trim()).filter(Boolean);\n if (parts.includes(add)) return existing;\n return [...parts, add].join(\",\");\n}\n\n/**\n * Per-batch keypair budget. Claude / OpenAI have hard `max_tokens`\n * output limits and most env-file responses run ~30-50 tokens per\n * `\"KEY\": \"value\"` entry, so a 200+ key request truncates partway\n * through and the JSON never closes. Batching keeps each round-trip\n * well under the cap (~40 keys × ~50 tokens = ~2k tokens response,\n * comfortably under our 4096 max_tokens).\n *\n * Set deliberately small — quality stays high (less context dilution)\n * and partial failure on one batch doesn't take down the whole run.\n */\nconst BATCH_SIZE = 40;\nconst MAX_TOKENS_PER_BATCH = 4096;\n\n/**\n * Generate an example value per key. Returns a Map keyed by env-var\n * name. Keys without a usable AI response fall back to an empty string\n * so the template still serializes cleanly.\n *\n * Internally batches into BATCH_SIZE chunks so large env files (200+\n * keys) don't truncate against the provider's max-output-tokens cap.\n * Batches run sequentially to avoid surprise rate-limit hits — a 200-\n * key file is 5 sequential calls, ~5-10s end-to-end.\n *\n * Per-key `hint` (typically the trailing-comment from the source line)\n * is forwarded to the prompt to anchor the AI's value choice.\n */\nexport async function generateExamples(\n keys: ReadonlyArray<{ readonly name: string; readonly hint?: string }>,\n opts: AiOptions = {},\n): Promise<Map<string, string>> {\n if (keys.length === 0) return new Map();\n\n const provider = opts.provider ?? \"anthropic\";\n const apiKeyEnv =\n opts.apiKeyEnv ??\n (provider === \"anthropic\" ? \"ANTHROPIC_API_KEY\" : \"OPENAI_API_KEY\");\n const model =\n opts.model ??\n (provider === \"anthropic\"\n ? \"claude-haiku-4-5-20251001\"\n : \"gpt-4o-mini\");\n\n // Resolve auth once, up front. Fail fast before any network call so\n // the error message is clean (no half-batches).\n let auth: AnthropicAuth | undefined;\n let openAiKey: string | undefined;\n if (provider === \"anthropic\") {\n auth = lookupAnthropicAuth(process.env, apiKeyEnv);\n if (!auth) {\n throw new AiError(\n `no Anthropic credentials in env (checked ${apiKeyEnv}, ${ANTHROPIC_OAUTH_ENVS.join(\", \")}). Either export one or set it in your loaded .env files.`,\n );\n }\n } else {\n openAiKey = process.env[apiKeyEnv];\n if (!openAiKey) throw new AiError(`${apiKeyEnv} is not set`);\n }\n\n const out = new Map<string, string>();\n const batches = chunk(keys, BATCH_SIZE);\n for (let i = 0; i < batches.length; i += 1) {\n const batch = batches[i]!;\n const prompt = buildPrompt(batch);\n let text: string;\n try {\n text =\n provider === \"anthropic\"\n ? await callAnthropic({ auth: auth!, model, prompt, baseUrl: opts.baseUrl })\n : await callOpenAi({\n apiKey: openAiKey!,\n model,\n prompt,\n baseUrl: opts.baseUrl,\n });\n } catch (e) {\n // Surface the batch index so the user knows which slice failed.\n throw new AiError(\n `batch ${String(i + 1)}/${String(batches.length)} (${String(batch.length)} keys) failed: ${(e as Error).message}`,\n );\n }\n const parsed = parseResponse(text, batch.map((k) => k.name));\n for (const [k, v] of parsed) out.set(k, v);\n }\n return out;\n}\n\nfunction chunk<T>(arr: ReadonlyArray<T>, size: number): T[][] {\n const out: T[][] = [];\n for (let i = 0; i < arr.length; i += size) {\n out.push(arr.slice(i, i + size));\n }\n return out;\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- Prompt + parsing ------------------------------\n\nfunction buildPrompt(\n keys: ReadonlyArray<{ readonly name: string; readonly hint?: string }>,\n): string {\n const items = keys\n .map((k) =>\n k.hint && k.hint.length > 0\n ? `- ${k.name} (${k.hint.trim()})`\n : `- ${k.name}`,\n )\n .join(\"\\n\");\n return [\n \"You are generating placeholder values for a `.env.example` file.\",\n \"Each value should be a realistic-looking but obviously-fake example a developer can copy and replace.\",\n \"\",\n \"Rules:\",\n \"- Output JSON only, no prose, no code fences. A single object mapping each key (verbatim) to its example string value.\",\n \"- Use shape that matches the key name: URLs for *_URL, ports for PORT/*_PORT, booleans (`true`/`false`) for IS_*/HAS_*/ENABLE_*, hex/base64-ish strings for *_KEY/*_TOKEN/*_SECRET, integers for *_COUNT/*_LIMIT, log levels for LOG_LEVEL, etc.\",\n \"- Never use a real-looking secret. Prefix sensitive-looking values with `your-` or end with `-here` so reviewers see them as placeholders.\",\n \"- Keep each value short — under 60 chars unless a JWT or URL forces it.\",\n \"- If a hint is given in parentheses after a key, use it as context.\",\n \"\",\n \"Keys:\",\n items,\n \"\",\n \"Return JSON object:\",\n ].join(\"\\n\");\n}\n\n/**\n * Parse the AI's JSON response. Tolerant of code fences, leading prose,\n * trailing junk — extracts the first {…} block and JSON.parses it. Any\n * key missing from the parsed object is omitted from the result map\n * (caller falls back to an empty value).\n */\nfunction parseResponse(\n text: string,\n expectedKeys: ReadonlyArray<string>,\n): Map<string, string> {\n // Strip code fences if present.\n const fenced = /```(?:json)?\\s*([\\s\\S]*?)```/.exec(text);\n const candidate = fenced ? fenced[1]! : text;\n // Find the outermost {…} block.\n const start = candidate.indexOf(\"{\");\n const end = candidate.lastIndexOf(\"}\");\n // No closing brace at all → response was truncated against the\n // model's max_tokens cap. Surface a hint that helps the user\n // (lower BATCH_SIZE, raise MAX_TOKENS_PER_BATCH, or split the env).\n if (start !== -1 && (end === -1 || end <= start)) {\n throw new AiError(\n `AI response truncated mid-JSON (no closing brace). Likely hit max_tokens — try fewer keys per batch. First 200 chars: ${text.slice(0, 200)}`,\n );\n }\n if (start === -1) {\n throw new AiError(`AI returned no JSON object: ${text.slice(0, 200)}`);\n }\n const slice = candidate.slice(start, end + 1);\n let parsed: unknown;\n try {\n parsed = JSON.parse(slice);\n } catch (e) {\n throw new AiError(\n `AI returned invalid JSON: ${(e as Error).message} — ${slice.slice(0, 200)}`,\n );\n }\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new AiError(\"AI returned a non-object payload\");\n }\n const out = new Map<string, string>();\n const obj = parsed as Record<string, unknown>;\n for (const k of expectedKeys) {\n const v = obj[k];\n if (typeof v === \"string\") out.set(k, v);\n else if (typeof v === \"number\" || typeof v === \"boolean\") out.set(k, String(v));\n // Missing keys / wrong types fall through; renderer emits `KEY=`.\n }\n return out;\n}\n\n// #endregion -----------------------------------------------\n\n// #region -- HTTP transport --------------------------------\n\nasync function fetchWithTimeout(\n url: string,\n init: RequestInit,\n ms: number,\n): Promise<Response> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), ms);\n try {\n return await fetch(url, { ...init, signal: ctrl.signal });\n } catch (err) {\n if ((err as { name?: string }).name === \"AbortError\") {\n throw new AiError(`request timed out after ${ms}ms (${url})`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nasync function callAnthropic(opts: {\n readonly auth: AnthropicAuth;\n readonly model: string;\n readonly prompt: string;\n readonly baseUrl?: string;\n}): Promise<string> {\n const base = opts.baseUrl ?? ANTHROPIC_DEFAULT_BASE;\n const url = `${base}/v1/messages`;\n const headers: Record<string, string> = {\n \"content-type\": \"application/json\",\n \"anthropic-version\": \"2023-06-01\",\n };\n if (opts.auth.kind === \"oauth\") {\n // Subscription OAuth bearer: API requires the oauth beta gate\n // alongside an `Authorization: Bearer` header. Preserve any\n // existing anthropic-beta values by appending the gate.\n headers.authorization = `Bearer ${opts.auth.token}`;\n headers[\"anthropic-beta\"] = mergeBetaHeader(\n headers[\"anthropic-beta\"],\n ANTHROPIC_OAUTH_BETA,\n );\n } else {\n headers[\"x-api-key\"] = opts.auth.token;\n }\n const res = await fetchWithTimeout(\n url,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n model: opts.model,\n max_tokens: MAX_TOKENS_PER_BATCH,\n messages: [{ role: \"user\", content: opts.prompt }],\n }),\n },\n REQUEST_TIMEOUT_MS,\n );\n if (!res.ok) {\n throw new AiError(`anthropic API ${res.status}: ${await res.text()}`);\n }\n const data = (await res.json()) as {\n content?: ReadonlyArray<{ type: string; text?: string }>;\n };\n const block = data.content?.find((b) => b.type === \"text\");\n if (!block?.text) throw new AiError(\"anthropic API returned no text\");\n return block.text;\n}\n\nasync function callOpenAi(opts: {\n readonly apiKey: string;\n readonly model: string;\n readonly prompt: string;\n readonly baseUrl?: string;\n}): Promise<string> {\n const base = opts.baseUrl ?? OPENAI_DEFAULT_BASE;\n const res = await fetchWithTimeout(\n `${base}/chat/completions`,\n {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n authorization: `Bearer ${opts.apiKey}`,\n },\n body: JSON.stringify({\n model: opts.model,\n messages: [{ role: \"user\", content: opts.prompt }],\n temperature: 0.2,\n }),\n },\n REQUEST_TIMEOUT_MS,\n );\n if (!res.ok) {\n throw new AiError(`openai API ${res.status}: ${await res.text()}`);\n }\n const data = (await res.json()) as {\n choices?: ReadonlyArray<{ message?: { content?: string } }>;\n };\n const text = data.choices?.[0]?.message?.content;\n if (!text) throw new AiError(\"openai API returned no text\");\n return text;\n}\n\n// #endregion -----------------------------------------------\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { CommandModule } from \"yargs\";\n\nimport {\n loadEnv,\n parseEnv,\n resolveCwdOrWorkspace,\n resolveEnvPaths,\n type DotenvxConfig,\n type EnvLine,\n} from \"../libs/index.js\";\nimport { log } from \"@super-repo/envx-common\";\n\nimport { AiError, generateExamples } from \"./template-ai.js\";\n\n// #region -- template command ------------------------------\n\n/**\n * Generate (or check) a stripped `.env.example` from one or more real\n * env files. The output mirrors the source files' organization —\n * comments, blank lines, and declaration order are preserved verbatim.\n * Values are stripped (or replaced with AI-generated placeholders when\n * `--ai` is set). The encryption banner block (`#/-----[ENVX_PUBLIC_KEY]…`)\n * and the `*PUBLIC_KEY*` kv lines themselves are dropped — the example\n * file should be encryption-agnostic.\n *\n * Three modes:\n * - default: write the rendered template to --out (default `.env.example`)\n * - --stdout: print to stdout (don't touch disk)\n * - --check: exit non-zero if the on-disk template is out of date\n */\nexport const templateCommand: CommandModule = {\n command: \"template\",\n describe:\n \"Emit a value-stripped .env.example from your real env files (or `--check` it for drift).\",\n builder: (yargs) =>\n yargs\n .option(\"out\", {\n // No `-o` alias — that's already taken by the global `--override`.\n type: \"string\",\n describe: \"Output path. Default: `<cwd>/.env.example`.\",\n })\n .option(\"stdout\", {\n type: \"boolean\",\n default: false,\n describe: \"Print template to stdout instead of writing to disk.\",\n })\n .option(\"check\", {\n type: \"boolean\",\n default: false,\n describe:\n \"Compare the rendered template against the on-disk file; exit 1 on drift. Use this in CI.\",\n })\n .option(\"env-keys-file\", {\n alias: \"fk\",\n type: \"string\",\n describe:\n \"Path to the .env.keys file (default: cwd-first then workspace-root walk-up). Pass when --ai is set and your env files live in a subdir like vault/ while .env.keys is at the workspace root.\",\n })\n .option(\"ai\", {\n type: \"boolean\",\n default: false,\n describe:\n \"Use Claude (or OpenAI) to generate realistic-looking placeholder values for each key. Reads ANTHROPIC_API_KEY (or OPENAI_API_KEY) from your loaded env files. Non-deterministic — usually paired with manual review, not --check.\",\n })\n .option(\"ai-provider\", {\n type: \"string\",\n choices: [\"anthropic\", \"openai\"] as const,\n default: \"anthropic\",\n describe: \"Which AI provider --ai uses. Default: anthropic.\",\n })\n .option(\"ai-model\", {\n type: \"string\",\n describe:\n \"Override the AI model. Defaults: claude-haiku-4-5-20251001 (anthropic), gpt-4o-mini (openai).\",\n }),\n handler: async (argv): Promise<void> => {\n const cfg = (argv[\"__envxConfig\"] as DotenvxConfig | undefined) ?? {};\n const outArg = argv[\"out\"] as string | undefined;\n const useStdout = argv[\"stdout\"] as boolean;\n const check = argv[\"check\"] as boolean;\n const useAi = argv[\"ai\"] as boolean;\n const aiProvider = argv[\"ai-provider\"] as \"anthropic\" | \"openai\";\n const aiModel = argv[\"ai-model\"] as string | undefined;\n\n const paths = resolveEnvPaths({\n ...(argv[\"env\"] !== undefined ? { envFiles: argv[\"env\"] as string[] } : {}),\n ...(argv[\"cascade\"] !== undefined\n ? { cascade: argv[\"cascade\"] as string }\n : {}),\n ...(cfg.autoDetect !== undefined ? { autoDetect: cfg.autoDetect } : {}),\n ...(cfg.nodeEnvMap !== undefined ? { nodeEnvMap: cfg.nodeEnvMap } : {}),\n });\n const subdir =\n (argv[\"env-path\"] as string | undefined) ??\n ((argv[\"vault\"] as boolean | undefined) ? \"vault\" : \"\");\n const resolved = paths.map((p) =>\n path.isAbsolute(p)\n ? p\n : subdir\n ? resolveCwdOrWorkspace(path.join(subdir, p))\n : resolveCwdOrWorkspace(p),\n );\n const existing = resolved.filter((p) => fs.existsSync(p));\n if (existing.length === 0) {\n log.error(\"no env files found to template from\");\n process.exit(1);\n }\n\n // --ai needs the API key. Load env files into process.env first\n // (decrypts via .env.keys) so the configured ANTHROPIC_API_KEY in\n // the user's `.env` becomes visible to the AI client. Mirror\n // run.ts's loadEnv invocation exactly — pass raw argv (NOT the\n // pre-resolved absolute paths in `existing`), because the absolute-\n // path code path in env.ts skips the `.env.keys` discovery and\n // dotenvx falls back to empty `DOTENV_PRIVATE_KEY*` env vars,\n // breaking decryption silently.\n let aiValues = new Map<string, string>();\n if (useAi) {\n // Mirror run.ts's loadEnv invocation. Pass envKeysFile through\n // (CLI flag wins; falls back to cfg.envKeysFile; finally\n // loadEnv auto-discovers via cwd → workspace walk-up). This is\n // what makes decryption work when env files live in a subdir\n // like vault/ but .env.keys is at the workspace root.\n const envKeysFileArg =\n (argv[\"env-keys-file\"] as string | undefined) ?? cfg.envKeysFile;\n try {\n loadEnv({\n envFiles: argv[\"env\"] as string[] | undefined,\n cascade: argv[\"cascade\"] as string | boolean | undefined,\n vault: argv[\"vault\"] as boolean | undefined,\n envPath: argv[\"env-path\"] as string | undefined,\n override: argv[\"override\"] as boolean | undefined,\n quiet: true,\n ...(envKeysFileArg !== undefined ? { envKeysFile: envKeysFileArg } : {}),\n ...(cfg.autoDetect !== undefined ? { autoDetect: cfg.autoDetect } : {}),\n ...(cfg.nodeEnvMap !== undefined ? { nodeEnvMap: cfg.nodeEnvMap } : {}),\n ...(cfg.workspaceRoot !== undefined ? { workspaceRoot: cfg.workspaceRoot } : {}),\n ...(cfg.expand !== undefined ? { expand: cfg.expand } : {}),\n ...(cfg.defaults !== undefined ? { defaults: cfg.defaults } : {}),\n ...(cfg.resolvers !== undefined ? { resolvers: cfg.resolvers } : {}),\n });\n } catch (e) {\n log.error(`--ai: failed to load env for API-key lookup: ${(e as Error).message}`);\n process.exit(1);\n }\n const keys = collectKeys(existing);\n if (keys.length === 0) {\n log.warn(\"--ai: no keys to generate examples for\");\n } else {\n try {\n aiValues = await generateExamples(keys, {\n provider: aiProvider,\n ...(aiModel !== undefined ? { model: aiModel } : {}),\n });\n log.info(`--ai: generated ${aiValues.size}/${keys.length} example value(s)`);\n } catch (e) {\n if (e instanceof AiError) log.error(e.message);\n else log.error(`--ai: ${(e as Error).message}`);\n process.exit(1);\n }\n }\n }\n\n const rendered = renderTemplate(existing, { aiValues });\n\n if (useStdout) {\n process.stdout.write(rendered);\n return;\n }\n\n const outPath = path.resolve(process.cwd(), outArg ?? \".env.example\");\n if (check) {\n const onDisk = fs.existsSync(outPath) ? fs.readFileSync(outPath, \"utf8\") : \"\";\n if (onDisk === rendered) {\n log.success(`template up to date: ${outPath}`);\n return;\n }\n log.error(`template drift: ${outPath} is out of date`);\n log.dim(\"hint: run `envx template` (without --check) to update it\");\n process.exit(1);\n }\n\n fs.writeFileSync(outPath, rendered);\n log.success(`wrote template: ${outPath} (${countKeys(rendered)} key(s))`);\n },\n};\n\n// #endregion -----------------------------------------------\n\n// #region -- renderer --------------------------------------\n\n/**\n * Render the template by walking each source file in order. Comments,\n * blank lines, and declaration order are preserved verbatim. A kv line\n * becomes `KEY=` (or `KEY=<ai-value>` when `--ai` populated `aiValues`).\n *\n * Two filters apply to every line, in this order:\n * 1. The encryption banner block — any line starting with `#/` (e.g.\n * `#/-------------------[ENVX_PUBLIC_KEY]------------------/`).\n * The full 4-line banner is dropped.\n * 2. Public-key kv lines — `ENVX_PUBLIC_KEY*` and the legacy\n * `DOTENV_PUBLIC_KEY*`. They're committed alongside encrypted\n * values, but `.env.example` is meant to be encryption-agnostic.\n *\n * Multi-file dedup: when a key appears in more than one source file,\n * only the first occurrence's line is emitted. Subsequent files'\n * comments and blank lines still pass through (so the per-file\n * structure stays visible), but their kv duplicates are skipped.\n */\nfunction renderTemplate(\n files: readonly string[],\n opts: { aiValues: Map<string, string> },\n): string {\n const seen = new Set<string>();\n const out: string[] = [];\n out.push(\"# Generated by `envx template` — do not edit by hand.\");\n out.push(\"# Run `envx template` to regenerate, or `envx template --check` in CI.\");\n out.push(\"\");\n\n for (let i = 0; i < files.length; i += 1) {\n const file = files[i]!;\n const display = path.relative(process.cwd(), file) || file;\n const lines = parseEnv(fs.readFileSync(file, \"utf8\"));\n // Multiple-file source: header each section so reviewers can see\n // where each block came from. Single-file source: skip the header.\n if (files.length > 1) {\n out.push(`# ── ${display} ─────────────────────────────────`);\n }\n appendFile(out, lines, seen, opts.aiValues);\n // Trailing blank line between files keeps the diff readable.\n if (i < files.length - 1 && (out.length === 0 || out[out.length - 1] !== \"\")) {\n out.push(\"\");\n }\n }\n // serializeEnv (which we mirror) joins with `\\n` and emits no trailing\n // newline. Match that for round-trip stability with `--check`.\n return out.join(\"\\n\");\n}\n\nfunction appendFile(\n out: string[],\n lines: readonly EnvLine[],\n seen: Set<string>,\n aiValues: Map<string, string>,\n): void {\n for (const ln of lines) {\n if (ln.type === \"raw\") {\n // Drop encryption-banner lines — they're a generated artifact of\n // `envx encrypt`, not user-authored content.\n if (isBannerLine(ln.raw)) continue;\n out.push(ln.raw);\n continue;\n }\n // kv line\n if (isPublicKeyName(ln.key)) continue;\n if (seen.has(ln.key)) continue;\n seen.add(ln.key);\n const aiValue = aiValues.get(ln.key);\n if (aiValue !== undefined && aiValue !== \"\") {\n // Quote the value if it contains characters that would break\n // unquoted parsing (whitespace, #, $, etc.). Conservative: quote\n // anything that isn't a single token of safe chars.\n const needsQuote = /[\\s#'\"\\\\$&;|<>(){}]/.test(aiValue);\n const quoted = needsQuote\n ? `\"${aiValue.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`\n : aiValue;\n out.push(`${ln.key}=${quoted}`);\n } else {\n out.push(`${ln.key}=`);\n }\n }\n}\n\n/**\n * Banner lines emitted by `envx encrypt` start with `#/`. Be permissive:\n * any comment beginning with that two-char prefix is treated as banner\n * decoration. Real user comments use `#` (with or without a space).\n */\nfunction isBannerLine(raw: string): boolean {\n return /^\\s*#\\//.test(raw);\n}\n\n/**\n * `ENVX_PUBLIC_KEY*` is the canonical public-key var; `DOTENV_PUBLIC_KEY*`\n * is the upstream-dotenvx-compat variant envx also reads. Both are an\n * artifact of encryption, never user-meaningful — drop from `.env.example`.\n */\nfunction isPublicKeyName(name: string): boolean {\n return /^(ENVX|DOTENV)_PUBLIC_KEY/.test(name);\n}\n\n/**\n * Collect every unique kv key (in declaration order) across the source\n * files, skipping the encryption-banner public-key vars. Used to feed\n * `--ai` exactly the keys that will appear in the rendered template.\n *\n * Each entry includes a `hint` derived from the kv line's trailing\n * comment (e.g. `# database connection string`) — the AI prompt uses\n * the hint to anchor the example value.\n */\nfunction collectKeys(\n files: readonly string[],\n): Array<{ readonly name: string; readonly hint?: string }> {\n const seen = new Set<string>();\n const out: Array<{ name: string; hint?: string }> = [];\n for (const file of files) {\n const lines = parseEnv(fs.readFileSync(file, \"utf8\"));\n for (const ln of lines) {\n if (ln.type !== \"kv\") continue;\n if (isPublicKeyName(ln.key)) continue;\n if (seen.has(ln.key)) continue;\n seen.add(ln.key);\n // Strip the leading `#` and surrounding whitespace from the\n // trailing comment so the prompt sees just the human note.\n const hint = ln.trailing.replace(/^\\s*#\\s*/, \"\").trim();\n out.push(hint.length > 0 ? { name: ln.key, hint } : { name: ln.key });\n }\n }\n return out;\n}\n\nfunction countKeys(rendered: string): number {\n return rendered.split(\"\\n\").filter((l) => /^[A-Za-z_][A-Za-z0-9_]*=/.test(l))\n .length;\n}\n\n// #endregion -----------------------------------------------\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { CommandModule } from \"yargs\";\n\nimport {\n parseEnv,\n resolveCwdOrWorkspace,\n resolveEnvPaths,\n toRecord,\n type DotenvxConfig,\n} from \"../libs/index.js\";\nimport { log } from \"@super-repo/envx-common\";\n\n// #region -- types command ---------------------------------\n\n/**\n * Emit a TypeScript declaration file (`env.d.ts`) declaring every key\n * found across the resolved env files. Adds the keys to `NodeJS.ProcessEnv`\n * via interface merging, so `process.env.MY_KEY` autocompletes and\n * type-checks across the project.\n *\n * Keys listed in `config.required` are typed as `string` (always set);\n * everything else is `string | undefined`. When a Zod schema is\n * configured we look at its `.shape` (when present) to pick up the same\n * required-vs-optional information.\n */\nexport const typesCommand: CommandModule = {\n command: \"types\",\n describe:\n \"Emit env.d.ts declaring every loaded key on NodeJS.ProcessEnv (string | undefined; required keys narrow to string).\",\n builder: (yargs) =>\n yargs\n .option(\"out\", {\n // No `-o` alias — that's already taken by the global `--override`.\n type: \"string\",\n default: \"env.d.ts\",\n describe: \"Output path (relative to cwd).\",\n })\n .option(\"stdout\", {\n type: \"boolean\",\n default: false,\n describe: \"Print to stdout instead of writing to disk.\",\n }),\n handler: (argv): void => {\n const cfg = (argv[\"__envxConfig\"] as DotenvxConfig | undefined) ?? {};\n const out = argv[\"out\"] as string;\n const useStdout = argv[\"stdout\"] as boolean;\n\n const paths = resolveEnvPaths({\n ...(argv[\"env\"] !== undefined ? { envFiles: argv[\"env\"] as string[] } : {}),\n ...(argv[\"cascade\"] !== undefined\n ? { cascade: argv[\"cascade\"] as string }\n : {}),\n ...(cfg.autoDetect !== undefined ? { autoDetect: cfg.autoDetect } : {}),\n ...(cfg.nodeEnvMap !== undefined ? { nodeEnvMap: cfg.nodeEnvMap } : {}),\n });\n const subdir =\n (argv[\"env-path\"] as string | undefined) ??\n ((argv[\"vault\"] as boolean | undefined) ? \"vault\" : \"\");\n const resolved = paths\n .map((p) =>\n path.isAbsolute(p)\n ? p\n : subdir\n ? resolveCwdOrWorkspace(path.join(subdir, p))\n : resolveCwdOrWorkspace(p),\n )\n .filter((p) => fs.existsSync(p));\n\n // Collect every key from every loaded file.\n const keysFromFiles = new Set<string>();\n for (const f of resolved) {\n const lines = parseEnv(fs.readFileSync(f, \"utf8\"));\n for (const k of Object.keys(toRecord(lines))) keysFromFiles.add(k);\n }\n\n const required = new Set<string>(cfg.required ?? []);\n\n // If a schema with a `.shape` (Zod object) is configured, treat its\n // required keys as required and include any keys we hadn't yet seen.\n const schemaShape = extractZodShape(cfg.schema);\n for (const [k, isOptional] of Object.entries(schemaShape)) {\n keysFromFiles.add(k);\n if (!isOptional) required.add(k);\n }\n\n const allKeys = [...keysFromFiles].sort();\n if (allKeys.length === 0) {\n log.error(\"no keys found — load at least one env file or configure a schema\");\n process.exit(1);\n }\n\n const lines: string[] = [];\n lines.push(\"// Generated by `envx types` — do not edit by hand.\");\n lines.push(\"// Run `envx types` to regenerate.\");\n lines.push(\"\");\n lines.push(\"declare global {\");\n lines.push(\" namespace NodeJS {\");\n lines.push(\" interface ProcessEnv {\");\n for (const k of allKeys) {\n const optional = required.has(k) ? \"\" : \"?\";\n lines.push(` readonly ${k}${optional}: string;`);\n }\n lines.push(\" }\");\n lines.push(\" }\");\n lines.push(\"}\");\n lines.push(\"\");\n lines.push(\"export {};\");\n lines.push(\"\");\n const rendered = lines.join(\"\\n\");\n\n if (useStdout) {\n process.stdout.write(rendered);\n return;\n }\n\n const outPath = path.resolve(process.cwd(), out);\n fs.writeFileSync(outPath, rendered);\n log.success(`wrote ${outPath} (${allKeys.length} key(s), ${required.size} required)`);\n },\n};\n\n// #endregion -----------------------------------------------\n\n// #region -- Zod introspection -----------------------------\n\n/**\n * Extract a `{ key → isOptional }` map from a duck-typed Zod schema.\n * Looks for `.shape` (ZodObject). Returns `{}` if the schema doesn't\n * follow that shape — we still emit types for every file-found key,\n * just without the required/optional refinement.\n */\nfunction extractZodShape(schema: unknown): Record<string, boolean> {\n if (!schema || typeof schema !== \"object\") return {};\n const shape = (schema as { shape?: unknown }).shape;\n if (!shape || typeof shape !== \"object\") return {};\n const out: Record<string, boolean> = {};\n for (const [k, v] of Object.entries(shape as Record<string, unknown>)) {\n if (!v || typeof v !== \"object\") continue;\n // Optional in Zod: ZodOptional wraps a ZodTypeAny. Check the\n // _def.typeName chain ('ZodOptional', 'ZodDefault') to mark optional.\n const def = (v as { _def?: { typeName?: string } })._def;\n const tn = def?.typeName ?? \"\";\n out[k] = tn === \"ZodOptional\" || tn === \"ZodDefault\";\n }\n return out;\n}\n\n// #endregion -----------------------------------------------\n","import { spawn, type ChildProcess } from \"child_process\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { CommandModule } from \"yargs\";\n\nimport {\n loadEnv,\n resolveCwdOrWorkspace,\n resolveEnvPaths,\n type DotenvxConfig,\n} from \"../libs/index.js\";\nimport { log } from \"@super-repo/envx-common\";\n\n// #region -- watch command ---------------------------------\n\n/**\n * Spawn a child process with the loaded env, then watch every resolved\n * env file. On change, kill the child (SIGTERM, then SIGKILL after a\n * grace period) and respawn with a fresh load.\n *\n * Differences from `nodemon`:\n * - Only env files are watched (not source code).\n * - Restart preserves the parent shell's stdin/stdout/stderr.\n * - Cascade-resolved paths are watched (so adding `.env.local` while\n * watching is picked up if it lives at one of the resolved paths).\n */\nexport const watchCommand: CommandModule = {\n command: \"watch [command..]\",\n describe:\n \"Load env files, spawn a command, and restart it whenever any of the resolved env files change.\",\n builder: (yargs) =>\n yargs\n .positional(\"command\", {\n type: \"string\",\n array: true,\n describe: \"Command to run (e.g. `node app.js`).\",\n })\n .option(\"debounce\", {\n type: \"number\",\n default: 200,\n describe: \"Debounce window (ms) for coalescing rapid file events.\",\n })\n .option(\"kill-grace\", {\n type: \"number\",\n default: 1500,\n describe:\n \"Grace period (ms) between SIGTERM and SIGKILL when restarting the child.\",\n }),\n handler: (argv): void => {\n const cfg = (argv[\"__envxConfig\"] as DotenvxConfig | undefined) ?? {};\n const command = ((argv[\"command\"] as string[] | undefined) ?? []).join(\" \");\n const debounceMs = argv[\"debounce\"] as number;\n const killGraceMs = argv[\"kill-grace\"] as number;\n\n if (!command) {\n log.error(\"watch: no command supplied. Example: envx watch -- node app.js\");\n process.exit(1);\n }\n\n const loadEnvOptions = (): Parameters<typeof loadEnv>[0] => ({\n envFiles: argv[\"env\"] as string[] | undefined,\n variables: argv[\"variables\"] as string[] | undefined,\n cascade: argv[\"cascade\"] as string | boolean | undefined,\n vault: argv[\"vault\"] as boolean | undefined,\n envPath: argv[\"env-path\"] as string | undefined,\n override: argv[\"override\"] as boolean | undefined,\n quiet: argv[\"quiet\"] as boolean | undefined,\n ...(cfg.autoDetect !== undefined ? { autoDetect: cfg.autoDetect } : {}),\n ...(cfg.nodeEnvMap !== undefined ? { nodeEnvMap: cfg.nodeEnvMap } : {}),\n ...(cfg.required !== undefined ? { required: cfg.required } : {}),\n ...(cfg.expand !== undefined ? { expand: cfg.expand } : {}),\n ...(cfg.defaults !== undefined ? { defaults: cfg.defaults } : {}),\n ...(cfg.workspaceRoot !== undefined ? { workspaceRoot: cfg.workspaceRoot } : {}),\n ...(cfg.schema !== undefined ? { schema: cfg.schema } : {}),\n ...(cfg.resolvers !== undefined ? { resolvers: cfg.resolvers } : {}),\n });\n\n const watchedPaths = resolveWatchedPaths(argv, cfg);\n if (watchedPaths.length === 0) {\n log.warn(\"watch: no env files exist to watch — running anyway\");\n } else {\n log.info(`watch: ${watchedPaths.length} file(s)`);\n for (const p of watchedPaths) log.dim(` • ${p}`);\n }\n\n let child: ChildProcess | null = null;\n let restarting = false;\n let pendingTimer: ReturnType<typeof setTimeout> | null = null;\n\n const start = (): void => {\n // Snapshot vars from this load so we can pass them to the child\n // without disturbing the parent's process.env permanently.\n // We snapshot full values (not just keys) so override:true loads\n // also restore correctly.\n const snapshot: Record<string, string | undefined> = { ...process.env };\n loadEnv(loadEnvOptions());\n const childEnv: Record<string, string | undefined> = { ...process.env };\n // Restore parent — child gets the merged view, parent stays clean.\n for (const k of Object.keys(process.env)) {\n if (!(k in snapshot)) delete process.env[k];\n }\n Object.assign(process.env, snapshot);\n\n log.info(`▶ ${command}`);\n child = spawn(command, {\n shell: true,\n stdio: \"inherit\",\n env: childEnv,\n });\n child.on(\"exit\", (code) => {\n if (restarting) return;\n const c = code ?? 0;\n if (c === 0) log.success(`exit 0`);\n else log.warn(`exit ${String(c)}`);\n child = null;\n });\n };\n\n const restart = (): void => {\n if (restarting) return;\n restarting = true;\n const cur = child;\n if (!cur) {\n restarting = false;\n start();\n return;\n }\n cur.kill(\"SIGTERM\");\n const t = setTimeout(() => {\n if (cur && !cur.killed) cur.kill(\"SIGKILL\");\n }, killGraceMs);\n cur.once(\"exit\", () => {\n clearTimeout(t);\n restarting = false;\n start();\n });\n };\n\n for (const p of watchedPaths) {\n try {\n fs.watch(p, () => {\n if (pendingTimer) clearTimeout(pendingTimer);\n pendingTimer = setTimeout(() => {\n log.info(`↻ env changed — restarting`);\n restart();\n }, debounceMs);\n });\n } catch (e) {\n log.warn(`watch failed for ${p}: ${(e as Error).message}`);\n }\n }\n\n const shutdown = (): void => {\n if (child && !child.killed) child.kill(\"SIGTERM\");\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n start();\n },\n};\n\n// #endregion -----------------------------------------------\n\n// #region -- helpers ---------------------------------------\n\nfunction resolveWatchedPaths(\n argv: { [k: string]: unknown },\n cfg: DotenvxConfig,\n): string[] {\n const paths = resolveEnvPaths({\n ...(argv[\"env\"] !== undefined ? { envFiles: argv[\"env\"] as string[] } : {}),\n ...(argv[\"cascade\"] !== undefined\n ? { cascade: argv[\"cascade\"] as string }\n : {}),\n ...(cfg.autoDetect !== undefined ? { autoDetect: cfg.autoDetect } : {}),\n ...(cfg.nodeEnvMap !== undefined ? { nodeEnvMap: cfg.nodeEnvMap } : {}),\n });\n const subdir =\n (argv[\"env-path\"] as string | undefined) ??\n ((argv[\"vault\"] as boolean | undefined) ? \"vault\" : \"\");\n return paths\n .map((p: string) =>\n path.isAbsolute(p)\n ? p\n : subdir\n ? resolveCwdOrWorkspace(path.join(subdir, p))\n : resolveCwdOrWorkspace(p),\n )\n .filter((p: string) => fs.existsSync(p));\n}\n\n// #endregion -----------------------------------------------\n","import yargs from \"yargs\";\nimport type { Argv } from \"yargs\";\n\nimport * as path from \"path\";\n\nimport {\n listEnvFiles,\n loadDotenvxConfig,\n resolveCwdOrWorkspace,\n} from \"../libs/index.js\";\n\nimport { log } from \"@super-repo/envx-common\";\nimport { auditCommand } from \"./audit.js\";\nimport { bakeCommand } from \"./bake.js\";\nimport { debugCommand } from \"./debug.js\";\nimport { decryptCommand } from \"./decrypt.js\";\nimport { diffCommand } from \"./diff.js\";\nimport { doctorCommand } from \"./doctor.js\";\nimport { encryptCommand } from \"./encrypt.js\";\nimport { expandCommand } from \"./expand.js\";\nimport { hookCommand } from \"./hook.js\";\nimport { infoCommand } from \"./info.js\";\nimport { printCommand } from \"./print.js\";\nimport { rotateCommand } from \"./rotate.js\";\nimport { runCommand } from \"./run.js\";\nimport { templateCommand } from \"./template.js\";\nimport { typesCommand } from \"./types.js\";\nimport { watchCommand } from \"./watch.js\";\n\n// #region -- CLI Factory -----------------------------------\n\n/**\n * Build the yargs CLI for `dotenvx-run`. Global options (env, variables,\n * cascade, vault, override, quiet) are registered on the root so every\n * subcommand inherits them.\n */\nexport function createCli(argvInput: string[]): Argv {\n return yargs(argvInput)\n .scriptName(\"envx\")\n .usage(\"$0 <command> [options]\")\n .option(\"config\", {\n alias: \"c\",\n type: \"string\",\n describe:\n \"Path to an envx config file (default: discovered from package.json `envx.config` or envx.config.{ts,js,json}).\",\n })\n .option(\"env\", {\n alias: \"e\",\n type: \"array\",\n describe:\n \"Env files to load. Default: [\\\".env\\\"] (or `envFiles` from config; or every .env* under --env-path when set). Auto-detects environment when omitted.\",\n })\n .option(\"env-path\", {\n alias: [\"dir\", \"d\"],\n type: \"string\",\n describe:\n \"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.\",\n })\n .option(\"variables\", {\n alias: \"v\",\n type: \"array\",\n describe: \"Inline variables in the form name=value (repeatable).\",\n default: [],\n })\n .option(\"cascade\", {\n type: \"string\",\n describe:\n \"Cascade load order: .env, .env.<cascade>, .env.local, .env.<cascade>.local\",\n })\n .option(\"vault\", {\n alias: \"va\",\n type: \"boolean\",\n describe: \"Shortcut for `--env-path vault`.\",\n })\n .option(\"override\", {\n alias: \"o\",\n type: \"boolean\",\n describe: \"Override existing process.env values. Conflicts with --cascade.\",\n })\n .option(\"quiet\", {\n alias: \"q\",\n type: \"boolean\",\n describe: \"Suppress dotenv's own output.\",\n })\n .option(\"profile\", {\n alias: \"P\",\n type: \"string\",\n describe:\n \"Named profile from `profiles` in envx.config.* — fields override the base config per-field.\",\n })\n .option(\"public-prefix\", {\n type: \"array\",\n string: true,\n describe:\n \"Framework prefix to mirror PUBLIC_ vars under (repeatable). e.g. `--public-prefix VITE_ --public-prefix NEXT_PUBLIC_`. Overrides `publicPrefixes` from envx.config.*.\",\n })\n .middleware((argv) => {\n const configPath = argv[\"config\"] as string | undefined;\n let loaded;\n try {\n loaded = loadDotenvxConfig({\n ...(configPath ? { configPath } : {}),\n });\n } catch (e) {\n log.error(`config error: ${(e as Error).message}`);\n process.exit(1);\n }\n if (loaded.source) {\n log.dim(`config: ${loaded.source} (${loaded.origin})`);\n }\n let cfg = loaded.config;\n // If --profile is set and the config defines that profile, merge\n // its fields on top of the base config (per-field, profile wins).\n const profileName = argv[\"profile\"] as string | undefined;\n if (profileName) {\n const profile = cfg.profiles?.[profileName];\n if (!profile) {\n log.error(\n `unknown profile: '${profileName}' (available: ${\n Object.keys(cfg.profiles ?? {}).join(\", \") || \"none\"\n })`,\n );\n process.exit(1);\n }\n cfg = { ...cfg, ...profile };\n log.dim(`profile: ${profileName}`);\n }\n // Stash the loaded config + source on argv so command handlers\n // (notably `info`) can introspect what envx resolved without\n // re-running the config discovery.\n argv[\"__envxConfig\"] = cfg;\n argv[\"__envxConfigSource\"] = loaded.source;\n argv[\"__envxConfigOrigin\"] = loaded.origin;\n\n // Apply config defaults only where the CLI didn't supply a value.\n if (argv[\"cascade\"] === undefined && cfg.cascade !== undefined) {\n argv[\"cascade\"] = cfg.cascade;\n }\n if (argv[\"override\"] === undefined) {\n argv[\"override\"] = cfg.override ?? false;\n }\n if (argv[\"quiet\"] === undefined) {\n argv[\"quiet\"] = cfg.quiet ?? true;\n }\n if (argv[\"vault\"] === undefined) {\n argv[\"vault\"] = false;\n }\n if (argv[\"env-keys-file\"] === undefined && cfg.envKeysFile !== undefined) {\n argv[\"env-keys-file\"] = cfg.envKeysFile;\n }\n\n // env-path: CLI > config > --vault shortcut\n if (argv[\"env-path\"] === undefined) {\n if (cfg.envPath !== undefined) argv[\"env-path\"] = cfg.envPath;\n else if (argv[\"vault\"]) argv[\"env-path\"] = \"vault\";\n }\n\n // env files: CLI > config > \"all .env* in env-path\" > [\".env\"]\n const userPassedEnv = Array.isArray(argv[\"env\"]) && argv[\"env\"].length > 0;\n let files: string[];\n if (userPassedEnv) {\n files = argv[\"env\"] as string[];\n } else if (cfg.envFiles && cfg.envFiles.length > 0) {\n files = [...cfg.envFiles];\n } else if (typeof argv[\"env-path\"] === \"string\") {\n // \"all files in the env-path are included\" — discover them.\n // env-path resolves cwd-first; walk-up to workspace root only\n // if the cwd-relative dir doesn't exist.\n const subdir = argv[\"env-path\"] as string;\n const dir = resolveCwdOrWorkspace(subdir);\n const discovered = listEnvFiles(dir);\n if (discovered.length > 0) {\n files = discovered;\n log.dim(\n `env-path ${subdir}: discovered ${String(discovered.length)} file(s) — ${discovered.join(\", \")}`,\n );\n } else {\n files = [\".env\"];\n log.warn(\n `env-path ${subdir}: no .env* files found; falling back to [\".env\"]`,\n );\n }\n } else {\n files = [\".env\"];\n }\n\n // When env-path is set, resolve every relative file against that\n // directory up-front. encrypt/decrypt/expand operate on the\n // resulting paths verbatim — no per-command envPath plumbing.\n if (typeof argv[\"env-path\"] === \"string\") {\n const dir = resolveCwdOrWorkspace(argv[\"env-path\"] as string);\n files = files.map((f) => (path.isAbsolute(f) ? f : path.join(dir, f)));\n }\n argv[\"env\"] = files;\n })\n .command(runCommand)\n .command(printCommand)\n .command(debugCommand)\n .command(encryptCommand)\n .command(decryptCommand)\n .command(expandCommand)\n .command(rotateCommand)\n .command(infoCommand)\n .command(doctorCommand)\n .command(templateCommand)\n .command(diffCommand)\n .command(hookCommand)\n .command(typesCommand)\n .command(watchCommand)\n .command(auditCommand)\n .command(bakeCommand)\n .help(\"h\")\n .alias(\"h\", \"help\")\n .version()\n .strictCommands()\n .demandCommand(0)\n .recommendCommands()\n .epilog(\n \"Examples:\\n\" +\n \" envx -- node app.js # load .env (auto-detected) and run\\n\" +\n \" envx --env dev -- pnpm start # load .env.dev\\n\" +\n \" envx print DATABASE_URL # print one variable\\n\" +\n \" envx debug --cascade prod # show resolved paths\\n\" +\n \" envx encrypt -e .env.prod --secrets # encrypt only conventional secret keys\\n\" +\n \" envx decrypt -e .env.prod -k FOO # decrypt only FOO\\n\" +\n \" envx expand -e vault/.env.prod # decrypt + expand to stdout\\n\" +\n \" envx doctor # health check (CI gate)\\n\" +\n \" envx template --check # verify .env.example is up to date\\n\" +\n \" envx diff .env.dev .env.prod # compare two env files\\n\" +\n \" eval \\\"$(envx hook bash)\\\" # inject env into the parent shell\\n\" +\n \" envx types # emit env.d.ts for typed process.env\\n\" +\n \" envx watch -- node app.js # restart on env change\\n\" +\n \" envx audit # scan repo for plaintext secrets\\n\" +\n \" envx --profile staging -- node app.js # apply named profile from envx.config.*\",\n );\n}\n\n// #endregion -----------------------------------------------\n"],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { n as buildProvider } from "./types-COrFYR0z.js";
|
|
2
|
+
//#region src/plugins/doppler.ts
|
|
3
|
+
/**
|
|
4
|
+
* Doppler provider — fetches secrets via the REST API using a service
|
|
5
|
+
* token. No SDK install required (uses native `fetch`).
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { doppler } from "@super-repo/envx/plugins/doppler";
|
|
9
|
+
*
|
|
10
|
+
* const dop = doppler({ token: process.env.DOPPLER_TOKEN! });
|
|
11
|
+
* await dop.preload(["DATABASE_URL", "API_KEY"]);
|
|
12
|
+
*
|
|
13
|
+
* envx({ resolvers: { [dop.name]: dop.resolve } });
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Reference shape — IDs are Doppler secret names:
|
|
17
|
+
*
|
|
18
|
+
* ```
|
|
19
|
+
* DATABASE_URL=${doppler:DATABASE_URL}
|
|
20
|
+
* API_KEY=${doppler:API_KEY}
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* Service-account tokens scope to one config (project + environment),
|
|
24
|
+
* so you typically don't need to specify project/config explicitly.
|
|
25
|
+
*/
|
|
26
|
+
function doppler(opts) {
|
|
27
|
+
const name = opts.name ?? "doppler";
|
|
28
|
+
const endpoint = (opts.endpoint ?? "https://api.doppler.com").replace(/\/$/, "");
|
|
29
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
30
|
+
const auth = "Basic " + Buffer.from(`${opts.token}:`).toString("base64");
|
|
31
|
+
return buildProvider(name, async (id) => {
|
|
32
|
+
const url = `${endpoint}/v3/configs/config/secret?name=${encodeURIComponent(id)}`;
|
|
33
|
+
const r = await doFetch(url, { headers: {
|
|
34
|
+
Authorization: auth,
|
|
35
|
+
Accept: "application/json"
|
|
36
|
+
} });
|
|
37
|
+
if (!r.ok) {
|
|
38
|
+
const text = await r.text().catch(() => "");
|
|
39
|
+
throw new Error(`doppler GET ${url} → ${String(r.status)} ${r.statusText}${text ? `: ${text}` : ""}`);
|
|
40
|
+
}
|
|
41
|
+
const body = await r.json();
|
|
42
|
+
const v = body.value?.computed ?? body.value?.raw;
|
|
43
|
+
if (typeof v !== "string") throw new Error(`doppler: secret '${id}' missing value.computed/raw`);
|
|
44
|
+
return v;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { doppler as t };
|
|
49
|
+
|
|
50
|
+
//# sourceMappingURL=doppler-BkQsajIp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doppler-BkQsajIp.js","names":[],"sources":["../../src/plugins/doppler.ts"],"sourcesContent":["import { buildProvider, type SecretProvider } from \"./types.js\";\n\n// #region -- Doppler ---------------------------------------\n\nexport interface DopplerOptions {\n /** Doppler service token (per-config). Required. */\n readonly token: string;\n /** Override Doppler's REST endpoint (testing / self-hosted). */\n readonly endpoint?: string;\n /** Override the global fetch (testing). */\n readonly fetchImpl?: typeof fetch;\n /** Provider name, defaults to `\"doppler\"`. */\n readonly name?: string;\n}\n\n/**\n * Doppler provider — fetches secrets via the REST API using a service\n * token. No SDK install required (uses native `fetch`).\n *\n * ```ts\n * import { doppler } from \"@super-repo/envx/plugins/doppler\";\n *\n * const dop = doppler({ token: process.env.DOPPLER_TOKEN! });\n * await dop.preload([\"DATABASE_URL\", \"API_KEY\"]);\n *\n * envx({ resolvers: { [dop.name]: dop.resolve } });\n * ```\n *\n * Reference shape — IDs are Doppler secret names:\n *\n * ```\n * DATABASE_URL=${doppler:DATABASE_URL}\n * API_KEY=${doppler:API_KEY}\n * ```\n *\n * Service-account tokens scope to one config (project + environment),\n * so you typically don't need to specify project/config explicitly.\n */\nexport function doppler(opts: DopplerOptions): SecretProvider {\n const name = opts.name ?? \"doppler\";\n const endpoint = (opts.endpoint ?? \"https://api.doppler.com\").replace(/\\/$/, \"\");\n const doFetch = opts.fetchImpl ?? fetch;\n const auth = \"Basic \" + Buffer.from(`${opts.token}:`).toString(\"base64\");\n\n return buildProvider(name, async (id) => {\n const url = `${endpoint}/v3/configs/config/secret?name=${encodeURIComponent(id)}`;\n const r = await doFetch(url, {\n headers: { Authorization: auth, Accept: \"application/json\" },\n });\n if (!r.ok) {\n const text = await r.text().catch(() => \"\");\n throw new Error(\n `doppler GET ${url} → ${String(r.status)} ${r.statusText}${text ? `: ${text}` : \"\"}`,\n );\n }\n const body = (await r.json()) as {\n value?: { computed?: string; raw?: string };\n };\n const v = body.value?.computed ?? body.value?.raw;\n if (typeof v !== \"string\") {\n throw new Error(`doppler: secret '${id}' missing value.computed/raw`);\n }\n return v;\n });\n}\n\n// #endregion -----------------------------------------------\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,QAAQ,MAAsC;CAC5D,MAAM,OAAO,KAAK,QAAQ;CAC1B,MAAM,YAAY,KAAK,YAAY,2BAA2B,QAAQ,OAAO,GAAG;CAChF,MAAM,UAAU,KAAK,aAAa;CAClC,MAAM,OAAO,WAAW,OAAO,KAAK,GAAG,KAAK,MAAM,GAAG,CAAC,SAAS,SAAS;CAExE,OAAO,cAAc,MAAM,OAAO,OAAO;EACvC,MAAM,MAAM,GAAG,SAAS,iCAAiC,mBAAmB,GAAG;EAC/E,MAAM,IAAI,MAAM,QAAQ,KAAK,EAC3B,SAAS;GAAE,eAAe;GAAM,QAAQ;GAAoB,EAC7D,CAAC;EACF,IAAI,CAAC,EAAE,IAAI;GACT,MAAM,OAAO,MAAM,EAAE,MAAM,CAAC,YAAY,GAAG;GAC3C,MAAM,IAAI,MACR,eAAe,IAAI,KAAK,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,aAAa,OAAO,KAAK,SAAS,KACjF;;EAEH,MAAM,OAAQ,MAAM,EAAE,MAAM;EAG5B,MAAM,IAAI,KAAK,OAAO,YAAY,KAAK,OAAO;EAC9C,IAAI,OAAO,MAAM,UACf,MAAM,IAAI,MAAM,oBAAoB,GAAG,8BAA8B;EAEvE,OAAO;GACP"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { n as buildProvider, t as MissingSdkError } from "./types-COrFYR0z.js";
|
|
2
|
+
//#region src/plugins/gcp.ts
|
|
3
|
+
/**
|
|
4
|
+
* GCP Secret Manager provider.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { gcpSecrets } from "@super-repo/envx/plugins/gcp";
|
|
8
|
+
*
|
|
9
|
+
* const gcp = gcpSecrets({ projectId: "acme-prod" });
|
|
10
|
+
* await gcp.preload(["prod-db-url", "prod-api-key"]);
|
|
11
|
+
*
|
|
12
|
+
* envx({ resolvers: { [gcp.name]: gcp.resolve } });
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Reference shape:
|
|
16
|
+
*
|
|
17
|
+
* ```
|
|
18
|
+
* DB_URL=${gcp-secrets:prod-db-url} # uses default version (latest)
|
|
19
|
+
* API_KEY=${gcp-secrets:prod-api-key@3} # pin to version 3
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* Uses `@google-cloud/secret-manager` (lazy-loaded). Install:
|
|
23
|
+
*
|
|
24
|
+
* pnpm add @google-cloud/secret-manager
|
|
25
|
+
*/
|
|
26
|
+
function gcpSecrets(opts) {
|
|
27
|
+
const name = opts.name ?? "gcp-secrets";
|
|
28
|
+
const defaultVersion = opts.version ?? "latest";
|
|
29
|
+
let client = opts.client ?? null;
|
|
30
|
+
return buildProvider(name, async (id) => {
|
|
31
|
+
if (!client) try {
|
|
32
|
+
client = new (await (import(
|
|
33
|
+
/* @vite-ignore */
|
|
34
|
+
"@google-cloud/secret-manager"
|
|
35
|
+
))).SecretManagerServiceClient();
|
|
36
|
+
} catch {
|
|
37
|
+
throw new MissingSdkError("gcp", "@google-cloud/secret-manager");
|
|
38
|
+
}
|
|
39
|
+
const at = id.indexOf("@");
|
|
40
|
+
const secretId = at >= 0 ? id.slice(0, at) : id;
|
|
41
|
+
const version = at >= 0 ? id.slice(at + 1) : defaultVersion;
|
|
42
|
+
const fullName = `projects/${opts.projectId}/secrets/${secretId}/versions/${version}`;
|
|
43
|
+
const [response] = await client.accessSecretVersion({ name: fullName });
|
|
44
|
+
const data = response?.payload?.data;
|
|
45
|
+
if (data === null || data === void 0) throw new Error(`secret '${id}' had empty payload`);
|
|
46
|
+
if (typeof data === "string") return data;
|
|
47
|
+
return Buffer.from(data).toString("utf8");
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { gcpSecrets as t };
|
|
52
|
+
|
|
53
|
+
//# sourceMappingURL=gcp-Dq7QncPS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gcp-Dq7QncPS.js","names":[],"sources":["../../src/plugins/gcp.ts"],"sourcesContent":["import { buildProvider, MissingSdkError, type SecretProvider } from \"./types.js\";\n\n// #region -- GCP Secret Manager ----------------------------\n\nexport interface GcpSecretsOptions {\n /** Google Cloud project ID (e.g. \"acme-prod\"). */\n readonly projectId: string;\n /**\n * Default version alias. `\"latest\"` (the default) reads the most\n * recent enabled version. Override per-id by including `@<version>`\n * in the reference: `${gcp-secrets:my-secret@3}`.\n */\n readonly version?: string;\n /** Optional pre-built SecretManagerServiceClient (e.g. for tests). */\n readonly client?: {\n accessSecretVersion: (req: {\n name: string;\n }) => Promise<[{ payload?: { data?: Buffer | string | null } } | null, ...unknown[]]>;\n };\n /** Provider name, defaults to `\"gcp-secrets\"`. */\n readonly name?: string;\n}\n\n/**\n * GCP Secret Manager provider.\n *\n * ```ts\n * import { gcpSecrets } from \"@super-repo/envx/plugins/gcp\";\n *\n * const gcp = gcpSecrets({ projectId: \"acme-prod\" });\n * await gcp.preload([\"prod-db-url\", \"prod-api-key\"]);\n *\n * envx({ resolvers: { [gcp.name]: gcp.resolve } });\n * ```\n *\n * Reference shape:\n *\n * ```\n * DB_URL=${gcp-secrets:prod-db-url} # uses default version (latest)\n * API_KEY=${gcp-secrets:prod-api-key@3} # pin to version 3\n * ```\n *\n * Uses `@google-cloud/secret-manager` (lazy-loaded). Install:\n *\n * pnpm add @google-cloud/secret-manager\n */\nexport function gcpSecrets(opts: GcpSecretsOptions): SecretProvider {\n const name = opts.name ?? \"gcp-secrets\";\n const defaultVersion = opts.version ?? \"latest\";\n let client: GcpSecretsOptions[\"client\"] | null = opts.client ?? null;\n\n return buildProvider(name, async (id) => {\n if (!client) {\n try {\n interface GcpSdk {\n readonly SecretManagerServiceClient: new () => unknown;\n }\n const specifier = \"@google-cloud/secret-manager\";\n const sdk = (await import(/* @vite-ignore */ specifier)) as unknown as GcpSdk;\n client = new sdk.SecretManagerServiceClient() as unknown as GcpSecretsOptions[\"client\"];\n } catch {\n throw new MissingSdkError(\"gcp\", \"@google-cloud/secret-manager\");\n }\n }\n\n // `id` may include an `@<version>` suffix.\n const at = id.indexOf(\"@\");\n const secretId = at >= 0 ? id.slice(0, at) : id;\n const version = at >= 0 ? id.slice(at + 1) : defaultVersion;\n const fullName = `projects/${opts.projectId}/secrets/${secretId}/versions/${version}`;\n const [response] = await client!.accessSecretVersion({ name: fullName });\n const data = response?.payload?.data;\n if (data === null || data === undefined) {\n throw new Error(`secret '${id}' had empty payload`);\n }\n if (typeof data === \"string\") return data;\n return Buffer.from(data).toString(\"utf8\");\n });\n}\n\n// #endregion -----------------------------------------------\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,SAAgB,WAAW,MAAyC;CAClE,MAAM,OAAO,KAAK,QAAQ;CAC1B,MAAM,iBAAiB,KAAK,WAAW;CACvC,IAAI,SAA6C,KAAK,UAAU;CAEhE,OAAO,cAAc,MAAM,OAAO,OAAO;EACvC,IAAI,CAAC,QACH,IAAI;GAMF,SAAS,KAAI,OADM;;IAA0B;IAC5B,4BAA4B;UACvC;GACN,MAAM,IAAI,gBAAgB,OAAO,+BAA+B;;EAKpE,MAAM,KAAK,GAAG,QAAQ,IAAI;EAC1B,MAAM,WAAW,MAAM,IAAI,GAAG,MAAM,GAAG,GAAG,GAAG;EAC7C,MAAM,UAAU,MAAM,IAAI,GAAG,MAAM,KAAK,EAAE,GAAG;EAC7C,MAAM,WAAW,YAAY,KAAK,UAAU,WAAW,SAAS,YAAY;EAC5E,MAAM,CAAC,YAAY,MAAM,OAAQ,oBAAoB,EAAE,MAAM,UAAU,CAAC;EACxE,MAAM,OAAO,UAAU,SAAS;EAChC,IAAI,SAAS,QAAQ,SAAS,KAAA,GAC5B,MAAM,IAAI,MAAM,WAAW,GAAG,qBAAqB;EAErD,IAAI,OAAO,SAAS,UAAU,OAAO;EACrC,OAAO,OAAO,KAAK,KAAK,CAAC,SAAS,OAAO;GACzC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { n as buildProvider } from "./types-COrFYR0z.js";
|
|
2
|
+
//#region src/plugins/infisical.ts
|
|
3
|
+
/**
|
|
4
|
+
* Infisical provider — uses the v3 REST API with a service / machine
|
|
5
|
+
* identity token. No SDK install required (uses native `fetch`).
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { infisical } from "@super-repo/envx/plugins/infisical";
|
|
9
|
+
*
|
|
10
|
+
* const inf = infisical({
|
|
11
|
+
* token: process.env.INFISICAL_TOKEN!,
|
|
12
|
+
* projectId: process.env.INFISICAL_PROJECT_ID!,
|
|
13
|
+
* environment: "prod",
|
|
14
|
+
* });
|
|
15
|
+
* await inf.preload(["DATABASE_URL", "API_KEY"]);
|
|
16
|
+
*
|
|
17
|
+
* envx({ resolvers: { [inf.name]: inf.resolve } });
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* Reference shape — IDs are Infisical secret names:
|
|
21
|
+
*
|
|
22
|
+
* ```
|
|
23
|
+
* DATABASE_URL=${infisical:DATABASE_URL}
|
|
24
|
+
* API_KEY=${infisical:API_KEY}
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* Self-hosted? Pass `endpoint: "https://infisical.example.com"`.
|
|
28
|
+
*/
|
|
29
|
+
function infisical(opts) {
|
|
30
|
+
const name = opts.name ?? "infisical";
|
|
31
|
+
const endpoint = (opts.endpoint ?? "https://app.infisical.com").replace(/\/$/, "");
|
|
32
|
+
const secretPath = opts.secretPath ?? "/";
|
|
33
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
34
|
+
return buildProvider(name, async (id) => {
|
|
35
|
+
const params = new URLSearchParams({
|
|
36
|
+
workspaceId: opts.projectId,
|
|
37
|
+
environment: opts.environment,
|
|
38
|
+
secretPath
|
|
39
|
+
});
|
|
40
|
+
const url = `${endpoint}/api/v3/secrets/raw/${encodeURIComponent(id)}?${params.toString()}`;
|
|
41
|
+
const r = await doFetch(url, { headers: {
|
|
42
|
+
Authorization: `Bearer ${opts.token}`,
|
|
43
|
+
Accept: "application/json"
|
|
44
|
+
} });
|
|
45
|
+
if (!r.ok) {
|
|
46
|
+
const text = await r.text().catch(() => "");
|
|
47
|
+
throw new Error(`infisical GET ${url} → ${String(r.status)} ${r.statusText}${text ? `: ${text}` : ""}`);
|
|
48
|
+
}
|
|
49
|
+
const v = (await r.json()).secret?.secretValue;
|
|
50
|
+
if (typeof v !== "string") throw new Error(`infisical: secret '${id}' missing secret.secretValue`);
|
|
51
|
+
return v;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { infisical as t };
|
|
56
|
+
|
|
57
|
+
//# sourceMappingURL=infisical-CO073rdx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"infisical-CO073rdx.js","names":[],"sources":["../../src/plugins/infisical.ts"],"sourcesContent":["import { buildProvider, type SecretProvider } from \"./types.js\";\n\n// #region -- Infisical -------------------------------------\n\nexport interface InfisicalOptions {\n /**\n * Service token or universal-auth access token. Required. Pass a\n * universal-auth token from your machine identity flow, or a project\n * service token for simpler setups.\n */\n readonly token: string;\n /** Project ID (workspace ID, \"workspaceId\"). */\n readonly projectId: string;\n /** Environment slug — `dev`, `staging`, `prod`, etc. */\n readonly environment: string;\n /**\n * Folder path inside the environment. Defaults to `/`.\n */\n readonly secretPath?: string;\n /** Self-hosted Infisical endpoint. Defaults to the SaaS host. */\n readonly endpoint?: string;\n /** Override the global fetch (testing). */\n readonly fetchImpl?: typeof fetch;\n /** Provider name, defaults to `\"infisical\"`. */\n readonly name?: string;\n}\n\n/**\n * Infisical provider — uses the v3 REST API with a service / machine\n * identity token. No SDK install required (uses native `fetch`).\n *\n * ```ts\n * import { infisical } from \"@super-repo/envx/plugins/infisical\";\n *\n * const inf = infisical({\n * token: process.env.INFISICAL_TOKEN!,\n * projectId: process.env.INFISICAL_PROJECT_ID!,\n * environment: \"prod\",\n * });\n * await inf.preload([\"DATABASE_URL\", \"API_KEY\"]);\n *\n * envx({ resolvers: { [inf.name]: inf.resolve } });\n * ```\n *\n * Reference shape — IDs are Infisical secret names:\n *\n * ```\n * DATABASE_URL=${infisical:DATABASE_URL}\n * API_KEY=${infisical:API_KEY}\n * ```\n *\n * Self-hosted? Pass `endpoint: \"https://infisical.example.com\"`.\n */\nexport function infisical(opts: InfisicalOptions): SecretProvider {\n const name = opts.name ?? \"infisical\";\n const endpoint = (opts.endpoint ?? \"https://app.infisical.com\").replace(/\\/$/, \"\");\n const secretPath = opts.secretPath ?? \"/\";\n const doFetch = opts.fetchImpl ?? fetch;\n\n return buildProvider(name, async (id) => {\n const params = new URLSearchParams({\n workspaceId: opts.projectId,\n environment: opts.environment,\n secretPath,\n });\n const url = `${endpoint}/api/v3/secrets/raw/${encodeURIComponent(id)}?${params.toString()}`;\n const r = await doFetch(url, {\n headers: {\n Authorization: `Bearer ${opts.token}`,\n Accept: \"application/json\",\n },\n });\n if (!r.ok) {\n const text = await r.text().catch(() => \"\");\n throw new Error(\n `infisical GET ${url} → ${String(r.status)} ${r.statusText}${text ? `: ${text}` : \"\"}`,\n );\n }\n const body = (await r.json()) as {\n secret?: { secretValue?: string };\n };\n const v = body.secret?.secretValue;\n if (typeof v !== \"string\") {\n throw new Error(`infisical: secret '${id}' missing secret.secretValue`);\n }\n return v;\n });\n}\n\n// #endregion -----------------------------------------------\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDA,SAAgB,UAAU,MAAwC;CAChE,MAAM,OAAO,KAAK,QAAQ;CAC1B,MAAM,YAAY,KAAK,YAAY,6BAA6B,QAAQ,OAAO,GAAG;CAClF,MAAM,aAAa,KAAK,cAAc;CACtC,MAAM,UAAU,KAAK,aAAa;CAElC,OAAO,cAAc,MAAM,OAAO,OAAO;EACvC,MAAM,SAAS,IAAI,gBAAgB;GACjC,aAAa,KAAK;GAClB,aAAa,KAAK;GAClB;GACD,CAAC;EACF,MAAM,MAAM,GAAG,SAAS,sBAAsB,mBAAmB,GAAG,CAAC,GAAG,OAAO,UAAU;EACzF,MAAM,IAAI,MAAM,QAAQ,KAAK,EAC3B,SAAS;GACP,eAAe,UAAU,KAAK;GAC9B,QAAQ;GACT,EACF,CAAC;EACF,IAAI,CAAC,EAAE,IAAI;GACT,MAAM,OAAO,MAAM,EAAE,MAAM,CAAC,YAAY,GAAG;GAC3C,MAAM,IAAI,MACR,iBAAiB,IAAI,KAAK,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,aAAa,OAAO,KAAK,SAAS,KACnF;;EAKH,MAAM,KAAI,MAHU,EAAE,MAAM,EAGb,QAAQ;EACvB,IAAI,OAAO,MAAM,UACf,MAAM,IAAI,MAAM,sBAAsB,GAAG,8BAA8B;EAEzE,OAAO;GACP"}
|
|
Binary file
|