UNPKG

js-barrels

Version:

A CLI for generating barrels in any Javascript project

182 lines (166 loc) 4.7 kB
#!/usr/bin/env node import { readdirSync, readFileSync, writeFileSync } from "fs"; import { join } from "path"; import yargs from "yargs"; import watch from "node-watch"; import chalk from "chalk"; const argv = yargs .options({ dir: { alias: "d", demandOption: true, type: "string", description: "Directory to generate barrels for", }, watch: { alias: "w", type: "boolean", description: "Watch directory and update barrels", }, ext: { alias: "e", type: "string", description: "Extension to create the barrel file with, auto-detected by default", }, }) .parseSync(); function joinPath(...path: string[]) { return join(process.cwd(), ...path); } function makeBarrels(watch: boolean, dir?: string, log?: boolean) { const dirFiles = readdirSync(joinPath(dir || argv.dir)); const extension = argv.ext || (dirFiles.join(",").includes(".ts") ? "ts" : "js"); const comments = `// AUTO GENERATED BY JS-BARRELS`; if (dirFiles.includes(`index.${extension}`)) { const fileContents = readFileSync( joinPath( dir || argv.dir, dirFiles.find((f) => f === `index.${extension}`)! ) ).toString(); if (!fileContents.startsWith(comments)) { console.log( chalk.bgRed("\n ERROR "), chalk.red( "Directory already contains an index file not generated by js-barrels." ) ); process.exit(); } } type Export = { default: boolean; name: string; fileName: string; }; const e: Export[] = []; for (const file of dirFiles) { if (file.includes(".")) { const fileContents = readFileSync( joinPath(dir || argv.dir, file) ).toString(); if ( (fileContents.includes("export") || file.includes("svelte") || file.includes("vue")) && !file.includes("index") ) { let stringToSearch = "export default"; if (file.includes("svelte") || file.includes("vue")) { e.push({ default: true, name: file.split(".")[0], fileName: `./${file}`, }); } else { if (fileContents.includes(stringToSearch)) { const contents = fileContents .substring( fileContents.indexOf(stringToSearch), fileContents.length ) .split("\n")[0]; const filteredContents = contents.substring( stringToSearch.length + 1, contents.length ); if ( filteredContents.startsWith("function") || filteredContents.startsWith("interface") ) { let keyword = filteredContents.startsWith("function") ? "function" : "interface"; const id = filteredContents.substring( keyword.length + 1, filteredContents.length ); const token = keyword === "function" ? id.substring(0, id.indexOf("(")) : id.substring(0, id.indexOf(" ")); e.push({ default: true, name: token, fileName: `./${ file.includes("ts") || file.includes("js") ? file.split(".")[0] : file }`, }); } } if (fileContents.includes("export")) e.push({ default: false, name: "", fileName: `./${ file.includes("ts") || file.includes("js") ? file.split(".")[0] : file }`, }); } } } else { makeBarrels(false, join(argv.dir, file), true); } } const generatedFile = `${comments} ${e .map((ex) => ex.default ? `export { default as ${ex.name} } from "${ex.fileName}";` : `export * from "${ex.fileName}";` ) .join("\n")}`; writeFileSync(joinPath(dir || argv.dir, `index.${extension}`), generatedFile); if (watch) { console.log( chalk.bgYellow(" FILE SAVED "), chalk.yellow("Barrel files regenerated.") ); } else if (!log) { console.log( "\n" + chalk.bgGreen(" SUCCESS "), chalk.green("Barrel files generated.\n") ); } } if (argv.watch) { makeBarrels(false); watch( argv.dir, { recursive: false, filter: (f) => !f.includes("index.ts") && !f.includes("index.js"), }, () => { makeBarrels(true); } ); } else { makeBarrels(false); }