@envctrl/cli 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -503,6 +503,7 @@ var EncryptBaseCommand = class extends BaseCommand {
503
503
  import fs10 from "fs/promises";
504
504
  import os3 from "os";
505
505
  import path9 from "path";
506
+ import { createInterface } from "readline/promises";
506
507
 
507
508
  // src/commands/init/workspace.ts
508
509
  import fs8 from "fs/promises";
@@ -643,6 +644,33 @@ async function writeConfig(cwd, config, dir = ".envctrl", file = "config.json")
643
644
  }
644
645
 
645
646
  // src/commands/init/index.ts
647
+ async function isInsideGitRepo(dir) {
648
+ let current = dir;
649
+ while (true) {
650
+ try {
651
+ await fs10.access(path9.join(current, ".git"));
652
+ return true;
653
+ } catch {
654
+ }
655
+ const parent = path9.dirname(current);
656
+ if (parent === current) return false;
657
+ current = parent;
658
+ }
659
+ }
660
+ async function appendGitignorePatterns(rootDir, patterns) {
661
+ const gitignorePath = path9.join(rootDir, ".gitignore");
662
+ let existing = "";
663
+ try {
664
+ existing = await fs10.readFile(gitignorePath, "utf8");
665
+ } catch {
666
+ }
667
+ const toAdd = patterns.filter((p) => !existing.includes(p));
668
+ if (toAdd.length === 0) return false;
669
+ const separator = existing === "" || existing.endsWith("\n") ? "" : "\n";
670
+ await fs10.writeFile(gitignorePath, `${existing}${separator}${toAdd.join("\n")}
671
+ `, "utf8");
672
+ return true;
673
+ }
646
674
  var InitCommand = class {
647
675
  /** @inheritdoc */
648
676
  async execute(options, context) {
@@ -700,6 +728,24 @@ var InitCommand = class {
700
728
  configDir,
701
729
  configFile
702
730
  );
731
+ let gitignoreUpdated = false;
732
+ if (!context.quiet) {
733
+ const inGit = await isInsideGitRepo(workspaceRoot);
734
+ if (inGit) {
735
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
736
+ try {
737
+ const answer = await rl.question("Configure .gitignore for envctrl? [y/N] ");
738
+ if (answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes") {
739
+ gitignoreUpdated = await appendGitignorePatterns(workspaceRoot, [
740
+ "# envctrl: unencrypted env files",
741
+ ".env.*.unencrypted"
742
+ ]);
743
+ }
744
+ } finally {
745
+ rl.close();
746
+ }
747
+ }
748
+ }
703
749
  const lines = [`Workspace: ${workspaceRoot}`, `Keystore: ${keystorePath}`];
704
750
  if (packages.length > 0) {
705
751
  lines.push("Packages:");
@@ -713,9 +759,12 @@ var InitCommand = class {
713
759
  `Config: ${configPath}`,
714
760
  `Environment: ${environment}${autoDetected ? ` (auto-detected from ${buildEnv.provider})` : ""}`
715
761
  );
762
+ if (gitignoreUpdated) {
763
+ lines.push(`Updated: ${path9.join(workspaceRoot, ".gitignore")}`);
764
+ }
716
765
  return {
717
766
  success: true,
718
- data: { workspaceRoot, packages, keystorePath, keysLinked, configPath, environment, autoDetected },
767
+ data: { workspaceRoot, packages, keystorePath, keysLinked, configPath, environment, autoDetected, gitignoreUpdated },
719
768
  message: lines.join("\n")
720
769
  };
721
770
  } catch (err) {
@@ -955,7 +1004,7 @@ var BlacklistBaseCommand = class extends BaseCommand {
955
1004
  import fs13 from "fs/promises";
956
1005
  import os4 from "os";
957
1006
  import path13 from "path";
958
- import { createInterface } from "readline/promises";
1007
+ import { createInterface as createInterface2 } from "readline/promises";
959
1008
  async function listExistingEnvironments(cwd) {
960
1009
  const files = listEnvFiles(cwd, ".env.*", [".env.keys"]);
961
1010
  const names = files.map((f) => parseEnvironmentFromFilename(path13.basename(f))).filter((e) => e !== void 0);
@@ -968,9 +1017,18 @@ async function buildExampleContent(unencryptedPath) {
968
1017
  } catch {
969
1018
  return "";
970
1019
  }
971
- const entries = parseEnvContent(raw);
972
- const lines = Object.keys(entries).map((k) => `${k}=`);
973
- return lines.length > 0 ? lines.join("\n") + "\n" : "";
1020
+ const result = raw.split("\n").map((line) => {
1021
+ const trimmed = line.trim();
1022
+ if (!trimmed || trimmed.startsWith("#")) {
1023
+ return line;
1024
+ }
1025
+ const eqIdx = trimmed.indexOf("=");
1026
+ if (eqIdx === -1) {
1027
+ return line;
1028
+ }
1029
+ return `${trimmed.slice(0, eqIdx).trim()}=`;
1030
+ });
1031
+ return result.join("\n");
974
1032
  }
975
1033
  var CreateCommand = class {
976
1034
  /** @inheritdoc */
@@ -1005,7 +1063,7 @@ var CreateCommand = class {
1005
1063
  error: 'No environments found. Create one first with "envctrl create <environment>".'
1006
1064
  };
1007
1065
  }
1008
- const rl = createInterface({ input: process.stdin, output: process.stdout });
1066
+ const rl = createInterface2({ input: process.stdin, output: process.stdout });
1009
1067
  try {
1010
1068
  base = await rl.question(
1011
1069
  `Choose a base environment [${existing.join(", ")}]: `
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/switch/index.ts","../src/base-command.ts","../src/utils/env-files.ts","../src/utils/dotenvx.ts","../src/commands/switch/sync.ts","../src/commands/keystore/create.ts","../src/utils/platform.ts","../src/commands/keystore/registry.ts","../src/commands/keystore/list.ts","../src/commands/keystore/delete.ts","../src/commands/keystore/index.ts","../src/commands/set/index.ts","../src/commands/encrypt/index.ts","../src/commands/init/index.ts","../src/commands/init/workspace.ts","../src/utils/build-env.ts","../src/utils/config.ts","../src/commands/list/index.ts","../src/utils/blacklist.ts","../src/commands/rm/index.ts","../src/commands/blacklist/index.ts","../src/commands/create/index.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { Command } from 'commander';\nimport { SwitchBaseCommand } from './commands/switch/index.js';\nimport { KeystoreBaseCommand } from './commands/keystore/index.js';\nimport { SetBaseCommand } from './commands/set/index.js';\nimport { EncryptBaseCommand } from './commands/encrypt/index.js';\nimport { InitBaseCommand } from './commands/init/index.js';\nimport { ListBaseCommand } from './commands/list/index.js';\nimport { RmBaseCommand } from './commands/rm/index.js';\nimport { BlacklistBaseCommand } from './commands/blacklist/index.js';\nimport { CreateBaseCommand } from './commands/create/index.js';\n\nconst _require = createRequire(import.meta.url);\nconst { version } = _require('../package.json') as { version: string };\n\nconst program = new Command();\n\nprogram\n .name('envctrl')\n .description('Encrypted environment file manager built on dotenvx')\n .version(version)\n .addHelpText('beforeAll', `envctrl v${version}\\n`)\n .option('-q, --quiet', 'suppress output', false);\n\nnew InitBaseCommand().register(program);\nnew CreateBaseCommand().register(program);\nnew ListBaseCommand().register(program);\nnew SwitchBaseCommand().register(program);\nnew KeystoreBaseCommand().register(program);\nnew SetBaseCommand().register(program);\nnew EncryptBaseCommand().register(program);\nnew RmBaseCommand().register(program);\nnew BlacklistBaseCommand().register(program);\n\nprogram.parseAsync(process.argv);\n","import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport type { Command } from 'commander';\nimport type { CommandContext, CommandResult, ISubCommand, SwitchResult } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { buildEnvFilePair } from '../../utils/env-files.js';\nimport { setKeyValue } from '../../utils/dotenvx.js';\nimport { syncUnencryptedToEncrypted } from './sync.js';\n\n/** Options parsed by Commander for the `switch` subcommand. */\ninterface SwitchOptions {\n environment: string;\n}\n\n/**\n * Switches the active environment.\n *\n * Creates `.env.[env].unencrypted` and `.env.[env]` if they do not exist,\n * syncs keys from the unencrypted source into the encrypted file, and\n * points `.env` at the encrypted file via symlink (POSIX) or copy (Windows).\n */\nexport class SwitchCommand implements ISubCommand<SwitchOptions, SwitchResult> {\n /** @inheritdoc */\n async execute(\n options: SwitchOptions,\n context: CommandContext,\n ): Promise<CommandResult<SwitchResult>> {\n const { environment, cwd } = { ...options, cwd: context.cwd };\n const pair = buildEnvFilePair(environment, cwd);\n const created: string[] = [];\n\n try {\n try {\n await fs.access(pair.unencrypted);\n } catch {\n await fs.writeFile(pair.unencrypted, '', 'utf8');\n created.push(pair.unencrypted);\n }\n\n const encryptedExists = await fs\n .access(pair.encrypted)\n .then(() => true)\n .catch(() => false);\n\n await syncUnencryptedToEncrypted(environment, cwd);\n\n if (!encryptedExists) {\n const stillMissing = await fs\n .access(pair.encrypted)\n .then(() => false)\n .catch(() => true);\n\n if (stillMissing) {\n setKeyValue('_ENVCTRL_INIT', '1', pair.encrypted);\n created.push(pair.encrypted);\n } else {\n created.push(pair.encrypted);\n }\n }\n\n const activePath = path.resolve(cwd, '.env');\n\n try {\n await fs.unlink(activePath);\n } catch {}\n\n if (os.platform() === 'win32') {\n await fs.copyFile(pair.encrypted, activePath);\n } else {\n await fs.symlink(pair.encrypted, activePath);\n }\n\n const lines = [`Switched to: ${environment}`];\n if (created.length > 0) {\n lines.push('Created:', ...created.map((f) => ` ${f}`));\n }\n\n return {\n success: true,\n data: { environment, created, activePath },\n message: lines.join('\\n'),\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/** Registers the `switch [environment]` command onto the Commander program. */\nexport class SwitchBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('switch <environment>')\n .description('Create, sync, and activate a named environment (.env.[env])')\n .action(async (environment: string) => {\n await this.dispatch(new SwitchCommand(), { environment }, this.buildContext(program));\n });\n }\n}\n","import type { Command } from 'commander';\nimport type { CommandContext, CommandResult, ISubCommand } from '@envctrl/types';\n\n/**\n * Abstract base for all top-level CLI commands.\n *\n * Subclasses implement {@link register} to attach their Commander subcommand\n * to the program. The {@link dispatch} helper handles uniform result\n * printing and process exit on failure.\n */\nexport abstract class BaseCommand {\n /**\n * Attaches this command's Commander definition onto `program`.\n *\n * @param program - The root Commander program instance\n */\n abstract register(program: Command): void;\n\n /**\n * Executes a subcommand and handles the result.\n *\n * Prints the error message to stderr and exits with code 1 on failure.\n * Prints `result.message` to stdout on success when `context.quiet` is false.\n *\n * @param cmd - The subcommand to execute\n * @param options - Parsed options from Commander\n * @param context - Injected runtime context\n */\n protected async dispatch<TOptions, TResult>(\n cmd: ISubCommand<TOptions, TResult>,\n options: TOptions,\n context: CommandContext,\n ): Promise<void> {\n const result: CommandResult<TResult> = await cmd.execute(options, context);\n\n if (!result.success) {\n process.stderr.write(`error: ${result.error ?? 'unknown error'}\\n`);\n process.exit(1);\n }\n\n if (!context.quiet && result.message !== undefined) {\n process.stdout.write(result.message + '\\n');\n }\n }\n\n /**\n * Builds a {@link CommandContext} from the Commander program's global options.\n *\n * @param program - The root Commander program instance\n */\n protected buildContext(program: Command): CommandContext {\n const opts = program.opts<{ quiet?: boolean }>();\n return {\n cwd: process.cwd(),\n quiet: opts.quiet ?? false,\n };\n }\n}\n","import path from 'node:path';\nimport type { EnvFilePair, EnvironmentName } from '@envctrl/types';\n\nconst RESERVED_ENV_NAMES = new Set(['keys', 'example']);\n\n/**\n * Derives the environment name from a `.env.*` filename, stripping `.unencrypted`\n * and `.local` suffixes. Returns `undefined` for reserved filenames like\n * `.env.keys` and `.env.example`.\n */\nexport function parseEnvironmentFromFilename(filename: string): EnvironmentName | undefined {\n const base = path.basename(filename);\n\n if (!base.startsWith('.env.')) {\n return undefined;\n }\n\n const withoutPrefix = base.slice('.env.'.length);\n\n if (!withoutPrefix || RESERVED_ENV_NAMES.has(withoutPrefix)) {\n return undefined;\n }\n\n let name = withoutPrefix.endsWith('.unencrypted')\n ? withoutPrefix.slice(0, -'.unencrypted'.length)\n : withoutPrefix;\n\n if (name.endsWith('.local')) {\n name = name.slice(0, -'.local'.length);\n }\n\n if (!name || RESERVED_ENV_NAMES.has(name)) {\n return undefined;\n }\n\n return name;\n}\n\n/**\n * Builds the {@link EnvFilePair} for a given environment name and working directory.\n *\n * @param environment - The environment name, e.g. `\"production\"`\n * @param cwd - The working directory that will contain the env files\n */\nexport function buildEnvFilePair(environment: EnvironmentName, cwd: string): EnvFilePair {\n return {\n environment,\n unencrypted: path.resolve(cwd, `.env.${environment}.unencrypted`),\n encrypted: path.resolve(cwd, `.env.${environment}`),\n };\n}\n\n/**\n * Parses KEY=VALUE pairs from a plaintext `.env` file string.\n *\n * Skips blank lines and comment lines starting with `#`.\n *\n * @param content - Raw file content\n */\nexport function parseEnvContent(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n\n if (!trimmed || trimmed.startsWith('#')) {\n continue;\n }\n\n const eqIdx = trimmed.indexOf('=');\n if (eqIdx === -1) {\n continue;\n }\n\n const key = trimmed.slice(0, eqIdx).trim();\n const value = trimmed.slice(eqIdx + 1).trim();\n result[key] = value;\n }\n\n return result;\n}\n\n/**\n * Writes or updates a single `KEY=VALUE` line in a plaintext env file string.\n *\n * If the key already exists its line is replaced in-place; otherwise the\n * entry is appended.\n *\n * @param content - Current raw file content\n * @param key - The environment variable name\n * @param value - The new value\n */\nexport function upsertEnvLine(content: string, key: string, value: string): string {\n const lines = content.split('\\n');\n const pattern = new RegExp(`^${key}\\\\s*=`);\n let replaced = false;\n\n const updated = lines.map((line) => {\n if (pattern.test(line)) {\n replaced = true;\n return `${key}=${value}`;\n }\n return line;\n });\n\n if (!replaced) {\n if (updated[updated.length - 1] !== '') {\n updated.push(`${key}=${value}`);\n } else {\n updated.splice(updated.length - 1, 0, `${key}=${value}`);\n }\n }\n\n return updated.join('\\n');\n}\n","import { createRequire } from 'node:module';\nimport path from 'node:path';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport * as dotenvx from '@dotenvx/dotenvx';\nimport type { DotenvxEncryptResult, DotenvxSetResult } from '@envctrl/types';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Resolves the path to the dotenvx CLI entry script from the installed package.\n *\n * Reads the `bin` field from the package's own `package.json` to avoid\n * hardcoding the path, which can change across dotenvx versions.\n */\nfunction resolveDotenvxBin(): string {\n const require = createRequire(import.meta.url);\n const pkgJsonPath = require.resolve('@dotenvx/dotenvx/package.json');\n const pkgJson = require('@dotenvx/dotenvx/package.json') as {\n bin: Record<string, string>;\n };\n const binRelPath = pkgJson.bin['dotenvx'];\n return path.resolve(path.dirname(pkgJsonPath), binRelPath);\n}\n\n/**\n * Sets a single key-value pair in an encrypted env file using the dotenvx JS API.\n *\n * @param key - The environment variable name\n * @param value - The value to set\n * @param encryptedFilePath - Absolute path to the target `.env.[env]` file\n * @param keysFilePath - Optional path to the `.env.keys` file\n */\nexport function setKeyValue(\n key: string,\n value: string,\n encryptedFilePath: string,\n keysFilePath?: string,\n): DotenvxSetResult {\n const output = dotenvx.set(key, value, {\n path: encryptedFilePath,\n encrypt: true,\n quiet: true,\n ...(keysFilePath ? { envKeysFile: keysFilePath } : {}),\n });\n\n return {\n changedFilepaths: output.changedFilepaths,\n unchangedFilepaths: output.unchangedFilepaths,\n };\n}\n\n/**\n * Encrypts an existing plaintext env file in-place using the dotenvx CLI.\n *\n * Spawns the bundled `dotenvx encrypt -f <filePath>` process. The CLI\n * handles creating or updating the corresponding `.env.keys` entry.\n *\n * @param filePath - Absolute path to the plaintext `.env.*` file to encrypt\n */\nexport async function encryptFile(filePath: string): Promise<DotenvxEncryptResult> {\n const bin = resolveDotenvxBin();\n await execFileAsync(process.execPath, [bin, 'encrypt', '-f', filePath]);\n\n return {\n changedFilepaths: [filePath],\n unchangedFilepaths: [],\n };\n}\n\n/**\n * Lists env files in a directory using the dotenvx JS API.\n *\n * @param directory - Directory to scan\n * @param include - Glob pattern(s) to include\n * @param exclude - Glob pattern(s) to exclude\n */\nexport function listEnvFiles(\n directory: string,\n include: string | string[],\n exclude: string | string[],\n): string[] {\n return dotenvx.ls(directory, include, exclude);\n}\n","import fs from 'node:fs/promises';\nimport { parseEnvContent, buildEnvFilePair } from '../../utils/env-files.js';\nimport { setKeyValue } from '../../utils/dotenvx.js';\nimport type { EnvironmentName } from '@envctrl/types';\n\n/**\n * Syncs all keys from the unencrypted file into the encrypted file.\n *\n * Reads the plaintext `.env.[env].unencrypted` file and calls dotenvx `set`\n * for each key so the encrypted counterpart stays in sync.\n *\n * @param environment - The environment name\n * @param cwd - Working directory containing the env files\n */\nexport async function syncUnencryptedToEncrypted(\n environment: EnvironmentName,\n cwd: string,\n): Promise<void> {\n const pair = buildEnvFilePair(environment, cwd);\n\n let content: string;\n try {\n content = await fs.readFile(pair.unencrypted, 'utf8');\n } catch {\n return;\n }\n\n const entries = parseEnvContent(content);\n\n for (const [key, value] of Object.entries(entries)) {\n setKeyValue(key, value, pair.encrypted);\n }\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { CommandContext, CommandResult, ISubCommand, KeystoreConfig } from '@envctrl/types';\nimport { resolveDefaultKeystorePath, resolveKeystoresRegistryPath } from '../../utils/platform.js';\nimport { readRegistry, writeRegistry } from './registry.js';\n\n/** Options parsed by Commander for `keystore create`. */\nexport interface KeystoreCreateOptions {\n keystorePath: string | undefined;\n name: string | undefined;\n}\n\n/**\n * Creates a new keystore directory and registers it in the global registry.\n *\n * If no path is provided, defaults to the platform-appropriate application\n * data directory. An empty `.env.keys` stub is written on first creation.\n */\nexport class KeystoreCreateSubCommand implements ISubCommand<\n KeystoreCreateOptions,\n KeystoreConfig\n> {\n /** @inheritdoc */\n async execute(\n options: KeystoreCreateOptions,\n _context: CommandContext,\n ): Promise<CommandResult<KeystoreConfig>> {\n const keystorePath = options.keystorePath ?? resolveDefaultKeystorePath();\n const name = options.name ?? path.basename(keystorePath);\n\n try {\n await fs.mkdir(keystorePath, { recursive: true });\n\n const keysFile = path.join(keystorePath, '.env.keys');\n try {\n await fs.access(keysFile);\n } catch {\n await fs.writeFile(keysFile, '# dotenvx keys\\n', 'utf8');\n }\n\n const registryPath = resolveKeystoresRegistryPath();\n await fs.mkdir(path.dirname(registryPath), { recursive: true });\n\n const registry = await readRegistry(registryPath);\n const exists = registry.some((e) => e.name === name || e.path === keystorePath);\n\n if (!exists) {\n registry.push({ name, path: keystorePath });\n await writeRegistry(registryPath, registry);\n }\n\n return {\n success: true,\n data: { path: keystorePath },\n message: `Keystore created at: ${keystorePath}`,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n","import os from 'node:os';\nimport path from 'node:path';\n\n/**\n * Resolves the envctrl application data root directory for the current platform.\n *\n * - Linux: `$XDG_DATA_HOME/envctrl` or `~/.local/share/envctrl`\n * - macOS: `~/Library/Application Support/envctrl`\n * - Windows: `%APPDATA%\\envctrl`\n */\nfunction resolveAppDataRoot(): string {\n const platform = os.platform();\n const home = os.homedir();\n\n if (platform === 'win32') {\n const appData = process.env['APPDATA'] ?? path.join(home, 'AppData', 'Roaming');\n return path.join(appData, 'envctrl');\n }\n\n if (platform === 'darwin') {\n return path.join(home, 'Library', 'Application Support', 'envctrl');\n }\n\n const xdgDataHome = process.env['XDG_DATA_HOME'] ?? path.join(home, '.local', 'share');\n return path.join(xdgDataHome, 'envctrl');\n}\n\n/**\n * Resolves the default keystore directory.\n *\n * Placed inside a `keystores/default` subdirectory of the app data root\n * so that the registry JSON file at the root level is never deleted when\n * the default keystore is removed.\n */\nexport function resolveDefaultKeystorePath(): string {\n return path.join(resolveAppDataRoot(), 'keystores', 'default');\n}\n\n/**\n * Returns the path to the global keystores registry JSON file.\n *\n * Stored at the app data root, outside any individual keystore directory,\n * so it survives keystore deletion.\n */\nexport function resolveKeystoresRegistryPath(): string {\n return path.join(resolveAppDataRoot(), 'keystores.json');\n}\n\n/** Returns the path to the blacklist JSON file. */\nexport function resolveBlacklistPath(): string {\n return path.join(resolveAppDataRoot(), 'blacklist.json');\n}\n","import fs from 'node:fs/promises';\nimport type { KeystoreEntry } from '@envctrl/types';\n\n/**\n * Reads the keystores registry JSON file.\n *\n * Returns an empty array if the file does not exist yet.\n *\n * @param registryPath - Absolute path to the `keystores.json` file\n */\nexport async function readRegistry(registryPath: string): Promise<KeystoreEntry[]> {\n try {\n const raw = await fs.readFile(registryPath, 'utf8');\n return JSON.parse(raw) as KeystoreEntry[];\n } catch {\n return [];\n }\n}\n\n/**\n * Writes the keystores registry to disk.\n *\n * @param registryPath - Absolute path to the `keystores.json` file\n * @param entries - Array of keystore entries to persist\n */\nexport async function writeRegistry(registryPath: string, entries: KeystoreEntry[]): Promise<void> {\n await fs.writeFile(registryPath, JSON.stringify(entries, null, 2) + '\\n', 'utf8');\n}\n","import type { CommandContext, CommandResult, ISubCommand, KeystoreEntry } from '@envctrl/types';\nimport { resolveKeystoresRegistryPath } from '../../utils/platform.js';\nimport { readRegistry } from './registry.js';\n\n/**\n * Lists all registered keystores from the global registry.\n *\n * Returns an empty array if no keystores have been created yet.\n */\nexport class KeystoreListSubCommand implements ISubCommand<Record<string, never>, KeystoreEntry[]> {\n /** @inheritdoc */\n async execute(\n _options: Record<string, never>,\n _context: CommandContext,\n ): Promise<CommandResult<KeystoreEntry[]>> {\n try {\n const registryPath = resolveKeystoresRegistryPath();\n const entries = await readRegistry(registryPath);\n\n let message: string;\n if (entries.length === 0) {\n message = 'No keystores registered.';\n } else {\n const maxLen = Math.max(...entries.map((e) => e.name.length));\n message = entries.map((e) => `${e.name.padEnd(maxLen)} ${e.path}`).join('\\n');\n }\n\n return { success: true, data: entries, message };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n","import fs from 'node:fs/promises';\nimport type { CommandContext, CommandResult, ISubCommand, KeystoreEntry } from '@envctrl/types';\nimport { resolveKeystoresRegistryPath } from '../../utils/platform.js';\nimport { readRegistry, writeRegistry } from './registry.js';\n\n/** Options parsed by Commander for `keystore delete`. */\nexport interface KeystoreDeleteOptions {\n name: string;\n force: boolean;\n}\n\n/**\n * Deletes a named keystore directory and removes its entry from the registry.\n *\n * Requires `--force` flag to skip the confirmation guard. Without it,\n * the command exits early with a descriptive error.\n */\nexport class KeystoreDeleteSubCommand implements ISubCommand<KeystoreDeleteOptions, KeystoreEntry> {\n /** @inheritdoc */\n async execute(\n options: KeystoreDeleteOptions,\n _context: CommandContext,\n ): Promise<CommandResult<KeystoreEntry>> {\n const { name, force } = options;\n\n try {\n const registryPath = resolveKeystoresRegistryPath();\n const registry = await readRegistry(registryPath);\n const entry = registry.find((e) => e.name === name);\n\n if (!entry) {\n return {\n success: false,\n error: `keystore \"${name}\" not found in registry`,\n };\n }\n\n if (!force) {\n return {\n success: false,\n error: `pass --force to confirm deletion of keystore \"${name}\" at ${entry.path}`,\n };\n }\n\n const updated = registry.filter((e) => e.name !== name);\n await writeRegistry(registryPath, updated);\n\n await fs.rm(entry.path, { recursive: true, force: true });\n\n return {\n success: true,\n data: entry,\n message: `Deleted keystore: ${entry.name} (${entry.path})`,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n","import type { Command } from 'commander';\nimport { BaseCommand } from '../../base-command.js';\nimport { KeystoreCreateSubCommand } from './create.js';\nimport { KeystoreListSubCommand } from './list.js';\nimport { KeystoreDeleteSubCommand } from './delete.js';\n\n/** Registers the `keystore` command group onto the Commander program. */\nexport class KeystoreBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n const keystoreCmd = program\n .command('keystore')\n .description('Manage keystore directories for dotenvx private keys');\n\n keystoreCmd\n .command('create [path]')\n .description('Create a new keystore (defaults to platform app data folder)')\n .option('-n, --name <name>', 'name for the keystore entry in the registry')\n .action(async (keystorePath: string | undefined, opts: { name?: string }) => {\n await this.dispatch(\n new KeystoreCreateSubCommand(),\n { keystorePath, name: opts.name },\n this.buildContext(program),\n );\n });\n\n keystoreCmd\n .command('list')\n .description('List all registered keystores')\n .action(async () => {\n await this.dispatch(new KeystoreListSubCommand(), {}, this.buildContext(program));\n });\n\n keystoreCmd\n .command('delete <name>')\n .description('Delete a named keystore and remove it from the registry')\n .option('--force', 'skip confirmation and delete immediately', false)\n .action(async (name: string, opts: { force: boolean }) => {\n await this.dispatch(\n new KeystoreDeleteSubCommand(),\n { name, force: opts.force },\n this.buildContext(program),\n );\n });\n }\n}\n","import fs from 'node:fs/promises';\nimport type { Command } from 'commander';\nimport type { CommandContext, CommandResult, ISubCommand, SetResult } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { buildEnvFilePair, upsertEnvLine } from '../../utils/env-files.js';\nimport { setKeyValue } from '../../utils/dotenvx.js';\n\n/** Options parsed by Commander for the `set` subcommand. */\ninterface SetOptions {\n environment: string;\n key: string;\n value: string;\n}\n\n/**\n * Sets a single environment variable in both the unencrypted and encrypted files.\n *\n * Writes the key to the plaintext `.env.[env].unencrypted` file first to\n * maintain human-readable source of truth, then calls dotenvx `set` to\n * write and encrypt the value in `.env.[env]`.\n */\nexport class SetCommand implements ISubCommand<SetOptions, SetResult> {\n /** @inheritdoc */\n async execute(options: SetOptions, context: CommandContext): Promise<CommandResult<SetResult>> {\n const { environment, key, value } = options;\n const pair = buildEnvFilePair(environment, context.cwd);\n\n try {\n let existingContent = '';\n try {\n existingContent = await fs.readFile(pair.unencrypted, 'utf8');\n } catch {}\n\n const updatedContent = upsertEnvLine(existingContent, key, value);\n await fs.writeFile(pair.unencrypted, updatedContent, 'utf8');\n\n const result = setKeyValue(key, value, pair.encrypted);\n const changed = result.changedFilepaths.length > 0;\n\n return {\n success: true,\n data: { environment, key, changed },\n message: `Set ${key} in ${environment}`,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/** Registers the `set <environment> <key> <value>` command onto the Commander program. */\nexport class SetBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('set <environment> <key> <value>')\n .description('Set an environment variable and sync it to the encrypted file')\n .action(async (environment: string, key: string, value: string) => {\n await this.dispatch(\n new SetCommand(),\n { environment, key, value },\n this.buildContext(program),\n );\n });\n }\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Command } from 'commander';\nimport type { CommandContext, CommandResult, EncryptResult, ISubCommand } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { parseEnvironmentFromFilename } from '../../utils/env-files.js';\nimport { listEnvFiles, encryptFile } from '../../utils/dotenvx.js';\n\n/** Options parsed by Commander for the `encrypt` subcommand. */\ninterface EncryptOptions {\n files: string[];\n}\n\n/**\n * Encrypts existing plaintext `.env.*` files using dotenvx, backing up each file's\n * content to `.env.[env].unencrypted` before encrypting in-place.\n * Defaults to all `.env.*` files in the working directory when no files are specified.\n */\nexport class EncryptCommand implements ISubCommand<EncryptOptions, EncryptResult> {\n /** @inheritdoc */\n async execute(\n options: EncryptOptions,\n context: CommandContext,\n ): Promise<CommandResult<EncryptResult>> {\n const { cwd } = context;\n\n try {\n const targets =\n options.files.length > 0\n ? options.files.map((f) => path.resolve(cwd, f))\n : listEnvFiles(cwd, '.env.*', ['.env.keys', '*.unencrypted']);\n\n const changedFiles: string[] = [];\n const unchangedFiles: string[] = [];\n\n for (const filePath of targets) {\n const basename = path.basename(filePath);\n const environment = parseEnvironmentFromFilename(basename);\n\n if (!environment) {\n unchangedFiles.push(filePath);\n continue;\n }\n\n const unencryptedPath = path.resolve(\n path.dirname(filePath),\n `.env.${environment}.unencrypted`,\n );\n\n try {\n const content = await fs.readFile(filePath, 'utf8');\n\n try {\n await fs.access(unencryptedPath);\n } catch {\n await fs.writeFile(unencryptedPath, content, 'utf8');\n }\n\n const result = await encryptFile(filePath);\n changedFiles.push(...result.changedFilepaths);\n } catch {\n unchangedFiles.push(filePath);\n }\n }\n\n const lines: string[] = [\n ...changedFiles.map((f) => `Encrypted: ${f}`),\n ...unchangedFiles.map((f) => `Unchanged: ${f}`),\n ];\n\n return {\n success: true,\n data: { changedFiles, unchangedFiles },\n message: lines.length > 0 ? lines.join('\\n') : 'No files processed.',\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/** Registers the `encrypt [files...]` command onto the Commander program. */\nexport class EncryptBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('encrypt [files...]')\n .description('Encrypt plaintext .env.* files and create .unencrypted backups')\n .action(async (files: string[]) => {\n await this.dispatch(new EncryptCommand(), { files }, this.buildContext(program));\n });\n }\n}\n","import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport type { Command } from 'commander';\nimport type { CommandContext, CommandResult, InitResult, ISubCommand } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { resolveDefaultKeystorePath, resolveKeystoresRegistryPath } from '../../utils/platform.js';\nimport { listEnvFiles } from '../../utils/dotenvx.js';\nimport { readRegistry, writeRegistry } from '../keystore/registry.js';\nimport { findWorkspaceRoot, scanWorkspacePackages } from './workspace.js';\nimport { detectBuildEnvironment } from '../../utils/build-env.js';\nimport { writeConfig } from '../../utils/config.js';\n\n/** Options parsed by Commander for the `init` subcommand. */\ninterface InitOptions {\n workspace: string | undefined;\n name: string | undefined;\n keystore: string | undefined;\n /** Override the config directory name (default: `.envctrl`). */\n configDir: string | undefined;\n /** Override the config file name (default: `config.json`). */\n configFile: string | undefined;\n}\n\n/**\n * Initialises envctrl for an existing workspace or monorepo by creating a shared keystore,\n * symlinking `.env.keys` into every package directory, and writing a `.envctrl/config.json`\n * that records the active environment.\n *\n * When a recognised CI/CD provider (Vercel, Netlify, Railway) is detected via environment\n * variables, the environment is automatically resolved from the provider context instead of\n * defaulting to `\"development\"`.\n */\nexport class InitCommand implements ISubCommand<InitOptions, InitResult> {\n /** @inheritdoc */\n async execute(options: InitOptions, context: CommandContext): Promise<CommandResult<InitResult>> {\n const startDir = options.workspace\n ? path.resolve(context.cwd, options.workspace)\n : context.cwd;\n\n const configDir = options.configDir ?? '.envctrl';\n const configFile = options.configFile ?? 'config.json';\n\n try {\n const workspaceRoot = await findWorkspaceRoot(startDir);\n const packages = await scanWorkspacePackages(workspaceRoot);\n\n const keystorePath = options.keystore ?? resolveDefaultKeystorePath();\n const keystoreName = options.name ?? path.basename(workspaceRoot);\n\n await fs.mkdir(keystorePath, { recursive: true });\n\n const keysFile = path.join(keystorePath, '.env.keys');\n try {\n await fs.access(keysFile);\n } catch {\n await fs.writeFile(keysFile, '# dotenvx keys\\n', 'utf8');\n }\n\n const registryPath = resolveKeystoresRegistryPath();\n await fs.mkdir(path.dirname(registryPath), { recursive: true });\n const registry = await readRegistry(registryPath);\n const alreadyRegistered = registry.some(\n (e) => e.name === keystoreName || e.path === keystorePath,\n );\n if (!alreadyRegistered) {\n registry.push({ name: keystoreName, path: keystorePath });\n await writeRegistry(registryPath, registry);\n }\n\n const linkTargets = [\n workspaceRoot,\n ...packages.map((p) => path.resolve(workspaceRoot, p.path)),\n ];\n\n const keysLinked: string[] = [];\n\n for (const dir of linkTargets) {\n const envFiles = listEnvFiles(dir, '.env.*', ['.env.keys']);\n if (envFiles.length === 0) continue;\n\n const linkPath = path.join(dir, '.env.keys');\n try {\n await fs.access(linkPath);\n } catch {\n if (os.platform() === 'win32') {\n await fs.copyFile(keysFile, linkPath);\n } else {\n await fs.symlink(keysFile, linkPath);\n }\n keysLinked.push(linkPath);\n }\n }\n\n const buildEnv = detectBuildEnvironment();\n const environment = buildEnv.environment ?? 'development';\n const autoDetected = buildEnv.provider !== null;\n\n const configPath = await writeConfig(\n context.cwd,\n { environment },\n configDir,\n configFile,\n );\n\n const lines = [`Workspace: ${workspaceRoot}`, `Keystore: ${keystorePath}`];\n if (packages.length > 0) {\n lines.push('Packages:');\n for (const p of packages) lines.push(` ${p.name} (${p.path})`);\n }\n if (keysLinked.length > 0) {\n lines.push('Linked .env.keys:');\n for (const l of keysLinked) lines.push(` ${l}`);\n }\n lines.push(\n `Config: ${configPath}`,\n `Environment: ${environment}${autoDetected ? ` (auto-detected from ${buildEnv.provider})` : ''}`,\n );\n\n return {\n success: true,\n data: { workspaceRoot, packages, keystorePath, keysLinked, configPath, environment, autoDetected },\n message: lines.join('\\n'),\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/** Registers the `init [workspace]` command onto the Commander program. */\nexport class InitBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('init [workspace]')\n .description(\n 'Scan the workspace or monorepo and link packages to a shared keystore',\n )\n .option('-n, --name <name>', 'name for the keystore entry in the registry')\n .option('-k, --keystore <path>', 'custom keystore directory path')\n .option('--config-dir <dir>', 'config directory name (default: .envctrl)')\n .option('--config-file <file>', 'config file name (default: config.json)')\n .action(\n async (\n workspace: string | undefined,\n opts: { name?: string; keystore?: string; configDir?: string; configFile?: string },\n ) => {\n await this.dispatch(\n new InitCommand(),\n {\n workspace,\n name: opts.name,\n keystore: opts.keystore,\n configDir: opts.configDir,\n configFile: opts.configFile,\n },\n this.buildContext(program),\n );\n },\n );\n }\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { WorkspacePackage } from '@envctrl/types';\n\n/**\n * Traverses up from `startDir` to find the workspace root.\n *\n * A directory is considered the workspace root if it contains\n * `pnpm-workspace.yaml` or a `package.json` with a `workspaces` field.\n * Falls back to `startDir` if no root is found.\n */\nexport async function findWorkspaceRoot(startDir: string): Promise<string> {\n let dir = startDir;\n\n while (true) {\n try {\n await fs.access(path.join(dir, 'pnpm-workspace.yaml'));\n return dir;\n } catch {}\n\n try {\n const raw = await fs.readFile(path.join(dir, 'package.json'), 'utf8');\n const pkg = JSON.parse(raw) as { workspaces?: unknown };\n if (pkg.workspaces) return dir;\n } catch {}\n\n const parent = path.dirname(dir);\n if (parent === dir) return startDir;\n dir = parent;\n }\n}\n\n/**\n * Reads workspace package glob patterns from `pnpm-workspace.yaml` or\n * the `workspaces` field in `package.json`.\n */\nasync function readWorkspacePatterns(workspaceRoot: string): Promise<string[]> {\n try {\n const raw = await fs.readFile(path.join(workspaceRoot, 'pnpm-workspace.yaml'), 'utf8');\n const patterns: string[] = [];\n let inPackages = false;\n\n for (const line of raw.split('\\n')) {\n if (/^packages\\s*:/.test(line)) {\n inPackages = true;\n continue;\n }\n if (inPackages) {\n const match = line.match(/^\\s+-\\s+['\"]?([^'\"]+)['\"]?/);\n if (match) {\n patterns.push(match[1].trim());\n } else if (line.trim() && !line.startsWith('#')) {\n break;\n }\n }\n }\n\n if (patterns.length > 0) return patterns;\n } catch {}\n\n try {\n const raw = await fs.readFile(path.join(workspaceRoot, 'package.json'), 'utf8');\n const pkg = JSON.parse(raw) as {\n workspaces?: string[] | { packages: string[] };\n };\n if (Array.isArray(pkg.workspaces)) return pkg.workspaces;\n if (pkg.workspaces?.packages) return pkg.workspaces.packages;\n } catch {}\n\n return [];\n}\n\n/**\n * Expands a single workspace glob pattern (supporting one trailing `*`) into\n * matching subdirectory paths under `workspaceRoot`.\n */\nasync function expandPattern(workspaceRoot: string, pattern: string): Promise<string[]> {\n if (!pattern.includes('*')) {\n return [path.resolve(workspaceRoot, pattern)];\n }\n\n const starIndex = pattern.indexOf('*');\n const baseRelative = pattern.slice(0, starIndex).replace(/\\/$/, '');\n const suffix = pattern.slice(starIndex + 1);\n const baseDir = path.resolve(workspaceRoot, baseRelative);\n\n try {\n const entries = await fs.readdir(baseDir, { withFileTypes: true });\n return entries\n .filter((e) => e.isDirectory() && !e.name.startsWith('.'))\n .map((e) => path.join(baseDir, e.name + suffix));\n } catch {\n return [];\n }\n}\n\n/**\n * Scans `workspaceRoot` for all packages by expanding workspace glob patterns\n * and filtering directories that contain a `package.json`.\n */\nexport async function scanWorkspacePackages(workspaceRoot: string): Promise<WorkspacePackage[]> {\n const patterns = await readWorkspacePatterns(workspaceRoot);\n const packages: WorkspacePackage[] = [];\n\n for (const pattern of patterns) {\n const dirs = await expandPattern(workspaceRoot, pattern);\n\n for (const dir of dirs) {\n try {\n const raw = await fs.readFile(path.join(dir, 'package.json'), 'utf8');\n const pkg = JSON.parse(raw) as { name?: string };\n if (pkg.name) {\n packages.push({\n name: pkg.name,\n path: path.relative(workspaceRoot, dir),\n });\n }\n } catch {}\n }\n }\n\n return packages;\n}\n","/** Known CI/CD providers that supply their own environment context. */\nexport type BuildProvider = 'vercel' | 'netlify' | 'railway';\n\n/** Result of probing the current process environment for a CI/CD context. */\nexport interface DetectedBuildEnv {\n /** The provider that was identified, or `null` when no provider is detected. */\n readonly provider: BuildProvider | null;\n /**\n * The canonical environment name derived from the provider's own variables.\n * `null` when no provider is detected.\n */\n readonly environment: 'production' | 'development' | null;\n}\n\n/**\n * Inspects `process.env` for well-known CI/CD provider variables and maps\n * them to a canonical `production` / `development` environment name.\n *\n * - **Vercel** – `VERCEL=1`; `VERCEL_ENV` is `production` | `preview` | `development`\n * - **Netlify** – `NETLIFY=true`; `CONTEXT` is `production` | `deploy-preview` | `branch-deploy` | `dev`\n * - **Railway** – `RAILWAY_ENVIRONMENT_NAME` holds the environment name directly\n */\nexport function detectBuildEnvironment(): DetectedBuildEnv {\n if (process.env['VERCEL'] === '1') {\n const vercelEnv = process.env['VERCEL_ENV'];\n return {\n provider: 'vercel',\n environment: vercelEnv === 'production' ? 'production' : 'development',\n };\n }\n\n if (process.env['NETLIFY'] === 'true') {\n const context = process.env['CONTEXT'];\n return {\n provider: 'netlify',\n environment: context === 'production' ? 'production' : 'development',\n };\n }\n\n if (process.env['RAILWAY_ENVIRONMENT_NAME'] !== undefined) {\n const railwayEnv = process.env['RAILWAY_ENVIRONMENT_NAME'];\n return {\n provider: 'railway',\n environment: railwayEnv === 'production' ? 'production' : 'development',\n };\n }\n\n return { provider: null, environment: null };\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { EnvctrlConfig } from '@envctrl/types';\n\n/**\n * Returns the absolute path to the envctrl config file.\n *\n * @param cwd - Base directory (typically the project root).\n * @param dir - Config directory name relative to `cwd`. Defaults to `.envctrl`.\n * @param file - Config file name inside `dir`. Defaults to `config.json`.\n */\nexport function resolveConfigPath(\n cwd: string,\n dir = '.envctrl',\n file = 'config.json',\n): string {\n return path.join(cwd, dir, file);\n}\n\n/**\n * Reads and parses the envctrl config file.\n * Returns `null` when the file does not exist or cannot be parsed.\n *\n * @param cwd - Base directory (typically the project root).\n * @param dir - Config directory name relative to `cwd`. Defaults to `.envctrl`.\n * @param file - Config file name inside `dir`. Defaults to `config.json`.\n */\nexport async function readConfig(\n cwd: string,\n dir = '.envctrl',\n file = 'config.json',\n): Promise<EnvctrlConfig | null> {\n try {\n const raw = await fs.readFile(resolveConfigPath(cwd, dir, file), 'utf8');\n return JSON.parse(raw) as EnvctrlConfig;\n } catch {\n return null;\n }\n}\n\n/**\n * Writes `config` as JSON, creating the config directory if needed.\n *\n * @param cwd - Base directory (typically the project root).\n * @param config - Configuration object to persist.\n * @param dir - Config directory name relative to `cwd`. Defaults to `.envctrl`.\n * @param file - Config file name inside `dir`. Defaults to `config.json`.\n * @returns The absolute path of the written file.\n */\nexport async function writeConfig(\n cwd: string,\n config: EnvctrlConfig,\n dir = '.envctrl',\n file = 'config.json',\n): Promise<string> {\n const configDir = path.join(cwd, dir);\n await fs.mkdir(configDir, { recursive: true });\n const configPath = resolveConfigPath(cwd, dir, file);\n await fs.writeFile(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf8');\n return configPath;\n}\n","import path from 'node:path';\nimport type { Command } from 'commander';\nimport type { CommandContext, CommandResult, EnvironmentName, ISubCommand, ListResult } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { listEnvFiles } from '../../utils/dotenvx.js';\nimport { readBlacklist } from '../../utils/blacklist.js';\nimport { parseEnvironmentFromFilename } from '../../utils/env-files.js';\n\n/**\n * Lists all unique environment names discovered in the working directory by\n * scanning `.env.*` files, normalising `.local` and `.unencrypted` suffixes,\n * and filtering out blacklisted names.\n */\nexport class ListCommand implements ISubCommand<Record<string, never>, ListResult> {\n /** @inheritdoc */\n async execute(\n _options: Record<string, never>,\n context: CommandContext,\n ): Promise<CommandResult<ListResult>> {\n try {\n const [files, blacklist] = await Promise.all([\n Promise.resolve(listEnvFiles(context.cwd, '.env.*', ['.env.keys'])),\n readBlacklist(),\n ]);\n const blacklisted = new Set(blacklist);\n const names = files\n .map((f) => parseEnvironmentFromFilename(path.basename(f)))\n .filter((e): e is EnvironmentName => e !== undefined && !blacklisted.has(e));\n const environments = [...new Set(names)].sort();\n\n const message =\n environments.length > 0 ? environments.join('\\n') : 'No environments found.';\n\n return { success: true, data: { environments }, message };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/** Registers the `list` command onto the Commander program. */\nexport class ListBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('list')\n .description('List all environment names discovered in the working directory')\n .action(async () => {\n await this.dispatch(new ListCommand(), {}, this.buildContext(program));\n });\n }\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { EnvironmentName } from '@envctrl/types';\nimport { resolveBlacklistPath } from './platform.js';\n\n/** Reads the blacklist from disk, returning an empty array if it does not exist. */\nexport async function readBlacklist(): Promise<EnvironmentName[]> {\n try {\n const raw = await fs.readFile(resolveBlacklistPath(), 'utf8');\n return JSON.parse(raw) as EnvironmentName[];\n } catch {\n return [];\n }\n}\n\n/** Writes the blacklist to disk. */\nexport async function writeBlacklist(entries: EnvironmentName[]): Promise<void> {\n const filePath = resolveBlacklistPath();\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(filePath, JSON.stringify(entries, null, 2) + '\\n', 'utf8');\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Command } from 'commander';\nimport type { CommandContext, CommandResult, EnvironmentName, ISubCommand, RemoveResult } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { listEnvFiles } from '../../utils/dotenvx.js';\nimport { parseEnvironmentFromFilename } from '../../utils/env-files.js';\n\n/** Options parsed by Commander for the `rm` subcommand. */\ninterface RmOptions {\n environment: EnvironmentName;\n all: boolean;\n force: boolean;\n}\n\n/**\n * Removes environment files from the working directory.\n *\n * Without `--force`, performs a dry run listing files that would be deleted.\n * With `-a`, includes all associated file variants (`.local`, `.unencrypted`).\n * With `--force`, permanently deletes the resolved files.\n */\nexport class RmCommand implements ISubCommand<RmOptions, RemoveResult> {\n /** @inheritdoc */\n async execute(options: RmOptions, context: CommandContext): Promise<CommandResult<RemoveResult>> {\n const { environment, all, force } = options;\n\n try {\n const allFiles = listEnvFiles(context.cwd, '.env.*', ['.env.keys']);\n const candidates = allFiles.filter((f) => {\n const name = parseEnvironmentFromFilename(path.basename(f));\n return name === environment;\n });\n\n if (!all) {\n const primary = path.resolve(context.cwd, `.env.${environment}`);\n const subset = candidates.filter((f) => f === primary);\n return buildResult(environment, subset, force);\n }\n\n return buildResult(environment, candidates, force);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\nasync function buildResult(\n environment: EnvironmentName,\n files: string[],\n force: boolean,\n): Promise<CommandResult<RemoveResult>> {\n if (!force) {\n const preview = files.length > 0\n ? `Would delete:\\n${files.map((f) => ` ${f}`).join('\\n')}\\n\\nPass --force to confirm deletion.`\n : `No files found for environment: ${environment}`;\n\n return {\n success: true,\n data: { environment, deletedFiles: [] },\n message: preview,\n };\n }\n\n const deleted: string[] = [];\n for (const f of files) {\n try {\n await fs.rm(f, { force: true });\n deleted.push(f);\n } catch {}\n }\n\n const message =\n deleted.length > 0\n ? `Deleted:\\n${deleted.map((f) => ` ${f}`).join('\\n')}`\n : `No files found for environment: ${environment}`;\n\n return {\n success: true,\n data: { environment, deletedFiles: deleted },\n message,\n };\n}\n\n/** Registers the `rm <environment>` command onto the Commander program. */\nexport class RmBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('rm <environment>')\n .description('Remove environment files from the working directory')\n .option('-a, --all', 'include all associated file variants (.local, .unencrypted)', false)\n .option('--force', 'actually delete files (default is dry run)', false)\n .action(async (environment: string, opts: { all: boolean; force: boolean }) => {\n await this.dispatch(\n new RmCommand(),\n { environment, all: opts.all, force: opts.force },\n this.buildContext(program),\n );\n });\n }\n}\n","import type { Command } from 'commander';\nimport type { BlacklistResult, CommandContext, CommandResult, EnvironmentName, ISubCommand } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { readBlacklist, writeBlacklist } from '../../utils/blacklist.js';\n\n/** Options parsed by Commander for `blacklist add`. */\ninterface BlacklistAddOptions {\n environment: EnvironmentName;\n}\n\n/** Options parsed by Commander for `blacklist rm`. */\ninterface BlacklistRmOptions {\n environment: EnvironmentName;\n}\n\n/**\n * Adds an environment name to the global blacklist, preventing it from\n * appearing in auto-detection results such as `envctrl list`.\n */\nexport class BlacklistAddSubCommand implements ISubCommand<BlacklistAddOptions, BlacklistResult> {\n /** @inheritdoc */\n async execute(\n options: BlacklistAddOptions,\n _context: CommandContext,\n ): Promise<CommandResult<BlacklistResult>> {\n const { environment } = options;\n\n try {\n const current = await readBlacklist();\n\n if (current.includes(environment)) {\n return {\n success: true,\n data: { environment, blacklisted: current },\n message: `Environment \"${environment}\" is already blacklisted.`,\n };\n }\n\n const updated = [...current, environment];\n await writeBlacklist(updated);\n\n return {\n success: true,\n data: { environment, blacklisted: updated },\n message: `Added \"${environment}\" to the blacklist.\\nBlacklisted environments:\\n${updated.map((e) => ` ${e}`).join('\\n')}`,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/**\n * Removes an environment name from the global blacklist, restoring it to\n * auto-detection results such as `envctrl list`.\n */\nexport class BlacklistRmSubCommand implements ISubCommand<BlacklistRmOptions, BlacklistResult> {\n /** @inheritdoc */\n async execute(\n options: BlacklistRmOptions,\n _context: CommandContext,\n ): Promise<CommandResult<BlacklistResult>> {\n const { environment } = options;\n\n try {\n const current = await readBlacklist();\n\n if (!current.includes(environment)) {\n return {\n success: false,\n error: `Environment \"${environment}\" is not in the blacklist.`,\n };\n }\n\n const updated = current.filter((e) => e !== environment);\n await writeBlacklist(updated);\n\n const message =\n updated.length > 0\n ? `Removed \"${environment}\" from the blacklist.\\nBlacklisted environments:\\n${updated.map((e) => ` ${e}`).join('\\n')}`\n : `Removed \"${environment}\" from the blacklist.\\nBlacklist is now empty.`;\n\n return {\n success: true,\n data: { environment, blacklisted: updated },\n message,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/** Registers the `blacklist` command group onto the Commander program. */\nexport class BlacklistBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n const blacklist = program\n .command('blacklist')\n .description('Manage the environment auto-detection blacklist');\n\n blacklist\n .command('add <environment>')\n .description('Exclude an environment from auto-detection')\n .action(async (environment: string) => {\n await this.dispatch(\n new BlacklistAddSubCommand(),\n { environment },\n this.buildContext(program),\n );\n });\n\n blacklist\n .command('rm <environment>')\n .description('Re-include an environment in auto-detection')\n .action(async (environment: string) => {\n await this.dispatch(\n new BlacklistRmSubCommand(),\n { environment },\n this.buildContext(program),\n );\n });\n }\n}\n","import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { createInterface } from 'node:readline/promises';\nimport type { Command } from 'commander';\nimport type {\n CommandContext,\n CommandResult,\n CreateResult,\n EnvironmentName,\n ISubCommand,\n} from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { listEnvFiles, setKeyValue } from '../../utils/dotenvx.js';\nimport { parseEnvContent, parseEnvironmentFromFilename, buildEnvFilePair } from '../../utils/env-files.js';\nimport { readConfig, writeConfig } from '../../utils/config.js';\nimport { syncUnencryptedToEncrypted } from '../switch/sync.js';\n\n/** Options parsed by Commander for the `create` subcommand. */\ninterface CreateOptions {\n environment: EnvironmentName;\n /**\n * Base environment whose key names are copied into the new environment (values set to empty).\n * Required when `environment` is `\"example\"` and omitted interactively; optional otherwise.\n */\n from: string | undefined;\n}\n\n/**\n * Returns the list of currently existing environment names by scanning `.env.*` files\n * in `cwd`, excluding `.env.keys` and `.env.example`.\n */\nasync function listExistingEnvironments(cwd: string): Promise<EnvironmentName[]> {\n const files = listEnvFiles(cwd, '.env.*', ['.env.keys']);\n const names = files\n .map((f) => parseEnvironmentFromFilename(path.basename(f)))\n .filter((e): e is EnvironmentName => e !== undefined);\n return [...new Set(names)];\n}\n\n/**\n * Reads keys from an unencrypted env file and returns a `.env.example`-style\n * string with each key set to an empty value.\n */\nasync function buildExampleContent(unencryptedPath: string): Promise<string> {\n let raw = '';\n try {\n raw = await fs.readFile(unencryptedPath, 'utf8');\n } catch {\n return '';\n }\n const entries = parseEnvContent(raw);\n const lines = Object.keys(entries).map((k) => `${k}=`);\n return lines.length > 0 ? lines.join('\\n') + '\\n' : '';\n}\n\n/**\n * Creates environments or generates a `.env.example` file.\n *\n * - `example`: Writes `.env.example` with key names (empty values) copied from a base\n * environment. If `--from` is omitted the user is prompted interactively.\n * - existing environment: Rejected with an error.\n * - new environment: Creates `.env.<env>.unencrypted` (empty, or pre-populated with key names\n * from `--from` base environment) and the encrypted `.env.<env>`, records the environment\n * in `.envctrl/config.json`, and re-encrypts `.env.local` from `.env.local.unencrypted`\n * if present.\n */\nexport class CreateCommand implements ISubCommand<CreateOptions, CreateResult> {\n /** @inheritdoc */\n async execute(\n options: CreateOptions,\n context: CommandContext,\n ): Promise<CommandResult<CreateResult>> {\n const { environment, cwd } = { ...options, cwd: context.cwd };\n\n try {\n if (environment === 'example') {\n return await this.createExample(options.from, cwd);\n }\n\n const existing = await listExistingEnvironments(cwd);\n if (existing.includes(environment)) {\n return {\n success: false,\n error: `Environment \"${environment}\" already exists. Use \"envctrl switch ${environment}\" to activate it.`,\n };\n }\n\n return await this.createEnvironment(environment, cwd, options.from);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n private async createExample(\n from: string | undefined,\n cwd: string,\n ): Promise<CommandResult<CreateResult>> {\n const existing = await listExistingEnvironments(cwd);\n\n let base = from;\n if (!base) {\n if (existing.length === 0) {\n return {\n success: false,\n error: 'No environments found. Create one first with \"envctrl create <environment>\".',\n };\n }\n\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n base = await rl.question(\n `Choose a base environment [${existing.join(', ')}]: `,\n );\n } finally {\n rl.close();\n }\n }\n\n if (!existing.includes(base)) {\n return {\n success: false,\n error: `Environment \"${base}\" does not exist. Available: ${existing.join(', ')}`,\n };\n }\n\n const pair = buildEnvFilePair(base, cwd);\n const content = await buildExampleContent(pair.unencrypted);\n const examplePath = path.resolve(cwd, '.env.example');\n await fs.writeFile(examplePath, content, 'utf8');\n\n return {\n success: true,\n data: {\n environment: 'example',\n createdFiles: [examplePath],\n isExample: true,\n baseEnvironment: base,\n },\n message: `Created .env.example from \"${base}\" (${Object.keys(parseEnvContent(content)).length} keys)`,\n };\n }\n\n private async createEnvironment(\n environment: EnvironmentName,\n cwd: string,\n from: string | undefined,\n ): Promise<CommandResult<CreateResult>> {\n const pair = buildEnvFilePair(environment, cwd);\n const created: string[] = [];\n\n if (from) {\n const existing = await listExistingEnvironments(cwd);\n if (!existing.includes(from)) {\n return {\n success: false,\n error: `Base environment \"${from}\" does not exist. Available: ${existing.join(', ')}`,\n };\n }\n const basePair = buildEnvFilePair(from, cwd);\n const content = await buildExampleContent(basePair.unencrypted);\n await fs.writeFile(pair.unencrypted, content, 'utf8');\n } else {\n await fs.writeFile(pair.unencrypted, '', 'utf8');\n }\n created.push(pair.unencrypted);\n\n if (from) {\n await syncUnencryptedToEncrypted(environment, cwd);\n } else {\n setKeyValue('_ENVCTRL_INIT', '1', pair.encrypted);\n }\n created.push(pair.encrypted);\n\n const config = (await readConfig(cwd)) ?? { environment };\n await writeConfig(cwd, { ...config, environment });\n\n const localUnencrypted = path.resolve(cwd, '.env.local.unencrypted');\n const localEncrypted = path.resolve(cwd, '.env.local');\n const localExists = await fs\n .access(localUnencrypted)\n .then(() => true)\n .catch(() => false);\n\n if (localExists) {\n await syncUnencryptedToEncrypted('local', cwd);\n } else {\n const encryptedLocalExists = await fs\n .access(localEncrypted)\n .then(() => true)\n .catch(() => false);\n\n if (!encryptedLocalExists) {\n if (os.platform() === 'win32') {\n await fs.copyFile(pair.encrypted, localEncrypted);\n } else {\n await fs.symlink(pair.encrypted, localEncrypted);\n }\n created.push(localEncrypted);\n }\n }\n\n const lines = [\n `Created environment: ${environment}${from ? ` (from \"${from}\")` : ''}`,\n 'Files:',\n ...created.map((f) => ` ${f}`),\n ];\n if (localExists) {\n lines.push(`Updated: ${localEncrypted}`);\n }\n\n return {\n success: true,\n data: { environment, createdFiles: created, isExample: false, baseEnvironment: from },\n message: lines.join('\\n'),\n };\n }\n}\n\n/** Registers the `create <environment>` command onto the Commander program. */\nexport class CreateBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('create <environment>')\n .description(\n 'Create a new environment or generate .env.example (use \"example\" as the environment name)',\n )\n .option('--from <env>', 'copy key names (empty values) from this base environment')\n .action(async (environment: string, opts: { from?: string }) => {\n await this.dispatch(\n new CreateCommand(),\n { environment, from: opts.from },\n this.buildContext(program),\n );\n });\n }\n}\n"],"mappings":"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","names":["createRequire","fs","path","program","path","require","fs","path","program","fs","path","os","path","fs","path","fs","fs","fs","program","fs","fs","program","fs","path","path","fs","program","fs","os","path","fs","path","fs","path","path","fs","os","program","path","fs","path","fs","path","path","program","fs","path","path","fs","program","program","fs","os","path","path","fs","os","program","createRequire"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/switch/index.ts","../src/base-command.ts","../src/utils/env-files.ts","../src/utils/dotenvx.ts","../src/commands/switch/sync.ts","../src/commands/keystore/create.ts","../src/utils/platform.ts","../src/commands/keystore/registry.ts","../src/commands/keystore/list.ts","../src/commands/keystore/delete.ts","../src/commands/keystore/index.ts","../src/commands/set/index.ts","../src/commands/encrypt/index.ts","../src/commands/init/index.ts","../src/commands/init/workspace.ts","../src/utils/build-env.ts","../src/utils/config.ts","../src/commands/list/index.ts","../src/utils/blacklist.ts","../src/commands/rm/index.ts","../src/commands/blacklist/index.ts","../src/commands/create/index.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { Command } from 'commander';\nimport { SwitchBaseCommand } from './commands/switch/index.js';\nimport { KeystoreBaseCommand } from './commands/keystore/index.js';\nimport { SetBaseCommand } from './commands/set/index.js';\nimport { EncryptBaseCommand } from './commands/encrypt/index.js';\nimport { InitBaseCommand } from './commands/init/index.js';\nimport { ListBaseCommand } from './commands/list/index.js';\nimport { RmBaseCommand } from './commands/rm/index.js';\nimport { BlacklistBaseCommand } from './commands/blacklist/index.js';\nimport { CreateBaseCommand } from './commands/create/index.js';\n\nconst _require = createRequire(import.meta.url);\nconst { version } = _require('../package.json') as { version: string };\n\nconst program = new Command();\n\nprogram\n .name('envctrl')\n .description('Encrypted environment file manager built on dotenvx')\n .version(version)\n .addHelpText('beforeAll', `envctrl v${version}\\n`)\n .option('-q, --quiet', 'suppress output', false);\n\nnew InitBaseCommand().register(program);\nnew CreateBaseCommand().register(program);\nnew ListBaseCommand().register(program);\nnew SwitchBaseCommand().register(program);\nnew KeystoreBaseCommand().register(program);\nnew SetBaseCommand().register(program);\nnew EncryptBaseCommand().register(program);\nnew RmBaseCommand().register(program);\nnew BlacklistBaseCommand().register(program);\n\nprogram.parseAsync(process.argv);\n","import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport type { Command } from 'commander';\nimport type { CommandContext, CommandResult, ISubCommand, SwitchResult } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { buildEnvFilePair } from '../../utils/env-files.js';\nimport { setKeyValue } from '../../utils/dotenvx.js';\nimport { syncUnencryptedToEncrypted } from './sync.js';\n\n/** Options parsed by Commander for the `switch` subcommand. */\ninterface SwitchOptions {\n environment: string;\n}\n\n/**\n * Switches the active environment.\n *\n * Creates `.env.[env].unencrypted` and `.env.[env]` if they do not exist,\n * syncs keys from the unencrypted source into the encrypted file, and\n * points `.env` at the encrypted file via symlink (POSIX) or copy (Windows).\n */\nexport class SwitchCommand implements ISubCommand<SwitchOptions, SwitchResult> {\n /** @inheritdoc */\n async execute(\n options: SwitchOptions,\n context: CommandContext,\n ): Promise<CommandResult<SwitchResult>> {\n const { environment, cwd } = { ...options, cwd: context.cwd };\n const pair = buildEnvFilePair(environment, cwd);\n const created: string[] = [];\n\n try {\n try {\n await fs.access(pair.unencrypted);\n } catch {\n await fs.writeFile(pair.unencrypted, '', 'utf8');\n created.push(pair.unencrypted);\n }\n\n const encryptedExists = await fs\n .access(pair.encrypted)\n .then(() => true)\n .catch(() => false);\n\n await syncUnencryptedToEncrypted(environment, cwd);\n\n if (!encryptedExists) {\n const stillMissing = await fs\n .access(pair.encrypted)\n .then(() => false)\n .catch(() => true);\n\n if (stillMissing) {\n setKeyValue('_ENVCTRL_INIT', '1', pair.encrypted);\n created.push(pair.encrypted);\n } else {\n created.push(pair.encrypted);\n }\n }\n\n const activePath = path.resolve(cwd, '.env');\n\n try {\n await fs.unlink(activePath);\n } catch {}\n\n if (os.platform() === 'win32') {\n await fs.copyFile(pair.encrypted, activePath);\n } else {\n await fs.symlink(pair.encrypted, activePath);\n }\n\n const lines = [`Switched to: ${environment}`];\n if (created.length > 0) {\n lines.push('Created:', ...created.map((f) => ` ${f}`));\n }\n\n return {\n success: true,\n data: { environment, created, activePath },\n message: lines.join('\\n'),\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/** Registers the `switch [environment]` command onto the Commander program. */\nexport class SwitchBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('switch <environment>')\n .description('Create, sync, and activate a named environment (.env.[env])')\n .action(async (environment: string) => {\n await this.dispatch(new SwitchCommand(), { environment }, this.buildContext(program));\n });\n }\n}\n","import type { Command } from 'commander';\nimport type { CommandContext, CommandResult, ISubCommand } from '@envctrl/types';\n\n/**\n * Abstract base for all top-level CLI commands.\n *\n * Subclasses implement {@link register} to attach their Commander subcommand\n * to the program. The {@link dispatch} helper handles uniform result\n * printing and process exit on failure.\n */\nexport abstract class BaseCommand {\n /**\n * Attaches this command's Commander definition onto `program`.\n *\n * @param program - The root Commander program instance\n */\n abstract register(program: Command): void;\n\n /**\n * Executes a subcommand and handles the result.\n *\n * Prints the error message to stderr and exits with code 1 on failure.\n * Prints `result.message` to stdout on success when `context.quiet` is false.\n *\n * @param cmd - The subcommand to execute\n * @param options - Parsed options from Commander\n * @param context - Injected runtime context\n */\n protected async dispatch<TOptions, TResult>(\n cmd: ISubCommand<TOptions, TResult>,\n options: TOptions,\n context: CommandContext,\n ): Promise<void> {\n const result: CommandResult<TResult> = await cmd.execute(options, context);\n\n if (!result.success) {\n process.stderr.write(`error: ${result.error ?? 'unknown error'}\\n`);\n process.exit(1);\n }\n\n if (!context.quiet && result.message !== undefined) {\n process.stdout.write(result.message + '\\n');\n }\n }\n\n /**\n * Builds a {@link CommandContext} from the Commander program's global options.\n *\n * @param program - The root Commander program instance\n */\n protected buildContext(program: Command): CommandContext {\n const opts = program.opts<{ quiet?: boolean }>();\n return {\n cwd: process.cwd(),\n quiet: opts.quiet ?? false,\n };\n }\n}\n","import path from 'node:path';\nimport type { EnvFilePair, EnvironmentName } from '@envctrl/types';\n\nconst RESERVED_ENV_NAMES = new Set(['keys', 'example']);\n\n/**\n * Derives the environment name from a `.env.*` filename, stripping `.unencrypted`\n * and `.local` suffixes. Returns `undefined` for reserved filenames like\n * `.env.keys` and `.env.example`.\n */\nexport function parseEnvironmentFromFilename(filename: string): EnvironmentName | undefined {\n const base = path.basename(filename);\n\n if (!base.startsWith('.env.')) {\n return undefined;\n }\n\n const withoutPrefix = base.slice('.env.'.length);\n\n if (!withoutPrefix || RESERVED_ENV_NAMES.has(withoutPrefix)) {\n return undefined;\n }\n\n let name = withoutPrefix.endsWith('.unencrypted')\n ? withoutPrefix.slice(0, -'.unencrypted'.length)\n : withoutPrefix;\n\n if (name.endsWith('.local')) {\n name = name.slice(0, -'.local'.length);\n }\n\n if (!name || RESERVED_ENV_NAMES.has(name)) {\n return undefined;\n }\n\n return name;\n}\n\n/**\n * Builds the {@link EnvFilePair} for a given environment name and working directory.\n *\n * @param environment - The environment name, e.g. `\"production\"`\n * @param cwd - The working directory that will contain the env files\n */\nexport function buildEnvFilePair(environment: EnvironmentName, cwd: string): EnvFilePair {\n return {\n environment,\n unencrypted: path.resolve(cwd, `.env.${environment}.unencrypted`),\n encrypted: path.resolve(cwd, `.env.${environment}`),\n };\n}\n\n/**\n * Parses KEY=VALUE pairs from a plaintext `.env` file string.\n *\n * Skips blank lines and comment lines starting with `#`.\n *\n * @param content - Raw file content\n */\nexport function parseEnvContent(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n\n if (!trimmed || trimmed.startsWith('#')) {\n continue;\n }\n\n const eqIdx = trimmed.indexOf('=');\n if (eqIdx === -1) {\n continue;\n }\n\n const key = trimmed.slice(0, eqIdx).trim();\n const value = trimmed.slice(eqIdx + 1).trim();\n result[key] = value;\n }\n\n return result;\n}\n\n/**\n * Writes or updates a single `KEY=VALUE` line in a plaintext env file string.\n *\n * If the key already exists its line is replaced in-place; otherwise the\n * entry is appended.\n *\n * @param content - Current raw file content\n * @param key - The environment variable name\n * @param value - The new value\n */\nexport function upsertEnvLine(content: string, key: string, value: string): string {\n const lines = content.split('\\n');\n const pattern = new RegExp(`^${key}\\\\s*=`);\n let replaced = false;\n\n const updated = lines.map((line) => {\n if (pattern.test(line)) {\n replaced = true;\n return `${key}=${value}`;\n }\n return line;\n });\n\n if (!replaced) {\n if (updated[updated.length - 1] !== '') {\n updated.push(`${key}=${value}`);\n } else {\n updated.splice(updated.length - 1, 0, `${key}=${value}`);\n }\n }\n\n return updated.join('\\n');\n}\n","import { createRequire } from 'node:module';\nimport path from 'node:path';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport * as dotenvx from '@dotenvx/dotenvx';\nimport type { DotenvxEncryptResult, DotenvxSetResult } from '@envctrl/types';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Resolves the path to the dotenvx CLI entry script from the installed package.\n *\n * Reads the `bin` field from the package's own `package.json` to avoid\n * hardcoding the path, which can change across dotenvx versions.\n */\nfunction resolveDotenvxBin(): string {\n const require = createRequire(import.meta.url);\n const pkgJsonPath = require.resolve('@dotenvx/dotenvx/package.json');\n const pkgJson = require('@dotenvx/dotenvx/package.json') as {\n bin: Record<string, string>;\n };\n const binRelPath = pkgJson.bin['dotenvx'];\n return path.resolve(path.dirname(pkgJsonPath), binRelPath);\n}\n\n/**\n * Sets a single key-value pair in an encrypted env file using the dotenvx JS API.\n *\n * @param key - The environment variable name\n * @param value - The value to set\n * @param encryptedFilePath - Absolute path to the target `.env.[env]` file\n * @param keysFilePath - Optional path to the `.env.keys` file\n */\nexport function setKeyValue(\n key: string,\n value: string,\n encryptedFilePath: string,\n keysFilePath?: string,\n): DotenvxSetResult {\n const output = dotenvx.set(key, value, {\n path: encryptedFilePath,\n encrypt: true,\n quiet: true,\n ...(keysFilePath ? { envKeysFile: keysFilePath } : {}),\n });\n\n return {\n changedFilepaths: output.changedFilepaths,\n unchangedFilepaths: output.unchangedFilepaths,\n };\n}\n\n/**\n * Encrypts an existing plaintext env file in-place using the dotenvx CLI.\n *\n * Spawns the bundled `dotenvx encrypt -f <filePath>` process. The CLI\n * handles creating or updating the corresponding `.env.keys` entry.\n *\n * @param filePath - Absolute path to the plaintext `.env.*` file to encrypt\n */\nexport async function encryptFile(filePath: string): Promise<DotenvxEncryptResult> {\n const bin = resolveDotenvxBin();\n await execFileAsync(process.execPath, [bin, 'encrypt', '-f', filePath]);\n\n return {\n changedFilepaths: [filePath],\n unchangedFilepaths: [],\n };\n}\n\n/**\n * Lists env files in a directory using the dotenvx JS API.\n *\n * @param directory - Directory to scan\n * @param include - Glob pattern(s) to include\n * @param exclude - Glob pattern(s) to exclude\n */\nexport function listEnvFiles(\n directory: string,\n include: string | string[],\n exclude: string | string[],\n): string[] {\n return dotenvx.ls(directory, include, exclude);\n}\n","import fs from 'node:fs/promises';\nimport { parseEnvContent, buildEnvFilePair } from '../../utils/env-files.js';\nimport { setKeyValue } from '../../utils/dotenvx.js';\nimport type { EnvironmentName } from '@envctrl/types';\n\n/**\n * Syncs all keys from the unencrypted file into the encrypted file.\n *\n * Reads the plaintext `.env.[env].unencrypted` file and calls dotenvx `set`\n * for each key so the encrypted counterpart stays in sync.\n *\n * @param environment - The environment name\n * @param cwd - Working directory containing the env files\n */\nexport async function syncUnencryptedToEncrypted(\n environment: EnvironmentName,\n cwd: string,\n): Promise<void> {\n const pair = buildEnvFilePair(environment, cwd);\n\n let content: string;\n try {\n content = await fs.readFile(pair.unencrypted, 'utf8');\n } catch {\n return;\n }\n\n const entries = parseEnvContent(content);\n\n for (const [key, value] of Object.entries(entries)) {\n setKeyValue(key, value, pair.encrypted);\n }\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { CommandContext, CommandResult, ISubCommand, KeystoreConfig } from '@envctrl/types';\nimport { resolveDefaultKeystorePath, resolveKeystoresRegistryPath } from '../../utils/platform.js';\nimport { readRegistry, writeRegistry } from './registry.js';\n\n/** Options parsed by Commander for `keystore create`. */\nexport interface KeystoreCreateOptions {\n keystorePath: string | undefined;\n name: string | undefined;\n}\n\n/**\n * Creates a new keystore directory and registers it in the global registry.\n *\n * If no path is provided, defaults to the platform-appropriate application\n * data directory. An empty `.env.keys` stub is written on first creation.\n */\nexport class KeystoreCreateSubCommand implements ISubCommand<\n KeystoreCreateOptions,\n KeystoreConfig\n> {\n /** @inheritdoc */\n async execute(\n options: KeystoreCreateOptions,\n _context: CommandContext,\n ): Promise<CommandResult<KeystoreConfig>> {\n const keystorePath = options.keystorePath ?? resolveDefaultKeystorePath();\n const name = options.name ?? path.basename(keystorePath);\n\n try {\n await fs.mkdir(keystorePath, { recursive: true });\n\n const keysFile = path.join(keystorePath, '.env.keys');\n try {\n await fs.access(keysFile);\n } catch {\n await fs.writeFile(keysFile, '# dotenvx keys\\n', 'utf8');\n }\n\n const registryPath = resolveKeystoresRegistryPath();\n await fs.mkdir(path.dirname(registryPath), { recursive: true });\n\n const registry = await readRegistry(registryPath);\n const exists = registry.some((e) => e.name === name || e.path === keystorePath);\n\n if (!exists) {\n registry.push({ name, path: keystorePath });\n await writeRegistry(registryPath, registry);\n }\n\n return {\n success: true,\n data: { path: keystorePath },\n message: `Keystore created at: ${keystorePath}`,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n","import os from 'node:os';\nimport path from 'node:path';\n\n/**\n * Resolves the envctrl application data root directory for the current platform.\n *\n * - Linux: `$XDG_DATA_HOME/envctrl` or `~/.local/share/envctrl`\n * - macOS: `~/Library/Application Support/envctrl`\n * - Windows: `%APPDATA%\\envctrl`\n */\nfunction resolveAppDataRoot(): string {\n const platform = os.platform();\n const home = os.homedir();\n\n if (platform === 'win32') {\n const appData = process.env['APPDATA'] ?? path.join(home, 'AppData', 'Roaming');\n return path.join(appData, 'envctrl');\n }\n\n if (platform === 'darwin') {\n return path.join(home, 'Library', 'Application Support', 'envctrl');\n }\n\n const xdgDataHome = process.env['XDG_DATA_HOME'] ?? path.join(home, '.local', 'share');\n return path.join(xdgDataHome, 'envctrl');\n}\n\n/**\n * Resolves the default keystore directory.\n *\n * Placed inside a `keystores/default` subdirectory of the app data root\n * so that the registry JSON file at the root level is never deleted when\n * the default keystore is removed.\n */\nexport function resolveDefaultKeystorePath(): string {\n return path.join(resolveAppDataRoot(), 'keystores', 'default');\n}\n\n/**\n * Returns the path to the global keystores registry JSON file.\n *\n * Stored at the app data root, outside any individual keystore directory,\n * so it survives keystore deletion.\n */\nexport function resolveKeystoresRegistryPath(): string {\n return path.join(resolveAppDataRoot(), 'keystores.json');\n}\n\n/** Returns the path to the blacklist JSON file. */\nexport function resolveBlacklistPath(): string {\n return path.join(resolveAppDataRoot(), 'blacklist.json');\n}\n","import fs from 'node:fs/promises';\nimport type { KeystoreEntry } from '@envctrl/types';\n\n/**\n * Reads the keystores registry JSON file.\n *\n * Returns an empty array if the file does not exist yet.\n *\n * @param registryPath - Absolute path to the `keystores.json` file\n */\nexport async function readRegistry(registryPath: string): Promise<KeystoreEntry[]> {\n try {\n const raw = await fs.readFile(registryPath, 'utf8');\n return JSON.parse(raw) as KeystoreEntry[];\n } catch {\n return [];\n }\n}\n\n/**\n * Writes the keystores registry to disk.\n *\n * @param registryPath - Absolute path to the `keystores.json` file\n * @param entries - Array of keystore entries to persist\n */\nexport async function writeRegistry(registryPath: string, entries: KeystoreEntry[]): Promise<void> {\n await fs.writeFile(registryPath, JSON.stringify(entries, null, 2) + '\\n', 'utf8');\n}\n","import type { CommandContext, CommandResult, ISubCommand, KeystoreEntry } from '@envctrl/types';\nimport { resolveKeystoresRegistryPath } from '../../utils/platform.js';\nimport { readRegistry } from './registry.js';\n\n/**\n * Lists all registered keystores from the global registry.\n *\n * Returns an empty array if no keystores have been created yet.\n */\nexport class KeystoreListSubCommand implements ISubCommand<Record<string, never>, KeystoreEntry[]> {\n /** @inheritdoc */\n async execute(\n _options: Record<string, never>,\n _context: CommandContext,\n ): Promise<CommandResult<KeystoreEntry[]>> {\n try {\n const registryPath = resolveKeystoresRegistryPath();\n const entries = await readRegistry(registryPath);\n\n let message: string;\n if (entries.length === 0) {\n message = 'No keystores registered.';\n } else {\n const maxLen = Math.max(...entries.map((e) => e.name.length));\n message = entries.map((e) => `${e.name.padEnd(maxLen)} ${e.path}`).join('\\n');\n }\n\n return { success: true, data: entries, message };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n","import fs from 'node:fs/promises';\nimport type { CommandContext, CommandResult, ISubCommand, KeystoreEntry } from '@envctrl/types';\nimport { resolveKeystoresRegistryPath } from '../../utils/platform.js';\nimport { readRegistry, writeRegistry } from './registry.js';\n\n/** Options parsed by Commander for `keystore delete`. */\nexport interface KeystoreDeleteOptions {\n name: string;\n force: boolean;\n}\n\n/**\n * Deletes a named keystore directory and removes its entry from the registry.\n *\n * Requires `--force` flag to skip the confirmation guard. Without it,\n * the command exits early with a descriptive error.\n */\nexport class KeystoreDeleteSubCommand implements ISubCommand<KeystoreDeleteOptions, KeystoreEntry> {\n /** @inheritdoc */\n async execute(\n options: KeystoreDeleteOptions,\n _context: CommandContext,\n ): Promise<CommandResult<KeystoreEntry>> {\n const { name, force } = options;\n\n try {\n const registryPath = resolveKeystoresRegistryPath();\n const registry = await readRegistry(registryPath);\n const entry = registry.find((e) => e.name === name);\n\n if (!entry) {\n return {\n success: false,\n error: `keystore \"${name}\" not found in registry`,\n };\n }\n\n if (!force) {\n return {\n success: false,\n error: `pass --force to confirm deletion of keystore \"${name}\" at ${entry.path}`,\n };\n }\n\n const updated = registry.filter((e) => e.name !== name);\n await writeRegistry(registryPath, updated);\n\n await fs.rm(entry.path, { recursive: true, force: true });\n\n return {\n success: true,\n data: entry,\n message: `Deleted keystore: ${entry.name} (${entry.path})`,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n","import type { Command } from 'commander';\nimport { BaseCommand } from '../../base-command.js';\nimport { KeystoreCreateSubCommand } from './create.js';\nimport { KeystoreListSubCommand } from './list.js';\nimport { KeystoreDeleteSubCommand } from './delete.js';\n\n/** Registers the `keystore` command group onto the Commander program. */\nexport class KeystoreBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n const keystoreCmd = program\n .command('keystore')\n .description('Manage keystore directories for dotenvx private keys');\n\n keystoreCmd\n .command('create [path]')\n .description('Create a new keystore (defaults to platform app data folder)')\n .option('-n, --name <name>', 'name for the keystore entry in the registry')\n .action(async (keystorePath: string | undefined, opts: { name?: string }) => {\n await this.dispatch(\n new KeystoreCreateSubCommand(),\n { keystorePath, name: opts.name },\n this.buildContext(program),\n );\n });\n\n keystoreCmd\n .command('list')\n .description('List all registered keystores')\n .action(async () => {\n await this.dispatch(new KeystoreListSubCommand(), {}, this.buildContext(program));\n });\n\n keystoreCmd\n .command('delete <name>')\n .description('Delete a named keystore and remove it from the registry')\n .option('--force', 'skip confirmation and delete immediately', false)\n .action(async (name: string, opts: { force: boolean }) => {\n await this.dispatch(\n new KeystoreDeleteSubCommand(),\n { name, force: opts.force },\n this.buildContext(program),\n );\n });\n }\n}\n","import fs from 'node:fs/promises';\nimport type { Command } from 'commander';\nimport type { CommandContext, CommandResult, ISubCommand, SetResult } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { buildEnvFilePair, upsertEnvLine } from '../../utils/env-files.js';\nimport { setKeyValue } from '../../utils/dotenvx.js';\n\n/** Options parsed by Commander for the `set` subcommand. */\ninterface SetOptions {\n environment: string;\n key: string;\n value: string;\n}\n\n/**\n * Sets a single environment variable in both the unencrypted and encrypted files.\n *\n * Writes the key to the plaintext `.env.[env].unencrypted` file first to\n * maintain human-readable source of truth, then calls dotenvx `set` to\n * write and encrypt the value in `.env.[env]`.\n */\nexport class SetCommand implements ISubCommand<SetOptions, SetResult> {\n /** @inheritdoc */\n async execute(options: SetOptions, context: CommandContext): Promise<CommandResult<SetResult>> {\n const { environment, key, value } = options;\n const pair = buildEnvFilePair(environment, context.cwd);\n\n try {\n let existingContent = '';\n try {\n existingContent = await fs.readFile(pair.unencrypted, 'utf8');\n } catch {}\n\n const updatedContent = upsertEnvLine(existingContent, key, value);\n await fs.writeFile(pair.unencrypted, updatedContent, 'utf8');\n\n const result = setKeyValue(key, value, pair.encrypted);\n const changed = result.changedFilepaths.length > 0;\n\n return {\n success: true,\n data: { environment, key, changed },\n message: `Set ${key} in ${environment}`,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/** Registers the `set <environment> <key> <value>` command onto the Commander program. */\nexport class SetBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('set <environment> <key> <value>')\n .description('Set an environment variable and sync it to the encrypted file')\n .action(async (environment: string, key: string, value: string) => {\n await this.dispatch(\n new SetCommand(),\n { environment, key, value },\n this.buildContext(program),\n );\n });\n }\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Command } from 'commander';\nimport type { CommandContext, CommandResult, EncryptResult, ISubCommand } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { parseEnvironmentFromFilename } from '../../utils/env-files.js';\nimport { listEnvFiles, encryptFile } from '../../utils/dotenvx.js';\n\n/** Options parsed by Commander for the `encrypt` subcommand. */\ninterface EncryptOptions {\n files: string[];\n}\n\n/**\n * Encrypts existing plaintext `.env.*` files using dotenvx, backing up each file's\n * content to `.env.[env].unencrypted` before encrypting in-place.\n * Defaults to all `.env.*` files in the working directory when no files are specified.\n */\nexport class EncryptCommand implements ISubCommand<EncryptOptions, EncryptResult> {\n /** @inheritdoc */\n async execute(\n options: EncryptOptions,\n context: CommandContext,\n ): Promise<CommandResult<EncryptResult>> {\n const { cwd } = context;\n\n try {\n const targets =\n options.files.length > 0\n ? options.files.map((f) => path.resolve(cwd, f))\n : listEnvFiles(cwd, '.env.*', ['.env.keys', '*.unencrypted']);\n\n const changedFiles: string[] = [];\n const unchangedFiles: string[] = [];\n\n for (const filePath of targets) {\n const basename = path.basename(filePath);\n const environment = parseEnvironmentFromFilename(basename);\n\n if (!environment) {\n unchangedFiles.push(filePath);\n continue;\n }\n\n const unencryptedPath = path.resolve(\n path.dirname(filePath),\n `.env.${environment}.unencrypted`,\n );\n\n try {\n const content = await fs.readFile(filePath, 'utf8');\n\n try {\n await fs.access(unencryptedPath);\n } catch {\n await fs.writeFile(unencryptedPath, content, 'utf8');\n }\n\n const result = await encryptFile(filePath);\n changedFiles.push(...result.changedFilepaths);\n } catch {\n unchangedFiles.push(filePath);\n }\n }\n\n const lines: string[] = [\n ...changedFiles.map((f) => `Encrypted: ${f}`),\n ...unchangedFiles.map((f) => `Unchanged: ${f}`),\n ];\n\n return {\n success: true,\n data: { changedFiles, unchangedFiles },\n message: lines.length > 0 ? lines.join('\\n') : 'No files processed.',\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/** Registers the `encrypt [files...]` command onto the Commander program. */\nexport class EncryptBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('encrypt [files...]')\n .description('Encrypt plaintext .env.* files and create .unencrypted backups')\n .action(async (files: string[]) => {\n await this.dispatch(new EncryptCommand(), { files }, this.buildContext(program));\n });\n }\n}\n","import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { createInterface } from 'node:readline/promises';\nimport type { Command } from 'commander';\nimport type { CommandContext, CommandResult, InitResult, ISubCommand } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { resolveDefaultKeystorePath, resolveKeystoresRegistryPath } from '../../utils/platform.js';\nimport { listEnvFiles } from '../../utils/dotenvx.js';\nimport { readRegistry, writeRegistry } from '../keystore/registry.js';\nimport { findWorkspaceRoot, scanWorkspacePackages } from './workspace.js';\nimport { detectBuildEnvironment } from '../../utils/build-env.js';\nimport { writeConfig } from '../../utils/config.js';\n\n/**\n * Traverses up from `dir` to determine whether it is inside a git repository.\n */\nasync function isInsideGitRepo(dir: string): Promise<boolean> {\n let current = dir;\n while (true) {\n try {\n await fs.access(path.join(current, '.git'));\n return true;\n } catch {}\n const parent = path.dirname(current);\n if (parent === current) return false;\n current = parent;\n }\n}\n\n/**\n * Appends the given `patterns` to `rootDir/.gitignore`, skipping any that are\n * already present. Returns `true` when the file was modified.\n *\n * @param rootDir - Directory containing the `.gitignore` file\n * @param patterns - Lines to append (comments and glob patterns)\n */\nasync function appendGitignorePatterns(rootDir: string, patterns: string[]): Promise<boolean> {\n const gitignorePath = path.join(rootDir, '.gitignore');\n let existing = '';\n try {\n existing = await fs.readFile(gitignorePath, 'utf8');\n } catch {}\n\n const toAdd = patterns.filter((p) => !existing.includes(p));\n if (toAdd.length === 0) return false;\n\n const separator = existing === '' || existing.endsWith('\\n') ? '' : '\\n';\n await fs.writeFile(gitignorePath, `${existing}${separator}${toAdd.join('\\n')}\\n`, 'utf8');\n return true;\n}\n\n/** Options parsed by Commander for the `init` subcommand. */\ninterface InitOptions {\n workspace: string | undefined;\n name: string | undefined;\n keystore: string | undefined;\n /** Override the config directory name (default: `.envctrl`). */\n configDir: string | undefined;\n /** Override the config file name (default: `config.json`). */\n configFile: string | undefined;\n}\n\n/**\n * Initialises envctrl for an existing workspace or monorepo by creating a shared keystore,\n * symlinking `.env.keys` into every package directory, and writing a `.envctrl/config.json`\n * that records the active environment.\n *\n * When a recognised CI/CD provider (Vercel, Netlify, Railway) is detected via environment\n * variables, the environment is automatically resolved from the provider context instead of\n * defaulting to `\"development\"`.\n */\nexport class InitCommand implements ISubCommand<InitOptions, InitResult> {\n /** @inheritdoc */\n async execute(options: InitOptions, context: CommandContext): Promise<CommandResult<InitResult>> {\n const startDir = options.workspace\n ? path.resolve(context.cwd, options.workspace)\n : context.cwd;\n\n const configDir = options.configDir ?? '.envctrl';\n const configFile = options.configFile ?? 'config.json';\n\n try {\n const workspaceRoot = await findWorkspaceRoot(startDir);\n const packages = await scanWorkspacePackages(workspaceRoot);\n\n const keystorePath = options.keystore ?? resolveDefaultKeystorePath();\n const keystoreName = options.name ?? path.basename(workspaceRoot);\n\n await fs.mkdir(keystorePath, { recursive: true });\n\n const keysFile = path.join(keystorePath, '.env.keys');\n try {\n await fs.access(keysFile);\n } catch {\n await fs.writeFile(keysFile, '# dotenvx keys\\n', 'utf8');\n }\n\n const registryPath = resolveKeystoresRegistryPath();\n await fs.mkdir(path.dirname(registryPath), { recursive: true });\n const registry = await readRegistry(registryPath);\n const alreadyRegistered = registry.some(\n (e) => e.name === keystoreName || e.path === keystorePath,\n );\n if (!alreadyRegistered) {\n registry.push({ name: keystoreName, path: keystorePath });\n await writeRegistry(registryPath, registry);\n }\n\n const linkTargets = [\n workspaceRoot,\n ...packages.map((p) => path.resolve(workspaceRoot, p.path)),\n ];\n\n const keysLinked: string[] = [];\n\n for (const dir of linkTargets) {\n const envFiles = listEnvFiles(dir, '.env.*', ['.env.keys']);\n if (envFiles.length === 0) continue;\n\n const linkPath = path.join(dir, '.env.keys');\n try {\n await fs.access(linkPath);\n } catch {\n if (os.platform() === 'win32') {\n await fs.copyFile(keysFile, linkPath);\n } else {\n await fs.symlink(keysFile, linkPath);\n }\n keysLinked.push(linkPath);\n }\n }\n\n const buildEnv = detectBuildEnvironment();\n const environment = buildEnv.environment ?? 'development';\n const autoDetected = buildEnv.provider !== null;\n\n const configPath = await writeConfig(\n context.cwd,\n { environment },\n configDir,\n configFile,\n );\n\n let gitignoreUpdated = false;\n if (!context.quiet) {\n const inGit = await isInsideGitRepo(workspaceRoot);\n if (inGit) {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n const answer = await rl.question('Configure .gitignore for envctrl? [y/N] ');\n if (answer.trim().toLowerCase() === 'y' || answer.trim().toLowerCase() === 'yes') {\n gitignoreUpdated = await appendGitignorePatterns(workspaceRoot, [\n '# envctrl: unencrypted env files',\n '.env.*.unencrypted',\n ]);\n }\n } finally {\n rl.close();\n }\n }\n }\n\n const lines = [`Workspace: ${workspaceRoot}`, `Keystore: ${keystorePath}`];\n if (packages.length > 0) {\n lines.push('Packages:');\n for (const p of packages) lines.push(` ${p.name} (${p.path})`);\n }\n if (keysLinked.length > 0) {\n lines.push('Linked .env.keys:');\n for (const l of keysLinked) lines.push(` ${l}`);\n }\n lines.push(\n `Config: ${configPath}`,\n `Environment: ${environment}${autoDetected ? ` (auto-detected from ${buildEnv.provider})` : ''}`,\n );\n if (gitignoreUpdated) {\n lines.push(`Updated: ${path.join(workspaceRoot, '.gitignore')}`);\n }\n\n return {\n success: true,\n data: { workspaceRoot, packages, keystorePath, keysLinked, configPath, environment, autoDetected, gitignoreUpdated },\n message: lines.join('\\n'),\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/** Registers the `init [workspace]` command onto the Commander program. */\nexport class InitBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('init [workspace]')\n .description(\n 'Scan the workspace or monorepo and link packages to a shared keystore',\n )\n .option('-n, --name <name>', 'name for the keystore entry in the registry')\n .option('-k, --keystore <path>', 'custom keystore directory path')\n .option('--config-dir <dir>', 'config directory name (default: .envctrl)')\n .option('--config-file <file>', 'config file name (default: config.json)')\n .action(\n async (\n workspace: string | undefined,\n opts: { name?: string; keystore?: string; configDir?: string; configFile?: string },\n ) => {\n await this.dispatch(\n new InitCommand(),\n {\n workspace,\n name: opts.name,\n keystore: opts.keystore,\n configDir: opts.configDir,\n configFile: opts.configFile,\n },\n this.buildContext(program),\n );\n },\n );\n }\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { WorkspacePackage } from '@envctrl/types';\n\n/**\n * Traverses up from `startDir` to find the workspace root.\n *\n * A directory is considered the workspace root if it contains\n * `pnpm-workspace.yaml` or a `package.json` with a `workspaces` field.\n * Falls back to `startDir` if no root is found.\n */\nexport async function findWorkspaceRoot(startDir: string): Promise<string> {\n let dir = startDir;\n\n while (true) {\n try {\n await fs.access(path.join(dir, 'pnpm-workspace.yaml'));\n return dir;\n } catch {}\n\n try {\n const raw = await fs.readFile(path.join(dir, 'package.json'), 'utf8');\n const pkg = JSON.parse(raw) as { workspaces?: unknown };\n if (pkg.workspaces) return dir;\n } catch {}\n\n const parent = path.dirname(dir);\n if (parent === dir) return startDir;\n dir = parent;\n }\n}\n\n/**\n * Reads workspace package glob patterns from `pnpm-workspace.yaml` or\n * the `workspaces` field in `package.json`.\n */\nasync function readWorkspacePatterns(workspaceRoot: string): Promise<string[]> {\n try {\n const raw = await fs.readFile(path.join(workspaceRoot, 'pnpm-workspace.yaml'), 'utf8');\n const patterns: string[] = [];\n let inPackages = false;\n\n for (const line of raw.split('\\n')) {\n if (/^packages\\s*:/.test(line)) {\n inPackages = true;\n continue;\n }\n if (inPackages) {\n const match = line.match(/^\\s+-\\s+['\"]?([^'\"]+)['\"]?/);\n if (match) {\n patterns.push(match[1].trim());\n } else if (line.trim() && !line.startsWith('#')) {\n break;\n }\n }\n }\n\n if (patterns.length > 0) return patterns;\n } catch {}\n\n try {\n const raw = await fs.readFile(path.join(workspaceRoot, 'package.json'), 'utf8');\n const pkg = JSON.parse(raw) as {\n workspaces?: string[] | { packages: string[] };\n };\n if (Array.isArray(pkg.workspaces)) return pkg.workspaces;\n if (pkg.workspaces?.packages) return pkg.workspaces.packages;\n } catch {}\n\n return [];\n}\n\n/**\n * Expands a single workspace glob pattern (supporting one trailing `*`) into\n * matching subdirectory paths under `workspaceRoot`.\n */\nasync function expandPattern(workspaceRoot: string, pattern: string): Promise<string[]> {\n if (!pattern.includes('*')) {\n return [path.resolve(workspaceRoot, pattern)];\n }\n\n const starIndex = pattern.indexOf('*');\n const baseRelative = pattern.slice(0, starIndex).replace(/\\/$/, '');\n const suffix = pattern.slice(starIndex + 1);\n const baseDir = path.resolve(workspaceRoot, baseRelative);\n\n try {\n const entries = await fs.readdir(baseDir, { withFileTypes: true });\n return entries\n .filter((e) => e.isDirectory() && !e.name.startsWith('.'))\n .map((e) => path.join(baseDir, e.name + suffix));\n } catch {\n return [];\n }\n}\n\n/**\n * Scans `workspaceRoot` for all packages by expanding workspace glob patterns\n * and filtering directories that contain a `package.json`.\n */\nexport async function scanWorkspacePackages(workspaceRoot: string): Promise<WorkspacePackage[]> {\n const patterns = await readWorkspacePatterns(workspaceRoot);\n const packages: WorkspacePackage[] = [];\n\n for (const pattern of patterns) {\n const dirs = await expandPattern(workspaceRoot, pattern);\n\n for (const dir of dirs) {\n try {\n const raw = await fs.readFile(path.join(dir, 'package.json'), 'utf8');\n const pkg = JSON.parse(raw) as { name?: string };\n if (pkg.name) {\n packages.push({\n name: pkg.name,\n path: path.relative(workspaceRoot, dir),\n });\n }\n } catch {}\n }\n }\n\n return packages;\n}\n","/** Known CI/CD providers that supply their own environment context. */\nexport type BuildProvider = 'vercel' | 'netlify' | 'railway';\n\n/** Result of probing the current process environment for a CI/CD context. */\nexport interface DetectedBuildEnv {\n /** The provider that was identified, or `null` when no provider is detected. */\n readonly provider: BuildProvider | null;\n /**\n * The canonical environment name derived from the provider's own variables.\n * `null` when no provider is detected.\n */\n readonly environment: 'production' | 'development' | null;\n}\n\n/**\n * Inspects `process.env` for well-known CI/CD provider variables and maps\n * them to a canonical `production` / `development` environment name.\n *\n * - **Vercel** – `VERCEL=1`; `VERCEL_ENV` is `production` | `preview` | `development`\n * - **Netlify** – `NETLIFY=true`; `CONTEXT` is `production` | `deploy-preview` | `branch-deploy` | `dev`\n * - **Railway** – `RAILWAY_ENVIRONMENT_NAME` holds the environment name directly\n */\nexport function detectBuildEnvironment(): DetectedBuildEnv {\n if (process.env['VERCEL'] === '1') {\n const vercelEnv = process.env['VERCEL_ENV'];\n return {\n provider: 'vercel',\n environment: vercelEnv === 'production' ? 'production' : 'development',\n };\n }\n\n if (process.env['NETLIFY'] === 'true') {\n const context = process.env['CONTEXT'];\n return {\n provider: 'netlify',\n environment: context === 'production' ? 'production' : 'development',\n };\n }\n\n if (process.env['RAILWAY_ENVIRONMENT_NAME'] !== undefined) {\n const railwayEnv = process.env['RAILWAY_ENVIRONMENT_NAME'];\n return {\n provider: 'railway',\n environment: railwayEnv === 'production' ? 'production' : 'development',\n };\n }\n\n return { provider: null, environment: null };\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { EnvctrlConfig } from '@envctrl/types';\n\n/**\n * Returns the absolute path to the envctrl config file.\n *\n * @param cwd - Base directory (typically the project root).\n * @param dir - Config directory name relative to `cwd`. Defaults to `.envctrl`.\n * @param file - Config file name inside `dir`. Defaults to `config.json`.\n */\nexport function resolveConfigPath(\n cwd: string,\n dir = '.envctrl',\n file = 'config.json',\n): string {\n return path.join(cwd, dir, file);\n}\n\n/**\n * Reads and parses the envctrl config file.\n * Returns `null` when the file does not exist or cannot be parsed.\n *\n * @param cwd - Base directory (typically the project root).\n * @param dir - Config directory name relative to `cwd`. Defaults to `.envctrl`.\n * @param file - Config file name inside `dir`. Defaults to `config.json`.\n */\nexport async function readConfig(\n cwd: string,\n dir = '.envctrl',\n file = 'config.json',\n): Promise<EnvctrlConfig | null> {\n try {\n const raw = await fs.readFile(resolveConfigPath(cwd, dir, file), 'utf8');\n return JSON.parse(raw) as EnvctrlConfig;\n } catch {\n return null;\n }\n}\n\n/**\n * Writes `config` as JSON, creating the config directory if needed.\n *\n * @param cwd - Base directory (typically the project root).\n * @param config - Configuration object to persist.\n * @param dir - Config directory name relative to `cwd`. Defaults to `.envctrl`.\n * @param file - Config file name inside `dir`. Defaults to `config.json`.\n * @returns The absolute path of the written file.\n */\nexport async function writeConfig(\n cwd: string,\n config: EnvctrlConfig,\n dir = '.envctrl',\n file = 'config.json',\n): Promise<string> {\n const configDir = path.join(cwd, dir);\n await fs.mkdir(configDir, { recursive: true });\n const configPath = resolveConfigPath(cwd, dir, file);\n await fs.writeFile(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf8');\n return configPath;\n}\n","import path from 'node:path';\nimport type { Command } from 'commander';\nimport type { CommandContext, CommandResult, EnvironmentName, ISubCommand, ListResult } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { listEnvFiles } from '../../utils/dotenvx.js';\nimport { readBlacklist } from '../../utils/blacklist.js';\nimport { parseEnvironmentFromFilename } from '../../utils/env-files.js';\n\n/**\n * Lists all unique environment names discovered in the working directory by\n * scanning `.env.*` files, normalising `.local` and `.unencrypted` suffixes,\n * and filtering out blacklisted names.\n */\nexport class ListCommand implements ISubCommand<Record<string, never>, ListResult> {\n /** @inheritdoc */\n async execute(\n _options: Record<string, never>,\n context: CommandContext,\n ): Promise<CommandResult<ListResult>> {\n try {\n const [files, blacklist] = await Promise.all([\n Promise.resolve(listEnvFiles(context.cwd, '.env.*', ['.env.keys'])),\n readBlacklist(),\n ]);\n const blacklisted = new Set(blacklist);\n const names = files\n .map((f) => parseEnvironmentFromFilename(path.basename(f)))\n .filter((e): e is EnvironmentName => e !== undefined && !blacklisted.has(e));\n const environments = [...new Set(names)].sort();\n\n const message =\n environments.length > 0 ? environments.join('\\n') : 'No environments found.';\n\n return { success: true, data: { environments }, message };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/** Registers the `list` command onto the Commander program. */\nexport class ListBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('list')\n .description('List all environment names discovered in the working directory')\n .action(async () => {\n await this.dispatch(new ListCommand(), {}, this.buildContext(program));\n });\n }\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { EnvironmentName } from '@envctrl/types';\nimport { resolveBlacklistPath } from './platform.js';\n\n/** Reads the blacklist from disk, returning an empty array if it does not exist. */\nexport async function readBlacklist(): Promise<EnvironmentName[]> {\n try {\n const raw = await fs.readFile(resolveBlacklistPath(), 'utf8');\n return JSON.parse(raw) as EnvironmentName[];\n } catch {\n return [];\n }\n}\n\n/** Writes the blacklist to disk. */\nexport async function writeBlacklist(entries: EnvironmentName[]): Promise<void> {\n const filePath = resolveBlacklistPath();\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(filePath, JSON.stringify(entries, null, 2) + '\\n', 'utf8');\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Command } from 'commander';\nimport type { CommandContext, CommandResult, EnvironmentName, ISubCommand, RemoveResult } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { listEnvFiles } from '../../utils/dotenvx.js';\nimport { parseEnvironmentFromFilename } from '../../utils/env-files.js';\n\n/** Options parsed by Commander for the `rm` subcommand. */\ninterface RmOptions {\n environment: EnvironmentName;\n all: boolean;\n force: boolean;\n}\n\n/**\n * Removes environment files from the working directory.\n *\n * Without `--force`, performs a dry run listing files that would be deleted.\n * With `-a`, includes all associated file variants (`.local`, `.unencrypted`).\n * With `--force`, permanently deletes the resolved files.\n */\nexport class RmCommand implements ISubCommand<RmOptions, RemoveResult> {\n /** @inheritdoc */\n async execute(options: RmOptions, context: CommandContext): Promise<CommandResult<RemoveResult>> {\n const { environment, all, force } = options;\n\n try {\n const allFiles = listEnvFiles(context.cwd, '.env.*', ['.env.keys']);\n const candidates = allFiles.filter((f) => {\n const name = parseEnvironmentFromFilename(path.basename(f));\n return name === environment;\n });\n\n if (!all) {\n const primary = path.resolve(context.cwd, `.env.${environment}`);\n const subset = candidates.filter((f) => f === primary);\n return buildResult(environment, subset, force);\n }\n\n return buildResult(environment, candidates, force);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\nasync function buildResult(\n environment: EnvironmentName,\n files: string[],\n force: boolean,\n): Promise<CommandResult<RemoveResult>> {\n if (!force) {\n const preview = files.length > 0\n ? `Would delete:\\n${files.map((f) => ` ${f}`).join('\\n')}\\n\\nPass --force to confirm deletion.`\n : `No files found for environment: ${environment}`;\n\n return {\n success: true,\n data: { environment, deletedFiles: [] },\n message: preview,\n };\n }\n\n const deleted: string[] = [];\n for (const f of files) {\n try {\n await fs.rm(f, { force: true });\n deleted.push(f);\n } catch {}\n }\n\n const message =\n deleted.length > 0\n ? `Deleted:\\n${deleted.map((f) => ` ${f}`).join('\\n')}`\n : `No files found for environment: ${environment}`;\n\n return {\n success: true,\n data: { environment, deletedFiles: deleted },\n message,\n };\n}\n\n/** Registers the `rm <environment>` command onto the Commander program. */\nexport class RmBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('rm <environment>')\n .description('Remove environment files from the working directory')\n .option('-a, --all', 'include all associated file variants (.local, .unencrypted)', false)\n .option('--force', 'actually delete files (default is dry run)', false)\n .action(async (environment: string, opts: { all: boolean; force: boolean }) => {\n await this.dispatch(\n new RmCommand(),\n { environment, all: opts.all, force: opts.force },\n this.buildContext(program),\n );\n });\n }\n}\n","import type { Command } from 'commander';\nimport type { BlacklistResult, CommandContext, CommandResult, EnvironmentName, ISubCommand } from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { readBlacklist, writeBlacklist } from '../../utils/blacklist.js';\n\n/** Options parsed by Commander for `blacklist add`. */\ninterface BlacklistAddOptions {\n environment: EnvironmentName;\n}\n\n/** Options parsed by Commander for `blacklist rm`. */\ninterface BlacklistRmOptions {\n environment: EnvironmentName;\n}\n\n/**\n * Adds an environment name to the global blacklist, preventing it from\n * appearing in auto-detection results such as `envctrl list`.\n */\nexport class BlacklistAddSubCommand implements ISubCommand<BlacklistAddOptions, BlacklistResult> {\n /** @inheritdoc */\n async execute(\n options: BlacklistAddOptions,\n _context: CommandContext,\n ): Promise<CommandResult<BlacklistResult>> {\n const { environment } = options;\n\n try {\n const current = await readBlacklist();\n\n if (current.includes(environment)) {\n return {\n success: true,\n data: { environment, blacklisted: current },\n message: `Environment \"${environment}\" is already blacklisted.`,\n };\n }\n\n const updated = [...current, environment];\n await writeBlacklist(updated);\n\n return {\n success: true,\n data: { environment, blacklisted: updated },\n message: `Added \"${environment}\" to the blacklist.\\nBlacklisted environments:\\n${updated.map((e) => ` ${e}`).join('\\n')}`,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/**\n * Removes an environment name from the global blacklist, restoring it to\n * auto-detection results such as `envctrl list`.\n */\nexport class BlacklistRmSubCommand implements ISubCommand<BlacklistRmOptions, BlacklistResult> {\n /** @inheritdoc */\n async execute(\n options: BlacklistRmOptions,\n _context: CommandContext,\n ): Promise<CommandResult<BlacklistResult>> {\n const { environment } = options;\n\n try {\n const current = await readBlacklist();\n\n if (!current.includes(environment)) {\n return {\n success: false,\n error: `Environment \"${environment}\" is not in the blacklist.`,\n };\n }\n\n const updated = current.filter((e) => e !== environment);\n await writeBlacklist(updated);\n\n const message =\n updated.length > 0\n ? `Removed \"${environment}\" from the blacklist.\\nBlacklisted environments:\\n${updated.map((e) => ` ${e}`).join('\\n')}`\n : `Removed \"${environment}\" from the blacklist.\\nBlacklist is now empty.`;\n\n return {\n success: true,\n data: { environment, blacklisted: updated },\n message,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/** Registers the `blacklist` command group onto the Commander program. */\nexport class BlacklistBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n const blacklist = program\n .command('blacklist')\n .description('Manage the environment auto-detection blacklist');\n\n blacklist\n .command('add <environment>')\n .description('Exclude an environment from auto-detection')\n .action(async (environment: string) => {\n await this.dispatch(\n new BlacklistAddSubCommand(),\n { environment },\n this.buildContext(program),\n );\n });\n\n blacklist\n .command('rm <environment>')\n .description('Re-include an environment in auto-detection')\n .action(async (environment: string) => {\n await this.dispatch(\n new BlacklistRmSubCommand(),\n { environment },\n this.buildContext(program),\n );\n });\n }\n}\n","import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { createInterface } from 'node:readline/promises';\nimport type { Command } from 'commander';\nimport type {\n CommandContext,\n CommandResult,\n CreateResult,\n EnvironmentName,\n ISubCommand,\n} from '@envctrl/types';\nimport { BaseCommand } from '../../base-command.js';\nimport { listEnvFiles, setKeyValue } from '../../utils/dotenvx.js';\nimport { parseEnvContent, parseEnvironmentFromFilename, buildEnvFilePair } from '../../utils/env-files.js';\nimport { readConfig, writeConfig } from '../../utils/config.js';\nimport { syncUnencryptedToEncrypted } from '../switch/sync.js';\n\n/** Options parsed by Commander for the `create` subcommand. */\ninterface CreateOptions {\n environment: EnvironmentName;\n /**\n * Base environment whose key names are copied into the new environment (values set to empty).\n * Required when `environment` is `\"example\"` and omitted interactively; optional otherwise.\n */\n from: string | undefined;\n}\n\n/**\n * Returns the list of currently existing environment names by scanning `.env.*` files\n * in `cwd`, excluding `.env.keys` and `.env.example`.\n */\nasync function listExistingEnvironments(cwd: string): Promise<EnvironmentName[]> {\n const files = listEnvFiles(cwd, '.env.*', ['.env.keys']);\n const names = files\n .map((f) => parseEnvironmentFromFilename(path.basename(f)))\n .filter((e): e is EnvironmentName => e !== undefined);\n return [...new Set(names)];\n}\n\n/**\n * Reads an unencrypted env file and returns a derived string that preserves\n * comments and blank lines while clearing all values (key names only).\n */\nasync function buildExampleContent(unencryptedPath: string): Promise<string> {\n let raw = '';\n try {\n raw = await fs.readFile(unencryptedPath, 'utf8');\n } catch {\n return '';\n }\n\n const result = raw.split('\\n').map((line) => {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) {\n return line;\n }\n const eqIdx = trimmed.indexOf('=');\n if (eqIdx === -1) {\n return line;\n }\n return `${trimmed.slice(0, eqIdx).trim()}=`;\n });\n\n return result.join('\\n');\n}\n\n/**\n * Creates environments or generates a `.env.example` file.\n *\n * - `example`: Writes `.env.example` with key names (empty values) copied from a base\n * environment. If `--from` is omitted the user is prompted interactively.\n * - existing environment: Rejected with an error.\n * - new environment: Creates `.env.<env>.unencrypted` (empty, or pre-populated with key names\n * from `--from` base environment) and the encrypted `.env.<env>`, records the environment\n * in `.envctrl/config.json`, and re-encrypts `.env.local` from `.env.local.unencrypted`\n * if present.\n */\nexport class CreateCommand implements ISubCommand<CreateOptions, CreateResult> {\n /** @inheritdoc */\n async execute(\n options: CreateOptions,\n context: CommandContext,\n ): Promise<CommandResult<CreateResult>> {\n const { environment, cwd } = { ...options, cwd: context.cwd };\n\n try {\n if (environment === 'example') {\n return await this.createExample(options.from, cwd);\n }\n\n const existing = await listExistingEnvironments(cwd);\n if (existing.includes(environment)) {\n return {\n success: false,\n error: `Environment \"${environment}\" already exists. Use \"envctrl switch ${environment}\" to activate it.`,\n };\n }\n\n return await this.createEnvironment(environment, cwd, options.from);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n private async createExample(\n from: string | undefined,\n cwd: string,\n ): Promise<CommandResult<CreateResult>> {\n const existing = await listExistingEnvironments(cwd);\n\n let base = from;\n if (!base) {\n if (existing.length === 0) {\n return {\n success: false,\n error: 'No environments found. Create one first with \"envctrl create <environment>\".',\n };\n }\n\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n base = await rl.question(\n `Choose a base environment [${existing.join(', ')}]: `,\n );\n } finally {\n rl.close();\n }\n }\n\n if (!existing.includes(base)) {\n return {\n success: false,\n error: `Environment \"${base}\" does not exist. Available: ${existing.join(', ')}`,\n };\n }\n\n const pair = buildEnvFilePair(base, cwd);\n const content = await buildExampleContent(pair.unencrypted);\n const examplePath = path.resolve(cwd, '.env.example');\n await fs.writeFile(examplePath, content, 'utf8');\n\n return {\n success: true,\n data: {\n environment: 'example',\n createdFiles: [examplePath],\n isExample: true,\n baseEnvironment: base,\n },\n message: `Created .env.example from \"${base}\" (${Object.keys(parseEnvContent(content)).length} keys)`,\n };\n }\n\n private async createEnvironment(\n environment: EnvironmentName,\n cwd: string,\n from: string | undefined,\n ): Promise<CommandResult<CreateResult>> {\n const pair = buildEnvFilePair(environment, cwd);\n const created: string[] = [];\n\n if (from) {\n const existing = await listExistingEnvironments(cwd);\n if (!existing.includes(from)) {\n return {\n success: false,\n error: `Base environment \"${from}\" does not exist. Available: ${existing.join(', ')}`,\n };\n }\n const basePair = buildEnvFilePair(from, cwd);\n const content = await buildExampleContent(basePair.unencrypted);\n await fs.writeFile(pair.unencrypted, content, 'utf8');\n } else {\n await fs.writeFile(pair.unencrypted, '', 'utf8');\n }\n created.push(pair.unencrypted);\n\n if (from) {\n await syncUnencryptedToEncrypted(environment, cwd);\n } else {\n setKeyValue('_ENVCTRL_INIT', '1', pair.encrypted);\n }\n created.push(pair.encrypted);\n\n const config = (await readConfig(cwd)) ?? { environment };\n await writeConfig(cwd, { ...config, environment });\n\n const localUnencrypted = path.resolve(cwd, '.env.local.unencrypted');\n const localEncrypted = path.resolve(cwd, '.env.local');\n const localExists = await fs\n .access(localUnencrypted)\n .then(() => true)\n .catch(() => false);\n\n if (localExists) {\n await syncUnencryptedToEncrypted('local', cwd);\n } else {\n const encryptedLocalExists = await fs\n .access(localEncrypted)\n .then(() => true)\n .catch(() => false);\n\n if (!encryptedLocalExists) {\n if (os.platform() === 'win32') {\n await fs.copyFile(pair.encrypted, localEncrypted);\n } else {\n await fs.symlink(pair.encrypted, localEncrypted);\n }\n created.push(localEncrypted);\n }\n }\n\n const lines = [\n `Created environment: ${environment}${from ? ` (from \"${from}\")` : ''}`,\n 'Files:',\n ...created.map((f) => ` ${f}`),\n ];\n if (localExists) {\n lines.push(`Updated: ${localEncrypted}`);\n }\n\n return {\n success: true,\n data: { environment, createdFiles: created, isExample: false, baseEnvironment: from },\n message: lines.join('\\n'),\n };\n }\n}\n\n/** Registers the `create <environment>` command onto the Commander program. */\nexport class CreateBaseCommand extends BaseCommand {\n /** @inheritdoc */\n register(program: Command): void {\n program\n .command('create <environment>')\n .description(\n 'Create a new environment or generate .env.example (use \"example\" as the environment name)',\n )\n .option('--from <env>', 'copy key names (empty values) from this base environment')\n .action(async (environment: string, opts: { from?: string }) => {\n await this.dispatch(\n new CreateCommand(),\n { environment, from: opts.from },\n this.buildContext(program),\n );\n });\n }\n}\n"],"mappings":";;;AAAA,SAAS,iBAAAA,sBAAqB;AAC9B,SAAS,eAAe;;;ACDxB,OAAOC,SAAQ;AACf,OAAO,QAAQ;AACf,OAAOC,WAAU;;;ACQV,IAAe,cAAf,MAA2B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBhC,MAAgB,SACd,KACA,SACA,SACe;AACf,UAAM,SAAiC,MAAM,IAAI,QAAQ,SAAS,OAAO;AAEzE,QAAI,CAAC,OAAO,SAAS;AACnB,cAAQ,OAAO,MAAM,UAAU,OAAO,SAAS,eAAe;AAAA,CAAI;AAClE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI,CAAC,QAAQ,SAAS,OAAO,YAAY,QAAW;AAClD,cAAQ,OAAO,MAAM,OAAO,UAAU,IAAI;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOU,aAAaC,UAAkC;AACvD,UAAM,OAAOA,SAAQ,KAA0B;AAC/C,WAAO;AAAA,MACL,KAAK,QAAQ,IAAI;AAAA,MACjB,OAAO,KAAK,SAAS;AAAA,IACvB;AAAA,EACF;AACF;;;ACzDA,OAAO,UAAU;AAGjB,IAAM,qBAAqB,oBAAI,IAAI,CAAC,QAAQ,SAAS,CAAC;AAO/C,SAAS,6BAA6B,UAA+C;AAC1F,QAAM,OAAO,KAAK,SAAS,QAAQ;AAEnC,MAAI,CAAC,KAAK,WAAW,OAAO,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,KAAK,MAAM,QAAQ,MAAM;AAE/C,MAAI,CAAC,iBAAiB,mBAAmB,IAAI,aAAa,GAAG;AAC3D,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,cAAc,SAAS,cAAc,IAC5C,cAAc,MAAM,GAAG,CAAC,eAAe,MAAM,IAC7C;AAEJ,MAAI,KAAK,SAAS,QAAQ,GAAG;AAC3B,WAAO,KAAK,MAAM,GAAG,CAAC,SAAS,MAAM;AAAA,EACvC;AAEA,MAAI,CAAC,QAAQ,mBAAmB,IAAI,IAAI,GAAG;AACzC,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAQO,SAAS,iBAAiB,aAA8B,KAA0B;AACvF,SAAO;AAAA,IACL;AAAA,IACA,aAAa,KAAK,QAAQ,KAAK,QAAQ,WAAW,cAAc;AAAA,IAChE,WAAW,KAAK,QAAQ,KAAK,QAAQ,WAAW,EAAE;AAAA,EACpD;AACF;AASO,SAAS,gBAAgB,SAAyC;AACvE,QAAM,SAAiC,CAAC;AAExC,aAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,UAAM,UAAU,KAAK,KAAK;AAE1B,QAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,GAAG;AACvC;AAAA,IACF;AAEA,UAAM,QAAQ,QAAQ,QAAQ,GAAG;AACjC,QAAI,UAAU,IAAI;AAChB;AAAA,IACF;AAEA,UAAM,MAAM,QAAQ,MAAM,GAAG,KAAK,EAAE,KAAK;AACzC,UAAM,QAAQ,QAAQ,MAAM,QAAQ,CAAC,EAAE,KAAK;AAC5C,WAAO,GAAG,IAAI;AAAA,EAChB;AAEA,SAAO;AACT;AAYO,SAAS,cAAc,SAAiB,KAAa,OAAuB;AACjF,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAM,UAAU,IAAI,OAAO,IAAI,GAAG,OAAO;AACzC,MAAI,WAAW;AAEf,QAAM,UAAU,MAAM,IAAI,CAAC,SAAS;AAClC,QAAI,QAAQ,KAAK,IAAI,GAAG;AACtB,iBAAW;AACX,aAAO,GAAG,GAAG,IAAI,KAAK;AAAA,IACxB;AACA,WAAO;AAAA,EACT,CAAC;AAED,MAAI,CAAC,UAAU;AACb,QAAI,QAAQ,QAAQ,SAAS,CAAC,MAAM,IAAI;AACtC,cAAQ,KAAK,GAAG,GAAG,IAAI,KAAK,EAAE;AAAA,IAChC,OAAO;AACL,cAAQ,OAAO,QAAQ,SAAS,GAAG,GAAG,GAAG,GAAG,IAAI,KAAK,EAAE;AAAA,IACzD;AAAA,EACF;AAEA,SAAO,QAAQ,KAAK,IAAI;AAC1B;;;AClHA,SAAS,qBAAqB;AAC9B,OAAOC,WAAU;AACjB,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAC1B,YAAY,aAAa;AAGzB,IAAM,gBAAgB,UAAU,QAAQ;AAQxC,SAAS,oBAA4B;AACnC,QAAMC,WAAU,cAAc,YAAY,GAAG;AAC7C,QAAM,cAAcA,SAAQ,QAAQ,+BAA+B;AACnE,QAAM,UAAUA,SAAQ,+BAA+B;AAGvD,QAAM,aAAa,QAAQ,IAAI,SAAS;AACxC,SAAOD,MAAK,QAAQA,MAAK,QAAQ,WAAW,GAAG,UAAU;AAC3D;AAUO,SAAS,YACd,KACA,OACA,mBACA,cACkB;AAClB,QAAM,SAAiB,YAAI,KAAK,OAAO;AAAA,IACrC,MAAM;AAAA,IACN,SAAS;AAAA,IACT,OAAO;AAAA,IACP,GAAI,eAAe,EAAE,aAAa,aAAa,IAAI,CAAC;AAAA,EACtD,CAAC;AAED,SAAO;AAAA,IACL,kBAAkB,OAAO;AAAA,IACzB,oBAAoB,OAAO;AAAA,EAC7B;AACF;AAUA,eAAsB,YAAY,UAAiD;AACjF,QAAM,MAAM,kBAAkB;AAC9B,QAAM,cAAc,QAAQ,UAAU,CAAC,KAAK,WAAW,MAAM,QAAQ,CAAC;AAEtE,SAAO;AAAA,IACL,kBAAkB,CAAC,QAAQ;AAAA,IAC3B,oBAAoB,CAAC;AAAA,EACvB;AACF;AASO,SAAS,aACd,WACA,SACA,SACU;AACV,SAAe,WAAG,WAAW,SAAS,OAAO;AAC/C;;;ACnFA,OAAO,QAAQ;AAcf,eAAsB,2BACpB,aACA,KACe;AACf,QAAM,OAAO,iBAAiB,aAAa,GAAG;AAE9C,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,GAAG,SAAS,KAAK,aAAa,MAAM;AAAA,EACtD,QAAQ;AACN;AAAA,EACF;AAEA,QAAM,UAAU,gBAAgB,OAAO;AAEvC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,gBAAY,KAAK,OAAO,KAAK,SAAS;AAAA,EACxC;AACF;;;AJVO,IAAM,gBAAN,MAAwE;AAAA;AAAA,EAE7E,MAAM,QACJ,SACA,SACsC;AACtC,UAAM,EAAE,aAAa,IAAI,IAAI,EAAE,GAAG,SAAS,KAAK,QAAQ,IAAI;AAC5D,UAAM,OAAO,iBAAiB,aAAa,GAAG;AAC9C,UAAM,UAAoB,CAAC;AAE3B,QAAI;AACF,UAAI;AACF,cAAME,IAAG,OAAO,KAAK,WAAW;AAAA,MAClC,QAAQ;AACN,cAAMA,IAAG,UAAU,KAAK,aAAa,IAAI,MAAM;AAC/C,gBAAQ,KAAK,KAAK,WAAW;AAAA,MAC/B;AAEA,YAAM,kBAAkB,MAAMA,IAC3B,OAAO,KAAK,SAAS,EACrB,KAAK,MAAM,IAAI,EACf,MAAM,MAAM,KAAK;AAEpB,YAAM,2BAA2B,aAAa,GAAG;AAEjD,UAAI,CAAC,iBAAiB;AACpB,cAAM,eAAe,MAAMA,IACxB,OAAO,KAAK,SAAS,EACrB,KAAK,MAAM,KAAK,EAChB,MAAM,MAAM,IAAI;AAEnB,YAAI,cAAc;AAChB,sBAAY,iBAAiB,KAAK,KAAK,SAAS;AAChD,kBAAQ,KAAK,KAAK,SAAS;AAAA,QAC7B,OAAO;AACL,kBAAQ,KAAK,KAAK,SAAS;AAAA,QAC7B;AAAA,MACF;AAEA,YAAM,aAAaC,MAAK,QAAQ,KAAK,MAAM;AAE3C,UAAI;AACF,cAAMD,IAAG,OAAO,UAAU;AAAA,MAC5B,QAAQ;AAAA,MAAC;AAET,UAAI,GAAG,SAAS,MAAM,SAAS;AAC7B,cAAMA,IAAG,SAAS,KAAK,WAAW,UAAU;AAAA,MAC9C,OAAO;AACL,cAAMA,IAAG,QAAQ,KAAK,WAAW,UAAU;AAAA,MAC7C;AAEA,YAAM,QAAQ,CAAC,gBAAgB,WAAW,EAAE;AAC5C,UAAI,QAAQ,SAAS,GAAG;AACtB,cAAM,KAAK,YAAY,GAAG,QAAQ,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;AAAA,MACxD;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM,EAAE,aAAa,SAAS,WAAW;AAAA,QACzC,SAAS,MAAM,KAAK,IAAI;AAAA,MAC1B;AAAA,IACF,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,oBAAN,cAAgC,YAAY;AAAA;AAAA,EAEjD,SAASE,UAAwB;AAC/B,IAAAA,SACG,QAAQ,sBAAsB,EAC9B,YAAY,6DAA6D,EACzE,OAAO,OAAO,gBAAwB;AACrC,YAAM,KAAK,SAAS,IAAI,cAAc,GAAG,EAAE,YAAY,GAAG,KAAK,aAAaA,QAAO,CAAC;AAAA,IACtF,CAAC;AAAA,EACL;AACF;;;AKvGA,OAAOC,SAAQ;AACf,OAAOC,WAAU;;;ACDjB,OAAOC,SAAQ;AACf,OAAOC,WAAU;AASjB,SAAS,qBAA6B;AACpC,QAAM,WAAWD,IAAG,SAAS;AAC7B,QAAM,OAAOA,IAAG,QAAQ;AAExB,MAAI,aAAa,SAAS;AACxB,UAAM,UAAU,QAAQ,IAAI,SAAS,KAAKC,MAAK,KAAK,MAAM,WAAW,SAAS;AAC9E,WAAOA,MAAK,KAAK,SAAS,SAAS;AAAA,EACrC;AAEA,MAAI,aAAa,UAAU;AACzB,WAAOA,MAAK,KAAK,MAAM,WAAW,uBAAuB,SAAS;AAAA,EACpE;AAEA,QAAM,cAAc,QAAQ,IAAI,eAAe,KAAKA,MAAK,KAAK,MAAM,UAAU,OAAO;AACrF,SAAOA,MAAK,KAAK,aAAa,SAAS;AACzC;AASO,SAAS,6BAAqC;AACnD,SAAOA,MAAK,KAAK,mBAAmB,GAAG,aAAa,SAAS;AAC/D;AAQO,SAAS,+BAAuC;AACrD,SAAOA,MAAK,KAAK,mBAAmB,GAAG,gBAAgB;AACzD;AAGO,SAAS,uBAA+B;AAC7C,SAAOA,MAAK,KAAK,mBAAmB,GAAG,gBAAgB;AACzD;;;ACnDA,OAAOC,SAAQ;AAUf,eAAsB,aAAa,cAAgD;AACjF,MAAI;AACF,UAAM,MAAM,MAAMA,IAAG,SAAS,cAAc,MAAM;AAClD,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAQA,eAAsB,cAAc,cAAsB,SAAyC;AACjG,QAAMA,IAAG,UAAU,cAAc,KAAK,UAAU,SAAS,MAAM,CAAC,IAAI,MAAM,MAAM;AAClF;;;AFTO,IAAM,2BAAN,MAGL;AAAA;AAAA,EAEA,MAAM,QACJ,SACA,UACwC;AACxC,UAAM,eAAe,QAAQ,gBAAgB,2BAA2B;AACxE,UAAM,OAAO,QAAQ,QAAQC,MAAK,SAAS,YAAY;AAEvD,QAAI;AACF,YAAMC,IAAG,MAAM,cAAc,EAAE,WAAW,KAAK,CAAC;AAEhD,YAAM,WAAWD,MAAK,KAAK,cAAc,WAAW;AACpD,UAAI;AACF,cAAMC,IAAG,OAAO,QAAQ;AAAA,MAC1B,QAAQ;AACN,cAAMA,IAAG,UAAU,UAAU,oBAAoB,MAAM;AAAA,MACzD;AAEA,YAAM,eAAe,6BAA6B;AAClD,YAAMA,IAAG,MAAMD,MAAK,QAAQ,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AAE9D,YAAM,WAAW,MAAM,aAAa,YAAY;AAChD,YAAM,SAAS,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,SAAS,YAAY;AAE9E,UAAI,CAAC,QAAQ;AACX,iBAAS,KAAK,EAAE,MAAM,MAAM,aAAa,CAAC;AAC1C,cAAM,cAAc,cAAc,QAAQ;AAAA,MAC5C;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM,EAAE,MAAM,aAAa;AAAA,QAC3B,SAAS,wBAAwB,YAAY;AAAA,MAC/C;AAAA,IACF,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACF;;;AGtDO,IAAM,yBAAN,MAA4F;AAAA;AAAA,EAEjG,MAAM,QACJ,UACA,UACyC;AACzC,QAAI;AACF,YAAM,eAAe,6BAA6B;AAClD,YAAM,UAAU,MAAM,aAAa,YAAY;AAE/C,UAAI;AACJ,UAAI,QAAQ,WAAW,GAAG;AACxB,kBAAU;AAAA,MACZ,OAAO;AACL,cAAM,SAAS,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,KAAK,MAAM,CAAC;AAC5D,kBAAU,QAAQ,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,OAAO,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,IAAI;AAAA,MAC/E;AAEA,aAAO,EAAE,SAAS,MAAM,MAAM,SAAS,QAAQ;AAAA,IACjD,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACF;;;ACnCA,OAAOE,SAAQ;AAiBR,IAAM,2BAAN,MAA4F;AAAA;AAAA,EAEjG,MAAM,QACJ,SACA,UACuC;AACvC,UAAM,EAAE,MAAM,MAAM,IAAI;AAExB,QAAI;AACF,YAAM,eAAe,6BAA6B;AAClD,YAAM,WAAW,MAAM,aAAa,YAAY;AAChD,YAAM,QAAQ,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAElD,UAAI,CAAC,OAAO;AACV,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,aAAa,IAAI;AAAA,QAC1B;AAAA,MACF;AAEA,UAAI,CAAC,OAAO;AACV,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,iDAAiD,IAAI,QAAQ,MAAM,IAAI;AAAA,QAChF;AAAA,MACF;AAEA,YAAM,UAAU,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI;AACtD,YAAM,cAAc,cAAc,OAAO;AAEzC,YAAMC,IAAG,GAAG,MAAM,MAAM,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAExD,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SAAS,qBAAqB,MAAM,IAAI,KAAK,MAAM,IAAI;AAAA,MACzD;AAAA,IACF,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACF;;;ACtDO,IAAM,sBAAN,cAAkC,YAAY;AAAA;AAAA,EAEnD,SAASC,UAAwB;AAC/B,UAAM,cAAcA,SACjB,QAAQ,UAAU,EAClB,YAAY,sDAAsD;AAErE,gBACG,QAAQ,eAAe,EACvB,YAAY,8DAA8D,EAC1E,OAAO,qBAAqB,6CAA6C,EACzE,OAAO,OAAO,cAAkC,SAA4B;AAC3E,YAAM,KAAK;AAAA,QACT,IAAI,yBAAyB;AAAA,QAC7B,EAAE,cAAc,MAAM,KAAK,KAAK;AAAA,QAChC,KAAK,aAAaA,QAAO;AAAA,MAC3B;AAAA,IACF,CAAC;AAEH,gBACG,QAAQ,MAAM,EACd,YAAY,+BAA+B,EAC3C,OAAO,YAAY;AAClB,YAAM,KAAK,SAAS,IAAI,uBAAuB,GAAG,CAAC,GAAG,KAAK,aAAaA,QAAO,CAAC;AAAA,IAClF,CAAC;AAEH,gBACG,QAAQ,eAAe,EACvB,YAAY,yDAAyD,EACrE,OAAO,WAAW,4CAA4C,KAAK,EACnE,OAAO,OAAO,MAAc,SAA6B;AACxD,YAAM,KAAK;AAAA,QACT,IAAI,yBAAyB;AAAA,QAC7B,EAAE,MAAM,OAAO,KAAK,MAAM;AAAA,QAC1B,KAAK,aAAaA,QAAO;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,EACL;AACF;;;AC7CA,OAAOC,SAAQ;AAqBR,IAAM,aAAN,MAA+D;AAAA;AAAA,EAEpE,MAAM,QAAQ,SAAqB,SAA4D;AAC7F,UAAM,EAAE,aAAa,KAAK,MAAM,IAAI;AACpC,UAAM,OAAO,iBAAiB,aAAa,QAAQ,GAAG;AAEtD,QAAI;AACF,UAAI,kBAAkB;AACtB,UAAI;AACF,0BAAkB,MAAMC,IAAG,SAAS,KAAK,aAAa,MAAM;AAAA,MAC9D,QAAQ;AAAA,MAAC;AAET,YAAM,iBAAiB,cAAc,iBAAiB,KAAK,KAAK;AAChE,YAAMA,IAAG,UAAU,KAAK,aAAa,gBAAgB,MAAM;AAE3D,YAAM,SAAS,YAAY,KAAK,OAAO,KAAK,SAAS;AACrD,YAAM,UAAU,OAAO,iBAAiB,SAAS;AAEjD,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM,EAAE,aAAa,KAAK,QAAQ;AAAA,QAClC,SAAS,OAAO,GAAG,OAAO,WAAW;AAAA,MACvC;AAAA,IACF,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,iBAAN,cAA6B,YAAY;AAAA;AAAA,EAE9C,SAASC,UAAwB;AAC/B,IAAAA,SACG,QAAQ,iCAAiC,EACzC,YAAY,+DAA+D,EAC3E,OAAO,OAAO,aAAqB,KAAa,UAAkB;AACjE,YAAM,KAAK;AAAA,QACT,IAAI,WAAW;AAAA,QACf,EAAE,aAAa,KAAK,MAAM;AAAA,QAC1B,KAAK,aAAaA,QAAO;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,EACL;AACF;;;ACpEA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAiBV,IAAM,iBAAN,MAA2E;AAAA;AAAA,EAEhF,MAAM,QACJ,SACA,SACuC;AACvC,UAAM,EAAE,IAAI,IAAI;AAEhB,QAAI;AACF,YAAM,UACJ,QAAQ,MAAM,SAAS,IACnB,QAAQ,MAAM,IAAI,CAAC,MAAMC,MAAK,QAAQ,KAAK,CAAC,CAAC,IAC7C,aAAa,KAAK,UAAU,CAAC,aAAa,eAAe,CAAC;AAEhE,YAAM,eAAyB,CAAC;AAChC,YAAM,iBAA2B,CAAC;AAElC,iBAAW,YAAY,SAAS;AAC9B,cAAM,WAAWA,MAAK,SAAS,QAAQ;AACvC,cAAM,cAAc,6BAA6B,QAAQ;AAEzD,YAAI,CAAC,aAAa;AAChB,yBAAe,KAAK,QAAQ;AAC5B;AAAA,QACF;AAEA,cAAM,kBAAkBA,MAAK;AAAA,UAC3BA,MAAK,QAAQ,QAAQ;AAAA,UACrB,QAAQ,WAAW;AAAA,QACrB;AAEA,YAAI;AACF,gBAAM,UAAU,MAAMC,IAAG,SAAS,UAAU,MAAM;AAElD,cAAI;AACF,kBAAMA,IAAG,OAAO,eAAe;AAAA,UACjC,QAAQ;AACN,kBAAMA,IAAG,UAAU,iBAAiB,SAAS,MAAM;AAAA,UACrD;AAEA,gBAAM,SAAS,MAAM,YAAY,QAAQ;AACzC,uBAAa,KAAK,GAAG,OAAO,gBAAgB;AAAA,QAC9C,QAAQ;AACN,yBAAe,KAAK,QAAQ;AAAA,QAC9B;AAAA,MACF;AAEA,YAAM,QAAkB;AAAA,QACtB,GAAG,aAAa,IAAI,CAAC,MAAM,cAAc,CAAC,EAAE;AAAA,QAC5C,GAAG,eAAe,IAAI,CAAC,MAAM,cAAc,CAAC,EAAE;AAAA,MAChD;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM,EAAE,cAAc,eAAe;AAAA,QACrC,SAAS,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI;AAAA,MACjD;AAAA,IACF,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,qBAAN,cAAiC,YAAY;AAAA;AAAA,EAElD,SAASC,UAAwB;AAC/B,IAAAA,SACG,QAAQ,oBAAoB,EAC5B,YAAY,gEAAgE,EAC5E,OAAO,OAAO,UAAoB;AACjC,YAAM,KAAK,SAAS,IAAI,eAAe,GAAG,EAAE,MAAM,GAAG,KAAK,aAAaA,QAAO,CAAC;AAAA,IACjF,CAAC;AAAA,EACL;AACF;;;AC/FA,OAAOC,UAAQ;AACf,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,uBAAuB;;;ACHhC,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAUjB,eAAsB,kBAAkB,UAAmC;AACzE,MAAI,MAAM;AAEV,SAAO,MAAM;AACX,QAAI;AACF,YAAMD,IAAG,OAAOC,MAAK,KAAK,KAAK,qBAAqB,CAAC;AACrD,aAAO;AAAA,IACT,QAAQ;AAAA,IAAC;AAET,QAAI;AACF,YAAM,MAAM,MAAMD,IAAG,SAASC,MAAK,KAAK,KAAK,cAAc,GAAG,MAAM;AACpE,YAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,UAAI,IAAI,WAAY,QAAO;AAAA,IAC7B,QAAQ;AAAA,IAAC;AAET,UAAM,SAASA,MAAK,QAAQ,GAAG;AAC/B,QAAI,WAAW,IAAK,QAAO;AAC3B,UAAM;AAAA,EACR;AACF;AAMA,eAAe,sBAAsB,eAA0C;AAC7E,MAAI;AACF,UAAM,MAAM,MAAMD,IAAG,SAASC,MAAK,KAAK,eAAe,qBAAqB,GAAG,MAAM;AACrF,UAAM,WAAqB,CAAC;AAC5B,QAAI,aAAa;AAEjB,eAAW,QAAQ,IAAI,MAAM,IAAI,GAAG;AAClC,UAAI,gBAAgB,KAAK,IAAI,GAAG;AAC9B,qBAAa;AACb;AAAA,MACF;AACA,UAAI,YAAY;AACd,cAAM,QAAQ,KAAK,MAAM,4BAA4B;AACrD,YAAI,OAAO;AACT,mBAAS,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC;AAAA,QAC/B,WAAW,KAAK,KAAK,KAAK,CAAC,KAAK,WAAW,GAAG,GAAG;AAC/C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS,SAAS,EAAG,QAAO;AAAA,EAClC,QAAQ;AAAA,EAAC;AAET,MAAI;AACF,UAAM,MAAM,MAAMD,IAAG,SAASC,MAAK,KAAK,eAAe,cAAc,GAAG,MAAM;AAC9E,UAAM,MAAM,KAAK,MAAM,GAAG;AAG1B,QAAI,MAAM,QAAQ,IAAI,UAAU,EAAG,QAAO,IAAI;AAC9C,QAAI,IAAI,YAAY,SAAU,QAAO,IAAI,WAAW;AAAA,EACtD,QAAQ;AAAA,EAAC;AAET,SAAO,CAAC;AACV;AAMA,eAAe,cAAc,eAAuB,SAAoC;AACtF,MAAI,CAAC,QAAQ,SAAS,GAAG,GAAG;AAC1B,WAAO,CAACA,MAAK,QAAQ,eAAe,OAAO,CAAC;AAAA,EAC9C;AAEA,QAAM,YAAY,QAAQ,QAAQ,GAAG;AACrC,QAAM,eAAe,QAAQ,MAAM,GAAG,SAAS,EAAE,QAAQ,OAAO,EAAE;AAClE,QAAM,SAAS,QAAQ,MAAM,YAAY,CAAC;AAC1C,QAAM,UAAUA,MAAK,QAAQ,eAAe,YAAY;AAExD,MAAI;AACF,UAAM,UAAU,MAAMD,IAAG,QAAQ,SAAS,EAAE,eAAe,KAAK,CAAC;AACjE,WAAO,QACJ,OAAO,CAAC,MAAM,EAAE,YAAY,KAAK,CAAC,EAAE,KAAK,WAAW,GAAG,CAAC,EACxD,IAAI,CAAC,MAAMC,MAAK,KAAK,SAAS,EAAE,OAAO,MAAM,CAAC;AAAA,EACnD,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAMA,eAAsB,sBAAsB,eAAoD;AAC9F,QAAM,WAAW,MAAM,sBAAsB,aAAa;AAC1D,QAAM,WAA+B,CAAC;AAEtC,aAAW,WAAW,UAAU;AAC9B,UAAM,OAAO,MAAM,cAAc,eAAe,OAAO;AAEvD,eAAW,OAAO,MAAM;AACtB,UAAI;AACF,cAAM,MAAM,MAAMD,IAAG,SAASC,MAAK,KAAK,KAAK,cAAc,GAAG,MAAM;AACpE,cAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,YAAI,IAAI,MAAM;AACZ,mBAAS,KAAK;AAAA,YACZ,MAAM,IAAI;AAAA,YACV,MAAMA,MAAK,SAAS,eAAe,GAAG;AAAA,UACxC,CAAC;AAAA,QACH;AAAA,MACF,QAAQ;AAAA,MAAC;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AACT;;;ACpGO,SAAS,yBAA2C;AACzD,MAAI,QAAQ,IAAI,QAAQ,MAAM,KAAK;AACjC,UAAM,YAAY,QAAQ,IAAI,YAAY;AAC1C,WAAO;AAAA,MACL,UAAU;AAAA,MACV,aAAa,cAAc,eAAe,eAAe;AAAA,IAC3D;AAAA,EACF;AAEA,MAAI,QAAQ,IAAI,SAAS,MAAM,QAAQ;AACrC,UAAM,UAAU,QAAQ,IAAI,SAAS;AACrC,WAAO;AAAA,MACL,UAAU;AAAA,MACV,aAAa,YAAY,eAAe,eAAe;AAAA,IACzD;AAAA,EACF;AAEA,MAAI,QAAQ,IAAI,0BAA0B,MAAM,QAAW;AACzD,UAAM,aAAa,QAAQ,IAAI,0BAA0B;AACzD,WAAO;AAAA,MACL,UAAU;AAAA,MACV,aAAa,eAAe,eAAe,eAAe;AAAA,IAC5D;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,MAAM,aAAa,KAAK;AAC7C;;;AChDA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAUV,SAAS,kBACd,KACA,MAAM,YACN,OAAO,eACC;AACR,SAAOA,MAAK,KAAK,KAAK,KAAK,IAAI;AACjC;AAUA,eAAsB,WACpB,KACA,MAAM,YACN,OAAO,eACwB;AAC/B,MAAI;AACF,UAAM,MAAM,MAAMD,IAAG,SAAS,kBAAkB,KAAK,KAAK,IAAI,GAAG,MAAM;AACvE,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAWA,eAAsB,YACpB,KACA,QACA,MAAM,YACN,OAAO,eACU;AACjB,QAAM,YAAYC,MAAK,KAAK,KAAK,GAAG;AACpC,QAAMD,IAAG,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC7C,QAAM,aAAa,kBAAkB,KAAK,KAAK,IAAI;AACnD,QAAMA,IAAG,UAAU,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,MAAM;AAC7E,SAAO;AACT;;;AH3CA,eAAe,gBAAgB,KAA+B;AAC5D,MAAI,UAAU;AACd,SAAO,MAAM;AACX,QAAI;AACF,YAAME,KAAG,OAAOC,MAAK,KAAK,SAAS,MAAM,CAAC;AAC1C,aAAO;AAAA,IACT,QAAQ;AAAA,IAAC;AACT,UAAM,SAASA,MAAK,QAAQ,OAAO;AACnC,QAAI,WAAW,QAAS,QAAO;AAC/B,cAAU;AAAA,EACZ;AACF;AASA,eAAe,wBAAwB,SAAiB,UAAsC;AAC5F,QAAM,gBAAgBA,MAAK,KAAK,SAAS,YAAY;AACrD,MAAI,WAAW;AACf,MAAI;AACF,eAAW,MAAMD,KAAG,SAAS,eAAe,MAAM;AAAA,EACpD,QAAQ;AAAA,EAAC;AAET,QAAM,QAAQ,SAAS,OAAO,CAAC,MAAM,CAAC,SAAS,SAAS,CAAC,CAAC;AAC1D,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,QAAM,YAAY,aAAa,MAAM,SAAS,SAAS,IAAI,IAAI,KAAK;AACpE,QAAMA,KAAG,UAAU,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,KAAK,IAAI,CAAC;AAAA,GAAM,MAAM;AACxF,SAAO;AACT;AAsBO,IAAM,cAAN,MAAkE;AAAA;AAAA,EAEvE,MAAM,QAAQ,SAAsB,SAA6D;AAC/F,UAAM,WAAW,QAAQ,YACrBC,MAAK,QAAQ,QAAQ,KAAK,QAAQ,SAAS,IAC3C,QAAQ;AAEZ,UAAM,YAAY,QAAQ,aAAa;AACvC,UAAM,aAAa,QAAQ,cAAc;AAEzC,QAAI;AACF,YAAM,gBAAgB,MAAM,kBAAkB,QAAQ;AACtD,YAAM,WAAW,MAAM,sBAAsB,aAAa;AAE1D,YAAM,eAAe,QAAQ,YAAY,2BAA2B;AACpE,YAAM,eAAe,QAAQ,QAAQA,MAAK,SAAS,aAAa;AAEhE,YAAMD,KAAG,MAAM,cAAc,EAAE,WAAW,KAAK,CAAC;AAEhD,YAAM,WAAWC,MAAK,KAAK,cAAc,WAAW;AACpD,UAAI;AACF,cAAMD,KAAG,OAAO,QAAQ;AAAA,MAC1B,QAAQ;AACN,cAAMA,KAAG,UAAU,UAAU,oBAAoB,MAAM;AAAA,MACzD;AAEA,YAAM,eAAe,6BAA6B;AAClD,YAAMA,KAAG,MAAMC,MAAK,QAAQ,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9D,YAAM,WAAW,MAAM,aAAa,YAAY;AAChD,YAAM,oBAAoB,SAAS;AAAA,QACjC,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,SAAS;AAAA,MAC/C;AACA,UAAI,CAAC,mBAAmB;AACtB,iBAAS,KAAK,EAAE,MAAM,cAAc,MAAM,aAAa,CAAC;AACxD,cAAM,cAAc,cAAc,QAAQ;AAAA,MAC5C;AAEA,YAAM,cAAc;AAAA,QAClB;AAAA,QACA,GAAG,SAAS,IAAI,CAAC,MAAMA,MAAK,QAAQ,eAAe,EAAE,IAAI,CAAC;AAAA,MAC5D;AAEA,YAAM,aAAuB,CAAC;AAE9B,iBAAW,OAAO,aAAa;AAC7B,cAAM,WAAW,aAAa,KAAK,UAAU,CAAC,WAAW,CAAC;AAC1D,YAAI,SAAS,WAAW,EAAG;AAE3B,cAAM,WAAWA,MAAK,KAAK,KAAK,WAAW;AAC3C,YAAI;AACF,gBAAMD,KAAG,OAAO,QAAQ;AAAA,QAC1B,QAAQ;AACN,cAAIE,IAAG,SAAS,MAAM,SAAS;AAC7B,kBAAMF,KAAG,SAAS,UAAU,QAAQ;AAAA,UACtC,OAAO;AACL,kBAAMA,KAAG,QAAQ,UAAU,QAAQ;AAAA,UACrC;AACA,qBAAW,KAAK,QAAQ;AAAA,QAC1B;AAAA,MACF;AAEA,YAAM,WAAW,uBAAuB;AACxC,YAAM,cAAc,SAAS,eAAe;AAC5C,YAAM,eAAe,SAAS,aAAa;AAE3C,YAAM,aAAa,MAAM;AAAA,QACvB,QAAQ;AAAA,QACR,EAAE,YAAY;AAAA,QACd;AAAA,QACA;AAAA,MACF;AAEA,UAAI,mBAAmB;AACvB,UAAI,CAAC,QAAQ,OAAO;AAClB,cAAM,QAAQ,MAAM,gBAAgB,aAAa;AACjD,YAAI,OAAO;AACT,gBAAM,KAAK,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC3E,cAAI;AACF,kBAAM,SAAS,MAAM,GAAG,SAAS,0CAA0C;AAC3E,gBAAI,OAAO,KAAK,EAAE,YAAY,MAAM,OAAO,OAAO,KAAK,EAAE,YAAY,MAAM,OAAO;AAChF,iCAAmB,MAAM,wBAAwB,eAAe;AAAA,gBAC9D;AAAA,gBACA;AAAA,cACF,CAAC;AAAA,YACH;AAAA,UACF,UAAE;AACA,eAAG,MAAM;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAEA,YAAM,QAAQ,CAAC,cAAc,aAAa,IAAI,cAAc,YAAY,EAAE;AAC1E,UAAI,SAAS,SAAS,GAAG;AACvB,cAAM,KAAK,WAAW;AACtB,mBAAW,KAAK,SAAU,OAAM,KAAK,KAAK,EAAE,IAAI,KAAK,EAAE,IAAI,GAAG;AAAA,MAChE;AACA,UAAI,WAAW,SAAS,GAAG;AACzB,cAAM,KAAK,mBAAmB;AAC9B,mBAAW,KAAK,WAAY,OAAM,KAAK,KAAK,CAAC,EAAE;AAAA,MACjD;AACA,YAAM;AAAA,QACJ,cAAc,UAAU;AAAA,QACxB,gBAAgB,WAAW,GAAG,eAAe,wBAAwB,SAAS,QAAQ,MAAM,EAAE;AAAA,MAChG;AACA,UAAI,kBAAkB;AACpB,cAAM,KAAK,cAAcC,MAAK,KAAK,eAAe,YAAY,CAAC,EAAE;AAAA,MACnE;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM,EAAE,eAAe,UAAU,cAAc,YAAY,YAAY,aAAa,cAAc,iBAAiB;AAAA,QACnH,SAAS,MAAM,KAAK,IAAI;AAAA,MAC1B;AAAA,IACF,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,kBAAN,cAA8B,YAAY;AAAA;AAAA,EAE/C,SAASE,UAAwB;AAC/B,IAAAA,SACG,QAAQ,kBAAkB,EAC1B;AAAA,MACC;AAAA,IACF,EACC,OAAO,qBAAqB,6CAA6C,EACzE,OAAO,yBAAyB,gCAAgC,EAChE,OAAO,sBAAsB,2CAA2C,EACxE,OAAO,wBAAwB,yCAAyC,EACxE;AAAA,MACC,OACE,WACA,SACG;AACH,cAAM,KAAK;AAAA,UACT,IAAI,YAAY;AAAA,UAChB;AAAA,YACE;AAAA,YACA,MAAM,KAAK;AAAA,YACX,UAAU,KAAK;AAAA,YACf,WAAW,KAAK;AAAA,YAChB,YAAY,KAAK;AAAA,UACnB;AAAA,UACA,KAAK,aAAaA,QAAO;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACJ;AACF;;;AIlOA,OAAOC,YAAU;;;ACAjB,OAAOC,UAAQ;AACf,OAAOC,YAAU;AAKjB,eAAsB,gBAA4C;AAChE,MAAI;AACF,UAAM,MAAM,MAAMC,KAAG,SAAS,qBAAqB,GAAG,MAAM;AAC5D,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAGA,eAAsB,eAAe,SAA2C;AAC9E,QAAM,WAAW,qBAAqB;AACtC,QAAMA,KAAG,MAAMC,OAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAC1D,QAAMD,KAAG,UAAU,UAAU,KAAK,UAAU,SAAS,MAAM,CAAC,IAAI,MAAM,MAAM;AAC9E;;;ADPO,IAAM,cAAN,MAA4E;AAAA;AAAA,EAEjF,MAAM,QACJ,UACA,SACoC;AACpC,QAAI;AACF,YAAM,CAAC,OAAO,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,QAC3C,QAAQ,QAAQ,aAAa,QAAQ,KAAK,UAAU,CAAC,WAAW,CAAC,CAAC;AAAA,QAClE,cAAc;AAAA,MAChB,CAAC;AACD,YAAM,cAAc,IAAI,IAAI,SAAS;AACrC,YAAM,QAAQ,MACX,IAAI,CAAC,MAAM,6BAA6BE,OAAK,SAAS,CAAC,CAAC,CAAC,EACzD,OAAO,CAAC,MAA4B,MAAM,UAAa,CAAC,YAAY,IAAI,CAAC,CAAC;AAC7E,YAAM,eAAe,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC,EAAE,KAAK;AAE9C,YAAM,UACJ,aAAa,SAAS,IAAI,aAAa,KAAK,IAAI,IAAI;AAEtD,aAAO,EAAE,SAAS,MAAM,MAAM,EAAE,aAAa,GAAG,QAAQ;AAAA,IAC1D,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,kBAAN,cAA8B,YAAY;AAAA;AAAA,EAE/C,SAASC,UAAwB;AAC/B,IAAAA,SACG,QAAQ,MAAM,EACd,YAAY,gEAAgE,EAC5E,OAAO,YAAY;AAClB,YAAM,KAAK,SAAS,IAAI,YAAY,GAAG,CAAC,GAAG,KAAK,aAAaA,QAAO,CAAC;AAAA,IACvE,CAAC;AAAA,EACL;AACF;;;AEtDA,OAAOC,UAAQ;AACf,OAAOC,YAAU;AAqBV,IAAM,YAAN,MAAgE;AAAA;AAAA,EAErE,MAAM,QAAQ,SAAoB,SAA+D;AAC/F,UAAM,EAAE,aAAa,KAAK,MAAM,IAAI;AAEpC,QAAI;AACF,YAAM,WAAW,aAAa,QAAQ,KAAK,UAAU,CAAC,WAAW,CAAC;AAClE,YAAM,aAAa,SAAS,OAAO,CAAC,MAAM;AACxC,cAAM,OAAO,6BAA6BC,OAAK,SAAS,CAAC,CAAC;AAC1D,eAAO,SAAS;AAAA,MAClB,CAAC;AAED,UAAI,CAAC,KAAK;AACR,cAAM,UAAUA,OAAK,QAAQ,QAAQ,KAAK,QAAQ,WAAW,EAAE;AAC/D,cAAM,SAAS,WAAW,OAAO,CAAC,MAAM,MAAM,OAAO;AACrD,eAAO,YAAY,aAAa,QAAQ,KAAK;AAAA,MAC/C;AAEA,aAAO,YAAY,aAAa,YAAY,KAAK;AAAA,IACnD,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,YACb,aACA,OACA,OACsC;AACtC,MAAI,CAAC,OAAO;AACV,UAAM,UAAU,MAAM,SAAS,IAC3B;AAAA,EAAkB,MAAM,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA,qCACvD,mCAAmC,WAAW;AAElD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM,EAAE,aAAa,cAAc,CAAC,EAAE;AAAA,MACtC,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,UAAoB,CAAC;AAC3B,aAAW,KAAK,OAAO;AACrB,QAAI;AACF,YAAMC,KAAG,GAAG,GAAG,EAAE,OAAO,KAAK,CAAC;AAC9B,cAAQ,KAAK,CAAC;AAAA,IAChB,QAAQ;AAAA,IAAC;AAAA,EACX;AAEA,QAAM,UACJ,QAAQ,SAAS,IACb;AAAA,EAAa,QAAQ,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,KACpD,mCAAmC,WAAW;AAEpD,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM,EAAE,aAAa,cAAc,QAAQ;AAAA,IAC3C;AAAA,EACF;AACF;AAGO,IAAM,gBAAN,cAA4B,YAAY;AAAA;AAAA,EAE7C,SAASC,UAAwB;AAC/B,IAAAA,SACG,QAAQ,kBAAkB,EAC1B,YAAY,qDAAqD,EACjE,OAAO,aAAa,+DAA+D,KAAK,EACxF,OAAO,WAAW,8CAA8C,KAAK,EACrE,OAAO,OAAO,aAAqB,SAA2C;AAC7E,YAAM,KAAK;AAAA,QACT,IAAI,UAAU;AAAA,QACd,EAAE,aAAa,KAAK,KAAK,KAAK,OAAO,KAAK,MAAM;AAAA,QAChD,KAAK,aAAaA,QAAO;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,EACL;AACF;;;ACrFO,IAAM,yBAAN,MAA0F;AAAA;AAAA,EAE/F,MAAM,QACJ,SACA,UACyC;AACzC,UAAM,EAAE,YAAY,IAAI;AAExB,QAAI;AACF,YAAM,UAAU,MAAM,cAAc;AAEpC,UAAI,QAAQ,SAAS,WAAW,GAAG;AACjC,eAAO;AAAA,UACL,SAAS;AAAA,UACT,MAAM,EAAE,aAAa,aAAa,QAAQ;AAAA,UAC1C,SAAS,gBAAgB,WAAW;AAAA,QACtC;AAAA,MACF;AAEA,YAAM,UAAU,CAAC,GAAG,SAAS,WAAW;AACxC,YAAM,eAAe,OAAO;AAE5B,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM,EAAE,aAAa,aAAa,QAAQ;AAAA,QAC1C,SAAS,UAAU,WAAW;AAAA;AAAA,EAAmD,QAAQ,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,MAC1H;AAAA,IACF,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACF;AAMO,IAAM,wBAAN,MAAwF;AAAA;AAAA,EAE7F,MAAM,QACJ,SACA,UACyC;AACzC,UAAM,EAAE,YAAY,IAAI;AAExB,QAAI;AACF,YAAM,UAAU,MAAM,cAAc;AAEpC,UAAI,CAAC,QAAQ,SAAS,WAAW,GAAG;AAClC,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,gBAAgB,WAAW;AAAA,QACpC;AAAA,MACF;AAEA,YAAM,UAAU,QAAQ,OAAO,CAAC,MAAM,MAAM,WAAW;AACvD,YAAM,eAAe,OAAO;AAE5B,YAAM,UACJ,QAAQ,SAAS,IACb,YAAY,WAAW;AAAA;AAAA,EAAqD,QAAQ,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,KACnH,YAAY,WAAW;AAAA;AAE7B,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM,EAAE,aAAa,aAAa,QAAQ;AAAA,QAC1C;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,uBAAN,cAAmC,YAAY;AAAA;AAAA,EAEpD,SAASC,UAAwB;AAC/B,UAAM,YAAYA,SACf,QAAQ,WAAW,EACnB,YAAY,iDAAiD;AAEhE,cACG,QAAQ,mBAAmB,EAC3B,YAAY,4CAA4C,EACxD,OAAO,OAAO,gBAAwB;AACrC,YAAM,KAAK;AAAA,QACT,IAAI,uBAAuB;AAAA,QAC3B,EAAE,YAAY;AAAA,QACd,KAAK,aAAaA,QAAO;AAAA,MAC3B;AAAA,IACF,CAAC;AAEH,cACG,QAAQ,kBAAkB,EAC1B,YAAY,6CAA6C,EACzD,OAAO,OAAO,gBAAwB;AACrC,YAAM,KAAK;AAAA,QACT,IAAI,sBAAsB;AAAA,QAC1B,EAAE,YAAY;AAAA,QACd,KAAK,aAAaA,QAAO;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,EACL;AACF;;;ACjIA,OAAOC,UAAQ;AACf,OAAOC,SAAQ;AACf,OAAOC,YAAU;AACjB,SAAS,mBAAAC,wBAAuB;AA6BhC,eAAe,yBAAyB,KAAyC;AAC/E,QAAM,QAAQ,aAAa,KAAK,UAAU,CAAC,WAAW,CAAC;AACvD,QAAM,QAAQ,MACX,IAAI,CAAC,MAAM,6BAA6BC,OAAK,SAAS,CAAC,CAAC,CAAC,EACzD,OAAO,CAAC,MAA4B,MAAM,MAAS;AACtD,SAAO,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;AAC3B;AAMA,eAAe,oBAAoB,iBAA0C;AAC3E,MAAI,MAAM;AACV,MAAI;AACF,UAAM,MAAMC,KAAG,SAAS,iBAAiB,MAAM;AAAA,EACjD,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,IAAI,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS;AAC3C,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,GAAG;AACvC,aAAO;AAAA,IACT;AACA,UAAM,QAAQ,QAAQ,QAAQ,GAAG;AACjC,QAAI,UAAU,IAAI;AAChB,aAAO;AAAA,IACT;AACA,WAAO,GAAG,QAAQ,MAAM,GAAG,KAAK,EAAE,KAAK,CAAC;AAAA,EAC1C,CAAC;AAED,SAAO,OAAO,KAAK,IAAI;AACzB;AAaO,IAAM,gBAAN,MAAwE;AAAA;AAAA,EAE7E,MAAM,QACJ,SACA,SACsC;AACtC,UAAM,EAAE,aAAa,IAAI,IAAI,EAAE,GAAG,SAAS,KAAK,QAAQ,IAAI;AAE5D,QAAI;AACF,UAAI,gBAAgB,WAAW;AAC7B,eAAO,MAAM,KAAK,cAAc,QAAQ,MAAM,GAAG;AAAA,MACnD;AAEA,YAAM,WAAW,MAAM,yBAAyB,GAAG;AACnD,UAAI,SAAS,SAAS,WAAW,GAAG;AAClC,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,gBAAgB,WAAW,yCAAyC,WAAW;AAAA,QACxF;AAAA,MACF;AAEA,aAAO,MAAM,KAAK,kBAAkB,aAAa,KAAK,QAAQ,IAAI;AAAA,IACpE,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,cACZ,MACA,KACsC;AACtC,UAAM,WAAW,MAAM,yBAAyB,GAAG;AAEnD,QAAI,OAAO;AACX,QAAI,CAAC,MAAM;AACT,UAAI,SAAS,WAAW,GAAG;AACzB,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO;AAAA,QACT;AAAA,MACF;AAEA,YAAM,KAAKC,iBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC3E,UAAI;AACF,eAAO,MAAM,GAAG;AAAA,UACd,8BAA8B,SAAS,KAAK,IAAI,CAAC;AAAA,QACnD;AAAA,MACF,UAAE;AACA,WAAG,MAAM;AAAA,MACX;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,SAAS,IAAI,GAAG;AAC5B,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,gBAAgB,IAAI,gCAAgC,SAAS,KAAK,IAAI,CAAC;AAAA,MAChF;AAAA,IACF;AAEA,UAAM,OAAO,iBAAiB,MAAM,GAAG;AACvC,UAAM,UAAU,MAAM,oBAAoB,KAAK,WAAW;AAC1D,UAAM,cAAcF,OAAK,QAAQ,KAAK,cAAc;AACpD,UAAMC,KAAG,UAAU,aAAa,SAAS,MAAM;AAE/C,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,QACJ,aAAa;AAAA,QACb,cAAc,CAAC,WAAW;AAAA,QAC1B,WAAW;AAAA,QACX,iBAAiB;AAAA,MACnB;AAAA,MACA,SAAS,8BAA8B,IAAI,MAAM,OAAO,KAAK,gBAAgB,OAAO,CAAC,EAAE,MAAM;AAAA,IAC/F;AAAA,EACF;AAAA,EAEA,MAAc,kBACZ,aACA,KACA,MACsC;AACtC,UAAM,OAAO,iBAAiB,aAAa,GAAG;AAC9C,UAAM,UAAoB,CAAC;AAE3B,QAAI,MAAM;AACR,YAAM,WAAW,MAAM,yBAAyB,GAAG;AACnD,UAAI,CAAC,SAAS,SAAS,IAAI,GAAG;AAC5B,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,qBAAqB,IAAI,gCAAgC,SAAS,KAAK,IAAI,CAAC;AAAA,QACrF;AAAA,MACF;AACA,YAAM,WAAW,iBAAiB,MAAM,GAAG;AAC3C,YAAM,UAAU,MAAM,oBAAoB,SAAS,WAAW;AAC9D,YAAMA,KAAG,UAAU,KAAK,aAAa,SAAS,MAAM;AAAA,IACtD,OAAO;AACL,YAAMA,KAAG,UAAU,KAAK,aAAa,IAAI,MAAM;AAAA,IACjD;AACA,YAAQ,KAAK,KAAK,WAAW;AAE7B,QAAI,MAAM;AACR,YAAM,2BAA2B,aAAa,GAAG;AAAA,IACnD,OAAO;AACL,kBAAY,iBAAiB,KAAK,KAAK,SAAS;AAAA,IAClD;AACA,YAAQ,KAAK,KAAK,SAAS;AAE3B,UAAM,SAAU,MAAM,WAAW,GAAG,KAAM,EAAE,YAAY;AACxD,UAAM,YAAY,KAAK,EAAE,GAAG,QAAQ,YAAY,CAAC;AAEjD,UAAM,mBAAmBD,OAAK,QAAQ,KAAK,wBAAwB;AACnE,UAAM,iBAAiBA,OAAK,QAAQ,KAAK,YAAY;AACrD,UAAM,cAAc,MAAMC,KACvB,OAAO,gBAAgB,EACvB,KAAK,MAAM,IAAI,EACf,MAAM,MAAM,KAAK;AAEpB,QAAI,aAAa;AACf,YAAM,2BAA2B,SAAS,GAAG;AAAA,IAC/C,OAAO;AACL,YAAM,uBAAuB,MAAMA,KAChC,OAAO,cAAc,EACrB,KAAK,MAAM,IAAI,EACf,MAAM,MAAM,KAAK;AAEpB,UAAI,CAAC,sBAAsB;AACzB,YAAIE,IAAG,SAAS,MAAM,SAAS;AAC7B,gBAAMF,KAAG,SAAS,KAAK,WAAW,cAAc;AAAA,QAClD,OAAO;AACL,gBAAMA,KAAG,QAAQ,KAAK,WAAW,cAAc;AAAA,QACjD;AACA,gBAAQ,KAAK,cAAc;AAAA,MAC7B;AAAA,IACF;AAEA,UAAM,QAAQ;AAAA,MACZ,wBAAwB,WAAW,GAAG,OAAO,WAAW,IAAI,OAAO,EAAE;AAAA,MACrE;AAAA,MACA,GAAG,QAAQ,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;AAAA,IAChC;AACA,QAAI,aAAa;AACf,YAAM,KAAK,YAAY,cAAc,EAAE;AAAA,IACzC;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM,EAAE,aAAa,cAAc,SAAS,WAAW,OAAO,iBAAiB,KAAK;AAAA,MACpF,SAAS,MAAM,KAAK,IAAI;AAAA,IAC1B;AAAA,EACF;AACF;AAGO,IAAM,oBAAN,cAAgC,YAAY;AAAA;AAAA,EAEjD,SAASG,UAAwB;AAC/B,IAAAA,SACG,QAAQ,sBAAsB,EAC9B;AAAA,MACC;AAAA,IACF,EACC,OAAO,gBAAgB,0DAA0D,EACjF,OAAO,OAAO,aAAqB,SAA4B;AAC9D,YAAM,KAAK;AAAA,QACT,IAAI,cAAc;AAAA,QAClB,EAAE,aAAa,MAAM,KAAK,KAAK;AAAA,QAC/B,KAAK,aAAaA,QAAO;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,EACL;AACF;;;AtB/OA,IAAM,WAAWC,eAAc,YAAY,GAAG;AAC9C,IAAM,EAAE,QAAQ,IAAI,SAAS,iBAAiB;AAE9C,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,SAAS,EACd,YAAY,qDAAqD,EACjE,QAAQ,OAAO,EACf,YAAY,aAAa,YAAY,OAAO;AAAA,CAAI,EAChD,OAAO,eAAe,mBAAmB,KAAK;AAEjD,IAAI,gBAAgB,EAAE,SAAS,OAAO;AACtC,IAAI,kBAAkB,EAAE,SAAS,OAAO;AACxC,IAAI,gBAAgB,EAAE,SAAS,OAAO;AACtC,IAAI,kBAAkB,EAAE,SAAS,OAAO;AACxC,IAAI,oBAAoB,EAAE,SAAS,OAAO;AAC1C,IAAI,eAAe,EAAE,SAAS,OAAO;AACrC,IAAI,mBAAmB,EAAE,SAAS,OAAO;AACzC,IAAI,cAAc,EAAE,SAAS,OAAO;AACpC,IAAI,qBAAqB,EAAE,SAAS,OAAO;AAE3C,QAAQ,WAAW,QAAQ,IAAI;","names":["createRequire","fs","path","program","path","require","fs","path","program","fs","path","os","path","fs","path","fs","fs","fs","program","fs","fs","program","fs","path","path","fs","program","fs","os","path","fs","path","fs","path","fs","path","os","program","path","fs","path","fs","path","path","program","fs","path","path","fs","program","program","fs","os","path","createInterface","path","fs","createInterface","os","program","createRequire"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@envctrl/cli",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -21,7 +21,7 @@
21
21
  "tsup": "^8.5.0",
22
22
  "typescript": "^5.8.0",
23
23
  "vitest": "^3.0.0",
24
- "@envctrl/types": "1.5.0"
24
+ "@envctrl/types": "1.6.0"
25
25
  },
26
26
  "scripts": {
27
27
  "build": "tsup",