UNPKG

envilder

Version:

A CLI and GitHub Action that securely centralizes your environment variables from AWS SSM or Azure Key Vault as a single source of truth

168 lines 6.29 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { readFile } from 'node:fs/promises'; import { createSecretProvider } from '../infrastructure/secret-provider-factory.js'; import { EnvilderClient } from './envilder-client.js'; import { MapFileParser } from './map-file-parser.js'; /** * Facade for loading secrets from cloud providers. * * Supports loading from a single map file or from an * environment-based mapping that routes each environment name * to its own map file (or `null` to skip). * * @example * ```typescript * // One-liner — resolve + inject into process.env: * await Envilder.load('envilder.json'); * * // Resolve without injecting: * const secrets = await Envilder.resolveFile('envilder.json'); * * // Fluent builder with provider override: * const secrets = await Envilder.fromMapFile('envilder.json') * .withProvider(SecretProviderType.Azure) * .withVaultUrl('https://my-vault.vault.azure.net') * .inject(); * ``` */ export class Envilder { constructor(filePath) { this.options = {}; this.filePath = filePath; } /** * Returns a fluent builder bound to the given map file. * * Chain `.withProvider()`, `.withVaultUrl()`, or `.withProfile()` * before calling `.resolve()` or `.inject()`. */ static fromMapFile(filePath) { validateFilePath(filePath); return new Envilder(filePath.trim()); } /** * Resolves secrets and injects them into `process.env`. * * Can be called in two ways: * - `load(filePath)` — load from a single map file * - `load(env, envMapping)` — look up env in the mapping */ static load(filePathOrEnv, envMapping) { return __awaiter(this, void 0, void 0, function* () { if (envMapping !== undefined) { const source = resolveEnvSource(filePathOrEnv, envMapping); if (source === null) { return new Map(); } return new Envilder(source).inject(); } validateFilePath(filePathOrEnv); return new Envilder(filePathOrEnv.trim()).inject(); }); } /** * Resolves secrets without injecting into `process.env`. * * Can be called in two ways: * - `resolveFile(filePath)` — resolve from a single map file * - `resolveFile(env, envMapping)` — look up env in the mapping */ static resolveFile(filePathOrEnv, envMapping) { return __awaiter(this, void 0, void 0, function* () { if (envMapping !== undefined) { const source = resolveEnvSource(filePathOrEnv, envMapping); if (source === null) { return new Map(); } return new Envilder(source).resolve(); } validateFilePath(filePathOrEnv); return new Envilder(filePathOrEnv.trim()).resolve(); }); } /** Override the secret provider (AWS or Azure). */ withProvider(provider) { this.options.provider = provider; return this; } /** Override the Azure Key Vault URL. */ withVaultUrl(vaultUrl) { this.options.vaultUrl = vaultUrl; return this; } /** Override the AWS named profile. */ withProfile(profile) { this.options.profile = profile; return this; } /** Resolve secrets and return them as a Map. */ resolve() { return __awaiter(this, void 0, void 0, function* () { const mapFile = yield this.parseFile(); const options = this.buildOptions(); const provider = createSecretProvider(mapFile.config, options); const client = new EnvilderClient(provider); return client.resolveSecrets(mapFile); }); } /** Resolve secrets, inject into `process.env`, and return them. */ inject() { return __awaiter(this, void 0, void 0, function* () { const secrets = yield this.resolve(); EnvilderClient.injectIntoEnvironment(secrets); return secrets; }); } parseFile() { return __awaiter(this, void 0, void 0, function* () { let json; try { json = yield readFile(this.filePath, 'utf-8'); } catch (err) { if (err instanceof Error && 'code' in err && err.code === 'ENOENT') { throw new Error(`Map file not found: ${this.filePath}`); } throw err; } return new MapFileParser().parse(json); }); } buildOptions() { const hasOverrides = this.options.provider !== undefined || this.options.vaultUrl !== undefined || this.options.profile !== undefined; return hasOverrides ? this.options : undefined; } } function validateFilePath(filePath) { if (!(filePath === null || filePath === void 0 ? void 0 : filePath.trim())) { throw new Error('file path cannot be empty'); } } function resolveEnvSource(env, envMapping) { if (!(env === null || env === void 0 ? void 0 : env.trim())) { throw new Error('env cannot be empty'); } const normalized = env.trim(); if (!Object.hasOwn(envMapping, normalized)) { return null; } const source = envMapping[normalized]; if (source === null) { return null; } if (!source.trim()) { throw new Error(`envMapping contains an empty file path for environment '${normalized}'.`); } return source.trim(); } //# sourceMappingURL=envilder.js.map