# core/adapters/environment.adapter.ts

> 38 lines of code and 7 definitions.

Tree: Secrets
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/secrets#file-secrets-core-adapters-environment-adapter-ts
Source text: https://banes-lab.com/source/secrets/core/adapters/environment.adapter.ts.txt

Listed in [core/adapters](https://banes-lab.com/api/source/secrets/core/adapters.md).

## Definitions

- `fieldLabels` (lexical_declaration, line 28, exported)
- `reasonOf` (lexical_declaration, line 6)
- `ask` (lexical_declaration, line 16)
- `revealField` (lexical_declaration, line 36, exported)
- `stderr` (lexical_declaration, line 8)
- `output` (lexical_declaration, line 18)
- `answer` (lexical_declaration, line 37, exported)

## Contained in

- [core/adapters](https://banes-lab.com/anatomy/secrets/folder-secrets-core-adapters.md)

## Uses

- [configuration/strings/environment.strings.ts](https://banes-lab.com/source/secrets/configuration/strings/environment.strings.ts.md)
- [core/predicates/environment.predicate.ts](https://banes-lab.com/source/secrets/core/predicates/environment.predicate.ts.md)

## Used by

- [core/resolvers/environment.resolver.ts](https://banes-lab.com/source/secrets/core/resolvers/environment.resolver.ts.md)

## Linked from

- [configuration/strings](https://banes-lab.com/anatomy/secrets/folder-secrets-configuration-strings.md)
- [core/adapters](https://banes-lab.com/anatomy/secrets/folder-secrets-core-adapters.md)
- [core/predicates](https://banes-lab.com/anatomy/secrets/folder-secrets-core-predicates.md)
- [core/resolvers](https://banes-lab.com/anatomy/secrets/folder-secrets-core-resolvers.md)

## Source

```typescript
import { JSON_SWITCH, REVEAL_WORDS, SHOW_WORDS, VAULT_BINARY } from "#configuration/constants/environment.constants";
import { answerMalformed, vaultRefused } from "#configuration/strings/environment.strings";
import { isEntryAnswer, isValueAnswer } from "#core/predicates/environment.predicate";
import { execFileSync } from "node:child_process";

const reasonOf = function reasonOf(error: unknown): string {
    if (typeof error === "object" && error !== null && "stderr" in error) {
        const stderr = String(error.stderr).trim();
        if (stderr.length > 0) {
            return stderr;
        }
    }
    return error instanceof Error ? error.message : String(error);
};

const ask = function ask(entry: string, words: readonly string[]): unknown {
    try {
        const output = execFileSync(VAULT_BINARY, [...words, JSON_SWITCH], {
            encoding: "utf8",
            stdio: ["ignore", "pipe", "pipe"],
        });
        return JSON.parse(output);
    } catch (error: unknown) {
        throw new Error(vaultRefused(entry, reasonOf(error)), { cause: error });
    }
};

export const fieldLabels = function fieldLabels(entry: string): ReadonlySet<string> {
    const answer = ask(entry, [...SHOW_WORDS, entry]);
    if (!isEntryAnswer(answer)) {
        throw new Error(answerMalformed(entry));
    }
    return new Set(answer.entry.fields.map((field) => field.label));
};

export const revealField = function revealField(entry: string, label: string): string {
    const answer = ask(entry, [...REVEAL_WORDS, entry, label]);
    if (!isValueAnswer(answer)) {
        throw new Error(answerMalformed(entry));
    }
    return answer.value;
};
```
