UNPKG

typia

Version:

Superfast runtime validators with only one line

153 lines (150 loc) • 5.48 kB
import ts from 'typescript'; import { MetadataProperty } from '../../../schemas/metadata/MetadataProperty.mjs'; import { Writable } from '../../../typings/Writable.mjs'; import { ArrayUtil } from '../../../utils/ArrayUtil.mjs'; import { CommentFactory } from '../../CommentFactory.mjs'; import { MetadataHelper } from './MetadataHelper.mjs'; import { explore_metadata } from './explore_metadata.mjs'; const emplace_metadata_object = (props) => { // EMPLACE OBJECT const [obj, newbie] = props.collection.emplace(props.checker, props.type); ArrayUtil.add(obj.nullables, props.metadata.nullable, (elem) => elem === props.metadata.nullable); if (newbie === false) return obj; // PREPARE ASSETS const isClass = props.type.isClass(); const isProperty = significant(!!props.options.functional); const pred = isClass ? (node) => { const capsuled = node .getChildren() .some((c) => c .getChildren() .some((n) => n.kind === ts.SyntaxKind.PrivateKeyword || n.kind === ts.SyntaxKind.ProtectedKeyword)); return capsuled === false && isProperty(node); } : (node) => isProperty(node); const insert = (props) => { // COMMENTS AND TAGS const description = props.symbol ? (CommentFactory.description(props.symbol) ?? null) : null; const jsDocTags = (props.symbol?.getJsDocTags() ?? []).filter(props.filter ?? (() => true)); // THE PROPERTY const property = MetadataProperty.create({ key: props.key, value: props.value, description, jsDocTags, }); obj.properties.push(property); return property; }; //---- // REGULAR PROPERTIES //---- for (const symbol of props.type.getApparentProperties()) { // CHECK INTERNAL TAG if ((symbol.getJsDocTags(props.checker) ?? []).find((tag) => tag.name === "internal") !== undefined) continue; // CHECK NODE IS A FORMAL PROPERTY const [node, type] = (() => { const node = symbol.getDeclarations()?.[0]; const type = node ? props.checker.getTypeOfSymbolAtLocation(symbol, node) : props.checker.getTypeOfPropertyOfType(props.type, symbol.name); return [node, type]; })(); if ((node && pred(node) === false) || type === undefined) continue; // GET EXACT TYPE const key = MetadataHelper.literal_to_metadata(symbol.name); const value = explore_metadata({ ...props, type, explore: { top: false, object: obj, property: symbol.name, parameter: null, nested: null, aliased: false, escaped: false, output: false, }, intersected: false, }); Writable(value).optional = (symbol.flags & ts.SymbolFlags.Optional) !== 0; insert({ key, value, symbol, }); } //---- // DYNAMIC PROPERTIES //---- for (const index of props.checker.getIndexInfosOfType(props.type)) { // GET EXACT TYPE const analyzer = (type) => (property) => explore_metadata({ ...props, type, explore: { top: false, object: obj, property, parameter: null, nested: null, aliased: false, escaped: false, output: false, }, intersected: false, }); const key = analyzer(index.keyType)(null); const value = analyzer(index.type)({}); if (key.atomics.length + key.constants.map((c) => c.values.length).reduce((a, b) => a + b, 0) + key.templates.length + key.natives.filter((native) => native.name === "Boolean" || native.name === "BigInt" || native.name === "Number" || native.name === "String").length !== key.size()) props.errors.push({ name: key.getName(), explore: { top: false, object: obj, property: "[key]", parameter: null, nested: null, aliased: false, escaped: false, output: false, }, messages: [], }); // INSERT WITH REQUIRED CONFIGURATION insert({ key, value, symbol: index.declaration?.parent ? props.checker.getSymbolAtLocation(index.declaration.parent) : undefined, filter: (doc) => doc.name !== "default", }); } return obj; }; const significant = (functional) => functional ? (node) => !ts.isAccessor(node) : (node) => ts.isParameter(node) || ts.isPropertyDeclaration(node) || ts.isPropertyAssignment(node) || ts.isPropertySignature(node) || ts.isTypeLiteralNode(node) || ts.isShorthandPropertyAssignment(node); export { emplace_metadata_object }; //# sourceMappingURL=emplace_metadata_object.mjs.map