/** * `.env` / `.env.local` collection for `telo run`. * * **The workspace marker bounds the walk, and its `env:` block says how.** A * walk-up needs a stop: walking to `/` would read a user's home `.env.local` * into an app run, and stopping at `.git` would tie env resolution to a VCS a * deployed checkout may not have. `telo-workspace.yaml` is already the anchor * every workspace-relative path is measured from, so it is the honest boundary * for "this repo" — and `env.roots` is how a workspace draws a tighter one, * which is what keeps a vendor subtree's apps from reading a repo-root `.env`. * * With no marker anywhere above the manifest the walk collapses to the * manifest's own directory, which is what this did before the bound existed, so * the file stays harmless by its absence: it enables the parent lookup rather * than gating one, and deleting it cannot silently drop a variable an app had. * * Precedence (highest first): the real environment > the nearest directory's * files, last-declared winning within one directory > the same, one directory * up, and so on. A repo-root file reaches every manifest beneath it, so a nearer * declaration has to win. * * **Only `env:` is consulted, and only its diagnostics stop a run.** A typo * under `release.modules` is a block this command has no interest in, so it is * reported and the run proceeds — aborting every app in a workspace over a * release typo is not a trade to make silently. A diagnostic inside `env:` is * fatal: degrading to the marker-wide bound there would WIDEN the walk, which is * the leak the block exists to prevent, and a block that opted into a boundary * and got nothing is a defect rather than a default. * * **Resolving is separate from applying**, so the walk is answerable without * touching `process.env` or writing a line of output — the caller owns both. */ import { type WorkspaceDiagnostic } from "@telorun/analyzer"; /** One file the walk could not read for a reason other than its absence. */ export interface UnreadableEnvFile { readonly path: string; /** The errno code (`EACCES`, `EISDIR`, …), or the message when there is none. */ readonly reason: string; } export interface EnvFileResolution { /** The merged values, precedence already applied. Never written anywhere by * this module. */ readonly values: Readonly>; /** The files that contributed, in the order they were merged (farthest * ancestor first, so the last entry is the one that won a conflict). */ readonly loaded: readonly string[]; /** Files that exist but could not be read. Reporting these is the caller's, * and it is not optional: an unreadable `.env` is indistinguishable from an * absent one to everything downstream. */ readonly unreadable: readonly UnreadableEnvFile[]; /** What the marker got wrong. Anything anchored outside `env:` is reported and * survivable; an error inside it is why `failed` is set. */ readonly diagnostics: readonly WorkspaceDiagnostic[]; /** Set when `env:` itself could not be read, so the caller must refuse rather * than run against a boundary it had to guess at. */ readonly failed?: string; } /** Collect the env files visible to a manifest. Pure: reads the filesystem and * returns what it found. */ export declare function resolveEnvFiles(manifestPath: string): EnvFileResolution; //# sourceMappingURL=env-files.d.ts.map