@nodeboot/aot
Version:
Node-Boot module for Ahead-of-Time (AOT) compilation. Generates node-boot beans and OpenAPI schemas at compile time
113 lines • 4.5 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const decorators_main_1 = require("../decorators.main");
/**
* Node-Boot AOT Beans Generator
*
* This script performs **Ahead-of-Time (AOT)** analysis of compiled JavaScript files
* in the `dist/` directory to detect classes annotated with key decorators like
* `@Controller`, `@Service`, etc., and generates a manifest (`node-boot-beans.json`)
* used for dynamic module registration at runtime.
*
* ### Features:
* - **Post-Build Hook**: Designed to run after the TypeScript build process completes.
* - **Decorator Detection**: Searches for files containing any of the known decorator types
* listed in `MAIN_DECORATORS`.
* - **Excludes `index.js`**: Skips barrel/index files to reduce false positives.
* - **Supports Nested Structures**: Recursively scans all subdirectories under `dist/`.
* - **Relative Paths**: Output paths are stored relative to `dist/`, aiding in dynamic imports.
* - **Safe by Default**: Creates `dist/` folder if missing (for robustness in CI/CD or clean builds).
*
* ### Output:
* Generates a file at:
* ```
* dist/node-boot-beans.json
* ```
* This file contains an array of strings, each representing a path to a JavaScript module
* exporting a decorated component (e.g., a controller or service).
*
* ### Usage:
* Run manually:
* ```sh
* node node-boot-aot-beans.js
* ```
*
* Or add it to your `package.json` lifecycle scripts:
* ```json
* {
* "scripts": {
* "postbuild": "node node-boot-aot-beans.js"
* }
* }
* ```
*
* ### Requirements:
* - Decorators like `@Controller`, `@Service`, etc., must be defined in `MAIN_DECORATORS`.
* - Ensure TypeScript has already been compiled to `dist/`.
*
* ---
* Part of the Node-Boot AOT toolchain for optimizing startup and reducing runtime scanning.
*
* @author Manuel Santos <https://github.com/manusant>
*/
// Define the `dist/` directory (output folder after TypeScript build)
const basePath = path_1.default.resolve(process.cwd(), "dist");
// Ensure `dist/` folder exists; create it if missing
if (!fs_1.default.existsSync(basePath)) {
console.log(`⚠️ dist/ folder not found. Creating it now...`);
fs_1.default.mkdirSync(basePath, { recursive: true });
}
const outputFile = path_1.default.join(basePath, "node-boot-beans.json");
console.log(`🔍 Scanning compiled files in: ${basePath}`);
/**
* Checks if a given file contains any of the specified decorators.
* @param {string} filePath - The full path of the file to check.
* @returns {boolean} - Returns `true` if the file contains a relevant decorator.
*/
function fileContainsRelevantDecorator(filePath) {
try {
const content = fs_1.default.readFileSync(filePath, "utf-8");
return decorators_main_1.MAIN_DECORATORS.some(decorator => content.includes(`${decorator})`));
}
catch {
return false;
}
}
/**
* Recursively scans a directory for files containing relevant decorators.
* @param {string} dir - The directory to scan.
* @returns {string[]} - A list of file paths (relative to `dist/`) containing decorators.
*/
function scanDirectory(dir) {
const beanFiles = [];
const files = fs_1.default.readdirSync(dir);
for (const file of files) {
const fullPath = path_1.default.join(dir, file);
const isDirectory = fs_1.default.statSync(fullPath).isDirectory();
if (isDirectory) {
// Recursively scan subdirectories
beanFiles.push(...scanDirectory(fullPath));
}
else if (file.endsWith(".js") && file !== "index.js" && fileContainsRelevantDecorator(fullPath)) {
// Store relative path instead of absolute
beanFiles.push(fullPath.replace(basePath + "/", ""));
}
}
return beanFiles;
}
function runAOTBeans() {
// Generate the list of beans
const beans = scanDirectory(basePath);
// Write to `node-boot-beans.json`
console.log(`📄 Writing bean metadata to: ${outputFile}`);
fs_1.default.writeFileSync(outputFile, JSON.stringify(beans, null, 2));
console.log(`✅ node-boot-beans.json created with ${beans.length} beans.`);
}
runAOTBeans();
//# sourceMappingURL=node-boot-aot-beans.js.map