@tanstack/cta-engine 0.10.0-alpha.25 → 0.10.0-alpha.26

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 (340) hide show
  1. package/dist/add-ons.js +5 -91
  2. package/dist/add-to-app.js +169 -0
  3. package/dist/config-file.js +14 -9
  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 +117 -0
  8. package/dist/custom-add-ons/starter.js +84 -0
  9. package/dist/environment.js +64 -32
  10. package/dist/file-helpers.js +165 -0
  11. package/dist/frameworks.js +92 -0
  12. package/dist/index.js +17 -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/special-steps/index.js +24 -0
  19. package/dist/special-steps/rimraf-node-modules.js +16 -0
  20. package/dist/template-file.js +112 -0
  21. package/dist/types/add-ons.d.ts +3 -8
  22. package/dist/types/add-to-app.d.ts +17 -0
  23. package/dist/types/config-file.d.ts +6 -4
  24. package/dist/types/constants.d.ts +0 -3
  25. package/dist/types/create-app.d.ts +1 -7
  26. package/dist/types/custom-add-ons/add-on.d.ts +69 -0
  27. package/dist/types/custom-add-ons/shared.d.ts +15 -0
  28. package/dist/types/custom-add-ons/starter.d.ts +7 -0
  29. package/dist/types/environment.d.ts +2 -1
  30. package/dist/types/file-helpers.d.ts +15 -0
  31. package/dist/types/frameworks.d.ts +7 -0
  32. package/dist/types/index.d.ts +20 -1
  33. package/dist/types/integrations/git.d.ts +2 -0
  34. package/dist/types/integrations/shadcn.d.ts +2 -0
  35. package/dist/types/options.d.ts +2 -6
  36. package/dist/types/package-json.d.ts +7 -0
  37. package/dist/types/package-manager.d.ts +18 -1
  38. package/dist/types/special-steps/index.d.ts +2 -0
  39. package/dist/types/special-steps/rimraf-node-modules.d.ts +2 -0
  40. package/dist/types/template-file.d.ts +2 -0
  41. package/dist/types/types.d.ts +788 -85
  42. package/dist/types/utils.d.ts +5 -0
  43. package/dist/types.js +65 -1
  44. package/dist/utils.js +9 -0
  45. package/package.json +9 -12
  46. package/src/add-ons.ts +7 -123
  47. package/src/add-to-app.ts +274 -0
  48. package/src/config-file.ts +26 -17
  49. package/src/constants.ts +0 -5
  50. package/src/create-app.ts +180 -730
  51. package/src/custom-add-ons/add-on.ts +261 -0
  52. package/src/custom-add-ons/shared.ts +161 -0
  53. package/src/custom-add-ons/starter.ts +126 -0
  54. package/src/environment.ts +77 -33
  55. package/src/file-helpers.ts +235 -0
  56. package/src/frameworks.ts +134 -0
  57. package/src/index.ts +77 -1
  58. package/src/integrations/git.ts +7 -0
  59. package/src/integrations/shadcn.ts +54 -0
  60. package/src/options.ts +8 -409
  61. package/src/package-json.ts +69 -0
  62. package/src/package-manager.ts +80 -9
  63. package/src/special-steps/index.ts +36 -0
  64. package/src/special-steps/rimraf-node-modules.ts +25 -0
  65. package/src/template-file.ts +150 -0
  66. package/src/types.ts +175 -87
  67. package/src/utils.ts +17 -0
  68. package/tests/add-ons.test.ts +67 -0
  69. package/tests/add-to-app.test.ts +358 -0
  70. package/tests/config-file.test.ts +68 -0
  71. package/tests/create-app.test.ts +120 -0
  72. package/tests/custom-add-ons/add-on.test.ts +12 -0
  73. package/tests/custom-add-ons/shared.test.ts +257 -0
  74. package/tests/custom-add-ons/starter.test.ts +58 -0
  75. package/tests/environment.test.ts +115 -0
  76. package/tests/file-helper.test.ts +90 -0
  77. package/tests/frameworks.test.ts +95 -0
  78. package/tests/index.test.ts +9 -0
  79. package/tests/integrations/git.test.ts +20 -0
  80. package/tests/integrations/shadcn.test.ts +91 -0
  81. package/tests/options.test.ts +42 -0
  82. package/tests/package-json.test.ts +63 -0
  83. package/tests/package-manager.test.ts +154 -0
  84. package/tests/setupVitest.ts +6 -0
  85. package/tests/template-file.test.ts +178 -0
  86. package/tests/utils.test.ts +23 -0
  87. package/vitest.config.ts +21 -0
  88. package/dist/add.js +0 -125
  89. package/dist/cli.js +0 -132
  90. package/dist/custom-add-on.js +0 -254
  91. package/dist/file-helper.js +0 -18
  92. package/dist/mcp.js +0 -229
  93. package/dist/templates.js +0 -6
  94. package/dist/toolchain.js +0 -6
  95. package/dist/types/add.d.ts +0 -3
  96. package/dist/types/cli.d.ts +0 -7
  97. package/dist/types/custom-add-on.d.ts +0 -3
  98. package/dist/types/file-helper.d.ts +0 -2
  99. package/dist/types/mcp.d.ts +0 -7
  100. package/dist/types/templates.d.ts +0 -1
  101. package/dist/types/toolchain.d.ts +0 -3
  102. package/src/add.ts +0 -186
  103. package/src/cli.ts +0 -210
  104. package/src/custom-add-on.ts +0 -325
  105. package/src/file-helper.ts +0 -20
  106. package/src/mcp.ts +0 -302
  107. package/src/templates.ts +0 -7
  108. package/src/toolchain.ts +0 -7
  109. package/templates/react/add-on/clerk/README.md +0 -3
  110. package/templates/react/add-on/clerk/assets/_dot_env.local.append +0 -2
  111. package/templates/react/add-on/clerk/assets/src/integrations/clerk/header-user.tsx +0 -19
  112. package/templates/react/add-on/clerk/assets/src/integrations/clerk/provider.tsx +0 -18
  113. package/templates/react/add-on/clerk/assets/src/routes/demo.clerk.tsx +0 -20
  114. package/templates/react/add-on/clerk/info.json +0 -13
  115. package/templates/react/add-on/clerk/package.json +0 -5
  116. package/templates/react/add-on/convex/README.md +0 -4
  117. package/templates/react/add-on/convex/assets/_dot_cursorrules.append +0 -93
  118. package/templates/react/add-on/convex/assets/_dot_env.local.append +0 -3
  119. package/templates/react/add-on/convex/assets/convex/products.ts +0 -8
  120. package/templates/react/add-on/convex/assets/convex/schema.ts +0 -10
  121. package/templates/react/add-on/convex/assets/src/integrations/convex/provider.tsx +0 -20
  122. package/templates/react/add-on/convex/assets/src/routes/demo.convex.tsx +0 -33
  123. package/templates/react/add-on/convex/info.json +0 -13
  124. package/templates/react/add-on/convex/package.json +0 -6
  125. package/templates/react/add-on/form/assets/src/components/demo.FormComponents.tsx.ejs +0 -300
  126. package/templates/react/add-on/form/assets/src/hooks/demo.form-context.ts +0 -4
  127. package/templates/react/add-on/form/assets/src/hooks/demo.form.ts +0 -22
  128. package/templates/react/add-on/form/assets/src/routes/demo.form.address.tsx.ejs +0 -213
  129. package/templates/react/add-on/form/assets/src/routes/demo.form.simple.tsx.ejs +0 -77
  130. package/templates/react/add-on/form/info.json +0 -26
  131. package/templates/react/add-on/form/package.json +0 -6
  132. package/templates/react/add-on/module-federation/assets/module-federation.config.js.ejs +0 -31
  133. package/templates/react/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
  134. package/templates/react/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -11
  135. package/templates/react/add-on/module-federation/info.json +0 -7
  136. package/templates/react/add-on/module-federation/package.json +0 -5
  137. package/templates/react/add-on/netlify/README.md +0 -11
  138. package/templates/react/add-on/netlify/info.json +0 -7
  139. package/templates/react/add-on/sentry/assets/_dot_cursorrules.append +0 -22
  140. package/templates/react/add-on/sentry/assets/_dot_env.local.append +0 -11
  141. package/templates/react/add-on/sentry/assets/src/app/global-middleware.ts +0 -11
  142. package/templates/react/add-on/sentry/assets/src/routes/demo.sentry.testing.tsx +0 -489
  143. package/templates/react/add-on/sentry/info.json +0 -14
  144. package/templates/react/add-on/sentry/package.json +0 -5
  145. package/templates/react/add-on/shadcn/README.md +0 -7
  146. package/templates/react/add-on/shadcn/assets/_dot_cursorrules.append +0 -7
  147. package/templates/react/add-on/shadcn/assets/components.json +0 -21
  148. package/templates/react/add-on/shadcn/assets/src/lib/utils.ts +0 -6
  149. package/templates/react/add-on/shadcn/assets/src/styles.css +0 -138
  150. package/templates/react/add-on/shadcn/info.json +0 -7
  151. package/templates/react/add-on/shadcn/package.json +0 -9
  152. package/templates/react/add-on/start/assets/_dot_gitignore.append +0 -2
  153. package/templates/react/add-on/start/assets/app.config.ts.ejs +0 -32
  154. package/templates/react/add-on/start/assets/src/api.ts +0 -6
  155. package/templates/react/add-on/start/assets/src/client.tsx.ejs +0 -33
  156. package/templates/react/add-on/start/assets/src/router.tsx.ejs +0 -48
  157. package/templates/react/add-on/start/assets/src/routes/api.demo-names.ts +0 -11
  158. package/templates/react/add-on/start/assets/src/routes/demo.start.api-request.tsx.ejs +0 -33
  159. package/templates/react/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +0 -50
  160. package/templates/react/add-on/start/assets/src/ssr.tsx.ejs +0 -30
  161. package/templates/react/add-on/start/info.json +0 -18
  162. package/templates/react/add-on/start/package.json +0 -13
  163. package/templates/react/add-on/store/assets/src/lib/demo-store.ts +0 -13
  164. package/templates/react/add-on/store/assets/src/routes/demo.store.tsx.ejs +0 -75
  165. package/templates/react/add-on/store/info.json +0 -13
  166. package/templates/react/add-on/store/package.json +0 -6
  167. package/templates/react/add-on/t3env/README.md +0 -16
  168. package/templates/react/add-on/t3env/assets/src/env.ts +0 -39
  169. package/templates/react/add-on/t3env/info.json +0 -10
  170. package/templates/react/add-on/t3env/package.json +0 -6
  171. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/init.ts +0 -9
  172. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/react.ts +0 -4
  173. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/router.ts +0 -18
  174. package/templates/react/add-on/tRPC/assets/src/routes/api.trpc.$.tsx +0 -16
  175. package/templates/react/add-on/tRPC/info.json +0 -9
  176. package/templates/react/add-on/tRPC/package.json +0 -9
  177. package/templates/react/add-on/table/assets/src/data/demo-table-data.ts +0 -50
  178. package/templates/react/add-on/table/assets/src/routes/demo.table.tsx.ejs +0 -373
  179. package/templates/react/add-on/table/info.json +0 -13
  180. package/templates/react/add-on/table/package.json +0 -7
  181. package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/layout.tsx +0 -5
  182. package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/root-provider.tsx.ejs +0 -70
  183. package/templates/react/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx.ejs +0 -53
  184. package/templates/react/add-on/tanstack-query/info.json +0 -13
  185. package/templates/react/add-on/tanstack-query/package.json +0 -6
  186. package/templates/react/base/README.md.ejs +0 -558
  187. package/templates/react/base/_dot_gitignore +0 -5
  188. package/templates/react/base/_dot_vscode/settings.biome.json +0 -35
  189. package/templates/react/base/_dot_vscode/settings.json +0 -11
  190. package/templates/react/base/index.html.ejs +0 -20
  191. package/templates/react/base/package.biome.json +0 -10
  192. package/templates/react/base/package.eslintprettier.json +0 -11
  193. package/templates/react/base/package.json +0 -30
  194. package/templates/react/base/package.ts.json +0 -7
  195. package/templates/react/base/package.tw.json +0 -6
  196. package/templates/react/base/public/favicon.ico +0 -0
  197. package/templates/react/base/public/logo192.png +0 -0
  198. package/templates/react/base/public/logo512.png +0 -0
  199. package/templates/react/base/public/manifest.json +0 -25
  200. package/templates/react/base/public/robots.txt +0 -3
  201. package/templates/react/base/src/App.css +0 -38
  202. package/templates/react/base/src/App.test.tsx.ejs +0 -10
  203. package/templates/react/base/src/App.tsx.ejs +0 -74
  204. package/templates/react/base/src/components/Header.tsx.ejs +0 -27
  205. package/templates/react/base/src/logo.svg +0 -44
  206. package/templates/react/base/src/reportWebVitals.ts.ejs +0 -28
  207. package/templates/react/base/src/styles.css.ejs +0 -15
  208. package/templates/react/base/toolchain/.prettierignore +0 -3
  209. package/templates/react/base/toolchain/biome.json +0 -31
  210. package/templates/react/base/toolchain/eslint.config.js +0 -5
  211. package/templates/react/base/toolchain/prettier.config.js +0 -10
  212. package/templates/react/base/tsconfig.json.ejs +0 -29
  213. package/templates/react/base/vite.config.js.ejs +0 -23
  214. package/templates/react/code-router/src/main.tsx.ejs +0 -92
  215. package/templates/react/example/tanchat/README.md +0 -37
  216. package/templates/react/example/tanchat/assets/_dot_env.local.append +0 -2
  217. package/templates/react/example/tanchat/assets/public/example-guitar-flowers.jpg +0 -0
  218. package/templates/react/example/tanchat/assets/public/example-guitar-motherboard.jpg +0 -0
  219. package/templates/react/example/tanchat/assets/public/example-guitar-racing.jpg +0 -0
  220. package/templates/react/example/tanchat/assets/public/example-guitar-steamer-trunk.jpg +0 -0
  221. package/templates/react/example/tanchat/assets/public/example-guitar-superhero.jpg +0 -0
  222. package/templates/react/example/tanchat/assets/public/example-guitar-traveling.jpg +0 -0
  223. package/templates/react/example/tanchat/assets/public/example-guitar-video-games.jpg +0 -0
  224. package/templates/react/example/tanchat/assets/src/components/example-AIAssistant.tsx +0 -173
  225. package/templates/react/example/tanchat/assets/src/components/example-GuitarRecommendation.tsx +0 -47
  226. package/templates/react/example/tanchat/assets/src/data/example-guitars.ts +0 -83
  227. package/templates/react/example/tanchat/assets/src/demo.index.css +0 -220
  228. package/templates/react/example/tanchat/assets/src/integrations/tanchat/header-user.tsx +0 -5
  229. package/templates/react/example/tanchat/assets/src/routes/api.messages.ts +0 -24
  230. package/templates/react/example/tanchat/assets/src/routes/api.sse.ts +0 -23
  231. package/templates/react/example/tanchat/assets/src/routes/example.chat.tsx +0 -159
  232. package/templates/react/example/tanchat/assets/src/routes/example.guitars/$guitarId.tsx +0 -50
  233. package/templates/react/example/tanchat/assets/src/routes/example.guitars/index.tsx +0 -54
  234. package/templates/react/example/tanchat/assets/src/store/example-assistant.ts +0 -3
  235. package/templates/react/example/tanchat/assets/src/utils/demo.ai.ts +0 -62
  236. package/templates/react/example/tanchat/assets/src/utils/demo.sse.ts +0 -31
  237. package/templates/react/example/tanchat/assets/src/utils/demo.tools.ts +0 -47
  238. package/templates/react/example/tanchat/info.json +0 -19
  239. package/templates/react/example/tanchat/package.json +0 -16
  240. package/templates/react/file-router/package.fr.json +0 -5
  241. package/templates/react/file-router/src/main.tsx.ejs +0 -55
  242. package/templates/react/file-router/src/routes/__root.tsx.ejs +0 -82
  243. package/templates/solid/add-on/form/assets/src/routes/demo.form.tsx.ejs +0 -352
  244. package/templates/solid/add-on/form/info.json +0 -13
  245. package/templates/solid/add-on/form/package.json +0 -5
  246. package/templates/solid/add-on/module-federation/assets/module-federation.config.js.ejs +0 -27
  247. package/templates/solid/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
  248. package/templates/solid/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -9
  249. package/templates/solid/add-on/module-federation/info.json +0 -7
  250. package/templates/solid/add-on/module-federation/package.json +0 -5
  251. package/templates/solid/add-on/sentry/assets/_dot_cursorrules.append +0 -22
  252. package/templates/solid/add-on/sentry/assets/_dot_env.local.append +0 -2
  253. package/templates/solid/add-on/sentry/assets/src/routes/demo.sentry.bad-event-handler.tsx +0 -20
  254. package/templates/solid/add-on/sentry/info.json +0 -13
  255. package/templates/solid/add-on/sentry/package.json +0 -5
  256. package/templates/solid/add-on/solid-ui/README.md +0 -9
  257. package/templates/solid/add-on/solid-ui/assets/src/lib/utils.ts +0 -6
  258. package/templates/solid/add-on/solid-ui/assets/src/styles.css +0 -138
  259. package/templates/solid/add-on/solid-ui/assets/ui.config.json +0 -13
  260. package/templates/solid/add-on/solid-ui/info.json +0 -11
  261. package/templates/solid/add-on/solid-ui/package.json +0 -9
  262. package/templates/solid/add-on/start/assets/app.config.ts +0 -16
  263. package/templates/solid/add-on/start/assets/src/api.ts +0 -6
  264. package/templates/solid/add-on/start/assets/src/client.tsx +0 -7
  265. package/templates/solid/add-on/start/assets/src/router.tsx.ejs +0 -24
  266. package/templates/solid/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +0 -49
  267. package/templates/solid/add-on/start/assets/src/ssr.tsx +0 -12
  268. package/templates/solid/add-on/start/info.json +0 -14
  269. package/templates/solid/add-on/start/package.json +0 -12
  270. package/templates/solid/add-on/store/assets/src/lib/demo-store.ts +0 -13
  271. package/templates/solid/add-on/store/assets/src/routes/demo.store.tsx.ejs +0 -77
  272. package/templates/solid/add-on/store/info.json +0 -13
  273. package/templates/solid/add-on/store/package.json +0 -6
  274. package/templates/solid/add-on/t3env/README.md +0 -16
  275. package/templates/solid/add-on/t3env/assets/src/env.ts +0 -39
  276. package/templates/solid/add-on/t3env/info.json +0 -10
  277. package/templates/solid/add-on/t3env/package.json +0 -6
  278. package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/header-user.tsx +0 -5
  279. package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/provider.tsx +0 -15
  280. package/templates/solid/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx +0 -30
  281. package/templates/solid/add-on/tanstack-query/info.json +0 -13
  282. package/templates/solid/add-on/tanstack-query/package.json +0 -6
  283. package/templates/solid/base/README.md.ejs +0 -215
  284. package/templates/solid/base/_dot_cursorrules.append +0 -35
  285. package/templates/solid/base/_dot_gitignore +0 -5
  286. package/templates/solid/base/_dot_vscode/settings.biome.json +0 -35
  287. package/templates/solid/base/_dot_vscode/settings.json +0 -11
  288. package/templates/solid/base/index.html.ejs +0 -20
  289. package/templates/solid/base/package.biome.json +0 -10
  290. package/templates/solid/base/package.eslintprettier.json +0 -11
  291. package/templates/solid/base/package.json +0 -23
  292. package/templates/solid/base/package.ts.json +0 -5
  293. package/templates/solid/base/package.tw.json +0 -6
  294. package/templates/solid/base/public/favicon.ico +0 -0
  295. package/templates/solid/base/public/logo192.png +0 -0
  296. package/templates/solid/base/public/logo512.png +0 -0
  297. package/templates/solid/base/public/manifest.json +0 -25
  298. package/templates/solid/base/public/robots.txt +0 -3
  299. package/templates/solid/base/src/App.css +0 -0
  300. package/templates/solid/base/src/App.tsx.ejs +0 -47
  301. package/templates/solid/base/src/components/Header.tsx.ejs +0 -26
  302. package/templates/solid/base/src/logo.svg +0 -120
  303. package/templates/solid/base/src/styles.css.ejs +0 -15
  304. package/templates/solid/base/toolchain/.prettierignore +0 -3
  305. package/templates/solid/base/toolchain/biome.json +0 -31
  306. package/templates/solid/base/toolchain/eslint.config.js +0 -5
  307. package/templates/solid/base/toolchain/prettier.config.js +0 -10
  308. package/templates/solid/base/tsconfig.json.ejs +0 -31
  309. package/templates/solid/base/vite.config.js.ejs +0 -22
  310. package/templates/solid/code-router/src/main.tsx.ejs +0 -71
  311. package/templates/solid/example/tanchat/README.md +0 -52
  312. package/templates/solid/example/tanchat/assets/ai-streaming-server/README.md +0 -110
  313. package/templates/solid/example/tanchat/assets/ai-streaming-server/_dot_env.example +0 -1
  314. package/templates/solid/example/tanchat/assets/ai-streaming-server/package.json +0 -26
  315. package/templates/solid/example/tanchat/assets/ai-streaming-server/src/index.ts +0 -102
  316. package/templates/solid/example/tanchat/assets/ai-streaming-server/tsconfig.json +0 -15
  317. package/templates/solid/example/tanchat/assets/src/components/demo.SettingsDialog.tsx +0 -149
  318. package/templates/solid/example/tanchat/assets/src/demo.index.css +0 -227
  319. package/templates/solid/example/tanchat/assets/src/lib/demo-store.ts +0 -13
  320. package/templates/solid/example/tanchat/assets/src/routes/example.chat.tsx +0 -435
  321. package/templates/solid/example/tanchat/assets/src/store/demo.hooks.ts +0 -17
  322. package/templates/solid/example/tanchat/assets/src/store/demo.store.ts +0 -133
  323. package/templates/solid/example/tanchat/info.json +0 -14
  324. package/templates/solid/example/tanchat/package.json +0 -7
  325. package/templates/solid/file-router/package.fr.json +0 -5
  326. package/templates/solid/file-router/src/main.tsx.ejs +0 -47
  327. package/templates/solid/file-router/src/routes/__root.tsx.ejs +0 -41
  328. package/templates/solid/file-router/src/routes/index.tsx +0 -43
  329. package/tests/cra.test.ts +0 -293
  330. package/tests/snapshots/cra/cr-js-npm.json +0 -33
  331. package/tests/snapshots/cra/cr-ts-npm.json +0 -34
  332. package/tests/snapshots/cra/cr-ts-start-npm.json +0 -38
  333. package/tests/snapshots/cra/fr-ts-npm.json +0 -34
  334. package/tests/snapshots/cra/fr-ts-tw-npm.json +0 -33
  335. package/tests/snapshots/cra/solid-cr-js-npm.json +0 -31
  336. package/tests/snapshots/cra/solid-cr-ts-npm.json +0 -32
  337. package/tests/snapshots/cra/solid-cr-ts-start-npm.json +0 -36
  338. package/tests/snapshots/cra/solid-fr-ts-npm.json +0 -33
  339. package/tests/snapshots/cra/solid-fr-ts-tw-npm.json +0 -32
  340. package/tests/test-utilities.ts +0 -87
@@ -1 +1,6 @@
1
1
  export declare function sortObject(obj: Record<string, string>): Record<string, string>;
2
+ export declare function jsSafeName(name: string): string;
3
+ export declare function formatCommand({ command, args, }: {
4
+ command: string;
5
+ args: Array<string>;
6
+ }): string;
package/dist/types.js CHANGED
@@ -1 +1,65 @@
1
- export {};
1
+ import z from 'zod';
2
+ export const AddOnBaseSchema = z.object({
3
+ id: z.string(),
4
+ name: z.string(),
5
+ description: z.string(),
6
+ author: z.string().optional(),
7
+ version: z.string().optional(),
8
+ link: z.string().optional(),
9
+ license: z.string().optional(),
10
+ warning: z.string().optional(),
11
+ type: z.enum(['add-on', 'example', 'starter', 'toolchain']),
12
+ command: z
13
+ .object({
14
+ command: z.string(),
15
+ args: z.array(z.string()).optional(),
16
+ })
17
+ .optional(),
18
+ routes: z
19
+ .array(z.object({
20
+ url: z.string().optional(),
21
+ name: z.string().optional(),
22
+ path: z.string(),
23
+ jsName: z.string(),
24
+ }))
25
+ .optional(),
26
+ packageAdditions: z
27
+ .object({
28
+ dependencies: z.record(z.string(), z.string()).optional(),
29
+ devDependencies: z.record(z.string(), z.string()).optional(),
30
+ scripts: z.record(z.string(), z.string()).optional(),
31
+ })
32
+ .optional(),
33
+ shadcnComponents: z.array(z.string()).optional(),
34
+ dependsOn: z.array(z.string()).optional(),
35
+ smallLogo: z.string().optional(),
36
+ logo: z.string().optional(),
37
+ addOnSpecialSteps: z.array(z.string()).optional(),
38
+ createSpecialSteps: z.array(z.string()).optional(),
39
+ });
40
+ export const StarterSchema = AddOnBaseSchema.extend({
41
+ framework: z.string(),
42
+ mode: z.string(),
43
+ typescript: z.boolean(),
44
+ tailwind: z.boolean(),
45
+ banner: z.string().optional(),
46
+ });
47
+ export const StarterCompiledSchema = StarterSchema.extend({
48
+ files: z.record(z.string(), z.string()),
49
+ deletedFiles: z.array(z.string()),
50
+ });
51
+ export const IntegrationSchema = z.object({
52
+ type: z.string(),
53
+ path: z.string(),
54
+ jsName: z.string(),
55
+ });
56
+ export const AddOnInfoSchema = AddOnBaseSchema.extend({
57
+ modes: z.array(z.string()),
58
+ integrations: z.array(IntegrationSchema).optional(),
59
+ phase: z.enum(['setup', 'add-on']),
60
+ readme: z.string().optional(),
61
+ });
62
+ export const AddOnCompiledSchema = AddOnInfoSchema.extend({
63
+ files: z.record(z.string(), z.string()),
64
+ deletedFiles: z.array(z.string()),
65
+ });
package/dist/utils.js CHANGED
@@ -6,3 +6,12 @@ export function sortObject(obj) {
6
6
  return acc;
7
7
  }, {});
8
8
  }
9
+ export function jsSafeName(name) {
10
+ return name
11
+ .split(/[^a-zA-Z0-9]/)
12
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
13
+ .join('');
14
+ }
15
+ export function formatCommand({ command, args, }) {
16
+ return `${command} ${args.join(' ')}`.trim();
17
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/cta-engine",
3
- "version": "0.10.0-alpha.25",
3
+ "version": "0.10.0-alpha.26",
4
4
  "description": "Tanstack Application Builder Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -15,35 +15,32 @@
15
15
  "url": "https://github.com/sponsors/tannerlinsley"
16
16
  },
17
17
  "keywords": [
18
- "react",
19
18
  "tanstack",
20
19
  "router",
21
- "create-react-app"
20
+ "create-tsrouter-app"
22
21
  ],
23
22
  "author": "Jack Herrington <jherr@pobox.com>",
24
23
  "license": "MIT",
25
24
  "dependencies": {
26
- "@clack/prompts": "^0.10.0",
27
- "@modelcontextprotocol/sdk": "^1.6.0",
28
- "chalk": "^5.4.1",
29
- "commander": "^13.1.0",
30
25
  "ejs": "^3.1.10",
31
26
  "execa": "^9.5.2",
32
- "express": "^4.21.2",
27
+ "ignore": "^7.0.3",
33
28
  "memfs": "^4.17.0",
29
+ "parse-gitignore": "^2.0.0",
34
30
  "prettier": "^3.5.0",
31
+ "rimraf": "^6.0.1",
35
32
  "zod": "^3.24.2"
36
33
  },
37
34
  "devDependencies": {
38
35
  "@tanstack/config": "^0.16.2",
39
36
  "@types/ejs": "^3.1.5",
40
- "@types/express": "^5.0.0",
41
37
  "@types/node": "^22.13.4",
38
+ "@types/parse-gitignore": "^1.0.2",
39
+ "@vitest/coverage-v8": "3.1.1",
42
40
  "eslint": "^9.20.0",
43
- "eslint-plugin-react-hooks": "^5.1.0",
44
- "eslint-plugin-unused-imports": "^4.1.4",
45
41
  "typescript": "^5.6.3",
46
- "vitest": "^3.0.8"
42
+ "vitest": "^3.0.8",
43
+ "vitest-fetch-mock": "^0.4.5"
47
44
  },
48
45
  "scripts": {}
49
46
  }
package/src/add-ons.ts CHANGED
@@ -1,100 +1,20 @@
1
- import { readFile } from 'node:fs/promises'
2
- import { existsSync, readdirSync, statSync } from 'node:fs'
3
- import { resolve } from 'node:path'
4
- import chalk from 'chalk'
1
+ import { loadRemoteAddOn } from './custom-add-ons/add-on.js'
5
2
 
6
- import { getTemplatesRoot } from './templates.js'
7
- import { DEFAULT_FRAMEWORK } from './constants.js'
8
- import { readFileHelper } from './file-helper.js'
3
+ import type { AddOn, Framework, Mode } from './types.js'
9
4
 
10
- import type { AddOn, CliOptions, Framework, TemplateOptions } from './types.js'
11
-
12
- function isDirectory(path: string): boolean {
13
- return statSync(path).isDirectory()
14
- }
15
-
16
- function findFilesRecursively(path: string, files: Record<string, string>) {
17
- const dirFiles = readdirSync(path)
18
- for (const file of dirFiles) {
19
- const filePath = resolve(path, file)
20
- if (isDirectory(filePath)) {
21
- findFilesRecursively(filePath, files)
22
- } else {
23
- files[filePath] = readFileHelper(filePath)
24
- }
25
- }
26
- }
27
-
28
- export async function getAllAddOns(
29
- framework: Framework,
30
- template: string,
31
- ): Promise<Array<AddOn>> {
32
- const addOns: Array<AddOn> = []
33
-
34
- for (const type of ['add-on', 'example']) {
35
- const addOnsBase = resolve(getTemplatesRoot(), framework, type)
36
-
37
- if (!existsSync(addOnsBase)) {
38
- continue
39
- }
40
-
41
- for (const dir of await readdirSync(addOnsBase).filter((file) =>
42
- isDirectory(resolve(addOnsBase, file)),
43
- )) {
44
- const filePath = resolve(addOnsBase, dir, 'info.json')
45
- const fileContent = await readFile(filePath, 'utf-8')
46
- const info = JSON.parse(fileContent)
47
-
48
- if (!info.templates.includes(template)) {
49
- continue
50
- }
51
-
52
- let packageAdditions: Record<string, string> = {}
53
- if (existsSync(resolve(addOnsBase, dir, 'package.json'))) {
54
- packageAdditions = JSON.parse(
55
- await readFile(resolve(addOnsBase, dir, 'package.json'), 'utf-8'),
56
- )
57
- }
58
-
59
- let readme: string | undefined
60
- if (existsSync(resolve(addOnsBase, dir, 'README.md'))) {
61
- readme = await readFile(resolve(addOnsBase, dir, 'README.md'), 'utf-8')
62
- }
63
-
64
- const absoluteFiles: Record<string, string> = {}
65
- const assetsDir = resolve(addOnsBase, dir, 'assets')
66
- if (existsSync(assetsDir)) {
67
- await findFilesRecursively(assetsDir, absoluteFiles)
68
- }
69
- const files: Record<string, string> = {}
70
- for (const file of Object.keys(absoluteFiles)) {
71
- files[file.replace(assetsDir, '.')] = absoluteFiles[file]
72
- }
73
-
74
- addOns.push({
75
- ...info,
76
- id: dir,
77
- type,
78
- packageAdditions,
79
- readme,
80
- files,
81
- deletedFiles: [],
82
- })
83
- }
84
- }
85
-
86
- return addOns
5
+ export function getAllAddOns(framework: Framework, mode: Mode): Array<AddOn> {
6
+ return framework.getAddOns().filter((a) => a.modes.includes(mode))
87
7
  }
88
8
 
89
9
  // Turn the list of chosen add-on IDs into a final list of add-ons by resolving dependencies
90
10
  export async function finalizeAddOns(
91
11
  framework: Framework,
92
- template: string,
12
+ mode: Mode,
93
13
  chosenAddOnIDs: Array<string>,
94
14
  ): Promise<Array<AddOn>> {
95
15
  const finalAddOnIDs = new Set(chosenAddOnIDs)
96
16
 
97
- const addOns = await getAllAddOns(framework, template)
17
+ const addOns = getAllAddOns(framework, mode)
98
18
 
99
19
  for (const addOnID of finalAddOnIDs) {
100
20
  let addOn: AddOn | undefined
@@ -120,46 +40,10 @@ export async function finalizeAddOns(
120
40
  const finalAddOns = [...finalAddOnIDs].map(
121
41
  (id) => addOns.find((a) => a.id === id)!,
122
42
  )
123
- return finalAddOns
124
- }
125
43
 
126
- export async function listAddOns(
127
- options: CliOptions,
128
- {
129
- forcedMode,
130
- forcedAddOns = [],
131
- }: {
132
- forcedMode?: TemplateOptions
133
- forcedAddOns?: Array<string>
134
- },
135
- ) {
136
- let mode = forcedMode
137
- if (!mode) {
138
- if (options.template) {
139
- mode =
140
- options.template === 'file-router'
141
- ? 'file-router'
142
- : ('code-router' as TemplateOptions)
143
- } else {
144
- mode = 'code-router' as TemplateOptions
145
- }
146
- }
147
- const addOns = await getAllAddOns(
148
- options.framework || DEFAULT_FRAMEWORK,
149
- mode,
150
- )
151
- for (const addOn of addOns.filter((a) => !forcedAddOns.includes(a.id))) {
152
- console.log(`${chalk.bold(addOn.id)}: ${addOn.description}`)
153
- }
44
+ return finalAddOns
154
45
  }
155
46
 
156
47
  function loadAddOn(addOn: AddOn): AddOn {
157
48
  return addOn
158
49
  }
159
-
160
- export async function loadRemoteAddOn(url: string): Promise<AddOn> {
161
- const response = await fetch(url)
162
- const fileContent = await response.json()
163
- fileContent.id = url
164
- return fileContent
165
- }
@@ -0,0 +1,274 @@
1
+ import { basename, resolve } from 'node:path'
2
+
3
+ import { CONFIG_FILE } from './constants.js'
4
+ import { finalizeAddOns } from './add-ons.js'
5
+ import { getFrameworkById } from './frameworks.js'
6
+ import { createMemoryEnvironment } from './environment.js'
7
+ import { createApp } from './create-app.js'
8
+ import {
9
+ readConfigFileFromEnvironment,
10
+ writeConfigFileToEnvironment,
11
+ } from './config-file.js'
12
+ import { formatCommand } from './utils.js'
13
+ import { packageManagerInstall } from './package-manager.js'
14
+ import {
15
+ isBase64,
16
+ recursivelyGatherFilesFromEnvironment,
17
+ } from './file-helpers.js'
18
+ import { mergePackageJSON } from './package-json.js'
19
+ import { runSpecialSteps } from './special-steps/index.js'
20
+
21
+ import type { Environment, Mode, Options } from './types.js'
22
+ import type { PersistedOptions } from './config-file.js'
23
+
24
+ export async function hasPendingGitChanges(
25
+ environment: Environment,
26
+ cwd: string,
27
+ ) {
28
+ const { stdout } = await environment.execute(
29
+ 'git',
30
+ ['status', '--porcelain'],
31
+ cwd,
32
+ )
33
+ return stdout.length > 0
34
+ }
35
+
36
+ async function createOptions(
37
+ json: PersistedOptions,
38
+ addOns: Array<string>,
39
+ targetDir: string,
40
+ ): Promise<Options> {
41
+ const framework = getFrameworkById(json.framework)
42
+
43
+ // TODO: Load the starter
44
+
45
+ return {
46
+ ...json,
47
+ framework,
48
+ tailwind: true,
49
+ addOns: true,
50
+ chosenAddOns: await finalizeAddOns(framework!, json.mode as Mode, [
51
+ ...json.existingAddOns,
52
+ ...addOns,
53
+ ]),
54
+ targetDir,
55
+ } as Options
56
+ }
57
+
58
+ async function runCreateApp(options: Required<Options>) {
59
+ const { environment, output } = createMemoryEnvironment(options.targetDir)
60
+ await createApp(environment, options)
61
+ return output
62
+ }
63
+
64
+ export async function getCurrentConfiguration(
65
+ environment: Environment,
66
+ cwd: string,
67
+ ) {
68
+ const persistedOptions = await readConfigFileFromEnvironment(environment, cwd)
69
+ if (!persistedOptions) {
70
+ environment.error(
71
+ 'There is no .cta.json file in your project.',
72
+ 'This is probably because this was created with an older version of create-tsrouter-app.',
73
+ )
74
+ return undefined
75
+ }
76
+
77
+ return persistedOptions
78
+ }
79
+
80
+ export async function writeFiles(
81
+ environment: Environment,
82
+ cwd: string,
83
+ output: {
84
+ files: Record<string, string>
85
+ deletedFiles: Array<string>
86
+ },
87
+ forced: boolean,
88
+ ) {
89
+ const currentFiles = await recursivelyGatherFilesFromEnvironment(
90
+ environment,
91
+ cwd,
92
+ false,
93
+ )
94
+
95
+ const overwrittenFiles: Array<string> = []
96
+ const changedFiles: Array<string> = []
97
+ for (const file of Object.keys(output.files)) {
98
+ const relativeFile = file.replace(cwd, '')
99
+ if (currentFiles[relativeFile]) {
100
+ if (currentFiles[relativeFile] !== output.files[file]) {
101
+ overwrittenFiles.push(relativeFile)
102
+ }
103
+ } else {
104
+ changedFiles.push(relativeFile)
105
+ }
106
+ }
107
+
108
+ if (!forced && overwrittenFiles.length) {
109
+ environment.warn(
110
+ 'The following will be overwritten',
111
+ [...overwrittenFiles, ...output.deletedFiles].join('\n'),
112
+ )
113
+ const shouldContinue = await environment.confirm('Do you want to continue?')
114
+ if (!shouldContinue) {
115
+ throw new Error('User cancelled')
116
+ }
117
+ }
118
+
119
+ for (const file of output.deletedFiles) {
120
+ if (environment.exists(resolve(cwd, file))) {
121
+ await environment.deleteFile(resolve(cwd, file))
122
+ }
123
+ }
124
+
125
+ environment.startStep({
126
+ id: 'write-files',
127
+ type: 'file',
128
+ message: 'Writing add-on files...',
129
+ })
130
+
131
+ for (const file of [...changedFiles, ...overwrittenFiles]) {
132
+ const fName = basename(file)
133
+ const contents = output.files[file]
134
+ if (fName === 'package.json') {
135
+ const currentJson = JSON.parse(
136
+ await environment.readFile(resolve(cwd, file)),
137
+ )
138
+ const newJSON = mergePackageJSON(currentJson, JSON.parse(contents))
139
+ environment.writeFile(
140
+ resolve(cwd, file),
141
+ JSON.stringify(newJSON, null, 2),
142
+ )
143
+ } else if (fName !== CONFIG_FILE) {
144
+ if (isBase64(contents)) {
145
+ await environment.writeFileBase64(resolve(cwd, file), contents)
146
+ } else {
147
+ await environment.writeFile(resolve(cwd, file), contents)
148
+ }
149
+ }
150
+ }
151
+
152
+ environment.finishStep('write-files', 'Add-on files written')
153
+ }
154
+
155
+ export async function runNewCommands(
156
+ environment: Environment,
157
+ originalOptions: PersistedOptions,
158
+ cwd: string,
159
+ output: {
160
+ commands: Array<{
161
+ command: string
162
+ args: Array<string>
163
+ }>
164
+ },
165
+ ) {
166
+ const originalOutput = await runCreateApp({
167
+ ...(await createOptions(originalOptions, [], cwd)),
168
+ } as Required<Options>)
169
+
170
+ const originalCommands = new Set(
171
+ originalOutput.commands.map((c) => [c.command, ...c.args].join(' ')),
172
+ )
173
+
174
+ for (const command of output.commands) {
175
+ const commandString = [command.command, ...command.args].join(' ')
176
+ if (!originalCommands.has(commandString)) {
177
+ environment.startStep({
178
+ id: 'run-commands',
179
+ type: 'command',
180
+ message: `Running ${formatCommand({ command: command.command, args: command.args })}...`,
181
+ })
182
+ await environment.execute(command.command, command.args, cwd)
183
+ environment.finishStep('run-commands', 'Setup commands complete')
184
+ }
185
+ }
186
+ }
187
+
188
+ export async function addToApp(
189
+ environment: Environment,
190
+ addOns: Array<string>,
191
+ cwd: string,
192
+ options?: {
193
+ forced?: boolean
194
+ },
195
+ ) {
196
+ const persistedOptions = await getCurrentConfiguration(environment, cwd)
197
+ if (!persistedOptions) {
198
+ return
199
+ }
200
+
201
+ if (!options?.forced && (await hasPendingGitChanges(environment, cwd))) {
202
+ environment.error(
203
+ 'You have pending git changes.',
204
+ 'Please commit or stash them before adding add-ons.',
205
+ )
206
+ return
207
+ }
208
+
209
+ environment.intro(`Adding ${addOns.join(', ')} to the project...`)
210
+ environment.startStep({
211
+ id: 'processing-new-app-setup',
212
+ type: 'file',
213
+ message: 'Processing new app setup...',
214
+ })
215
+
216
+ const newOptions = await createOptions(persistedOptions, addOns, cwd)
217
+
218
+ const output = await runCreateApp({
219
+ ...newOptions,
220
+ targetDir: cwd,
221
+ } as Required<Options>)
222
+
223
+ await writeFiles(environment, cwd, output, !!options?.forced)
224
+
225
+ environment.finishStep(
226
+ 'processing-new-app-setup',
227
+ 'Application files written',
228
+ )
229
+
230
+ // Run any special steps for the new add-ons
231
+
232
+ const specialSteps = new Set<string>([])
233
+ for (const addOn of newOptions.chosenAddOns) {
234
+ for (const step of addOn.addOnSpecialSteps || []) {
235
+ if (addOns.includes(addOn.id)) {
236
+ specialSteps.add(step)
237
+ }
238
+ }
239
+ }
240
+ if (specialSteps.size) {
241
+ await runSpecialSteps(environment, newOptions, Array.from(specialSteps))
242
+ }
243
+
244
+ // Install dependencies
245
+
246
+ environment.startStep({
247
+ id: 'install-dependencies',
248
+ type: 'package-manager',
249
+ message: `Installing dependencies via ${newOptions.packageManager}...`,
250
+ })
251
+ const s = environment.spinner()
252
+ s.start(`Installing dependencies via ${newOptions.packageManager}...`)
253
+ await packageManagerInstall(
254
+ environment,
255
+ newOptions.targetDir,
256
+ newOptions.packageManager,
257
+ )
258
+ s.stop(`Installed dependencies`)
259
+ environment.finishStep('install-dependencies', 'Dependencies installed')
260
+
261
+ // Handle new commands
262
+
263
+ await runNewCommands(environment, persistedOptions, cwd, output)
264
+
265
+ environment.startStep({
266
+ id: 'write-config-file',
267
+ type: 'file',
268
+ message: 'Writing config file...',
269
+ })
270
+ writeConfigFileToEnvironment(environment, newOptions)
271
+ environment.finishStep('write-config-file', 'Config file written')
272
+
273
+ environment.outro('Add-ons added successfully!')
274
+ }
@@ -1,43 +1,52 @@
1
- import { readFile } from 'node:fs/promises'
2
1
  import { resolve } from 'node:path'
3
2
 
4
3
  import { CONFIG_FILE } from './constants.js'
5
4
 
6
- import type { Environment, Options } from './types'
5
+ import type { Environment, Options } from './types.js'
7
6
 
8
- export type PersistedOptions = Exclude<
7
+ export type PersistedOptions = Omit<
9
8
  Partial<Options>,
10
- 'addOns' | 'chosenAddOns'
9
+ 'addOns' | 'chosenAddOns' | 'framework' | 'starter' | 'targetDir'
11
10
  > & {
11
+ framework: string
12
12
  version: number
13
13
  existingAddOns: Array<string>
14
+ starter?: string
14
15
  }
15
16
 
16
- export async function writeConfigFile(
17
- environment: Environment,
18
- targetDir: string,
19
- options: Options,
20
- ) {
21
- const persistedOptions: PersistedOptions = {
22
- ...options,
17
+ function createPersistedOptions(options: Options): PersistedOptions {
18
+ /* eslint-disable unused-imports/no-unused-vars */
19
+ const { chosenAddOns, framework, targetDir, ...rest } = options
20
+ /* eslint-enable unused-imports/no-unused-vars */
21
+ return {
22
+ ...rest,
23
23
  version: 1,
24
+ framework: options.framework.id,
24
25
  existingAddOns: options.chosenAddOns.map((addOn) => addOn.id),
26
+ starter: options.starter?.id ?? undefined,
25
27
  }
26
- delete persistedOptions.addOns
27
- delete persistedOptions.chosenAddOns
28
+ }
28
29
 
30
+ export async function writeConfigFileToEnvironment(
31
+ environment: Environment,
32
+ options: Options,
33
+ ) {
29
34
  await environment.writeFile(
30
- resolve(targetDir, CONFIG_FILE),
31
- JSON.stringify(persistedOptions, null, 2),
35
+ resolve(options.targetDir, CONFIG_FILE),
36
+ JSON.stringify(createPersistedOptions(options), null, 2),
32
37
  )
33
38
  }
34
39
 
35
- export async function readConfigFile(
40
+ export async function readConfigFileFromEnvironment(
41
+ environment: Environment,
36
42
  targetDir: string,
37
43
  ): Promise<PersistedOptions | null> {
38
44
  try {
39
45
  const configFile = resolve(targetDir, CONFIG_FILE)
40
- const config = await readFile(configFile, 'utf8')
46
+ const config = await environment.readFile(configFile)
47
+
48
+ // TODO: Look for old config files and convert them to the new format
49
+
41
50
  return JSON.parse(config)
42
51
  } catch {
43
52
  return null
package/src/constants.ts CHANGED
@@ -1,9 +1,4 @@
1
- import type { Framework } from './types.js'
2
-
3
1
  export const CODE_ROUTER = 'code-router'
4
2
  export const FILE_ROUTER = 'file-router'
5
3
 
6
- export const SUPPORTED_FRAMEWORKS: Array<Framework> = ['solid', 'react']
7
- export const DEFAULT_FRAMEWORK: Framework = 'react'
8
-
9
4
  export const CONFIG_FILE = '.cta.json'