import { SpecifyDesignTokenFormat } from '@specifyapp/specify-design-token-format'; import { ParserFunction } from './definitions/ParserFunction.js'; import { ParsersPipelineState } from './definitions/ParsersPipelineState.js'; import { createPipelineStatesFromRules } from './internals/createPipelineStatesFromRules.js'; import { ParsersEngineDataBox, SDTFEngineDataBox } from './definitions/parsersEngineDataBox.js'; import { BuiltInGenerationParserRule, BuiltInParserRule, BuiltInUtilityParserRule, } from '../builtInParsers/builtInParserRule.js'; import { makeExecuteParsersEngine, ParsersEngineExecutionContext, } from './internals/makeExecuteParsersEngine.js'; import { SpecifyError, specifyErrors } from '../errors/index.js'; import { createPipelineStatesFromParserFunctions } from './internals/createPipelineStatesFromParserFunctions.js'; export type ParsersEngineContext< BuiltInParserKind extends 'generation' | 'utility' | 'all' | undefined = 'all', > = { isRemote?: boolean; builtInParserKind?: BuiltInParserKind; personalAccessToken?: string; resolveRepositoryTokenTree?: ( owner: string, name: string, ) => Promise< | { status: 'success'; tokenTree: SpecifyDesignTokenFormat } | { status: 'error'; content: string; originalError: unknown } >; }; /** * Create a parsers engine from an array of pipelines or parser rules * @param pipelines * @param data * @param context */ export function createParsersEngine< BuiltInParserKind extends 'generation' | 'utility' | 'all' | undefined, >( pipelines: Array< BuiltInParserKind extends 'generation' ? ParserFunction | BuiltInGenerationParserRule : BuiltInParserKind extends 'utility' ? ParserFunction | BuiltInUtilityParserRule : ParserFunction | BuiltInParserRule >, data: ParsersEngineDataBox, context?: ParsersEngineContext, ) { if (!Array.isArray(pipelines)) { throw new SpecifyError({ errorKey: specifyErrors.PARSERS_ENGINE_VALIDATION_ERROR.errorKey, publicMessage: 'Invalid pipelines argument. Must be an array of Parser functions and/or Parser configuration rules.', }); } // Segregate the pipelines to be created from parserFunctions and parserRules const { functions, rules } = pipelines.reduce<{ functions: Array>; rules: Array; }>( (acc, input, i) => { if (typeof input === 'function') { acc.functions.push(input); } else if (input !== null && typeof input === 'object' && !Array.isArray(input)) { acc.rules.push(input); } else { throw new SpecifyError({ errorKey: specifyErrors.PARSERS_ENGINE_VALIDATION_ERROR.errorKey, publicMessage: 'Invalid pipeline argument. Must be a Parser function or a Rule configuration object.', }); } return acc; }, { functions: [], rules: [] }, ); const pipelineStates: Array = [ ...createPipelineStatesFromParserFunctions(functions), ...createPipelineStatesFromRules(rules, { isRemote: context?.isRemote ?? false, builtInParserKind: context?.builtInParserKind ?? 'all', personalAccessToken: context?.personalAccessToken, }), ]; const executionContext: ParsersEngineExecutionContext = { isRemote: context?.isRemote ?? false, resolveRepositoryTokenTree: context?.resolveRepositoryTokenTree ?? (() => Promise.reject( new SpecifyError({ errorKey: specifyErrors.PARSERS_ENGINE_RESOLVE_REPOSITORY_FAILED.errorKey, publicMessage: '`resolveRepositoryTokenTree` method is not implemented.', }), )), }; return makeExecuteParsersEngine(pipelineStates, executionContext, data); }