UNPKG

@beignet/core

Version:

Core framework primitives for Beignet

99 lines (90 loc) 3.14 kB
import type { StandardSchemaV1 } from "@standard-schema/spec"; import { ConfigValidationError, parseStandardSchemaAsync, readEnv, } from "../../config/index.js"; import { SchemaValidationError } from "../../errors/index.js"; import type { AnyPorts } from "../../ports/index.js"; import type { ServiceProvider } from "../../providers/index.js"; type ProviderConfigDef<Schema extends StandardSchemaV1<unknown, unknown>> = { schema: Schema; envPrefix?: string; overrides?: Record<string, unknown>; }; async function parseStandardSchema< Schema extends StandardSchemaV1<unknown, unknown>, >( schema: Schema, input: unknown, ): Promise<StandardSchemaV1.InferOutput<Schema>> { try { return await parseStandardSchemaAsync(schema, input); } catch (error) { if (error instanceof ConfigValidationError) { throw new SchemaValidationError(error.issues); } throw error; } } /** * Load and validate config for a provider. * * Explicit overrides take precedence over env-derived config. When a provider * declares `envPrefix`, matching env keys are stripped before validation. */ export async function loadProviderConfig< Ports extends AnyPorts, Schema extends StandardSchemaV1<unknown, unknown>, >( provider: ServiceProvider<Ports, Schema>, env: Record<string, string | undefined>, overrides: Record<string, unknown>, ): Promise<StandardSchemaV1.InferOutput<Schema> | undefined> { const configDef = provider.config as ProviderConfigDef<Schema> | undefined; if (!configDef) return undefined; const { schema, envPrefix, overrides: fieldOverrides } = configDef; const hasOverride = Object.hasOwn(overrides, provider.name); const base = hasOverride ? overrides[provider.name] : envPrefix ? readEnv({ env, prefix: envPrefix }) : {}; // Field-level overrides from the provider's own config definition (factory // options) win over env-derived and server-supplied values. Defined values // only, so absent options fall back to the base input and schema defaults. let input = base; if (fieldOverrides) { const defined = Object.fromEntries( Object.entries(fieldOverrides).filter(([, value]) => value !== undefined), ); if (Object.keys(defined).length > 0) { input = { ...(typeof base === "object" && base !== null ? base : {}), ...defined, }; } } try { return await parseStandardSchema(schema, input); } catch (error) { const suffix = envPrefix ? ` (envPrefix=${envPrefix})` : ""; const found = envPrefix ? Object.keys(env).filter( (k) => k.startsWith(envPrefix) && env[k] !== undefined, ) : []; const hint = envPrefix ? found.length ? `\n Env vars found with prefix "${envPrefix}": ${found.join(", ")}` : `\n No env vars found with prefix "${envPrefix}"` : ""; throw new Error( `Failed to load config for provider "${provider.name}"${suffix}: ${(error as Error).message}${hint}`, ); } } /** * Parse provider config with Standard Schema and normalize validation errors. */ export { parseStandardSchema };