import { SDTFEngine, createSDTFEngine } from '@specifyapp/specify-design-token-format'; import type { DeriveBuiltInParserHandlerFromDefinition } from '../../internals/createBuiltInParserDefinition.js'; import { SpecifyError, specifyErrors } from '../../../errors/index.js'; import type { ToJsonListParserDefinition } from './definition.js'; export type FlattenNode = ( | { kind: 'group'; } | { kind: 'collection'; modes: Array; } | { kind: 'token'; type: string; modeValues: Array<{ mode: string; value: unknown; }>; } ) & { path: Array; stringPath: string; name: string; description?: string; extensions?: unknown; }; export const toJsonListHandler: DeriveBuiltInParserHandlerFromDefinition< ToJsonListParserDefinition > = async (previousDataBox, toolbox, parserOptions, outputOptions, _context) => { let sdtfEngine: SDTFEngine; switch (previousDataBox.type) { case 'SDTF': { sdtfEngine = createSDTFEngine(previousDataBox.graph, previousDataBox.metadata); break; } case 'SDTF Engine': { sdtfEngine = previousDataBox.engine; break; } default: { throw new SpecifyError({ errorKey: specifyErrors.PARSERS_ENGINE_INVALID_PARSER_INPUT.errorKey, publicMessage: `${ (previousDataBox as any).type } is not a valid input for the to-json-list parser.`, }); } } const stringPathSeparator = parserOptions?.stringPathSeparator || '.'; const flattenNodes: Array = []; sdtfEngine.query.getAllNodeStates().forEach(node => { if (node.isToken) { const jsonValue = node.getJSONValue(); const item: FlattenNode = { path: node.path.clone().toArray(), stringPath: node.path.toArray().join(stringPathSeparator), name: node.name, kind: 'token', type: node.type, modeValues: node.isTopLevelAlias ? [] : node.modes.map(mode => ({ mode, value: (jsonValue as any)[mode], })), }; if (node.description) item.description = node.description; if (node.extensions) item.extensions = node.extensions; flattenNodes.push(item); } else if (node.isGroup) { const item: FlattenNode = { path: node.path.clone().toArray(), stringPath: node.path.toArray().join(stringPathSeparator), name: node.name, kind: 'group', }; if (node.description) item.description = node.description; if (node.extensions) item.extensions = node.extensions; flattenNodes.push(item); } else if (node.isCollection) { const item: FlattenNode = { path: node.path.clone().toArray(), stringPath: node.path.toArray().join(stringPathSeparator), name: node.name, kind: 'collection', modes: node.allowedModes, }; if (node.description) item.description = node.description; if (node.extensions) item.extensions = node.extensions; flattenNodes.push(item); } }); switch (outputOptions?.type) { case 'file': { toolbox.populateOutput({ type: 'files', files: [ { path: outputOptions.filePath, content: { type: 'text', text: JSON.stringify(flattenNodes, null, 2), }, }, ], }); break; } case 'JSON': { toolbox.populateOutput({ type: 'JSON', json: flattenNodes as any, }); break; } default: { throw new SpecifyError({ errorKey: specifyErrors.PARSERS_ENGINE_INVALID_OUTPUT_TYPE.errorKey, publicMessage: `The output type ${ (outputOptions as any)?.type } is not supported by the to-json-list parser.`, }); } } return { type: 'SDTF Engine', engine: sdtfEngine, }; };