{"version":3,"file":"env.cjs","names":["expand","childProcess","path","fs"],"sources":["../src/env.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport childProcess from 'node:child_process';\n\nimport { expand } from 'dotenv-expand';\nimport type { ArgumentsCamelCase, InferredOptionTypes } from 'yargs';\n\nexport const yargsOptionsBuilderForEnv = {\n  'cascade-env': {\n    description:\n      'Environment (fnox profile / mise env) to load environment variables for. Preferred over `cascade-node-env` and `auto-cascade-env`.',\n    type: 'string',\n  },\n  'cascade-node-env': {\n    description: 'Same with --cascade-env=<NODE_ENV || \"development\">. Preferred over `auto-cascade-env`.',\n    type: 'boolean',\n  },\n  'auto-cascade-env': {\n    description: 'Same with --cascade-env=<WB_ENV || NODE_ENV || \"development\">.',\n    type: 'boolean',\n    default: true,\n  },\n  'quiet-env': {\n    description: 'Suppress environment variable loading information.',\n    type: 'boolean',\n  },\n  verbose: {\n    description: 'Whether to show verbose information',\n    type: 'boolean',\n    alias: 'v',\n  },\n} as const;\n\nexport type EnvReaderOptions = Partial<ArgumentsCamelCase<InferredOptionTypes<typeof yargsOptionsBuilderForEnv>>> & {\n  /**\n   * Command-level fallback for an unset WB_ENV (e.g. `wb test` supplies 'test' when explicit env\n   * flags suppress its default test cascade). Not a CLI flag.\n   */\n  commandDefaultWbEnv?: string;\n};\n\nconst standardWbEnvModes = new Set(['development', 'test', 'staging', 'production']);\n\n/**\n * Resolves the cascade (fnox profile / env-file suffix) the reader loads for the given options:\n * the forced `--cascade-env` first, then `--cascade-node-env`'s NODE_ENV, then the auto cascade\n * driven by the ambient WB_ENV/NODE_ENV. Exported so commands that select a profile WITHOUT\n * loading environment sources (e.g. `wb gen-docker-env`) cannot drift from the reader's selection.\n */\nexport function resolveCascade(argv: EnvReaderOptions): string | undefined {\n  // Read NODE_ENV through an alias, never as the `process.env.NODE_ENV` member expression:\n  // bundlers replace that exact expression at build time (see readEnvironmentVariables).\n  const runtimeEnv = process.env;\n  return (\n    argv.cascadeEnv ??\n    (argv.cascadeNodeEnv\n      ? runtimeEnv.NODE_ENV || 'development'\n      : argv.autoCascadeEnv\n        ? runtimeEnv.WB_ENV || runtimeEnv.NODE_ENV || 'development'\n        : undefined)\n  );\n}\n\n/**\n * Resolves the WB_ENV value wb falls back to when no env source and no exported variable defines\n * it: the command-level default first (`wb test --cascade-env=staging` loads the staging files\n * but its tests must still run as `test`, mirroring the pre-15 `||= 'test'` behavior), then the\n * forced cascade, then the ambient-NODE_ENV-driven auto cascade clamped to a standard mode (a\n * non-standard NODE_ENV such as `qa` still selects the cascade suffix, but must not produce a\n * non-standard WB_ENV).\n */\nexport function resolveFallbackWbEnv(argv: EnvReaderOptions): string {\n  if (argv.commandDefaultWbEnv) return argv.commandDefaultWbEnv;\n  if (argv.cascadeEnv) return argv.cascadeEnv;\n  // Read NODE_ENV through the alias for the same bundler-inlining reason as in\n  // readEnvironmentVariables, and from the AMBIENT environment (not loaded files) because the\n  // cascade selection below uses the ambient value as well.\n  const runtimeEnv = process.env;\n  const derived =\n    argv.cascadeNodeEnv || argv.autoCascadeEnv !== false ? runtimeEnv.NODE_ENV || 'development' : 'development';\n  return standardWbEnvModes.has(derived) ? derived : 'development';\n}\n\n/**\n * This function reads environment variables from the repository's fnox configuration and mise.\n * Note it does not assign them in `process.env`.\n * @return [envVars, [envSourceNames, envVarNames][]]\n * */\nexport function readEnvironmentVariables(\n  argv: EnvReaderOptions,\n  cwd: string,\n  options?: {\n    /**\n     * Load variables even if they already exist in process.env.\n     * Useful when a parent process has already injected the fnox values into the environment\n     * and the configured variables themselves are needed (e.g. `wb gen-dev-vars`).\n     */\n    ignoreProcessEnv?: boolean;\n    /**\n     * Expand `${WB_ENV}` references against the fallback mode when nothing defines WB_ENV.\n     * Only for callers that subsequently COMPLETE WB_ENV with that fallback (wb's Project.env).\n     */\n    expandFallbackWbEnv?: boolean;\n  }\n): [Record<string, string>, [string, string[]][]] {\n  // Read NODE_ENV through an alias, never as the `process.env.NODE_ENV` member expression:\n  // bundlers replace that exact expression at build time (rolldown/build-ts inline it as\n  // 'production'), which constant-folds the fallback below and made the published wb select\n  // the production profile whenever WB_ENV was unset.\n  const runtimeEnv = process.env;\n  const cascade = resolveCascade(argv);\n  const shouldSuppressOutput = shouldSuppressEnvironmentOutput(argv);\n  if (argv.verbose && !shouldSuppressOutput) {\n    console.info(`WB_ENV: ${runtimeEnv.WB_ENV}, NODE_ENV: ${runtimeEnv.NODE_ENV}`);\n  }\n\n  // When the caller explicitly forces a mode (--cascade-env / --cascade-node-env / an exported\n  // WB_ENV), values that the mode's own fnox profile defines must win over variables inherited\n  // from the parent shell: a stale `export DATABASE_URL=...` from a development shell must not\n  // leak into `wb test`'s test mode (cf. https://github.com/WillBooster/shared/issues/930). On CI\n  // the inherited variables keep winning — workflows deliberately inject env vars that override\n  // the committed values — and that shadowing is the designed behavior.\n  const modeIsForced = Boolean(\n    argv.cascadeEnv ??\n    (argv.cascadeNodeEnv ? runtimeEnv.NODE_ENV || 'development' : argv.autoCascadeEnv ? runtimeEnv.WB_ENV : undefined)\n  );\n  const modeFileOverridesProcessEnv = modeIsForced && !isCIEnvironment(runtimeEnv.CI);\n\n  const envPathAndLoadedEnvVarNames: [string, string[]][] = [];\n  const envVars: Record<string, string> = {};\n  const projectHasFnoxConfig = hasProjectFnoxConfig(cwd);\n  const [fnoxEnvVars, fnoxEnvVarNames] = readFnoxEnvironmentVariables(cwd, cascade, {\n    ...options,\n    modeFileOverridesProcessEnv,\n    hasFnoxConfig: projectHasFnoxConfig,\n  });\n  Object.assign(envVars, fnoxEnvVars);\n  // Report the fnox source whenever fnox.toml exists — even when it yields no keys (all shadowed,\n  // empty profile, or a failing export): consumers such as wb's required-environment validation\n  // must see that a declared env source exists rather than silently failing open.\n  if (fnoxEnvVarNames.length > 0 || projectHasFnoxConfig) {\n    const fnoxSourceName = fnoxEnvironmentSourceName(cascade);\n    envPathAndLoadedEnvVarNames.push([fnoxSourceName, fnoxEnvVarNames]);\n    if (argv.verbose && !shouldSuppressOutput) {\n      console.info(`Read ${fnoxEnvVarNames.length} environment variables from ${fnoxSourceName}`);\n    }\n  }\n  const [miseEnvVars, miseEnvVarNames] = readMiseEnvironmentVariables(cwd, cascade, envVars, options);\n  Object.assign(envVars, miseEnvVars);\n  if (miseEnvVarNames.length > 0) {\n    const miseSourceName = miseEnvironmentSourceName(cascade);\n    envPathAndLoadedEnvVarNames.push([miseSourceName, miseEnvVarNames]);\n    if (argv.verbose && !shouldSuppressOutput) {\n      console.info(`Read ${miseEnvVarNames.length} environment variables from ${miseSourceName}`);\n    }\n  }\n  if (!argv.verbose && !shouldSuppressOutput) {\n    console.info(\n      `Read env sources: ${envPathAndLoadedEnvVarNames.map(([envPath, keys]) => (keys.length > 0 ? `${envPath} (${keys.join(', ')})` : envPath)).join(', ') || 'nothing'}`\n    );\n  }\n\n  // Expand references against the live environment for keys NOT loaded from files, so that a\n  // reference to an exported key (excluded from envVars by process-env precedence) resolves to\n  // the effective value instead of an empty string. Loaded keys are deliberately absent from\n  // the reference set: dotenv-expand would otherwise replace their parsed values with the\n  // process values, breaking callers that need the file-defined values themselves.\n  const referenceEnv: Record<string, string> = {};\n  for (const [key, value] of Object.entries(process.env)) {\n    // Escape dollar signs so dotenv-expand substitutes exported values literally instead of\n    // recursively re-expanding them (an exported `pa$word` must stay `pa$word`).\n    if (value !== undefined && !(key in envVars)) referenceEnv[key] = value.replaceAll('$', String.raw`\\$`);\n  }\n  // dotenv-expand resolves references in key-insertion order, so a fnox value referencing a\n  // mise-provided key would see an empty string if the mise entries stayed appended after the\n  // fnox entries. Rebuild the expansion input with the lower-priority sources first; the values\n  // themselves already reflect the intended fnox-over-mise precedence.\n  const orderedEnvVars: Record<string, string> = {};\n  for (const key of [...miseEnvVarNames, ...fnoxEnvVarNames]) orderedEnvVars[key] = envVars[key]!;\n  Object.assign(orderedEnvVars, envVars);\n  // expand() mutates BOTH its parsed input AND processEnv (dotenv-expand writes every parsed\n  // result into processEnv), so snapshot both for the re-expansion below — the retry must not\n  // see the first pass's stale dependent values.\n  const preExpansionEnvVars = { ...orderedEnvVars };\n  const pristineReferenceEnv = { ...referenceEnv };\n  let expandedEnvVars = expand({ parsed: orderedEnvVars, processEnv: referenceEnv }).parsed ?? orderedEnvVars;\n  // A value referencing ${WB_ENV} must expand to what the child will actually see: when the\n  // EFFECTIVE WB_ENV ends up empty — whether it was never defined, defined empty, or emptied by\n  // the expansion itself (e.g. `WB_ENV=${MISSING_MODE}`) — wb's Project.env later fills it with\n  // the fallback mode, so re-expand from the original values with that fallback available.\n  // Opt-in via the option: a direct readEnvironmentVariables/readAndApplyEnvironmentVariables\n  // caller never receives the completed WB_ENV, and expanding references against a value that is\n  // not actually applied would make the pair inconsistent.\n  // The loaded key masks the ambient value, so a loaded-but-emptied WB_ENV needs the retry even\n  // when an exported WB_ENV exists (a forced mode file overrides the export locally): retry with\n  // the value the merged environment will ultimately retain.\n  const effectiveWbEnv = expandedEnvVars.WB_ENV ?? runtimeEnv.WB_ENV;\n  if (options?.expandFallbackWbEnv && !effectiveWbEnv) {\n    const reExpansionInput = { ...preExpansionEnvVars };\n    delete reExpansionInput.WB_ENV;\n    const retryReferenceEnv = { ...pristineReferenceEnv, WB_ENV: runtimeEnv.WB_ENV || resolveFallbackWbEnv(argv) };\n    expandedEnvVars = expand({ parsed: reExpansionInput, processEnv: retryReferenceEnv }).parsed ?? reExpansionInput;\n  }\n  return [expandedEnvVars, envPathAndLoadedEnvVarNames];\n}\n\n/**\n * This function reads environment variables from the repository's fnox configuration (`fnox.toml`).\n * The base `[secrets]` table carries the development values, and `[profiles.<cascade>.secrets]`\n * overlays it; an unknown profile falls back to the base secrets.\n */\nexport function readFnoxEnvironmentVariables(\n  cwd: string,\n  cascade: string | undefined,\n  options?: {\n    ignoreProcessEnv?: boolean;\n    modeFileOverridesProcessEnv?: boolean;\n    /** Precomputed hasProjectFnoxConfig(cwd) result, to avoid re-walking the ancestor directories. */\n    hasFnoxConfig?: boolean;\n  }\n): [Record<string, string>, string[]] {\n  if (!(options?.hasFnoxConfig ?? hasProjectFnoxConfig(cwd))) return [{}, []];\n\n  const secrets = runFnoxExport(cwd, cascade, { quiet: false });\n  if (!secrets) return [{}, []];\n  // `[profiles.<cascade>.secrets]` is the fnox analogue of `.env.<cascade>`: when the caller\n  // forces a mode off CI, profile-declared values must override inherited shell variables just\n  // like `.env.<mode>` values do, while base `[secrets]` values keep losing to process.env.\n  // A key's value is profile-specific under EITHER criterion, because neither alone covers both\n  // shapes: `--no-defaults` omits the base `[secrets]` table, so its key set is exactly the\n  // profile's own declarations — including one repeating the base value, which a value comparison\n  // cannot see (https://github.com/WillBooster/shared/issues/1080) — while a base entry\n  // interpolating a profile-overridden key (`DATABASE_URL = \"postgres://${DB_HOST}/app\"`) stays\n  // out of that key set although its exported value differs from the base export's.\n  // Both exports run LAZILY, only when a process.env collision actually needs adjudicating — they\n  // would otherwise add subprocesses (including age decryption) to every forced-mode invocation\n  // for nothing — and a failing export simply disables its own criterion (conservative).\n  // The omitted base table also makes fnox reject a profile default REFERENCING a base secret\n  // (`URL = { default = \"https://${HOST}/x\" }`), which the repository rules therefore forbid; the\n  // warning names that rule because the lost precision would otherwise be invisible.\n  let cachedProfileKeys: Set<string> | undefined | false = false;\n  const getProfileKeys = (): Set<string> | undefined => {\n    if (cachedProfileKeys === false) {\n      const profileSecrets = runFnoxExport(cwd, cascade, { quiet: false, profileOnly: true });\n      cachedProfileKeys = profileSecrets && new Set(Object.keys(profileSecrets));\n    }\n    return cachedProfileKeys;\n  };\n  let cachedBaseSecrets: Record<string, unknown> | undefined | false = false;\n  const overridesProcessEnv = (key: string, value: string): boolean => {\n    if (getProfileKeys()?.has(key)) return true;\n    if (cachedBaseSecrets === false) {\n      cachedBaseSecrets = runFnoxExport(cwd, undefined, { quiet: true, ignoreProfileEnvVar: true });\n    }\n    return cachedBaseSecrets !== undefined && cachedBaseSecrets[key] !== value;\n  };\n\n  const envVars: Record<string, string> = {};\n  const keys: string[] = [];\n  for (const [key, value] of Object.entries(secrets)) {\n    if (typeof value !== 'string') continue;\n    // Explicitly exported environment variables win over fnox base values.\n    // (The mise reader below intentionally uses a value-equality check instead: `mise env` echoes\n    // back variables the ambient mise activation already exported, and a differing value means the\n    // requested cascade profile should win over the stale activation.)\n    if (\n      !options?.ignoreProcessEnv &&\n      key in process.env &&\n      !(options?.modeFileOverridesProcessEnv && cascade && overridesProcessEnv(key, value))\n    ) {\n      continue;\n    }\n    envVars[key] = value;\n    keys.push(key);\n  }\n  return [envVars, keys];\n}\n\nfunction runFnoxExport(\n  cwd: string,\n  cascade: string | undefined,\n  options: { quiet: boolean; profileOnly?: boolean; ignoreProfileEnvVar?: boolean }\n): Record<string, unknown> | undefined {\n  // `--if-missing error` (default): fnox otherwise exits 0 and silently omits secrets it fails to\n  // resolve (e.g. a missing age key), which would be indistinguishable from undeclared secrets.\n  // Opt-in escape hatch `WB_ALLOW_MISSING_SECRETS=1`: switch to `warn` so a keyless context — e.g. a\n  // Docker/Railway image build that only inlines non-secret public values (`APP_TITLE`,\n  // `NEXT_PUBLIC_*`) while the age key is deliberately absent — still loads the resolvable values\n  // (plaintext defaults plus any secret that DID decrypt) instead of failing outright. `warn`, not\n  // `ignore`, keeps fnox reporting the skipped secret names on stderr (surfaced below), so relaxing\n  // the check stays auditable rather than silently dropping declared secrets.\n  // `--non-interactive`: prompts or browser auth flows would hang forever because stdin is ignored.\n  const allowMissingSecrets =\n    process.env.WB_ALLOW_MISSING_SECRETS === '1' || process.env.WB_ALLOW_MISSING_SECRETS === 'true';\n  const args = [\n    'export',\n    '--format',\n    'json',\n    '--no-color',\n    '--if-missing',\n    allowMissingSecrets ? 'warn' : 'error',\n    '--non-interactive',\n  ];\n  if (cascade) {\n    args.push('--profile', cascade);\n  }\n  if (options.profileOnly) {\n    args.push('--no-defaults');\n  }\n  const env = { ...process.env };\n  if (options.ignoreProfileEnvVar) {\n    // Without `--profile`, fnox falls back to FNOX_PROFILE; the base-adjudication export must\n    // read the BASE secrets, so the inherited profile selection is cleared for it — and only for\n    // it. A PRIMARY export still honors FNOX_PROFILE: it either stays profile-less (fnox reads the\n    // variable) or folds it into the `--profile` it passes (see wb dotenv's cascade).\n    delete env.FNOX_PROFILE;\n  }\n  const result = childProcess.spawnSync('fnox', args, {\n    cwd,\n    env,\n    encoding: 'utf8',\n    stdio: ['ignore', 'pipe', 'pipe'],\n  });\n  if (result.error || result.status !== 0 || !result.stdout?.trim()) {\n    // The repository declares fnox-managed secrets (fnox.toml exists), so a failing export must be\n    // surfaced: swallowing it would make declared secrets indistinguishable from undeclared ones.\n    // The profile-only export reports what its failure costs plus its likeliest cause, and always\n    // quotes fnox's own error because other causes (e.g. a fnox too old for `--no-defaults`) look\n    // identical from here.\n    if (!options.quiet) {\n      const reason = result.error?.message || result.stderr?.trim() || `fnox exited with status ${result.status}`;\n      console.warn(\n        options.profileOnly\n          ? `Failed to read the \"${cascade}\" fnox profile's own secrets, so its values equal to the base values do not override the inherited environment variables. Make the defaults in [profiles.${cascade}.secrets] independent of the base [secrets] table. ${reason}`\n          : `Failed to read fnox secrets: ${reason}`\n      );\n    }\n    return;\n  }\n\n  if (allowMissingSecrets && !options.quiet && result.stderr?.trim()) {\n    // With `--if-missing warn`, fnox exits 0 but reports the secrets it could not resolve on stderr.\n    // Surface them so relaxing the check via WB_ALLOW_MISSING_SECRETS does not hide a real gap.\n    console.warn(`WB_ALLOW_MISSING_SECRETS: continuing without unresolved fnox secrets.\\n${result.stderr.trim()}`);\n  }\n\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(result.stdout);\n  } catch {\n    return;\n  }\n  const secrets = (parsed as { secrets?: unknown } | undefined)?.secrets;\n  if (!secrets || typeof secrets !== 'object' || Array.isArray(secrets)) return;\n  return secrets as Record<string, unknown>;\n}\n\nexport function hasProjectFnoxConfig(cwd: string): boolean {\n  return hasAncestorContaining(cwd, ['fnox.toml']);\n}\n\nfunction fnoxEnvironmentSourceName(cascade: string | undefined): string {\n  return cascade ? `fnox export --profile ${cascade}` : 'fnox export';\n}\n\nfunction readMiseEnvironmentVariables(\n  cwd: string,\n  cascade: string | undefined,\n  currentEnvVars: Record<string, string>,\n  options?: { ignoreProcessEnv?: boolean }\n): [Record<string, string>, string[]] {\n  if (!hasProjectMiseConfig(cwd)) return [{}, []];\n\n  const args = ['env', '--json', '--cd', cwd];\n  if (cascade) {\n    args.push('--env', cascade);\n  }\n  const result = childProcess.spawnSync('mise', args, {\n    encoding: 'utf8',\n    stdio: ['ignore', 'pipe', 'pipe'],\n  });\n  if (result.error || result.status !== 0 || !result.stdout?.trim()) return [{}, []];\n\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(result.stdout);\n  } catch {\n    return [{}, []];\n  }\n  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return [{}, []];\n\n  const envVars: Record<string, string> = {};\n  const keys: string[] = [];\n  for (const [key, value] of Object.entries(parsed)) {\n    if (typeof value !== 'string' || key in currentEnvVars) continue;\n    if (options?.ignoreProcessEnv) {\n      // `mise env` always emits PATH due to tool shims; consumers of file-defined variables\n      // (e.g. `wb gen-dev-vars`) must not propagate it.\n      if (key === 'PATH') continue;\n    } else if (process.env[key] === value) {\n      continue;\n    }\n    envVars[key] = value;\n    keys.push(key);\n  }\n  return [envVars, keys];\n}\n\nfunction hasProjectMiseConfig(cwd: string): boolean {\n  return hasAncestorContaining(cwd, ['mise.toml', '.mise.toml']);\n}\n\nfunction hasAncestorContaining(cwd: string, fileNames: string[]): boolean {\n  for (let currentPath = path.resolve(cwd); ; currentPath = path.dirname(currentPath)) {\n    if (fileNames.some((fileName) => fs.existsSync(path.join(currentPath, fileName)))) {\n      return true;\n    }\n    const parentPath = path.dirname(currentPath);\n    if (parentPath === currentPath) return false;\n  }\n}\n\nfunction miseEnvironmentSourceName(cascade: string | undefined): string {\n  return cascade ? `mise env --env ${cascade}` : 'mise env';\n}\n\nfunction isCIEnvironment(ciEnv: string | undefined): boolean {\n  return !!ciEnv && ciEnv !== '0' && ciEnv !== 'false';\n}\n\nexport function shouldSuppressEnvironmentOutput(argv: EnvReaderOptions): boolean {\n  const outputOptions = argv as EnvReaderOptions & { quietEnv?: boolean; silent?: boolean };\n  return outputOptions.quietEnv === true || (outputOptions.quietEnv !== false && outputOptions.silent === true);\n}\n\n/**\n * This function reads environment variables from fnox/mise and assigns them in `process.env`.\n * */\nexport function readAndApplyEnvironmentVariables(\n  argv: EnvReaderOptions,\n  cwd: string\n): Record<string, string | undefined> {\n  const [envVars] = readEnvironmentVariables(argv, cwd);\n  for (const [key, value] of Object.entries(envVars)) {\n    // Existing process.env keys are kept: envVars may deliberately contain differing values that\n    // must win only in the returned record (mise cascade-profile values, forced-mode overrides\n    // consumed via `project.env`), never clobber the caller's own process environment.\n    if (!(key in process.env)) {\n      process.env[key] = value;\n    }\n  }\n  return envVars;\n}\n\n/**\n * This function removes environment variables related to npm and yarn from the given environment variables.\n * */\nexport function removeNpmAndYarnEnvironmentVariables(envVars: Record<string, string | undefined>): void {\n  if (envVars.PATH && envVars.BERRY_BIN_FOLDER) {\n    envVars.PATH = envVars.PATH.replace(`${envVars.BERRY_BIN_FOLDER}:`, '')\n      // Temporary directory in macOS\n      .replaceAll(/\\/private\\/var\\/folders\\/[^:]+:/g, '')\n      // Temporary directories in Linux\n      .replaceAll(/\\/var\\/tmp\\/[^:]+:/g, '')\n      .replaceAll(/\\/tmp\\/[^:]+:/g, '');\n  }\n  for (const key of Object.keys(envVars)) {\n    const upperKey = key.toUpperCase();\n    if (\n      upperKey.startsWith('NPM_') ||\n      upperKey.startsWith('YARN_') ||\n      upperKey.startsWith('BERRY_') ||\n      upperKey === 'PROJECT_CWD' ||\n      upperKey === 'INIT_CWD'\n    ) {\n      // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n      delete envVars[key];\n    }\n  }\n}\n"],"mappings":"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"}