import { DomainError } from "@tailor-platform/erp-kit/app"; /** * Validate that `raw` is one of `allowed`, narrowing the return type to the * matching literal. Throws a descriptive DomainError listing every accepted * value otherwise. * * Why this exists: erp-kit 0.26.0 moved several enum-typed command inputs * (partner type / role / identification type / costing method, etc.) from * runtime error codes to compile-time unions. Our GraphQL inputs remain * `t.string()`, so each resolver needs a small guard between the loose * string input and the typed command call. This helper standardises that * pattern. * * Usage: * const ROLES = ["CUSTOMER", "SUPPLIER"] as const; * const role = assertEnum(context.input.role ?? "SUPPLIER", ROLES, "role"); * // role is narrowed to "CUSTOMER" | "SUPPLIER" * * Implementation note: iterating returns the matching element directly so * TypeScript narrows it to `T[number]` without an explicit `as` cast (which * `@typescript-eslint/no-unnecessary-type-assertion` would reject — the * generic constraint is too loose for the linter to see the cast as load- * bearing). O(n) lookup is fine for the 2-6 element tuples we use this for. */ export function assertEnum( raw: string, allowed: T, fieldName: string, ): T[number] { for (const value of allowed) { if (value === raw) return value; } throw new DomainError(`Invalid ${fieldName}: ${raw}. Must be one of ${allowed.join(", ")}.`); }