UNPKG

nuxt-safe-runtime-config

Version:

Validate Nuxt runtime config with Standard Schema at build time

51 lines (50 loc) 2.19 kB
export const runtimeValidationContextKey = Symbol.for("nuxt-safe-runtime-config.validation-context"); function isRuntimeConfig(value) { return !!value && typeof value === "object" && !Array.isArray(value); } export function mergeTransformedRuntimeConfig(current, transformed) { if (!isRuntimeConfig(current) || !isRuntimeConfig(transformed)) return transformed; const merged = { ...current }; for (const [key, value] of Object.entries(transformed)) merged[key] = mergeTransformedRuntimeConfig(current[key], value); return merged; } const validationStoreKey = Symbol.for("nuxt-safe-runtime-config.validation-store"); const existingValidationStore = Reflect.get(globalThis, validationStoreKey); const validationStore = existingValidationStore ?? { states: /* @__PURE__ */ new WeakMap() }; if (!existingValidationStore) Reflect.set(globalThis, validationStoreKey, validationStore); export function getRuntimeValidationState(config) { return validationStore.states.get(config); } export function setRuntimeValidationState(config, state) { validationStore.states.set(config, state); } export function applyValidatedRuntimeConfig(config, value) { if (!isRuntimeConfig(value)) throw new TypeError("Runtime config schema output must be an object"); for (const [key, transformedValue] of Object.entries(value)) { if (Object.hasOwn(config, key)) Reflect.set(config, key, mergeTransformedRuntimeConfig(config[key], transformedValue)); } setRuntimeValidationState(config, { status: "valid", value }); } export function useValidatedRuntimeConfig(config) { const state = getRuntimeValidationState(config); if (!state || state.status === "invalid") return config; if (state.status === "valid") return state.value; if (state.status === "failed") throw state.error; throw new Error("Runtime config validation is still pending"); } export async function waitForRuntimeConfigValidation(config) { const state = getRuntimeValidationState(config); if (state?.status === "pending") await state.ready; const settledState = getRuntimeValidationState(config); if (settledState?.status === "failed") throw settledState.error; }