import { diffSets, Evaluate, isRecursible, mergeAll, Narrow, transform } from "@re-do/utils" import { createParseFunction, ParseFunction, DefaultParseTypeOptions } from "./parse.js" import { extraneousTypesErrorMessage, missingTypesErrorMessage, TypeSet } from "./components" export const createCompileFunction = ( declaredTypeNames: Narrow ) => < Definitions extends TypeSet.ValidateMemberList< Definitions, DeclaredTypeNames > >( // @ts-ignore ...definitions: Narrow ) => { if ( !Array.isArray(definitions) || definitions.some((def) => !isRecursible(def) || Array.isArray(def)) ) { throw new Error(`Compile args must be a list of names mapped to their corresponding definitions passed as rest args, e.g.: compile( { user: { name: "string" } }, { group: "user[]" } )`) } const typeSetFromDefinitions = mergeAll(definitions as any) as any const declarationErrors = diffSets( declaredTypeNames, Object.keys(typeSetFromDefinitions) ) if (declaredTypeNames.length && declarationErrors) { const errorParts = [] as string[] if (declarationErrors.added) { errorParts.push( extraneousTypesErrorMessage.replace( "@types", declarationErrors.added.map((_) => `'${_}'`).join(", ") ) ) } if (declarationErrors.removed) { errorParts.push( missingTypesErrorMessage.replace( "@types", declarationErrors.removed .map((_) => `'${_}'`) .join(", ") ) ) } throw new Error(errorParts.join(" ")) } const parse = createParseFunction(typeSetFromDefinitions) as any return { parse, types: transform( typeSetFromDefinitions, ([typeName, definition]) => [ typeName, // @ts-ignore parse(definition, { // @ts-ignore typeSet: typeSetFromDefinitions }) ] ) } as CompiledTypeSet } // Exported compile function is equivalent to compile from an empty declare call // and will not validate missing or extraneous definitions export const compile = createCompileFunction([]) export type CompileFunction = < Definitions extends TypeSet.ValidateMemberList< Definitions, DeclaredTypeNames > >( // @ts-ignore ...definitions: Narrow ) => CompiledTypeSet export type CompiledTypeSet< Definitions, MergedTypeSet = TypeSet.MergeMemberList > = Evaluate<{ parse: ParseFunction types: TypeSet.Parse }>