UNPKG

typia

Version:

Superfast runtime validators with only one line

290 lines (287 loc) 9.44 kB
import ts from 'typescript'; import { Metadata } from '../schemas/metadata/Metadata.mjs'; import { MetadataConstant } from '../schemas/metadata/MetadataConstant.mjs'; import { MetadataObject } from '../schemas/metadata/MetadataObject.mjs'; import { explore_metadata } from './internal/metadata/explore_metadata.mjs'; import { iterate_metadata_collection } from './internal/metadata/iterate_metadata_collection.mjs'; import { iterate_metadata_sort } from './internal/metadata/iterate_metadata_sort.mjs'; import { ExpressionFactory } from './ExpressionFactory.mjs'; var MetadataFactory; (function (MetadataFactory) { MetadataFactory.analyze = (props) => { const errors = []; const metadata = explore_metadata({ ...props, errors, explore: { top: true, object: null, property: null, parameter: null, nested: null, aliased: false, escaped: false, output: false, }, intersected: false, }); iterate_metadata_collection({ errors, collection: props.collection, }); iterate_metadata_sort({ collection: props.collection, metadata: metadata, }); if (props.options.validate) errors.push(...MetadataFactory.validate({ transformer: props.transformer, options: props.options, functor: props.options.validate, metadata, })); return errors.length ? { success: false, errors, } : { success: true, data: metadata, }; }; /** @internal */ MetadataFactory.soleLiteral = (value) => { const meta = Metadata.initialize(); meta.constants.push(MetadataConstant.from({ values: [ { value, tags: [], }, ], type: "string", })); return meta; }; MetadataFactory.validate = (props) => { const visitor = { functor: props.functor, errors: [], objects: new Set(), arrays: new Set(), tuples: new Set(), aliases: new Set(), functions: new Set(), }; validateMeta({ ...props, visitor, explore: { object: null, property: null, parameter: null, nested: null, top: true, aliased: false, escaped: false, output: false, }, }); return visitor.errors; }; const validateMeta = (props) => { const result = []; for (const atomic of props.metadata.atomics) for (const row of atomic.tags) for (const tag of row.filter((t) => t.validate !== undefined && t.predicate === undefined)) try { tag.predicate = ExpressionFactory.transpile({ script: tag.validate, }); } catch { result.push(`Unable to transpile type tag script: ${JSON.stringify(tag.validate)}`); tag.predicate = () => ts.factory.createTrue(); } result.push(...props.visitor.functor(props.metadata, props.explore)); if (result.length) props.visitor.errors.push({ name: props.metadata.getName(), explore: { ...props.explore }, messages: [...new Set(result)], }); for (const alias of props.metadata.aliases) validateAlias({ ...props, alias: alias.type, }); for (const array of props.metadata.arrays) validateArray({ ...props, array: array.type, }); for (const tuple of props.metadata.tuples) validateTuple({ ...props, tuple: tuple.type, }); for (const object of props.metadata.objects) validateObject({ ...props, object: object.type, }); for (const func of props.metadata.functions) validateFunction({ ...props, function: func, }); for (const set of props.metadata.sets) validateMeta({ ...props, metadata: set.value, }); for (const map of props.metadata.maps) { validateMeta({ ...props, metadata: map.key, }); validateMeta({ ...props, metadata: map.value, }); } if (props.options.escape === true && props.metadata.escaped !== null) validateMeta({ ...props, metadata: props.metadata.escaped.returns, explore: { ...props.explore, escaped: true, }, }); }; const validateAlias = (props) => { if (props.visitor.aliases.has(props.alias)) return; props.visitor.aliases.add(props.alias); validateMeta({ ...props, metadata: props.alias.value, explore: { ...props.explore, nested: props.alias, aliased: true, }, }); }; const validateArray = (props) => { if (props.visitor.arrays.has(props.array)) return; props.visitor.arrays.add(props.array); validateMeta({ ...props, metadata: props.array.value, explore: { ...props.explore, nested: props.array, top: false, }, }); }; const validateTuple = (props) => { if (props.visitor.tuples.has(props.tuple)) return; props.visitor.tuples.add(props.tuple); for (const elem of props.tuple.elements) validateMeta({ ...props, metadata: elem, explore: { ...props.explore, nested: props.tuple, top: false, }, }); }; const validateObject = (props) => { if (props.visitor.objects.has(props.object)) return; props.visitor.objects.add(props.object); if (props.options.validate) { const explore = { object: props.object, top: false, property: null, parameter: null, nested: null, aliased: false, escaped: false, output: false, }; const errors = props.options.validate(Metadata.create({ ...Metadata.initialize(), objects: [ MetadataObject.create({ type: props.object, tags: [], }), ], }), explore); if (errors.length) props.visitor.errors.push({ name: props.object.name, explore, messages: [...new Set(errors)], }); } for (const property of props.object.properties) validateMeta({ ...props, metadata: property.value, explore: { object: props.object, property: property.key.isSoleLiteral() ? property.key.getSoleLiteral() : {}, parameter: null, nested: null, top: false, aliased: false, escaped: false, output: false, }, }); }; const validateFunction = (props) => { if (props.visitor.functions.has(props.function)) return; props.visitor.functions.add(props.function); for (const param of props.function.parameters) validateMeta({ ...props, metadata: param.type, explore: { ...props.explore, parameter: param.name, nested: null, top: false, output: false, }, }); if (props.function.output) validateMeta({ ...props, metadata: props.function.output, explore: { ...props.explore, parameter: null, nested: null, top: false, output: true, }, }); }; })(MetadataFactory || (MetadataFactory = {})); export { MetadataFactory }; //# sourceMappingURL=MetadataFactory.mjs.map