UNPKG

template-nestjs-generator

Version:

A custom NestJS CRUD generator

140 lines (129 loc) 6.64 kB
import * as ts from "typescript" import * as fs from "fs-extra" interface PropertyInfo { name: string type: string required?: boolean nullable?: boolean length?: number default?: any relation?: string } export function getEntityProperties(entityFilePath: string): PropertyInfo[] { const sourceFile = ts.createSourceFile( entityFilePath, fs.readFileSync(entityFilePath, "utf8"), ts.ScriptTarget.ESNext, true ) const properties: PropertyInfo[] = [] let propertyInfo: PropertyInfo ts.forEachChild(sourceFile, (node) => { if (ts.isClassDeclaration(node)) { node.members.forEach((member) => { if (ts.isPropertyDeclaration(member) && member.name) { const propertyName = member.name.getText(sourceFile) const typeNode = member.type const type = typeNode ? typeNode.getText(sourceFile) : "any" // Extract specific attributes from decorators const decorators = ts.getDecorators(member) propertyInfo = { name: propertyName, type, } as PropertyInfo if (decorators) { decorators.forEach((decorator) => { const expression = decorator.expression if ( ts.isCallExpression(expression) && ts.isIdentifier(expression.expression) ) { const decoratorName = expression.expression.getText(sourceFile) if ( decoratorName === "Column" || decoratorName === "PrimaryGeneratedColumn" ) { const args = expression.arguments if ( args.length > 0 && ts.isObjectLiteralExpression(args[0]) ) { args[0].properties.forEach( (property) => { if ( ts.isPropertyAssignment( property ) && ts.isIdentifier( property.name ) ) { const key = property.name.getText( sourceFile ) const value = property.initializer.getText( sourceFile ) if (key === "nullable") { propertyInfo.nullable = value === "true" } else if ( key === "length" ) { propertyInfo.length = parseInt(value, 10) } else if ( key === "default" ) { propertyInfo.default = value } propertyInfo.required = !propertyInfo.nullable } } ) } } } }) } properties.push(propertyInfo) } else if ( ts.isPropertyDeclaration(member) && ts.isIdentifier(member.name) ) { const propertyName = member.name.getText(sourceFile) const typeNode = member.type const type = typeNode ? typeNode.getText(sourceFile) : "any" // Check for relation decorators const decorators = ts.getDecorators(member) if (decorators) { decorators.forEach((decorator) => { const expression = decorator.expression if ( ts.isCallExpression(expression) && ts.isIdentifier(expression.expression) ) { const decoratorName = expression.expression.getText(sourceFile) if ( decoratorName === "OneToMany" || decoratorName === "ManyToOne" || decoratorName === "OneToOne" || decoratorName === "ManyToMany" ) { propertyInfo.relation = decoratorName } } }) } properties.push({ name: propertyName, type }) } }) } }) return properties }