@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
@@ -0,0 +1,261 @@
1
+ import { readFile } from 'node:fs/promises'
2
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
3
+ import { basename, dirname, resolve } from 'node:path'
4
+
5
+ import { AddOnCompiledSchema } from '../types.js'
6
+ import { createIgnore, recursivelyGatherFiles } from '../file-helpers.js'
7
+ import {
8
+ compareFilesRecursively,
9
+ createAppOptionsFromPersisted,
10
+ createPackageAdditions,
11
+ readCurrentProjectOptions,
12
+ runCreateApp,
13
+ } from './shared.js'
14
+
15
+ import type { PersistedOptions } from '../config-file'
16
+ import type {
17
+ AddOn,
18
+ AddOnCompiled,
19
+ AddOnInfo,
20
+ Environment,
21
+ Options,
22
+ } from '../types'
23
+
24
+ const ADD_ON_DIR = '.add-on'
25
+
26
+ export const ADD_ON_IGNORE_FILES: Array<string> = [
27
+ 'main.jsx',
28
+ 'App.jsx',
29
+ 'main.tsx',
30
+ 'App.tsx',
31
+ 'routeTree.gen.ts',
32
+ ]
33
+
34
+ const INFO_FILE = '.add-on/info.json'
35
+ const COMPILED_FILE = 'add-on.json'
36
+
37
+ const ASSETS_DIR = 'assets'
38
+
39
+ export function camelCase(str: string) {
40
+ return str
41
+ .split(/(\.|-|\/)/)
42
+ .filter((part) => /^[a-zA-Z]+$/.test(part))
43
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
44
+ .join('')
45
+ }
46
+
47
+ export function templatize(routeCode: string, routeFile: string) {
48
+ let code = routeCode
49
+
50
+ // Replace the import
51
+ code = code.replace(
52
+ /import { createFileRoute } from ['"]@tanstack\/react-router['"]/g,
53
+ `import { <% if (fileRouter) { %>createFileRoute<% } else { %>createRoute<% } %> } from '@tanstack/react-router'`,
54
+ )
55
+
56
+ // Extract route path and definition, then transform the route declaration
57
+ const routeMatch = code.match(
58
+ /export\s+const\s+Route\s*=\s*createFileRoute\(['"]([^'"]+)['"]\)\s*\(\{([^}]+)\}\)/,
59
+ )
60
+
61
+ let path = ''
62
+
63
+ if (routeMatch) {
64
+ const fullMatch = routeMatch[0]
65
+ path = routeMatch[1]
66
+ const routeDefinition = routeMatch[2]
67
+ code = code.replace(
68
+ fullMatch,
69
+ `<% if (codeRouter) { %>
70
+ import type { RootRoute } from '@tanstack/react-router'
71
+ <% } else { %>
72
+ export const Route = createFileRoute('${path}')({${routeDefinition}})
73
+ <% } %>`,
74
+ )
75
+
76
+ code += `
77
+ <% if (codeRouter) { %>
78
+ export default (parentRoute: RootRoute) => createRoute({
79
+ path: '${path}',
80
+ ${routeDefinition}
81
+ getParentRoute: () => parentRoute,
82
+ })
83
+ <% } %>
84
+ `
85
+ } else {
86
+ console.error(`No route found in the file: ${routeFile}`)
87
+ }
88
+
89
+ const name = basename(path)
90
+ .replace('.tsx', '')
91
+ .replace(/^demo/, '')
92
+ .replace('.', ' ')
93
+ .trim()
94
+
95
+ const jsName = camelCase(basename(path))
96
+
97
+ return { url: path, code, name, jsName }
98
+ }
99
+
100
+ export async function validateAddOnSetup(environment: Environment) {
101
+ const options = await readCurrentProjectOptions(environment)
102
+
103
+ if (options.mode !== 'file-router') {
104
+ environment.error(
105
+ 'This project is not using file-router mode.',
106
+ 'To create an add-on, the project must be created with the file-router mode.',
107
+ )
108
+ process.exit(1)
109
+ }
110
+ if (!options.tailwind) {
111
+ environment.error(
112
+ 'This project is not using Tailwind CSS.',
113
+ 'To create an add-on, the project must be created with Tailwind CSS.',
114
+ )
115
+ process.exit(1)
116
+ }
117
+ if (!options.typescript) {
118
+ environment.error(
119
+ 'This project is not using TypeScript.',
120
+ 'To create an add-on, the project must be created with TypeScript.',
121
+ )
122
+ process.exit(1)
123
+ }
124
+ }
125
+
126
+ export async function readOrGenerateAddOnInfo(
127
+ options: PersistedOptions,
128
+ ): Promise<AddOnInfo> {
129
+ return existsSync(INFO_FILE)
130
+ ? JSON.parse((await readFile(INFO_FILE)).toString())
131
+ : ({
132
+ id: `${options.projectName}-add-on`,
133
+ name: `${options.projectName}-add-on`,
134
+ version: '0.0.1',
135
+ description: 'Add-on',
136
+ author: 'Jane Smith <jane.smith@example.com>',
137
+ license: 'MIT',
138
+ link: `https://github.com/jane-smith/${options.projectName}-add-on`,
139
+ shadcnComponents: [],
140
+ framework: options.framework,
141
+ modes: [options.mode],
142
+ routes: [],
143
+ warning: '',
144
+ phase: 'add-on',
145
+ type: 'add-on',
146
+ packageAdditions: {
147
+ scripts: {},
148
+ dependencies: {},
149
+ devDependencies: {},
150
+ },
151
+ dependsOn: options.existingAddOns,
152
+ } as AddOnInfo)
153
+ }
154
+
155
+ export async function generateProject(persistedOptions: PersistedOptions) {
156
+ const info = await readOrGenerateAddOnInfo(persistedOptions)
157
+
158
+ const output = await runCreateApp(
159
+ (await createAppOptionsFromPersisted(
160
+ persistedOptions,
161
+ )) as Required<Options>,
162
+ )
163
+
164
+ return { info, output }
165
+ }
166
+
167
+ export async function buildAssetsDirectory(
168
+ output: {
169
+ files: Record<string, string>
170
+ },
171
+ info: AddOnInfo,
172
+ ) {
173
+ const assetsDir = resolve(ADD_ON_DIR, ASSETS_DIR)
174
+ const ignore = createIgnore(process.cwd())
175
+
176
+ if (!existsSync(assetsDir)) {
177
+ const changedFiles: Record<string, string> = {}
178
+ await compareFilesRecursively('.', ignore, output.files, changedFiles)
179
+
180
+ for (const file of Object.keys(changedFiles).filter(
181
+ (file) => !ADD_ON_IGNORE_FILES.includes(basename(file)),
182
+ )) {
183
+ mkdirSync(dirname(resolve(assetsDir, file)), {
184
+ recursive: true,
185
+ })
186
+ if (file.includes('/routes/')) {
187
+ const { url, code, name, jsName } = templatize(changedFiles[file], file)
188
+ info.routes ||= []
189
+ if (!info.routes.find((r) => r.url === url)) {
190
+ info.routes.push({
191
+ url,
192
+ name,
193
+ jsName,
194
+ path: file,
195
+ })
196
+ }
197
+ writeFileSync(resolve(assetsDir, `${file}.ejs`), code)
198
+ } else {
199
+ writeFileSync(resolve(assetsDir, file), changedFiles[file])
200
+ }
201
+ }
202
+ }
203
+ }
204
+
205
+ export async function updateAddOnInfo(environment: Environment) {
206
+ const { info, output } = await generateProject(
207
+ await readCurrentProjectOptions(environment),
208
+ )
209
+
210
+ info.packageAdditions = createPackageAdditions(
211
+ JSON.parse(output.files['./package.json']),
212
+ JSON.parse((await readFile('package.json')).toString()),
213
+ )
214
+
215
+ await buildAssetsDirectory(output, info)
216
+
217
+ mkdirSync(resolve(dirname(INFO_FILE)), { recursive: true })
218
+ writeFileSync(INFO_FILE, JSON.stringify(info, null, 2))
219
+ }
220
+
221
+ export async function compileAddOn(environment: Environment) {
222
+ const info = await readOrGenerateAddOnInfo(
223
+ await readCurrentProjectOptions(environment),
224
+ )
225
+
226
+ const assetsDir = resolve(ADD_ON_DIR, ASSETS_DIR)
227
+
228
+ const compiledInfo: AddOnCompiled = {
229
+ ...info,
230
+ files: await recursivelyGatherFiles(assetsDir),
231
+ deletedFiles: [],
232
+ }
233
+
234
+ writeFileSync(COMPILED_FILE, JSON.stringify(compiledInfo, null, 2))
235
+ }
236
+
237
+ export async function initAddOn(environment: Environment) {
238
+ await validateAddOnSetup(environment)
239
+ await updateAddOnInfo(environment)
240
+ await compileAddOn(environment)
241
+ }
242
+
243
+ export async function loadRemoteAddOn(url: string): Promise<AddOn> {
244
+ const response = await fetch(url)
245
+ const jsonContent = await response.json()
246
+
247
+ const checked = AddOnCompiledSchema.safeParse(jsonContent)
248
+ if (!checked.success) {
249
+ throw new Error(`Invalid add-on: ${url}`)
250
+ }
251
+
252
+ const addOn = checked.data
253
+ addOn.id = url
254
+ const out = {
255
+ ...addOn,
256
+ getFiles: () => Promise.resolve(Object.keys(addOn.files)),
257
+ getFileContents: (path: string) => Promise.resolve(addOn.files[path]),
258
+ getDeletedFiles: () => Promise.resolve(addOn.deletedFiles),
259
+ }
260
+ return out
261
+ }
@@ -0,0 +1,161 @@
1
+ import { readdir } from 'node:fs/promises'
2
+ import { resolve } from 'node:path'
3
+ import { createApp } from '../create-app.js'
4
+ import { createMemoryEnvironment } from '../environment.js'
5
+ import { finalizeAddOns } from '../add-ons.js'
6
+ import { getFrameworkById } from '../frameworks.js'
7
+ import { readConfigFileFromEnvironment } from '../config-file.js'
8
+ import { readFileHelper } from '../file-helpers.js'
9
+ import { loadStarter } from '../custom-add-ons/starter.js'
10
+
11
+ import type { Environment, Mode, Options, SerializedOptions } from '../types.js'
12
+ import type { PersistedOptions } from '../config-file.js'
13
+
14
+ export function createPackageAdditions(
15
+ originalPackageJson: Record<string, any>,
16
+ currentPackageJson: Record<string, any>,
17
+ ) {
18
+ const packageAdditions: Record<string, any> = {}
19
+
20
+ const scripts: Record<string, any> = {}
21
+ for (const script of Object.keys(currentPackageJson.scripts || {})) {
22
+ if (
23
+ originalPackageJson.scripts[script] !== currentPackageJson.scripts[script]
24
+ ) {
25
+ scripts[script] = currentPackageJson.scripts[script]
26
+ }
27
+ }
28
+ packageAdditions.scripts = Object.keys(scripts).length ? scripts : undefined
29
+
30
+ const dependencies: Record<string, string> = {}
31
+ for (const dependency of Object.keys(currentPackageJson.dependencies || {})) {
32
+ if (
33
+ originalPackageJson.dependencies[dependency] !==
34
+ currentPackageJson.dependencies[dependency]
35
+ ) {
36
+ dependencies[dependency] = currentPackageJson.dependencies[dependency]
37
+ }
38
+ }
39
+ packageAdditions.dependencies = Object.keys(dependencies).length
40
+ ? dependencies
41
+ : undefined
42
+
43
+ const devDependencies: Record<string, string> = {}
44
+ for (const dependency of Object.keys(
45
+ currentPackageJson.devDependencies || {},
46
+ )) {
47
+ if (
48
+ originalPackageJson.devDependencies[dependency] !==
49
+ currentPackageJson.devDependencies[dependency]
50
+ ) {
51
+ devDependencies[dependency] =
52
+ currentPackageJson.devDependencies[dependency]
53
+ }
54
+ }
55
+ packageAdditions.devDependencies = Object.keys(devDependencies).length
56
+ ? devDependencies
57
+ : undefined
58
+
59
+ return packageAdditions
60
+ }
61
+
62
+ export async function createAppOptionsFromPersisted(
63
+ json: PersistedOptions,
64
+ ): Promise<Options> {
65
+ /* eslint-disable unused-imports/no-unused-vars */
66
+ const { version, ...rest } = json
67
+ /* eslint-enable unused-imports/no-unused-vars */
68
+ const framework = getFrameworkById(rest.framework)
69
+ return {
70
+ ...rest,
71
+ mode: json.mode as Mode,
72
+ projectName: json.projectName!,
73
+ typescript: json.typescript!,
74
+ tailwind: json.tailwind!,
75
+ git: json.git!,
76
+ packageManager: json.packageManager!,
77
+ targetDir: '',
78
+ framework: framework!,
79
+ starter: json.starter ? await loadStarter(json.starter) : undefined,
80
+ chosenAddOns: await finalizeAddOns(framework!, json.mode as Mode, [
81
+ ...json.existingAddOns,
82
+ ]),
83
+ }
84
+ }
85
+
86
+ export function createSerializedOptionsFromPersisted(
87
+ json: PersistedOptions,
88
+ ): SerializedOptions {
89
+ /* eslint-disable unused-imports/no-unused-vars */
90
+ const { version, ...rest } = json
91
+ /* eslint-enable unused-imports/no-unused-vars */
92
+ return {
93
+ ...rest,
94
+ mode: json.mode as Mode,
95
+ projectName: json.projectName!,
96
+ typescript: json.typescript!,
97
+ tailwind: json.tailwind!,
98
+ git: json.git!,
99
+ packageManager: json.packageManager!,
100
+ targetDir: '',
101
+ framework: json.framework,
102
+ starter: json.starter,
103
+ chosenAddOns: json.existingAddOns,
104
+ }
105
+ }
106
+
107
+ export async function runCreateApp(options: Required<Options>) {
108
+ const { environment, output } = createMemoryEnvironment()
109
+
110
+ const targetDir = resolve(process.cwd())
111
+
112
+ await createApp(environment, {
113
+ ...options,
114
+ targetDir,
115
+ })
116
+
117
+ output.files = Object.fromEntries(
118
+ Object.entries(output.files).map(([key, value]) => {
119
+ return [key.replace(targetDir, '.'), value]
120
+ }),
121
+ )
122
+
123
+ return output
124
+ }
125
+
126
+ export async function compareFilesRecursively(
127
+ path: string,
128
+ ignore: (filePath: string) => boolean,
129
+ original: Record<string, string>,
130
+ changedFiles: Record<string, string>,
131
+ ) {
132
+ const files = await readdir(path, { withFileTypes: true })
133
+ for (const file of files) {
134
+ const filePath = `${path}/${file.name}`
135
+ if (!ignore(file.name)) {
136
+ if (file.isDirectory()) {
137
+ await compareFilesRecursively(filePath, ignore, original, changedFiles)
138
+ } else {
139
+ const contents = await readFileHelper(filePath)
140
+ if (!original[filePath] || original[filePath] !== contents) {
141
+ changedFiles[filePath] = contents
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+
148
+ export async function readCurrentProjectOptions(environment: Environment) {
149
+ const persistedOptions = await readConfigFileFromEnvironment(
150
+ environment,
151
+ process.cwd(),
152
+ )
153
+ if (!persistedOptions) {
154
+ environment.error(
155
+ 'There is no .cta.json file in your project.',
156
+ `This is probably because this was created with an older version of create-tsrouter-app.`,
157
+ )
158
+ process.exit(1)
159
+ }
160
+ return persistedOptions
161
+ }
@@ -0,0 +1,126 @@
1
+ import { readFile } from 'node:fs/promises'
2
+ import { existsSync, writeFileSync } from 'node:fs'
3
+ import { resolve } from 'node:path'
4
+
5
+ import { StarterCompiledSchema } from '../types.js'
6
+ import { createIgnore } from '../file-helpers.js'
7
+ import {
8
+ compareFilesRecursively,
9
+ createAppOptionsFromPersisted,
10
+ createPackageAdditions,
11
+ readCurrentProjectOptions,
12
+ runCreateApp,
13
+ } from './shared.js'
14
+
15
+ import type { PersistedOptions } from '../config-file'
16
+ import type {
17
+ Environment,
18
+ Options,
19
+ Starter,
20
+ StarterCompiled,
21
+ StarterInfo,
22
+ } from '../types'
23
+
24
+ const INFO_FILE = 'starter-info.json'
25
+ const COMPILED_FILE = 'starter.json'
26
+
27
+ export async function readOrGenerateStarterInfo(
28
+ options: PersistedOptions,
29
+ ): Promise<StarterInfo> {
30
+ return existsSync(INFO_FILE)
31
+ ? JSON.parse((await readFile(INFO_FILE)).toString())
32
+ : {
33
+ id: `${options.projectName}-starter`,
34
+ name: `${options.projectName}-starter`,
35
+ version: '0.0.1',
36
+ description: 'Project starter',
37
+ author: 'Jane Smith <jane.smith@example.com>',
38
+ license: 'MIT',
39
+ link: `https://github.com/jane-smith/${options.projectName}-starter`,
40
+ shadcnComponents: [],
41
+ framework: options.framework,
42
+ mode: options.mode!,
43
+ routes: [],
44
+ warning: '',
45
+ type: 'starter',
46
+ packageAdditions: {
47
+ scripts: {},
48
+ dependencies: {},
49
+ devDependencies: {},
50
+ },
51
+ dependsOn: options.existingAddOns,
52
+ typescript: options.typescript!,
53
+ tailwind: options.tailwind!,
54
+ }
55
+ }
56
+
57
+ async function loadCurrentStarterInfo(environment: Environment) {
58
+ const persistedOptions = await readCurrentProjectOptions(environment)
59
+ const info = await readOrGenerateStarterInfo(persistedOptions)
60
+
61
+ const output = await runCreateApp(
62
+ (await createAppOptionsFromPersisted(
63
+ persistedOptions,
64
+ )) as Required<Options>,
65
+ )
66
+
67
+ return { info, output }
68
+ }
69
+
70
+ export async function updateStarterInfo(environment: Environment) {
71
+ const { info, output } = await loadCurrentStarterInfo(environment)
72
+
73
+ info.packageAdditions = createPackageAdditions(
74
+ JSON.parse(output.files['./package.json']),
75
+ JSON.parse((await readFile('package.json')).toString()),
76
+ )
77
+
78
+ writeFileSync(INFO_FILE, JSON.stringify(info, null, 2))
79
+ }
80
+
81
+ export async function compileStarter(environment: Environment) {
82
+ const { info, output } = await loadCurrentStarterInfo(environment)
83
+
84
+ const ignore = createIgnore(process.cwd())
85
+ const changedFiles: Record<string, string> = {}
86
+ await compareFilesRecursively('.', ignore, output.files, changedFiles)
87
+
88
+ const deletedFiles: Array<string> = []
89
+ for (const file of Object.keys(output.files)) {
90
+ if (!existsSync(resolve(process.cwd(), file))) {
91
+ deletedFiles.push(file)
92
+ }
93
+ }
94
+
95
+ const compiledInfo: StarterCompiled = {
96
+ ...info,
97
+ files: changedFiles,
98
+ deletedFiles,
99
+ }
100
+
101
+ writeFileSync(COMPILED_FILE, JSON.stringify(compiledInfo, null, 2))
102
+ }
103
+
104
+ export async function initStarter(environment: Environment) {
105
+ await updateStarterInfo(environment)
106
+ await compileStarter(environment)
107
+ }
108
+
109
+ export async function loadStarter(url: string): Promise<Starter> {
110
+ const response = await fetch(url)
111
+ const jsonContent = await response.json()
112
+
113
+ const checked = StarterCompiledSchema.safeParse(jsonContent)
114
+ if (!checked.success) {
115
+ throw new Error(`Invalid starter: ${url}`)
116
+ }
117
+
118
+ const starter = checked.data
119
+ starter.id = url
120
+ return {
121
+ ...starter,
122
+ getFiles: () => Promise.resolve(Object.keys(starter.files)),
123
+ getFileContents: (path: string) => Promise.resolve(starter.files[path]),
124
+ getDeletedFiles: () => Promise.resolve(starter.deletedFiles),
125
+ }
126
+ }