UNPKG

@adonis-cockpit/lucid-infer

Version:

Package to infer Lucid model attributes by parsing AST tree

81 lines (80 loc) 3.16 kB
export function getColumnsFromAST(ast) { const defaultExport = getDefaultExportFromAST(ast); if (!defaultExport) { console.warn("This module does not have a default export"); // TODO: Errors return []; } if (defaultExport.declaration.type !== "ClassDeclaration") { console.warn("This module does not default export a class"); // TODO: Errors return []; } // TODO: We might want to get computed aswell const nodes = defaultExport.declaration.body.body .filter((node) => node.type === "ClassProperty") .filter((node) => { const decorator = node.decorators?.find((d) => { if (d.expression.type !== "CallExpression") return false; const callee = d.expression.callee; if (callee.type === "MemberExpression" && callee.object.type === "Identifier") { return callee.object.name === "column"; } if (callee.type === "Identifier") { return callee.name === "column"; } return false; }); return Boolean(decorator); }); return nodes; } export function getDefaultExportFromAST(ast) { if (!("body" in ast) || !ast.body) { return; } const body = ast.body; if (!Array.isArray(body)) return; return body.find((node) => node.type === "ExportDefaultDeclaration"); } export function isClassPropertyNullable(property) { if (property.optional) return true; if (property.typeAnnotation?.type !== "TSTypeAnnotation") return false; const annotation = property.typeAnnotation.typeAnnotation; if (annotation.type !== "TSUnionType") return false; return Boolean(annotation.types.find((t) => ["TSUndefinedKeyword", "TSNullKeyword"].includes(t.type))); } export function getColumnType(property) { if (property.typeAnnotation?.type !== "TSTypeAnnotation") return { isArray: false, type: "unknown" }; const annotation = property.typeAnnotation.typeAnnotation; return getColumnTypeFromTSType(annotation); } export function getColumnTypeFromTSType(type) { if (type.type === "TSStringKeyword") return { isArray: false, type: "string" }; if (type.type === "TSNumberKeyword") return { isArray: false, type: "number" }; if (type.type === "TSBooleanKeyword") return { isArray: false, type: "boolean" }; if (type.type === "TSUnionType") { const nonNull = type.types.filter((f) => f.type !== "TSNullKeyword"); if (nonNull.length > 1) return { isArray: false, type: "complex" }; return getColumnTypeFromTSType(nonNull[0]); } if (type.type === "TSArrayType") { const child = getColumnTypeFromTSType(type.elementType); if (child.isArray) return { isArray: true, type: "complex" }; return { isArray: true, type: child.type }; } if (type.type === "TSTypeReference" && type.typeName.type === "Identifier") { return { isArray: false, type: type.typeName.name }; } return { isArray: false, type: "unknown" }; }