From d8fb82943fc989eb63233433de308a98725072c0 Mon Sep 17 00:00:00 2001 From: "Max P." Date: Tue, 11 Mar 2025 13:31:22 +0100 Subject: [PATCH] feat: Introduced a new script to automate the generation of import statements for registered dependencies --- bin/generate-imports.cjs | 111 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 bin/generate-imports.cjs diff --git a/bin/generate-imports.cjs b/bin/generate-imports.cjs new file mode 100644 index 0000000..9c4c5bd --- /dev/null +++ b/bin/generate-imports.cjs @@ -0,0 +1,111 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const path = require('path'); +const yargs = require('yargs'); + +// CLI argument parsing +const argv = yargs + .option('src', { + alias: 's', + type: 'string', + description: 'Directory to search for files', + default: 'src', + }) + .option('output', { + alias: 'o', + type: 'string', + description: 'Path to the output file', + default: 'src/auto-imports.ts', + }) + .option('pattern', { + alias: 'p', + type: 'string', + description: 'File pattern to search for (e.g., .ts, .js)', + default: '.ts', + }) + .help() + .argv; + +// Fixed RegEx patterns for decorator detection +const SEARCH_PATTERNS = [ + /^@Register(?:<(.+)?>)?\(\s*["']{1}(.+)?["']{1}\s*,?\s*(true|false)?\s*\)/m, // Matches @Register(...) + /^@RegisterInstance(?:<(.+)?>)?\(\s*["']{1}(.+)?["']{1}\s*,?\s*(.+)?\s*\)/m, // Matches @RegisterInstance(...) +]; + +const FILE_PATTERN = argv.pattern.startsWith('.') ? argv.pattern : `.${argv.pattern}`; // Ensure the pattern starts with a dot + +/** + * Recursively searches for all files in a directory matching the specified pattern. + * @param {string} dirPath - The directory to search. + * @returns {string[]} - List of matching files. + */ +function getAllFiles(dirPath) { + let files = fs.readdirSync(dirPath); + let arrayOfFiles = []; + + files.forEach((file) => { + const fullPath = path.join(dirPath, file); + if (fs.statSync(fullPath).isDirectory()) { + arrayOfFiles = arrayOfFiles.concat(getAllFiles(fullPath)); + } else if (file.endsWith(FILE_PATTERN)) { + arrayOfFiles.push(fullPath); + } + }); + + return arrayOfFiles; +} + +/** + * Filters files that contain at least one of the specified regex patterns. + * @param {string[]} files - List of files to check. + * @returns {string[]} - Files that contain at least one of the specified patterns. + */ +function findFilesWithPattern(files) { + return files.filter((file) => { + const content = fs.readFileSync(file, 'utf8'); + return SEARCH_PATTERNS.some((pattern) => pattern.test(content)); + }); +} + +/** + * Generates an import file containing imports for all found files. + * @param {string[]} files - List of relevant files. + * @returns {string} - Generated import code. + */ +function generateImports(files) { + return files.map((file) => `import '${file.replace(/\\/g, '/')}';`).join('\n') + '\n'; +} + +/** + * Main function that executes the script. + */ +function main() { + try { + const srcDir = path.resolve(process.cwd(), argv.src); + const outputFile = path.resolve(process.cwd(), argv.output); + + if (!fs.existsSync(srcDir)) { + console.error(`❌ Error: The directory '${srcDir}' does not exist.`); + process.exit(1); + } + + const allFiles = getAllFiles(srcDir); + const filesWithPattern = findFilesWithPattern(allFiles); + + if (filesWithPattern.length === 0) { + console.log(`ℹ️ No ${FILE_PATTERN} files found matching the specified decorator patterns.`); + return; + } + + const importContent = generateImports(filesWithPattern); + fs.writeFileSync(outputFile, importContent); + + console.log(`✅ Imports successfully generated: ${outputFile}`); + } catch (error) { + console.error('❌ An error occurred:', error.message); + process.exit(1); + } +} + +main();