UNPKG

create-nalth

Version:

🛡️ Create secure, modern web applications with the Nalth framework - HTTPS, CSP, and enterprise-grade security by default

41 lines (35 loc) 9.9 kB
import e from"node:fs";import t from"node:path";import{fileURLToPath as n}from"node:url";import r from"cross-spawn";import i from"mri";import*as a from"@clack/prompts";import o from"picocolors";const{blue:s,cyan:c,green:l,magenta:u,red:d,redBright:f,yellow:p}=o,m=i(process.argv.slice(2),{alias:{h:`help`,t:`template`},boolean:[`help`,`overwrite`],string:[`template`]}),h=process.cwd(),g=`\ ${s(`┌─────────────────────────────────────────────────────────────┐`)} ${s(`│`)} ${s(`🛡️ NALTH`)} ${s(`│`)} ${s(`│`)} ${c(`Security-First Web Framework`)} ${s(`│`)} ${s(`└─────────────────────────────────────────────────────────────┘`)} ${p(`USAGE:`)} ${l(`create-nalth`)} ${u(`[OPTIONS]`)} ${c(`[DIRECTORY]`)} ${p(`DESCRIPTION:`)} Bootstrap secure, enterprise-ready web applications with: ${l(`✓`)} HTTPS & TLS encryption by default ${l(`✓`)} Content Security Policy (CSP) auto-generation ${l(`✓`)} Real-time security monitoring & auditing ${l(`✓`)} Zero-config security headers & rate limiting ${p(`OPTIONS:`)} ${l(`-t, --template`)} ${c(`NAME`)} Use a specific framework template ${l(`-h, --help`)} Show this help message ${l(`--overwrite`)} Overwrite existing directory ${p(`AVAILABLE TEMPLATES:`)} ${p(`🟡 nalth-vanilla`)} Pure TypeScript with enterprise security ${l(`🟢 nalth-vue`)} Vue.js with security middleware ${c(`🔵 nalth-react`)} React with CSP & security headers ${u(`🟣 nalth-preact`)} Preact with HTTPS & monitoring ${f(`🔴 nalth-lit`)} Lit components with security features ${d(`⭐ nalth-svelte`)} Svelte with built-in protection ${s(`💙 nalth-solid`)} SolidJS with enterprise security ${c(`⚡ nalth-qwik`)} Qwik with zero-config security ${p(`EXAMPLES:`)} ${l(`create-nalth`)} # Interactive mode ${l(`create-nalth`)} ${c(`my-secure-app`)} # Create with default template ${l(`create-nalth`)} ${c(`my-app`)} ${u(`--template nalth-react`)} # Use React template ${s(`────────────────────────────────────────────────────────────────`)} ${c(`🌐 Learn more:`)} https://nalth.dev ${c(`📚 Documentation:`)} https://docs.nalth.dev ${c(`🔧 GitHub:`)} https://github.com/nalikiru-dev/nalth.js`,_=[{name:`nalth-vanilla`,display:`🟡 Vanilla TypeScript (Enterprise Security)`,color:p,variants:[{name:`nalth-vanilla`,display:`🛡️ TypeScript + Security Headers + HTTPS`,color:s}]},{name:`nalth-vue`,display:`🟢 Vue.js (Security + Reactivity)`,color:l,variants:[{name:`nalth-vue`,display:`🛡️ Vue.js + CSP + Security Middleware`,color:l}]},{name:`nalth-react`,display:`🔵 React (Enterprise Security)`,color:c,variants:[{name:`nalth-react`,display:`🛡️ React + Security Headers + Monitoring`,color:c}]},{name:`nalth-preact`,display:`🟣 Preact (Lightweight + Secure)`,color:u,variants:[{name:`nalth-preact`,display:`🛡️ Preact + HTTPS + Real-time Security`,color:u}]},{name:`nalth-lit`,display:`🔴 Lit (Web Components + Security)`,color:f,variants:[{name:`nalth-lit`,display:`🛡️ Lit Components + Security Features`,color:f}]},{name:`nalth-svelte`,display:`⭐ Svelte (Compiled + Protected)`,color:d,variants:[{name:`nalth-svelte`,display:`🛡️ Svelte + Built-in Security Protection`,color:d}]},{name:`nalth-solid`,display:`💙 SolidJS (Performance + Security)`,color:s,variants:[{name:`nalth-solid`,display:`🛡️ SolidJS + Enterprise Security Suite`,color:s}]},{name:`nalth-qwik`,display:`⚡ Qwik (Zero-Config Security)`,color:c,variants:[{name:`nalth-qwik`,display:`🛡️ Qwik + Automatic Security Configuration`,color:c}]}],v=_.map(e=>e.variants.map(e=>e.name)).reduce((e,t)=>e.concat(t),[]),y={_gitignore:`.gitignore`},b=`nalth-project`;async function x(){let i=m._[0]?S(String(m._[0])):void 0,o=m.template,d=m.overwrite,f=m.help;if(f){console.log(g);return}let x=k(process.env.npm_config_user_agent),E=()=>a.cancel(`Operation cancelled`),j=i;if(!j){let e=await a.text({message:`Project name:`,defaultValue:b,placeholder:b,validate:e=>e.length===0||S(e).length>0?void 0:`Invalid project name`});if(a.isCancel(e))return E();j=S(e)}if(e.existsSync(j)&&!D(j)){let e=d?`yes`:await a.select({message:(j===`.`?`Current directory`:`Target directory "${j}"`)+` is not empty. Please choose how to proceed:`,options:[{label:`Cancel operation`,value:`no`},{label:`Remove existing files and continue`,value:`yes`},{label:`Ignore files and continue`,value:`ignore`}]});if(a.isCancel(e))return E();switch(e){case`yes`:O(j);break;case`no`:E();return}}let N=t.basename(t.resolve(j));if(!w(N)){let e=await a.text({message:`Package name:`,defaultValue:T(N),placeholder:T(N),validate(e){if(!w(e))return`Invalid package.json name`}});if(a.isCancel(e))return E();N=e}let P=o,F=!1;if(o&&!v.includes(o)&&(P=void 0,F=!0),!P){let e=await a.select({message:F?`"${o}" isn't a valid template. Please choose from below: `:`Select a framework:`,options:_.map(e=>{let t=e.color;return{label:t(e.display||e.name),value:e}})});if(a.isCancel(e))return E();let t=await a.select({message:`Select a variant:`,options:e.variants.map(e=>{let t=e.color,n=e.customCommand?M(e.customCommand,x).replace(/ TARGET_DIR$/,``):void 0;return{label:t(e.display||e.name),value:e.name,hint:n}})});if(a.isCancel(t))return E();P=t}let I=t.join(h,j);e.mkdirSync(I,{recursive:!0});let L=!1;P.includes(`-swc`)&&(L=!0,P=P.replace(`-swc`,``));let R=x?x.name:`npm`,{customCommand:z}=_.flatMap(e=>e.variants).find(e=>e.name===P)??{};if(z){let e=M(z,x),[t,...n]=e.split(` `),i=n.map(e=>e.replace(`TARGET_DIR`,()=>j)),{status:a}=r.sync(t,i,{stdio:`inherit`});process.exit(a??0)}a.log.step(`🛡️ Scaffolding secure Nalth project in ${l(I)}...`),a.log.info(`🔍 Setting up enterprise-grade security features...`);let B=t.resolve(n(import.meta.url),`../..`,P),V=(n,r)=>{let i=t.join(I,y[n]??n);r?e.writeFileSync(i,r):C(t.join(B,n),i)},H=e.readdirSync(B);for(let e of H.filter(e=>e!==`package.json`))V(e);let U=JSON.parse(e.readFileSync(t.join(B,`package.json`),`utf-8`));U.name=N,V(`package.json`,JSON.stringify(U,null,2)+` `),L&&A(I,P.endsWith(`-ts`));let W=``,G=t.relative(h,I);switch(W+=`${s(`┌─────────────────────────────────────────────┐`)}\n`,W+=`${s(`│`)} 🎉 ${l(`PROJECT CREATED SUCCESSFULLY!`)} 🎉 ${s(`│`)}\n`,W+=`${s(`└─────────────────────────────────────────────┘`)}\n\n`,W+=`📋 ${p(`Project:`)} ${c(t.basename(I))}\n`,W+=`📁 ${p(`Location:`)} ${c(I)}\n`,W+=`🔥 ${p(`Template:`)} ${u(P)}\n\n`,W+=`${l(`SECURITY FEATURES ENABLED:`)}\n`,W+=` ${l(`✓`)} HTTPS & TLS encryption\n`,W+=` ${l(`✓`)} Content Security Policy (CSP)\n`,W+=` ${l(`✓`)} Security headers & rate limiting\n`,W+=` ${l(`✓`)} Real-time security monitoring\n\n`,W+=`${p(`🚀 NEXT STEPS:`)}\n`,I!==h&&(W+=`\n 1. ${c(`cd`)} ${G.includes(` `)?`"${G}"`:G}`),R){case`yarn`:W+=`\n ${I===h?`1`:`2`}. ${c(`yarn`)} ${u(`# Install dependencies`)}`,W+=`\n ${I===h?`2`:`3`}. ${c(`yarn dev`)} ${u(`# Start secure HTTPS development server`)}`;break;default:W+=`\n ${I===h?`1`:`2`}. ${c(`${R} install`)} ${u(`# Install dependencies`)}`,W+=`\n ${I===h?`2`:`3`}. ${c(`${R} run dev`)} ${u(`# Start secure HTTPS development server`)}`;break}W+=`\n\n${s(`═══════════════════════════════════════════════`)}\n`,W+=`🌐 ${c(`Your app will be available at:`)} ${l(`https://localhost:3000`)}\n`,W+=`🔒 ${c(`Security dashboard:`)} ${l(`https://localhost:3000/__nalth`)}\n`,W+=`📚 ${c(`Documentation:`)} ${s(`https://docs.nalth.dev`)}\n`,W+=`${s(`═══════════════════════════════════════════════`)}`,a.outro(W)}function S(e){return e.trim().replace(/\/+$/g,``)}function C(t,n){let r=e.statSync(t);r.isDirectory()?E(t,n):e.copyFileSync(t,n)}function w(e){return/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(e)}function T(e){return e.trim().toLowerCase().replace(/\s+/g,`-`).replace(/^[._]/,``).replace(/[^a-z\d\-~]+/g,`-`)}function E(n,r){e.mkdirSync(r,{recursive:!0});for(let i of e.readdirSync(n)){let e=t.resolve(n,i),a=t.resolve(r,i);C(e,a)}}function D(t){let n=e.readdirSync(t);return n.length===0||n.length===1&&n[0]===`.git`}function O(n){if(e.existsSync(n))for(let r of e.readdirSync(n)){if(r===`.git`)continue;e.rmSync(t.resolve(n,r),{recursive:!0,force:!0})}}function k(e){if(!e)return;let t=e.split(` `)[0],n=t.split(`/`);return{name:n[0],version:n[1]}}function A(e,n){j(t.resolve(e,`package.json`),e=>e.replace(/"@vitejs\/plugin-react": ".+?"/,`"@vitejs/plugin-react-swc": "^4.0.0"`)),j(t.resolve(e,`vite.config.${n?`ts`:`js`}`),e=>e.replace(`@vitejs/plugin-react`,`@vitejs/plugin-react-swc`))}function j(t,n){let r=e.readFileSync(t,`utf-8`);e.writeFileSync(t,n(r),`utf-8`)}function M(e,t){let n=t?t.name:`npm`,r=n===`yarn`&&t?.version.startsWith(`1.`);return e.replace(/^npm create (?:-- )?/,()=>n===`bun`?`bun x create-`:n===`pnpm`?`pnpm create `:e.startsWith(`npm create -- `)?`${n} create -- `:`${n} create `).replace(`@latest`,()=>r?``:`@latest`).replace(/^npm exec/,()=>n===`pnpm`?`pnpm dlx`:n===`yarn`&&!r?`yarn dlx`:n===`bun`?`bun x`:`npm exec`)}x().catch(e=>{console.error(e)});export{};