typia
Version:
Superfast runtime validators with only one line
64 lines (55 loc) • 2.23 kB
text/typescript
import ts from "typescript";
import { LiteralFactory } from "../../../factories/LiteralFactory";
import { MetadataCollection } from "../../../factories/MetadataCollection";
import { MetadataFactory } from "../../../factories/MetadataFactory";
import { IMetadataApplication } from "../../../schemas/metadata/IMetadataApplication";
import { Metadata } from "../../../schemas/metadata/Metadata";
import { IProject } from "../../IProject";
import { TransformerError } from "../../TransformerError";
export namespace ReflectMetadataTransformer {
export const transform =
(project: IProject) =>
(expression: ts.CallExpression): ts.Expression => {
if (!expression.typeArguments?.length)
throw new TransformerError({
code: "typia.reflect.metadata",
message: "no generic argument.",
});
// VALIDATE TUPLE ARGUMENTS
const top: ts.Node = expression.typeArguments[0]!;
if (!ts.isTupleTypeNode(top)) return expression;
else if (top.elements.some((child) => !ts.isTypeNode(child)))
return expression;
// GET TYPES
const types: ts.Type[] = top.elements.map((child) =>
project.checker.getTypeFromTypeNode(child as ts.TypeNode),
);
if (types.some((t) => t.isTypeParameter()))
throw new TransformerError({
code: "typia.reflect.metadata",
message: "non-specified generic argument(s).",
});
// METADATA
const collection: MetadataCollection = new MetadataCollection();
const metadatas: Array<Metadata> = types.map((type) => {
const result = MetadataFactory.analyze(
project.checker,
project.context,
)({
escape: true,
constant: true,
absorb: true,
functional: true,
})(collection)(type);
if (result.success === false)
throw TransformerError.from("typia.reflect.metadata")(result.errors);
return result.data;
});
// CONVERT TO PRIMITIVE TYPE
const app: IMetadataApplication = {
metadatas: metadatas.map((metadata) => metadata.toJSON()),
components: collection.toJSON(),
};
return LiteralFactory.generate(app);
};
}