1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

  2. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

How to generate dynamic metadata from an Angular component using node js?

Discussão em 'Angular' iniciado por Marcos Laredo, Dezembro 14, 2024.

  1. I want to create a library with components example pages generated automatically by a node js code. Using some Copilot help, I got this function to read the component's metadata, but it is returning me empty. My knowledge in node is not so developed yet and I want to understand the process, not only copy from AI. This is the function with the interfaces - the code is in typescript for node. The function receives the angular component file path as parameter

    interface InputMetadata {
    name: string;
    type: string | null;
    defaultValue: string | null;
    }

    interface ComponentMetadata {
    selector: string;
    standalone: boolean;
    inputs: InputMetadata[];
    }

    // Function to read component metadata
    function readComponentMetadata(componentPath: string): ComponentMetadata {
    const componentFile = fs.readFileSync(componentPath, 'utf-8');
    const sourceFile = ts.createSourceFile(componentPath, componentFile, ts.ScriptTarget.Latest, true);
    const inputs: InputMetadata[] = [];
    let selector: string = '';
    let standalone: boolean = false;

    function visit(node: ts.Node) {
    if (ts.isClassDeclaration(node) && node.decorators) {
    node.decorators.forEach(decorator => {
    if (ts.isCallExpression(decorator.expression) && decorator.expression.expression.getText() === 'Component') {
    const args = decorator.expression.arguments;
    if (args.length) {
    const componentMetadata = args[0] as ts.ObjectLiteralExpression;
    componentMetadata.properties.forEach(property => {
    if (ts.isPropertyAssignment(property)) {
    if (property.name.getText() === 'selector') {
    selector = (property.initializer as ts.StringLiteral).text;
    } else if (property.name.getText() === 'standalone') {
    standalone = (property.initializer.kind === ts.SyntaxKind.TrueKeyword);
    }
    }
    });
    }
    }
    });
    }
    if (ts.isPropertyDeclaration(node) && node.decorators) {
    node.decorators.forEach(decorator => {
    if (ts.isCallExpression(decorator.expression) && decorator.expression.expression.getText() === 'Input') {
    const name = node.name.getText();
    const type = node.type ? node.type.getText() : null;
    const initializer = node.initializer ? node.initializer.getText() : null;
    inputs.push({name, type, defaultValue: initializer});
    }
    });
    }
    ts.forEachChild(node, visit);
    }

    visit(sourceFile);
    return {selector, standalone, inputs};
    }


    The file must be "compiled" using npx tsc and then the js file can be called.

    The node and typescript I'm using are:

    "devDependencies": {
    "@types/node": "^22.10.1",
    "typescript": "^5.7.2"
    }


    This is the tsconfig.json file:

    {
    "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
    },
    "include": ["src/**/*.ts"],
    "exclude": ["node_modules"]
    }

    Continue reading...

Compartilhe esta Página