@tanstack/cta-engine 0.14.3 → 0.14.4

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 (343) hide show
  1. package/dist/add-ons.js +5 -91
  2. package/dist/add-to-app.js +171 -0
  3. package/dist/config-file.js +34 -11
  4. package/dist/constants.js +0 -2
  5. package/dist/create-app.js +142 -451
  6. package/dist/custom-add-ons/add-on.js +175 -0
  7. package/dist/custom-add-ons/shared.js +116 -0
  8. package/dist/custom-add-ons/starter.js +84 -0
  9. package/dist/environment.js +67 -44
  10. package/dist/file-helpers.js +165 -0
  11. package/dist/frameworks.js +92 -0
  12. package/dist/index.js +18 -1
  13. package/dist/integrations/git.js +4 -0
  14. package/dist/integrations/shadcn.js +33 -0
  15. package/dist/options.js +9 -333
  16. package/dist/package-json.js +48 -0
  17. package/dist/package-manager.js +51 -6
  18. package/dist/registry.js +56 -0
  19. package/dist/special-steps/index.js +24 -0
  20. package/dist/special-steps/rimraf-node-modules.js +16 -0
  21. package/dist/template-file.js +112 -0
  22. package/dist/types/add-ons.d.ts +3 -8
  23. package/dist/types/add-to-app.d.ts +17 -0
  24. package/dist/types/config-file.d.ts +7 -4
  25. package/dist/types/constants.d.ts +0 -3
  26. package/dist/types/create-app.d.ts +1 -7
  27. package/dist/types/custom-add-ons/add-on.d.ts +69 -0
  28. package/dist/types/custom-add-ons/shared.d.ts +15 -0
  29. package/dist/types/custom-add-ons/starter.d.ts +7 -0
  30. package/dist/types/environment.d.ts +2 -1
  31. package/dist/types/file-helpers.d.ts +15 -0
  32. package/dist/types/frameworks.d.ts +7 -0
  33. package/dist/types/index.d.ts +21 -1
  34. package/dist/types/integrations/git.d.ts +2 -0
  35. package/dist/types/integrations/shadcn.d.ts +2 -0
  36. package/dist/types/options.d.ts +2 -6
  37. package/dist/types/package-json.d.ts +7 -0
  38. package/dist/types/package-manager.d.ts +18 -1
  39. package/dist/types/registry.d.ts +25 -0
  40. package/dist/types/special-steps/index.d.ts +2 -0
  41. package/dist/types/special-steps/rimraf-node-modules.d.ts +2 -0
  42. package/dist/types/template-file.d.ts +2 -0
  43. package/dist/types/types.d.ts +788 -85
  44. package/dist/types/utils.d.ts +5 -0
  45. package/dist/types.js +65 -1
  46. package/dist/utils.js +9 -0
  47. package/package.json +9 -12
  48. package/src/add-ons.ts +7 -123
  49. package/src/add-to-app.ts +276 -0
  50. package/src/config-file.ts +51 -20
  51. package/src/constants.ts +0 -5
  52. package/src/create-app.ts +180 -730
  53. package/src/custom-add-ons/add-on.ts +261 -0
  54. package/src/custom-add-ons/shared.ts +160 -0
  55. package/src/custom-add-ons/starter.ts +126 -0
  56. package/src/environment.ts +80 -45
  57. package/src/file-helpers.ts +235 -0
  58. package/src/frameworks.ts +134 -0
  59. package/src/index.ts +85 -1
  60. package/src/integrations/git.ts +7 -0
  61. package/src/integrations/shadcn.ts +54 -0
  62. package/src/options.ts +8 -409
  63. package/src/package-json.ts +69 -0
  64. package/src/package-manager.ts +80 -9
  65. package/src/registry.ts +92 -0
  66. package/src/special-steps/index.ts +36 -0
  67. package/src/special-steps/rimraf-node-modules.ts +25 -0
  68. package/src/template-file.ts +150 -0
  69. package/src/types.ts +175 -87
  70. package/src/utils.ts +17 -0
  71. package/tests/add-ons.test.ts +67 -0
  72. package/tests/add-to-app.test.ts +358 -0
  73. package/tests/config-file.test.ts +105 -0
  74. package/tests/create-app.test.ts +120 -0
  75. package/tests/custom-add-ons/add-on.test.ts +12 -0
  76. package/tests/custom-add-ons/shared.test.ts +253 -0
  77. package/tests/custom-add-ons/starter.test.ts +58 -0
  78. package/tests/environment.test.ts +115 -0
  79. package/tests/file-helper.test.ts +90 -0
  80. package/tests/frameworks.test.ts +95 -0
  81. package/tests/index.test.ts +9 -0
  82. package/tests/integrations/git.test.ts +20 -0
  83. package/tests/integrations/shadcn.test.ts +91 -0
  84. package/tests/options.test.ts +42 -0
  85. package/tests/package-json.test.ts +63 -0
  86. package/tests/package-manager.test.ts +154 -0
  87. package/tests/setupVitest.ts +6 -0
  88. package/tests/template-file.test.ts +178 -0
  89. package/tests/utils.test.ts +23 -0
  90. package/vitest.config.ts +21 -0
  91. package/dist/add.js +0 -125
  92. package/dist/cli.js +0 -132
  93. package/dist/custom-add-on.js +0 -254
  94. package/dist/file-helper.js +0 -18
  95. package/dist/mcp.js +0 -229
  96. package/dist/templates.js +0 -6
  97. package/dist/toolchain.js +0 -6
  98. package/dist/types/add.d.ts +0 -3
  99. package/dist/types/cli.d.ts +0 -7
  100. package/dist/types/custom-add-on.d.ts +0 -3
  101. package/dist/types/file-helper.d.ts +0 -2
  102. package/dist/types/mcp.d.ts +0 -7
  103. package/dist/types/templates.d.ts +0 -1
  104. package/dist/types/toolchain.d.ts +0 -3
  105. package/src/add.ts +0 -186
  106. package/src/cli.ts +0 -210
  107. package/src/custom-add-on.ts +0 -325
  108. package/src/file-helper.ts +0 -20
  109. package/src/mcp.ts +0 -302
  110. package/src/templates.ts +0 -7
  111. package/src/toolchain.ts +0 -7
  112. package/templates/react/add-on/clerk/README.md +0 -3
  113. package/templates/react/add-on/clerk/assets/_dot_env.local.append +0 -2
  114. package/templates/react/add-on/clerk/assets/src/integrations/clerk/header-user.tsx +0 -19
  115. package/templates/react/add-on/clerk/assets/src/integrations/clerk/provider.tsx +0 -18
  116. package/templates/react/add-on/clerk/assets/src/routes/demo.clerk.tsx +0 -20
  117. package/templates/react/add-on/clerk/info.json +0 -13
  118. package/templates/react/add-on/clerk/package.json +0 -5
  119. package/templates/react/add-on/convex/README.md +0 -4
  120. package/templates/react/add-on/convex/assets/_dot_cursorrules.append +0 -93
  121. package/templates/react/add-on/convex/assets/_dot_env.local.append +0 -3
  122. package/templates/react/add-on/convex/assets/convex/products.ts +0 -8
  123. package/templates/react/add-on/convex/assets/convex/schema.ts +0 -10
  124. package/templates/react/add-on/convex/assets/src/integrations/convex/provider.tsx +0 -20
  125. package/templates/react/add-on/convex/assets/src/routes/demo.convex.tsx +0 -33
  126. package/templates/react/add-on/convex/info.json +0 -13
  127. package/templates/react/add-on/convex/package.json +0 -6
  128. package/templates/react/add-on/form/assets/src/components/demo.FormComponents.tsx.ejs +0 -300
  129. package/templates/react/add-on/form/assets/src/hooks/demo.form-context.ts +0 -4
  130. package/templates/react/add-on/form/assets/src/hooks/demo.form.ts +0 -22
  131. package/templates/react/add-on/form/assets/src/routes/demo.form.address.tsx.ejs +0 -213
  132. package/templates/react/add-on/form/assets/src/routes/demo.form.simple.tsx.ejs +0 -77
  133. package/templates/react/add-on/form/info.json +0 -26
  134. package/templates/react/add-on/form/package.json +0 -6
  135. package/templates/react/add-on/module-federation/assets/module-federation.config.js.ejs +0 -31
  136. package/templates/react/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
  137. package/templates/react/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -11
  138. package/templates/react/add-on/module-federation/info.json +0 -7
  139. package/templates/react/add-on/module-federation/package.json +0 -5
  140. package/templates/react/add-on/netlify/README.md +0 -11
  141. package/templates/react/add-on/netlify/info.json +0 -7
  142. package/templates/react/add-on/sentry/assets/_dot_cursorrules.append +0 -22
  143. package/templates/react/add-on/sentry/assets/_dot_env.local.append +0 -11
  144. package/templates/react/add-on/sentry/assets/src/app/global-middleware.ts +0 -11
  145. package/templates/react/add-on/sentry/assets/src/routes/demo.sentry.testing.tsx +0 -489
  146. package/templates/react/add-on/sentry/info.json +0 -14
  147. package/templates/react/add-on/sentry/package.json +0 -5
  148. package/templates/react/add-on/shadcn/README.md +0 -7
  149. package/templates/react/add-on/shadcn/assets/_dot_cursorrules.append +0 -7
  150. package/templates/react/add-on/shadcn/assets/components.json +0 -21
  151. package/templates/react/add-on/shadcn/assets/src/lib/utils.ts +0 -6
  152. package/templates/react/add-on/shadcn/assets/src/styles.css +0 -138
  153. package/templates/react/add-on/shadcn/info.json +0 -7
  154. package/templates/react/add-on/shadcn/package.json +0 -9
  155. package/templates/react/add-on/start/assets/_dot_gitignore.append +0 -2
  156. package/templates/react/add-on/start/assets/app.config.ts.ejs +0 -32
  157. package/templates/react/add-on/start/assets/src/api.ts +0 -6
  158. package/templates/react/add-on/start/assets/src/client.tsx.ejs +0 -33
  159. package/templates/react/add-on/start/assets/src/router.tsx.ejs +0 -48
  160. package/templates/react/add-on/start/assets/src/routes/api.demo-names.ts +0 -11
  161. package/templates/react/add-on/start/assets/src/routes/demo.start.api-request.tsx.ejs +0 -33
  162. package/templates/react/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +0 -50
  163. package/templates/react/add-on/start/assets/src/ssr.tsx.ejs +0 -30
  164. package/templates/react/add-on/start/info.json +0 -18
  165. package/templates/react/add-on/start/package.json +0 -13
  166. package/templates/react/add-on/store/assets/src/lib/demo-store.ts +0 -13
  167. package/templates/react/add-on/store/assets/src/routes/demo.store.tsx.ejs +0 -75
  168. package/templates/react/add-on/store/info.json +0 -13
  169. package/templates/react/add-on/store/package.json +0 -6
  170. package/templates/react/add-on/t3env/README.md +0 -16
  171. package/templates/react/add-on/t3env/assets/src/env.ts +0 -39
  172. package/templates/react/add-on/t3env/info.json +0 -10
  173. package/templates/react/add-on/t3env/package.json +0 -6
  174. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/init.ts +0 -9
  175. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/react.ts +0 -4
  176. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/router.ts +0 -18
  177. package/templates/react/add-on/tRPC/assets/src/routes/api.trpc.$.tsx +0 -16
  178. package/templates/react/add-on/tRPC/info.json +0 -9
  179. package/templates/react/add-on/tRPC/package.json +0 -9
  180. package/templates/react/add-on/table/assets/src/data/demo-table-data.ts +0 -50
  181. package/templates/react/add-on/table/assets/src/routes/demo.table.tsx.ejs +0 -373
  182. package/templates/react/add-on/table/info.json +0 -13
  183. package/templates/react/add-on/table/package.json +0 -7
  184. package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/layout.tsx +0 -5
  185. package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/root-provider.tsx.ejs +0 -70
  186. package/templates/react/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx.ejs +0 -53
  187. package/templates/react/add-on/tanstack-query/info.json +0 -13
  188. package/templates/react/add-on/tanstack-query/package.json +0 -6
  189. package/templates/react/base/README.md.ejs +0 -558
  190. package/templates/react/base/_dot_gitignore +0 -5
  191. package/templates/react/base/_dot_vscode/settings.biome.json +0 -38
  192. package/templates/react/base/_dot_vscode/settings.json +0 -11
  193. package/templates/react/base/index.html.ejs +0 -20
  194. package/templates/react/base/package.biome.json +0 -10
  195. package/templates/react/base/package.eslintprettier.json +0 -11
  196. package/templates/react/base/package.json +0 -30
  197. package/templates/react/base/package.ts.json +0 -7
  198. package/templates/react/base/package.tw.json +0 -6
  199. package/templates/react/base/public/favicon.ico +0 -0
  200. package/templates/react/base/public/logo192.png +0 -0
  201. package/templates/react/base/public/logo512.png +0 -0
  202. package/templates/react/base/public/manifest.json +0 -25
  203. package/templates/react/base/public/robots.txt +0 -3
  204. package/templates/react/base/src/App.css +0 -38
  205. package/templates/react/base/src/App.test.tsx.ejs +0 -10
  206. package/templates/react/base/src/App.tsx.ejs +0 -74
  207. package/templates/react/base/src/components/Header.tsx.ejs +0 -27
  208. package/templates/react/base/src/logo.svg +0 -44
  209. package/templates/react/base/src/reportWebVitals.ts.ejs +0 -28
  210. package/templates/react/base/src/styles.css.ejs +0 -15
  211. package/templates/react/base/toolchain/.prettierignore +0 -3
  212. package/templates/react/base/toolchain/biome.json +0 -31
  213. package/templates/react/base/toolchain/eslint.config.js +0 -5
  214. package/templates/react/base/toolchain/prettier.config.js +0 -10
  215. package/templates/react/base/tsconfig.json.ejs +0 -29
  216. package/templates/react/base/vite.config.js.ejs +0 -23
  217. package/templates/react/code-router/src/main.tsx.ejs +0 -92
  218. package/templates/react/example/tanchat/README.md +0 -37
  219. package/templates/react/example/tanchat/assets/_dot_env.local.append +0 -2
  220. package/templates/react/example/tanchat/assets/public/example-guitar-flowers.jpg +0 -0
  221. package/templates/react/example/tanchat/assets/public/example-guitar-motherboard.jpg +0 -0
  222. package/templates/react/example/tanchat/assets/public/example-guitar-racing.jpg +0 -0
  223. package/templates/react/example/tanchat/assets/public/example-guitar-steamer-trunk.jpg +0 -0
  224. package/templates/react/example/tanchat/assets/public/example-guitar-superhero.jpg +0 -0
  225. package/templates/react/example/tanchat/assets/public/example-guitar-traveling.jpg +0 -0
  226. package/templates/react/example/tanchat/assets/public/example-guitar-video-games.jpg +0 -0
  227. package/templates/react/example/tanchat/assets/src/components/example-AIAssistant.tsx +0 -173
  228. package/templates/react/example/tanchat/assets/src/components/example-GuitarRecommendation.tsx +0 -47
  229. package/templates/react/example/tanchat/assets/src/data/example-guitars.ts +0 -83
  230. package/templates/react/example/tanchat/assets/src/demo.index.css +0 -220
  231. package/templates/react/example/tanchat/assets/src/integrations/tanchat/header-user.tsx +0 -5
  232. package/templates/react/example/tanchat/assets/src/routes/api.messages.ts +0 -24
  233. package/templates/react/example/tanchat/assets/src/routes/api.sse.ts +0 -23
  234. package/templates/react/example/tanchat/assets/src/routes/example.chat.tsx +0 -159
  235. package/templates/react/example/tanchat/assets/src/routes/example.guitars/$guitarId.tsx +0 -50
  236. package/templates/react/example/tanchat/assets/src/routes/example.guitars/index.tsx +0 -54
  237. package/templates/react/example/tanchat/assets/src/store/example-assistant.ts +0 -3
  238. package/templates/react/example/tanchat/assets/src/utils/demo.ai.ts +0 -62
  239. package/templates/react/example/tanchat/assets/src/utils/demo.sse.ts +0 -31
  240. package/templates/react/example/tanchat/assets/src/utils/demo.tools.ts +0 -47
  241. package/templates/react/example/tanchat/info.json +0 -19
  242. package/templates/react/example/tanchat/package.json +0 -16
  243. package/templates/react/file-router/package.fr.json +0 -5
  244. package/templates/react/file-router/src/main.tsx.ejs +0 -55
  245. package/templates/react/file-router/src/routes/__root.tsx.ejs +0 -82
  246. package/templates/solid/add-on/form/assets/src/routes/demo.form.tsx.ejs +0 -352
  247. package/templates/solid/add-on/form/info.json +0 -13
  248. package/templates/solid/add-on/form/package.json +0 -5
  249. package/templates/solid/add-on/module-federation/assets/module-federation.config.js.ejs +0 -27
  250. package/templates/solid/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
  251. package/templates/solid/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -9
  252. package/templates/solid/add-on/module-federation/info.json +0 -7
  253. package/templates/solid/add-on/module-federation/package.json +0 -5
  254. package/templates/solid/add-on/sentry/assets/_dot_cursorrules.append +0 -22
  255. package/templates/solid/add-on/sentry/assets/_dot_env.local.append +0 -2
  256. package/templates/solid/add-on/sentry/assets/src/routes/demo.sentry.bad-event-handler.tsx +0 -20
  257. package/templates/solid/add-on/sentry/info.json +0 -13
  258. package/templates/solid/add-on/sentry/package.json +0 -5
  259. package/templates/solid/add-on/solid-ui/README.md +0 -9
  260. package/templates/solid/add-on/solid-ui/assets/src/lib/utils.ts +0 -6
  261. package/templates/solid/add-on/solid-ui/assets/src/styles.css +0 -138
  262. package/templates/solid/add-on/solid-ui/assets/ui.config.json +0 -13
  263. package/templates/solid/add-on/solid-ui/info.json +0 -11
  264. package/templates/solid/add-on/solid-ui/package.json +0 -9
  265. package/templates/solid/add-on/start/assets/app.config.ts +0 -16
  266. package/templates/solid/add-on/start/assets/src/api.ts +0 -6
  267. package/templates/solid/add-on/start/assets/src/client.tsx +0 -7
  268. package/templates/solid/add-on/start/assets/src/router.tsx.ejs +0 -24
  269. package/templates/solid/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +0 -49
  270. package/templates/solid/add-on/start/assets/src/ssr.tsx +0 -12
  271. package/templates/solid/add-on/start/info.json +0 -14
  272. package/templates/solid/add-on/start/package.json +0 -12
  273. package/templates/solid/add-on/store/assets/src/lib/demo-store.ts +0 -13
  274. package/templates/solid/add-on/store/assets/src/routes/demo.store.tsx.ejs +0 -77
  275. package/templates/solid/add-on/store/info.json +0 -13
  276. package/templates/solid/add-on/store/package.json +0 -6
  277. package/templates/solid/add-on/t3env/README.md +0 -16
  278. package/templates/solid/add-on/t3env/assets/src/env.ts +0 -39
  279. package/templates/solid/add-on/t3env/info.json +0 -10
  280. package/templates/solid/add-on/t3env/package.json +0 -6
  281. package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/header-user.tsx +0 -5
  282. package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/provider.tsx +0 -15
  283. package/templates/solid/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx +0 -30
  284. package/templates/solid/add-on/tanstack-query/info.json +0 -13
  285. package/templates/solid/add-on/tanstack-query/package.json +0 -6
  286. package/templates/solid/base/README.md.ejs +0 -215
  287. package/templates/solid/base/_dot_cursorrules.append +0 -35
  288. package/templates/solid/base/_dot_gitignore +0 -5
  289. package/templates/solid/base/_dot_vscode/settings.biome.json +0 -38
  290. package/templates/solid/base/_dot_vscode/settings.json +0 -11
  291. package/templates/solid/base/index.html.ejs +0 -20
  292. package/templates/solid/base/package.biome.json +0 -10
  293. package/templates/solid/base/package.eslintprettier.json +0 -11
  294. package/templates/solid/base/package.json +0 -23
  295. package/templates/solid/base/package.ts.json +0 -5
  296. package/templates/solid/base/package.tw.json +0 -6
  297. package/templates/solid/base/public/favicon.ico +0 -0
  298. package/templates/solid/base/public/logo192.png +0 -0
  299. package/templates/solid/base/public/logo512.png +0 -0
  300. package/templates/solid/base/public/manifest.json +0 -25
  301. package/templates/solid/base/public/robots.txt +0 -3
  302. package/templates/solid/base/src/App.css +0 -0
  303. package/templates/solid/base/src/App.tsx.ejs +0 -47
  304. package/templates/solid/base/src/components/Header.tsx.ejs +0 -26
  305. package/templates/solid/base/src/logo.svg +0 -120
  306. package/templates/solid/base/src/styles.css.ejs +0 -15
  307. package/templates/solid/base/toolchain/.prettierignore +0 -3
  308. package/templates/solid/base/toolchain/biome.json +0 -31
  309. package/templates/solid/base/toolchain/eslint.config.js +0 -5
  310. package/templates/solid/base/toolchain/prettier.config.js +0 -10
  311. package/templates/solid/base/tsconfig.json.ejs +0 -31
  312. package/templates/solid/base/vite.config.js.ejs +0 -22
  313. package/templates/solid/code-router/src/main.tsx.ejs +0 -71
  314. package/templates/solid/example/tanchat/README.md +0 -52
  315. package/templates/solid/example/tanchat/assets/ai-streaming-server/README.md +0 -110
  316. package/templates/solid/example/tanchat/assets/ai-streaming-server/_dot_env.example +0 -1
  317. package/templates/solid/example/tanchat/assets/ai-streaming-server/package.json +0 -26
  318. package/templates/solid/example/tanchat/assets/ai-streaming-server/src/index.ts +0 -102
  319. package/templates/solid/example/tanchat/assets/ai-streaming-server/tsconfig.json +0 -15
  320. package/templates/solid/example/tanchat/assets/src/components/demo.SettingsDialog.tsx +0 -149
  321. package/templates/solid/example/tanchat/assets/src/demo.index.css +0 -227
  322. package/templates/solid/example/tanchat/assets/src/lib/demo-store.ts +0 -13
  323. package/templates/solid/example/tanchat/assets/src/routes/example.chat.tsx +0 -435
  324. package/templates/solid/example/tanchat/assets/src/store/demo.hooks.ts +0 -17
  325. package/templates/solid/example/tanchat/assets/src/store/demo.store.ts +0 -133
  326. package/templates/solid/example/tanchat/info.json +0 -14
  327. package/templates/solid/example/tanchat/package.json +0 -7
  328. package/templates/solid/file-router/package.fr.json +0 -5
  329. package/templates/solid/file-router/src/main.tsx.ejs +0 -47
  330. package/templates/solid/file-router/src/routes/__root.tsx.ejs +0 -41
  331. package/templates/solid/file-router/src/routes/index.tsx +0 -43
  332. package/tests/cra.test.ts +0 -293
  333. package/tests/snapshots/cra/cr-js-npm.json +0 -33
  334. package/tests/snapshots/cra/cr-ts-npm.json +0 -34
  335. package/tests/snapshots/cra/cr-ts-start-npm.json +0 -38
  336. package/tests/snapshots/cra/fr-ts-npm.json +0 -34
  337. package/tests/snapshots/cra/fr-ts-tw-npm.json +0 -33
  338. package/tests/snapshots/cra/solid-cr-js-npm.json +0 -31
  339. package/tests/snapshots/cra/solid-cr-ts-npm.json +0 -32
  340. package/tests/snapshots/cra/solid-cr-ts-start-npm.json +0 -36
  341. package/tests/snapshots/cra/solid-fr-ts-npm.json +0 -33
  342. package/tests/snapshots/cra/solid-fr-ts-tw-npm.json +0 -32
  343. package/tests/test-utilities.ts +0 -87
@@ -0,0 +1,92 @@
1
+ import { loadRemoteAddOn } from './custom-add-ons/add-on.js'
2
+ import { loadStarter } from './custom-add-ons/starter.js'
3
+
4
+ import type { AddOn, Mode, Starter } from './types'
5
+
6
+ export type Registry = {
7
+ starters: Array<{
8
+ name: string
9
+ description: string
10
+ url: string
11
+ banner?: string
12
+ mode: Mode
13
+ framework: string
14
+ }>
15
+ 'add-ons': Array<{
16
+ name: string
17
+ description: string
18
+ url: string
19
+ modes: Array<Mode>
20
+ framework: string
21
+ }>
22
+ }
23
+
24
+ function absolutizeUrl(originalUrl: string, relativeUrl: string) {
25
+ if (relativeUrl.startsWith('http') || relativeUrl.startsWith('https')) {
26
+ return relativeUrl
27
+ }
28
+ const baseUrl = originalUrl.replace(/registry.json$/, '')
29
+ return `${baseUrl}${relativeUrl.replace(/^\.\//, '')}`
30
+ }
31
+
32
+ export async function getRawRegistry(
33
+ registryUrl?: string,
34
+ ): Promise<Registry | undefined> {
35
+ const regUrl = registryUrl || process.env.CTA_REGISTRY
36
+ if (regUrl) {
37
+ const registry = (await fetch(regUrl).then((res) => res.json())) as Registry
38
+ for (const addOn of registry['add-ons']) {
39
+ addOn.url = absolutizeUrl(regUrl, addOn.url)
40
+ }
41
+ for (const starter of registry.starters) {
42
+ starter.url = absolutizeUrl(regUrl, starter.url)
43
+ if (starter.banner) {
44
+ starter.banner = absolutizeUrl(regUrl, starter.banner)
45
+ }
46
+ }
47
+ return registry
48
+ }
49
+ }
50
+
51
+ async function getAddOns(registry: Registry): Promise<Array<AddOn>> {
52
+ const addOns: Array<AddOn> = []
53
+ for (const addOnInfo of registry['add-ons']) {
54
+ const addOn = await loadRemoteAddOn(addOnInfo.url)
55
+ addOns.push(addOn)
56
+ }
57
+ return addOns
58
+ }
59
+
60
+ export async function getRegistryAddOns(
61
+ registryUrl?: string,
62
+ ): Promise<Array<AddOn>> {
63
+ const registry = await getRawRegistry(registryUrl)
64
+ return registry ? await getAddOns(registry) : []
65
+ }
66
+
67
+ async function getStarters(registry: Registry): Promise<Array<Starter>> {
68
+ const starters: Array<Starter> = []
69
+ for (const starterInfo of registry.starters) {
70
+ const starter = await loadStarter(starterInfo.url)
71
+ starters.push(starter)
72
+ }
73
+ return starters
74
+ }
75
+
76
+ export async function getRegistryStarters(
77
+ registryUrl?: string,
78
+ ): Promise<Array<Starter>> {
79
+ const registry = await getRawRegistry(registryUrl)
80
+ return registry ? await getStarters(registry) : []
81
+ }
82
+
83
+ export async function getRegistry(registryUrl?: string): Promise<{
84
+ addOns: Array<AddOn>
85
+ starters: Array<Starter>
86
+ }> {
87
+ const registry = await getRawRegistry(registryUrl)
88
+ return {
89
+ addOns: registry ? await getAddOns(registry) : [],
90
+ starters: registry ? await getStarters(registry) : [],
91
+ }
92
+ }
@@ -0,0 +1,36 @@
1
+ import { rimrafNodeModules } from './rimraf-node-modules.js'
2
+
3
+ import type { Environment, Options } from '../types.js'
4
+
5
+ const specialStepsLookup: Record<
6
+ string,
7
+ (environment: Environment, options: Options) => Promise<void>
8
+ > = {
9
+ 'rimraf-node-modules': rimrafNodeModules,
10
+ }
11
+
12
+ export async function runSpecialSteps(
13
+ environment: Environment,
14
+ options: Options,
15
+ specialSteps: Array<string>,
16
+ ) {
17
+ if (specialSteps.length) {
18
+ environment.startStep({
19
+ id: 'special-steps',
20
+ type: 'command',
21
+ message: 'Removing node_modules...',
22
+ })
23
+
24
+ for (const step of specialSteps) {
25
+ const stepFunction = specialStepsLookup[step]
26
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
27
+ if (stepFunction) {
28
+ await stepFunction(environment, options)
29
+ } else {
30
+ environment.error(`Special step ${step} not found`)
31
+ }
32
+ }
33
+
34
+ environment.finishStep('special-steps', 'Special steps complete')
35
+ }
36
+ }
@@ -0,0 +1,25 @@
1
+ import { resolve } from 'node:path'
2
+
3
+ import type { Environment, Options } from '../types.js'
4
+
5
+ const lockFiles = ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml']
6
+
7
+ export async function rimrafNodeModules(
8
+ environment: Environment,
9
+ options: Options,
10
+ ) {
11
+ environment.startStep({
12
+ id: 'special-steps',
13
+ type: 'command',
14
+ message: 'Removing node_modules...',
15
+ })
16
+
17
+ await environment.rimraf(resolve(options.targetDir, 'node_modules'))
18
+
19
+ for (const lockFile of lockFiles) {
20
+ const lockFilePath = resolve(options.targetDir, lockFile)
21
+ if (environment.exists(lockFilePath)) {
22
+ await environment.deleteFile(lockFilePath)
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,150 @@
1
+ import { resolve, sep } from 'node:path'
2
+ import { render } from 'ejs'
3
+ import { format } from 'prettier'
4
+
5
+ import { CODE_ROUTER, FILE_ROUTER } from './constants.js'
6
+ import { formatCommand } from './utils.js'
7
+ import {
8
+ getPackageManagerInstallCommand,
9
+ getPackageManagerScriptCommand,
10
+ } from './package-manager.js'
11
+ import { relativePath } from './file-helpers.js'
12
+
13
+ import type { AddOn, Environment, Options } from './types.js'
14
+
15
+ function convertDotFilesAndPaths(path: string) {
16
+ return path
17
+ .split(sep)
18
+ .map((segment) => segment.replace(/^_dot_/, '.'))
19
+ .join(sep)
20
+ }
21
+
22
+ export function createTemplateFile(environment: Environment, options: Options) {
23
+ function getPackageManagerAddScript(
24
+ packageName: string,
25
+ isDev: boolean = false,
26
+ ) {
27
+ return formatCommand(
28
+ getPackageManagerInstallCommand(
29
+ options.packageManager,
30
+ packageName,
31
+ isDev,
32
+ ),
33
+ )
34
+ }
35
+ function getPackageManagerRunScript(
36
+ scriptName: string,
37
+ args: Array<string> = [],
38
+ ) {
39
+ return formatCommand(
40
+ getPackageManagerScriptCommand(options.packageManager, [
41
+ scriptName,
42
+ ...args,
43
+ ]),
44
+ )
45
+ }
46
+
47
+ class IgnoreFileError extends Error {
48
+ constructor() {
49
+ super('ignoreFile')
50
+ this.name = 'IgnoreFileError'
51
+ }
52
+ }
53
+
54
+ const integrations: Array<Required<AddOn>['integrations'][number]> = []
55
+ for (const addOn of options.chosenAddOns) {
56
+ if (addOn.integrations) {
57
+ for (const integration of addOn.integrations) {
58
+ integrations.push(integration)
59
+ }
60
+ }
61
+ }
62
+
63
+ const routes: Array<Required<AddOn>['routes'][number]> = []
64
+ for (const addOn of options.chosenAddOns) {
65
+ if (addOn.routes) {
66
+ routes.push(...addOn.routes)
67
+ }
68
+ }
69
+
70
+ const addOnEnabled = options.chosenAddOns.reduce<Record<string, boolean>>(
71
+ (acc, addOn) => {
72
+ acc[addOn.id] = true
73
+ return acc
74
+ },
75
+ {},
76
+ )
77
+
78
+ return async function templateFile(file: string, content: string) {
79
+ const templateValues = {
80
+ packageManager: options.packageManager,
81
+ projectName: options.projectName,
82
+ typescript: options.typescript,
83
+ tailwind: options.tailwind,
84
+ js: options.typescript ? 'ts' : 'js',
85
+ jsx: options.typescript ? 'tsx' : 'jsx',
86
+ fileRouter: options.mode === FILE_ROUTER,
87
+ codeRouter: options.mode === CODE_ROUTER,
88
+ addOnEnabled,
89
+ addOns: options.chosenAddOns,
90
+ integrations,
91
+ routes,
92
+
93
+ getPackageManagerAddScript,
94
+ getPackageManagerRunScript,
95
+
96
+ relativePath: (path: string) => relativePath(file, path),
97
+
98
+ ignoreFile: () => {
99
+ throw new IgnoreFileError()
100
+ },
101
+ }
102
+
103
+ let ignoreFile = false
104
+
105
+ if (file.endsWith('.ejs')) {
106
+ try {
107
+ content = render(content, templateValues)
108
+ } catch (error) {
109
+ if (error instanceof IgnoreFileError) {
110
+ ignoreFile = true
111
+ } else {
112
+ console.error(file, error)
113
+ environment.error(`EJS error in file ${file}`, error?.toString())
114
+ process.exit(1)
115
+ }
116
+ }
117
+ }
118
+
119
+ if (ignoreFile) {
120
+ return
121
+ }
122
+
123
+ let target = convertDotFilesAndPaths(file.replace('.ejs', ''))
124
+
125
+ let append = false
126
+ if (target.endsWith('.append')) {
127
+ append = true
128
+ target = target.replace('.append', '')
129
+ }
130
+
131
+ if (target.endsWith('.ts') || target.endsWith('.tsx')) {
132
+ content = await format(content, {
133
+ semi: false,
134
+ singleQuote: true,
135
+ trailingComma: 'all',
136
+ parser: 'typescript',
137
+ })
138
+ }
139
+
140
+ if (!options.typescript) {
141
+ target = target.replace(/\.tsx$/, '.jsx').replace(/\.ts$/, '.js')
142
+ }
143
+
144
+ if (append) {
145
+ await environment.appendFile(resolve(options.targetDir, target), content)
146
+ } else {
147
+ await environment.writeFile(resolve(options.targetDir, target), content)
148
+ }
149
+ }
150
+ }
package/src/types.ts CHANGED
@@ -1,124 +1,212 @@
1
+ import z from 'zod'
2
+
1
3
  import type { CODE_ROUTER, FILE_ROUTER } from './constants.js'
2
4
  import type { PackageManager } from './package-manager.js'
3
- import type { ToolChain } from './toolchain.js'
4
5
 
5
- export type Framework = 'solid' | 'react'
6
+ export type Mode = typeof CODE_ROUTER | typeof FILE_ROUTER
7
+
8
+ export type StatusStepType =
9
+ | 'file'
10
+ | 'command'
11
+ | 'info'
12
+ | 'package-manager'
13
+ | 'other'
6
14
 
7
- export type TemplateOptions = 'typescript' | 'javascript' | 'file-router'
15
+ export const AddOnBaseSchema = z.object({
16
+ id: z.string(),
17
+ name: z.string(),
18
+ description: z.string(),
19
+ author: z.string().optional(),
20
+ version: z.string().optional(),
21
+ link: z.string().optional(),
22
+ license: z.string().optional(),
23
+ warning: z.string().optional(),
24
+ type: z.enum(['add-on', 'example', 'starter', 'toolchain']),
25
+ command: z
26
+ .object({
27
+ command: z.string(),
28
+ args: z.array(z.string()).optional(),
29
+ })
30
+ .optional(),
31
+ routes: z
32
+ .array(
33
+ z.object({
34
+ url: z.string().optional(),
35
+ name: z.string().optional(),
36
+ path: z.string(),
37
+ jsName: z.string(),
38
+ }),
39
+ )
40
+ .optional(),
41
+ packageAdditions: z
42
+ .object({
43
+ dependencies: z.record(z.string(), z.string()).optional(),
44
+ devDependencies: z.record(z.string(), z.string()).optional(),
45
+ scripts: z.record(z.string(), z.string()).optional(),
46
+ })
47
+ .optional(),
48
+ shadcnComponents: z.array(z.string()).optional(),
49
+ dependsOn: z.array(z.string()).optional(),
50
+ smallLogo: z.string().optional(),
51
+ logo: z.string().optional(),
52
+ addOnSpecialSteps: z.array(z.string()).optional(),
53
+ createSpecialSteps: z.array(z.string()).optional(),
54
+ })
8
55
 
9
- export type Mode = typeof CODE_ROUTER | typeof FILE_ROUTER
56
+ export const StarterSchema = AddOnBaseSchema.extend({
57
+ framework: z.string(),
58
+ mode: z.string(),
59
+ typescript: z.boolean(),
60
+ tailwind: z.boolean(),
61
+ banner: z.string().optional(),
62
+ })
63
+
64
+ export const StarterCompiledSchema = StarterSchema.extend({
65
+ files: z.record(z.string(), z.string()),
66
+ deletedFiles: z.array(z.string()),
67
+ })
68
+
69
+ export const IntegrationSchema = z.object({
70
+ type: z.string(),
71
+ path: z.string(),
72
+ jsName: z.string(),
73
+ })
74
+
75
+ export const AddOnInfoSchema = AddOnBaseSchema.extend({
76
+ modes: z.array(z.string()),
77
+ integrations: z.array(IntegrationSchema).optional(),
78
+ phase: z.enum(['setup', 'add-on']),
79
+ readme: z.string().optional(),
80
+ })
81
+
82
+ export const AddOnCompiledSchema = AddOnInfoSchema.extend({
83
+ files: z.record(z.string(), z.string()),
84
+ deletedFiles: z.array(z.string()),
85
+ })
86
+
87
+ export type Integration = z.infer<typeof IntegrationSchema>
88
+
89
+ export type AddOnBase = z.infer<typeof AddOnBaseSchema>
90
+
91
+ export type StarterInfo = z.infer<typeof StarterSchema>
92
+
93
+ export type StarterCompiled = z.infer<typeof StarterCompiledSchema>
94
+
95
+ export type AddOnInfo = z.infer<typeof AddOnInfoSchema>
96
+
97
+ export type AddOnCompiled = z.infer<typeof AddOnCompiledSchema>
98
+
99
+ export type FileBundleHandler = {
100
+ getFiles: () => Promise<Array<string>>
101
+ getFileContents: (path: string) => Promise<string>
102
+ getDeletedFiles: () => Promise<Array<string>>
103
+ }
104
+
105
+ export type AddOn = AddOnInfo & FileBundleHandler
106
+
107
+ export type Starter = StarterCompiled & FileBundleHandler
108
+
109
+ export type FrameworkDefinition = {
110
+ id: string
111
+ name: string
112
+ description: string
113
+ version: string
114
+
115
+ baseDirectory: string
116
+ addOnsDirectories: Array<string>
117
+ examplesDirectory: string
118
+ }
119
+
120
+ export type Framework = FrameworkDefinition &
121
+ FileBundleHandler & {
122
+ basePackageJSON: Record<string, any>
123
+ optionalPackages: Record<string, any>
124
+
125
+ getAddOns: () => Array<AddOn>
126
+ }
10
127
 
11
128
  export interface Options {
12
- framework: Framework
13
129
  projectName: string
130
+ targetDir: string
131
+
132
+ framework: Framework
133
+ mode: Mode
134
+
14
135
  typescript: boolean
15
136
  tailwind: boolean
137
+
16
138
  packageManager: PackageManager
17
- toolchain: ToolChain
18
- mode: Mode
19
- addOns: boolean
20
- chosenAddOns: Array<AddOn>
21
139
  git: boolean
22
- variableValues: Record<string, string | number | boolean>
23
- overlay?: AddOn | undefined
140
+
141
+ chosenAddOns: Array<AddOn>
142
+ starter?: Starter | undefined
24
143
  }
25
144
 
26
- export interface CliOptions {
27
- template?: TemplateOptions
28
- framework?: Framework
29
- tailwind?: boolean
30
- packageManager?: PackageManager
31
- toolchain?: ToolChain
32
- projectName?: string
33
- git?: boolean
34
- addOns?: Array<string> | boolean
35
- listAddOns?: boolean
36
- mcp?: boolean
37
- mcpSse?: boolean
38
- overlay?: string
39
- targetDir?: string
40
- interactive?: boolean
145
+ export type SerializedOptions = Omit<
146
+ Options,
147
+ 'chosenAddOns' | 'starter' | 'framework'
148
+ > & {
149
+ chosenAddOns: Array<string>
150
+ starter?: string | undefined
151
+ framework: string
41
152
  }
42
153
 
43
- export type Environment = {
154
+ type ProjectEnvironment = {
44
155
  startRun: () => void
45
156
  finishRun: () => void
46
157
  getErrors: () => Array<string>
158
+ }
47
159
 
160
+ type FileEnvironment = {
48
161
  appendFile: (path: string, contents: string) => Promise<void>
49
162
  copyFile: (from: string, to: string) => Promise<void>
50
163
  writeFile: (path: string, contents: string) => Promise<void>
51
- execute: (command: string, args: Array<string>, cwd: string) => Promise<void>
164
+ writeFileBase64: (path: string, base64Contents: string) => Promise<void>
165
+ execute: (
166
+ command: string,
167
+ args: Array<string>,
168
+ cwd: string,
169
+ ) => Promise<{ stdout: string }>
52
170
  deleteFile: (path: string) => Promise<void>
53
171
 
54
- readFile: (path: string, encoding?: BufferEncoding) => Promise<string>
55
172
  exists: (path: string) => boolean
56
- readdir: (path: string) => Array<string>
57
173
  isDirectory: (path: string) => boolean
174
+ readFile: (path: string) => Promise<string>
175
+ readdir: (path: string) => Promise<Array<string>>
176
+ rimraf: (path: string) => Promise<void>
58
177
  }
59
178
 
60
- type BooleanVariable = {
61
- name: string
62
- default: boolean
63
- description: string
64
- type: 'boolean'
179
+ export type StatusEvent = {
180
+ id: string
181
+ type: StatusStepType
182
+ message: string
65
183
  }
66
-
67
- type NumberVariable = {
68
- name: string
69
- default: number
70
- description: string
71
- type: 'number'
184
+ export type StopEvent = {
185
+ id: string
72
186
  }
73
187
 
74
- type StringVariable = {
75
- name: string
76
- default: string
77
- description: string
78
- type: 'string'
79
- }
188
+ type UIEnvironment = {
189
+ appName: string
80
190
 
81
- export type Variable = BooleanVariable | NumberVariable | StringVariable
191
+ startStep: (info: {
192
+ id: string
193
+ type: StatusStepType
194
+ message: string
195
+ }) => void
196
+ finishStep: (id: string, finalMessage: string) => void
82
197
 
83
- export type AddOn = {
84
- id: string
85
- name: string
86
- description: string
87
- type: 'add-on' | 'example' | 'overlay'
88
- link: string
89
- templates: Array<string>
90
- routes: Array<{
91
- url: string
92
- name: string
93
- }>
94
- packageAdditions: {
95
- dependencies?: Record<string, string>
96
- devDependencies?: Record<string, string>
97
- scripts?: Record<string, string>
98
- }
99
- command?: {
100
- command: string
101
- args?: Array<string>
198
+ intro: (message: string) => void
199
+ outro: (message: string) => void
200
+
201
+ info: (title?: string, message?: string) => void
202
+ error: (title?: string, message?: string) => void
203
+ warn: (title?: string, message?: string) => void
204
+
205
+ spinner: () => {
206
+ start: (message: string) => void
207
+ stop: (message: string) => void
102
208
  }
103
- readme?: string
104
- phase: 'setup' | 'add-on'
105
- shadcnComponents?: Array<string>
106
- warning?: string
107
- dependsOn?: Array<string>
108
- variables?: Array<Variable>
109
-
110
- files?: Record<string, string>
111
- deletedFiles?: Array<string>
209
+ confirm: (message: string) => Promise<boolean>
112
210
  }
113
211
 
114
- export type Overlay = AddOn & {
115
- type: 'overlay'
116
- version: string
117
- author: string
118
- link: string
119
- license: string
120
- mode: Mode
121
- framework: Framework
122
- typescript: boolean
123
- tailwind: boolean
124
- }
212
+ export type Environment = ProjectEnvironment & FileEnvironment & UIEnvironment
package/src/utils.ts CHANGED
@@ -8,3 +8,20 @@ export function sortObject(
8
8
  return acc
9
9
  }, {})
10
10
  }
11
+
12
+ export function jsSafeName(name: string) {
13
+ return name
14
+ .split(/[^a-zA-Z0-9]/)
15
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
16
+ .join('')
17
+ }
18
+
19
+ export function formatCommand({
20
+ command,
21
+ args,
22
+ }: {
23
+ command: string
24
+ args: Array<string>
25
+ }) {
26
+ return `${command} ${args.join(' ')}`.trim()
27
+ }
@@ -0,0 +1,67 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { finalizeAddOns, getAllAddOns } from '../src/add-ons.js'
4
+
5
+ import type { AddOn, Framework } from '../src/types.js'
6
+
7
+ describe('getAllAddOns', () => {
8
+ it('filter add-ons', () => {
9
+ const addOns = getAllAddOns(
10
+ {
11
+ id: 'react-cra',
12
+ getAddOns: () => [
13
+ {
14
+ id: 'add-on-1',
15
+ description: 'Add-on 1',
16
+ modes: ['file-router'],
17
+ } as AddOn,
18
+ {
19
+ id: 'add-on-2',
20
+ description: 'Add-on 2',
21
+ modes: ['code-router'],
22
+ } as AddOn,
23
+ ],
24
+ } as Framework,
25
+ 'file-router',
26
+ )
27
+
28
+ expect(addOns.length).toEqual(1)
29
+ expect(addOns[0].id).toEqual('add-on-1')
30
+ })
31
+ })
32
+
33
+ describe('finalizeAddOns', () => {
34
+ it('should finalize add-ons', async () => {
35
+ const addOns = await finalizeAddOns(
36
+ {
37
+ id: 'react-cra',
38
+ getAddOns: () => [
39
+ {
40
+ id: 'add-on-1',
41
+ description: 'Add-on 1',
42
+ modes: ['file-router'],
43
+ dependsOn: ['add-on-2'],
44
+ } as AddOn,
45
+ {
46
+ id: 'add-on-2',
47
+ description: 'Add-on 2',
48
+ modes: ['file-router'],
49
+ } as AddOn,
50
+ {
51
+ id: 'add-on-3',
52
+ description: 'Add-on 3',
53
+ modes: ['file-router'],
54
+ } as AddOn,
55
+ ],
56
+ } as Framework,
57
+ 'file-router',
58
+ ['add-on-1'],
59
+ )
60
+
61
+ expect(addOns.length).toEqual(2)
62
+ const addOnIds = addOns.map((a) => a.id)
63
+ expect(addOnIds.includes('add-on-1')).toEqual(true)
64
+ expect(addOnIds.includes('add-on-2')).toEqual(true)
65
+ expect(addOnIds.includes('add-on-3')).toEqual(false)
66
+ })
67
+ })