create-nexo 1.1.5 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/nexo.js +1889 -420
- package/dist/index.js +1808 -96
- package/package.json +8 -6
- package/dist/api/index.d.ts +0 -196
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js +0 -233
- package/dist/api/index.js.map +0 -7
- package/dist/bin/nexo.d.ts +0 -2
- package/dist/bin/nexo.d.ts.map +0 -1
- package/dist/bin/nexo.js.map +0 -7
- package/dist/configurators/core/framework.d.ts +0 -3
- package/dist/configurators/core/framework.d.ts.map +0 -1
- package/dist/configurators/core/framework.js +0 -66
- package/dist/configurators/core/framework.js.map +0 -7
- package/dist/configurators/core/index.d.ts +0 -4
- package/dist/configurators/core/index.d.ts.map +0 -1
- package/dist/configurators/core/index.js +0 -9
- package/dist/configurators/core/index.js.map +0 -7
- package/dist/configurators/core/language.d.ts +0 -3
- package/dist/configurators/core/language.d.ts.map +0 -1
- package/dist/configurators/core/language.js +0 -58
- package/dist/configurators/core/language.js.map +0 -7
- package/dist/configurators/core/variant.d.ts +0 -3
- package/dist/configurators/core/variant.d.ts.map +0 -1
- package/dist/configurators/core/variant.js +0 -22
- package/dist/configurators/core/variant.js.map +0 -7
- package/dist/configurators/factory.d.ts +0 -36
- package/dist/configurators/factory.d.ts.map +0 -1
- package/dist/configurators/factory.js +0 -48
- package/dist/configurators/factory.js.map +0 -7
- package/dist/configurators/index.d.ts +0 -5
- package/dist/configurators/index.d.ts.map +0 -1
- package/dist/configurators/index.js +0 -5
- package/dist/configurators/index.js.map +0 -7
- package/dist/configurators/project/ai-instructions.d.ts +0 -7
- package/dist/configurators/project/ai-instructions.d.ts.map +0 -1
- package/dist/configurators/project/ai-instructions.js +0 -540
- package/dist/configurators/project/ai-instructions.js.map +0 -7
- package/dist/configurators/project/auth.d.ts +0 -3
- package/dist/configurators/project/auth.d.ts.map +0 -1
- package/dist/configurators/project/auth.js +0 -44
- package/dist/configurators/project/auth.js.map +0 -7
- package/dist/configurators/project/cicd.d.ts +0 -30
- package/dist/configurators/project/cicd.d.ts.map +0 -1
- package/dist/configurators/project/cicd.js +0 -298
- package/dist/configurators/project/cicd.js.map +0 -7
- package/dist/configurators/project/i18n.d.ts +0 -3
- package/dist/configurators/project/i18n.d.ts.map +0 -1
- package/dist/configurators/project/i18n.js +0 -83
- package/dist/configurators/project/i18n.js.map +0 -7
- package/dist/configurators/project/index.d.ts +0 -7
- package/dist/configurators/project/index.d.ts.map +0 -1
- package/dist/configurators/project/index.js +0 -16
- package/dist/configurators/project/index.js.map +0 -7
- package/dist/configurators/project/mandatory.d.ts +0 -3
- package/dist/configurators/project/mandatory.d.ts.map +0 -1
- package/dist/configurators/project/mandatory.js +0 -160
- package/dist/configurators/project/mandatory.js.map +0 -7
- package/dist/configurators/project/structure.d.ts +0 -3
- package/dist/configurators/project/structure.d.ts.map +0 -1
- package/dist/configurators/project/structure.js +0 -79
- package/dist/configurators/project/structure.js.map +0 -7
- package/dist/configurators/state/animation.d.ts +0 -2
- package/dist/configurators/state/animation.d.ts.map +0 -1
- package/dist/configurators/state/animation.js +0 -18
- package/dist/configurators/state/animation.js.map +0 -7
- package/dist/configurators/state/dataFetching.d.ts +0 -3
- package/dist/configurators/state/dataFetching.d.ts.map +0 -1
- package/dist/configurators/state/dataFetching.js +0 -36
- package/dist/configurators/state/dataFetching.js.map +0 -7
- package/dist/configurators/state/forms.d.ts +0 -2
- package/dist/configurators/state/forms.d.ts.map +0 -1
- package/dist/configurators/state/forms.js +0 -31
- package/dist/configurators/state/forms.js.map +0 -7
- package/dist/configurators/state/index.d.ts +0 -6
- package/dist/configurators/state/index.d.ts.map +0 -1
- package/dist/configurators/state/index.js +0 -13
- package/dist/configurators/state/index.js.map +0 -7
- package/dist/configurators/state/routing.d.ts +0 -2
- package/dist/configurators/state/routing.d.ts.map +0 -1
- package/dist/configurators/state/routing.js +0 -17
- package/dist/configurators/state/routing.js.map +0 -7
- package/dist/configurators/state/state.d.ts +0 -3
- package/dist/configurators/state/state.d.ts.map +0 -1
- package/dist/configurators/state/state.js +0 -94
- package/dist/configurators/state/state.js.map +0 -7
- package/dist/configurators/styling/icons.d.ts +0 -2
- package/dist/configurators/styling/icons.d.ts.map +0 -1
- package/dist/configurators/styling/icons.js +0 -25
- package/dist/configurators/styling/icons.js.map +0 -7
- package/dist/configurators/styling/index.d.ts +0 -4
- package/dist/configurators/styling/index.d.ts.map +0 -1
- package/dist/configurators/styling/index.js +0 -9
- package/dist/configurators/styling/index.js.map +0 -7
- package/dist/configurators/styling/styling.d.ts +0 -3
- package/dist/configurators/styling/styling.d.ts.map +0 -1
- package/dist/configurators/styling/styling.js +0 -141
- package/dist/configurators/styling/styling.js.map +0 -7
- package/dist/configurators/styling/ui.d.ts +0 -3
- package/dist/configurators/styling/ui.d.ts.map +0 -1
- package/dist/configurators/styling/ui.js +0 -179
- package/dist/configurators/styling/ui.js.map +0 -7
- package/dist/constants/index.d.ts +0 -94
- package/dist/constants/index.d.ts.map +0 -1
- package/dist/constants/index.js +0 -94
- package/dist/constants/index.js.map +0 -7
- package/dist/core/config.d.ts +0 -62
- package/dist/core/config.d.ts.map +0 -1
- package/dist/core/config.js +0 -121
- package/dist/core/config.js.map +0 -7
- package/dist/core/index.d.ts +0 -7
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -12
- package/dist/core/index.js.map +0 -7
- package/dist/core/lazy-loader.d.ts +0 -57
- package/dist/core/lazy-loader.d.ts.map +0 -1
- package/dist/core/lazy-loader.js +0 -211
- package/dist/core/lazy-loader.js.map +0 -7
- package/dist/core/parallel.d.ts +0 -29
- package/dist/core/parallel.d.ts.map +0 -1
- package/dist/core/parallel.js +0 -100
- package/dist/core/parallel.js.map +0 -7
- package/dist/core/presets.d.ts +0 -10
- package/dist/core/presets.d.ts.map +0 -1
- package/dist/core/presets.js +0 -76
- package/dist/core/presets.js.map +0 -7
- package/dist/core/prompts/core.d.ts +0 -18
- package/dist/core/prompts/core.d.ts.map +0 -1
- package/dist/core/prompts/core.js +0 -424
- package/dist/core/prompts/core.js.map +0 -7
- package/dist/core/prompts/filter.d.ts +0 -34
- package/dist/core/prompts/filter.d.ts.map +0 -1
- package/dist/core/prompts/filter.js +0 -28
- package/dist/core/prompts/filter.js.map +0 -7
- package/dist/core/prompts/index.d.ts +0 -10
- package/dist/core/prompts/index.d.ts.map +0 -1
- package/dist/core/prompts/index.js +0 -71
- package/dist/core/prompts/index.js.map +0 -7
- package/dist/core/prompts/optional.d.ts +0 -16
- package/dist/core/prompts/optional.d.ts.map +0 -1
- package/dist/core/prompts/optional.js +0 -290
- package/dist/core/prompts/optional.js.map +0 -7
- package/dist/core/prompts/utils.d.ts +0 -25
- package/dist/core/prompts/utils.d.ts.map +0 -1
- package/dist/core/prompts/utils.js +0 -25
- package/dist/core/prompts/utils.js.map +0 -7
- package/dist/core/prompts.d.ts +0 -6
- package/dist/core/prompts.d.ts.map +0 -1
- package/dist/core/prompts.js +0 -2
- package/dist/core/prompts.js.map +0 -7
- package/dist/core/setup.d.ts +0 -38
- package/dist/core/setup.d.ts.map +0 -1
- package/dist/core/setup.js +0 -110
- package/dist/core/setup.js.map +0 -7
- package/dist/core/wizard.d.ts +0 -39
- package/dist/core/wizard.d.ts.map +0 -1
- package/dist/core/wizard.js +0 -242
- package/dist/core/wizard.js.map +0 -7
- package/dist/errors/index.d.ts +0 -67
- package/dist/errors/index.d.ts.map +0 -1
- package/dist/errors/index.js +0 -213
- package/dist/errors/index.js.map +0 -7
- package/dist/errors/messages.d.ts +0 -56
- package/dist/errors/messages.d.ts.map +0 -1
- package/dist/errors/messages.js +0 -214
- package/dist/errors/messages.js.map +0 -7
- package/dist/generators/index.d.ts +0 -86
- package/dist/generators/index.d.ts.map +0 -1
- package/dist/generators/index.js +0 -364
- package/dist/generators/index.js.map +0 -7
- package/dist/index.d.ts +0 -16
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -7
- package/dist/plugins/index.d.ts +0 -48
- package/dist/plugins/index.d.ts.map +0 -1
- package/dist/plugins/index.js +0 -25
- package/dist/plugins/index.js.map +0 -7
- package/dist/plugins/loader.d.ts +0 -38
- package/dist/plugins/loader.d.ts.map +0 -1
- package/dist/plugins/loader.js +0 -173
- package/dist/plugins/loader.js.map +0 -7
- package/dist/plugins/manager.d.ts +0 -32
- package/dist/plugins/manager.d.ts.map +0 -1
- package/dist/plugins/manager.js +0 -144
- package/dist/plugins/manager.js.map +0 -7
- package/dist/plugins/types.d.ts +0 -186
- package/dist/plugins/types.d.ts.map +0 -1
- package/dist/plugins/types.js +0 -1
- package/dist/plugins/types.js.map +0 -7
- package/dist/security/index.d.ts +0 -59
- package/dist/security/index.d.ts.map +0 -1
- package/dist/security/index.js +0 -189
- package/dist/security/index.js.map +0 -7
- package/dist/templates/entry.d.ts +0 -9
- package/dist/templates/entry.d.ts.map +0 -1
- package/dist/templates/entry.js +0 -24
- package/dist/templates/entry.js.map +0 -7
- package/dist/templates/index.d.ts +0 -7
- package/dist/templates/index.d.ts.map +0 -1
- package/dist/templates/index.js +0 -12
- package/dist/templates/index.js.map +0 -7
- package/dist/templates/main.d.ts +0 -6
- package/dist/templates/main.d.ts.map +0 -1
- package/dist/templates/main.js +0 -99
- package/dist/templates/main.js.map +0 -7
- package/dist/templates/readme.d.ts +0 -3
- package/dist/templates/readme.d.ts.map +0 -1
- package/dist/templates/readme.js +0 -145
- package/dist/templates/readme.js.map +0 -7
- package/dist/templates/styles.d.ts +0 -6
- package/dist/templates/styles.d.ts.map +0 -1
- package/dist/templates/styles.js +0 -206
- package/dist/templates/styles.js.map +0 -7
- package/dist/templates/welcome.d.ts +0 -10
- package/dist/templates/welcome.d.ts.map +0 -1
- package/dist/templates/welcome.js +0 -294
- package/dist/templates/welcome.js.map +0 -7
- package/dist/types/index.d.ts +0 -51
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -1
- package/dist/types/index.js.map +0 -7
- package/dist/utils/batch-writer.d.ts +0 -101
- package/dist/utils/batch-writer.d.ts.map +0 -1
- package/dist/utils/batch-writer.js +0 -155
- package/dist/utils/batch-writer.js.map +0 -7
- package/dist/utils/cache.d.ts +0 -60
- package/dist/utils/cache.d.ts.map +0 -1
- package/dist/utils/cache.js +0 -114
- package/dist/utils/cache.js.map +0 -7
- package/dist/utils/detection.d.ts +0 -4
- package/dist/utils/detection.d.ts.map +0 -1
- package/dist/utils/detection.js +0 -36
- package/dist/utils/detection.js.map +0 -7
- package/dist/utils/fileTree.d.ts +0 -3
- package/dist/utils/fileTree.d.ts.map +0 -1
- package/dist/utils/fileTree.js +0 -84
- package/dist/utils/fileTree.js.map +0 -7
- package/dist/utils/fs.d.ts +0 -22
- package/dist/utils/fs.d.ts.map +0 -1
- package/dist/utils/fs.js +0 -79
- package/dist/utils/fs.js.map +0 -7
- package/dist/utils/helpers.d.ts +0 -91
- package/dist/utils/helpers.d.ts.map +0 -1
- package/dist/utils/helpers.js +0 -154
- package/dist/utils/helpers.js.map +0 -7
- package/dist/utils/index.d.ts +0 -10
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -15
- package/dist/utils/index.js.map +0 -7
- package/dist/utils/logger.d.ts +0 -98
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -159
- package/dist/utils/logger.js.map +0 -7
- package/dist/utils/package-manager.d.ts +0 -26
- package/dist/utils/package-manager.d.ts.map +0 -1
- package/dist/utils/package-manager.js +0 -64
- package/dist/utils/package-manager.js.map +0 -7
- package/dist/utils/progress.d.ts +0 -85
- package/dist/utils/progress.d.ts.map +0 -1
- package/dist/utils/progress.js +0 -147
- package/dist/utils/progress.js.map +0 -7
- package/dist/utils/spinner.d.ts +0 -9
- package/dist/utils/spinner.d.ts.map +0 -1
- package/dist/utils/spinner.js +0 -59
- package/dist/utils/spinner.js.map +0 -7
- package/dist/validation/index.d.ts +0 -63
- package/dist/validation/index.d.ts.map +0 -1
- package/dist/validation/index.js +0 -234
- package/dist/validation/index.js.map +0 -7
package/dist/bin/nexo.js
CHANGED
|
@@ -1,432 +1,1901 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from "
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { dirname } from 'node:path';
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
var On=Object.defineProperty;var b=(e,t)=>()=>(e&&(t=e(e=0)),t);var T=(e,t)=>{for(var r in t)On(e,r,{get:t[r],enumerable:!0})};var Nt={};T(Nt,{addDependency:()=>d,addScript:()=>Q,copy:()=>Rt,createProjectDir:()=>Se,ensureDir:()=>m,getPackageJson:()=>x,pathExists:()=>I,readJson:()=>Ve,remove:()=>Ft,removeFile:()=>ke,savePackageJson:()=>P,writeFile:()=>p,writeJson:()=>B});import K from"node:fs/promises";import qe from"node:path";var I,m,Ve,B,p,ke,Ft,Rt,Se,x,P,d,Q,E=b(()=>{"use strict";I=async e=>{try{return await K.access(e),!0}catch{return!1}},m=async e=>{await K.mkdir(e,{recursive:!0})},Ve=async e=>{let t=await K.readFile(e,"utf-8");return JSON.parse(t)},B=async(e,t,r=2)=>{await K.writeFile(e,JSON.stringify(t,null,r)+`
|
|
9
|
+
`)},p=async(e,t)=>{if(await I(e))try{if(await K.readFile(e,"utf-8")===t)return}catch{}await K.writeFile(e,t)},ke=async e=>{await K.unlink(e)},Ft=async e=>{await K.rm(e,{recursive:!0,force:!0})},Rt=async(e,t)=>{await K.cp(e,t,{recursive:!0})},Se=async e=>{await m(e.projectPath),await m(qe.join(e.projectPath,"src"))},x=async e=>{let t=qe.join(e.projectPath,"package.json");return await I(t)?await Ve(t):{name:e.selections?.projectName||"my-nexo-app",version:"0.1.0",private:!0,type:"module",dependencies:{},devDependencies:{},scripts:{}}},P=async(e,t)=>{await B(qe.join(e.projectPath,"package.json"),t)},d=(e,t,r,n=!1)=>{n?(e.devDependencies=e.devDependencies||{},e.devDependencies[t]=r):(e.dependencies=e.dependencies||{},e.dependencies[t]=r)},Q=(e,t,r)=>{e.scripts=e.scripts||{},e.scripts[t]=r}});import er from"node:fs/promises";import Ye from"node:path";var Re,Wn,Jn,ae,et,tr,Hn,qn,Vn,rr=b(()=>{"use strict";E();Re=(e={})=>{let{maxConcurrency:t=10,baseDir:r="",createDirs:n=!0,onWrite:o,onError:s}=e,i=new Map,l=k=>r&&!Ye.isAbsolute(k)?Ye.join(r,k):k,u=(k,f)=>{let A=l(k);return i.set(A,{path:A,content:f,type:"file"}),N},a=(k,f)=>{let A=l(k);return i.set(A,{path:A,content:f,type:"json"}),N},w=k=>{for(let[f,A]of Object.entries(k))u(f,A);return N},h=()=>i.size,C=()=>{i.clear()},S=k=>{let f=l(k);return i.has(f)},L=async k=>{try{let f=k.type==="json"?JSON.stringify(k.content,null,2)+`
|
|
10
|
+
`:k.content;if(await I(k.path))try{if(await er.readFile(k.path,"utf-8")===f)return{path:k.path,success:!0,skipped:!0}}catch{}if(n){let A=Ye.dirname(k.path);await m(A)}return await er.writeFile(k.path,f),o?.(k.path),{path:k.path,success:!0,skipped:!1}}catch(f){let A=f instanceof Error?f.message:String(f);return s?.(k.path,f instanceof Error?f:new Error(A)),{path:k.path,success:!1,error:A}}},N={add:u,addJson:a,addMany:w,pending:h,clear:C,flush:async()=>{let k=Date.now(),f=[],A=[],ne=[],ee=Array.from(i.values());i.clear();for(let oe=0;oe<ee.length;oe+=t){let Je=ee.slice(oe,oe+t),He=await Promise.all(Je.map(L));for(let y of He)y.success?y.skipped?A.push(y.path):f.push(y.path):ne.push({path:y.path,error:y.error||"Unknown error"})}return{success:ne.length===0,written:f,skipped:A,failed:ne,duration:Date.now()-k}},has:S};return N},Wn=async(e,t={})=>{let r=Re(t);return r.addMany(e),r.flush()},Jn=async(e,t,r={})=>{let n=Re(r);for(let[o,s]of Object.entries(e))n.add(o,s);for(let[o,s]of Object.entries(t))n.addJson(o,s);return n.flush()},ae=null,et=e=>(ae||(ae=Re(e)),ae),tr=()=>{ae=null},Hn=(e,t)=>{et().add(e,t)},qn=(e,t)=>{et().addJson(e,t)},Vn=async()=>{if(!ae)return{success:!0,written:[],skipped:[],failed:[],duration:0};let e=await ae.flush();return tr(),e}});import tt from"node:fs/promises";import Kn from"node:os";import nr from"node:path";var rt,V,nt,Qn,Xn,Zn,Yn,eo,Ne=b(()=>{"use strict";E();rt=class{cache=new Map;defaultTTL=24*60*60*1e3;cacheDir=nr.join(Kn.homedir(),".nexo");cacheFile=nr.join(this.cacheDir,"cache.json");version="1.0.0";async load(){try{if(!await tt.access(this.cacheFile).then(()=>!0).catch(()=>!1))return;let r=await tt.readFile(this.cacheFile,"utf-8"),n=JSON.parse(r);if(n.version!==this.version)return;this.cache=new Map(Object.entries(n.entries))}catch{}}async save(){try{await m(this.cacheDir);let t=Date.now();for(let[n,o]of this.cache.entries())t-o.timestamp>this.defaultTTL&&this.cache.delete(n);let r={version:this.version,entries:Object.fromEntries(this.cache)};await tt.writeFile(this.cacheFile,JSON.stringify(r,null,2))}catch{}}async get(t,r,n){let o=this.cache.get(t),s=Date.now();if(o&&s-o.timestamp<(n??this.defaultTTL))return o.value;let i=await r();return this.cache.set(t,{value:i,timestamp:s}),i}getSync(t,r,n){let o=this.cache.get(t),s=Date.now();if(o&&s-o.timestamp<(n??this.defaultTTL))return o.value;let i=r();return this.cache.set(t,{value:i,timestamp:s}),i}has(t,r){let n=this.cache.get(t);return n?Date.now()-n.timestamp<(r??this.defaultTTL):!1}set(t,r){this.cache.set(t,{value:r,timestamp:Date.now()})}invalidate(t){this.cache.delete(t)}invalidatePattern(t){let r=new RegExp(t);for(let n of this.cache.keys())r.test(n)&&this.cache.delete(n)}clear(){this.cache.clear()}stats(){return{size:this.cache.size,keys:[...this.cache.keys()]}}},V=new rt,nt=(e,t,r)=>V.get(e,t,r),Qn=(e,t,r)=>V.getSync(e,t,r),Xn=e=>{V.invalidate(e)},Zn=()=>{V.clear()},Yn=(e,t)=>{let r=t??((...n)=>JSON.stringify(n));return async(...n)=>{let o=`memoize:${e.name}:${r(...n)}`;return V.get(o,()=>e(...n))}},eo=(e,t)=>{let r=t??((...n)=>JSON.stringify(n));return(...n)=>{let o=`memoize:${e.name}:${r(...n)}`;return V.getSync(o,()=>e(...n))}}});import sr from"node:fs/promises";import or from"node:path";var ot,ge,ir=b(()=>{"use strict";ot=async e=>{try{return(await sr.readdir(e)).filter(n=>n!==".git"&&n!==".DS_Store"&&n!=="Thumbs.db").length===0}catch{return!0}},ge=async e=>{try{let t=or.join(e,"package.json"),r=await sr.readFile(t,"utf-8"),n=JSON.parse(r),o={...n.dependencies,...n.devDependencies},s={projectName:n.name||or.basename(e)};return o.next?s.framework="next":o.react&&(s.framework="react"),o.typescript?s.variant="ts":s.variant="js",o.tailwindcss?s.styling="tailwind":o.sass&&(s.styling="sass"),s}catch{return null}}});var X,ar,cr=b(()=>{"use strict";X=e=>{let t=[],r=e.variant.includes("ts"),n=r?"tsx":"jsx",o=r?"ts":"js";t.push({name:"package.json"}),t.push({name:"vite.config."+o}),t.push({name:"index.html"}),t.push({name:"README.md"}),r&&t.push({name:"tsconfig.json"}),e.styling==="tailwind"&&t.push({name:"tailwind.config.js"}),e.ui==="shadcn"&&t.push({name:"components.json"});let s=[{name:`main.${n}`},{name:`App.${n}`},{name:"index.css"}];return e.state==="redux"&&s.push({name:"store/",children:[{name:"store."+o},{name:"hooks."+o},{name:"counterSlice."+o}]}),e.ui==="shadcn"&&s.push({name:"lib/",children:[{name:"utils."+o}]}),e.structure==="fsd"?s.push({name:"app/",children:[]},{name:"pages/",children:[]},{name:"widgets/",children:[]},{name:"features/",children:[]},{name:"entities/",children:[]},{name:"shared/",children:[]}):e.structure==="clean"?s.push({name:"domain/",children:[]},{name:"application/",children:[]},{name:"infrastructure/",children:[]},{name:"presentation/",children:[]}):s.push({name:"components/",children:[]},{name:"hooks/",children:[]},{name:"utils/",children:[]},{name:"assets/",children:[]}),t.push({name:"src/",children:s}),ar(t)},ar=(e,t="")=>{let r="";return e.forEach((n,o)=>{let s=o===e.length-1,i=s?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",l=s?" ":"\u2502 ";r+=`${t}${i}${n.name}
|
|
11
|
+
`,n.children&&(r+=ar(n.children,t+l))}),r}});import fe from"node:path";var st,to,lr,pr,ro,ur,no,oo,so,io,ao,co,lo,po,uo,mr=b(()=>{"use strict";E();st=async(e,t)=>{let r=await x(e);if(t.dependencies)for(let[n,o]of Object.entries(t.dependencies))d(r,n,o,!1);if(t.devDependencies)for(let[n,o]of Object.entries(t.devDependencies))d(r,n,o,!0);return await P(e,r),r},to=async(e,t,r)=>t?st(e,r):null,lr=async(e,t)=>{await Promise.all(t.map(async r=>{let n=fe.join(e.projectPath,r.path);await m(fe.dirname(n)),await p(n,r.content)}))},pr=async(e,t)=>{let r=Object.entries(t).map(([n,o])=>({path:n,content:o}));await lr(e,r)},ro=async(e,t,r)=>{let n=fe.join(e.projectPath,t),{pathExists:o}=await Promise.resolve().then(()=>(E(),Nt));return await o(n)?!1:(await m(fe.dirname(n)),await p(n,r),!0)},ur=async(e,t)=>{await Promise.all(t.map(r=>m(fe.join(e.projectPath,r))))},no=(e,t)=>{let r=e;for(let[n,o]of Object.entries(t))r=r.replace(new RegExp(`\\{\\{${n}\\}\\}`,"g"),o);return r},oo=e=>e.map(({from:t,imports:r,default:n})=>{let o=[];return n&&o.push(n),Array.isArray(r)&&r.length>0?o.push(`{ ${r.join(", ")} }`):typeof r=="string"&&r&&o.push(`{ ${r} }`),`import ${o.join(", ")} from '${t}'`}).join(`
|
|
12
|
+
`),so=(e,t)=>e.selections[t]==="none",io=e=>{let t=e.selections.variant.startsWith("ts");return{ts:t,ext:t?"tsx":"jsx",configExt:t?"ts":"js"}},ao=e=>async t=>{let r=t.selections[e.selectionKey];if(r==="none")return;let n=e.configs[r];if(n){if((n.dependencies||n.devDependencies)&&await st(t,{dependencies:n.dependencies,devDependencies:n.devDependencies}),n.directories&&await ur(t,n.directories),n.files){let o=n.files(t);await pr(t,o)}n.setup&&await n.setup(t)}},co=async(e,t)=>e?t():null,lo=(e,t,r)=>e?t:r,po=(...e)=>e.filter(t=>t!==!1&&t!==null&&t!==void 0),uo=(...e)=>{let t={};for(let r of e)if(r&&Array.isArray(r)){let[n,o]=r;o!=null&&(t[n]=o)}return t}});var dr={};T(dr,{PackageManager:()=>Ae});import{exec as mo}from"node:child_process";import go from"node:path";import{promisify as fo}from"node:util";var ho,Ae,it=b(()=>{"use strict";Ne();E();ho=fo(mo),Ae=class{projectPath;pkg=null;dependencies=new Map;devDependencies=new Map;scripts=new Map;constructor(t){this.projectPath=t}async load(t){this.pkg=await x(t),this.pkg.dependencies&&Object.entries(this.pkg.dependencies).forEach(([r,n])=>this.dependencies.set(r,n)),this.pkg.devDependencies&&Object.entries(this.pkg.devDependencies).forEach(([r,n])=>this.devDependencies.set(r,n)),this.pkg.scripts&&Object.entries(this.pkg.scripts).forEach(([r,n])=>this.scripts.set(r,n))}add(t,r,n=!1){n?this.devDependencies.set(t,r):this.dependencies.set(t,r)}addScript(t,r){this.scripts.set(t,r)}set(t,r){this.pkg&&(this.pkg[t]=r)}async resolveLatestVersions(){if(process.env.NODE_ENV==="test")return;let t=[...this.dependencies.keys()],r=[...this.devDependencies.keys()],n=[...new Set([...t,...r])];if(n.length!==0)try{(await Promise.all(n.map(async s=>{try{let i=await nt(`npm:version:${s}`,async()=>{let{stdout:l}=await ho(`npm view ${s} version`);return l.trim()},432e5);return{name:s,version:i}}catch{return null}}))).forEach(s=>{s&&(this.dependencies.has(s.name)&&this.dependencies.set(s.name,`^${s.version}`),this.devDependencies.has(s.name)&&this.devDependencies.set(s.name,`^${s.version}`))})}catch{}}async save(){if(!this.pkg)throw new Error("Package.json not loaded. Call load() first.");let t=r=>Object.fromEntries([...r.entries()].sort((n,o)=>n[0].localeCompare(o[0])));this.pkg.dependencies=t(this.dependencies),this.pkg.devDependencies=t(this.devDependencies),this.pkg.scripts=t(this.scripts),await B(go.join(this.projectPath,"package.json"),this.pkg)}}});import _ from"picocolors";var yo,vo,wo,bo,gr=b(()=>{"use strict";yo=e=>{let{total:t,width:r=30,showPercentage:n=!0,showStepCount:o=!0,completeChar:s="\u2588",incompleteChar:i="\u2591",filledColor:l=_.cyan,emptyColor:u=_.dim}=e,a=0,w="",h=()=>{let C=Math.round(a/t*100),S=Math.round(a/t*r),L=r-S,N=`\r${l(s.repeat(S))+u(i.repeat(L))}`;n&&(N+=` ${C.toString().padStart(3)}%`),o&&(N+=` (${a}/${t})`),w&&(N+=` ${_.dim(w)}`),N+="\x1B[K",process.stdout.write(N)};return{increment:C=>{a=Math.min(a+1,t),w=C||"",h()},update:(C,S)=>{a=Math.min(Math.max(0,C),t),w=S||"",h()},complete:C=>{a=t,w="",h(),console.log(),C&&console.log(_.green(`\u2713 ${C}`))},fail:C=>{w="",console.log(),C&&console.log(_.red(`\u2717 ${C}`))},getPercentage:()=>Math.round(a/t*100)}},vo=e=>{let{total:t,showStepNumbers:r=!0}=e,n=0,o="",s=()=>r?`[${n}/${t}]`:"";return{start:i=>{n++,o=i,process.stdout.write(`${_.cyan("\u25CF")} ${s()} ${i}...`)},succeed:i=>{process.stdout.write(`\r${_.green("\u2713")} ${s()} ${i||o}\x1B[K
|
|
13
|
+
`)},fail:i=>{process.stdout.write(`\r${_.red("\u2717")} ${s()} ${i||o}\x1B[K
|
|
14
|
+
`)},skip:i=>{let l=i?` (${i})`:"";process.stdout.write(`\r${_.yellow("\u25CB")} ${s()} ${o}${_.dim(l)}\x1B[K
|
|
15
|
+
`)},complete:()=>{console.log(),console.log(_.green(`\u2713 All ${t} steps completed successfully!`))}}},wo=()=>({log:e=>{console.log(` ${e}`)},success:e=>{console.log(`${_.green("\u2713")} ${e}`)},error:e=>{console.log(`${_.red("\u2717")} ${e}`)},warn:e=>{console.log(`${_.yellow("\u26A0")} ${e}`)},info:e=>{console.log(`${_.blue("\u2139")} ${e}`)}}),bo=()=>{let e=Date.now(),t=null;return{elapsed:()=>(t||Date.now())-e,format:()=>{let r=(t||Date.now())-e;return r<1e3?`${r}ms`:`${(r/1e3).toFixed(2)}s`},stop:()=>{t=Date.now();let r=t-e;return r<1e3?`${r}ms`:`${(r/1e3).toFixed(2)}s`}}}});import at from"picocolors";var fr,Co,xo,ct,te,hr=b(()=>{"use strict";fr=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],Co=at.green("\u2714"),xo=at.red("\u2716"),ct=()=>{let e=null,t=0,r="",n=()=>{process.stdout.write("\r\x1B[K")},o=()=>{n(),process.stdout.write(`${at.cyan(fr[t])} ${r}`),t=(t+1)%fr.length};return{start:s=>{r=s,t=0,e&&clearInterval(e),e=setInterval(o,80),o()},succeed:s=>{e&&(clearInterval(e),e=null),n(),console.log(`${Co} ${s||r}`)},fail:s=>{e&&(clearInterval(e),e=null),n(),console.log(`${xo} ${s||r}`)},stop:()=>{e&&(clearInterval(e),e=null),n()}}},te=e=>{let t=ct();return t.start(e),t}});var lt={};T(lt,{PackageManager:()=>Ae,addDependencies:()=>st,addDependenciesIf:()=>to,addDependency:()=>d,addScript:()=>Q,buildArray:()=>po,buildObject:()=>uo,cache:()=>V,clearCache:()=>Zn,copy:()=>Rt,createBatchWriter:()=>Re,createDirectories:()=>ur,createFileIfNotExists:()=>ro,createFiles:()=>lr,createFilesFromRecord:()=>pr,createProgressBar:()=>yo,createProjectDir:()=>Se,createSimpleProgress:()=>wo,createSpinner:()=>ct,createStandardConfigurator:()=>ao,createStepProgress:()=>vo,createTimer:()=>bo,detectProjectConfig:()=>ge,doIf:()=>co,ensureDir:()=>m,flushGlobalWriter:()=>Vn,generateFileTree:()=>X,generateImports:()=>oo,getCached:()=>nt,getCachedSync:()=>Qn,getExtension:()=>io,getGlobalWriter:()=>et,getPackageJson:()=>x,invalidateCache:()=>Xn,isDirEmpty:()=>ot,memoize:()=>Yn,memoizeSync:()=>eo,pathExists:()=>I,queueFile:()=>Hn,queueJson:()=>qn,readJson:()=>Ve,remove:()=>Ft,removeFile:()=>ke,resetGlobalWriter:()=>tr,savePackageJson:()=>P,selectIf:()=>lo,skipIfNone:()=>so,spinner:()=>te,template:()=>no,writeAllParallel:()=>Jn,writeFile:()=>p,writeFilesParallel:()=>Wn,writeJson:()=>B});var $=b(()=>{"use strict";rr();Ne();ir();cr();E();mr();it();gr();hr()});var yr={};T(yr,{frameworkConfigurator:()=>ko});import De from"node:path";var ko,vr=b(()=>{"use strict";$();ko=async e=>{let{variant:t}=e.selections,r=t.startsWith("ts"),n=t.includes("swc"),o=r?"ts":"js";if(e.pkg)e.pkg.add("react","^19.0.0"),e.pkg.add("react-dom","^19.0.0"),e.pkg.add("vite","^6.0.0",!0),n?e.pkg.add("@vitejs/plugin-react-swc","^3.7.0",!0):e.pkg.add("@vitejs/plugin-react","^4.3.0",!0),e.pkg.addScript("dev","vite"),e.pkg.addScript("build","vite build"),e.pkg.addScript("preview","vite preview"),e.pkg.set("type","module");else{let a=await x(e);d(a,"react","^19.0.0"),d(a,"react-dom","^19.0.0"),d(a,"vite","^6.0.0",!0),n?d(a,"@vitejs/plugin-react-swc","^3.7.0",!0):d(a,"@vitejs/plugin-react","^4.3.0",!0),Q(a,"dev","vite"),Q(a,"build","vite build"),Q(a,"build","vite build"),Q(a,"preview","vite preview"),a.type="module",await P(e,a)}let i=`${n?"import react from '@vitejs/plugin-react-swc'":"import react from '@vitejs/plugin-react'"}
|
|
16
|
+
import { defineConfig } from 'vite'
|
|
17
|
+
|
|
18
|
+
export default defineConfig({
|
|
19
|
+
plugins: [react()],
|
|
20
|
+
})
|
|
21
|
+
`;await p(De.join(e.projectPath,`vite.config.${o}`),i);let l=`<!DOCTYPE html>
|
|
22
|
+
<html lang="en">
|
|
23
|
+
<head>
|
|
24
|
+
<meta charset="UTF-8" />
|
|
25
|
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
26
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
27
|
+
<title>${e.selections.projectName}</title>
|
|
28
|
+
</head>
|
|
29
|
+
<body>
|
|
30
|
+
<div id="root"></div>
|
|
31
|
+
<script type="module" src="/src/main.${r?"tsx":"jsx"}"></script>
|
|
32
|
+
</body>
|
|
33
|
+
</html>
|
|
34
|
+
`;await p(De.join(e.projectPath,"index.html"),l),await m(De.join(e.projectPath,"public")),await p(De.join(e.projectPath,"public","vite.svg"),'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFBD4F"></stop><stop offset="100%" stop-color="#FF980E"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>')}});var wr={};T(wr,{variantConfigurator:()=>So});var So,br=b(()=>{"use strict";$();So=async e=>{let{variant:t,framework:r}=e.selections;if(r!=="react")return;let n=await x(e),o=t.includes("compiler"),s=t.includes("swc");o&&(d(n,"babel-plugin-react-compiler","^19.0.0-beta-e552027-20250112",!0),d(n,"eslint-plugin-react-compiler","^19.0.0-beta-e552027-20250112",!0),d(n,"@babel/core","^7.26.0",!0),d(n,"@babel/preset-react","^7.26.0",!0)),s&&d(n,"@vitejs/plugin-react-swc","^3.7.0",!0),await P(e,n)}});var Cr={};T(Cr,{languageConfigurator:()=>Po});import he from"node:path";var Po,xr=b(()=>{"use strict";$();Po=async e=>{let{variant:t,framework:r}=e.selections,n=t.startsWith("ts"),o=await x(e);if(n){d(o,"typescript","^5.7.0",!0),r==="react"&&(d(o,"@types/react","^19.0.0",!0),d(o,"@types/react-dom","^19.0.0",!0));let l={compilerOptions:{target:"ES2022",useDefineForClassFields:!0,lib:["ES2022","DOM","DOM.Iterable"],module:"ESNext",skipLibCheck:!0,moduleResolution:"bundler",allowImportingTsExtensions:!0,resolveJsonModule:!0,isolatedModules:!0,noEmit:!0,jsx:r==="react"?"react-jsx":"preserve",strict:!0,noUnusedLocals:!0,noUnusedParameters:!0,noFallthroughCasesInSwitch:!0,baseUrl:".",paths:{"@/*":["./src/*"]}},include:["src"],references:[{path:"./tsconfig.node.json"}]};await B(he.join(e.projectPath,"tsconfig.json"),l);let u={compilerOptions:{composite:!0,skipLibCheck:!0,module:"ESNext",moduleResolution:"bundler",allowSyntheticDefaultImports:!0,strict:!0},include:["vite.config.ts"]};await B(he.join(e.projectPath,"tsconfig.node.json"),u)}Q(o,"build",n?"tsc && vite build":"vite build"),await P(e,o);let s=`import js from '@eslint/js';
|
|
35
|
+
import globals from 'globals';
|
|
36
|
+
import reactHooks from 'eslint-plugin-react-hooks';
|
|
37
|
+
import reactRefresh from 'eslint-plugin-react-refresh';
|
|
38
|
+
import tseslint from 'typescript-eslint';
|
|
39
|
+
|
|
40
|
+
export default tseslint.config(
|
|
41
|
+
{ ignores: ['dist', 'node_modules', 'public', '.nexo'] },
|
|
42
|
+
{
|
|
43
|
+
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
|
44
|
+
files: ['**/*.{ts,tsx${n?"":",js,jsx"}}'],
|
|
45
|
+
languageOptions: {
|
|
46
|
+
ecmaVersion: 2020,
|
|
47
|
+
globals: globals.browser,
|
|
48
|
+
${n?`parserOptions: {
|
|
49
|
+
projectService: true,
|
|
50
|
+
tsconfigRootDir: import.meta.dirname,
|
|
51
|
+
},`:""}
|
|
52
|
+
},
|
|
53
|
+
plugins: {
|
|
54
|
+
'react-hooks': reactHooks,
|
|
55
|
+
'react-refresh': reactRefresh,
|
|
56
|
+
},
|
|
57
|
+
rules: {
|
|
58
|
+
...reactHooks.configs.recommended.rules,
|
|
59
|
+
'react-refresh/only-export-components': [
|
|
60
|
+
'warn',
|
|
61
|
+
{ allowConstantExport: true },
|
|
62
|
+
],
|
|
63
|
+
${n?"":"'@typescript-eslint/no-unused-vars': 'off',"}
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
);
|
|
67
|
+
`;await p(he.join(e.projectPath,"eslint.config.js"),s),d(o,"eslint","^9.15.0",!0),d(o,"eslint-plugin-react-hooks","^5.0.0",!0),d(o,"eslint-plugin-react-refresh","^0.4.14",!0),d(o,"globals","^15.12.0",!0),d(o,"typescript-eslint","^8.15.0",!0),d(o,"@eslint/js","^9.15.0",!0),await m(he.join(e.projectPath,".vscode")),await B(he.join(e.projectPath,".vscode","settings.json"),{"json.schemas":[],"typescript.tsdk":"node_modules/typescript/lib"})}});var kr={};T(kr,{stylingConfigurator:()=>jo});import W from"node:path";var jo,Sr=b(()=>{"use strict";$();jo=async e=>{let{variant:t}=e.selections,n=t.startsWith("ts")?"ts":"js";switch(e.selections.styling){case"tailwind":if(e.pkg)e.pkg.add("tailwindcss","^4.0.0",!0),e.pkg.add("@tailwindcss/vite","^4.0.0",!0);else{let l=await x(e);d(l,"tailwindcss","^4.0.0",!0),d(l,"@tailwindcss/vite","^4.0.0",!0),await P(e,l)}let s=`${t.includes("swc")?"import react from '@vitejs/plugin-react-swc'":"import react from '@vitejs/plugin-react'"}
|
|
68
|
+
import { defineConfig } from 'vite'
|
|
69
|
+
import tailwindcss from '@tailwindcss/vite'
|
|
70
|
+
|
|
71
|
+
export default defineConfig({
|
|
72
|
+
plugins: [
|
|
73
|
+
react(),
|
|
74
|
+
tailwindcss(),
|
|
75
|
+
],
|
|
76
|
+
})
|
|
77
|
+
`;await p(W.join(e.projectPath,`vite.config.${n}`),s);let i='@import "tailwindcss";';await m(W.join(e.projectPath,"src")),await p(W.join(e.projectPath,"src","index.css"),i);break;case"css-modules":await m(W.join(e.projectPath,"src")),await p(W.join(e.projectPath,"src","index.css"),`/* CSS Modules - import styles from './Component.module.css' */
|
|
78
|
+
:root {
|
|
79
|
+
font-family: system-ui, sans-serif;
|
|
80
|
+
}
|
|
81
|
+
`);break;case"plain-css":await m(W.join(e.projectPath,"src")),await p(W.join(e.projectPath,"src","index.css"),`/* Plain CSS */
|
|
82
|
+
* {
|
|
83
|
+
margin: 0;
|
|
84
|
+
padding: 0;
|
|
85
|
+
box-sizing: border-box;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
:root {
|
|
89
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
90
|
+
line-height: 1.5;
|
|
91
|
+
color: #213547;
|
|
92
|
+
background-color: #ffffff;
|
|
93
|
+
}
|
|
94
|
+
`);break;case"sass":if(e.pkg)e.pkg.add("sass","^1.77.0",!0);else{let l=await x(e);d(l,"sass","^1.77.0",!0),await P(e,l)}await m(W.join(e.projectPath,"src")),await m(W.join(e.projectPath,"src","styles")),await p(W.join(e.projectPath,"src","index.scss"),`// Import variables and mixins
|
|
95
|
+
@import './styles/variables';
|
|
96
|
+
@import './styles/mixins';
|
|
97
|
+
|
|
98
|
+
* {
|
|
99
|
+
margin: 0;
|
|
100
|
+
padding: 0;
|
|
101
|
+
box-sizing: border-box;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
:root {
|
|
105
|
+
font-family: $font-family;
|
|
106
|
+
line-height: 1.5;
|
|
107
|
+
}
|
|
108
|
+
`),await p(W.join(e.projectPath,"src","styles","_variables.scss"),`// Colors
|
|
109
|
+
$primary: #646cff;
|
|
110
|
+
$secondary: #535bf2;
|
|
111
|
+
$background: #ffffff;
|
|
112
|
+
$text: #213547;
|
|
113
|
+
|
|
114
|
+
// Typography
|
|
115
|
+
$font-family: system-ui, -apple-system, sans-serif;
|
|
116
|
+
$font-size-base: 16px;
|
|
117
|
+
|
|
118
|
+
// Spacing
|
|
119
|
+
$spacing-unit: 8px;
|
|
120
|
+
`),await p(W.join(e.projectPath,"src","styles","_mixins.scss"),`// Responsive breakpoints
|
|
121
|
+
@mixin mobile {
|
|
122
|
+
@media (max-width: 768px) {
|
|
123
|
+
@content;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@mixin tablet {
|
|
128
|
+
@media (max-width: 1024px) {
|
|
129
|
+
@content;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Flexbox helpers
|
|
134
|
+
@mixin flex-center {
|
|
135
|
+
display: flex;
|
|
136
|
+
align-items: center;
|
|
137
|
+
justify-content: center;
|
|
138
|
+
}
|
|
139
|
+
`);break;default:break}}});var Pr={};T(Pr,{uiConfigurator:()=>Io});import{appendFile as $o}from"node:fs/promises";import ce from"node:path";var To,Io,jr=b(()=>{"use strict";$();To={shadcn:{"@radix-ui/react-slot":"^1.1.0","class-variance-authority":"^0.7.1",clsx:"^2.1.1","tailwind-merge":"^2.6.0"},radix:{"@radix-ui/react-dialog":"^1.1.0","@radix-ui/react-dropdown-menu":"^2.1.0","@radix-ui/react-slot":"^1.1.0"},mantine:{"@mantine/core":"^7.15.0","@mantine/hooks":"^7.15.0"},heroui:{"@heroui/react":"^2.7.0","framer-motion":"^12.0.0"},mui:{"@mui/material":"^7.3.7","@emotion/react":"^11.14.0","@emotion/styled":"^11.14.0"},antd:{antd:"^5.23.0"},chakra:{"@chakra-ui/react":"^3.3.0","@emotion/react":"^11.14.0"},"styled-components":{"styled-components":"^6.1.14"}},Io=async e=>{if(e.selections.ui==="none")return;let t=To[e.selections.ui];if(t){if(e.pkg)for(let[r,n]of Object.entries(t))e.pkg.add(r,n);else{let{addDependency:r,getPackageJson:n,savePackageJson:o}=await Promise.resolve().then(()=>($(),lt)),s=await n(e);for(let[i,l]of Object.entries(t))r(s,i,l);await o(e,s)}if(e.selections.ui==="heroui"){let n=e.selections.variant.startsWith("ts")?"ts":"js";await p(ce.join(e.projectPath,`src/hero.${n}`),`import { heroui } from "@heroui/react";
|
|
140
|
+
|
|
141
|
+
export default heroui();`)}if(e.selections.ui==="shadcn"){let r=e.selections.variant.startsWith("ts"),n=r?"ts":"js";await m(ce.join(e.projectPath,"src/lib")),await p(ce.join(e.projectPath,"src/lib",`utils.${n}`),`import { clsx, type ClassValue } from "clsx"
|
|
142
|
+
import { twMerge } from "tailwind-merge"
|
|
143
|
+
|
|
144
|
+
export function cn(...inputs: ClassValue[]) {
|
|
145
|
+
return twMerge(clsx(inputs))
|
|
146
|
+
}
|
|
147
|
+
`);let s={$schema:"https://ui.shadcn.com/schema.json",style:"new-york",rsc:!1,tsx:r,tailwind:{config:"tailwind.config.js",css:"src/index.css",baseColor:"slate",cssVariables:!0,prefix:""},aliases:{components:"@/components",utils:"@/lib/utils"}};await p(ce.join(e.projectPath,"components.json"),JSON.stringify(s,null,2)),await $o(ce.join(e.projectPath,"src/index.css"),`
|
|
148
|
+
@layer base {
|
|
149
|
+
:root {
|
|
150
|
+
--background: 0 0% 100%;
|
|
151
|
+
--foreground: 222.2 84% 4.9%;
|
|
152
|
+
--card: 0 0% 100%;
|
|
153
|
+
--card-foreground: 222.2 84% 4.9%;
|
|
154
|
+
--popover: 0 0% 100%;
|
|
155
|
+
--popover-foreground: 222.2 84% 4.9%;
|
|
156
|
+
--primary: 222.2 47.4% 11.2%;
|
|
157
|
+
--primary-foreground: 210 40% 98%;
|
|
158
|
+
--secondary: 210 40% 96.1%;
|
|
159
|
+
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
160
|
+
--muted: 210 40% 96.1%;
|
|
161
|
+
--muted-foreground: 215.4 16.3% 46.9%;
|
|
162
|
+
--accent: 210 40% 96.1%;
|
|
163
|
+
--accent-foreground: 222.2 47.4% 11.2%;
|
|
164
|
+
--destructive: 0 84.2% 60.2%;
|
|
165
|
+
--destructive-foreground: 210 40% 98%;
|
|
166
|
+
--border: 214.3 31.8% 91.4%;
|
|
167
|
+
--input: 214.3 31.8% 91.4%;
|
|
168
|
+
--ring: 222.2 84% 4.9%;
|
|
169
|
+
--radius: 0.5rem;
|
|
170
|
+
--chart-1: 12 76% 61%;
|
|
171
|
+
--chart-2: 173 58% 39%;
|
|
172
|
+
--chart-3: 197 37% 24%;
|
|
173
|
+
--chart-4: 43 74% 66%;
|
|
174
|
+
--chart-5: 27 87% 67%;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.dark {
|
|
178
|
+
--background: 222.2 84% 4.9%;
|
|
179
|
+
--foreground: 210 40% 98%;
|
|
180
|
+
--card: 222.2 84% 4.9%;
|
|
181
|
+
--card-foreground: 210 40% 98%;
|
|
182
|
+
--popover: 222.2 84% 4.9%;
|
|
183
|
+
--popover-foreground: 210 40% 98%;
|
|
184
|
+
--primary: 210 40% 98%;
|
|
185
|
+
--primary-foreground: 222.2 47.4% 11.2%;
|
|
186
|
+
--secondary: 217.2 32.6% 17.5%;
|
|
187
|
+
--secondary-foreground: 210 40% 98%;
|
|
188
|
+
--muted: 217.2 32.6% 17.5%;
|
|
189
|
+
--muted-foreground: 215 20.2% 65.1%;
|
|
190
|
+
--accent: 217.2 32.6% 17.5%;
|
|
191
|
+
--accent-foreground: 210 40% 98%;
|
|
192
|
+
--destructive: 0 62.8% 30.6%;
|
|
193
|
+
--destructive-foreground: 210 40% 98%;
|
|
194
|
+
--border: 217.2 32.6% 17.5%;
|
|
195
|
+
--input: 217.2 32.6% 17.5%;
|
|
196
|
+
--ring: 212.7 26.8% 83.9%;
|
|
197
|
+
--chart-1: 220 70% 50%;
|
|
198
|
+
--chart-2: 160 60% 45%;
|
|
199
|
+
--chart-3: 30 80% 55%;
|
|
200
|
+
--chart-4: 280 65% 60%;
|
|
201
|
+
--chart-5: 340 75% 55%;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
@layer base {
|
|
206
|
+
* {
|
|
207
|
+
border-color: hsl(var(--border));
|
|
208
|
+
}
|
|
209
|
+
body {
|
|
210
|
+
background-color: hsl(var(--background));
|
|
211
|
+
color: hsl(var(--foreground));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
`)}if(e.selections.ui==="heroui"){let o=`
|
|
215
|
+
@import "tailwindcss";
|
|
216
|
+
@plugin "./hero.${e.selections.variant.startsWith("ts")?"ts":"js"}";
|
|
217
|
+
@source "../node_modules/@heroui/theme/dist/**/*.{js,ts,jsx,tsx}";
|
|
218
|
+
@custom-variant dark (&:is(.dark *));
|
|
219
|
+
`;await p(ce.join(e.projectPath,"src/index.css"),o)}}}});var Z,ye=b(()=>{"use strict";$();Z=(e,t,r={})=>async n=>{let o=n.selections[e];if(!o||o==="none"||r.skipIf?.(n))return;let s=t[o];if(s){if(n.pkg)for(let[i,l]of Object.entries(s))n.pkg.add(i,l);else{let i=await x(n);for(let[l,u]of Object.entries(s))d(i,l,u);await P(n,i)}r.afterInstall&&await r.afterInstall(n,o)}}});var $r={};T($r,{iconsConfigurator:()=>Ro});var Fo,Ro,Tr=b(()=>{"use strict";ye();Fo={lucide:{"lucide-react":"^0.474.0"},"react-icons":{"react-icons":"^5.5.0"},iconify:{"@iconify/react":"^6.0.2"},heroicons:{"@heroicons/react":"^2.2.0"},fontawesome:{"@fortawesome/fontawesome-svg-core":"^6.7.0","@fortawesome/free-solid-svg-icons":"^6.7.0","@fortawesome/react-fontawesome":"^0.2.2"}},Ro=Z("icons",Fo)});var Ir={};T(Ir,{formsConfigurator:()=>Ao});var No,Ao,Fr=b(()=>{"use strict";ye();No={"rhf-zod":{"react-hook-form":"^7.54.0",zod:"^3.24.0","@hookform/resolvers":"^3.9.0"},"rhf-yup":{"react-hook-form":"^7.54.0",yup:"^1.6.0","@hookform/resolvers":"^3.9.0"},"formik-zod":{formik:"^2.4.6",zod:"^3.24.0","zod-formik-adapter":"^1.3.0"},"formik-yup":{formik:"^2.4.6",yup:"^1.6.0"},"tanstack-form":{"@tanstack/react-form":"^1.27.7",zod:"^3.24.0"}},Ao=Z("forms",No)});var Rr={};T(Rr,{stateConfigurator:()=>Eo});var Do,Eo,Nr=b(()=>{"use strict";$();Do={zustand:{zustand:"^5.0.0"},redux:{"@reduxjs/toolkit":"^2.5.0","react-redux":"^9.2.0"},jotai:{jotai:"^2.11.0"}},Eo=async e=>{if(e.selections.state==="none")return;let t=Do[e.selections.state];if(t&&t){if(e.pkg)for(let[r,n]of Object.entries(t))e.pkg.add(r,n);else{let r=await x(e);for(let[n,o]of Object.entries(t))d(r,n,o);await P(e,r)}if(e.selections.state==="redux"){let r=e.selections.variant.startsWith("ts"),n=r?"ts":"js",{writeFile:o,ensureDir:s}=await Promise.resolve().then(()=>($(),lt)),i=await import("node:path");await s(i.join(e.projectPath,"src/store"));let l=`import { configureStore } from '@reduxjs/toolkit'
|
|
220
|
+
import counterReducer from './counterSlice'
|
|
221
|
+
|
|
222
|
+
export const store = configureStore({
|
|
223
|
+
reducer: {
|
|
224
|
+
counter: counterReducer,
|
|
225
|
+
},
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
${r?`export type RootState = ReturnType<typeof store.getState>
|
|
229
|
+
export type AppDispatch = typeof store.dispatch`:""}
|
|
230
|
+
`;await o(i.join(e.projectPath,"src/store",`store.${n}`),l);let u=`import { createSlice } from '@reduxjs/toolkit'
|
|
231
|
+
${r?`import type { PayloadAction } from '@reduxjs/toolkit'
|
|
232
|
+
|
|
233
|
+
export interface CounterState {
|
|
234
|
+
value: number
|
|
235
|
+
}`:""}
|
|
236
|
+
|
|
237
|
+
const initialState${r?": CounterState":""} = {
|
|
238
|
+
value: 0,
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export const counterSlice = createSlice({
|
|
242
|
+
name: 'counter',
|
|
243
|
+
initialState,
|
|
244
|
+
reducers: {
|
|
245
|
+
increment: (state) => {
|
|
246
|
+
state.value += 1
|
|
247
|
+
},
|
|
248
|
+
decrement: (state) => {
|
|
249
|
+
state.value -= 1
|
|
250
|
+
},
|
|
251
|
+
incrementByAmount: (state, action${r?": PayloadAction<number>":""}) => {
|
|
252
|
+
state.value += action.payload
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
export const { increment, decrement, incrementByAmount } = counterSlice.actions
|
|
258
|
+
|
|
259
|
+
export default counterSlice.reducer
|
|
260
|
+
`;await o(i.join(e.projectPath,"src/store",`counterSlice.${n}`),u);let a=r?`import { useDispatch, useSelector } from 'react-redux'
|
|
261
|
+
import type { TypedUseSelectorHook } from 'react-redux'
|
|
262
|
+
import type { RootState, AppDispatch } from './store'
|
|
263
|
+
|
|
264
|
+
export const useAppDispatch: () => AppDispatch = useDispatch
|
|
265
|
+
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
|
|
266
|
+
`:`import { useDispatch, useSelector } from 'react-redux'
|
|
267
|
+
|
|
268
|
+
export const useAppDispatch = useDispatch
|
|
269
|
+
export const useAppSelector = useSelector
|
|
270
|
+
`;await o(i.join(e.projectPath,"src/store",`hooks.${n}`),a)}}}});var Ar={};T(Ar,{routingConfigurator:()=>Uo});var Oo,Uo,Dr=b(()=>{"use strict";ye();Oo={"react-router":{"react-router-dom":"^7.1.0"},"tanstack-router":{"@tanstack/react-router":"^1.95.0","@tanstack/react-router-devtools":"^1.95.0"}},Uo=Z("routing",Oo,{skipIf:e=>e.selections.framework!=="react"})});var Er={};T(Er,{dataFetchingConfigurator:()=>_o});var _o,Or=b(()=>{"use strict";$();_o=async e=>{let{dataFetching:t,framework:r}=e.selections;if(!(!t||t==="none"||t==="fetch"))if(e.pkg)t==="tanstack-query"&&r==="react"?(e.pkg.add("@tanstack/react-query","^5.60.0"),e.pkg.add("@tanstack/react-query-devtools","^5.60.0")):t==="swr"?e.pkg.add("swr","^2.3.8"):t==="axios"&&e.pkg.add("axios","^1.7.0");else{let n=await x(e);switch(t){case"tanstack-query":r==="react"&&(d(n,"@tanstack/react-query","^5.60.0"),d(n,"@tanstack/react-query-devtools","^5.60.0"));break;case"swr":d(n,"swr","^2.3.8");break;case"axios":d(n,"axios","^1.7.0");break}await P(e,n)}}});var Ur={};T(Ur,{animationConfigurator:()=>zo});var Lo,zo,_r=b(()=>{"use strict";ye();Lo={"framer-motion":{"framer-motion":"^12.0.0"},gsap:{gsap:"^3.14.2","@gsap/react":"^2.1.2"},"react-spring":{"@react-spring/web":"^9.7.0"}},zo=Z("animation",Lo)});var Lr={};T(Lr,{structureConfigurator:()=>Bo});import Mo from"node:path";var Bo,zr=b(()=>{"use strict";$();Bo=async e=>{let t=[];switch(e.selections.structure){case"feature-based":t.push("src/app","src/features","src/shared/components","src/shared/hooks","src/shared/utils","src/shared/types");break;case"fsd":t.push("src/app","src/pages","src/widgets","src/features","src/entities","src/shared/api","src/shared/config","src/shared/lib","src/shared/ui");break;case"atomic":t.push("src/components/atoms","src/components/molecules","src/components/organisms","src/components/templates","src/hooks","src/utils");break;case"clean":t.push("src/domain/entities","src/domain/usecases","src/application/services","src/infrastructure/api","src/infrastructure/storage","src/presentation/components","src/presentation/pages","src/presentation/hooks");break;case"mvc":t.push("src/models","src/views/components","src/views/pages","src/controllers","src/services","src/utils");break;case"simple":default:t.push("src/components","src/hooks","src/utils","src/assets");break}for(let r of t){let n=Mo.join(e.projectPath,r);await m(n)}}});var Mr={};T(Mr,{i18nConfigurator:()=>Go});import le from"node:path";var Go,Br=b(()=>{"use strict";$();Go=async e=>{let{i18n:t,framework:r}=e.selections;if(!t||t==="none")return;let n=await x(e);switch(t){case"i18next":e.pkg?(e.pkg.add("i18next","^23.15.0"),r==="react"&&e.pkg.add("react-i18next","^15.0.0"),e.pkg.add("i18next-browser-languagedetector","^8.0.0")):(d(n,"i18next","^23.15.0"),r==="react"&&d(n,"react-i18next","^15.0.0"),d(n,"i18next-browser-languagedetector","^8.0.0"),await P(e,n));let o=`import i18n from 'i18next';
|
|
271
|
+
import { initReactI18next } from 'react-i18next';
|
|
272
|
+
import LanguageDetector from 'i18next-browser-languagedetector';
|
|
273
|
+
import en from './locales/en.json';
|
|
274
|
+
import ar from './locales/ar.json';
|
|
275
|
+
|
|
276
|
+
i18n
|
|
277
|
+
.use(LanguageDetector)
|
|
278
|
+
.use(initReactI18next)
|
|
279
|
+
.init({
|
|
280
|
+
resources: {
|
|
281
|
+
en: { translation: en },
|
|
282
|
+
ar: { translation: ar },
|
|
283
|
+
},
|
|
284
|
+
fallbackLng: 'en',
|
|
285
|
+
interpolation: {
|
|
286
|
+
escapeValue: false,
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
export default i18n;
|
|
291
|
+
`;await m(le.join(e.projectPath,"src/i18n")),await m(le.join(e.projectPath,"src/i18n/locales")),await p(le.join(e.projectPath,"src/i18n/index.ts"),o),await B(le.join(e.projectPath,"src/i18n/locales/en.json"),{welcome:"Welcome"}),await B(le.join(e.projectPath,"src/i18n/locales/ar.json"),{welcome:"\u0645\u0631\u062D\u0628\u0627\u064B"});break;case"lingui":e.pkg?(e.pkg.add("@lingui/core","^4.11.0"),e.pkg.add("@lingui/react","^4.11.0"),e.pkg.add("@lingui/cli","^4.11.0",!0),e.pkg.add("@lingui/macro","^4.11.0",!0)):(d(n,"@lingui/core","^4.11.0"),d(n,"@lingui/react","^4.11.0"),d(n,"@lingui/cli","^4.11.0",!0),d(n,"@lingui/macro","^4.11.0",!0),await P(e,n)),await p(le.join(e.projectPath,"lingui.config.js"),`module.exports = {
|
|
292
|
+
locales: ['en', 'ar'],
|
|
293
|
+
sourceLocale: 'en',
|
|
294
|
+
catalogs: [
|
|
295
|
+
{
|
|
296
|
+
path: 'src/locales/{locale}/messages',
|
|
297
|
+
include: ['src'],
|
|
298
|
+
},
|
|
299
|
+
],
|
|
300
|
+
format: 'po',
|
|
301
|
+
};
|
|
302
|
+
`);break}}});var Wr={};T(Wr,{authConfigurator:()=>Wo});import Gr from"node:path";var Wo,Jr=b(()=>{"use strict";$();Wo=async e=>{let{auth:t,variant:r}=e.selections;if(!t||t==="none")return;let o=r.startsWith("ts")?"ts":"js";switch(t){case"jwt":await m(Gr.join(e.projectPath,"src/lib/auth")),await p(Gr.join(e.projectPath,"src/lib/auth",`index.${o}`),`// JWT Authentication utilities
|
|
303
|
+
|
|
304
|
+
const TOKEN_KEY = 'auth_token';
|
|
305
|
+
// ... (rest of the content is unchanged, but avoiding repetition for tool call efficiency)
|
|
306
|
+
export const parseToken = (token: string): User | null => {
|
|
43
307
|
try {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const v = value || DEFAULT_PROJECT_NAME;
|
|
50
|
-
if (!/^[a-z0-9-_]+$/i.test(v)) {
|
|
51
|
-
return "Project name can only contain letters, numbers, hyphens, and underscores";
|
|
52
|
-
}
|
|
53
|
-
return void 0;
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
if (p.isCancel(projectName)) {
|
|
57
|
-
p.cancel("Operation cancelled.");
|
|
58
|
-
process.exit(0);
|
|
59
|
-
}
|
|
60
|
-
const answers = {
|
|
61
|
-
projectName
|
|
62
|
-
};
|
|
63
|
-
const projectPath = path.resolve(options.dir, projectName);
|
|
64
|
-
if (!await isDirEmpty(projectPath)) {
|
|
65
|
-
const detectedConfig = await detectProjectConfig(projectPath);
|
|
66
|
-
let detectedInfo = "";
|
|
67
|
-
if (detectedConfig) {
|
|
68
|
-
detectedInfo = `
|
|
69
|
-
${pc.bold("Previous Configuration Found:")}
|
|
70
|
-
${pc.dim("\u2022 Framework:")} ${detectedConfig.framework || "Unknown"}
|
|
71
|
-
${pc.dim("\u2022 Language:")} ${detectedConfig.variant === "ts" ? "TypeScript" : "JavaScript"}
|
|
72
|
-
${pc.dim("\u2022 Styling:")} ${detectedConfig.styling || "Unknown"}
|
|
73
|
-
`;
|
|
74
|
-
}
|
|
75
|
-
const action = await p.select({
|
|
76
|
-
message: `Folder "${projectName}" already exists and is not empty.${detectedInfo}`,
|
|
77
|
-
options: [
|
|
78
|
-
...detectedConfig ? [{
|
|
79
|
-
value: "continue",
|
|
80
|
-
label: "Continue with previous setup",
|
|
81
|
-
hint: "Uses detected configuration"
|
|
82
|
-
}] : [],
|
|
83
|
-
{
|
|
84
|
-
value: "overwrite",
|
|
85
|
-
label: "Start fresh",
|
|
86
|
-
hint: "\u26A0\uFE0F Clears directory and starts new setup"
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
value: "cancel",
|
|
90
|
-
label: "Cancel",
|
|
91
|
-
hint: "Exit operation"
|
|
92
|
-
}
|
|
93
|
-
]
|
|
94
|
-
});
|
|
95
|
-
if (p.isCancel(action) || action === "cancel") {
|
|
96
|
-
p.cancel("Operation cancelled.");
|
|
97
|
-
process.exit(0);
|
|
98
|
-
}
|
|
99
|
-
if (action === "overwrite") {
|
|
100
|
-
const confirm = await p.confirm({
|
|
101
|
-
message: `Are you sure you want to clear "${projectName}"? This action cannot be undone.`
|
|
102
|
-
});
|
|
103
|
-
if (p.isCancel(confirm) || !confirm) {
|
|
104
|
-
p.cancel("Operation cancelled.");
|
|
105
|
-
process.exit(0);
|
|
106
|
-
}
|
|
107
|
-
await import("node:fs/promises").then((fs) => fs.rm(projectPath, { recursive: true, force: true }));
|
|
108
|
-
await import("node:fs/promises").then((fs) => fs.mkdir(projectPath, { recursive: true }));
|
|
109
|
-
} else if (action === "continue" && detectedConfig) {
|
|
110
|
-
const selections2 = {
|
|
111
|
-
projectName,
|
|
112
|
-
framework: detectedConfig.framework || "react",
|
|
113
|
-
variant: detectedConfig.variant || "ts",
|
|
114
|
-
language: detectedConfig.variant === "js" ? "javascript" : "typescript",
|
|
115
|
-
styling: detectedConfig.styling || "tailwind",
|
|
116
|
-
ui: detectedConfig.ui || "none",
|
|
117
|
-
forms: detectedConfig.forms || "none",
|
|
118
|
-
state: detectedConfig.state || "none",
|
|
119
|
-
routing: detectedConfig.routing || "none",
|
|
120
|
-
dataFetching: detectedConfig.dataFetching || "none",
|
|
121
|
-
structure: detectedConfig.structure || "feature",
|
|
122
|
-
icons: detectedConfig.icons || "lucide",
|
|
123
|
-
i18n: detectedConfig.i18n || "none",
|
|
124
|
-
auth: detectedConfig.auth || "none",
|
|
125
|
-
optionalFeatures: [],
|
|
126
|
-
...detectedConfig
|
|
127
|
-
};
|
|
128
|
-
await setup({ selections: selections2, targetDir: projectPath });
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
const frameworkOptions = frameworkPrompt.options.map((opt) => ({
|
|
133
|
-
value: opt.value,
|
|
134
|
-
label: opt.name,
|
|
135
|
-
hint: opt.hover_note
|
|
136
|
-
}));
|
|
137
|
-
const selectedFramework = await p.select({
|
|
138
|
-
message: frameworkPrompt.message,
|
|
139
|
-
options: frameworkOptions
|
|
140
|
-
});
|
|
141
|
-
if (p.isCancel(selectedFramework)) {
|
|
142
|
-
p.cancel("Operation cancelled.");
|
|
143
|
-
process.exit(0);
|
|
144
|
-
}
|
|
145
|
-
answers.framework = selectedFramework;
|
|
146
|
-
if (selectedFramework === "nextjs") {
|
|
147
|
-
p.note(
|
|
148
|
-
`${pc.yellow("\u23F3")} Next.js support is coming soon!
|
|
149
|
-
We're working hard to bring you Next.js support.
|
|
150
|
-
Please select React for now.`,
|
|
151
|
-
"Coming Soon"
|
|
152
|
-
);
|
|
153
|
-
p.outro(pc.cyan("Run nexo again and select React to continue."));
|
|
154
|
-
process.exit(0);
|
|
155
|
-
}
|
|
156
|
-
const framework = answers.framework;
|
|
157
|
-
for (const promptConfig of corePrompts) {
|
|
158
|
-
const filteredPrompt = filterPromptByFramework(promptConfig, framework);
|
|
159
|
-
if (filteredPrompt.options.length === 0) {
|
|
160
|
-
answers[promptConfig.name] = "none";
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
const options2 = filteredPrompt.options.map((opt) => ({
|
|
164
|
-
value: opt.value,
|
|
165
|
-
label: opt.name,
|
|
166
|
-
hint: opt.hover_note
|
|
167
|
-
}));
|
|
168
|
-
const answer = await p.select({
|
|
169
|
-
message: promptConfig.message,
|
|
170
|
-
options: options2
|
|
171
|
-
});
|
|
172
|
-
if (p.isCancel(answer)) {
|
|
173
|
-
p.cancel("Operation cancelled.");
|
|
174
|
-
process.exit(0);
|
|
175
|
-
}
|
|
176
|
-
answers[promptConfig.name] = answer;
|
|
177
|
-
const selectedOption = filteredPrompt.options.find((o) => o.value === answer);
|
|
178
|
-
if (selectedOption?.folder_info) {
|
|
179
|
-
p.note(selectedOption.folder_info.join("\n"), "\u{1F4C1} Folders");
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
const optionalFeatures = await p.multiselect({
|
|
183
|
-
message: "Select optional features (Space to select):",
|
|
184
|
-
options: optionalFeaturesPrompt.options.map((opt) => ({
|
|
185
|
-
value: opt.value,
|
|
186
|
-
label: opt.name,
|
|
187
|
-
hint: opt.hover_note
|
|
188
|
-
})),
|
|
189
|
-
required: false
|
|
190
|
-
});
|
|
191
|
-
if (p.isCancel(optionalFeatures)) {
|
|
192
|
-
p.cancel("Operation cancelled.");
|
|
193
|
-
process.exit(0);
|
|
194
|
-
}
|
|
195
|
-
answers.optionalFeatures = optionalFeatures;
|
|
196
|
-
for (const feature of optionalFeatures) {
|
|
197
|
-
const subPrompt = optionalSubPrompts[feature];
|
|
198
|
-
if (subPrompt) {
|
|
199
|
-
const subAnswer = await p.select({
|
|
200
|
-
message: subPrompt.message,
|
|
201
|
-
options: subPrompt.options.map((opt) => ({
|
|
202
|
-
value: opt.value,
|
|
203
|
-
label: opt.name,
|
|
204
|
-
hint: opt.hover_note
|
|
205
|
-
}))
|
|
206
|
-
});
|
|
207
|
-
if (p.isCancel(subAnswer)) {
|
|
208
|
-
p.cancel("Operation cancelled.");
|
|
209
|
-
process.exit(0);
|
|
210
|
-
}
|
|
211
|
-
answers[feature] = subAnswer;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
const summaryItems = [
|
|
215
|
-
`Project: ${pc.cyan(answers.projectName)}`,
|
|
216
|
-
`Framework: ${pc.cyan(framework)}`,
|
|
217
|
-
`Variant: ${pc.cyan(answers.variant)}`,
|
|
218
|
-
`Styling: ${pc.cyan(answers.styling)}`,
|
|
219
|
-
`UI Library: ${pc.cyan(answers.ui)}`,
|
|
220
|
-
`Forms: ${pc.cyan(answers.forms)}`,
|
|
221
|
-
`State: ${pc.cyan(answers.state)}`,
|
|
222
|
-
`Routing: ${pc.cyan(answers.routing)}`,
|
|
223
|
-
`Data Fetching: ${pc.cyan(answers.dataFetching)}`,
|
|
224
|
-
`Icons: ${pc.cyan(answers.icons)}`,
|
|
225
|
-
`Structure: ${pc.cyan(answers.structure)}`
|
|
226
|
-
];
|
|
227
|
-
if (answers.optionalFeatures.length > 0) {
|
|
228
|
-
summaryItems.push("", pc.yellow("Optional Features:"));
|
|
229
|
-
for (const feature of answers.optionalFeatures) {
|
|
230
|
-
const value = answers[feature] || feature;
|
|
231
|
-
summaryItems.push(` ${feature}: ${pc.green(value)}`);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
p.note(summaryItems.join("\n"), "\u{1F4CB} Summary");
|
|
235
|
-
const tempSelections = {
|
|
236
|
-
projectName: answers.projectName,
|
|
237
|
-
framework,
|
|
238
|
-
variant: answers.variant,
|
|
239
|
-
language: answers.variant.startsWith("ts") ? "typescript" : "javascript",
|
|
240
|
-
styling: answers.styling,
|
|
241
|
-
ui: answers.ui,
|
|
242
|
-
forms: answers.forms,
|
|
243
|
-
state: answers.state,
|
|
244
|
-
routing: answers.routing,
|
|
245
|
-
dataFetching: answers.dataFetching,
|
|
246
|
-
icons: answers.icons,
|
|
247
|
-
structure: answers.structure,
|
|
248
|
-
i18n: "none",
|
|
249
|
-
auth: "none"
|
|
308
|
+
const payload = JSON.parse(atob(token.split('.')[1]));
|
|
309
|
+
return {
|
|
310
|
+
id: payload.sub,
|
|
311
|
+
email: payload.email,
|
|
312
|
+
name: payload.name,
|
|
250
313
|
};
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
const confirmed = await p.confirm({
|
|
254
|
-
message: "Create project with these settings?"
|
|
255
|
-
});
|
|
256
|
-
if (p.isCancel(confirmed) || !confirmed) {
|
|
257
|
-
p.cancel("Operation cancelled.");
|
|
258
|
-
process.exit(0);
|
|
259
|
-
}
|
|
260
|
-
const variant = answers.variant;
|
|
261
|
-
const isTypeScript = variant.startsWith("ts");
|
|
262
|
-
const hasCompiler = variant.includes("compiler");
|
|
263
|
-
const hasSWC = variant.includes("swc");
|
|
264
|
-
const selections = {
|
|
265
|
-
projectName: answers.projectName,
|
|
266
|
-
framework,
|
|
267
|
-
variant,
|
|
268
|
-
language: isTypeScript ? "typescript" : "javascript",
|
|
269
|
-
styling: answers.styling,
|
|
270
|
-
ui: answers.ui,
|
|
271
|
-
forms: answers.forms,
|
|
272
|
-
state: answers.state,
|
|
273
|
-
routing: answers.routing,
|
|
274
|
-
dataFetching: answers.dataFetching,
|
|
275
|
-
icons: answers.icons,
|
|
276
|
-
structure: answers.structure,
|
|
277
|
-
i18n: answers.optionalFeatures.includes("i18n") ? answers.i18n : "none",
|
|
278
|
-
auth: answers.optionalFeatures.includes("auth") ? answers.auth : "none",
|
|
279
|
-
testing: answers.optionalFeatures.includes("testing") ? answers.testing : void 0,
|
|
280
|
-
linting: answers.optionalFeatures.includes("linting") ? answers.linting : void 0,
|
|
281
|
-
api: answers.optionalFeatures.includes("api") ? answers.api : void 0,
|
|
282
|
-
animation: answers.optionalFeatures.includes("animation") ? answers.animation : void 0,
|
|
283
|
-
docker: answers.optionalFeatures.includes("docker"),
|
|
284
|
-
monorepo: answers.optionalFeatures.includes("monorepo") ? answers.monorepo : void 0,
|
|
285
|
-
packageManager: "npm",
|
|
286
|
-
hasCompiler,
|
|
287
|
-
hasSWC
|
|
288
|
-
};
|
|
289
|
-
if (options.dryRun) {
|
|
290
|
-
log.newline();
|
|
291
|
-
log.header("DRY RUN MODE", "warning");
|
|
292
|
-
log.warn("No files will be created.");
|
|
293
|
-
log.newline();
|
|
294
|
-
const fileTree2 = generateFileTree(selections);
|
|
295
|
-
p.note(fileTree2, "\u{1F4C2} Files that would be created");
|
|
296
|
-
p.outro(pc.cyan("Dry run complete. Run without --dry-run to create the project."));
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
const startTime = Date.now();
|
|
300
|
-
await setup({
|
|
301
|
-
selections,
|
|
302
|
-
targetDir: options.dir,
|
|
303
|
-
parallel: options.parallel,
|
|
304
|
-
cicd: options.cicd
|
|
305
|
-
});
|
|
306
|
-
const endTime = Date.now();
|
|
307
|
-
const duration = ((endTime - startTime) / 1e3).toFixed(2);
|
|
308
|
-
p.outro(pc.green(`\u2728 Project created successfully in ${duration}s!`));
|
|
309
|
-
const installCmd = "npm install";
|
|
310
|
-
const devCmd = "npm run dev";
|
|
311
|
-
log.newline();
|
|
312
|
-
log.dim("Next steps:");
|
|
313
|
-
log.dim(` cd ${selections.projectName}`);
|
|
314
|
-
log.dim(` ${installCmd}`);
|
|
315
|
-
log.dim(` ${devCmd}`);
|
|
316
|
-
log.newline();
|
|
317
|
-
log.cyan("Happy coding! \u{1F680}");
|
|
318
|
-
log.newline();
|
|
319
|
-
} catch (error) {
|
|
320
|
-
p.cancel("Error creating project");
|
|
321
|
-
log.error(String(error));
|
|
322
|
-
process.exit(1);
|
|
314
|
+
} catch {
|
|
315
|
+
return null;
|
|
323
316
|
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
317
|
+
};
|
|
318
|
+
`);break;case"authjs":if(e.pkg)e.pkg.add("next-auth","^5.0.0-beta.25");else{let i=await x(e);d(i,"next-auth","^5.0.0-beta.25"),await P(e,i)}break}}});var Hr={};T(Hr,{mandatoryConfigurator:()=>qo});import{exec as Jo}from"node:child_process";import Ee from"node:path";import{promisify as Ho}from"node:util";var pt,qo,qr=b(()=>{"use strict";$();pt=Ho(Jo),qo=async e=>{let t=await x(e),{projectName:r}=e.selections;d(t,"@vite-pwa/assets-generator","^0.2.0",!0),d(t,"workbox-window","^7.1.0"),await P(e,t);let n={name:r,short_name:r,theme_color:"#ffffff",background_color:"#ffffff",display:"standalone",start_url:"/",icons:[{src:"/icon-192.png",sizes:"192x192",type:"image/png"},{src:"/icon-512.png",sizes:"512x512",type:"image/png"}]};await m(Ee.join(e.projectPath,"public")),await p(Ee.join(e.projectPath,"public","manifest.json"),JSON.stringify(n,null,2)),await p(Ee.join(e.projectPath,".gitignore"),`# Dependencies
|
|
319
|
+
node_modules
|
|
320
|
+
.pnp
|
|
321
|
+
.pnp.js
|
|
322
|
+
|
|
323
|
+
# Build output
|
|
324
|
+
dist
|
|
325
|
+
dist-ssr
|
|
326
|
+
build
|
|
327
|
+
out
|
|
328
|
+
.next
|
|
329
|
+
.nuxt
|
|
330
|
+
|
|
331
|
+
# Editor directories and files
|
|
332
|
+
.vscode/*
|
|
333
|
+
!.vscode/extensions.json
|
|
334
|
+
!.vscode/settings.json
|
|
335
|
+
.idea
|
|
336
|
+
*.suo
|
|
337
|
+
*.ntvs*
|
|
338
|
+
*.njsproj
|
|
339
|
+
*.sln
|
|
340
|
+
*.sw?
|
|
341
|
+
|
|
342
|
+
# Environment files - SECURITY CRITICAL
|
|
343
|
+
.env
|
|
344
|
+
.env.*
|
|
345
|
+
.env.local
|
|
346
|
+
.env.*.local
|
|
347
|
+
!.env.example
|
|
348
|
+
|
|
349
|
+
# Secrets and credentials - NEVER commit these
|
|
350
|
+
*.pem
|
|
351
|
+
*.key
|
|
352
|
+
*.crt
|
|
353
|
+
*.p12
|
|
354
|
+
*.pfx
|
|
355
|
+
secrets/
|
|
356
|
+
.secrets
|
|
357
|
+
credentials.json
|
|
358
|
+
service-account*.json
|
|
359
|
+
**/secrets/**
|
|
360
|
+
**/.secrets/**
|
|
361
|
+
|
|
362
|
+
# Logs
|
|
363
|
+
npm-debug.log*
|
|
364
|
+
yarn-debug.log*
|
|
365
|
+
yarn-error.log*
|
|
366
|
+
pnpm-debug.log*
|
|
367
|
+
logs/
|
|
368
|
+
*.log
|
|
369
|
+
|
|
370
|
+
# OS generated files
|
|
371
|
+
.DS_Store
|
|
372
|
+
.DS_Store?
|
|
373
|
+
._*
|
|
374
|
+
.Spotlight-V100
|
|
375
|
+
.Trashes
|
|
376
|
+
Thumbs.db
|
|
377
|
+
ehthumbs.db
|
|
378
|
+
Desktop.ini
|
|
379
|
+
|
|
380
|
+
# TypeScript cache
|
|
381
|
+
*.tsbuildinfo
|
|
382
|
+
tsconfig.tsbuildinfo
|
|
383
|
+
|
|
384
|
+
# Testing
|
|
385
|
+
coverage
|
|
386
|
+
.nyc_output
|
|
387
|
+
|
|
388
|
+
# Debug
|
|
389
|
+
*.map
|
|
390
|
+
|
|
391
|
+
# Temp files
|
|
392
|
+
tmp/
|
|
393
|
+
temp/
|
|
394
|
+
*.tmp
|
|
395
|
+
*.temp
|
|
396
|
+
|
|
397
|
+
# IDE specific
|
|
398
|
+
.fleet
|
|
399
|
+
*.swp
|
|
400
|
+
*~
|
|
401
|
+
|
|
402
|
+
# Security - prevent accidental exposure
|
|
403
|
+
.npmrc
|
|
404
|
+
.yarnrc
|
|
405
|
+
.docker/
|
|
406
|
+
docker-compose.override.yml
|
|
407
|
+
`);let s=`# ${r}
|
|
408
|
+
|
|
409
|
+
Built with [NEXO](https://github.com/nexo-cli) \u2014 Next-generation scaffolding CLI.
|
|
410
|
+
|
|
411
|
+
## Getting Started
|
|
412
|
+
|
|
413
|
+
\`\`\`bash
|
|
414
|
+
npm install
|
|
415
|
+
npm run dev
|
|
416
|
+
\`\`\`
|
|
417
|
+
|
|
418
|
+
## Scripts
|
|
419
|
+
|
|
420
|
+
- \`npm run dev\` - Start development server
|
|
421
|
+
- \`npm run build\` - Build for production
|
|
422
|
+
- \`npm run preview\` - Preview production build
|
|
423
|
+
|
|
424
|
+
## License
|
|
425
|
+
|
|
426
|
+
MIT
|
|
427
|
+
`;await p(Ee.join(e.projectPath,"README.md"),s);try{await pt("git init",{cwd:e.projectPath}),await pt("git add -A",{cwd:e.projectPath}),await pt('git commit -m "Initial commit from NEXO"',{cwd:e.projectPath})}catch{}}});var Vr={};T(Vr,{cicdConfigurator:()=>ut,createCICD:()=>es,default:()=>ts});import Y from"node:path";var Vo,Ko,Qo,Xo,Zo,Yo,ut,es,ts,Kr=b(()=>{"use strict";E();Vo=e=>`name: CI
|
|
428
|
+
|
|
429
|
+
on:
|
|
430
|
+
push:
|
|
431
|
+
branches: [main, master]
|
|
432
|
+
pull_request:
|
|
433
|
+
branches: [main, master]
|
|
434
|
+
|
|
435
|
+
jobs:
|
|
436
|
+
build:
|
|
437
|
+
runs-on: ubuntu-latest
|
|
438
|
+
|
|
439
|
+
strategy:
|
|
440
|
+
matrix:
|
|
441
|
+
node-version: [18.x, 20.x]
|
|
442
|
+
|
|
443
|
+
steps:
|
|
444
|
+
- name: Checkout repository
|
|
445
|
+
uses: actions/checkout@v4
|
|
446
|
+
|
|
447
|
+
- name: Setup Node.js \${{ matrix.node-version }}
|
|
448
|
+
uses: actions/setup-node@v4
|
|
449
|
+
with:
|
|
450
|
+
node-version: \${{ matrix.node-version }}
|
|
451
|
+
cache: 'npm'
|
|
452
|
+
|
|
453
|
+
- name: Install dependencies
|
|
454
|
+
run: npm ci
|
|
455
|
+
|
|
456
|
+
${e?` - name: Type check
|
|
457
|
+
run: npm run type-check
|
|
458
|
+
|
|
459
|
+
`:""} - name: Lint
|
|
460
|
+
run: npm run lint
|
|
461
|
+
|
|
462
|
+
- name: Run tests
|
|
463
|
+
run: npm run test:run
|
|
464
|
+
|
|
465
|
+
- name: Build
|
|
466
|
+
run: npm run build
|
|
467
|
+
`,Ko=e=>`name: Deploy
|
|
468
|
+
|
|
469
|
+
on:
|
|
470
|
+
push:
|
|
471
|
+
branches: [main, master]
|
|
472
|
+
workflow_dispatch:
|
|
473
|
+
|
|
474
|
+
permissions:
|
|
475
|
+
contents: read
|
|
476
|
+
pages: write
|
|
477
|
+
id-token: write
|
|
478
|
+
|
|
479
|
+
concurrency:
|
|
480
|
+
group: 'pages'
|
|
481
|
+
cancel-in-progress: true
|
|
482
|
+
|
|
483
|
+
jobs:
|
|
484
|
+
build:
|
|
485
|
+
runs-on: ubuntu-latest
|
|
486
|
+
steps:
|
|
487
|
+
- name: Checkout
|
|
488
|
+
uses: actions/checkout@v4
|
|
489
|
+
|
|
490
|
+
- name: Setup Node.js
|
|
491
|
+
uses: actions/setup-node@v4
|
|
492
|
+
with:
|
|
493
|
+
node-version: '20'
|
|
494
|
+
cache: 'npm'
|
|
495
|
+
|
|
496
|
+
- name: Install dependencies
|
|
497
|
+
run: npm ci
|
|
498
|
+
|
|
499
|
+
- name: Build
|
|
500
|
+
run: npm run build
|
|
501
|
+
|
|
502
|
+
- name: Setup Pages
|
|
503
|
+
uses: actions/configure-pages@v4
|
|
504
|
+
|
|
505
|
+
- name: Upload artifact
|
|
506
|
+
uses: actions/upload-pages-artifact@v3
|
|
507
|
+
with:
|
|
508
|
+
path: './dist'
|
|
509
|
+
|
|
510
|
+
deploy:
|
|
511
|
+
environment:
|
|
512
|
+
name: github-pages
|
|
513
|
+
url: \${{ steps.deployment.outputs.page_url }}
|
|
514
|
+
runs-on: ubuntu-latest
|
|
515
|
+
needs: build
|
|
516
|
+
steps:
|
|
517
|
+
- name: Deploy to GitHub Pages
|
|
518
|
+
id: deployment
|
|
519
|
+
uses: actions/deploy-pages@v4
|
|
520
|
+
`,Qo=()=>`name: Release
|
|
521
|
+
|
|
522
|
+
on:
|
|
523
|
+
push:
|
|
524
|
+
tags:
|
|
525
|
+
- 'v*'
|
|
526
|
+
|
|
527
|
+
permissions:
|
|
528
|
+
contents: write
|
|
529
|
+
|
|
530
|
+
jobs:
|
|
531
|
+
release:
|
|
532
|
+
runs-on: ubuntu-latest
|
|
533
|
+
steps:
|
|
534
|
+
- name: Checkout
|
|
535
|
+
uses: actions/checkout@v4
|
|
536
|
+
|
|
537
|
+
- name: Setup Node.js
|
|
538
|
+
uses: actions/setup-node@v4
|
|
539
|
+
with:
|
|
540
|
+
node-version: '20'
|
|
541
|
+
cache: 'npm'
|
|
542
|
+
|
|
543
|
+
- name: Install dependencies
|
|
544
|
+
run: npm ci
|
|
545
|
+
|
|
546
|
+
- name: Build
|
|
547
|
+
run: npm run build
|
|
548
|
+
|
|
549
|
+
- name: Create Release
|
|
550
|
+
uses: softprops/action-gh-release@v1
|
|
551
|
+
with:
|
|
552
|
+
generate_release_notes: true
|
|
553
|
+
files: |
|
|
554
|
+
dist/**/*
|
|
555
|
+
`,Xo=e=>`name: PR Check
|
|
556
|
+
|
|
557
|
+
on:
|
|
558
|
+
pull_request:
|
|
559
|
+
types: [opened, synchronize, reopened]
|
|
560
|
+
|
|
561
|
+
jobs:
|
|
562
|
+
check:
|
|
563
|
+
runs-on: ubuntu-latest
|
|
564
|
+
|
|
565
|
+
steps:
|
|
566
|
+
- name: Checkout
|
|
567
|
+
uses: actions/checkout@v4
|
|
568
|
+
|
|
569
|
+
- name: Setup Node.js
|
|
570
|
+
uses: actions/setup-node@v4
|
|
571
|
+
with:
|
|
572
|
+
node-version: '20'
|
|
573
|
+
cache: 'npm'
|
|
574
|
+
|
|
575
|
+
- name: Install dependencies
|
|
576
|
+
run: npm ci
|
|
577
|
+
|
|
578
|
+
${e?` - name: Type check
|
|
579
|
+
run: npm run type-check
|
|
580
|
+
|
|
581
|
+
`:""} - name: Lint
|
|
582
|
+
run: npm run lint
|
|
583
|
+
|
|
584
|
+
- name: Test
|
|
585
|
+
run: npm run test:run
|
|
586
|
+
|
|
587
|
+
- name: Build
|
|
588
|
+
run: npm run build
|
|
589
|
+
|
|
590
|
+
- name: Check bundle size
|
|
591
|
+
run: |
|
|
592
|
+
BUNDLE_SIZE=$(du -sk dist | cut -f1)
|
|
593
|
+
echo "Bundle size: \${BUNDLE_SIZE}KB"
|
|
594
|
+
if [ "$BUNDLE_SIZE" -gt 5000 ]; then
|
|
595
|
+
echo "\u26A0\uFE0F Warning: Bundle size exceeds 5MB"
|
|
596
|
+
fi
|
|
597
|
+
`,Zo=()=>`version: 2
|
|
598
|
+
updates:
|
|
599
|
+
- package-ecosystem: "npm"
|
|
600
|
+
directory: "/"
|
|
601
|
+
schedule:
|
|
602
|
+
interval: "weekly"
|
|
603
|
+
open-pull-requests-limit: 10
|
|
604
|
+
groups:
|
|
605
|
+
development-dependencies:
|
|
606
|
+
dependency-type: "development"
|
|
607
|
+
update-types:
|
|
608
|
+
- "minor"
|
|
609
|
+
- "patch"
|
|
610
|
+
production-dependencies:
|
|
611
|
+
dependency-type: "production"
|
|
612
|
+
update-types:
|
|
613
|
+
- "patch"
|
|
614
|
+
`,Yo=()=>`name: "CodeQL"
|
|
615
|
+
|
|
616
|
+
on:
|
|
617
|
+
push:
|
|
618
|
+
branches: [main, master]
|
|
619
|
+
pull_request:
|
|
620
|
+
branches: [main, master]
|
|
621
|
+
schedule:
|
|
622
|
+
- cron: '0 0 * * 0'
|
|
623
|
+
|
|
624
|
+
jobs:
|
|
625
|
+
analyze:
|
|
626
|
+
name: Analyze
|
|
627
|
+
runs-on: ubuntu-latest
|
|
628
|
+
permissions:
|
|
629
|
+
actions: read
|
|
630
|
+
contents: read
|
|
631
|
+
security-events: write
|
|
632
|
+
|
|
633
|
+
strategy:
|
|
634
|
+
fail-fast: false
|
|
635
|
+
matrix:
|
|
636
|
+
language: ['javascript']
|
|
637
|
+
|
|
638
|
+
steps:
|
|
639
|
+
- name: Checkout repository
|
|
640
|
+
uses: actions/checkout@v4
|
|
641
|
+
|
|
642
|
+
- name: Initialize CodeQL
|
|
643
|
+
uses: github/codeql-action/init@v3
|
|
644
|
+
with:
|
|
645
|
+
languages: \${{ matrix.language }}
|
|
646
|
+
|
|
647
|
+
- name: Autobuild
|
|
648
|
+
uses: github/codeql-action/autobuild@v3
|
|
649
|
+
|
|
650
|
+
- name: Perform CodeQL Analysis
|
|
651
|
+
uses: github/codeql-action/analyze@v3
|
|
652
|
+
`,ut=async(e,t={})=>{let{ci:r=!0,deploy:n=!1,release:o=!1,prCheck:s=!0,dependabot:i=!0,codeql:l=!1}=t,u=e.selections.language==="typescript",a=Y.join(e.projectPath,".github","workflows");if(await m(a),r&&await p(Y.join(a,"ci.yml"),Vo(u)),n&&await p(Y.join(a,"deploy.yml"),Ko(e.selections.projectName)),o&&await p(Y.join(a,"release.yml"),Qo()),s&&await p(Y.join(a,"pr-check.yml"),Xo(u)),l&&await p(Y.join(a,"codeql.yml"),Yo()),i){let w=Y.join(e.projectPath,".github");await m(w),await p(Y.join(w,"dependabot.yml"),Zo())}},es=async e=>{await ut(e,{ci:!0,prCheck:!0,dependabot:!0})},ts=ut});var Qr={};T(Qr,{aiInstructionsConfigurator:()=>gs});import re from"path";var ve,rs,ns,os,ss,is,as,cs,ls,ps,us,ms,ds,gs,Xr=b(()=>{"use strict";E();ve=(e,t)=>`# ${t} - ${e.projectName}
|
|
653
|
+
|
|
654
|
+
## Project Overview
|
|
655
|
+
This is a **${e.framework}** application built with modern best practices and tools.
|
|
656
|
+
|
|
657
|
+
## Tech Stack
|
|
658
|
+
|
|
659
|
+
### Core
|
|
660
|
+
- **Framework**: ${e.framework}
|
|
661
|
+
- **Language**: ${e.variant.includes("ts")?"TypeScript":"JavaScript"}${e.variant.includes("compiler")?" + React Compiler":""}${e.variant.includes("swc")?" + SWC":""}
|
|
662
|
+
- **Build Tool**: Vite
|
|
663
|
+
|
|
664
|
+
### Styling & UI
|
|
665
|
+
- **Styling**: ${e.styling}
|
|
666
|
+
${e.ui!=="none"?`- **UI Library**: ${e.ui}`:""}
|
|
667
|
+
${e.icons!=="none"?`- **Icons**: ${e.icons}`:""}
|
|
668
|
+
|
|
669
|
+
### State & Data
|
|
670
|
+
${e.state!=="none"?`- **State**: ${e.state}`:""}
|
|
671
|
+
${e.routing!=="none"?`- **Routing**: ${e.routing}`:""}
|
|
672
|
+
${e.dataFetching!=="none"?`- **Data Fetching**: ${e.dataFetching}`:""}
|
|
673
|
+
${e.forms!=="none"?`- **Forms**: ${e.forms}`:""}
|
|
674
|
+
|
|
675
|
+
### Additional Features
|
|
676
|
+
${e.hasAuth?"- **Authentication**: Configured":""}
|
|
677
|
+
${e.hasI18n?"- **Internationalization**: Configured":""}
|
|
678
|
+
${e.hasTesting?"- **Testing**: Configured":""}
|
|
679
|
+
|
|
680
|
+
## Project Structure
|
|
681
|
+
|
|
682
|
+
This project follows the **${e.structure}** architecture pattern.
|
|
683
|
+
|
|
684
|
+
${e.structure==="feature-based"?`
|
|
685
|
+
### Feature-Based Structure
|
|
686
|
+
\`\`\`
|
|
687
|
+
src/
|
|
688
|
+
\u251C\u2500\u2500 features/ # Feature modules
|
|
689
|
+
\u2502 \u2514\u2500\u2500 [feature]/
|
|
690
|
+
\u2502 \u251C\u2500\u2500 components/
|
|
691
|
+
\u2502 \u251C\u2500\u2500 hooks/
|
|
692
|
+
\u2502 \u2514\u2500\u2500 utils/
|
|
693
|
+
\u251C\u2500\u2500 shared/ # Shared utilities
|
|
694
|
+
\u2514\u2500\u2500 app/ # App-level config
|
|
695
|
+
\`\`\`
|
|
696
|
+
|
|
697
|
+
**Architecture**: ${e.structure}
|
|
698
|
+
**Organization**: Group related files by feature/domain
|
|
699
|
+
`:""}
|
|
700
|
+
|
|
701
|
+
${e.structure==="fsd"?`
|
|
702
|
+
### FSD (Feature-Sliced Design)
|
|
703
|
+
\`\`\`
|
|
704
|
+
src/
|
|
705
|
+
\u251C\u2500\u2500 app/ # App initialization
|
|
706
|
+
\u251C\u2500\u2500 pages/ # Page components
|
|
707
|
+
\u251C\u2500\u2500 widgets/ # Complex components
|
|
708
|
+
\u251C\u2500\u2500 features/ # Business features
|
|
709
|
+
\u251C\u2500\u2500 entities/ # Business entities
|
|
710
|
+
\u2514\u2500\u2500 shared/ # Shared code
|
|
711
|
+
\`\`\`
|
|
712
|
+
|
|
713
|
+
**Architecture**: ${e.structure}
|
|
714
|
+
**Organization**: Group related files by feature/domain
|
|
715
|
+
`:""}
|
|
716
|
+
|
|
717
|
+
${e.structure==="simple"?`
|
|
718
|
+
### Simple Structure
|
|
719
|
+
\`\`\`
|
|
720
|
+
src/
|
|
721
|
+
\u251C\u2500\u2500 components/ # React components
|
|
722
|
+
\u251C\u2500\u2500 hooks/ # Custom hooks
|
|
723
|
+
\u251C\u2500\u2500 utils/ # Utilities
|
|
724
|
+
\u2514\u2500\u2500 assets/ # Static assets
|
|
725
|
+
\`\`\`
|
|
726
|
+
|
|
727
|
+
**Architecture**: ${e.structure}
|
|
728
|
+
**Organization**: Group related files by feature/domain
|
|
729
|
+
`:""}
|
|
730
|
+
|
|
731
|
+
## Code Style Guidelines
|
|
732
|
+
|
|
733
|
+
### General Principles
|
|
734
|
+
1. **Type Safety First**: Always use proper TypeScript types (no \`any\` unless absolutely necessary)
|
|
735
|
+
2. **Component Composition**: Prefer small, focused components over large monoliths
|
|
736
|
+
3. **Custom Hooks**: Extract reusable logic into custom hooks
|
|
737
|
+
4. **Consistent Naming**: Use PascalCase for components, camelCase for functions/variables
|
|
738
|
+
|
|
739
|
+
### React Best Practices
|
|
740
|
+
- Use functional components with hooks
|
|
741
|
+
- Keep components pure when possible
|
|
742
|
+
- Use React.memo() for expensive renders
|
|
743
|
+
- Prefer composition over prop drilling
|
|
744
|
+
${e.variant.includes("compiler")?"- React Compiler handles memoization automatically":"- Use useMemo/useCallback strategically"}
|
|
745
|
+
|
|
746
|
+
### Styling Conventions
|
|
747
|
+
${e.styling==="tailwind"?`
|
|
748
|
+
- Use Tailwind utility classes
|
|
749
|
+
- Create reusable component variants
|
|
750
|
+
- Keep class names semantic and organized
|
|
751
|
+
- Use \`cn()\` utility for conditional classes
|
|
752
|
+
`:""}
|
|
753
|
+
|
|
754
|
+
${e.styling==="css-modules"?`
|
|
755
|
+
- One CSS module per component
|
|
756
|
+
- Use BEM naming within modules
|
|
757
|
+
- Keep styles scoped to components
|
|
758
|
+
`:""}
|
|
759
|
+
|
|
760
|
+
${e.ui==="shadcn"?`
|
|
761
|
+
### shadcn/ui Guidelines
|
|
762
|
+
- Components are in \`src/components/ui/\`
|
|
763
|
+
- Customize via Tailwind config
|
|
764
|
+
- Use the CLI to add new components: \`npx shadcn@latest add [component]\`
|
|
765
|
+
`:""}
|
|
766
|
+
|
|
767
|
+
${e.state==="zustand"?`
|
|
768
|
+
### State Management (Zustand)
|
|
769
|
+
- Create focused stores for specific domains
|
|
770
|
+
- Use slices pattern for large stores
|
|
771
|
+
- Keep actions alongside state
|
|
772
|
+
- Use selectors to prevent unnecessary rerenders
|
|
773
|
+
`:""}
|
|
774
|
+
|
|
775
|
+
${e.state==="redux"?`
|
|
776
|
+
### State Management (Redux Toolkit)
|
|
777
|
+
- Use createSlice for reducers
|
|
778
|
+
- Keep slices focused on single domains
|
|
779
|
+
- Use RTK Query for API calls
|
|
780
|
+
- Leverage TypeScript for state typing
|
|
781
|
+
`:""}
|
|
782
|
+
|
|
783
|
+
${e.routing==="react-router"?`
|
|
784
|
+
### Routing (React Router)
|
|
785
|
+
- Define routes in a centralized location
|
|
786
|
+
- Use loader functions for data fetching
|
|
787
|
+
- Implement error boundaries per route
|
|
788
|
+
- Use nested routes for layouts
|
|
789
|
+
`:""}
|
|
790
|
+
|
|
791
|
+
${e.routing==="tanstack-router"?`
|
|
792
|
+
### Routing (TanStack Router)
|
|
793
|
+
- Leverage full type safety in routes
|
|
794
|
+
- Use route loaders for data
|
|
795
|
+
- Define routes with type-safe params
|
|
796
|
+
- Utilize route-based code splitting
|
|
797
|
+
`:""}
|
|
798
|
+
|
|
799
|
+
${e.forms!=="none"?`
|
|
800
|
+
### Forms Best Practices
|
|
801
|
+
- Validate on submit, not on every keystroke
|
|
802
|
+
- Use schema-based validation
|
|
803
|
+
- Provide clear error messages
|
|
804
|
+
- Handle loading/error states
|
|
805
|
+
`:""}
|
|
806
|
+
|
|
807
|
+
## Important Patterns
|
|
808
|
+
|
|
809
|
+
### Error Handling
|
|
810
|
+
- Always handle async errors with try/catch
|
|
811
|
+
- Provide user-friendly error messages
|
|
812
|
+
- Log errors for debugging
|
|
813
|
+
- Use error boundaries for component errors
|
|
814
|
+
|
|
815
|
+
### Performance
|
|
816
|
+
- Code-split routes and heavy components
|
|
817
|
+
- Lazy load images and assets
|
|
818
|
+
- Debounce expensive operations
|
|
819
|
+
- Use virtual scrolling for long lists
|
|
820
|
+
|
|
821
|
+
|
|
822
|
+
### Accessibility
|
|
823
|
+
- Use semantic HTML elements
|
|
824
|
+
- Provide ARIA labels where needed
|
|
825
|
+
- Ensure keyboard navigation works
|
|
826
|
+
- Maintain proper heading hierarchy
|
|
827
|
+
|
|
828
|
+
## API Layer & Data Fetching
|
|
829
|
+
|
|
830
|
+
${e.dataFetching==="trpc"?"\n### tRPC Architecture\n- **Routers**: Defined in `src/server/api/routers`\n- **Procedures**: Use `publicProcedure` or `protectedProcedure`\n- **Client**: Use `api.router.procedure.useQuery()`\n- **Types**: Inferred automatically from backend routers\n":""}
|
|
831
|
+
|
|
832
|
+
${e.dataFetching==="tanstack-query"?`
|
|
833
|
+
### TanStack Query
|
|
834
|
+
- **Keys**: Use query key factories (e.g. \`userKeys.all\`)
|
|
835
|
+
- **Hooks**: Custom hooks for queries/mutations
|
|
836
|
+
- **Error Handling**: Global error boundary or per-query
|
|
837
|
+
`:""}
|
|
838
|
+
|
|
839
|
+
## Localization Context
|
|
840
|
+
**Primary Language**: ${e.language==="ar"?"Arabic (ar)":"English (en)"}
|
|
841
|
+
${e.language==="ar"?`
|
|
842
|
+
### Arabic Support Guidelines
|
|
843
|
+
- **Direction**: Ensure all UI components support RTL (Right-to-Left)
|
|
844
|
+
- **Fonts**: Use Arabic-friendly fonts (e.g., Cairo, IBM Plex Sans Arabic)
|
|
845
|
+
- **Content**: Placeholders and static text should be in Arabic
|
|
846
|
+
- **Layout**: Flip margins, paddings, and icons for RTL
|
|
847
|
+
`:""}
|
|
848
|
+
|
|
849
|
+
## AI Behavior Guidelines
|
|
850
|
+
|
|
851
|
+
### Code Generation Rules
|
|
852
|
+
1. **Always Generate Complete Code**
|
|
853
|
+
- Provide full, working implementations
|
|
854
|
+
- Never use placeholders like "// rest of the code"
|
|
855
|
+
- Include all necessary imports
|
|
856
|
+
- Write complete functions, not stubs
|
|
857
|
+
|
|
858
|
+
2. **Type Safety**
|
|
859
|
+
- Use explicit TypeScript types
|
|
860
|
+
- No \`any\` types unless absolutely necessary
|
|
861
|
+
- Define interfaces for component props
|
|
862
|
+
- Type all function parameters and return values
|
|
863
|
+
|
|
864
|
+
3. **Best Practices**
|
|
865
|
+
- Follow the project's architecture pattern
|
|
866
|
+
- Use existing utilities and helpers
|
|
867
|
+
- Match the established coding style
|
|
868
|
+
- Consider performance implications
|
|
869
|
+
|
|
870
|
+
### Response Template
|
|
871
|
+
|
|
872
|
+
When generating code, follow this structure:
|
|
873
|
+
|
|
874
|
+
\`\`\`typescript
|
|
875
|
+
// 1. Imports
|
|
876
|
+
import React from 'react';
|
|
877
|
+
import { type ComponentProps } from './types';
|
|
878
|
+
|
|
879
|
+
// 2. Types/Interfaces
|
|
880
|
+
interface Props {
|
|
881
|
+
// ...
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// 3. Component/Function
|
|
885
|
+
export function Component({ prop }: Props) {
|
|
886
|
+
// Complete implementation
|
|
887
|
+
return (
|
|
888
|
+
// Full JSX
|
|
889
|
+
);
|
|
890
|
+
}
|
|
891
|
+
\`\`\`
|
|
892
|
+
|
|
893
|
+
### Code Review Checklist
|
|
894
|
+
- [ ] All TypeScript types are defined
|
|
895
|
+
- [ ] No \`any\` types used
|
|
896
|
+
- [ ] Error handling is implemented
|
|
897
|
+
- [ ] Component is accessible
|
|
898
|
+
- [ ] Performance is considered
|
|
899
|
+
- [ ] Code follows project patterns
|
|
900
|
+
|
|
901
|
+
## Development Workflow
|
|
902
|
+
|
|
903
|
+
### Adding New Features
|
|
904
|
+
1. Create feature branch from main
|
|
905
|
+
2. Follow the project structure pattern
|
|
906
|
+
3. Write tests alongside code
|
|
907
|
+
4. Ensure type safety
|
|
908
|
+
5. Update documentation
|
|
909
|
+
|
|
910
|
+
## Common Commands
|
|
911
|
+
|
|
912
|
+
\`\`\`bash
|
|
913
|
+
npm run dev # Start development server
|
|
914
|
+
npm run build # Build for production
|
|
915
|
+
npm run preview # Preview production build
|
|
916
|
+
${e.hasTesting?"npm test # Run tests":""}
|
|
917
|
+
npm run lint # Lint code
|
|
918
|
+
\`\`\`
|
|
919
|
+
|
|
920
|
+
## Notes for AI Assistants
|
|
921
|
+
|
|
922
|
+
- **Always maintain type safety** - TypeScript is critical to this project
|
|
923
|
+
- **Follow the established architecture** - Don't introduce new patterns without discussion
|
|
924
|
+
- **Test your changes** - Ensure components work as expected
|
|
925
|
+
- **Keep dependencies minimal** - Only add packages when necessary
|
|
926
|
+
- **Respect the project structure** - Place files in the correct directories
|
|
927
|
+
- **Write self-documenting code** - Clear names over comments when possible
|
|
928
|
+
- **Generate complete code** - No placeholders or incomplete implementations
|
|
929
|
+
`,rs=e=>`# Cursor Rules for ${e.projectName}
|
|
930
|
+
|
|
931
|
+
You are an expert ${e.framework} developer working on this project.
|
|
932
|
+
|
|
933
|
+
## Tech Stack
|
|
934
|
+
Framework: ${e.framework}
|
|
935
|
+
Language: ${e.variant.includes("ts")?"TypeScript":"JavaScript"}
|
|
936
|
+
Styling: ${e.styling}
|
|
937
|
+
${e.ui!=="none"?`UI Library: ${e.ui}`:""}
|
|
938
|
+
${e.state!=="none"?`State: ${e.state}`:""}
|
|
939
|
+
|
|
940
|
+
## Code Style
|
|
941
|
+
- Use ${e.variant.includes("ts")?"TypeScript with strict types":"JavaScript with JSDoc"}
|
|
942
|
+
- Functional components with hooks only
|
|
943
|
+
- Extract logic into custom hooks
|
|
944
|
+
${e.styling==="tailwind"?"- Use Tailwind utility classes":""}
|
|
945
|
+
${e.ui==="shadcn"?"- shadcn/ui components in src/components/ui/":""}
|
|
946
|
+
|
|
947
|
+
## File Structure
|
|
948
|
+
Follow ${e.structure} architecture:
|
|
949
|
+
${e.structure==="feature-based"?"- Group by features in src/features/":""}
|
|
950
|
+
${e.structure==="fsd"?"- Use FSD layers: app/pages/widgets/features/entities/shared":""}
|
|
951
|
+
${e.structure==="simple"?"- Keep it simple: components/hooks/utils/assets":""}
|
|
952
|
+
|
|
953
|
+
## Best Practices
|
|
954
|
+
1. Type everything explicitly
|
|
955
|
+
2. Keep components small and focused
|
|
956
|
+
3. Use composition over complexity
|
|
957
|
+
4. Write self-documenting code
|
|
958
|
+
${e.hasTesting?"5. Write tests alongside features":""}
|
|
959
|
+
|
|
960
|
+
## When Creating Components
|
|
961
|
+
- PascalCase for component files
|
|
962
|
+
- Co-locate tests and styles
|
|
963
|
+
- Export from index files
|
|
964
|
+
- Use proper TypeScript types
|
|
965
|
+
|
|
966
|
+
## When Writing Code
|
|
967
|
+
- No \`any\` types
|
|
968
|
+
- Handle errors gracefully
|
|
969
|
+
- Consider accessibility
|
|
970
|
+
- Optimize for performance
|
|
971
|
+
`,ns=e=>`# Windsurf Rules for ${e.projectName}
|
|
972
|
+
|
|
973
|
+
Project: ${e.framework} with ${e.variant}
|
|
974
|
+
Architecture: ${e.structure}
|
|
975
|
+
|
|
976
|
+
## Stack
|
|
977
|
+
${e.framework} | ${e.styling} | ${e.ui!=="none"?e.ui:"No UI lib"} | ${e.state!=="none"?e.state:"React state"}
|
|
978
|
+
|
|
979
|
+
## Coding Standards
|
|
980
|
+
\u2713 ${e.variant.includes("ts")?"TypeScript strict mode":"JavaScript"}
|
|
981
|
+
\u2713 Functional components only
|
|
982
|
+
\u2713 Custom hooks for logic extraction
|
|
983
|
+
${e.styling==="tailwind"?"\u2713 Tailwind for styling":""}
|
|
984
|
+
|
|
985
|
+
## Project Structure
|
|
986
|
+
${e.structure}
|
|
987
|
+
|
|
988
|
+
## Key Principles
|
|
989
|
+
1. Type safety is non-negotiable
|
|
990
|
+
2. Components should be composable
|
|
991
|
+
3. Extract reusable logic to hooks
|
|
992
|
+
4. Follow established patterns
|
|
993
|
+
5. Test critical paths
|
|
994
|
+
|
|
995
|
+
## Commands
|
|
996
|
+
dev: npm run dev
|
|
997
|
+
build: npm run build
|
|
998
|
+
${e.hasTesting?"test: npm test":""}
|
|
999
|
+
`,os=e=>`# Cline Rules
|
|
1000
|
+
|
|
1001
|
+
## Project Details
|
|
1002
|
+
- Framework: ${e.framework}
|
|
1003
|
+
- Language: ${e.variant}
|
|
1004
|
+
- Structure: ${e.structure}
|
|
1005
|
+
|
|
1006
|
+
## Tech Stack Overview
|
|
1007
|
+
Styling: ${e.styling}
|
|
1008
|
+
${e.ui!=="none"?`UI Library: ${e.ui}`:""}
|
|
1009
|
+
${e.state!=="none"?`State: ${e.state}`:""}
|
|
1010
|
+
${e.routing!=="none"?`Routing: ${e.routing}`:""}
|
|
1011
|
+
${e.dataFetching!=="none"?`Data: ${e.dataFetching}`:""}
|
|
1012
|
+
|
|
1013
|
+
## Development Guidelines
|
|
1014
|
+
|
|
1015
|
+
### Code Quality
|
|
1016
|
+
- Strict TypeScript typing
|
|
1017
|
+
- Functional React patterns
|
|
1018
|
+
- Component composition
|
|
1019
|
+
- Custom hooks for shared logic
|
|
1020
|
+
|
|
1021
|
+
### File Organization
|
|
1022
|
+
Follow ${e.structure} pattern:
|
|
1023
|
+
${e.structure==="feature-based"?"- src/features/[feature-name]/":""}
|
|
1024
|
+
${e.structure==="fsd"?"- FSD layers: app/pages/widgets/features/entities/shared":""}
|
|
1025
|
+
${e.structure==="simple"?"- src/components/, src/hooks/, src/utils/":""}
|
|
1026
|
+
|
|
1027
|
+
### Best Practices
|
|
1028
|
+
1. Type all props and return values
|
|
1029
|
+
2. Use semantic HTML
|
|
1030
|
+
3. Handle loading/error states
|
|
1031
|
+
4. Optimize re-renders
|
|
1032
|
+
${e.hasTesting?"5. Write unit tests":""}
|
|
1033
|
+
|
|
1034
|
+
### Common Patterns
|
|
1035
|
+
- Custom hooks for data fetching
|
|
1036
|
+
- Error boundaries for resilience
|
|
1037
|
+
- Code splitting for performance
|
|
1038
|
+
${e.state==="zustand"?"- Zustand stores for state":""}
|
|
1039
|
+
${e.state==="redux"?"- Redux slices for state":""}
|
|
1040
|
+
|
|
1041
|
+
## Quick Reference
|
|
1042
|
+
\`\`\`bash
|
|
1043
|
+
npm run dev # Development
|
|
1044
|
+
npm run build # Production build
|
|
1045
|
+
${e.hasTesting?"npm test # Run tests":""}
|
|
1046
|
+
\`\`\`
|
|
1047
|
+
`,ss=e=>`# Roo-Cline Instructions for ${e.projectName}
|
|
1048
|
+
|
|
1049
|
+
## Project Configuration
|
|
1050
|
+
- **Framework**: ${e.framework}
|
|
1051
|
+
- **Language**: ${e.variant.includes("ts")?"TypeScript":"JavaScript"}
|
|
1052
|
+
- **Architecture**: ${e.structure}
|
|
1053
|
+
|
|
1054
|
+
## Technology Stack
|
|
1055
|
+
**Styling**: ${e.styling}
|
|
1056
|
+
${e.ui!=="none"?`**UI Library**: ${e.ui}`:""}
|
|
1057
|
+
${e.state!=="none"?`**State Management**: ${e.state}`:""}
|
|
1058
|
+
${e.routing!=="none"?`**Routing**: ${e.routing}`:""}
|
|
1059
|
+
${e.dataFetching!=="none"?`**Data Fetching**: ${e.dataFetching}`:""}
|
|
1060
|
+
${e.forms!=="none"?`**Forms**: ${e.forms}`:""}
|
|
1061
|
+
|
|
1062
|
+
## Development Standards
|
|
1063
|
+
|
|
1064
|
+
### TypeScript Guidelines
|
|
1065
|
+
- Enable strict mode
|
|
1066
|
+
- No implicit any
|
|
1067
|
+
- Explicit return types for functions
|
|
1068
|
+
- Type all component props
|
|
1069
|
+
|
|
1070
|
+
### Component Guidelines
|
|
1071
|
+
- Functional components only
|
|
1072
|
+
- Use hooks for state and effects
|
|
1073
|
+
- Keep components focused and small
|
|
1074
|
+
- Extract reusable logic to custom hooks
|
|
1075
|
+
|
|
1076
|
+
### File Organization
|
|
1077
|
+
Architecture: **${e.structure}**
|
|
1078
|
+
|
|
1079
|
+
${e.structure==="feature-based"?`
|
|
1080
|
+
- Group related files by feature
|
|
1081
|
+
- Each feature: components, hooks, utils
|
|
1082
|
+
- Shared code in src/shared/
|
|
1083
|
+
`:""}
|
|
1084
|
+
|
|
1085
|
+
${e.structure==="fsd"?`
|
|
1086
|
+
- Follow FSD layers strictly
|
|
1087
|
+
- app \u2192 pages \u2192 widgets \u2192 features \u2192 entities \u2192 shared
|
|
1088
|
+
- One-way dependencies only
|
|
1089
|
+
`:""}
|
|
1090
|
+
|
|
1091
|
+
${e.structure==="simple"?`
|
|
1092
|
+
- src/components/ - All React components
|
|
1093
|
+
- src/hooks/ - Custom hooks
|
|
1094
|
+
- src/utils/ - Helper functions
|
|
1095
|
+
- src/assets/ - Static files
|
|
1096
|
+
`:""}
|
|
1097
|
+
|
|
1098
|
+
### Styling Approach
|
|
1099
|
+
${e.styling==="tailwind"?`
|
|
1100
|
+
- Use Tailwind utility classes
|
|
1101
|
+
- Avoid custom CSS when possible
|
|
1102
|
+
- Use cn() for conditional classes
|
|
1103
|
+
`:""}
|
|
1104
|
+
|
|
1105
|
+
${e.styling==="css-modules"?`
|
|
1106
|
+
- One CSS module per component
|
|
1107
|
+
- Use BEM methodology
|
|
1108
|
+
- Keep styles scoped
|
|
1109
|
+
`:""}
|
|
1110
|
+
|
|
1111
|
+
### Best Practices
|
|
1112
|
+
1. **Type Safety**: Always use proper types
|
|
1113
|
+
2. **Composition**: Build with small, reusable pieces
|
|
1114
|
+
3. **Performance**: Lazy load and code split
|
|
1115
|
+
4. **Accessibility**: Semantic HTML and ARIA labels
|
|
1116
|
+
${e.hasTesting?"5. **Testing**: Write tests for features":""}
|
|
1117
|
+
|
|
1118
|
+
## Common Commands
|
|
1119
|
+
\`\`\`
|
|
1120
|
+
npm run dev \u2192 Start dev server
|
|
1121
|
+
npm run build \u2192 Production build
|
|
1122
|
+
${e.hasTesting?"npm test \u2192 Run tests":""}
|
|
1123
|
+
npm run lint \u2192 Lint code
|
|
1124
|
+
\`\`\`
|
|
1125
|
+
|
|
1126
|
+
## AI Assistant Notes
|
|
1127
|
+
- Maintain strict TypeScript typing
|
|
1128
|
+
- Follow the ${e.structure} architecture
|
|
1129
|
+
- Keep code clean and well-organized
|
|
1130
|
+
- Write self-documenting code
|
|
1131
|
+
- Ask before introducing new patterns
|
|
1132
|
+
`,is=e=>`# Aider configuration for ${e.projectName}
|
|
1133
|
+
|
|
1134
|
+
## Project Info
|
|
1135
|
+
framework: ${e.framework}
|
|
1136
|
+
language: ${e.variant.includes("ts")?"typescript":"javascript"}
|
|
1137
|
+
architecture: ${e.structure}
|
|
1138
|
+
|
|
1139
|
+
## Key Technologies
|
|
1140
|
+
styling: ${e.styling}
|
|
1141
|
+
${e.ui!=="none"?`ui_library: ${e.ui}`:""}
|
|
1142
|
+
${e.state!=="none"?`state_management: ${e.state}`:""}
|
|
1143
|
+
|
|
1144
|
+
## Code Standards
|
|
1145
|
+
- Use TypeScript strict mode
|
|
1146
|
+
- Functional components only
|
|
1147
|
+
- Extract hooks for reusable logic
|
|
1148
|
+
- Follow project structure pattern
|
|
1149
|
+
|
|
1150
|
+
## File Structure
|
|
1151
|
+
${e.structure}
|
|
1152
|
+
|
|
1153
|
+
## Development Commands
|
|
1154
|
+
dev: "npm run dev"
|
|
1155
|
+
build: "npm run build"
|
|
1156
|
+
${e.hasTesting?'test: "npm test"':""}
|
|
1157
|
+
`,as=e=>ve(e,"Claude Development Instructions"),cs=e=>ve(e,"Gemini Development Instructions"),ls=e=>ve(e,"OpenAI Codex Instructions"),ps=e=>ve(e,"AI Development Instructions"),us=e=>`---
|
|
1158
|
+
description: React & UI Best Practices
|
|
1159
|
+
globs: ["**/*.tsx", "**/*.jsx"]
|
|
1160
|
+
---
|
|
1161
|
+
# React Best Practices
|
|
1162
|
+
|
|
1163
|
+
- Use functional components with hooks
|
|
1164
|
+
- Prefer composition over prop drilling
|
|
1165
|
+
- Usage of ${e.styling} for styling
|
|
1166
|
+
${e.ui!=="none"?`- Use ${e.ui} components`:""}
|
|
1167
|
+
- Implement error boundaries
|
|
1168
|
+
- Use React.memo/useMemo/useCallback appropriately
|
|
1169
|
+
`,ms=e=>`---
|
|
1170
|
+
description: TypeScript & Code Quality
|
|
1171
|
+
globs: ["**/*.ts", "**/*.tsx"]
|
|
1172
|
+
---
|
|
1173
|
+
# TypeScript Guidelines
|
|
1174
|
+
|
|
1175
|
+
- No \`any\` types - use \`unknown\` if needed
|
|
1176
|
+
- Explicit return types for exported functions
|
|
1177
|
+
- Use interfaces for object definitions
|
|
1178
|
+
- Strict null checks enabled
|
|
1179
|
+
`,ds=e=>`---
|
|
1180
|
+
description: General Project Context & Architecture
|
|
1181
|
+
globs: ["*"]
|
|
1182
|
+
---
|
|
1183
|
+
# Project Context
|
|
1184
|
+
|
|
1185
|
+
## Stack
|
|
1186
|
+
- Framework: ${e.framework}
|
|
1187
|
+
- Language: ${e.variant}
|
|
1188
|
+
- Structure: ${e.structure}
|
|
1189
|
+
|
|
1190
|
+
## Architecture
|
|
1191
|
+
${e.structure==="feature-based"?"Feature-based: src/features/[feature]":""}
|
|
1192
|
+
${e.structure==="fsd"?"FSD Layers: app/pages/widgets/features/entities/shared":""}
|
|
1193
|
+
${e.structure==="simple"?"Simple: components/hooks/utils":""}
|
|
1194
|
+
`,gs=async({projectPath:e,selections:t})=>{let r=t.aiInstructions||[],n={projectName:t.projectName||re.basename(e),framework:t.framework,variant:t.variant,styling:t.styling,ui:t.ui||"none",forms:t.forms||"none",state:t.state||"none",routing:t.routing||"none",dataFetching:t.dataFetching||"none",structure:t.structure||"feature-based",icons:t.icons||"none",hasAuth:t.auth!=="none",hasI18n:t.i18n!=="none",hasTesting:t.testing!==void 0&&t.testing!=="none",language:"en"},o=re.join(e,".nexo");if(await m(o),await p(re.join(o,"ai-context.md"),ve(n,"Project Context")),r.length===0)return;let s={cursor:{file:".cursorrules",generate:rs},"cursor-modular":{isModular:!0,generators:{".cursor/rules/react.mdc":us,".cursor/rules/typescript.mdc":ms,".cursor/rules/general.mdc":ds}},windsurf:{file:".windsurfrules",generate:ns},cline:{file:".clinerules",generate:os},"roo-cline":{file:".roo-clinerules",generate:ss},aider:{file:".aider.conf.yml",generate:is},claude:{file:"CLAUDE_INSTRUCTIONS.md",generate:as},gemini:{file:"GEMINI_INSTRUCTIONS.md",generate:cs},codex:{file:"CODEX_INSTRUCTIONS.md",generate:ls},universal:{file:"AI_INSTRUCTIONS.md",generate:ps}};for(let i of r){let l=s[i];if(l)if(l.isModular&&l.generators)for(let[u,a]of Object.entries(l.generators))await m(re.dirname(re.join(e,u))),await p(re.join(e,u),a(n));else l.file&&l.generate&&await p(re.join(e,l.file),l.generate(n))}}});var Zr={};T(Zr,{visualTestingConfigurator:()=>fs});import we from"node:path";var fs,Yr=b(()=>{"use strict";E();fs=async({selections:e,projectPath:t,pkg:r})=>{let n=e["visual-testing"];if(!(!n||n==="none")){if(n==="storybook"){r?.add("storybook","^8.0.0",!0),r?.add("@storybook/react","^8.0.0",!0),r?.add("@storybook/react-vite","^8.0.0",!0),r?.add("@storybook/addon-essentials","^8.0.0",!0),r?.add("@storybook/blocks","^8.0.0",!0),r?.addScript("storybook","storybook dev -p 6006"),r?.addScript("build-storybook","storybook build");let o=we.join(t,".storybook");await m(o),await p(we.join(o,"main.ts"),`import type { StorybookConfig } from "@storybook/react-vite";
|
|
1195
|
+
|
|
1196
|
+
const config: StorybookConfig = {
|
|
1197
|
+
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
|
|
1198
|
+
addons: [
|
|
1199
|
+
"@storybook/addon-essentials",
|
|
1200
|
+
],
|
|
1201
|
+
framework: {
|
|
1202
|
+
name: "@storybook/react-vite",
|
|
1203
|
+
options: {},
|
|
1204
|
+
},
|
|
1205
|
+
};
|
|
1206
|
+
export default config;`),await p(we.join(o,"preview.ts"),`import type { Preview } from "@storybook/react";
|
|
1207
|
+
import '../src/index.css'; // Global styles
|
|
1208
|
+
|
|
1209
|
+
const preview: Preview = {
|
|
1210
|
+
parameters: {
|
|
1211
|
+
controls: {
|
|
1212
|
+
matchers: {
|
|
1213
|
+
color: /(background|color)$/i,
|
|
1214
|
+
date: /Date$/i,
|
|
1215
|
+
},
|
|
1216
|
+
},
|
|
1217
|
+
},
|
|
1218
|
+
};
|
|
1219
|
+
|
|
1220
|
+
export default preview;`)}else if(n==="ladle"){r?.add("@ladle/react","^4.0.0",!0),r?.addScript("ladle","ladle serve"),r?.addScript("build-ladle","ladle build");let o=we.join(t,".ladle");await m(o),await p(we.join(o,"config.mjs"),`export default {
|
|
1221
|
+
stories: ["src/**/*.stories.{js,jsx,ts,tsx}"],
|
|
1222
|
+
port: 61000,
|
|
1223
|
+
};`)}}}});import gt from"node:path";var be,ft=b(()=>{"use strict";$();be=async(e,t)=>{let r=gt.join(e.projectPath,"src"),{variant:n,styling:o,ui:s,state:i,routing:l,dataFetching:u}=e.selections,a=n.startsWith("ts"),h=["import { StrictMode } from 'react'","import { createRoot } from 'react-dom/client'",`import './index.${o==="sass"?"scss":"css"}'`,`import App from './App.${t}'`],C=[];i==="redux"&&(h.push("import { Provider } from 'react-redux'"),h.push("import { store } from './store/store'"),C.push({start:"<Provider store={store}>",end:"</Provider>"})),u==="tanstack-query"&&(h.push("import { QueryClient, QueryClientProvider } from '@tanstack/react-query'"),C.push({start:"<QueryClientProvider client={queryClient}>",end:"</QueryClientProvider>"})),s==="heroui"?(h.push("import { HeroUIProvider } from '@heroui/react'"),C.push({start:"<HeroUIProvider>",end:"</HeroUIProvider>"})):s==="chakra"?(h.push("import { ChakraProvider, defaultSystem } from '@chakra-ui/react'"),C.push({start:"<ChakraProvider value={defaultSystem}>",end:"</ChakraProvider>"})):s==="mantine"?(h.push("import { MantineProvider } from '@mantine/core'"),h.push("import '@mantine/core/styles.css'"),C.push({start:"<MantineProvider>",end:"</MantineProvider>"})):s==="antd"?(h.push("import { ConfigProvider } from 'antd'"),C.push({start:"<ConfigProvider>",end:"</ConfigProvider>"})):s==="styled-components"&&(h.push("import { ThemeProvider } from 'styled-components'"),h.push("const theme = {}"),C.push({start:"<ThemeProvider theme={theme}>",end:"</ThemeProvider>"}));let S="",L="<App />";l==="react-router"?(h.push("import { createBrowserRouter, RouterProvider } from 'react-router-dom'"),S=`
|
|
1224
|
+
const router = createBrowserRouter([
|
|
1225
|
+
{
|
|
1226
|
+
path: "*",
|
|
1227
|
+
element: <App />,
|
|
339
1228
|
}
|
|
340
|
-
|
|
1229
|
+
]);`,L="<RouterProvider router={router} />"):l==="tanstack-router"&&(h.push("import { RouterProvider, createRouter, createRootRoute } from '@tanstack/react-router'"),S=`
|
|
1230
|
+
const rootRoute = createRootRoute({
|
|
1231
|
+
component: App,
|
|
341
1232
|
});
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
log.newline();
|
|
349
|
-
log.dim("Usage: nexo create my-app --preset=saas\n");
|
|
350
|
-
});
|
|
351
|
-
program.command("generate").alias("g").description("Generate a component, hook, page, or feature").argument("<type>", "Type to generate (component, hook, page, feature)").argument("<name>", "Name of the item to generate").option("-d, --dir <directory>", "Target directory").option("--js", "Use JavaScript instead of TypeScript").option("--with-tests", "Include test file").option("--with-styles", "Include styles file").option("--style <type>", "Styling solution (css, scss, tailwind, css-modules)", "css").option("--with-index", "Include index file for exports").action(async (type, name, options) => {
|
|
352
|
-
const validTypes = ["component", "hook", "page", "feature"];
|
|
353
|
-
if (!validTypes.includes(type)) {
|
|
354
|
-
console.log(pc.red(`
|
|
355
|
-
\u2717 Invalid type: ${type}`));
|
|
356
|
-
console.log(pc.dim(` Valid types: ${validTypes.join(", ")}
|
|
357
|
-
`));
|
|
358
|
-
process.exit(1);
|
|
1233
|
+
|
|
1234
|
+
const router = createRouter({ routeTree: rootRoute });
|
|
1235
|
+
|
|
1236
|
+
declare module '@tanstack/react-router' {
|
|
1237
|
+
interface Register {
|
|
1238
|
+
router: typeof router
|
|
359
1239
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
1240
|
+
}`,L="<RouterProvider router={router} />");let D=h.join(`
|
|
1241
|
+
`);D+=`
|
|
1242
|
+
|
|
1243
|
+
`,u==="tanstack-query"&&(D+=`const queryClient = new QueryClient()
|
|
1244
|
+
`),D+=S+`
|
|
1245
|
+
`,D+=`createRoot(document.getElementById('root')${a?"!":""}).render(
|
|
1246
|
+
<StrictMode>
|
|
1247
|
+
`,C.forEach(N=>D+=` ${N.start}
|
|
1248
|
+
`),D+=` ${L}
|
|
1249
|
+
`,[...C].reverse().forEach(N=>D+=` ${N.end}
|
|
1250
|
+
`),D+=` </StrictMode>,
|
|
1251
|
+
)
|
|
1252
|
+
`,await p(gt.join(r,`main.${t}`),D),a&&await p(gt.join(r,"vite-env.d.ts"),`/// <reference types="vite/client" />
|
|
1253
|
+
`)}});import on from"node:path";var z,hs,ys,vs,Oe,ht,yt=b(()=>{"use strict";$();z={"React 19":"\u269B\uFE0F",Vite:"\u26A1",TypeScript:"\u{1F537}",JavaScript:"\u{1F7E8}","React Compiler":"\u{1F680}",SWC:"\u{1F980}","Tailwind CSS":"\u{1F30A}","Sass/SCSS":"\u{1F485}","CSS Modules":"\u{1F4E6}","shadcn/ui":"\u{1F3A8}","Radix UI":"\u{1F518}",Mantine:"\u{1F3AF}",HeroUI:"\u{1F9B8}","Ant Design":"\u{1F41C}","Chakra UI":"\u26A1",Zustand:"\u{1F43B}","Redux Toolkit":"\u{1F504}",Jotai:"\u{1F47B}","React Router":"\u{1F9ED}","TanStack Router":"\u{1F6E4}\uFE0F","TanStack Query":"\u{1F504}",Axios:"\u{1F4E1}","Fetch API":"\u{1F310}","React Hook Form + Zod":"\u{1F4DD}","React Hook Form + Yup":"\u{1F4DD}","Formik + Zod":"\u{1F4CB}","Formik + Yup":"\u{1F4CB}",Vitest:"\u{1F9EA}",Jest:"\u{1F0CF}","ESLint + Prettier":"\u2728",Biome:"\u{1F33F}","Framer Motion":"\u{1F3AC}","React Spring":"\u{1F338}"},hs=e=>{let{variant:t,styling:r,ui:n,forms:o,state:s,routing:i,dataFetching:l,testing:u,linting:a,animation:w}=e.selections,h=[{name:"React 19",icon:z["React 19"]??"\u269B\uFE0F"},{name:"Vite",icon:z.Vite??"\u26A1"}];t.includes("ts")&&h.push({name:"TypeScript",icon:z.TypeScript??"\u{1F537}"}),t.includes("compiler")&&h.push({name:"React Compiler",icon:z["React Compiler"]??"\u{1F680}"}),t.includes("swc")&&h.push({name:"SWC",icon:z.SWC??"\u{1F980}"});let C={tailwind:"Tailwind CSS",sass:"Sass/SCSS","css-modules":"CSS Modules"};if(C[r]){let f=C[r];h.push({name:f,icon:z[f]??"\u{1F3A8}"})}let S={shadcn:"shadcn/ui",radix:"Radix UI",mantine:"Mantine",heroui:"HeroUI",antd:"Ant Design",chakra:"Chakra UI"};if(n&&n!=="none"&&S[n]){let f=S[n];h.push({name:f,icon:z[f]??"\u{1F4E6}"})}let L={zustand:"Zustand",redux:"Redux Toolkit",jotai:"Jotai"};if(s&&s!=="none"&&L[s]){let f=L[s];h.push({name:f,icon:z[f]??"\u{1F4E6}"})}let D={"react-router":"React Router","tanstack-router":"TanStack Router"};if(i&&i!=="none"&&D[i]){let f=D[i];h.push({name:f,icon:z[f]??"\u{1F4E6}"})}let N={"tanstack-query":"TanStack Query",axios:"Axios",fetch:"Fetch API"};if(l&&l!=="none"&&N[l]){let f=N[l];h.push({name:f,icon:z[f]??"\u{1F4E6}"})}let k={"rhf-zod":"React Hook Form + Zod","rhf-yup":"React Hook Form + Yup","formik-zod":"Formik + Zod","formik-yup":"Formik + Yup"};if(o&&o!=="none"&&k[o]){let f=k[o];h.push({name:f,icon:z[f]??"\u{1F4DD}"})}if(u){let f=u==="vitest"?"Vitest":"Jest";h.push({name:f,icon:z[f]??"\u{1F9EA}"})}if(a){let f=a==="biome"?"Biome":"ESLint + Prettier";h.push({name:f,icon:z[f]??"\u2728"})}if(w){let f=w==="framer-motion"?"Framer Motion":"React Spring";h.push({name:f,icon:z[f]??"\u{1F3AC}"})}return h},ys=(e,t)=>`const techStack = [${t.map(n=>`{ name: '${n.name}', icon: '${n.icon}' }`).join(", ")}]
|
|
1254
|
+
|
|
1255
|
+
function App() {
|
|
1256
|
+
return (
|
|
1257
|
+
<div className="min-h-screen bg-[#0a0a0a] text-white selection:bg-cyan-500/30">
|
|
1258
|
+
{/* Background Gradients */}
|
|
1259
|
+
<div className="fixed inset-0 z-0 pointer-events-none">
|
|
1260
|
+
<div className="absolute top-[-10%] left-[-10%] w-[40%] h-[40%] rounded-full bg-purple-600/20 blur-[120px]" />
|
|
1261
|
+
<div className="absolute bottom-[-10%] right-[-10%] w-[40%] h-[40%] rounded-full bg-cyan-600/10 blur-[120px]" />
|
|
1262
|
+
</div>
|
|
1263
|
+
|
|
1264
|
+
<div className="relative z-10 max-w-5xl mx-auto px-6 py-20 flex flex-col items-center justify-center min-h-screen">
|
|
1265
|
+
|
|
1266
|
+
{/* Header */}
|
|
1267
|
+
<div className="text-center mb-16 space-y-4 animate-in fade-in slide-in-from-bottom-4 duration-700">
|
|
1268
|
+
<div className="inline-block px-3 py-1 pb-1.5 mb-4 text-xs font-medium tracking-wider text-cyan-400 uppercase bg-cyan-950/30 border border-cyan-800/50 rounded-full">
|
|
1269
|
+
NEXO CLI
|
|
1270
|
+
</div>
|
|
1271
|
+
<h1 className="text-6xl md:text-7xl font-bold tracking-tight">
|
|
1272
|
+
<span className="bg-gradient-to-br from-white via-white to-white/40 bg-clip-text text-transparent">
|
|
1273
|
+
${e}
|
|
1274
|
+
</span>
|
|
1275
|
+
</h1>
|
|
1276
|
+
<p className="text-lg text-neutral-400 max-w-lg mx-auto">
|
|
1277
|
+
Your high-performance React application is ready for takeoff.
|
|
1278
|
+
</p>
|
|
1279
|
+
</div>
|
|
1280
|
+
|
|
1281
|
+
{/* Tech Stack Grid */}
|
|
1282
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 w-full max-w-4xl mb-12">
|
|
1283
|
+
{/* Tech Card */}
|
|
1284
|
+
<div className="group relative p-8 rounded-3xl bg-neutral-900/50 border border-neutral-800 backdrop-blur-sm transition-all hover:border-neutral-700 hover:bg-neutral-900/80">
|
|
1285
|
+
<div className="absolute inset-0 bg-gradient-to-br from-purple-600/5 to-transparent rounded-3xl opacity-0 group-hover:opacity-100 transition-opacity" />
|
|
1286
|
+
<div className="relative">
|
|
1287
|
+
<div className="flex items-center gap-3 mb-6">
|
|
1288
|
+
<div className="p-2.5 bg-neutral-800 rounded-xl">
|
|
1289
|
+
<svg className="w-6 h-6 text-purple-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
1290
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
|
|
1291
|
+
</svg>
|
|
1292
|
+
</div>
|
|
1293
|
+
<h2 className="text-xl font-semibold text-white">Tech Stack</h2>
|
|
1294
|
+
</div>
|
|
1295
|
+
<div className="flex flex-wrap gap-2">
|
|
1296
|
+
{techStack.map((tech, i) => (
|
|
1297
|
+
<span key={i} className="px-3 py-1.5 flex items-center gap-1.5 border border-neutral-800 bg-neutral-900/50 rounded-lg text-sm text-neutral-300 hover:text-white hover:border-purple-500/30 hover:bg-purple-500/10 transition-colors cursor-default">
|
|
1298
|
+
<span>{tech.icon}</span>
|
|
1299
|
+
<span>{tech.name}</span>
|
|
1300
|
+
</span>
|
|
1301
|
+
))}
|
|
1302
|
+
</div>
|
|
1303
|
+
</div>
|
|
1304
|
+
</div>
|
|
1305
|
+
|
|
1306
|
+
{/* Steps Card */}
|
|
1307
|
+
<div className="group relative p-8 rounded-3xl bg-neutral-900/50 border border-neutral-800 backdrop-blur-sm transition-all hover:border-neutral-700 hover:bg-neutral-900/80">
|
|
1308
|
+
<div className="absolute inset-0 bg-gradient-to-br from-cyan-600/5 to-transparent rounded-3xl opacity-0 group-hover:opacity-100 transition-opacity" />
|
|
1309
|
+
<div className="relative">
|
|
1310
|
+
<div className="flex items-center gap-3 mb-6">
|
|
1311
|
+
<div className="p-2.5 bg-neutral-800 rounded-xl">
|
|
1312
|
+
<svg className="w-6 h-6 text-cyan-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
1313
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
|
|
1314
|
+
</svg>
|
|
1315
|
+
</div>
|
|
1316
|
+
<h2 className="text-xl font-semibold text-white">Get Started</h2>
|
|
1317
|
+
</div>
|
|
1318
|
+
<div className="space-y-4">
|
|
1319
|
+
{[
|
|
1320
|
+
{ text: 'Edit src/App.tsx', code: true },
|
|
1321
|
+
{ text: 'Save and see changes', code: false },
|
|
1322
|
+
{ text: 'Build something amazing! \u2728', code: false }
|
|
1323
|
+
].map((step, i) => (
|
|
1324
|
+
<div key={i} className="flex items-center gap-4 text-sm text-neutral-400">
|
|
1325
|
+
<div className="flex items-center justify-center w-6 h-6 rounded-full border border-neutral-800 bg-neutral-900 text-xs font-mono">
|
|
1326
|
+
{i + 1}
|
|
1327
|
+
</div>
|
|
1328
|
+
{step.code ? (
|
|
1329
|
+
<span>Edit <code className="px-1.5 py-0.5 rounded bg-cyan-950/30 border border-cyan-800/30 text-cyan-300 font-mono text-xs">src/App.tsx</code></span>
|
|
1330
|
+
) : (
|
|
1331
|
+
<span>{step.text}</span>
|
|
1332
|
+
)}
|
|
1333
|
+
</div>
|
|
1334
|
+
))}
|
|
1335
|
+
</div>
|
|
1336
|
+
</div>
|
|
1337
|
+
</div>
|
|
1338
|
+
</div>
|
|
1339
|
+
|
|
1340
|
+
{/* Footer */}
|
|
1341
|
+
<p className="text-neutral-500 text-sm animate-in fade-in duration-1000 delay-500">
|
|
1342
|
+
Made with \u2764\uFE0F using <span className="text-neutral-300 font-medium">NEXO CLI</span>
|
|
1343
|
+
</p>
|
|
1344
|
+
</div>
|
|
1345
|
+
</div>
|
|
1346
|
+
)
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
export default App
|
|
1350
|
+
`,vs=(e,t)=>`import './App.css'
|
|
1351
|
+
|
|
1352
|
+
const techStack = [${t.map(n=>`{ name: '${n.name}', icon: '${n.icon}' }`).join(", ")}]
|
|
1353
|
+
|
|
1354
|
+
function App() {
|
|
1355
|
+
return (
|
|
1356
|
+
<div className="app-container">
|
|
1357
|
+
<div className="background-glow"></div>
|
|
1358
|
+
|
|
1359
|
+
<div className="content">
|
|
1360
|
+
<div className="header">
|
|
1361
|
+
<div className="badge">NEXO CLI</div>
|
|
1362
|
+
<h1 className="title">${e}</h1>
|
|
1363
|
+
<p className="subtitle">Your high-performance React application is ready.</p>
|
|
1364
|
+
</div>
|
|
1365
|
+
|
|
1366
|
+
<div className="grid">
|
|
1367
|
+
<div className="card tech-card">
|
|
1368
|
+
<div className="card-header">
|
|
1369
|
+
<span className="icon">\u{1F6E0}\uFE0F</span>
|
|
1370
|
+
<h2>Tech Stack</h2>
|
|
1371
|
+
</div>
|
|
1372
|
+
<div className="tech-tags">
|
|
1373
|
+
{techStack.map((tech, i) => <span key={i} className="tag">{tech.icon} {tech.name}</span>)}
|
|
1374
|
+
</div>
|
|
1375
|
+
</div>
|
|
1376
|
+
|
|
1377
|
+
<div className="card steps-card">
|
|
1378
|
+
<div className="card-header">
|
|
1379
|
+
<span className="icon">\u{1F680}</span>
|
|
1380
|
+
<h2>Get Started</h2>
|
|
1381
|
+
</div>
|
|
1382
|
+
<div className="steps">
|
|
1383
|
+
<div className="step">
|
|
1384
|
+
<span className="number">1</span>
|
|
1385
|
+
<span>Edit <code>src/App.tsx</code></span>
|
|
1386
|
+
</div>
|
|
1387
|
+
<div className="step">
|
|
1388
|
+
<span className="number">2</span>
|
|
1389
|
+
<span>Save and see changes</span>
|
|
1390
|
+
</div>
|
|
1391
|
+
<div className="step">
|
|
1392
|
+
<span className="number">3</span>
|
|
1393
|
+
<span>Build something amazing!</span>
|
|
1394
|
+
</div>
|
|
1395
|
+
</div>
|
|
1396
|
+
</div>
|
|
1397
|
+
</div>
|
|
1398
|
+
|
|
1399
|
+
<p className="footer">Made with \u2764\uFE0F using NEXO CLI</p>
|
|
1400
|
+
</div>
|
|
1401
|
+
</div>
|
|
1402
|
+
)
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
export default App
|
|
1406
|
+
`,Oe=e=>{let{projectName:t,styling:r}=e.selections,n=hs(e);return r==="tailwind"?ys(t,n):vs(t,n)},ht=async(e,t)=>{let r=on.join(e.projectPath,"src"),n=Oe(e);await p(on.join(r,`App.${t}`),n)}});import sn from"node:path";var ws,Ue,vt=b(()=>{"use strict";$();ws=()=>`
|
|
1407
|
+
:root {
|
|
1408
|
+
--bg-dark: #0a0a0a;
|
|
1409
|
+
--text-white: #ffffff;
|
|
1410
|
+
--text-gray: #a3a3a3;
|
|
1411
|
+
--border-color: #262626;
|
|
1412
|
+
--card-bg: rgba(23, 23, 23, 0.5);
|
|
1413
|
+
--primary: #8b5cf6;
|
|
1414
|
+
--cyan: #06b6d4;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
body {
|
|
1418
|
+
margin: 0;
|
|
1419
|
+
background-color: var(--bg-dark);
|
|
1420
|
+
color: var(--text-white);
|
|
1421
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
1422
|
+
-webkit-font-smoothing: antialiased;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
.app-container {
|
|
1426
|
+
min-height: 100vh;
|
|
1427
|
+
display: flex;
|
|
1428
|
+
align-items: center;
|
|
1429
|
+
justify-content: center;
|
|
1430
|
+
position: relative;
|
|
1431
|
+
overflow: hidden;
|
|
1432
|
+
padding: 2rem;
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
.background-glow {
|
|
1436
|
+
position: absolute;
|
|
1437
|
+
top: -20%;
|
|
1438
|
+
left: -20%;
|
|
1439
|
+
width: 140%;
|
|
1440
|
+
height: 140%;
|
|
1441
|
+
background: radial-gradient(circle at 50% 50%, rgba(139, 92, 246, 0.05) 0%, transparent 50%);
|
|
1442
|
+
pointer-events: none;
|
|
1443
|
+
z-index: 0;
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
.content {
|
|
1447
|
+
position: relative;
|
|
1448
|
+
z-index: 10;
|
|
1449
|
+
max-width: 64rem;
|
|
1450
|
+
width: 100%;
|
|
1451
|
+
display: flex;
|
|
1452
|
+
flex-direction: column;
|
|
1453
|
+
align-items: center;
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
.header {
|
|
1457
|
+
text-align: center;
|
|
1458
|
+
margin-bottom: 4rem;
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
.badge {
|
|
1462
|
+
display: inline-block;
|
|
1463
|
+
padding: 0.25rem 0.75rem;
|
|
1464
|
+
border-radius: 9999px;
|
|
1465
|
+
background: rgba(6, 182, 212, 0.1);
|
|
1466
|
+
border: 1px solid rgba(6, 182, 212, 0.2);
|
|
1467
|
+
color: #22d3ee;
|
|
1468
|
+
font-size: 0.75rem;
|
|
1469
|
+
font-weight: 600;
|
|
1470
|
+
letter-spacing: 0.05em;
|
|
1471
|
+
margin-bottom: 1rem;
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
.title {
|
|
1475
|
+
font-size: 3.75rem;
|
|
1476
|
+
font-weight: 700;
|
|
1477
|
+
line-height: 1;
|
|
1478
|
+
margin: 0 0 1rem 0;
|
|
1479
|
+
background: linear-gradient(to bottom right, #ffffff 30%, rgba(255,255,255,0.5));
|
|
1480
|
+
-webkit-background-clip: text;
|
|
1481
|
+
background-clip: text;
|
|
1482
|
+
color: transparent;
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
.subtitle {
|
|
1486
|
+
color: var(--text-gray);
|
|
1487
|
+
font-size: 1.125rem;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
.grid {
|
|
1491
|
+
display: grid;
|
|
1492
|
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
1493
|
+
gap: 1.5rem;
|
|
1494
|
+
width: 100%;
|
|
1495
|
+
max-width: 56rem;
|
|
1496
|
+
margin-bottom: 3rem;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
.card {
|
|
1500
|
+
background: var(--card-bg);
|
|
1501
|
+
border: 1px solid var(--border-color);
|
|
1502
|
+
border-radius: 1.5rem;
|
|
1503
|
+
padding: 2rem;
|
|
1504
|
+
backdrop-filter: blur(12px);
|
|
1505
|
+
transition: all 0.3s ease;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
.card:hover {
|
|
1509
|
+
border-color: #404040;
|
|
1510
|
+
background: rgba(23, 23, 23, 0.8);
|
|
1511
|
+
transform: translateY(-2px);
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
.card-header {
|
|
1515
|
+
display: flex;
|
|
1516
|
+
align-items: center;
|
|
1517
|
+
gap: 0.75rem;
|
|
1518
|
+
margin-bottom: 1.5rem;
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
.card-header h2 {
|
|
1522
|
+
font-size: 1.25rem;
|
|
1523
|
+
font-weight: 600;
|
|
1524
|
+
margin: 0;
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
.icon {
|
|
1528
|
+
font-size: 1.25rem;
|
|
1529
|
+
padding: 0.5rem;
|
|
1530
|
+
background: #262626;
|
|
1531
|
+
border-radius: 0.75rem;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
.tech-tags {
|
|
1535
|
+
display: flex;
|
|
1536
|
+
flex-wrap: wrap;
|
|
1537
|
+
gap: 0.5rem;
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
.tag {
|
|
1541
|
+
padding: 0.375rem 0.75rem;
|
|
1542
|
+
background: rgba(255, 255, 255, 0.03);
|
|
1543
|
+
border: 1px solid var(--border-color);
|
|
1544
|
+
border-radius: 0.5rem;
|
|
1545
|
+
color: #d4d4d4;
|
|
1546
|
+
font-size: 0.875rem;
|
|
1547
|
+
transition: all 0.2s;
|
|
1548
|
+
cursor: default;
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
.tag:hover {
|
|
1552
|
+
background: rgba(139, 92, 246, 0.1);
|
|
1553
|
+
border-color: rgba(139, 92, 246, 0.3);
|
|
1554
|
+
color: white;
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
.steps {
|
|
1558
|
+
display: flex;
|
|
1559
|
+
flex-direction: column;
|
|
1560
|
+
gap: 1rem;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
.step {
|
|
1564
|
+
display: flex;
|
|
1565
|
+
align-items: center;
|
|
1566
|
+
gap: 1rem;
|
|
1567
|
+
color: var(--text-gray);
|
|
1568
|
+
font-size: 0.9375rem;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
.number {
|
|
1572
|
+
width: 1.5rem;
|
|
1573
|
+
height: 1.5rem;
|
|
1574
|
+
display: flex;
|
|
1575
|
+
align-items: center;
|
|
1576
|
+
justify-content: center;
|
|
1577
|
+
border-radius: 50%;
|
|
1578
|
+
background: #262626;
|
|
1579
|
+
border: 1px solid #404040;
|
|
1580
|
+
color: white;
|
|
1581
|
+
font-size: 0.75rem;
|
|
1582
|
+
font-family: monospace;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
code {
|
|
1586
|
+
background: rgba(6, 182, 212, 0.1);
|
|
1587
|
+
color: #22d3ee;
|
|
1588
|
+
padding: 0.2rem 0.4rem;
|
|
1589
|
+
border-radius: 0.25rem;
|
|
1590
|
+
font-family: monospace;
|
|
1591
|
+
font-size: 0.8em;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
.footer {
|
|
1595
|
+
color: #525252;
|
|
1596
|
+
font-size: 0.875rem;
|
|
1597
|
+
}
|
|
1598
|
+
`,Ue=async e=>{let{styling:t}=e.selections;if(t!=="tailwind"){let r=sn.join(e.projectPath,"src");await p(sn.join(r,"App.css"),ws())}}});import bs from"node:path";var an,cn=b(()=>{"use strict";$();ft();yt();ft();vt();yt();an=async e=>{let{variant:t}=e.selections,n=t.startsWith("ts")?"tsx":"jsx",o=bs.join(e.projectPath,"src");await m(o),await be(e,n),await ht(e,n)}});import Cs from"node:path";function xs(e){return{tailwind:"Tailwind CSS",sass:"Sass/SCSS","css-modules":"CSS Modules","plain-css":"CSS"}[e]||e}function ks(e){return{shadcn:"shadcn/ui",heroui:"HeroUI",mantine:"Mantine",chakra:"Chakra UI",antd:"Ant Design"}[e]||e}function Ss(e){return{redux:"Redux Toolkit",zustand:"Zustand",jotai:"Jotai"}[e]||e}function Ps(e){return{"react-router":"React Router","tanstack-router":"TanStack Router"}[e]||e}function js(e){return{"tanstack-query":"TanStack Query",axios:"Axios"}[e]||e}var ln,pn=b(()=>{"use strict";$();ln=async e=>{let{projectName:t,variant:r,styling:n,ui:o,state:s,routing:i,dataFetching:l,structure:u,testing:a,docker:w}=e.selections,h="npm run",S=`# ${t}
|
|
1599
|
+
|
|
1600
|
+
Built with **NEXO CLI** \u{1F680}
|
|
1601
|
+
|
|
1602
|
+
## \u{1F6E0}\uFE0F Tech Stack
|
|
1603
|
+
|
|
1604
|
+
- **Framework**: React 19 + Vite 6
|
|
1605
|
+
- **Language**: ${r.includes("ts")?"TypeScript":"JavaScript"}
|
|
1606
|
+
- **Styling**: ${xs(n)}
|
|
1607
|
+
${o!=="none"?`- **UI Library**: ${ks(o)}`:""}
|
|
1608
|
+
${s!=="none"?`- **State Management**: ${Ss(s)}`:""}
|
|
1609
|
+
${i!=="none"?`- **Routing**: ${Ps(i)}`:""}
|
|
1610
|
+
${l!=="none"?`- **Data Fetching**: ${js(l)}`:""}
|
|
1611
|
+
${a?`- **Testing**: ${a}`:""}
|
|
1612
|
+
|
|
1613
|
+
## \u{1F680} Getting Started
|
|
1614
|
+
|
|
1615
|
+
1. **Install dependencies**:
|
|
1616
|
+
\`\`\`bash
|
|
1617
|
+
npm install
|
|
1618
|
+
\`\`\`
|
|
1619
|
+
|
|
1620
|
+
2. **Start the dev server**:
|
|
1621
|
+
\`\`\`bash
|
|
1622
|
+
${h} dev
|
|
1623
|
+
\`\`\`
|
|
1624
|
+
|
|
1625
|
+
3. **Build for production**:
|
|
1626
|
+
\`\`\`bash
|
|
1627
|
+
${h} build
|
|
1628
|
+
\`\`\`
|
|
1629
|
+
|
|
1630
|
+
`;n==="tailwind"&&(S+=`## \u{1F3A8} Styling (Tailwind CSS v4)
|
|
1631
|
+
This project uses Tailwind CSS v4.
|
|
1632
|
+
- Configuration is handled in \`vite.config.ts\` via \`@tailwindcss/vite\`.
|
|
1633
|
+
- ${o==="shadcn"||o==="heroui"?"Includes extensions for UI library.":"Standard configuration."}
|
|
1634
|
+
|
|
1635
|
+
`),o==="shadcn"&&(S+="## \u{1F9E9} Shadcn UI\n- **Add components**:\n ```bash\n npx shadcn@latest add button\n ```\n- Configuration: `components.json`\n- Utils: `src/lib/utils.ts`\n\n"),s==="redux"&&(S+="## \u{1F4E6} State Management (Redux Toolkit)\n- **Store**: `src/store/store.ts`\n- **Hooks**: Use `useAppDispatch` and `useAppSelector` from `src/store/hooks.ts` instead of raw hooks.\n- **Slices**: Add new slices in `src/store` and register them in the store.\n\n"),u==="clean"?S+="## \u{1F4C2} Project Structure (Clean Architecture)\n- `src/domain`: Entities and business logic (Framework independent).\n- `src/application`: Use cases and services.\n- `src/infrastructure`: API calls, storage, third-party services.\n- `src/presentation`: UI components, pages, hooks.\n\n":u==="fsd"&&(S+="## \u{1F4C2} Project Structure (Feature-Sliced Design)\n- `app`: Global app setup (providers, styles).\n- `pages`: Route components.\n- `widgets`: Composition of entities/feautres.\n- `features`: User interactions (e.g. Auth, Search).\n- `entities`: Business entities (e.g. User, Product).\n- `shared`: Reusable UI, libs, api.\n\n"),a&&(S+=`## \u{1F9EA} Testing
|
|
1636
|
+
Run unit tests:
|
|
1637
|
+
\`\`\`bash
|
|
1638
|
+
${h} test:run
|
|
1639
|
+
\`\`\`
|
|
1640
|
+
|
|
1641
|
+
`),w&&(S+=`## \u{1F433} Docker
|
|
1642
|
+
Build and run container:
|
|
1643
|
+
\`\`\`bash
|
|
1644
|
+
docker build -t ${t} .
|
|
1645
|
+
docker run -p 3000:80 ${t}
|
|
1646
|
+
\`\`\`
|
|
1647
|
+
|
|
1648
|
+
`),S+=`## \u{1F4C4} License
|
|
1649
|
+
|
|
1650
|
+
This project is licensed under the MIT License.
|
|
1651
|
+
`,await p(Cs.join(e.projectPath,"README.md"),S)}});var un={};T(un,{createAppCss:()=>Ue,createEntryFiles:()=>an,createMainFile:()=>be,createReadme:()=>ln,createStyles:()=>Ue,createWelcomePage:()=>Oe});var mn=b(()=>{"use strict";cn();vt();pn()});import{Command as Ks}from"commander";import{createRequire as Qs}from"node:module";import"v8-compile-cache";import Pe from"picocolors";E();import Dt from"node:path";import Un from"picocolors";import{generateApi as _n}from"swagger-typescript-api";import U from"picocolors";var At={debug:0,info:1,warn:2,error:3,silent:4},Ke=class{level;prefix;colors;constructor(t={}){this.level=t.level||(process.env.DEBUG?"debug":"info"),this.prefix=t.prefix||"",this.colors=t.colors!==!1}shouldLog(t){return At[t]>=At[this.level]}format(t){return this.prefix?`${this.prefix} ${t}`:t}newline(){this.shouldLog("info")&&process.stdout.write(`
|
|
1652
|
+
`)}print(t){this.shouldLog("info")&&process.stdout.write(t+`
|
|
1653
|
+
`)}debug(t){this.shouldLog("debug")&&process.stdout.write(this.colors?U.dim(`[debug] ${t}`)+`
|
|
1654
|
+
`:`[debug] ${t}
|
|
1655
|
+
`)}info(t){this.shouldLog("info")&&process.stdout.write(this.format(t)+`
|
|
1656
|
+
`)}success(t){this.shouldLog("info")&&process.stdout.write(this.colors?U.green(this.format(t))+`
|
|
1657
|
+
`:this.format(t)+`
|
|
1658
|
+
`)}warn(t){this.shouldLog("warn")&&process.stderr.write(this.colors?U.yellow(`\u26A0 ${t}`)+`
|
|
1659
|
+
`:`Warning: ${t}
|
|
1660
|
+
`)}error(t){this.shouldLog("error")&&process.stderr.write(this.colors?U.red(`\u2716 ${t}`)+`
|
|
1661
|
+
`:`Error: ${t}
|
|
1662
|
+
`)}dim(t){this.shouldLog("info")&&process.stdout.write(this.colors?U.dim(t)+`
|
|
1663
|
+
`:t+`
|
|
1664
|
+
`)}cyan(t){this.shouldLog("info")&&process.stdout.write(this.colors?U.cyan(t)+`
|
|
1665
|
+
`:t+`
|
|
1666
|
+
`)}bold(t){this.shouldLog("info")&&process.stdout.write(this.colors?U.bold(t)+`
|
|
1667
|
+
`:t+`
|
|
1668
|
+
`)}header(t,r="info"){if(!this.shouldLog("info"))return;let n=this.colors?r==="error"?U.bgRed(U.white(U.bold(` ${t} `))):r==="warning"?U.bgYellow(U.black(` ${t} `)):U.bgCyan(U.white(` ${t} `)):`[ ${t} ]`;process.stdout.write(n+`
|
|
1669
|
+
`)}list(t,r=2){if(!this.shouldLog("info"))return;let n=" ".repeat(r);for(let o of t)process.stdout.write(this.colors?U.dim(`${n}${o}`)+`
|
|
1670
|
+
`:`${n}${o}
|
|
1671
|
+
`)}},G=new Ke,c={newline:()=>G.newline(),print:e=>G.print(e),debug:e=>G.debug(e),info:e=>G.info(e),success:e=>G.success(e),warn:e=>G.warn(e),error:e=>G.error(e),dim:e=>G.dim(e),cyan:e=>G.cyan(e),bold:e=>G.bold(e),header:(e,t)=>G.header(e,t),list:(e,t)=>G.list(e,t)};var Qe=async e=>{let t=e.name||"api",r=e.url,n=e.outputDir||Dt.join(e.targetDir||"src","api");try{return await m(n),c.info(Un.cyan(`
|
|
1672
|
+
\u{1F680} Generating API client from ${r}...
|
|
1673
|
+
`)),await _n({fileName:`${t}.ts`,output:n,url:r,httpClientType:"fetch",modular:!1,singleHttpClient:!0,generateClient:!0,generateRouteTypes:!0,generateResponses:!0,extractRequestParams:!0,extractRequestBody:!0,unwrapResponseData:!0}),{success:!0,files:[Dt.join(n,`${t}.ts`)],errors:[]}}catch(o){return{success:!1,files:[],errors:[o instanceof Error?o.message:String(o)]}}};var Et={name:"api",description:"Generate a typed API client from Swagger/OpenAPI",args:[{name:"<url>",description:"Swagger/OpenAPI JSON URL or file path",required:!0}],options:[{flags:"-n, --name <name>",description:"Name of the generated client",defaultValue:"api"},{flags:"-o, --output <path>",description:"Output directory"}],action:async(e,t)=>{let r=await Qe({name:t.name,url:e,outputDir:t.output,targetDir:"."});r.success?(console.log(Pe.green(`
|
|
1674
|
+
\u2728 API client generated successfully!`)),console.log(Pe.dim(` \u{1F4CD} ${r.files[0]}
|
|
1675
|
+
`))):(console.error(Pe.red(`
|
|
1676
|
+
\u2717 Failed to generate API client`)),r.errors.forEach(n=>console.error(Pe.red(` ${n}`))),console.log(),process.exit(1))}};import*as v from"@clack/prompts";import dn from"node:fs/promises";import Rs from"node:path";import j from"picocolors";import{createRequire as Ln}from"node:module";import ie from"picocolors";var zn=Ln(import.meta.url),Mn=zn("../../package.json"),Ot=`
|
|
1677
|
+
${ie.cyan(" _ _ _____ __ __ ___ ")}
|
|
1678
|
+
${ie.cyan(" | \\ | || ____|\\ \\/ / / _ \\ ")}
|
|
1679
|
+
${ie.cyan(" | \\| || _| \\ / | | | |")}
|
|
1680
|
+
${ie.cyan(" | |\\ || |___ / \\ | |_| |")}
|
|
1681
|
+
${ie.cyan(" |_| \\_||_____|/_/\\_\\ \\___/ ")}
|
|
1682
|
+
${ie.dim(" v"+Mn.version)}
|
|
1683
|
+
`;var R={react:2.5,"react-dom":42,vue:23,next:75,remix:50,"class-variance-authority":1,clsx:.4,"tailwind-merge":1,"@mantine/core":150,"@chakra-ui/react":100,zustand:1.1,"@reduxjs/toolkit":12,"react-redux":4.5,jotai:2.5,"react-router-dom":16,"@tanstack/react-router":13,"@tanstack/react-query":13,axios:12,swr:4,"react-hook-form":9,zod:13,"@hookform/resolvers":2,"lucide-react":5,i18next:8,"react-i18next":6},je=e=>{let t=0;return t+=R.react||0,t+=R["react-dom"]||0,e.ui==="shadcn"?t+=(R["class-variance-authority"]||0)+(R.clsx||0)+(R["tailwind-merge"]||0):e.ui==="mantine"&&(t+=R["@mantine/core"]||0),e.state==="zustand"?t+=R.zustand||0:e.state==="redux"?t+=(R["@reduxjs/toolkit"]||0)+(R["react-redux"]||0):e.state==="jotai"&&(t+=R.jotai||0),e.routing==="react-router"?t+=R["react-router-dom"]||0:e.routing==="tanstack-router"&&(t+=R["@tanstack/react-router"]||0),e.dataFetching==="tanstack-query"?t+=R["@tanstack/react-query"]||0:e.dataFetching==="axios"&&(t+=R.axios||0),e.forms?.includes("rhf")&&(t+=R["react-hook-form"]||0,e.forms.includes("zod")&&(t+=(R.zod||0)+(R["@hookform/resolvers"]||0))),e.icons==="lucide"&&(t+=R["lucide-react"]||0),e.i18n==="i18next"&&(t+=(R.i18next||0)+(R["react-i18next"]||0)),Number(t.toFixed(1))},$e=e=>e>=1024?`${(e/1024).toFixed(2)} MB`:`${e} kB`;var Te=e=>{let t={performance:70,accessibility:85,bestPractices:90,seo:80};return e.framework==="next"?(t.performance+=25,t.seo+=15):e.framework,e.styling==="tailwind"&&(t.performance+=5),e.ui==="none"?t.performance+=5:t.performance-=5,(e.ui==="mantine"||e.ui==="chakra"||e.ui==="shadcn")&&(t.accessibility+=10),t.performance=Math.min(100,t.performance),t.accessibility=Math.min(100,t.accessibility),t.bestPractices=Math.min(100,t.bestPractices),t.seo=Math.min(100,t.seo),t};var Ie={minimal:{framework:"react",variant:"ts",language:"typescript",styling:"plain-css",ui:"none",forms:"none",state:"none",routing:"none",dataFetching:"none",icons:"none",structure:"simple",i18n:"none",auth:"none",optionalFeatures:[]},saas:{framework:"react",variant:"ts",language:"typescript",styling:"tailwind",ui:"shadcn",forms:"rhf-zod",state:"zustand",routing:"react-router",dataFetching:"tanstack-query",icons:"lucide",structure:"feature-based",i18n:"i18next",auth:"jwt",testing:"vitest",linting:"eslint",api:"axios",optionalFeatures:["i18n","auth","testing","linting","api","aiInstructions"],aiInstructions:["universal"]},dashboard:{framework:"react",variant:"ts",language:"typescript",styling:"tailwind",ui:"shadcn",forms:"rhf-zod",state:"zustand",routing:"react-router",dataFetching:"tanstack-query",icons:"lucide",structure:"feature-based",i18n:"i18next",auth:"none",optionalFeatures:["i18n","aiInstructions"],aiInstructions:["universal"]},landing:{framework:"react",variant:"ts",language:"typescript",styling:"tailwind",ui:"shadcn",forms:"none",state:"none",routing:"none",dataFetching:"none",icons:"lucide",structure:"simple",i18n:"none",auth:"none",optionalFeatures:["animation","aiInstructions"],animation:"framer-motion",aiInstructions:["universal"]}};var Fe={name:"framework",message:"Select a framework:",type:"list",options:[{value:"react",name:"React",comment:"A JavaScript library for building user interfaces",hover_note:"React 19 with Vite - fast development and optimized builds"},{value:"nextjs",name:"Next.js",comment:"\u23F3 Coming Soon",hover_note:"Server-side rendering, API routes, and more - Coming Soon!"}]},Ut={name:"variant",message:"Select a variant:",type:"list",options:[{value:"ts",name:"TypeScript",comment:"Type-safe JavaScript",hover_note:"Standard TypeScript setup with full type checking"},{value:"ts-compiler",name:"TypeScript + React Compiler",comment:"Auto-optimization with React 19",hover_note:"Uses React Compiler for automatic memoization - best for React 19+"},{value:"ts-swc",name:"TypeScript + SWC",comment:"Faster builds with SWC",hover_note:"Rust-based compiler for 20x faster builds than Babel"},{value:"js",name:"JavaScript",comment:"Standard JavaScript",hover_note:"No type system, simpler setup"},{value:"js-compiler",name:"JavaScript + React Compiler",comment:"Auto-optimization without types",hover_note:"React Compiler benefits without TypeScript overhead"},{value:"js-swc",name:"JavaScript + SWC",comment:"Faster builds without types",hover_note:"Fast SWC compilation for JavaScript projects"}]},_t={name:"styling",message:"Select a styling solution:",type:"list",options:[{value:"tailwind",name:"Tailwind CSS",comment:"Utility-first CSS framework",hover_note:"Rapidly build modern websites without leaving your HTML - includes dark mode"},{value:"css-modules",name:"CSS Modules",comment:"Scoped CSS by default",hover_note:"CSS files where class names are scoped locally to avoid conflicts"},{value:"plain-css",name:"Plain CSS",comment:"Standard CSS files",hover_note:"Classic CSS with no preprocessing - simple and straightforward"},{value:"sass",name:"Sass/SCSS",comment:"CSS with superpowers",hover_note:"Variables, nesting, mixins, and more - industry standard preprocessor"},{value:"styled-components",name:"Styled Components",comment:"CSS-in-JS solution",hover_note:"Write actual CSS code inside your React components"}]},Lt={name:"ui",message:"Select a UI library:",type:"list",options:[{value:"shadcn",name:"shadcn/ui",comment:"Beautifully designed components (~0KB base)",hover_note:"Copy-paste components built with Radix and Tailwind - only import what you use",supportedFrameworks:["react"]},{value:"radix",name:"Radix UI",comment:"Unstyled, accessible (~5KB per component)",hover_note:"Low-level primitives for building custom design systems",supportedFrameworks:["react"]},{value:"mantine",name:"Mantine",comment:"Full-featured library (~50KB gzipped)",hover_note:"Over 100 customizable components and 50+ hooks included",supportedFrameworks:["react"]},{value:"heroui",name:"HeroUI",comment:"Beautiful, fast UI (~30KB gzipped)",hover_note:"Modern components built on Tailwind CSS and Radix primitives",supportedFrameworks:["react"]},{value:"mui",name:"Material UI (MUI)",comment:"Google Material Design",hover_note:"Comprehensive component library following Material Design guidelines",supportedFrameworks:["react"]},{value:"antd",name:"Ant Design",comment:"Enterprise-class UI (~120KB gzipped)",hover_note:"Feature-rich for enterprise apps with design system",supportedFrameworks:["react"]},{value:"chakra",name:"Chakra UI",comment:"Simple, modular (~80KB gzipped)",hover_note:"Good developer experience with accessible components",supportedFrameworks:["react"]},{value:"none",name:"None",comment:"No UI library (0KB)",hover_note:"Build your own components from scratch"}]},zt={name:"forms",message:"Select a forms solution:",type:"list",options:[{value:"rhf-zod",name:"React Hook Form + Zod",comment:"Best performance + type safety",hover_note:"Minimal re-renders with TypeScript-first validation schema",supportedFrameworks:["react"]},{value:"rhf-yup",name:"React Hook Form + Yup",comment:"Performant with Yup validation",hover_note:"Well-established validation library with good ecosystem",supportedFrameworks:["react"]},{value:"formik-zod",name:"Formik + Zod",comment:"Popular form library + Zod",hover_note:"Formik's simplicity with Zod's type inference",supportedFrameworks:["react"]},{value:"formik-yup",name:"Formik + Yup",comment:"Traditional Formik setup",hover_note:"Classic combination for form handling",supportedFrameworks:["react"]},{value:"tanstack-form",name:"TanStack Form",comment:"Type-safe forms by TanStack",hover_note:"Framework-agnostic with first-class TypeScript support",supportedFrameworks:["react"]},{value:"none",name:"None",comment:"No forms library",hover_note:"Use native form handling or add later"}]},Mt={name:"state",message:"Select a state management solution:",type:"list",options:[{value:"zustand",name:"Zustand",comment:"Small, fast, scalable",hover_note:"Minimal API with excellent TypeScript support - no boilerplate",supportedFrameworks:["react"]},{value:"redux",name:"Redux Toolkit",comment:"Industry standard",hover_note:"Best for complex state with devtools, middleware, and persistence",supportedFrameworks:["react"]},{value:"jotai",name:"Jotai",comment:"Primitive atoms approach",hover_note:"Atomic state management - great for derived state",supportedFrameworks:["react"]},{value:"none",name:"None",comment:"React built-in state",hover_note:"Use useState, useReducer, and Context API"}]},Bt={name:"routing",message:"Select a routing solution:",type:"list",options:[{value:"react-router",name:"React Router",comment:"Most popular routing",hover_note:"Declarative routing with data loading and actions support",supportedFrameworks:["react"]},{value:"tanstack-router",name:"TanStack Router",comment:"Fully type-safe routing",hover_note:"Type-safe from route definition to component - great DX",supportedFrameworks:["react"]},{value:"none",name:"None",comment:"No routing",hover_note:"Single page app without navigation"}]},Gt={name:"dataFetching",message:"Select a data fetching solution:",type:"list",options:[{value:"tanstack-query",name:"TanStack Query",comment:"Powerful async state",hover_note:"Caching, background updates, optimistic UI, infinite scroll built-in"},{value:"swr",name:"SWR",comment:"By Vercel",hover_note:"Stale-while-revalidate strategy with built-in cache and revalidation"},{value:"axios",name:"Axios",comment:"Promise-based HTTP client",hover_note:"Simple API with interceptors, transforms, and automatic JSON parsing"},{value:"fetch",name:"Native Fetch",comment:"Built-in browser API",hover_note:"No dependencies - use browser's native fetch API"},{value:"none",name:"None",comment:"No data fetching setup",hover_note:"Add data fetching solution later"}]},Wt={name:"icons",message:"Select an icon library:",type:"list",options:[{value:"lucide",name:"Lucide",comment:"Beautiful & consistent",hover_note:"Community-driven fork of Feather Icons - tree-shakeable"},{value:"react-icons",name:"React Icons",comment:"Largest collection (Fa, Md, Ai...)",hover_note:"Includes Font Awesome, Material, Ant Design, Bootstrap icons and more"},{value:"iconify",name:"Iconify",comment:"Universal icon framework",hover_note:"Access to 100,000+ icons from 100+ icon sets in one library"},{value:"heroicons",name:"Heroicons",comment:"By Tailwind Labs",hover_note:"Hand-crafted SVG icons designed to pair with Tailwind CSS"},{value:"fontawesome",name:"Font Awesome",comment:"Extensive icon library",hover_note:"Thousands of icons in multiple styles (solid, regular, brands)"},{value:"none",name:"None",comment:"No icon library",hover_note:"Use your own SVGs or add icons later"}]},Jt={name:"structure",message:"Select a project structure:",type:"list",options:[{value:"feature-based",name:"Feature-based",comment:"Organize by features",hover_note:"Group files by feature/domain - scales well for large apps",folder_info:["src/features/*","src/shared/*","src/app/*"]},{value:"fsd",name:"FSD (Feature-Sliced Design)",comment:"Architectural methodology",hover_note:"Layers \u2192 Slices \u2192 Segments - highly scalable architecture",folder_info:["src/app","src/pages","src/widgets","src/features","src/entities","src/shared"]},{value:"atomic",name:"Atomic Design",comment:"Atoms \u2192 Molecules \u2192 Organisms",hover_note:"Design system methodology by Brad Frost - great for component libraries",folder_info:["src/components/atoms","src/components/molecules","src/components/organisms"]},{value:"clean",name:"Clean Architecture",comment:"Domain-driven layers",hover_note:"Separation of concerns with domain, application, and infrastructure layers",folder_info:["src/domain","src/application","src/infrastructure","src/presentation"]},{value:"mvc",name:"MVC Pattern",comment:"Model-View-Controller",hover_note:"Classic pattern separating data, UI, and business logic",folder_info:["src/models","src/views","src/controllers"]},{value:"simple",name:"Simple",comment:"Minimal structure",hover_note:"Basic folders for small projects - easy to reorganize later",folder_info:["src/components","src/hooks","src/utils","src/assets"]}]},me=[Ut,_t,Lt,zt,Mt,Bt,Gt,Wt,Jt];var de={name:"optionalFeatures",message:"Select optional features (Space to select, Enter to continue):",type:"checkbox",options:[{value:"i18n",name:"Internationalization (i18n)",comment:"Multi-language support",hover_note:"Add i18next for translations - configure languages after creation"},{value:"auth",name:"Authentication",comment:"User authentication",hover_note:"JWT template or Auth.js setup for login/signup flows"},{value:"testing",name:"Testing",comment:"Unit & integration tests",hover_note:"Vitest or Jest configuration with React Testing Library"},{value:"linting",name:"Linting & Formatting",comment:"Code quality tools",hover_note:"ESLint + Prettier or Biome for consistent code style"},{value:"api",name:"API Layer",comment:"API client generation",hover_note:"OpenAPI client, GraphQL Apollo, or tRPC for type-safe APIs"},{value:"animation",name:"Animation Library",comment:"Motion & transitions",hover_note:"Framer Motion, GSAP, or React Spring for smooth animations"},{value:"docker",name:"Docker",comment:"Container configuration",hover_note:"Dockerfile and docker-compose for containerized deployment"},{value:"monorepo",name:"Monorepo Setup",comment:"Multi-package workspace",hover_note:"Turborepo or Nx for managing multiple packages in one repo"},{value:"visual-testing",name:"Visual Testing (Storybook)",comment:"Component documentation & testing",hover_note:"Storybook or Ladle setup for isolated component support"},{value:"ai-instructions",name:"AI Instructions",comment:"AI IDE/CLI guidance files",hover_note:"Generate instruction files for AI tools (Cursor, Windsurf, Claude, etc.)"}]},Ht={name:"i18n",message:"Select i18n solution:",type:"list",options:[{value:"i18next",name:"i18next",comment:"Most popular i18n",hover_note:"Feature-rich with React integration, plurals, formatting, and fallbacks"},{value:"lingui",name:"Lingui",comment:"Lightweight i18n",hover_note:"Compile-time extraction with minimal runtime - ICU message format"}]},qt={name:"auth",message:"Select authentication solution:",type:"list",options:[{value:"jwt",name:"Custom JWT",comment:"Flexible JWT auth",hover_note:"JWT template with login, logout, refresh token handling"},{value:"authjs",name:"Auth.js",comment:"Multi-provider auth",hover_note:"OAuth providers (Google, GitHub, etc.) + credentials auth"}]},Vt={name:"testing",message:"Select testing framework:",type:"list",options:[{value:"vitest",name:"Vitest",comment:"Vite-native testing",hover_note:"Blazing fast with Vite - compatible with Jest API"},{value:"jest",name:"Jest",comment:"Industry standard",hover_note:"Mature ecosystem with extensive documentation"}]},Kt={name:"linting",message:"Select linting setup:",type:"list",options:[{value:"eslint-prettier",name:"ESLint + Prettier",comment:"Standard combo",hover_note:"ESLint for linting, Prettier for formatting - widely adopted"},{value:"biome",name:"Biome",comment:"All-in-one tool",hover_note:"Fast Rust-based linter and formatter in one - simpler config"}]},Qt={name:"api",message:"Select API layer:",type:"list",options:[{value:"openapi",name:"OpenAPI Client",comment:"Generate from spec",hover_note:"Auto-generate typed API client from OpenAPI/Swagger spec"},{value:"graphql",name:"GraphQL (Apollo)",comment:"GraphQL client",hover_note:"Apollo Client with hooks, caching, and devtools"},{value:"trpc",name:"tRPC",comment:"End-to-end type safety",hover_note:"Full-stack TypeScript - types flow from backend to frontend"}]},Xt={name:"animation",message:"Select animation library:",type:"list",options:[{value:"framer-motion",name:"Framer Motion",comment:"Production-ready",hover_note:"Declarative animations with gestures, layout animations, and SVG support"},{value:"gsap",name:"GSAP",comment:"Professional-grade",hover_note:"Industry-standard animation library with timeline control and ScrollTrigger"},{value:"react-spring",name:"React Spring",comment:"Physics-based",hover_note:"Spring-physics animations for natural motion feel"}]},Zt={name:"monorepo",message:"Select monorepo tool:",type:"list",options:[{value:"turborepo",name:"Turborepo",comment:"By Vercel",hover_note:"Fast incremental builds with remote caching"},{value:"nx",name:"Nx",comment:"Full-featured",hover_note:"Advanced features with generators, executors, and graph visualization"}]},Bn={name:"aiInstructions",message:"Select AI tools to generate instructions for:",type:"checkbox",options:[{value:"cursor",name:"Cursor",comment:"AI-first code editor",hover_note:"Generate .cursorrules for Cursor IDE"},{value:"windsurf",name:"Windsurf",comment:"AI-powered IDE",hover_note:"Generate .windsurfrules for Windsurf"},{value:"cline",name:"Cline",comment:"VS Code AI extension",hover_note:"Generate .clinerules for Cline (formerly Claude Dev)"},{value:"roo-cline",name:"Roo Cline",comment:"Enhanced Cline fork",hover_note:"Generate .roo-clinerules for Roo Cline"},{value:"aider",name:"Aider",comment:"AI pair programming in terminal",hover_note:"Generate .aider.conf.yml for Aider CLI"},{value:"claude",name:"Claude",comment:"Anthropic Claude AI",hover_note:"Generate CLAUDE_INSTRUCTIONS.md for Claude CLI/API"},{value:"gemini",name:"Google Gemini",comment:"Google Gemini AI",hover_note:"Generate GEMINI_INSTRUCTIONS.md for Gemini"},{value:"codex",name:"OpenAI Codex",comment:"OpenAI Codex/ChatGPT",hover_note:"Generate CODEX_INSTRUCTIONS.md for Codex/ChatGPT"},{value:"universal",name:"Universal (All AI Tools)",comment:"Generic AI instructions",hover_note:"Generate AI_INSTRUCTIONS.md for any AI assistant"}]},Gn={name:"visual-testing",message:"Select visual testing tool:",type:"list",options:[{value:"storybook",name:"Storybook",comment:"Industry standard",hover_note:"Most popular tool for UI component development and documentation"},{value:"ladle",name:"Ladle",comment:"Fast & Lightweight",hover_note:"Drop-in alternative to Storybook, much faster startup"}]},Xe={i18n:Ht,auth:qt,testing:Vt,linting:Kt,api:Qt,animation:Xt,monorepo:Zt,"ai-instructions":Bn,"visual-testing":Gn};function Yt(e,t){return e.filter(r=>r.supportedFrameworks?r.supportedFrameworks.includes(t):!0)}function Ze(e,t){return{...e,options:Yt(e.options,t)}}var Ri=[...me,de];$();import $s from"node:path";var dt={framework:{loader:()=>Promise.resolve().then(()=>(vr(),yr)),exportName:"frameworkConfigurator"},variant:{loader:()=>Promise.resolve().then(()=>(br(),wr)),exportName:"variantConfigurator",dependencies:["framework"]},language:{loader:()=>Promise.resolve().then(()=>(xr(),Cr)),exportName:"languageConfigurator",dependencies:["variant"]},styling:{loader:()=>Promise.resolve().then(()=>(Sr(),kr)),exportName:"stylingConfigurator",dependencies:["language"]},ui:{loader:()=>Promise.resolve().then(()=>(jr(),Pr)),exportName:"uiConfigurator",dependencies:["styling"],condition:e=>e.selections.ui!=="none"},icons:{loader:()=>Promise.resolve().then(()=>(Tr(),$r)),exportName:"iconsConfigurator",dependencies:["language"],condition:e=>e.selections.icons!=="none"},forms:{loader:()=>Promise.resolve().then(()=>(Fr(),Ir)),exportName:"formsConfigurator",dependencies:["language"],condition:e=>e.selections.forms!=="none"},state:{loader:()=>Promise.resolve().then(()=>(Nr(),Rr)),exportName:"stateConfigurator",dependencies:["language"],condition:e=>e.selections.state!=="none"},routing:{loader:()=>Promise.resolve().then(()=>(Dr(),Ar)),exportName:"routingConfigurator",dependencies:["language"],condition:e=>e.selections.routing!=="none"},dataFetching:{loader:()=>Promise.resolve().then(()=>(Or(),Er)),exportName:"dataFetchingConfigurator",dependencies:["language"],condition:e=>e.selections.dataFetching!=="none"},animation:{loader:()=>Promise.resolve().then(()=>(_r(),Ur)),exportName:"animationConfigurator",dependencies:["language"],condition:e=>e.selections.animation!==void 0&&e.selections.animation!=="none"},structure:{loader:()=>Promise.resolve().then(()=>(zr(),Lr)),exportName:"structureConfigurator",dependencies:["language"]},i18n:{loader:()=>Promise.resolve().then(()=>(Br(),Mr)),exportName:"i18nConfigurator",dependencies:["language"],condition:e=>e.selections.i18n!=="none"},auth:{loader:()=>Promise.resolve().then(()=>(Jr(),Wr)),exportName:"authConfigurator",dependencies:["language"],condition:e=>e.selections.auth!=="none"},mandatory:{loader:()=>Promise.resolve().then(()=>(qr(),Hr)),exportName:"mandatoryConfigurator",dependencies:["styling","structure"]},cicd:{loader:()=>Promise.resolve().then(()=>(Kr(),Vr)),exportName:"cicdConfigurator",dependencies:["mandatory"],condition:()=>!1},"ai-instructions":{loader:()=>Promise.resolve().then(()=>(Xr(),Qr)),exportName:"aiInstructionsConfigurator",dependencies:["language"],condition:e=>{let t=e.selections.aiInstructions;return t!==void 0&&t.length>0}},"visual-testing":{loader:()=>Promise.resolve().then(()=>(Yr(),Zr)),exportName:"visualTestingConfigurator",dependencies:["language"],condition:e=>{let t=e.selections["visual-testing"];return t!==void 0&&t!=="none"}}},mt=new Map,tn=async(e,t={})=>{let r=dt[e];if(!r)return console.warn(`Unknown configurator: ${e}`),null;let{cache:n=!0}=t,o=e;if(n&&mt.has(o)){let s=mt.get(o);return en(s,r.exportName||e)}try{let s=await r.loader();return n&&mt.set(o,s),en(s,r.exportName||e)}catch(s){return console.error(`Failed to load configurator "${e}":`,s),null}},en=(e,t)=>{if(e[t])return e[t];if(e.default)return e.default;let r=`${t}Configurator`;return e[r]?e[r]:null};var rn=e=>{let t=[];for(let[r,n]of Object.entries(dt))n.condition&&!n.condition(e)||t.push(r);return t},nn=e=>{let t=[],r=new Set,n=new Set,o=s=>{if(r.has(s))return;if(n.has(s))throw new Error(`Circular dependency detected: ${s}`);n.add(s);let i=dt[s];if(i?.dependencies)for(let l of i.dependencies)e.includes(l)&&o(l);n.delete(s),r.add(s),t.push(s)};for(let s of e)o(s);return t};var wt=async(e,t)=>{let r=await tn(e);r&&await r(t)},Ts=async(e,t)=>{let r={framework:"Setting up framework",variant:"Configuring build variant",language:"Setting up language",styling:"Configuring styling",ui:"Adding UI library",forms:"Setting up forms",state:"Configuring state management",routing:"Setting up routing",dataFetching:"Configuring data fetching",icons:"Adding icon library",structure:"Creating project structure",i18n:"Setting up internationalization",auth:"Configuring authentication",animation:"Adding animation library",mandatory:"Adding mandatory features",cicd:"Setting up CI/CD","ai-instructions":"Generating AI instructions"};for(let n of e){let o=r[n]||`Configuring ${n}`,s=te(o);try{await wt(n,t),s.succeed()}catch(i){throw s.fail(),i}}},Is=async(e,t)=>{let r=["framework","variant","language"],n=["styling","forms","state","routing","dataFetching","icons","structure","i18n","auth","animation","ai-instructions"],o=["ui"],s=["mandatory"],i=async(l,u=!1)=>{let a=l.filter(w=>e.includes(w));if(a.length!==0)if(u)await Promise.all(a.map(w=>wt(w,t)));else for(let w of a)await wt(w,t)};c.info(" Setting up project..."),await i(r,!1),await i(n,!0),await i(o,!1),await i(s,!1)},Fs=async e=>{let{createEntryFiles:t,createReadme:r,createStyles:n}=await Promise.resolve().then(()=>(mn(),un));await t(e),await n(e),await r(e)},Ce=async({selections:e,targetDir:t,parallel:r=!0,cicd:n=!1})=>{let o=te("Initializing..."),s=$s.resolve(t,e.projectName),{PackageManager:i}=await Promise.resolve().then(()=>(it(),dr)),l=new i(s);o.stop();let u={projectPath:s,selections:e,pkg:l};await l.load(u),await Se(u);let a=rn(u);n&&!a.includes("cicd")&&a.push("cicd");let w=nn(a);r?await Is(w,u):await Ts(w,u);let h=te("Creating project files");await Fs(u),h.succeed();let C=te("Resolving latest dependencies...");await l.resolveLatestVersions(),C.succeed(),await l.save()};var bt=class e{static instance;isLearningMode=!1;isDebugMode=!1;constructor(){}static getInstance(){return e.instance||(e.instance=new e),e.instance}},Ct=bt.getInstance();Ne();$();var xt="my-nexo-app",_e=(e,t="\u{1F4A1} Educational Context")=>{Ct.isLearningMode&&v.note(e,t)},gn={name:"create",description:"Create a new project",isDefault:!0,args:[{name:"[name]",description:"Project name"}],options:[{flags:"-d, --dir <directory>",description:"Target directory",defaultValue:"."},{flags:"--dry-run",description:"Preview changes without creating files"},{flags:"--preset <preset>",description:"Use a preset configuration (saas, dashboard, landing)"},{flags:"--cicd",description:"Add CI/CD configuration (GitHub Actions)"},{flags:"--parallel",description:"Use parallel execution for faster setup"},{flags:"--learn",description:"Enable educational mode with explanations"}],action:async(e,t)=>{t.learn&&(Ct.isLearningMode=!0),t.silent&&(console.log=()=>{},console.error=()=>{},console.warn=()=>{}),c.dim(` NEXO is a next-generation, extensible CLI for scaffolding and orchestrating modern frontend projects
|
|
1684
|
+
`),console.log(Ot),v.intro(j.bgCyan(j.black(" NEXO "))),await V.load();try{let r=e||await v.text({message:"Project name:",placeholder:xt,defaultValue:xt,validate:a=>{let w=a||xt;if(!/^[a-z0-9-_]+$/i.test(w))return"Project name can only contain letters, numbers, hyphens, and underscores"}});v.isCancel(r)&&(v.cancel("Operation cancelled."),process.exit(0));let n;if(t.preset){let a=t.preset.toLowerCase();Object.keys(Ie).includes(a)||(c.error(`Invalid preset: "${t.preset}". Available items: ${Object.keys(Ie).join(", ")}`),process.exit(1)),c.info(`Using preset: ${j.cyan(a)}`);let w=Ie[a];n={projectName:r,framework:"react",variant:"ts",language:"typescript",styling:"tailwind",ui:"none",forms:"none",state:"none",routing:"none",dataFetching:"none",icons:"none",structure:"simple",i18n:"none",auth:"none",hasCompiler:!1,hasSWC:!1,packageManager:"npm",optionalFeatures:[],...w};let h=n.variant;n.hasCompiler=h.includes("compiler"),n.hasSWC=h.includes("swc"),n.language=h.startsWith("ts")?"typescript":"javascript"}else{let a={projectName:r},w=Rs.resolve(t.dir,r);if(!await ot(w)){let y=await ge(w),M="";y&&(M=`
|
|
1685
|
+
${j.bold("Previous Configuration Found:")}
|
|
1686
|
+
${j.dim("\u2022 Framework:")} ${y.framework||"Unknown"}
|
|
1687
|
+
${j.dim("\u2022 Language:")} ${y.variant==="ts"?"TypeScript":"JavaScript"}
|
|
1688
|
+
${j.dim("\u2022 Styling:")} ${y.styling||"Unknown"}
|
|
1689
|
+
`);let J=await v.select({message:`Folder "${r}" already exists and is not empty.${M}`,options:[...y?[{value:"continue",label:"Continue with previous setup",hint:"Uses detected configuration"}]:[],{value:"overwrite",label:"Start fresh",hint:"\u26A0\uFE0F Clears directory and starts new setup"},{value:"cancel",label:"Cancel",hint:"Exit operation"}]});if((v.isCancel(J)||J==="cancel")&&(v.cancel("Operation cancelled."),process.exit(0)),J==="overwrite"){let H=await v.confirm({message:`Are you sure you want to clear "${r}"? This action cannot be undone.`});(v.isCancel(H)||!H)&&(v.cancel("Operation cancelled."),process.exit(0)),await dn.rm(w,{recursive:!0,force:!0}),await dn.mkdir(w,{recursive:!0})}else if(J==="continue"&&y){let H={projectName:r,framework:y.framework||"react",variant:y.variant||"ts",language:y.variant==="js"?"javascript":"typescript",styling:y.styling||"tailwind",ui:y.ui||"none",forms:y.forms||"none",state:y.state||"none",routing:y.routing||"none",dataFetching:y.dataFetching||"none",structure:y.structure||"feature",icons:y.icons||"lucide",i18n:y.i18n||"none",auth:y.auth||"none",optionalFeatures:[],...y};await Ce({selections:H,targetDir:w});return}}let h=Fe.options.map(y=>({value:y.value,label:y.name,hint:y.hover_note})),C=await v.select({message:Fe.message,options:h});v.isCancel(C)&&(v.cancel("Operation cancelled."),process.exit(0)),a.framework=C,C==="nextjs"&&(v.note(`${j.yellow("\u23F3")} Next.js support is coming soon!
|
|
1690
|
+
We're working hard to bring you Next.js support.
|
|
1691
|
+
Please select React for now.`,"Coming Soon"),v.outro(j.cyan("Run nexo again and select React to continue.")),process.exit(0));let S=a.framework;for(let y of me){let M=Ze(y,S);if(M.options.length===0){a[y.name]="none";continue}y.name==="variant"?_e(`We recommend TypeScript for better type safety and developer experience.
|
|
1692
|
+
The "React Compiler" variant uses the new experimental compiler for auto-memoization.`):y.name==="styling"?_e(`Tailwind CSS offers a utility-first approach for rapid UI development.
|
|
1693
|
+
CSS Modules provide scoped CSS to avoid global conflicts.`):y.name==="state"?_e(`Local state (useState) is sufficient for simple apps.
|
|
1694
|
+
Zustand is a lightweight, scalable global state manager.
|
|
1695
|
+
Redux is powerful but has more boilerplate.`):y.name==="dataFetching"&&_e("TanStack Query (React Query) handles caching, deduplication, and background updates automatically.");let J=M.options.map(ue=>({value:ue.value,label:ue.name,hint:ue.hover_note})),H=await v.select({message:y.message,options:J});v.isCancel(H)&&(v.cancel("Operation cancelled."),process.exit(0)),a[y.name]=H;let se=M.options.find(ue=>ue.value===H);se?.folder_info&&v.note(se.folder_info.join(`
|
|
1696
|
+
`),"\u{1F4C1} Folders")}let L=await v.multiselect({message:"Select optional features (Space to select):",options:de.options.map(y=>({value:y.value,label:y.name,hint:y.hover_note})),required:!1});v.isCancel(L)&&(v.cancel("Operation cancelled."),process.exit(0)),a.optionalFeatures=L;for(let y of L){let M=Xe[y];if(M){let J,H=M.options.map(se=>({value:se.value,label:se.name,hint:se.hover_note}));M.type==="checkbox"?J=await v.multiselect({message:M.message,options:H,required:!1}):J=await v.select({message:M.message,options:H}),v.isCancel(J)&&(v.cancel("Operation cancelled."),process.exit(0)),a[y]=J}}let D={framework:S,variant:a.variant,styling:a.styling,ui:a.ui,forms:a.forms,state:a.state,routing:a.routing,dataFetching:a.dataFetching,icons:a.icons,i18n:a.optionalFeatures?.includes("i18n")?a.i18n:"none"},N=je(D),k=$e(N),f=Te(D),A=[`Project: ${j.cyan(a.projectName)}`,`Framework: ${j.cyan(S)}`,`Variant: ${j.cyan(a.variant)}`,`Styling: ${j.cyan(a.styling)}`,`UI Library: ${j.cyan(a.ui)}`,`Forms: ${j.cyan(a.forms)}`,`State: ${j.cyan(a.state)}`,`Routing: ${j.cyan(a.routing)}`,`Bundle Est.: ${j.green(k)} ${j.dim("(Initial JS)")}`,`Lighthouse Est: ${j.green(f.performance+"")} ${j.dim("(Perf)")} | ${j.green(f.seo+"")} ${j.dim("(SEO)")}`];v.note(A.join(`
|
|
1697
|
+
`),"\u{1F4CB} Summary");let ne=await v.confirm({message:"Create project with these settings?"});(v.isCancel(ne)||!ne)&&(v.cancel("Operation cancelled."),process.exit(0));let ee=a.variant,oe=ee.startsWith("ts"),Je=ee.includes("compiler"),He=ee.includes("swc");n={projectName:a.projectName,framework:S,variant:ee,language:oe?"typescript":"javascript",styling:a.styling,ui:a.ui,forms:a.forms,state:a.state,routing:a.routing,dataFetching:a.dataFetching,icons:a.icons,structure:a.structure,i18n:a.optionalFeatures.includes("i18n")?a.i18n:"none",auth:a.optionalFeatures.includes("auth")?a.auth:"none",testing:a.optionalFeatures.includes("testing")?a.testing:void 0,linting:a.optionalFeatures.includes("linting")?a.linting:void 0,api:a.optionalFeatures.includes("api")?a.api:void 0,animation:a.optionalFeatures.includes("animation")?a.animation:void 0,docker:a.optionalFeatures.includes("docker"),monorepo:a.optionalFeatures.includes("monorepo")?a.monorepo:void 0,aiInstructions:a.optionalFeatures.includes("ai-instructions")?a["ai-instructions"]:void 0,packageManager:"npm",hasCompiler:Je,hasSWC:He}}if(t.dryRun){c.newline(),c.header("DRY RUN MODE","warning"),c.warn("No files will be created."),c.newline();let a=X(n);v.note(a,"\u{1F4C2} Files that would be created"),v.outro(j.cyan("Dry run complete. Run without --dry-run to create the project."));return}let o=Date.now();await Ce({selections:n,targetDir:t.dir,parallel:t.parallel,cicd:t.cicd});let i=((Date.now()-o)/1e3).toFixed(2);v.outro(j.green(`\u2728 Project created successfully in ${i}s!`));let l="npm install",u="npm run dev";c.newline(),c.dim("Next steps:"),c.dim(` cd ${n.projectName}`),c.dim(` ${l}`),c.dim(` ${u}`),c.newline(),c.cyan("Happy coding! \u{1F680}"),c.newline()}catch(r){v.cancel("Error creating project"),c.error(String(r)),process.exit(1)}finally{await V.save()}}};import kt from"node:path";E();$();var fn={name:"docs",description:"Manage project documentation",args:[{name:"action",description:"Action to perform (generate)"}],action:async e=>{if(e!=="generate"){c.error('Unknown action. Use "generate".');return}let t=process.cwd(),r=kt.join(t,"package.json");if(!await I(r)){c.error("No package.json found. Run this in a project root.");return}c.info("Generating documentation...");try{let n=await x({projectPath:t}),o=await ge(t),s={projectName:n.name||"Project",...o},i=je(s),l=Te(s),u=`# Architecture: ${n.name}
|
|
1698
|
+
|
|
1699
|
+
> Auto-generated by Nexo CLI
|
|
1700
|
+
|
|
1701
|
+
## \u{1F6E0}\uFE0F Tech Stack
|
|
1702
|
+
|
|
1703
|
+
| Category | Technology |
|
|
1704
|
+
|----------|------------|
|
|
1705
|
+
| **Framework** | ${o?.framework||"Unknown"} |
|
|
1706
|
+
| **Language** | ${o?.variant==="ts"?"TypeScript":"JavaScript"} |
|
|
1707
|
+
| **Styling** | ${o?.styling||"Unknown"} |
|
|
1708
|
+
| **UI** | ${o?.ui||"None"} |
|
|
1709
|
+
| **State** | ${o?.state||"None"} |
|
|
1710
|
+
|
|
1711
|
+
## \u{1F4CA} Insights & Metrics
|
|
1712
|
+
|
|
1713
|
+
- **Estimated Initial Bundle**: ${$e(i)} (JS)
|
|
1714
|
+
- **Predicted Performance**: ${l.performance}/100
|
|
1715
|
+
- **Predicted SEO**: ${l.seo}/100
|
|
1716
|
+
|
|
1717
|
+
## \u{1F4C2} Project Structure
|
|
1718
|
+
|
|
1719
|
+
\`\`\`
|
|
1720
|
+
${X(s)}
|
|
1721
|
+
\`\`\`
|
|
1722
|
+
|
|
1723
|
+
## \u{1F504} Data Flow (Conceptual)
|
|
1724
|
+
|
|
1725
|
+
${s.dataFetching==="tanstack-query"?"- **Server State**: Managed by TanStack Query with caching/invalidation strategies.":"- **Data Fetching**: Standard fetch/axios calls."}
|
|
1726
|
+
${s.state==="zustand"?"- **Client State**: Global store managed by Zustand.":""}
|
|
1727
|
+
${s.state==="redux"?"- **Client State**: Centralized Redux store with slices.":""}
|
|
1728
|
+
|
|
1729
|
+
`;if(await p(kt.join(t,"ARCHITECTURE.md"),u),c.success("\u2713 Generated ARCHITECTURE.md"),o?.api){let a=`# API Documentation
|
|
1730
|
+
|
|
1731
|
+
## Client Generation
|
|
1732
|
+
This project uses **${o.api}** for API interactions.
|
|
1733
|
+
|
|
1734
|
+
## Endpoints
|
|
1735
|
+
(Run 'nexo docs refresh' to update specific endpoint docs - coming soon)
|
|
1736
|
+
`;await p(kt.join(t,"API.md"),a),c.success("\u2713 Generated API.md placeholder")}}catch(n){c.error("Failed to generate docs: "+String(n))}}};import{execa as Le}from"execa";var hn={name:"doctor",description:"Check project health and dependencies",action:async()=>{c.cyan(`
|
|
1737
|
+
\u{1FA7A} NEXO Doctor
|
|
1738
|
+
`);let e=[{name:"Node.js",check:async()=>process.version},{name:"npm",check:async()=>{let{stdout:r}=await Le("npm",["--version"]);return r.trim()}},{name:"Git",check:async()=>{let{stdout:r}=await Le("git",["--version"]);return r.trim().replace("git version ","")}},{name:"Git User",check:async()=>{try{let r=(await Le("git",["config","user.name"])).stdout.trim(),n=(await Le("git",["config","user.email"])).stdout.trim();return`${r} <${n}>`}catch{throw new Error("Git user not configured")}}}],t=!0;for(let{name:r,check:n}of e)try{let o=await n();c.success(` \u2713 ${r}: ${o}`)}catch{t=!1,c.error(` \u2717 ${r}: Not found or error`)}c.newline(),t?c.success("\u2728 System is ready for NEXO!"):c.warn("\u26A0\uFE0F Some checks failed. You may encounter issues."),c.newline()}};import xn from"picocolors";E();import F from"node:path";E();import pe from"node:fs/promises";import ze from"node:path";var St=".nexo/history.json",yn=async(e,t,r=process.cwd())=>{let n=ze.join(r,St),o={id:Math.random().toString(36).substring(7),action:e,timestamp:new Date().toISOString(),files:t},s=[];try{if(await I(n)){let l=await pe.readFile(n,"utf-8");s=JSON.parse(l)}}catch{}s.unshift(o),s.length>10&&(s=s.slice(0,10));let i=ze.dirname(n);await I(i)||await pe.mkdir(i,{recursive:!0}),await pe.writeFile(n,JSON.stringify(s,null,2))},vn=async(e=process.cwd())=>{let t=ze.join(e,St);try{if(!await I(t))return null;let r=await pe.readFile(t,"utf-8"),n=JSON.parse(r);return n.length>0?n[0]:null}catch{return null}},wn=async(e=process.cwd())=>{let t=ze.join(e,St);try{if(!await I(t))return;let r=await pe.readFile(t,"utf-8"),n=JSON.parse(r);n.length>0&&(n.shift(),await pe.writeFile(t,JSON.stringify(n,null,2)))}catch{}};var Ns=(e,t,r)=>{let n=t?`
|
|
1739
|
+
|
|
1740
|
+
interface ${e}Props {
|
|
1741
|
+
// Add props here
|
|
1742
|
+
}
|
|
1743
|
+
`:"",o=t?`{ }: ${e}Props`:"{ }";return`${r==="css-modules"?`import styles from './${e}.module.css';
|
|
1744
|
+
`:r==="scss"?`import './${e}.scss';
|
|
1745
|
+
`:r==="css"?`import './${e}.css';
|
|
1746
|
+
`:""}${n}
|
|
1747
|
+
export const ${e} = (${o}) => {
|
|
1748
|
+
return (
|
|
1749
|
+
<div${r==="css-modules"?" className={styles.container}":r==="tailwind"?' className=""':""}>
|
|
1750
|
+
<h1>${e}</h1>
|
|
1751
|
+
</div>
|
|
1752
|
+
);
|
|
1753
|
+
};
|
|
1754
|
+
|
|
1755
|
+
export default ${e};
|
|
1756
|
+
`},As=(e,t)=>{let r=t?": { value: string; setValue: (v: string) => void }":"";return`import { useState } from 'react';
|
|
1757
|
+
${t?`
|
|
1758
|
+
interface Use`+e.replace(/^use/,"")+`Options {
|
|
1759
|
+
initialValue?: string;
|
|
1760
|
+
}
|
|
1761
|
+
`:""}
|
|
1762
|
+
export const ${e} = (${t?"options: Use"+e.replace(/^use/,"")+"Options = {}":"options = {}"})${r} => {
|
|
1763
|
+
const { initialValue = '' } = options;
|
|
1764
|
+
const [value, setValue] = useState${t?"<string>":""}(initialValue);
|
|
1765
|
+
|
|
1766
|
+
// Add your hook logic here
|
|
1767
|
+
|
|
1768
|
+
return {
|
|
1769
|
+
value,
|
|
1770
|
+
setValue,
|
|
1771
|
+
};
|
|
1772
|
+
};
|
|
1773
|
+
|
|
1774
|
+
export default ${e};
|
|
1775
|
+
`},Ds=(e,t,r)=>{let n=t?`
|
|
1776
|
+
|
|
1777
|
+
interface ${e}PageProps {
|
|
1778
|
+
// Add props here
|
|
1779
|
+
}
|
|
1780
|
+
`:"",o=t?`{ }: ${e}PageProps`:"{ }",s=r==="tailwind"?' className="container mx-auto px-4 py-8"':r==="css-modules"?" className={styles.page}":"";return`${r==="css-modules"?`import styles from './${e}Page.module.css';
|
|
1781
|
+
`:""}${n}
|
|
1782
|
+
export const ${e}Page = (${o}) => {
|
|
1783
|
+
return (
|
|
1784
|
+
<main${s}>
|
|
1785
|
+
<h1>${e}</h1>
|
|
1786
|
+
<p>Welcome to the ${e} page.</p>
|
|
1787
|
+
</main>
|
|
1788
|
+
);
|
|
1789
|
+
};
|
|
1790
|
+
|
|
1791
|
+
export default ${e}Page;
|
|
1792
|
+
`},Es=(e,t)=>`// ${e} Feature
|
|
1793
|
+
// Export components, hooks, and utilities from this feature
|
|
1794
|
+
|
|
1795
|
+
export * from './components';
|
|
1796
|
+
export * from './hooks';
|
|
1797
|
+
${t?`export * from './types';
|
|
1798
|
+
`:""}`,Os=e=>`// ${e} Feature Types
|
|
1799
|
+
|
|
1800
|
+
export interface ${e}State {
|
|
1801
|
+
// Add state properties
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
export interface ${e}Actions {
|
|
1805
|
+
// Add action types
|
|
1806
|
+
}
|
|
1807
|
+
`,Pt=(e,t,r)=>{let n=t==="hook"?`./${e}`:`./${e}`,o=t==="hook"?e:t==="page"?`${e}Page`:e;return t==="hook"?`import { renderHook, act } from '@testing-library/react';
|
|
1808
|
+
import { ${e} } from '${n}';
|
|
1809
|
+
|
|
1810
|
+
describe('${e}', () => {
|
|
1811
|
+
it('should initialize with default value', () => {
|
|
1812
|
+
const { result } = renderHook(() => ${e}());
|
|
1813
|
+
expect(result.current.value).toBe('');
|
|
379
1814
|
});
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
1815
|
+
|
|
1816
|
+
it('should update value', () => {
|
|
1817
|
+
const { result } = renderHook(() => ${e}());
|
|
1818
|
+
|
|
1819
|
+
act(() => {
|
|
1820
|
+
result.current.setValue('test');
|
|
1821
|
+
});
|
|
1822
|
+
|
|
1823
|
+
expect(result.current.value).toBe('test');
|
|
388
1824
|
});
|
|
389
1825
|
});
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
`Project: ${pc.cyan(result.projectName)}`,
|
|
398
|
-
`Type: ${pc.cyan(result.projectType)}`,
|
|
399
|
-
`Styling: ${pc.cyan(result.selections.styling)}`,
|
|
400
|
-
`UI: ${pc.cyan(result.selections.ui)}`,
|
|
401
|
-
`State: ${pc.cyan(result.selections.state)}`,
|
|
402
|
-
`Routing: ${pc.cyan(result.selections.routing)}`
|
|
403
|
-
];
|
|
404
|
-
p.note(summaryItems.join("\n"), "\u{1F4CB} Configuration");
|
|
405
|
-
const fileTree = generateFileTree(result.selections);
|
|
406
|
-
p.note(fileTree, "\u{1F4C2} Files to be created");
|
|
407
|
-
const confirmed = await p.confirm({
|
|
408
|
-
message: "Create project with these settings?"
|
|
409
|
-
});
|
|
410
|
-
if (p.isCancel(confirmed) || !confirmed) {
|
|
411
|
-
p.cancel("Project creation cancelled.");
|
|
412
|
-
process.exit(0);
|
|
413
|
-
}
|
|
414
|
-
const startTime = Date.now();
|
|
415
|
-
await setup({
|
|
416
|
-
selections: result.selections,
|
|
417
|
-
targetDir: options.dir,
|
|
418
|
-
cicd: options.cicd
|
|
1826
|
+
`:`import { render, screen } from '@testing-library/react';
|
|
1827
|
+
import { ${o} } from '${n}';
|
|
1828
|
+
|
|
1829
|
+
describe('${o}', () => {
|
|
1830
|
+
it('should render correctly', () => {
|
|
1831
|
+
render(<${o} />);
|
|
1832
|
+
expect(screen.getByText('${e}')).toBeInTheDocument();
|
|
419
1833
|
});
|
|
420
|
-
const duration = ((Date.now() - startTime) / 1e3).toFixed(2);
|
|
421
|
-
p.outro(pc.green(`\u2728 Project created successfully in ${duration}s!`));
|
|
422
|
-
console.log();
|
|
423
|
-
console.log(pc.dim("Next steps:"));
|
|
424
|
-
console.log(pc.dim(` cd ${result.projectName}`));
|
|
425
|
-
console.log(pc.dim(" npm install"));
|
|
426
|
-
console.log(pc.dim(" npm run dev"));
|
|
427
|
-
console.log();
|
|
428
|
-
console.log(pc.cyan("Happy coding! \u{1F680}"));
|
|
429
|
-
console.log();
|
|
430
1834
|
});
|
|
431
|
-
|
|
432
|
-
|
|
1835
|
+
`},bn=(e,t)=>`${t==="css-modules"?".container":`.${e.toLowerCase()}`} {
|
|
1836
|
+
/* Add styles here */
|
|
1837
|
+
}
|
|
1838
|
+
`,Cn=(e,t)=>{let r=t==="page"?`${e}Page`:e;return`export { ${r}, default } from './${r}';
|
|
1839
|
+
`},Us=(e,t)=>`import type { Meta, StoryObj } from '@storybook/react';
|
|
1840
|
+
import { ${e} } from './${e}';
|
|
1841
|
+
|
|
1842
|
+
const meta${t?": Meta<typeof "+e+">":""} = {
|
|
1843
|
+
title: 'Components/${e}',
|
|
1844
|
+
component: ${e},
|
|
1845
|
+
tags: ['autodocs'],
|
|
1846
|
+
parameters: {
|
|
1847
|
+
layout: 'centered',
|
|
1848
|
+
},
|
|
1849
|
+
};
|
|
1850
|
+
|
|
1851
|
+
export default meta;
|
|
1852
|
+
${t?"type Story = StoryObj<typeof meta>;":""}
|
|
1853
|
+
|
|
1854
|
+
export const Default${t?": Story":""} = {
|
|
1855
|
+
args: {
|
|
1856
|
+
// Add default props here
|
|
1857
|
+
},
|
|
1858
|
+
};
|
|
1859
|
+
`,xe=e=>e.replace(/[-_](.)/g,(t,r)=>r.toUpperCase()).replace(/^(.)/,(t,r)=>r.toUpperCase()),_s=e=>{let t=xe(e);return t.charAt(0).toLowerCase()+t.slice(1)},Ls=e=>{let t=_s(e);return t.startsWith("use")?t:`use${xe(e)}`},Me=e=>{switch(e){case"component":return"src/components";case"hook":return"src/hooks";case"page":return"src/pages";case"feature":return"src/features";default:return"src"}},jt=(e,t)=>t?e?"tsx":"jsx":e?"ts":"js",zs=e=>{switch(e){case"scss":return"scss";case"css-modules":return"module.css";default:return"css"}},Ms=async e=>{let t=[],r=[],n=xe(e.name),o=e.typescript??!0,s=F.join(e.targetDir||Me("component"),n);try{await m(s);let i=jt(o,!0),l=F.join(s,`${n}.${i}`);if(await p(l,Ns(n,o,e.styling)),t.push(l),e.withStyles&&e.styling&&e.styling!=="tailwind"){let u=zs(e.styling),a=F.join(s,`${n}.${u}`);await p(a,bn(n,e.styling)),t.push(a)}if(e.withTests){let u=F.join(s,`${n}.test.${i}`);await p(u,Pt(n,"component",o)),t.push(u)}if(e.withIndex){let u=F.join(s,`index.${o?"ts":"js"}`);await p(u,Cn(n,"component")),t.push(u)}if(e.withStory){let u=F.join(s,`${n}.stories.${i}`);await p(u,Us(n,o)),t.push(u)}return{success:!0,files:t,errors:r}}catch(i){return r.push(i instanceof Error?i.message:String(i)),{success:!1,files:t,errors:r}}},Bs=async e=>{let t=[],r=[],n=Ls(e.name),o=e.typescript??!0,s=e.targetDir||Me("hook");try{await m(s);let i=jt(o,!1),l=F.join(s,`${n}.${i}`);if(await p(l,As(n,o)),t.push(l),e.withTests){let u=F.join(s,`${n}.test.${i}`);await p(u,Pt(n,"hook",o)),t.push(u)}return{success:!0,files:t,errors:r}}catch(i){return r.push(i instanceof Error?i.message:String(i)),{success:!1,files:t,errors:r}}},Gs=async e=>{let t=[],r=[],n=xe(e.name),o=e.typescript??!0,s=F.join(e.targetDir||Me("page"),n);try{await m(s);let i=jt(o,!0),l=F.join(s,`${n}Page.${i}`);if(await p(l,Ds(n,o,e.styling)),t.push(l),e.withStyles&&e.styling==="css-modules"){let u=F.join(s,`${n}Page.module.css`);await p(u,bn(`${n}Page`,"css-modules")),t.push(u)}if(e.withTests){let u=F.join(s,`${n}Page.test.${i}`);await p(u,Pt(n,"page",o)),t.push(u)}if(e.withIndex){let u=F.join(s,`index.${o?"ts":"js"}`);await p(u,Cn(n,"page")),t.push(u)}return{success:!0,files:t,errors:r}}catch(i){return r.push(i instanceof Error?i.message:String(i)),{success:!1,files:t,errors:r}}},Ws=async e=>{let t=[],r=[],n=xe(e.name),o=e.typescript??!0,s=F.join(e.targetDir||Me("feature"),n.toLowerCase()),i=o?"ts":"js";try{await m(F.join(s,"components")),await m(F.join(s,"hooks")),o&&await m(F.join(s,"types"));let l=F.join(s,`index.${i}`);if(await p(l,Es(n,o)),t.push(l),o){let w=F.join(s,"types",`index.${i}`);await p(w,Os(n)),t.push(w)}let u=F.join(s,"components",`index.${i}`);await p(u,`// ${n} Components
|
|
1860
|
+
// Export components here
|
|
1861
|
+
`),t.push(u);let a=F.join(s,"hooks",`index.${i}`);return await p(a,`// ${n} Hooks
|
|
1862
|
+
// Export hooks here
|
|
1863
|
+
`),t.push(a),{success:!0,files:t,errors:r}}catch(l){return r.push(l instanceof Error?l.message:String(l)),{success:!1,files:t,errors:r}}},Be=async e=>{let{type:t,silent:r}=e,n;switch(t){case"component":n=await Ms(e);break;case"hook":n=await Bs(e);break;case"page":n=await Gs(e);break;case"feature":n=await Ws(e);break;default:return{success:!1,files:[],errors:[`Unknown generator type: ${t}`]}}if(n.success){let o=`generate ${t} ${e.name}`;await yn(o,n.files)}return r||(n.success?(c.success(`
|
|
1864
|
+
\u2713 Generated ${t}: ${e.name}
|
|
1865
|
+
`),c.dim("Created files:"),n.files.forEach(o=>{c.cyan(` ${o}`)}),c.newline()):(c.error(`
|
|
1866
|
+
\u2717 Failed to generate ${t}: ${e.name}
|
|
1867
|
+
`),n.errors.forEach(o=>{c.error(` ${o}`)}),c.newline())),n};var kn={name:"generate",alias:"g",description:"Generate a component, hook, page, or feature",args:[{name:"<type>",description:"Type to generate (component, hook, page, feature)",required:!0},{name:"<name>",description:"Name of the item to generate",required:!0}],options:[{flags:"-d, --dir <directory>",description:"Target directory"},{flags:"--js",description:"Use JavaScript instead of TypeScript"},{flags:"--with-tests",description:"Include test file"},{flags:"--with-styles",description:"Include styles file"},{flags:"--style <type>",description:"Styling solution (css, scss, tailwind, css-modules)",defaultValue:"css"},{flags:"--with-index",description:"Include index file for exports"}],action:async(e,t,r)=>{let n=["component","hook","page","feature"];n.includes(e)||(console.log(xn.red(`
|
|
1868
|
+
\u2717 Invalid type: ${e}`)),console.log(xn.dim(` Valid types: ${n.join(", ")}
|
|
1869
|
+
`)),process.exit(1)),await Be({type:e,name:t,targetDir:r.dir,typescript:!r.js,withTests:r.withTests,withStyles:r.withStyles,styling:r.style,withIndex:r.withIndex})}},Sn={name:"gc",description:"Alias for: generate component",args:[{name:"<name>",description:"Component name",required:!0}],options:[{flags:"-d, --dir <directory>",description:"Target directory"},{flags:"--js",description:"Use JavaScript instead of TypeScript"},{flags:"--with-tests",description:"Include test file"}],action:async(e,t)=>{await Be({type:"component",name:e,targetDir:t.dir,typescript:!t.js,withTests:t.withTests,withIndex:!0})}},Pn={name:"gh",description:"Alias for: generate hook",args:[{name:"<name>",description:"Hook name",required:!0}],options:[{flags:"-d, --dir <directory>",description:"Target directory"},{flags:"--js",description:"Use JavaScript instead of TypeScript"},{flags:"--with-tests",description:"Include test file"}],action:async(e,t)=>{await Be({type:"hook",name:e,targetDir:t.dir,typescript:!t.js,withTests:t.withTests})}};E();import{execa as Js}from"execa";import Ge from"node:path";import Hs from"picocolors";var jn={name:"health",description:"Analyze project health, security, and optimizations",action:async()=>{c.cyan(`
|
|
1870
|
+
\u{1FA7A} NEXO Project Health Check
|
|
1871
|
+
`);let e=process.cwd();if(!await I(Ge.join(e,"package.json"))){c.error("No package.json found. Run this in a project root.");return}try{let t=await x({projectPath:e});c.info(`Project: ${Hs.bold(t.name||"unnamed")} v${t.version||"0.0.0"}`),c.newline(),c.dim("Running security audit (npm audit)...");try{let{stdout:i}=await Js("npm",["audit","--json"],{reject:!1}),u=JSON.parse(i).metadata?.vulnerabilities||{},a=Object.values(u).reduce((w,h)=>w+h,0);a===0?c.success("\u2713 Security: No known vulnerabilities found."):(c.warn(`\u26A0\uFE0F Security: Found ${a} vulnerabilities.`),(u.high||u.critical)&&c.error(` Critical: ${u.critical||0}, High: ${u.high||0}`),c.dim(' Run "npm audit fix" to resolve.'))}catch{c.warn("Could not complete security audit.")}c.newline(),c.dim("Checking best practices..."),await I(Ge.join(e,"package-lock.json"))||await I(Ge.join(e,"yarn.lock"))||await I(Ge.join(e,"pnpm-lock.yaml"))?c.success("\u2713 Lockfile present"):c.warn("\u26A0\uFE0F No lockfile found (package-lock.json, yarn.lock, etc)."),t.scripts&&(t.scripts.test?c.success("\u2713 Test script found"):c.warn("\u25CB No test script defined"),t.scripts.lint?c.success("\u2713 Lint script found"):c.warn("\u25CB No lint script defined")),c.newline(),c.dim("Bundle Analysis (Heuristic)...");let n=["three","d3","lodash","moment","framer-motion"],o={...t.dependencies,...t.devDependencies},s=n.filter(i=>o[i]);s.length>0?(c.info(`\u2139\uFE0F Detected heavy dependencies: ${s.join(", ")}`),c.dim(" Consider using light-weight alternatives or tree-shaking.")):c.success("\u2713 No obviously heavy dependencies detected."),c.newline()}catch(t){c.error("Health check failed: "+(t instanceof Error?t.message:String(t)))}}};E();import $t from"node:path";var $n={name:"migrate",description:"Initialize NEXO in an existing project",action:async()=>{c.info("Migrating project to NEXO...");let e=process.cwd();if(!await I($t.join(e,"package.json"))){c.error("No package.json found. Please run this command in a project root.");return}if(await I($t.join(e,"nexo.config.json"))){c.warn("nexo.config.json already exists.");return}try{let t=await x({projectPath:e}),r=!!(t.dependencies?.react||t.devDependencies?.react),n=!!(t.dependencies?.next||t.devDependencies?.next),o=!!t.devDependencies?.typescript,s=!!t.devDependencies?.tailwindcss,i={framework:n?"next":r?"react":"unknown",variant:o?"ts":"js",styling:s?"tailwind":"css-modules",ui:"none",forms:"none",state:"none",routing:"none"};await p($t.join(e,"nexo.config.json"),JSON.stringify(i,null,2)),c.success(`
|
|
1872
|
+
\u2728 Project migrated! Created nexo.config.json`),c.info('You can now run "nexo generate" commands.')}catch(t){c.error("Migration failed: "+(t instanceof Error?t.message:String(t)))}}};var Tn={name:"presets",description:"List available project presets",action:async()=>{c.cyan(`
|
|
1873
|
+
\u{1F4E6} Available Presets:
|
|
1874
|
+
`),c.dim(" saas - Full-stack SaaS with auth and API"),c.dim(" dashboard - Admin dashboard with charts"),c.dim(" landing - Fast, SEO-optimized marketing page"),c.dim(" minimal - Bare-bones React + TypeScript"),c.newline(),c.dim(`Usage: nexo create my-app --preset=saas
|
|
1875
|
+
`)}};E();import*as We from"@clack/prompts";import qs from"node:path";var In={name:"undo",description:"Undo the last generation command",action:async()=>{let e=await vn();if(!e){c.warn("No history found. Nothing to undo.");return}c.warn(`
|
|
1876
|
+
Usage: Undo "${e.action}"?`),c.dim(`Timestamp: ${e.timestamp}`),c.dim("Files to delete:"),e.files.forEach(n=>c.dim(` - ${n}`)),c.newline();let t=await We.confirm({message:"Are you sure you want to delete these files?",initialValue:!1});if(We.isCancel(t)||!t){c.info("Undo cancelled.");return}let r=0;for(let n of e.files)try{await ke(qs.resolve(process.cwd(),n)),r++}catch{c.warn(`Could not delete ${n}`)}await wn(),c.success(`
|
|
1877
|
+
\u2728 Undid "${e.action}". Deleted ${r} files.`)}};import{execa as Fn}from"execa";var Rn={name:"update",description:"Update NEXO CLI to the latest version",action:async()=>{c.info("Checking for updates...");try{let{stdout:e}=await Fn("npm",["view","create-nexo","version"]),t=e.trim();c.info(`Latest version: ${t}`),c.info("Updating NEXO CLI..."),await Fn("npm",["install","-g","create-nexo@latest"],{stdio:"inherit"}),c.success(`
|
|
1878
|
+
\u2728 NEXO CLI updated to v${t}!`)}catch(e){c.error("Failed to update NEXO CLI."),e instanceof Error&&c.dim(e.message)}}};import*as q from"@clack/prompts";import g from"picocolors";import*as O from"@clack/prompts";import Tt from"picocolors";var Nn={webapp:{name:"Web Application",description:"Interactive web application with forms and state",icon:"\u{1F310}",recommendations:{variant:"ts",styling:"tailwind",ui:"shadcn",forms:"rhf-zod",state:"zustand",routing:"react-router",dataFetching:"tanstack-query",icons:"lucide",structure:"feature-based"},features:["TypeScript for type safety","Tailwind CSS + shadcn/ui","Form handling with validation","State management","Client-side routing","Data fetching with caching"]},dashboard:{name:"Admin Dashboard",description:"Data-rich admin panel with charts and tables",icon:"\u{1F4CA}",recommendations:{variant:"ts",styling:"tailwind",ui:"shadcn",forms:"rhf-zod",state:"redux",routing:"react-router",dataFetching:"tanstack-query",icons:"lucide",structure:"fsd"},features:["TypeScript for type safety","Tailwind CSS + shadcn/ui","Redux for complex state","FSD architecture","Data fetching with caching","Ready for charts integration"]},landing:{name:"Landing Page",description:"Fast, SEO-optimized marketing page",icon:"\u{1F680}",recommendations:{variant:"ts",styling:"tailwind",ui:"none",forms:"none",state:"none",routing:"none",dataFetching:"none",icons:"lucide",structure:"simple"},features:["TypeScript for type safety","Tailwind CSS for styling","Minimal dependencies","Fast load times","Simple structure","Easy to customize"]},"api-client":{name:"API Client",description:"Application consuming external APIs",icon:"\u{1F50C}",recommendations:{variant:"ts",styling:"tailwind",ui:"mantine",forms:"rhf-zod",state:"zustand",routing:"react-router",dataFetching:"tanstack-query",icons:"lucide",structure:"feature-based"},features:["TypeScript for type safety","TanStack Query for API calls","Zustand for client state","Mantine UI components","Form handling","Feature-based structure"]},portfolio:{name:"Portfolio Website",description:"Personal portfolio or showcase site",icon:"\u{1F464}",recommendations:{variant:"ts",styling:"tailwind",ui:"none",forms:"none",state:"none",routing:"react-router",dataFetching:"none",icons:"lucide",structure:"simple"},features:["TypeScript for type safety","Tailwind CSS for styling","Client-side routing","Lucide icons","Simple structure","Easy to personalize"]},ecommerce:{name:"E-Commerce",description:"Online store with cart and checkout",icon:"\u{1F6D2}",recommendations:{variant:"ts",styling:"tailwind",ui:"shadcn",forms:"rhf-zod",state:"zustand",routing:"tanstack-router",dataFetching:"tanstack-query",icons:"lucide",structure:"fsd",auth:"jwt"},features:["TypeScript for type safety","Tailwind CSS + shadcn/ui","Zustand for cart state","TanStack Router (type-safe)","TanStack Query for products","JWT authentication ready","FSD architecture"]}},Vs=e=>e.map(t=>` ${Tt.green("\u2713")} ${t}`).join(`
|
|
1879
|
+
`),An=async()=>{c.print(Tt.cyan(`
|
|
1880
|
+
\u{1F9D9} Welcome to NEXO Wizard!
|
|
1881
|
+
`)),c.dim(`Let me help you set up your project.
|
|
1882
|
+
`);let e=await O.text({message:"What is your project name?",placeholder:"my-awesome-app",defaultValue:"my-app",validate:i=>{let l=i||"my-app";if(!/^[a-z0-9-_]+$/i.test(l))return"Project name can only contain letters, numbers, hyphens, and underscores"}});if(O.isCancel(e))return O.cancel("Wizard cancelled."),null;let t=await O.select({message:"What are you building?",options:Object.entries(Nn).map(([i,l])=>({value:i,label:`${l.icon} ${l.name}`,hint:l.description}))});if(O.isCancel(t))return O.cancel("Wizard cancelled."),null;let r=Nn[t];console.log(),O.note(`${Tt.bold("Recommended stack for "+r.name+":")}
|
|
1883
|
+
|
|
1884
|
+
${Vs(r.features)}`,"\u{1F4E6} Configuration");let n=await O.confirm({message:"Use these recommended settings?",initialValue:!0});if(O.isCancel(n))return O.cancel("Wizard cancelled."),null;let o=r.recommendations,s={projectName:e,framework:"react",variant:o.variant||"ts",language:(o.variant||"ts").startsWith("ts")?"typescript":"javascript",styling:o.styling||"tailwind",ui:o.ui||"none",forms:o.forms||"none",state:o.state||"none",routing:o.routing||"none",dataFetching:o.dataFetching||"none",icons:o.icons||"none",structure:o.structure||"simple",i18n:o.i18n||"none",auth:o.auth||"none"};return{projectName:e,projectType:t,selections:s,useRecommended:n}};$();var Dn={name:"wizard",alias:"w",description:"Guided project creation for beginners",options:[{flags:"-d, --dir <directory>",description:"Target directory",defaultValue:"."},{flags:"--cicd",description:"Add CI/CD configuration (GitHub Actions)"}],action:async e=>{let t=`
|
|
1885
|
+
${g.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")}
|
|
1886
|
+
${g.cyan("\u2551")} ${g.cyan("\u2551")}
|
|
1887
|
+
${g.cyan("\u2551")} ${g.bold("\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ")} ${g.cyan("\u2551")}
|
|
1888
|
+
${g.cyan("\u2551")} ${g.bold("\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557")} ${g.cyan("\u2551")}
|
|
1889
|
+
${g.cyan("\u2551")} ${g.bold("\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551")} ${g.cyan("\u2551")}
|
|
1890
|
+
${g.cyan("\u2551")} ${g.bold("\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551")} ${g.cyan("\u2551")}
|
|
1891
|
+
${g.cyan("\u2551")} ${g.bold("\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2554\u255D \u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D")} ${g.cyan("\u2551")}
|
|
1892
|
+
${g.cyan("\u2551")} ${g.bold("\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D ")} ${g.cyan("\u2551")}
|
|
1893
|
+
${g.cyan("\u2551")} ${g.cyan("\u2551")}
|
|
1894
|
+
${g.cyan("\u2551")} ${g.dim("N - Next-generation")} ${g.cyan("\u2551")}
|
|
1895
|
+
${g.cyan("\u2551")} ${g.dim("E - Extensible")} ${g.cyan("\u2551")}
|
|
1896
|
+
${g.cyan("\u2551")} ${g.dim("X - X-framework")} ${g.cyan("\u2551")}
|
|
1897
|
+
${g.cyan("\u2551")} ${g.dim("O - Orchestrator")} ${g.cyan("\u2551")}
|
|
1898
|
+
${g.cyan("\u2551")} ${g.cyan("\u2551")}
|
|
1899
|
+
${g.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")}
|
|
1900
|
+
`;console.log(t);let r=await An();r||process.exit(0);let n=[`Project: ${g.cyan(r.projectName)}`,`Type: ${g.cyan(r.projectType)}`,`Styling: ${g.cyan(r.selections.styling)}`,`UI: ${g.cyan(r.selections.ui)}`,`State: ${g.cyan(r.selections.state)}`,`Routing: ${g.cyan(r.selections.routing)}`];q.note(n.join(`
|
|
1901
|
+
`),"\u{1F4CB} Configuration");let o=X(r.selections);q.note(o,"\u{1F4C2} Files to be created");let s=await q.confirm({message:"Create project with these settings?"});(q.isCancel(s)||!s)&&(q.cancel("Project creation cancelled."),process.exit(0));let i=Date.now();await Ce({selections:r.selections,targetDir:e.dir,cicd:e.cicd});let l=((Date.now()-i)/1e3).toFixed(2);q.outro(g.green(`\u2728 Project created successfully in ${l}s!`)),console.log(),console.log(g.dim("Next steps:")),console.log(g.dim(` cd ${r.projectName}`)),console.log(g.dim(" npm install")),console.log(g.dim(" npm run dev")),console.log(),console.log(g.cyan("Happy coding! \u{1F680}")),console.log()}};var En=[hn,jn,fn,Tn,kn,Sn,Pn,Dn,gn,Et,Rn,In,$n];var Xs=Qs(import.meta.url),{version:Zs}=Xs("../../package.json"),It=new Ks;It.name("nexo").description("NEXO is a next-generation, extensible CLI for scaffolding and orchestrating modern frontend projects").version(Zs);for(let e of En){let t=It.command(e.name,{isDefault:e.isDefault});if(e.alias&&t.alias(e.alias),t.description(e.description),e.args)for(let r of e.args)t.argument(r.name,r.description);if(e.options)for(let r of e.options)r.defaultValue!==void 0?t.option(r.flags,r.description,r.defaultValue):t.option(r.flags,r.description);t.action(e.action)}It.parse();
|