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.
Files changed (269) hide show
  1. package/dist/bin/nexo.js +1889 -420
  2. package/dist/index.js +1808 -96
  3. package/package.json +8 -6
  4. package/dist/api/index.d.ts +0 -196
  5. package/dist/api/index.d.ts.map +0 -1
  6. package/dist/api/index.js +0 -233
  7. package/dist/api/index.js.map +0 -7
  8. package/dist/bin/nexo.d.ts +0 -2
  9. package/dist/bin/nexo.d.ts.map +0 -1
  10. package/dist/bin/nexo.js.map +0 -7
  11. package/dist/configurators/core/framework.d.ts +0 -3
  12. package/dist/configurators/core/framework.d.ts.map +0 -1
  13. package/dist/configurators/core/framework.js +0 -66
  14. package/dist/configurators/core/framework.js.map +0 -7
  15. package/dist/configurators/core/index.d.ts +0 -4
  16. package/dist/configurators/core/index.d.ts.map +0 -1
  17. package/dist/configurators/core/index.js +0 -9
  18. package/dist/configurators/core/index.js.map +0 -7
  19. package/dist/configurators/core/language.d.ts +0 -3
  20. package/dist/configurators/core/language.d.ts.map +0 -1
  21. package/dist/configurators/core/language.js +0 -58
  22. package/dist/configurators/core/language.js.map +0 -7
  23. package/dist/configurators/core/variant.d.ts +0 -3
  24. package/dist/configurators/core/variant.d.ts.map +0 -1
  25. package/dist/configurators/core/variant.js +0 -22
  26. package/dist/configurators/core/variant.js.map +0 -7
  27. package/dist/configurators/factory.d.ts +0 -36
  28. package/dist/configurators/factory.d.ts.map +0 -1
  29. package/dist/configurators/factory.js +0 -48
  30. package/dist/configurators/factory.js.map +0 -7
  31. package/dist/configurators/index.d.ts +0 -5
  32. package/dist/configurators/index.d.ts.map +0 -1
  33. package/dist/configurators/index.js +0 -5
  34. package/dist/configurators/index.js.map +0 -7
  35. package/dist/configurators/project/ai-instructions.d.ts +0 -7
  36. package/dist/configurators/project/ai-instructions.d.ts.map +0 -1
  37. package/dist/configurators/project/ai-instructions.js +0 -540
  38. package/dist/configurators/project/ai-instructions.js.map +0 -7
  39. package/dist/configurators/project/auth.d.ts +0 -3
  40. package/dist/configurators/project/auth.d.ts.map +0 -1
  41. package/dist/configurators/project/auth.js +0 -44
  42. package/dist/configurators/project/auth.js.map +0 -7
  43. package/dist/configurators/project/cicd.d.ts +0 -30
  44. package/dist/configurators/project/cicd.d.ts.map +0 -1
  45. package/dist/configurators/project/cicd.js +0 -298
  46. package/dist/configurators/project/cicd.js.map +0 -7
  47. package/dist/configurators/project/i18n.d.ts +0 -3
  48. package/dist/configurators/project/i18n.d.ts.map +0 -1
  49. package/dist/configurators/project/i18n.js +0 -83
  50. package/dist/configurators/project/i18n.js.map +0 -7
  51. package/dist/configurators/project/index.d.ts +0 -7
  52. package/dist/configurators/project/index.d.ts.map +0 -1
  53. package/dist/configurators/project/index.js +0 -16
  54. package/dist/configurators/project/index.js.map +0 -7
  55. package/dist/configurators/project/mandatory.d.ts +0 -3
  56. package/dist/configurators/project/mandatory.d.ts.map +0 -1
  57. package/dist/configurators/project/mandatory.js +0 -160
  58. package/dist/configurators/project/mandatory.js.map +0 -7
  59. package/dist/configurators/project/structure.d.ts +0 -3
  60. package/dist/configurators/project/structure.d.ts.map +0 -1
  61. package/dist/configurators/project/structure.js +0 -79
  62. package/dist/configurators/project/structure.js.map +0 -7
  63. package/dist/configurators/state/animation.d.ts +0 -2
  64. package/dist/configurators/state/animation.d.ts.map +0 -1
  65. package/dist/configurators/state/animation.js +0 -18
  66. package/dist/configurators/state/animation.js.map +0 -7
  67. package/dist/configurators/state/dataFetching.d.ts +0 -3
  68. package/dist/configurators/state/dataFetching.d.ts.map +0 -1
  69. package/dist/configurators/state/dataFetching.js +0 -36
  70. package/dist/configurators/state/dataFetching.js.map +0 -7
  71. package/dist/configurators/state/forms.d.ts +0 -2
  72. package/dist/configurators/state/forms.d.ts.map +0 -1
  73. package/dist/configurators/state/forms.js +0 -31
  74. package/dist/configurators/state/forms.js.map +0 -7
  75. package/dist/configurators/state/index.d.ts +0 -6
  76. package/dist/configurators/state/index.d.ts.map +0 -1
  77. package/dist/configurators/state/index.js +0 -13
  78. package/dist/configurators/state/index.js.map +0 -7
  79. package/dist/configurators/state/routing.d.ts +0 -2
  80. package/dist/configurators/state/routing.d.ts.map +0 -1
  81. package/dist/configurators/state/routing.js +0 -17
  82. package/dist/configurators/state/routing.js.map +0 -7
  83. package/dist/configurators/state/state.d.ts +0 -3
  84. package/dist/configurators/state/state.d.ts.map +0 -1
  85. package/dist/configurators/state/state.js +0 -94
  86. package/dist/configurators/state/state.js.map +0 -7
  87. package/dist/configurators/styling/icons.d.ts +0 -2
  88. package/dist/configurators/styling/icons.d.ts.map +0 -1
  89. package/dist/configurators/styling/icons.js +0 -25
  90. package/dist/configurators/styling/icons.js.map +0 -7
  91. package/dist/configurators/styling/index.d.ts +0 -4
  92. package/dist/configurators/styling/index.d.ts.map +0 -1
  93. package/dist/configurators/styling/index.js +0 -9
  94. package/dist/configurators/styling/index.js.map +0 -7
  95. package/dist/configurators/styling/styling.d.ts +0 -3
  96. package/dist/configurators/styling/styling.d.ts.map +0 -1
  97. package/dist/configurators/styling/styling.js +0 -141
  98. package/dist/configurators/styling/styling.js.map +0 -7
  99. package/dist/configurators/styling/ui.d.ts +0 -3
  100. package/dist/configurators/styling/ui.d.ts.map +0 -1
  101. package/dist/configurators/styling/ui.js +0 -179
  102. package/dist/configurators/styling/ui.js.map +0 -7
  103. package/dist/constants/index.d.ts +0 -94
  104. package/dist/constants/index.d.ts.map +0 -1
  105. package/dist/constants/index.js +0 -94
  106. package/dist/constants/index.js.map +0 -7
  107. package/dist/core/config.d.ts +0 -62
  108. package/dist/core/config.d.ts.map +0 -1
  109. package/dist/core/config.js +0 -121
  110. package/dist/core/config.js.map +0 -7
  111. package/dist/core/index.d.ts +0 -7
  112. package/dist/core/index.d.ts.map +0 -1
  113. package/dist/core/index.js +0 -12
  114. package/dist/core/index.js.map +0 -7
  115. package/dist/core/lazy-loader.d.ts +0 -57
  116. package/dist/core/lazy-loader.d.ts.map +0 -1
  117. package/dist/core/lazy-loader.js +0 -211
  118. package/dist/core/lazy-loader.js.map +0 -7
  119. package/dist/core/parallel.d.ts +0 -29
  120. package/dist/core/parallel.d.ts.map +0 -1
  121. package/dist/core/parallel.js +0 -100
  122. package/dist/core/parallel.js.map +0 -7
  123. package/dist/core/presets.d.ts +0 -10
  124. package/dist/core/presets.d.ts.map +0 -1
  125. package/dist/core/presets.js +0 -76
  126. package/dist/core/presets.js.map +0 -7
  127. package/dist/core/prompts/core.d.ts +0 -18
  128. package/dist/core/prompts/core.d.ts.map +0 -1
  129. package/dist/core/prompts/core.js +0 -424
  130. package/dist/core/prompts/core.js.map +0 -7
  131. package/dist/core/prompts/filter.d.ts +0 -34
  132. package/dist/core/prompts/filter.d.ts.map +0 -1
  133. package/dist/core/prompts/filter.js +0 -28
  134. package/dist/core/prompts/filter.js.map +0 -7
  135. package/dist/core/prompts/index.d.ts +0 -10
  136. package/dist/core/prompts/index.d.ts.map +0 -1
  137. package/dist/core/prompts/index.js +0 -71
  138. package/dist/core/prompts/index.js.map +0 -7
  139. package/dist/core/prompts/optional.d.ts +0 -16
  140. package/dist/core/prompts/optional.d.ts.map +0 -1
  141. package/dist/core/prompts/optional.js +0 -290
  142. package/dist/core/prompts/optional.js.map +0 -7
  143. package/dist/core/prompts/utils.d.ts +0 -25
  144. package/dist/core/prompts/utils.d.ts.map +0 -1
  145. package/dist/core/prompts/utils.js +0 -25
  146. package/dist/core/prompts/utils.js.map +0 -7
  147. package/dist/core/prompts.d.ts +0 -6
  148. package/dist/core/prompts.d.ts.map +0 -1
  149. package/dist/core/prompts.js +0 -2
  150. package/dist/core/prompts.js.map +0 -7
  151. package/dist/core/setup.d.ts +0 -38
  152. package/dist/core/setup.d.ts.map +0 -1
  153. package/dist/core/setup.js +0 -110
  154. package/dist/core/setup.js.map +0 -7
  155. package/dist/core/wizard.d.ts +0 -39
  156. package/dist/core/wizard.d.ts.map +0 -1
  157. package/dist/core/wizard.js +0 -242
  158. package/dist/core/wizard.js.map +0 -7
  159. package/dist/errors/index.d.ts +0 -67
  160. package/dist/errors/index.d.ts.map +0 -1
  161. package/dist/errors/index.js +0 -213
  162. package/dist/errors/index.js.map +0 -7
  163. package/dist/errors/messages.d.ts +0 -56
  164. package/dist/errors/messages.d.ts.map +0 -1
  165. package/dist/errors/messages.js +0 -214
  166. package/dist/errors/messages.js.map +0 -7
  167. package/dist/generators/index.d.ts +0 -86
  168. package/dist/generators/index.d.ts.map +0 -1
  169. package/dist/generators/index.js +0 -364
  170. package/dist/generators/index.js.map +0 -7
  171. package/dist/index.d.ts +0 -16
  172. package/dist/index.d.ts.map +0 -1
  173. package/dist/index.js.map +0 -7
  174. package/dist/plugins/index.d.ts +0 -48
  175. package/dist/plugins/index.d.ts.map +0 -1
  176. package/dist/plugins/index.js +0 -25
  177. package/dist/plugins/index.js.map +0 -7
  178. package/dist/plugins/loader.d.ts +0 -38
  179. package/dist/plugins/loader.d.ts.map +0 -1
  180. package/dist/plugins/loader.js +0 -173
  181. package/dist/plugins/loader.js.map +0 -7
  182. package/dist/plugins/manager.d.ts +0 -32
  183. package/dist/plugins/manager.d.ts.map +0 -1
  184. package/dist/plugins/manager.js +0 -144
  185. package/dist/plugins/manager.js.map +0 -7
  186. package/dist/plugins/types.d.ts +0 -186
  187. package/dist/plugins/types.d.ts.map +0 -1
  188. package/dist/plugins/types.js +0 -1
  189. package/dist/plugins/types.js.map +0 -7
  190. package/dist/security/index.d.ts +0 -59
  191. package/dist/security/index.d.ts.map +0 -1
  192. package/dist/security/index.js +0 -189
  193. package/dist/security/index.js.map +0 -7
  194. package/dist/templates/entry.d.ts +0 -9
  195. package/dist/templates/entry.d.ts.map +0 -1
  196. package/dist/templates/entry.js +0 -24
  197. package/dist/templates/entry.js.map +0 -7
  198. package/dist/templates/index.d.ts +0 -7
  199. package/dist/templates/index.d.ts.map +0 -1
  200. package/dist/templates/index.js +0 -12
  201. package/dist/templates/index.js.map +0 -7
  202. package/dist/templates/main.d.ts +0 -6
  203. package/dist/templates/main.d.ts.map +0 -1
  204. package/dist/templates/main.js +0 -99
  205. package/dist/templates/main.js.map +0 -7
  206. package/dist/templates/readme.d.ts +0 -3
  207. package/dist/templates/readme.d.ts.map +0 -1
  208. package/dist/templates/readme.js +0 -145
  209. package/dist/templates/readme.js.map +0 -7
  210. package/dist/templates/styles.d.ts +0 -6
  211. package/dist/templates/styles.d.ts.map +0 -1
  212. package/dist/templates/styles.js +0 -206
  213. package/dist/templates/styles.js.map +0 -7
  214. package/dist/templates/welcome.d.ts +0 -10
  215. package/dist/templates/welcome.d.ts.map +0 -1
  216. package/dist/templates/welcome.js +0 -294
  217. package/dist/templates/welcome.js.map +0 -7
  218. package/dist/types/index.d.ts +0 -51
  219. package/dist/types/index.d.ts.map +0 -1
  220. package/dist/types/index.js +0 -1
  221. package/dist/types/index.js.map +0 -7
  222. package/dist/utils/batch-writer.d.ts +0 -101
  223. package/dist/utils/batch-writer.d.ts.map +0 -1
  224. package/dist/utils/batch-writer.js +0 -155
  225. package/dist/utils/batch-writer.js.map +0 -7
  226. package/dist/utils/cache.d.ts +0 -60
  227. package/dist/utils/cache.d.ts.map +0 -1
  228. package/dist/utils/cache.js +0 -114
  229. package/dist/utils/cache.js.map +0 -7
  230. package/dist/utils/detection.d.ts +0 -4
  231. package/dist/utils/detection.d.ts.map +0 -1
  232. package/dist/utils/detection.js +0 -36
  233. package/dist/utils/detection.js.map +0 -7
  234. package/dist/utils/fileTree.d.ts +0 -3
  235. package/dist/utils/fileTree.d.ts.map +0 -1
  236. package/dist/utils/fileTree.js +0 -84
  237. package/dist/utils/fileTree.js.map +0 -7
  238. package/dist/utils/fs.d.ts +0 -22
  239. package/dist/utils/fs.d.ts.map +0 -1
  240. package/dist/utils/fs.js +0 -79
  241. package/dist/utils/fs.js.map +0 -7
  242. package/dist/utils/helpers.d.ts +0 -91
  243. package/dist/utils/helpers.d.ts.map +0 -1
  244. package/dist/utils/helpers.js +0 -154
  245. package/dist/utils/helpers.js.map +0 -7
  246. package/dist/utils/index.d.ts +0 -10
  247. package/dist/utils/index.d.ts.map +0 -1
  248. package/dist/utils/index.js +0 -15
  249. package/dist/utils/index.js.map +0 -7
  250. package/dist/utils/logger.d.ts +0 -98
  251. package/dist/utils/logger.d.ts.map +0 -1
  252. package/dist/utils/logger.js +0 -159
  253. package/dist/utils/logger.js.map +0 -7
  254. package/dist/utils/package-manager.d.ts +0 -26
  255. package/dist/utils/package-manager.d.ts.map +0 -1
  256. package/dist/utils/package-manager.js +0 -64
  257. package/dist/utils/package-manager.js.map +0 -7
  258. package/dist/utils/progress.d.ts +0 -85
  259. package/dist/utils/progress.d.ts.map +0 -1
  260. package/dist/utils/progress.js +0 -147
  261. package/dist/utils/progress.js.map +0 -7
  262. package/dist/utils/spinner.d.ts +0 -9
  263. package/dist/utils/spinner.d.ts.map +0 -1
  264. package/dist/utils/spinner.js +0 -59
  265. package/dist/utils/spinner.js.map +0 -7
  266. package/dist/validation/index.d.ts +0 -63
  267. package/dist/validation/index.d.ts.map +0 -1
  268. package/dist/validation/index.js +0 -234
  269. 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 * as p from "@clack/prompts";
3
- import { Command } from "commander";
4
- import path from "node:path";
5
- import pc from "picocolors";
6
- import {
7
- corePrompts,
8
- filterPromptByFramework,
9
- frameworkPrompt,
10
- optionalFeaturesPrompt,
11
- optionalSubPrompts
12
- } from "../core/prompts.js";
13
- import { setup } from "../core/setup.js";
14
- import { runWizard } from "../core/wizard.js";
15
- import { generate } from "../generators/index.js";
16
- import { detectProjectConfig, generateFileTree, isDirEmpty } from "../utils/index.js";
17
- import { log } from "../utils/logger.js";
18
- const VERSION = "1.0.0";
19
- const DEFAULT_PROJECT_NAME = "my-nexo-app";
20
- const banner = `
21
- ${pc.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")}
22
- ${pc.cyan("\u2551")} ${pc.cyan("\u2551")}
23
- ${pc.cyan("\u2551")} ${pc.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 ")} ${pc.cyan("\u2551")}
24
- ${pc.cyan("\u2551")} ${pc.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")} ${pc.cyan("\u2551")}
25
- ${pc.cyan("\u2551")} ${pc.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")} ${pc.cyan("\u2551")}
26
- ${pc.cyan("\u2551")} ${pc.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")} ${pc.cyan("\u2551")}
27
- ${pc.cyan("\u2551")} ${pc.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")} ${pc.cyan("\u2551")}
28
- ${pc.cyan("\u2551")} ${pc.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 ")} ${pc.cyan("\u2551")}
29
- ${pc.cyan("\u2551")} ${pc.cyan("\u2551")}
30
- ${pc.cyan("\u2551")} ${pc.dim("N - Next-generation")} ${pc.cyan("\u2551")}
31
- ${pc.cyan("\u2551")} ${pc.dim("E - Extensible")} ${pc.cyan("\u2551")}
32
- ${pc.cyan("\u2551")} ${pc.dim("X - X-framework")} ${pc.cyan("\u2551")}
33
- ${pc.cyan("\u2551")} ${pc.dim("O - Orchestrator")} ${pc.cyan("\u2551")}
34
- ${pc.cyan("\u2551")} ${pc.cyan("\u2551")}
35
- ${pc.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")}
36
- `;
37
- const program = new Command();
38
- program.name("nexo").description("NEXO is a next-generation, extensible CLI for scaffolding and orchestrating modern frontend projects").version(VERSION);
39
- program.command("create", { isDefault: true }).description("Create a new project").argument("[name]", "Project name").option("-d, --dir <directory>", "Target directory", ".").option("--dry-run", "Preview changes without creating files").option("--preset <preset>", "Use a preset configuration (saas, dashboard, landing)").option("--cicd", "Add CI/CD configuration (GitHub Actions)").option("--parallel", "Use parallel execution for faster setup").action(async (name, options) => {
40
- console.log(banner);
41
- console.log(pc.dim(" NEXO is a next-generation, extensible CLI for scaffolding and orchestrating modern frontend projects\n"));
42
- p.intro(pc.bgCyan(pc.black(" NEXO ")));
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 projectName = name || await p.text({
45
- message: "Project name:",
46
- placeholder: DEFAULT_PROJECT_NAME,
47
- defaultValue: DEFAULT_PROJECT_NAME,
48
- validate: (value) => {
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
- const fileTree = generateFileTree(tempSelections);
252
- p.note(fileTree, "\u{1F4C2} Files to be created");
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
- program.command("doctor").description("Check project health and dependencies").action(async () => {
326
- log.cyan("\n\u{1FA7A} NEXO Doctor\n");
327
- const checks = [
328
- { name: "Node.js version", check: () => process.version },
329
- { name: "npm version", check: () => "Available" },
330
- { name: "Git installed", check: () => "Available" }
331
- ];
332
- for (const { name, check } of checks) {
333
- try {
334
- const result = check();
335
- log.success(` ${name}: ${result}`);
336
- } catch {
337
- log.error(` ${name}: Not found`);
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
- log.success("\n\u2728 All checks passed!\n");
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
- program.command("presets").description("List available project presets").action(() => {
343
- log.cyan("\n\u{1F4E6} Available Presets:\n");
344
- log.dim(" saas - Full-stack SaaS with auth and API");
345
- log.dim(" dashboard - Admin dashboard with charts");
346
- log.dim(" landing - Fast, SEO-optimized marketing page");
347
- log.dim(" minimal - Bare-bones React + TypeScript");
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
- await generate({
361
- type,
362
- name,
363
- targetDir: options.dir,
364
- typescript: !options.js,
365
- withTests: options.withTests,
366
- withStyles: options.withStyles,
367
- styling: options.style,
368
- withIndex: options.withIndex
369
- });
370
- });
371
- program.command("gc").description("Alias for: generate component").argument("<name>", "Component name").option("-d, --dir <directory>", "Target directory").option("--js", "Use JavaScript instead of TypeScript").option("--with-tests", "Include test file").action(async (name, options) => {
372
- await generate({
373
- type: "component",
374
- name,
375
- targetDir: options.dir,
376
- typescript: !options.js,
377
- withTests: options.withTests,
378
- withIndex: true
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
- program.command("gh").description("Alias for: generate hook").argument("<name>", "Hook name").option("-d, --dir <directory>", "Target directory").option("--js", "Use JavaScript instead of TypeScript").option("--with-tests", "Include test file").action(async (name, options) => {
382
- await generate({
383
- type: "hook",
384
- name,
385
- targetDir: options.dir,
386
- typescript: !options.js,
387
- withTests: options.withTests
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
- program.command("wizard").alias("w").description("Guided project creation for beginners").option("-d, --dir <directory>", "Target directory", ".").option("--cicd", "Add CI/CD configuration (GitHub Actions)").action(async (options) => {
391
- console.log(banner);
392
- const result = await runWizard();
393
- if (!result) {
394
- process.exit(0);
395
- }
396
- const summaryItems = [
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
- program.parse();
432
- //# sourceMappingURL=nexo.js.map
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();