import { z } from 'zod'; import { createRPCClient } from '../../httpApi/clients/createRPCClient.js'; import { SDKTelemetry } from '../../telemetry/provider.js'; import { formatZodErrorMessages } from '../../utils/zod/index.js'; import { BuiltInParserDefinitionSignature } from './createBuiltInParserDefinition.js'; import { ParserFunction, ParserToolbox } from '../../parsersEngine/index.js'; import { BuiltInParserFunction } from './BuiltInParserFunction.js'; import { serializeParsersEngineDataBox } from '../../parsersEngine/utils/serializeParsersEngineDataBox.js'; import { SpecifyError, specifyErrors } from '../../errors/index.js'; import { handleSerializedParsersEngineResult } from '../../parsersEngine/internals/handleSerializedParsersEngineResult.js'; import { BuiltInParserRuleSignature } from './BuiltInParserRuleSignature.js'; export async function wrapBuiltInParserHandler< Def extends BuiltInParserDefinitionSignature, >( definition: Def, handler: BuiltInParserFunction< z.infer, z.infer, z.infer, z.infer, false >, { dataBox, toolbox, options, output, }: { dataBox: z.infer; toolbox: ParserToolbox; options: z.infer; output: z.infer; }, ): Promise> { try { z.object({ options: definition.optionsSchema, output: definition.outputSchema, }).parse({ options, output }, { path: [definition.name] }); new SDKTelemetry().track('Built In Parser Initialized', { isFromRule: false, parserName: definition.name, options: options ?? {}, output: output ?? {}, }); } catch (error) { const parserFunctionWithError: ParserFunction = async (_, toolbox) => { if (error instanceof z.ZodError) { const [first, ...rest] = formatZodErrorMessages(error); rest.forEach(message => { toolbox.populateMessage({ type: 'error', content: `Invalid parser configuration: ${message}`, errorKey: specifyErrors.PARSERS_ENGINE_INVALID_RULE_CONFIGURATION.errorKey, }); }); throw new SpecifyError({ errorKey: specifyErrors.PARSERS_ENGINE_INVALID_RULE_CONFIGURATION.errorKey, publicMessage: `Invalid parser configuration: ${first}`, }); /* v8 ignore next 3 */ } else { throw error; } }; return parserFunctionWithError(dataBox, toolbox); } try { definition.inSchema.parse(dataBox, { path: [definition.name] }); } catch (error) { const parserFunctionWithError: ParserFunction = async (_, toolbox) => { if (error instanceof z.ZodError) { const [first, ...rest] = formatZodErrorMessages(error); rest.forEach(message => { toolbox.populateMessage({ type: 'error', content: `Invalid input dataBox: ${message}`, errorKey: specifyErrors.PARSERS_ENGINE_INVALID_RULE_CONFIGURATION.errorKey, }); }); throw new SpecifyError({ errorKey: specifyErrors.PARSERS_ENGINE_INVALID_RULE_CONFIGURATION.errorKey, publicMessage: `Invalid input dataBox: ${first}`, }); /* v8 ignore next 3 */ } else { throw error; } }; return parserFunctionWithError(dataBox, toolbox); } if (options?.shouldExecuteRemotely) { const rule: BuiltInParserRuleSignature = { name: `RPC for "${definition.name}" parser`, parsers: [ { name: definition.name, options, output, }, ], }; return createRPCClient(undefined) .executeParsersEngine({ body: { dataBox: serializeParsersEngineDataBox(dataBox), rules: [rule] }, }) .then(results => { const result = results[0]; if (!result) { throw new SpecifyError({ errorKey: specifyErrors.PARSERS_ENGINE_RPC_EXECUTION_FAILED.errorKey, publicMessage: `RPC result not found for parser "${definition.name}".`, }); } return handleSerializedParsersEngineResult(result, toolbox, definition.outType); }); } return handler(dataBox, toolbox, options, output, { isRemote: false }); }