import { z, ZodObject } from 'zod'; import { OptionValues, Command, InferCommandArguments, Option, CommandUnknownOpts } from '@commander-js/extra-typings'; /** * Dotenv provenance model (descriptor-only). * * Requirements addressed: * - Host ctx carries a dotenv provenance mapping describing per-key origin and override history. * - Provenance is descriptor-only (no value payloads). * - Provenance is an ordered stack per key in ascending precedence; the last entry is effective. * - Explicit unsets are represented as `op: 'unset'` without requiring deletion of keys from the env map. */ /** * Provenance kind for an entry in {@link DotenvProvenance}. * * @public */ type DotenvProvenanceKind = 'file' | 'config' | 'vars' | 'dynamic'; /** * Operation represented by a provenance entry. * * @public */ type DotenvProvenanceOp = 'set' | 'unset'; /** * Base shape for all provenance entries. * * @public */ interface DotenvProvenanceEntryBase { /** * The kind of provenance entry. */ kind: DotenvProvenanceKind; /** * The operation applied at this layer. */ op: DotenvProvenanceOp; } /** * Provenance entry representing a value sourced from a dotenv file in the cascade. * * @public */ interface DotenvFileProvenanceEntry extends DotenvProvenanceEntryBase { /** Discriminator. */ kind: 'file'; /** Global vs env-scoped file. */ scope: 'global' | 'env'; /** Public vs private file. */ privacy: 'public' | 'private'; /** Environment name (required when scope is `env`). */ env?: string; /** * The corresponding `paths[]` entry as provided by the caller/CLI. * This is not an absolute path by policy. */ path: string; /** * The computed dotenv filename token (e.g., `.env`, `.env.dev`, `.env.local`, `.env.dev.local`). */ file: string; } /** * Provenance entry representing a value sourced from config overlays (`vars` / `envVars`). * * @public */ interface DotenvConfigProvenanceEntry extends DotenvProvenanceEntryBase { /** Discriminator. */ kind: 'config'; /** Global vs env-scoped config slice. */ scope: 'global' | 'env'; /** Public vs private on the privacy axis (`local` config maps to `private`). */ privacy: 'public' | 'private'; /** Environment name (required when scope is `env`). */ env?: string; /** Packaged vs project config origin. */ configScope: 'packaged' | 'project'; /** Public vs local config file. */ configPrivacy: 'public' | 'local'; } /** * Provenance entry representing explicit variables overrides. * * Notes: * - This kind represents values injected via `vars` (CLI/programmatic), not dotenv files. * * @public */ interface DotenvVarsProvenanceEntry extends DotenvProvenanceEntryBase { /** Discriminator. */ kind: 'vars'; } /** * Source tier for dynamic variables. * * @public */ type DotenvDynamicSource = 'config' | 'programmatic' | 'dynamicPath'; /** * Provenance entry representing dynamic variables. * * @public */ interface DotenvDynamicProvenanceEntry extends DotenvProvenanceEntryBase { /** Discriminator. */ kind: 'dynamic'; /** Dynamic source tier. */ dynamicSource: DotenvDynamicSource; /** * The `dynamicPath` value as provided by the caller/CLI when `dynamicSource` is `dynamicPath`. * This is not resolved to an absolute path by provenance policy. */ dynamicPath?: string; } /** * Union of all supported provenance entry shapes. * * @public */ type DotenvProvenanceEntry = DotenvFileProvenanceEntry | DotenvConfigProvenanceEntry | DotenvVarsProvenanceEntry | DotenvDynamicProvenanceEntry; /** * Per-key provenance history. * * Each key maps to an array of entries ordered in ascending precedence (lower to higher). * * @public */ type DotenvProvenance = Record; /** * Resolved CLI options schema. * For the current step this mirrors the RAW schema; later stages may further * narrow types post-resolution in the host pipeline. */ /** * CLI options schema (resolved). * * Today this mirrors {@link getDotenvCliOptionsSchemaRaw}, but is kept as a distinct export * so future resolution steps can narrow or materialize defaults without breaking the API. * * @public */ declare const getDotenvCliOptionsSchemaResolved: z.ZodObject<{ defaultEnv: z.ZodOptional; defaultEnvKey: z.ZodOptional; dotenvToken: z.ZodOptional; dynamicPath: z.ZodOptional; dynamic: z.ZodOptional>; env: z.ZodOptional; excludeDynamic: z.ZodOptional; excludeEnv: z.ZodOptional; excludeGlobal: z.ZodOptional; excludePrivate: z.ZodOptional; excludePublic: z.ZodOptional; loadProcess: z.ZodOptional; log: z.ZodOptional; logger: z.ZodDefault; outputPath: z.ZodOptional; privateToken: z.ZodOptional; debug: z.ZodOptional; strict: z.ZodOptional; capture: z.ZodOptional; trace: z.ZodOptional]>>; redact: z.ZodOptional; warnEntropy: z.ZodOptional; entropyThreshold: z.ZodOptional; entropyMinLength: z.ZodOptional; entropyWhitelist: z.ZodOptional>; redactPatterns: z.ZodOptional>; paths: z.ZodOptional; pathsDelimiter: z.ZodOptional; pathsDelimiterPattern: z.ZodOptional; scripts: z.ZodOptional>; shell: z.ZodOptional>; vars: z.ZodOptional; varsAssignor: z.ZodOptional; varsAssignorPattern: z.ZodOptional; varsDelimiter: z.ZodOptional; varsDelimiterPattern: z.ZodOptional; }, z.core.$strip>; /** * Resolved programmatic options schema (post-inheritance). * For now, this mirrors the RAW schema; future stages may materialize defaults * and narrow shapes as resolution is wired into the host. */ /** * Programmatic options schema (resolved). * * Today this mirrors {@link getDotenvOptionsSchemaRaw}, but is kept as a distinct export * so future resolution steps can narrow or materialize defaults without breaking the API. * * @public */ declare const getDotenvOptionsSchemaResolved: z.ZodObject<{ defaultEnv: z.ZodOptional; defaultEnvKey: z.ZodOptional; dotenvToken: z.ZodOptional; dynamicPath: z.ZodOptional; dynamic: z.ZodOptional>; env: z.ZodOptional; excludeDynamic: z.ZodOptional; excludeEnv: z.ZodOptional; excludeGlobal: z.ZodOptional; excludePrivate: z.ZodOptional; excludePublic: z.ZodOptional; loadProcess: z.ZodOptional; log: z.ZodOptional; logger: z.ZodDefault; outputPath: z.ZodOptional; paths: z.ZodOptional>; privateToken: z.ZodOptional; vars: z.ZodOptional>>; }, z.core.$strip>; /** * Minimal root options shape shared by CLI and generator layers. * Keep keys optional to respect exactOptionalPropertyTypes semantics. * * @public */ interface RootOptionsShape { /** Target environment (dotenv-expanded). */ env?: string; /** Explicit variable overrides (dotenv-expanded). */ vars?: string; /** Command to execute (dotenv-expanded). */ command?: string; /** Output path for the consolidated environment file (dotenv-expanded). */ outputPath?: string; /** * Shell execution strategy. * - `true`: use default OS shell. * - `false`: use plain execution (no shell). * - string: use specific shell path. */ shell?: string | boolean; /** Whether to load variables into `process.env`. */ loadProcess?: boolean; /** Exclude all variables from loading. */ excludeAll?: boolean; /** Exclude dynamic variables. */ excludeDynamic?: boolean; /** Exclude environment-specific variables. */ excludeEnv?: boolean; /** Exclude global variables. */ excludeGlobal?: boolean; /** Exclude private variables. */ excludePrivate?: boolean; /** Exclude public variables. */ excludePublic?: boolean; /** Enable console logging of loaded variables. */ log?: boolean; /** Enable debug logging to stderr. */ debug?: boolean; /** Capture child process stdio (useful for tests/CI). */ capture?: boolean; /** Fail on validation errors (schema/requiredKeys). */ strict?: boolean; /** Enable presentation-time redaction of secret-like keys. */ redact?: boolean; /** Enable entropy warnings for high-entropy values. */ warnEntropy?: boolean; /** Entropy threshold (bits/char) for warnings (default 3.8). */ entropyThreshold?: number; /** Minimum string length to check for entropy (default 16). */ entropyMinLength?: number; /** Regex patterns for keys to exclude from entropy checks. */ entropyWhitelist?: ReadonlyArray; /** Additional regex patterns for keys to redact. */ redactPatterns?: string[]; /** Default target environment when not specified. */ defaultEnv?: string; /** Env var name in global dotenv files that specifies the default environment. */ defaultEnvKey?: string; /** Token indicating a dotenv file (default: ".env"). */ dotenvToken?: string; /** Path to dynamic variables module (default: undefined). */ dynamicPath?: string; /** * Emit diagnostics for child env composition. * - `true`: trace all keys. * - `string[]`: trace selected keys. */ trace?: boolean | string[]; /** Paths to search for dotenv files (space-delimited string or array). */ paths?: string | string[]; /** Delimiter for paths string (default: space). */ pathsDelimiter?: string; /** Regex pattern for paths delimiter. */ pathsDelimiterPattern?: string; /** Token indicating private variables (default: "local"). */ privateToken?: string; /** Delimiter for vars string (default: space). */ varsDelimiter?: string; /** Regex pattern for vars delimiter. */ varsDelimiterPattern?: string; /** Assignment operator for vars (default: "="). */ varsAssignor?: string; /** Regex pattern for vars assignment operator. */ varsAssignorPattern?: string; /** Table of named scripts for execution. */ scripts?: ScriptsTable; } /** * Definition for a single script entry. */ interface ScriptDef { /** The command string to execute. */ cmd: string; /** Shell override for this script. */ shell?: TShell | undefined; } /** * Scripts table shape. */ type ScriptsTable = Record>; /** * Per-invocation context shared with plugins and actions. * * @public */ interface GetDotenvCliCtx { /** * Effective environment name after resolution (explicit -e \> defaultEnvKey \> defaultEnv). */ env?: string; /** * Fully resolved option bag used to compute this context. */ optionsResolved: TOptions; /** * Final composed dotenv environment for this invocation. */ dotenv: ProcessEnv; /** * Dotenv provenance history for {@link GetDotenvCliCtx.dotenv}. * * Descriptor-only: does not include value payloads. */ dotenvProvenance: DotenvProvenance; /** * Optional runtime plugin state bag. Plugins may publish non-sensitive metadata here. */ plugins?: Record; /** * Per-plugin validated configuration slices keyed by realized mount path. */ pluginConfigs?: Record; } /** * Options for branding the CLI. * * @public */ interface BrandOptions { /** CLI name. */ name?: string; /** CLI description. */ description?: string; /** CLI version string. */ version?: string; /** Import URL for resolving package version. */ importMetaUrl?: string; /** Custom help header text. */ helpHeader?: string; } /** * A minimal representation of an environment key/value mapping. * Values may be `undefined` to represent "unset". */ type ProcessEnv = Record; /** * Dynamic variable function signature. Receives the current expanded variables * and the selected environment (if any), and returns either a string to set * or `undefined` to unset/skip the variable. */ type GetDotenvDynamicFunction = (vars: ProcessEnv, env: string | undefined) => string | null | undefined; /** * A map of dynamic variable definitions. * Keys are variable names; values are either literal strings or functions. */ type GetDotenvDynamic = Record>; /** * Logger interface compatible with AWS SDK v3 expectations (`debug`, `info`, `warn`, `error`). * Consumers must provide an object that implements these four methods. * Additional methods (like `log`) are allowed but not required or used by this library. */ type Logger = Pick; /** * Canonical programmatic options type (schema-derived). * This type is the single source of truth for programmatic options. */ type GetDotenvOptions = Omit, 'logger' | 'dynamic'> & { /** * Compile-time overlay: narrowed logger for DX (schema stores unknown). */ logger: Logger; /** * Compile-time overlay: narrowed dynamic map for DX (schema stores unknown). */ dynamic?: GetDotenvDynamic; }; /** * Unify Scripts via the generic ScriptsTable so shell types propagate. */ type Scripts = ScriptsTable; /** * Canonical CLI options type derived from the Zod schema output. * Includes CLI-only flags (debug/strict/capture/trace/redaction/entropy), * stringly paths/vars, and inherited programmatic fields (minus normalized * shapes that are handled by resolution). */ type GetDotenvCliOptions = Omit, 'logger' | 'dynamic' | 'scripts'> & { /** * Compile-only overlay for DX: logger narrowed from unknown. */ logger: Logger; /** * Compile-only overlay for DX: dynamic map narrowed from unknown. */ dynamic?: GetDotenvDynamic; /** * Compile-only overlay for DX: scripts narrowed from Record\. */ scripts?: Scripts; }; /** * Configuration context used for generating dynamic help descriptions. * Contains merged CLI options and plugin configuration slices. * * @public */ type ResolvedHelpConfig = Partial & { /** * Per‑plugin configuration slices keyed by realized mount path * (e.g., `"aws"` or `"aws/whoami"`), used for dynamic help text. */ plugins: Record; }; /** src/cliHost/definePlugin/contracts.ts * Public contracts for plugin authoring (types only). * - No runtime logic or state. * - Safe to import broadly without introducing cycles. */ /** * Options for resolving and loading the configuration. * * @public */ interface ResolveAndLoadOptions { /** * When false, skips running plugin afterResolve hooks. * Useful for top-level help rendering to avoid long-running side-effects * while still evaluating dynamic help text. * * @default true */ runAfterResolve?: boolean; /** * Name of the invoked subcommand (plugin namespace). When provided, * only the matching plugin subtree runs afterResolve hooks. * When omitted, all plugins run afterResolve (backward compatibility). */ invokedSubcommand?: string; } /** * Structural public interface for the host exposed to plugins. * - Extends Commander.Command so plugins can attach options/commands/hooks. * - Adds host-specific helpers used by built-in plugins. * * Purpose: remove nominal class identity (private fields) from the plugin seam * to avoid TS2379 under exactOptionalPropertyTypes in downstream consumers. */ interface GetDotenvCliPublic extends Command { /** * Create a namespaced child command with argument inference. * Mirrors Commander generics so downstream chaining remains fully typed. */ ns(name: Usage, opts?: NsOptions): GetDotenvCliPublic ], {}, TOpts & TGlobal>; /** Return the current context; throws if not yet resolved. */ getCtx(): GetDotenvCliCtx; /** Check whether a context has been resolved (non-throwing). */ hasCtx(): boolean; /** * Resolve options and compute the dotenv context for this invocation. * * @param customOptions - Partial options to overlay for this invocation. * @param opts - Optional resolver behavior switches (for example, whether to run `afterResolve`). * @returns A promise resolving to the computed invocation context. */ resolveAndLoad(customOptions?: Partial, opts?: ResolveAndLoadOptions): Promise>; /** * Tag an option with a help group identifier for grouped root help rendering. * * @param opt - The Commander option to tag. * @param group - Group identifier (for example, `base`, `app`, or `plugin:`). * @returns Nothing. */ setOptionGroup(opt: Option, group: string): void; /** * Create a dynamic option whose description is computed at help time * from the resolved configuration. */ /** * Create a dynamic option whose description is computed at help time from the resolved configuration. * * @param flags - Commander option flags usage string. * @param desc - Description builder called during help rendering with the resolved help config. * @param parser - Optional argument parser. * @param defaultValue - Optional default value. * @returns A Commander `Option` instance with a dynamic description. */ createDynamicOption(flags: Usage, desc: (cfg: ResolvedHelpConfig) => string, parser?: (value: string, previous?: unknown) => unknown, defaultValue?: unknown): Option; /** {@inheritDoc} */ createDynamicOption(flags: Usage, desc: (cfg: ResolvedHelpConfig) => string, parser: (value: string, previous?: TValue) => TValue, defaultValue?: TValue): Option; } /** * Options for the `ns()` subcommand factory, forwarded to Commander's * `command(name, opts)` second argument. * * @public */ interface NsOptions { /** * When true, this subcommand becomes the default: Commander routes * unrecognized positional tokens to it when no explicit subcommand matches. */ isDefault?: boolean; /** * When true, the subcommand is hidden from help output. */ hidden?: boolean; } /** * Optional overrides for plugin composition. * * @public */ interface PluginNamespaceOverride { /** * Override the default namespace for this plugin instance. */ ns?: string; } /** * An entry in the plugin children array. * * @public */ interface PluginChildEntry { /** The child plugin instance to mount under this parent. */ plugin: GetDotenvCliPlugin; /** * Optional namespace override for the child when mounted under the parent. * When provided, this name is used instead of the child's default `ns`. */ override: PluginNamespaceOverride | undefined; } /** Public plugin contract used by the GetDotenv CLI host. */ interface GetDotenvCliPlugin { /** Namespace (required): the command name where this plugin is mounted. */ ns: string; /** * Options forwarded to the host's `ns()` call when creating the mount * for this plugin (e.g. `{ isDefault: true }`). */ nsOptions?: NsOptions; /** * Setup phase: register commands and wiring on the provided mount. * Runs parent → children (pre-order). Return nothing (void). */ setup: (cli: GetDotenvCliPublic) => void | Promise; /** * After the dotenv context is resolved, initialize any clients/secrets * or attach per-plugin state under ctx.plugins (by convention). * Runs parent → children (pre-order). * * **Scoping**: When the host provides an invoked subcommand filter, * afterResolve only fires for plugins whose namespace matches the * invoked command path. A plugin's afterResolve should never produce * side effects for commands outside its subtree. */ afterResolve?: (cli: GetDotenvCliPublic, ctx: GetDotenvCliCtx) => void | Promise; /** Zod schema for this plugin's config slice (from config.plugins[…]). */ configSchema?: ZodObject; /** * Compositional children, with optional per-child overrides (e.g., ns). * Installed after the parent per pre-order. */ children: Array>; /** * Compose a child plugin with optional override (ns). Returns the parent * to enable chaining. */ use: (child: GetDotenvCliPlugin, override?: PluginNamespaceOverride) => GetDotenvCliPlugin; } /** src/cliHost/GetDotenvCli.ts * Plugin-first CLI host for get-dotenv with Commander generics preserved. * Public surface implements GetDotenvCliPublic and provides: * - attachRootOptions (builder-only; no public override wiring) * - resolveAndLoad (strict resolve + context compute) * - getCtx/hasCtx accessors * - ns() for typed subcommand creation with duplicate-name guard * - grouped help rendering with dynamic option descriptions */ declare const CTX_SYMBOL: unique symbol; declare const OPTS_SYMBOL: unique symbol; declare const HELP_HEADER_SYMBOL: unique symbol; /** * Plugin-first CLI host for get-dotenv. Extends Commander.Command. * * Responsibilities: * - Resolve options strictly and compute dotenv context (resolveAndLoad). * - Expose a stable accessor for the current context (getCtx). * - Provide a namespacing helper (ns). * - Support composable plugins with parent → children install and afterResolve. */ declare class GetDotenvCli extends Command implements GetDotenvCliPublic { /** Registered top-level plugins (composition happens via .use()) */ private _plugins; /** One-time installation guard */ private _installed; /** In-flight installation promise to guard against concurrent installs */ private _installing?; /** Optional header line to prepend in help output */ private [HELP_HEADER_SYMBOL]; /** Context/options stored under symbols (typed) */ private [CTX_SYMBOL]?; private [OPTS_SYMBOL]?; /** * Create a subcommand using the same subclass, preserving helpers like * dynamicOption on children. */ createCommand(name?: string): GetDotenvCli; constructor(alias?: string); /** * Attach legacy/base root flags to this CLI instance. * Delegates to the pure builder in attachRootOptions.ts. */ attachRootOptions(defaults?: Partial): this; /** * Resolve options (strict) and compute dotenv context. * Stores the context on the instance under a symbol. * * @param customOptions - Partial options to overlay for this invocation. * @param opts - Optional resolver behavior switches. * - `runAfterResolve` (default `true`): when false, skips running plugin * afterResolve hooks. Useful for top-level help rendering to avoid * long-running side-effects while still evaluating dynamic help text. * - `invokedSubcommand`: when provided, only the plugin subtree whose * namespace matches this name runs afterResolve hooks. When omitted, * all plugins run afterResolve (backward compatibility). */ resolveAndLoad(customOptions?: Partial, opts?: ResolveAndLoadOptions): Promise>; /** * Create a Commander Option that computes its description at help time. * The returned Option may be configured (conflicts, default, parser) and * added via addOption(). */ createDynamicOption(flags: Usage, desc: (cfg: ResolvedHelpConfig) => string, parser?: (value: string, previous?: unknown) => unknown, defaultValue?: unknown): Option; createDynamicOption(flags: Usage, desc: (cfg: ResolvedHelpConfig) => string, parser: (value: string, previous?: TValue) => TValue, defaultValue?: TValue): Option; /** * Evaluate dynamic descriptions for this command and all descendants using * the provided resolved configuration. Mutates the Option.description in * place so Commander help renders updated text. */ evaluateDynamicOptions(resolved: ResolvedHelpConfig): void; /** Internal: climb to the true root (host) command. */ private _root; /** * Retrieve the current invocation context (if any). */ getCtx(): GetDotenvCliCtx; /** * Check whether a context has been resolved (non-throwing guard). */ hasCtx(): boolean; /** * Retrieve the merged root CLI options bag (if set by passOptions()). * Downstream-safe: no generics required. */ getOptions(): GetDotenvCliOptions | undefined; /** Internal: set the merged root options bag for this run. */ _setOptionsBag(bag: GetDotenvCliOptions): void; /** * Convenience helper to create a namespaced subcommand with argument inference. * This mirrors Commander generics so downstream chaining stays fully typed. */ ns(name: Usage, opts?: NsOptions): GetDotenvCliPublic ], {}, TOpts & TGlobal>; /** * Tag options added during the provided callback as 'app' for grouped help. * Allows downstream apps to demarcate their root-level options. */ tagAppOptions(fn: (root: CommandUnknownOpts) => T): T; /** * Branding helper: set CLI name/description/version and optional help header. * If version is omitted and importMetaUrl is provided, attempts to read the * nearest package.json version (best-effort; non-fatal on failure). */ brand(args: BrandOptions): Promise; /** * Insert grouped plugin/app options between "Options" and "Commands" for * hybrid ordering. Applies to root and any parent command. */ helpInformation(): string; /** * Public: tag an Option with a display group for help (root/app/plugin:). */ setOptionGroup(opt: Option, group: string): void; /** * Register a plugin for installation (parent level). * Installation occurs on first resolveAndLoad() (or explicit install()). */ use(plugin: GetDotenvCliPlugin, override?: PluginNamespaceOverride): this; /** * Install all registered plugins in parent → children (pre-order). * Runs only once per CLI instance. */ install(): Promise; /** * Run afterResolve hooks for registered plugins (parent → children). * When {@link commandPath} is provided, only the matching branch of the * plugin tree runs; otherwise all plugins run (backward compatibility). * * The path is walked segment-by-segment against the plugin tree. * Intermediate matches run their own afterResolve hook. * The deepest match runs afterResolve for itself and all its descendants. */ _runAfterResolve(ctx: GetDotenvCliCtx, commandPath?: string[]): Promise; } /** * Create a get-dotenv CLI host with included plugins. * * Options: * - alias: command name used for help/argv scaffolding (default: "getdotenv") * - branding: optional help header; when omitted, brand() uses " v" * * Usage: * ```ts * import { createCli } from '@karmaniverous/get-dotenv'; * * await createCli({ * alias: 'getdotenv', * branding: 'getdotenv vX.Y.Z' * })(); * ``` */ type CreateCliOptions = { /** * CLI command name used for help and argv scaffolding. * Defaults to `'getdotenv'` when omitted. */ alias?: string; /** * Optional help header text. When omitted, brand() uses * `" v"` if a version can be read. */ branding?: string; /** * Optional composer to wire the CLI (plugins/options). If not provided, * the shipped default wiring is applied. Any `configureOutput`/`exitOverride` * you call here override the defaults. */ compose?: (program: GetDotenvCli) => GetDotenvCli; /** * Root defaults applied once before composition. These are used by flag declaration * and merge-time defaults (and top-level -h parity labels). * Note: shipped CLI does not force loadProcess OFF; base defaults apply unless set here. */ rootOptionDefaults?: Partial; /** * Visibility map to hide families/singles from root help. When a key is false, * the corresponding option(s) are hidden (via hideHelp) after flags are declared. */ rootOptionVisibility?: Partial>; }; /** * Create a configured get-dotenv CLI host. * Applies defaults, installs root hooks, and composes plugins. * Returns a runner function that accepts an argv array. */ declare function createCli(opts?: CreateCliOptions): (argv?: string[]) => Promise; export { createCli }; export type { CreateCliOptions };