folder-validator
Version:
A powerful tool to validate and maintain consistent folder structures across your projects
7 lines • 5.12 kB
JavaScript
;var O=Object.create;var C=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var k=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty;var U=(e,r,o,i)=>{if(r&&typeof r=="object"||typeof r=="function")for(let n of b(r))!A.call(e,n)&&n!==o&&C(e,n,{get:()=>r[n],enumerable:!(i=S(r,n))||i.enumerable});return e};var u=(e,r,o)=>(o=e!=null?O(k(e)):{},U(r||!e||!e.__esModule?C(o,"default",{value:e,enumerable:!0}):o,e));var V=u(require("fs"),1),y=u(require("path"),1),c=u(require("chalk"),1),E=u(require("chokidar"),1);var $=u(require("fs"),1),F=u(require("path"),1);var q=[{name:"node_modules",required:!1},{name:".next",required:!1},{name:".git",required:!1},{name:"dist",required:!1},{name:"build",required:!1},{name:"coverage",required:!1},{name:".husky",required:!1},{name:".vscode",required:!1}];var p=e=>e.map(r=>({...r,required:r.required??!1,children:r.children?p(r.children):void 0})),I=async e=>{if(!$.default.existsSync(e))return console.warn(`Config file not found: ${e}. Using default folders only.`),[];let r=F.default.extname(e);try{if(r===".ts"||r===".js"){let{default:o}=await import(`file://${F.default.resolve(e)}`);return p(o)}else throw new Error("Unsupported config file format. Use .ts or .js")}catch(o){return console.error("Error loading config:",o),[]}},R=async e=>{try{return(await $.default.promises.readdir(e,{withFileTypes:!0})).filter(o=>o.isDirectory()).map(o=>o.name)}catch(r){return console.error("Error reading directory:",r),[]}},h=(e,r,o)=>{let i=o.ignoreCase?(n,t)=>n.toLowerCase()===t.toLowerCase():(n,t)=>n===t;return r.some(n=>i(e,n.name))};async function v(e,r,o,i,n="",t){let d=await R(e),g=d.filter(s=>!h(s,r,o));if(g.length>0){if(o.strict){i.isValid=!1;let s=n?`${n}/`:"";i.errors.push(`Disallowed folders found in ${s}: ${g.join(", ")}`)}else if(!o.allowUnknown){let s=n?`${n}/`:"";i.warnings.push(`Unknown folders found in ${s}: ${g.join(", ")}`)}}let m=r.filter(s=>s.required).filter(s=>!d.some(l=>h(l,[s],o)));if(m.length>0){i.isValid=!1;let s=n?`${n}/`:"";i.errors.push(`Missing required folders in ${s}: ${m.map(l=>l.name).join(", ")}`)}let w=r.filter(s=>!s.required).filter(s=>{if(!t)return!0;let l=n?`${n}/${s.name}`:s.name;return t.has(l)}).filter(s=>!d.some(l=>h(l,[s],o)));if(w.length>0){let s=n?`${n}/`:"",l=w.map(a=>{let f=[];return f.push(a.name),a.description&&f.push(a.description),f.join(" - ")}).join(`
\u2022 `);i.warnings.push(`Optional folders that could be added in ${s}:
\u2022 ${l}`)}for(let s of d){let l=r.find(a=>h(s,[a],o));if(l!=null&&l.children){let a=F.default.join(e,s),f=n?`${n}/${s}`:s;await v(a,l.children,o,i,f,t)}}}var D=async(e,r,o={})=>{let n={...{strict:!1,allowUnknown:!0,ignoreCase:!1},...o},t={isValid:!0,errors:[],warnings:[]};try{let d=typeof r=="string"?await I(r):r,g=[...d,...q],m=new Set,w=(s,l="")=>{for(let a of s){let f=l?`${l}/${a.name}`:a.name;m.add(f),a.children&&w(a.children,f)}};return w(d),await v(e,g,n,t,"",m),t}catch(d){return t.isValid=!1,t.errors.push(`Error checking folder structure: ${d}`),t}};var N=["folder.config.json","folder.config.js"];async function L(e){for(let r of N){let o=y.default.join(e,r);if(V.default.existsSync(o))return o}return null}async function W(e){var r;try{if(y.default.extname(e)===".json"){let i=await V.default.promises.readFile(e,"utf-8"),n=JSON.parse(i),t=n.folders||n;return p(Array.isArray(t)?t:[])}else{let n=await import(y.default.resolve(e)),t=((r=n.default)==null?void 0:r.folders)||n.default||n.folders||n;return p(Array.isArray(t)?t:[])}}catch(o){console.error(c.default.red(`Error loading config: ${o}`)),process.exit(1)}}async function x(e,r){try{let o=await W(r),i=await D(e,o,{strict:!0,ignoreCase:!0});return i.isValid?console.log(c.default.green("[Success]")+" - All folders match the expected structure"):(console.log(c.default.red("[Error]")+" - Folder structure validation failed"),i.errors.forEach(n=>{console.log(c.default.red("[Error]")+` ${n}`)})),i.warnings.length>0&&i.warnings.forEach(n=>{console.log(c.default.yellow("[Warning]")+` ${n}`)}),i.isValid}catch(o){return console.error(c.default.red(`
\u274C Error: ${o}
`)),!1}}async function _(e,r){console.log(c.default.blue("info")+" - Watching for folder structure changes. Press Ctrl+C to stop"),E.default.watch(e,{ignored:[/(^|[\/\\])\../,"node_modules","dist"],persistent:!0,ignoreInitial:!1,depth:5,awaitWriteFinish:!0}).on("addDir",async i=>{console.log(c.default.blue("[Info]")+` - New folder detected: ${i}`),await x(e,r)}).on("unlinkDir",async i=>{console.log(c.default.blue("[Info]")+` - Folder removed: ${i}`),await x(e,r)})}async function M(){let e=process.argv.slice(2),r=e.includes("--watch")||e.includes("-w"),o=process.cwd(),i=await L(o);if(i||(console.error(c.default.red("[Error]")+" - No configuration file found. Create one of: folder.config.ts, folder.config.js, or folder.config.json"),process.exit(1)),r)await _(o,i);else{let n=await x(o,i);process.exit(n?0:1)}}M().catch(e=>{console.error(c.default.red("[Error]")+` - Fatal error occurred: ${e}`),process.exit(1)});
//# sourceMappingURL=cli.cjs.map