UNPKG

@daiso-tech/core

Version:

The library offers flexible, framework-agnostic solutions for modern web applications, built on adaptable components that integrate seamlessly with popular frameworks like Next Js.

96 lines 3.2 kB
/** * @module EnvAccessor */ import {} from "@standard-schema/spec"; import { UninitializedEnvAccessorError, } from "../../env-accessor/contracts/_module.js"; import { resolveOneOrMore, isInvokable, callInvokable, validate, } from "../../utilities/_module.js"; /** * `EnvAccessor` provides type-safe access to environment variables, with optional schema validation. * * It supports multiple sources (sync/async/lazy), schema validation, and convenient access patterns. * * @template TEnvConfig The environment config type. * @group Implementations */ export class EnvAccessor { envConfig = null; schema; sources; /** * @example * ```ts * import { EnvAccessor } from "@daiso-tech/core/env-accessor"; * import { z } from "zod"; * import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager"; * * * // Combine AWS Secrets Manager and process.env as sources * // Note: The order matters—later sources override previous ones for overlapping keys. * const secretsManager = new SecretsManagerClient({ region: "us-east-1" }); * const sources = [ * process.env, * async () => { * const secret = await secretsManager.send( * new GetSecretValueCommand({ SecretId: "my-app/env" }) * ); * return JSON.parse(secret.SecretString ?? "{}"); * }, * ]; * * // Define a schema for your environment variables * const schema = z.object({ * NODE_ENV: z.string(), * PORT: z.string().default("3000").pipe(z.coerce.number()), * }); * * // Initialize the accessor * const accessor = new EnvAccessor({ schema, sources }); * await accessor.init(); * * // Retrieve a value * const port = accessor.get("PORT"); * ``` */ constructor(settings) { const { schema, sources } = settings; this.schema = schema; this.sources = sources; } /** * Initialize the EnvAccessor by resolving all sources and validating the merged config. * * @returns Promise that resolves when initialization is complete. */ async init() { const resolvedSource = resolveOneOrMore(this.sources).map((source) => { if (isInvokable(source)) { return source; } return () => source; }); let mergedRawConfig = {}; for (const source of resolvedSource) { mergedRawConfig = { ...mergedRawConfig, ...(await callInvokable(source)), }; } this.envConfig = await validate(this.schema, mergedRawConfig); } get(field) { if (this.envConfig === null) { throw UninitializedEnvAccessorError.create(); } const value = this.envConfig[field] ?? null; return value; } getOr(field, defaultValue) { const value = this.get(field); if (value === null) { return defaultValue; } // eslint-disable-next-line @typescript-eslint/no-unsafe-return return value; } } //# sourceMappingURL=env-accessor.js.map