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

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 +91 -5
  2. package/dist/add.js +125 -0
  3. package/dist/cli.js +132 -0
  4. package/dist/config-file.js +9 -14
  5. package/dist/constants.js +2 -0
  6. package/dist/create-app.js +451 -142
  7. package/dist/custom-add-on.js +254 -0
  8. package/dist/environment.js +32 -64
  9. package/dist/file-helper.js +18 -0
  10. package/dist/index.js +1 -17
  11. package/dist/mcp.js +229 -0
  12. package/dist/options.js +333 -9
  13. package/dist/package-manager.js +6 -51
  14. package/dist/templates.js +6 -0
  15. package/dist/toolchain.js +6 -0
  16. package/dist/types/add-ons.d.ts +8 -3
  17. package/dist/types/add.d.ts +3 -0
  18. package/dist/types/cli.d.ts +7 -0
  19. package/dist/types/config-file.d.ts +4 -6
  20. package/dist/types/constants.d.ts +3 -0
  21. package/dist/types/create-app.d.ts +7 -1
  22. package/dist/types/custom-add-on.d.ts +3 -0
  23. package/dist/types/environment.d.ts +1 -2
  24. package/dist/types/file-helper.d.ts +2 -0
  25. package/dist/types/index.d.ts +1 -20
  26. package/dist/types/mcp.d.ts +7 -0
  27. package/dist/types/options.d.ts +6 -2
  28. package/dist/types/package-manager.d.ts +1 -18
  29. package/dist/types/templates.d.ts +1 -0
  30. package/dist/types/toolchain.d.ts +3 -0
  31. package/dist/types/types.d.ts +85 -788
  32. package/dist/types/utils.d.ts +0 -5
  33. package/dist/types.js +1 -65
  34. package/dist/utils.js +0 -9
  35. package/package.json +12 -9
  36. package/src/add-ons.ts +123 -7
  37. package/src/add.ts +186 -0
  38. package/src/cli.ts +210 -0
  39. package/src/config-file.ts +17 -26
  40. package/src/constants.ts +5 -0
  41. package/src/create-app.ts +730 -180
  42. package/src/custom-add-on.ts +325 -0
  43. package/src/environment.ts +33 -77
  44. package/src/file-helper.ts +20 -0
  45. package/src/index.ts +1 -77
  46. package/src/mcp.ts +302 -0
  47. package/src/options.ts +409 -8
  48. package/src/package-manager.ts +9 -80
  49. package/src/templates.ts +7 -0
  50. package/src/toolchain.ts +7 -0
  51. package/src/types.ts +87 -175
  52. package/src/utils.ts +0 -17
  53. package/templates/react/add-on/clerk/README.md +3 -0
  54. package/templates/react/add-on/clerk/assets/_dot_env.local.append +2 -0
  55. package/templates/react/add-on/clerk/assets/src/integrations/clerk/header-user.tsx +19 -0
  56. package/templates/react/add-on/clerk/assets/src/integrations/clerk/provider.tsx +18 -0
  57. package/templates/react/add-on/clerk/assets/src/routes/demo.clerk.tsx +20 -0
  58. package/templates/react/add-on/clerk/info.json +13 -0
  59. package/templates/react/add-on/clerk/package.json +5 -0
  60. package/templates/react/add-on/convex/README.md +4 -0
  61. package/templates/react/add-on/convex/assets/_dot_cursorrules.append +93 -0
  62. package/templates/react/add-on/convex/assets/_dot_env.local.append +3 -0
  63. package/templates/react/add-on/convex/assets/convex/products.ts +8 -0
  64. package/templates/react/add-on/convex/assets/convex/schema.ts +10 -0
  65. package/templates/react/add-on/convex/assets/src/integrations/convex/provider.tsx +20 -0
  66. package/templates/react/add-on/convex/assets/src/routes/demo.convex.tsx +33 -0
  67. package/templates/react/add-on/convex/info.json +13 -0
  68. package/templates/react/add-on/convex/package.json +6 -0
  69. package/templates/react/add-on/form/assets/src/components/demo.FormComponents.tsx.ejs +300 -0
  70. package/templates/react/add-on/form/assets/src/hooks/demo.form-context.ts +4 -0
  71. package/templates/react/add-on/form/assets/src/hooks/demo.form.ts +22 -0
  72. package/templates/react/add-on/form/assets/src/routes/demo.form.address.tsx.ejs +213 -0
  73. package/templates/react/add-on/form/assets/src/routes/demo.form.simple.tsx.ejs +77 -0
  74. package/templates/react/add-on/form/info.json +26 -0
  75. package/templates/react/add-on/form/package.json +6 -0
  76. package/templates/react/add-on/module-federation/assets/module-federation.config.js.ejs +31 -0
  77. package/templates/react/add-on/module-federation/assets/src/demo-mf-component.tsx +3 -0
  78. package/templates/react/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +11 -0
  79. package/templates/react/add-on/module-federation/info.json +7 -0
  80. package/templates/react/add-on/module-federation/package.json +5 -0
  81. package/templates/react/add-on/netlify/README.md +11 -0
  82. package/templates/react/add-on/netlify/info.json +7 -0
  83. package/templates/react/add-on/sentry/assets/_dot_cursorrules.append +22 -0
  84. package/templates/react/add-on/sentry/assets/_dot_env.local.append +11 -0
  85. package/templates/react/add-on/sentry/assets/src/app/global-middleware.ts +11 -0
  86. package/templates/react/add-on/sentry/assets/src/routes/demo.sentry.testing.tsx +489 -0
  87. package/templates/react/add-on/sentry/info.json +14 -0
  88. package/templates/react/add-on/sentry/package.json +5 -0
  89. package/templates/react/add-on/shadcn/README.md +7 -0
  90. package/templates/react/add-on/shadcn/assets/_dot_cursorrules.append +7 -0
  91. package/templates/react/add-on/shadcn/assets/components.json +21 -0
  92. package/templates/react/add-on/shadcn/assets/src/lib/utils.ts +6 -0
  93. package/templates/react/add-on/shadcn/assets/src/styles.css +138 -0
  94. package/templates/react/add-on/shadcn/info.json +7 -0
  95. package/templates/react/add-on/shadcn/package.json +9 -0
  96. package/templates/react/add-on/start/assets/_dot_gitignore.append +2 -0
  97. package/templates/react/add-on/start/assets/app.config.ts.ejs +32 -0
  98. package/templates/react/add-on/start/assets/src/api.ts +6 -0
  99. package/templates/react/add-on/start/assets/src/client.tsx.ejs +33 -0
  100. package/templates/react/add-on/start/assets/src/router.tsx.ejs +48 -0
  101. package/templates/react/add-on/start/assets/src/routes/api.demo-names.ts +11 -0
  102. package/templates/react/add-on/start/assets/src/routes/demo.start.api-request.tsx.ejs +33 -0
  103. package/templates/react/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +50 -0
  104. package/templates/react/add-on/start/assets/src/ssr.tsx.ejs +30 -0
  105. package/templates/react/add-on/start/info.json +18 -0
  106. package/templates/react/add-on/start/package.json +13 -0
  107. package/templates/react/add-on/store/assets/src/lib/demo-store.ts +13 -0
  108. package/templates/react/add-on/store/assets/src/routes/demo.store.tsx.ejs +75 -0
  109. package/templates/react/add-on/store/info.json +13 -0
  110. package/templates/react/add-on/store/package.json +6 -0
  111. package/templates/react/add-on/t3env/README.md +16 -0
  112. package/templates/react/add-on/t3env/assets/src/env.ts +39 -0
  113. package/templates/react/add-on/t3env/info.json +10 -0
  114. package/templates/react/add-on/t3env/package.json +6 -0
  115. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/init.ts +9 -0
  116. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/react.ts +4 -0
  117. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/router.ts +18 -0
  118. package/templates/react/add-on/tRPC/assets/src/routes/api.trpc.$.tsx +16 -0
  119. package/templates/react/add-on/tRPC/info.json +9 -0
  120. package/templates/react/add-on/tRPC/package.json +9 -0
  121. package/templates/react/add-on/table/assets/src/data/demo-table-data.ts +50 -0
  122. package/templates/react/add-on/table/assets/src/routes/demo.table.tsx.ejs +373 -0
  123. package/templates/react/add-on/table/info.json +13 -0
  124. package/templates/react/add-on/table/package.json +7 -0
  125. package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/layout.tsx +5 -0
  126. package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/root-provider.tsx.ejs +70 -0
  127. package/templates/react/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx.ejs +53 -0
  128. package/templates/react/add-on/tanstack-query/info.json +13 -0
  129. package/templates/react/add-on/tanstack-query/package.json +6 -0
  130. package/templates/react/base/README.md.ejs +558 -0
  131. package/templates/react/base/_dot_gitignore +5 -0
  132. package/templates/react/base/_dot_vscode/settings.biome.json +35 -0
  133. package/templates/react/base/_dot_vscode/settings.json +11 -0
  134. package/templates/react/base/index.html.ejs +20 -0
  135. package/templates/react/base/package.biome.json +10 -0
  136. package/templates/react/base/package.eslintprettier.json +11 -0
  137. package/templates/react/base/package.json +30 -0
  138. package/templates/react/base/package.ts.json +7 -0
  139. package/templates/react/base/package.tw.json +6 -0
  140. package/templates/react/base/public/favicon.ico +0 -0
  141. package/templates/react/base/public/logo192.png +0 -0
  142. package/templates/react/base/public/logo512.png +0 -0
  143. package/templates/react/base/public/manifest.json +25 -0
  144. package/templates/react/base/public/robots.txt +3 -0
  145. package/templates/react/base/src/App.css +38 -0
  146. package/templates/react/base/src/App.test.tsx.ejs +10 -0
  147. package/templates/react/base/src/App.tsx.ejs +74 -0
  148. package/templates/react/base/src/components/Header.tsx.ejs +27 -0
  149. package/templates/react/base/src/logo.svg +44 -0
  150. package/templates/react/base/src/reportWebVitals.ts.ejs +28 -0
  151. package/templates/react/base/src/styles.css.ejs +15 -0
  152. package/templates/react/base/toolchain/.prettierignore +3 -0
  153. package/templates/react/base/toolchain/biome.json +31 -0
  154. package/templates/react/base/toolchain/eslint.config.js +5 -0
  155. package/templates/react/base/toolchain/prettier.config.js +10 -0
  156. package/templates/react/base/tsconfig.json.ejs +29 -0
  157. package/templates/react/base/vite.config.js.ejs +23 -0
  158. package/templates/react/code-router/src/main.tsx.ejs +92 -0
  159. package/templates/react/example/tanchat/README.md +37 -0
  160. package/templates/react/example/tanchat/assets/_dot_env.local.append +2 -0
  161. package/templates/react/example/tanchat/assets/public/example-guitar-flowers.jpg +0 -0
  162. package/templates/react/example/tanchat/assets/public/example-guitar-motherboard.jpg +0 -0
  163. package/templates/react/example/tanchat/assets/public/example-guitar-racing.jpg +0 -0
  164. package/templates/react/example/tanchat/assets/public/example-guitar-steamer-trunk.jpg +0 -0
  165. package/templates/react/example/tanchat/assets/public/example-guitar-superhero.jpg +0 -0
  166. package/templates/react/example/tanchat/assets/public/example-guitar-traveling.jpg +0 -0
  167. package/templates/react/example/tanchat/assets/public/example-guitar-video-games.jpg +0 -0
  168. package/templates/react/example/tanchat/assets/src/components/example-AIAssistant.tsx +173 -0
  169. package/templates/react/example/tanchat/assets/src/components/example-GuitarRecommendation.tsx +47 -0
  170. package/templates/react/example/tanchat/assets/src/data/example-guitars.ts +83 -0
  171. package/templates/react/example/tanchat/assets/src/demo.index.css +220 -0
  172. package/templates/react/example/tanchat/assets/src/integrations/tanchat/header-user.tsx +5 -0
  173. package/templates/react/example/tanchat/assets/src/routes/api.messages.ts +24 -0
  174. package/templates/react/example/tanchat/assets/src/routes/api.sse.ts +23 -0
  175. package/templates/react/example/tanchat/assets/src/routes/example.chat.tsx +159 -0
  176. package/templates/react/example/tanchat/assets/src/routes/example.guitars/$guitarId.tsx +50 -0
  177. package/templates/react/example/tanchat/assets/src/routes/example.guitars/index.tsx +54 -0
  178. package/templates/react/example/tanchat/assets/src/store/example-assistant.ts +3 -0
  179. package/templates/react/example/tanchat/assets/src/utils/demo.ai.ts +62 -0
  180. package/templates/react/example/tanchat/assets/src/utils/demo.sse.ts +31 -0
  181. package/templates/react/example/tanchat/assets/src/utils/demo.tools.ts +47 -0
  182. package/templates/react/example/tanchat/info.json +19 -0
  183. package/templates/react/example/tanchat/package.json +16 -0
  184. package/templates/react/file-router/package.fr.json +5 -0
  185. package/templates/react/file-router/src/main.tsx.ejs +55 -0
  186. package/templates/react/file-router/src/routes/__root.tsx.ejs +82 -0
  187. package/templates/solid/add-on/form/assets/src/routes/demo.form.tsx.ejs +352 -0
  188. package/templates/solid/add-on/form/info.json +13 -0
  189. package/templates/solid/add-on/form/package.json +5 -0
  190. package/templates/solid/add-on/module-federation/assets/module-federation.config.js.ejs +27 -0
  191. package/templates/solid/add-on/module-federation/assets/src/demo-mf-component.tsx +3 -0
  192. package/templates/solid/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +9 -0
  193. package/templates/solid/add-on/module-federation/info.json +7 -0
  194. package/templates/solid/add-on/module-federation/package.json +5 -0
  195. package/templates/solid/add-on/sentry/assets/_dot_cursorrules.append +22 -0
  196. package/templates/solid/add-on/sentry/assets/_dot_env.local.append +2 -0
  197. package/templates/solid/add-on/sentry/assets/src/routes/demo.sentry.bad-event-handler.tsx +20 -0
  198. package/templates/solid/add-on/sentry/info.json +13 -0
  199. package/templates/solid/add-on/sentry/package.json +5 -0
  200. package/templates/solid/add-on/solid-ui/README.md +9 -0
  201. package/templates/solid/add-on/solid-ui/assets/src/lib/utils.ts +6 -0
  202. package/templates/solid/add-on/solid-ui/assets/src/styles.css +138 -0
  203. package/templates/solid/add-on/solid-ui/assets/ui.config.json +13 -0
  204. package/templates/solid/add-on/solid-ui/info.json +11 -0
  205. package/templates/solid/add-on/solid-ui/package.json +9 -0
  206. package/templates/solid/add-on/start/assets/app.config.ts +16 -0
  207. package/templates/solid/add-on/start/assets/src/api.ts +6 -0
  208. package/templates/solid/add-on/start/assets/src/client.tsx +7 -0
  209. package/templates/solid/add-on/start/assets/src/router.tsx.ejs +24 -0
  210. package/templates/solid/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +49 -0
  211. package/templates/solid/add-on/start/assets/src/ssr.tsx +12 -0
  212. package/templates/solid/add-on/start/info.json +14 -0
  213. package/templates/solid/add-on/start/package.json +12 -0
  214. package/templates/solid/add-on/store/assets/src/lib/demo-store.ts +13 -0
  215. package/templates/solid/add-on/store/assets/src/routes/demo.store.tsx.ejs +77 -0
  216. package/templates/solid/add-on/store/info.json +13 -0
  217. package/templates/solid/add-on/store/package.json +6 -0
  218. package/templates/solid/add-on/t3env/README.md +16 -0
  219. package/templates/solid/add-on/t3env/assets/src/env.ts +39 -0
  220. package/templates/solid/add-on/t3env/info.json +10 -0
  221. package/templates/solid/add-on/t3env/package.json +6 -0
  222. package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/header-user.tsx +5 -0
  223. package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/provider.tsx +15 -0
  224. package/templates/solid/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx +30 -0
  225. package/templates/solid/add-on/tanstack-query/info.json +13 -0
  226. package/templates/solid/add-on/tanstack-query/package.json +6 -0
  227. package/templates/solid/base/README.md.ejs +215 -0
  228. package/templates/solid/base/_dot_cursorrules.append +35 -0
  229. package/templates/solid/base/_dot_gitignore +5 -0
  230. package/templates/solid/base/_dot_vscode/settings.biome.json +35 -0
  231. package/templates/solid/base/_dot_vscode/settings.json +11 -0
  232. package/templates/solid/base/index.html.ejs +20 -0
  233. package/templates/solid/base/package.biome.json +10 -0
  234. package/templates/solid/base/package.eslintprettier.json +11 -0
  235. package/templates/solid/base/package.json +23 -0
  236. package/templates/solid/base/package.ts.json +5 -0
  237. package/templates/solid/base/package.tw.json +6 -0
  238. package/templates/solid/base/public/favicon.ico +0 -0
  239. package/templates/solid/base/public/logo192.png +0 -0
  240. package/templates/solid/base/public/logo512.png +0 -0
  241. package/templates/solid/base/public/manifest.json +25 -0
  242. package/templates/solid/base/public/robots.txt +3 -0
  243. package/templates/solid/base/src/App.css +0 -0
  244. package/templates/solid/base/src/App.tsx.ejs +47 -0
  245. package/templates/solid/base/src/components/Header.tsx.ejs +26 -0
  246. package/templates/solid/base/src/logo.svg +120 -0
  247. package/templates/solid/base/src/styles.css.ejs +15 -0
  248. package/templates/solid/base/toolchain/.prettierignore +3 -0
  249. package/templates/solid/base/toolchain/biome.json +31 -0
  250. package/templates/solid/base/toolchain/eslint.config.js +5 -0
  251. package/templates/solid/base/toolchain/prettier.config.js +10 -0
  252. package/templates/solid/base/tsconfig.json.ejs +31 -0
  253. package/templates/solid/base/vite.config.js.ejs +22 -0
  254. package/templates/solid/code-router/src/main.tsx.ejs +71 -0
  255. package/templates/solid/example/tanchat/README.md +52 -0
  256. package/templates/solid/example/tanchat/assets/ai-streaming-server/README.md +110 -0
  257. package/templates/solid/example/tanchat/assets/ai-streaming-server/_dot_env.example +1 -0
  258. package/templates/solid/example/tanchat/assets/ai-streaming-server/package.json +26 -0
  259. package/templates/solid/example/tanchat/assets/ai-streaming-server/src/index.ts +102 -0
  260. package/templates/solid/example/tanchat/assets/ai-streaming-server/tsconfig.json +15 -0
  261. package/templates/solid/example/tanchat/assets/src/components/demo.SettingsDialog.tsx +149 -0
  262. package/templates/solid/example/tanchat/assets/src/demo.index.css +227 -0
  263. package/templates/solid/example/tanchat/assets/src/lib/demo-store.ts +13 -0
  264. package/templates/solid/example/tanchat/assets/src/routes/example.chat.tsx +435 -0
  265. package/templates/solid/example/tanchat/assets/src/store/demo.hooks.ts +17 -0
  266. package/templates/solid/example/tanchat/assets/src/store/demo.store.ts +133 -0
  267. package/templates/solid/example/tanchat/info.json +14 -0
  268. package/templates/solid/example/tanchat/package.json +7 -0
  269. package/templates/solid/file-router/package.fr.json +5 -0
  270. package/templates/solid/file-router/src/main.tsx.ejs +47 -0
  271. package/templates/solid/file-router/src/routes/__root.tsx.ejs +41 -0
  272. package/templates/solid/file-router/src/routes/index.tsx +43 -0
  273. package/tests/cra.test.ts +293 -0
  274. package/tests/snapshots/cra/cr-js-npm.json +33 -0
  275. package/tests/snapshots/cra/cr-ts-npm.json +34 -0
  276. package/tests/snapshots/cra/cr-ts-start-npm.json +38 -0
  277. package/tests/snapshots/cra/fr-ts-npm.json +34 -0
  278. package/tests/snapshots/cra/fr-ts-tw-npm.json +33 -0
  279. package/tests/snapshots/cra/solid-cr-js-npm.json +31 -0
  280. package/tests/snapshots/cra/solid-cr-ts-npm.json +32 -0
  281. package/tests/snapshots/cra/solid-cr-ts-start-npm.json +36 -0
  282. package/tests/snapshots/cra/solid-fr-ts-npm.json +33 -0
  283. package/tests/snapshots/cra/solid-fr-ts-tw-npm.json +32 -0
  284. package/tests/test-utilities.ts +87 -0
  285. package/dist/add-to-app.js +0 -169
  286. package/dist/custom-add-ons/add-on.js +0 -175
  287. package/dist/custom-add-ons/shared.js +0 -117
  288. package/dist/custom-add-ons/starter.js +0 -84
  289. package/dist/file-helpers.js +0 -165
  290. package/dist/frameworks.js +0 -92
  291. package/dist/integrations/git.js +0 -4
  292. package/dist/integrations/shadcn.js +0 -33
  293. package/dist/package-json.js +0 -48
  294. package/dist/special-steps/index.js +0 -24
  295. package/dist/special-steps/rimraf-node-modules.js +0 -16
  296. package/dist/template-file.js +0 -112
  297. package/dist/types/add-to-app.d.ts +0 -17
  298. package/dist/types/custom-add-ons/add-on.d.ts +0 -69
  299. package/dist/types/custom-add-ons/shared.d.ts +0 -15
  300. package/dist/types/custom-add-ons/starter.d.ts +0 -7
  301. package/dist/types/file-helpers.d.ts +0 -15
  302. package/dist/types/frameworks.d.ts +0 -7
  303. package/dist/types/integrations/git.d.ts +0 -2
  304. package/dist/types/integrations/shadcn.d.ts +0 -2
  305. package/dist/types/package-json.d.ts +0 -7
  306. package/dist/types/special-steps/index.d.ts +0 -2
  307. package/dist/types/special-steps/rimraf-node-modules.d.ts +0 -2
  308. package/dist/types/template-file.d.ts +0 -2
  309. package/src/add-to-app.ts +0 -274
  310. package/src/custom-add-ons/add-on.ts +0 -261
  311. package/src/custom-add-ons/shared.ts +0 -161
  312. package/src/custom-add-ons/starter.ts +0 -126
  313. package/src/file-helpers.ts +0 -235
  314. package/src/frameworks.ts +0 -134
  315. package/src/integrations/git.ts +0 -7
  316. package/src/integrations/shadcn.ts +0 -54
  317. package/src/package-json.ts +0 -69
  318. package/src/special-steps/index.ts +0 -36
  319. package/src/special-steps/rimraf-node-modules.ts +0 -25
  320. package/src/template-file.ts +0 -150
  321. package/tests/add-ons.test.ts +0 -67
  322. package/tests/add-to-app.test.ts +0 -358
  323. package/tests/config-file.test.ts +0 -68
  324. package/tests/create-app.test.ts +0 -120
  325. package/tests/custom-add-ons/add-on.test.ts +0 -12
  326. package/tests/custom-add-ons/shared.test.ts +0 -257
  327. package/tests/custom-add-ons/starter.test.ts +0 -58
  328. package/tests/environment.test.ts +0 -115
  329. package/tests/file-helper.test.ts +0 -90
  330. package/tests/frameworks.test.ts +0 -95
  331. package/tests/index.test.ts +0 -9
  332. package/tests/integrations/git.test.ts +0 -20
  333. package/tests/integrations/shadcn.test.ts +0 -91
  334. package/tests/options.test.ts +0 -42
  335. package/tests/package-json.test.ts +0 -63
  336. package/tests/package-manager.test.ts +0 -154
  337. package/tests/setupVitest.ts +0 -6
  338. package/tests/template-file.test.ts +0 -178
  339. package/tests/utils.test.ts +0 -23
  340. package/vitest.config.ts +0 -21
@@ -0,0 +1,325 @@
1
+ import { readFile, readdir } from 'node:fs/promises'
2
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
3
+ import { basename, dirname, resolve } from 'node:path'
4
+ import chalk from 'chalk'
5
+
6
+ import { createMemoryEnvironment } from './environment.js'
7
+ import { createApp } from './create-app.js'
8
+ import { readConfigFile } from './config-file.js'
9
+ import { finalizeAddOns } from './add-ons.js'
10
+ import { readFileHelper } from './file-helper.js'
11
+
12
+ import type { Framework, Options } from './types.js'
13
+ import type { PersistedOptions } from './config-file.js'
14
+
15
+ type AddOnMode = 'add-on' | 'overlay'
16
+
17
+ const INFO_FILE: Record<AddOnMode, string> = {
18
+ 'add-on': '.add-on/info.json',
19
+ overlay: 'overlay-info.json',
20
+ }
21
+ const COMPILED_FILE: Record<AddOnMode, string> = {
22
+ 'add-on': 'add-on.json',
23
+ overlay: 'overlay.json',
24
+ }
25
+
26
+ const ADD_ON_DIR = '.add-on'
27
+ const ASSETS_DIR = 'assets'
28
+
29
+ const IGNORE_FILES = [
30
+ ADD_ON_DIR,
31
+ 'node_modules',
32
+ 'dist',
33
+ 'build',
34
+ '.git',
35
+ 'pnpm-lock.yaml',
36
+ 'package-lock.json',
37
+ 'yarn.lock',
38
+ 'bun.lockb',
39
+ 'bun.lock',
40
+ 'deno.lock',
41
+ 'add-on.json',
42
+ 'add-on-info.json',
43
+ 'package.json',
44
+ ]
45
+
46
+ const ADD_ON_IGNORE_FILES: Array<string> = [
47
+ 'main.jsx',
48
+ 'App.jsx',
49
+ 'main.tsx',
50
+ 'App.tsx',
51
+ 'routeTree.gen.ts',
52
+ ]
53
+
54
+ function templatize(routeCode: string, routeFile: string) {
55
+ let code = routeCode
56
+
57
+ // Replace the import
58
+ code = code.replace(
59
+ /import { createFileRoute } from '@tanstack\/react-router'/g,
60
+ `import { <% if (fileRouter) { %>createFileRoute<% } else { %>createRoute<% } %> } from '@tanstack/react-router'`,
61
+ )
62
+
63
+ // Extract route path and definition, then transform the route declaration
64
+ const routeMatch = code.match(
65
+ /export\s+const\s+Route\s*=\s*createFileRoute\(['"]([^'"]+)['"]\)\s*\(\{([^}]+)\}\)/,
66
+ )
67
+
68
+ let path = ''
69
+
70
+ if (routeMatch) {
71
+ const fullMatch = routeMatch[0]
72
+ path = routeMatch[1]
73
+ const routeDefinition = routeMatch[2]
74
+ code = code.replace(
75
+ fullMatch,
76
+ `<% if (codeRouter) { %>
77
+ import type { RootRoute } from '@tanstack/react-router'
78
+ <% } else { %>
79
+ export const Route = createFileRoute('${path}')({${routeDefinition}})
80
+ <% } %>`,
81
+ )
82
+
83
+ code += `
84
+ <% if (codeRouter) { %>
85
+ export default (parentRoute: RootRoute) => createRoute({
86
+ path: '${path}',
87
+ ${routeDefinition}
88
+ getParentRoute: () => parentRoute,
89
+ })
90
+ <% } %>
91
+ `
92
+ } else {
93
+ console.error(`No route found in the file: ${routeFile}`)
94
+ }
95
+
96
+ const name = basename(path)
97
+ .replace('.tsx', '')
98
+ .replace(/^demo/, '')
99
+ .replace('.', ' ')
100
+ .trim()
101
+
102
+ return { url: path, code, name }
103
+ }
104
+
105
+ async function createOptions(
106
+ json: PersistedOptions,
107
+ ): Promise<Required<Options>> {
108
+ return {
109
+ ...json,
110
+ chosenAddOns: await finalizeAddOns(
111
+ json.framework as Framework,
112
+ json.mode as string,
113
+ [...json.existingAddOns],
114
+ ),
115
+ } as Required<Options>
116
+ }
117
+
118
+ async function runCreateApp(options: Required<Options>) {
119
+ const { environment, output } = createMemoryEnvironment()
120
+ await createApp(options, {
121
+ silent: true,
122
+ environment,
123
+ cwd: process.cwd(),
124
+ name: 'create-tsrouter-app',
125
+ })
126
+ return output
127
+ }
128
+
129
+ async function recursivelyGatherFiles(
130
+ path: string,
131
+ files: Record<string, string>,
132
+ ) {
133
+ const dirFiles = await readdir(path, { withFileTypes: true })
134
+ for (const file of dirFiles) {
135
+ if (file.isDirectory()) {
136
+ await recursivelyGatherFiles(resolve(path, file.name), files)
137
+ } else {
138
+ files[resolve(path, file.name)] = readFileHelper(resolve(path, file.name))
139
+ }
140
+ }
141
+ }
142
+
143
+ async function compareFiles(
144
+ path: string,
145
+ ignore: Array<string>,
146
+ original: Record<string, string>,
147
+ changedFiles: Record<string, string>,
148
+ ) {
149
+ const files = await readdir(path, { withFileTypes: true })
150
+ for (const file of files) {
151
+ const filePath = `${path}/${file.name}`
152
+ if (!ignore.includes(file.name)) {
153
+ if (file.isDirectory()) {
154
+ await compareFiles(filePath, ignore, original, changedFiles)
155
+ } else {
156
+ const contents = (await readFile(filePath)).toString()
157
+ const absolutePath = resolve(process.cwd(), filePath)
158
+ if (!original[absolutePath] || original[absolutePath] !== contents) {
159
+ changedFiles[filePath] = contents
160
+ }
161
+ }
162
+ }
163
+ }
164
+ }
165
+
166
+ export async function initAddOn(mode: AddOnMode) {
167
+ const persistedOptions = await readConfigFile(process.cwd())
168
+ if (!persistedOptions) {
169
+ console.error(`${chalk.red('There is no .cta.json file in your project.')}
170
+
171
+ This is probably because this was created with an older version of create-tsrouter-app.`)
172
+ return
173
+ }
174
+
175
+ if (mode === 'add-on') {
176
+ if (persistedOptions.mode !== 'file-router') {
177
+ console.error(`${chalk.red('This project is not using file-router mode.')}
178
+
179
+ To create an add-on, the project must be created with the file-router mode.`)
180
+ return
181
+ }
182
+ if (!persistedOptions.tailwind) {
183
+ console.error(`${chalk.red('This project is not using Tailwind CSS.')}
184
+
185
+ To create an add-on, the project must be created with Tailwind CSS.`)
186
+ return
187
+ }
188
+ if (!persistedOptions.typescript) {
189
+ console.error(`${chalk.red('This project is not using TypeScript.')}
190
+
191
+ To create an add-on, the project must be created with TypeScript.`)
192
+ return
193
+ }
194
+ }
195
+
196
+ const info = existsSync(INFO_FILE[mode])
197
+ ? JSON.parse((await readFile(INFO_FILE[mode])).toString())
198
+ : {
199
+ name: `${persistedOptions.projectName}-${mode}`,
200
+ version: '0.0.1',
201
+ description: mode === 'add-on' ? 'Add-on' : 'Project overlay',
202
+ author: 'Jane Smith <jane.smith@example.com>',
203
+ license: 'MIT',
204
+ link: `https://github.com/jane-smith/${persistedOptions.projectName}-${mode}`,
205
+ command: {},
206
+ shadcnComponents: [],
207
+ templates: [persistedOptions.mode],
208
+ routes: [],
209
+ warning: '',
210
+ variables: {},
211
+ phase: 'add-on',
212
+ type: mode,
213
+ packageAdditions: {
214
+ scripts: {},
215
+ dependencies: {},
216
+ devDependencies: {},
217
+ },
218
+ }
219
+
220
+ const compiledInfo = JSON.parse(JSON.stringify(info))
221
+
222
+ const originalOutput = await runCreateApp(
223
+ await createOptions(persistedOptions),
224
+ )
225
+
226
+ const originalPackageJson = JSON.parse(
227
+ originalOutput.files[resolve(process.cwd(), 'package.json')],
228
+ )
229
+ const currentPackageJson = JSON.parse(
230
+ (await readFile('package.json')).toString(),
231
+ )
232
+
233
+ for (const script of Object.keys(currentPackageJson.scripts)) {
234
+ if (
235
+ originalPackageJson.scripts[script] !== currentPackageJson.scripts[script]
236
+ ) {
237
+ info.packageAdditions.scripts[script] = currentPackageJson.scripts[script]
238
+ }
239
+ }
240
+
241
+ const dependencies: Record<string, string> = {}
242
+ for (const dependency of Object.keys(currentPackageJson.dependencies)) {
243
+ if (
244
+ originalPackageJson.dependencies[dependency] !==
245
+ currentPackageJson.dependencies[dependency]
246
+ ) {
247
+ dependencies[dependency] = currentPackageJson.dependencies[dependency]
248
+ }
249
+ }
250
+ info.packageAdditions.dependencies = dependencies
251
+
252
+ const devDependencies: Record<string, string> = {}
253
+ for (const dependency of Object.keys(currentPackageJson.devDependencies)) {
254
+ if (
255
+ originalPackageJson.devDependencies[dependency] !==
256
+ currentPackageJson.devDependencies[dependency]
257
+ ) {
258
+ devDependencies[dependency] =
259
+ currentPackageJson.devDependencies[dependency]
260
+ }
261
+ }
262
+ info.packageAdditions.devDependencies = devDependencies
263
+
264
+ // Find altered files
265
+ const changedFiles: Record<string, string> = {}
266
+ await compareFiles('.', IGNORE_FILES, originalOutput.files, changedFiles)
267
+ if (mode === 'overlay') {
268
+ compiledInfo.files = changedFiles
269
+ } else {
270
+ const assetsDir = resolve(ADD_ON_DIR, ASSETS_DIR)
271
+ if (!existsSync(assetsDir)) {
272
+ await compareFiles('.', IGNORE_FILES, originalOutput.files, changedFiles)
273
+ for (const file of Object.keys(changedFiles).filter(
274
+ (file) => !ADD_ON_IGNORE_FILES.includes(basename(file)),
275
+ )) {
276
+ mkdirSync(dirname(resolve(assetsDir, file)), {
277
+ recursive: true,
278
+ })
279
+ if (file.includes('/routes/')) {
280
+ const { url, code, name } = templatize(changedFiles[file], file)
281
+ info.routes.push({
282
+ url,
283
+ name,
284
+ })
285
+ writeFileSync(resolve(assetsDir, `${file}.ejs`), code)
286
+ } else {
287
+ writeFileSync(resolve(assetsDir, file), changedFiles[file])
288
+ }
289
+ }
290
+ }
291
+ const addOnFiles: Record<string, string> = {}
292
+ await recursivelyGatherFiles(assetsDir, addOnFiles)
293
+ compiledInfo.files = Object.keys(addOnFiles).reduce(
294
+ (acc, file) => {
295
+ acc[file.replace(assetsDir, '.')] = addOnFiles[file]
296
+ return acc
297
+ },
298
+ {} as Record<string, string>,
299
+ )
300
+ }
301
+
302
+ compiledInfo.routes = info.routes
303
+ compiledInfo.framework = persistedOptions.framework
304
+ compiledInfo.addDependencies = persistedOptions.existingAddOns
305
+
306
+ if (mode === 'overlay') {
307
+ compiledInfo.mode = persistedOptions.mode
308
+ compiledInfo.typescript = persistedOptions.typescript
309
+ compiledInfo.tailwind = persistedOptions.tailwind
310
+
311
+ compiledInfo.deletedFiles = []
312
+ for (const file of Object.keys(originalOutput.files)) {
313
+ if (!existsSync(file)) {
314
+ compiledInfo.deletedFiles.push(file.replace(process.cwd(), '.'))
315
+ }
316
+ }
317
+ }
318
+
319
+ if (!existsSync(resolve(INFO_FILE[mode]))) {
320
+ mkdirSync(resolve(dirname(INFO_FILE[mode])), { recursive: true })
321
+ writeFileSync(INFO_FILE[mode], JSON.stringify(info, null, 2))
322
+ }
323
+
324
+ writeFileSync(COMPILED_FILE[mode], JSON.stringify(compiledInfo, null, 2))
325
+ }
@@ -3,21 +3,13 @@ import {
3
3
  copyFile,
4
4
  mkdir,
5
5
  readFile,
6
- readdir,
7
6
  unlink,
8
7
  writeFile,
9
8
  } from 'node:fs/promises'
10
- import { existsSync, statSync } from 'node:fs'
9
+ import { existsSync, readdirSync, statSync } from 'node:fs'
11
10
  import { dirname } from 'node:path'
12
11
  import { execa } from 'execa'
13
12
  import { memfs } from 'memfs'
14
- import { rimraf } from 'rimraf'
15
-
16
- import {
17
- cleanUpFileArray,
18
- cleanUpFiles,
19
- getBinaryFile,
20
- } from './file-helpers.js'
21
13
 
22
14
  import type { Environment } from './types.js'
23
15
 
@@ -42,63 +34,37 @@ export function createDefaultEnvironment(): Environment {
42
34
  await mkdir(dirname(path), { recursive: true })
43
35
  return writeFile(path, contents)
44
36
  },
45
- writeFileBase64: async (path: string, base64Contents: string) => {
46
- await mkdir(dirname(path), { recursive: true })
47
- return writeFile(path, getBinaryFile(base64Contents) as string)
48
- },
49
37
  execute: async (command: string, args: Array<string>, cwd: string) => {
50
38
  try {
51
- const result = await execa(command, args, {
39
+ await execa(command, args, {
52
40
  cwd,
53
41
  })
54
- return { stdout: result.stdout }
55
42
  } catch {
56
43
  errors.push(
57
44
  `Command "${command} ${args.join(' ')}" did not run successfully. Please run this manually in your project.`,
58
45
  )
59
- return { stdout: '' }
60
46
  }
61
47
  },
62
48
  deleteFile: async (path: string) => {
63
- if (existsSync(path)) {
64
- await unlink(path)
65
- }
49
+ await unlink(path)
66
50
  },
67
51
 
68
- readFile: async (path: string) => {
69
- return (await readFile(path)).toString()
70
- },
52
+ readFile: (path: string, encoding?: BufferEncoding) =>
53
+ readFile(path, { encoding: encoding || 'utf8' }),
71
54
  exists: (path: string) => existsSync(path),
72
- isDirectory: (path: string) => statSync(path).isDirectory(),
73
- readdir: async (path: string) => readdir(path),
74
- rimraf: async (path: string) => {
75
- await rimraf(path)
55
+ readdir: (path) => readdirSync(path),
56
+ isDirectory: (path) => {
57
+ const stat = statSync(path)
58
+ return stat.isDirectory()
76
59
  },
77
-
78
- appName: 'TanStack',
79
-
80
- startStep: () => {},
81
- finishStep: () => {},
82
-
83
- intro: () => {},
84
- outro: () => {},
85
- info: () => {},
86
- error: () => {},
87
- warn: () => {},
88
- confirm: () => Promise.resolve(true),
89
- spinner: () => ({
90
- start: () => {},
91
- stop: () => {},
92
- }),
93
60
  }
94
61
  }
95
62
 
96
- export function createMemoryEnvironment(returnPathsRelativeTo: string = '') {
63
+ export function createMemoryEnvironment() {
97
64
  const environment = createDefaultEnvironment()
98
65
 
99
66
  const output: {
100
67
  files: Record<string, string>
101
- deletedFiles: Array<string>
102
68
  commands: Array<{
103
69
  command: string
104
70
  args: Array<string>
@@ -106,7 +72,6 @@ export function createMemoryEnvironment(returnPathsRelativeTo: string = '') {
106
72
  } = {
107
73
  files: {},
108
74
  commands: [],
109
- deletedFiles: [],
110
75
  }
111
76
 
112
77
  const { fs, vol } = memfs({})
@@ -134,52 +99,43 @@ export function createMemoryEnvironment(returnPathsRelativeTo: string = '') {
134
99
  command,
135
100
  args,
136
101
  })
137
- return Promise.resolve({ stdout: '' })
102
+ return Promise.resolve()
138
103
  }
139
- environment.readFile = async (path: string) => {
140
- return Promise.resolve(fs.readFileSync(path, 'utf-8').toString())
104
+ environment.readFile = async (path: string, encoding?: BufferEncoding) => {
105
+ if (isTemplatePath(path)) {
106
+ return (await readFile(path, encoding)).toString()
107
+ }
108
+ return fs.readFileSync(path, 'utf8').toString()
141
109
  }
142
110
  environment.writeFile = async (path: string, contents: string) => {
143
111
  fs.mkdirSync(dirname(path), { recursive: true })
144
112
  await fs.writeFileSync(path, contents)
145
113
  }
146
- environment.writeFileBase64 = async (path: string, contents: string) => {
147
- // For the in-memory file system, we are not converting the base64 to binary
148
- // because it's not needed.
149
- fs.mkdirSync(dirname(path), { recursive: true })
150
- await fs.writeFileSync(path, contents)
151
- }
152
114
  environment.deleteFile = async (path: string) => {
153
- output.deletedFiles.push(path)
154
- if (fs.existsSync(path)) {
155
- await fs.unlinkSync(path)
156
- }
157
- }
158
- environment.finishRun = () => {
159
- output.files = vol.toJSON() as Record<string, string>
160
- for (const file of Object.keys(output.files)) {
161
- if (fs.statSync(file).isDirectory()) {
162
- delete output.files[file]
163
- }
164
- }
165
- if (returnPathsRelativeTo.length) {
166
- output.files = cleanUpFiles(output.files, returnPathsRelativeTo)
167
- output.deletedFiles = cleanUpFileArray(
168
- output.deletedFiles,
169
- returnPathsRelativeTo,
170
- )
171
- }
115
+ await fs.unlinkSync(path)
172
116
  }
173
117
  environment.exists = (path: string) => {
118
+ if (isTemplatePath(path)) {
119
+ return existsSync(path)
120
+ }
174
121
  return fs.existsSync(path)
175
122
  }
176
- environment.isDirectory = (path: string) => {
123
+ environment.readdir = (path: string) => {
124
+ if (isTemplatePath(path)) {
125
+ return readdirSync(path)
126
+ }
127
+ return fs.readdirSync(path).map((file) => file.toString())
128
+ }
129
+ environment.isDirectory = (path) => {
130
+ if (isTemplatePath(path)) {
131
+ const stat = statSync(path)
132
+ return stat.isDirectory()
133
+ }
177
134
  return fs.statSync(path).isDirectory()
178
135
  }
179
- environment.readdir = async (path: string) => {
180
- return Promise.resolve(fs.readdirSync(path).map((d) => d.toString()))
136
+ environment.finishRun = () => {
137
+ output.files = vol.toJSON() as Record<string, string>
181
138
  }
182
- environment.rimraf = async () => {}
183
139
 
184
140
  return {
185
141
  environment,
@@ -0,0 +1,20 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import { extname } from 'node:path'
3
+
4
+ const BINARY_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico']
5
+
6
+ export function readFileHelper(path: string): string {
7
+ if (BINARY_EXTENSIONS.includes(extname(path))) {
8
+ return `base64::${readFileSync(path).toString('base64')}`
9
+ } else {
10
+ return readFileSync(path, 'utf-8').toString()
11
+ }
12
+ }
13
+
14
+ export function getBinaryFile(content: string): string | null {
15
+ if (content.startsWith('base64::')) {
16
+ const binaryContent = Buffer.from(content.replace('base64::', ''), 'base64')
17
+ return binaryContent as unknown as string
18
+ }
19
+ return null
20
+ }
package/src/index.ts CHANGED
@@ -1,77 +1 @@
1
- export { createApp } from './create-app.js'
2
- export { addToApp } from './add-to-app.js'
3
-
4
- export { finalizeAddOns, getAllAddOns } from './add-ons.js'
5
-
6
- export { loadRemoteAddOn } from './custom-add-ons/add-on.js'
7
- export { loadStarter } from './custom-add-ons/starter.js'
8
-
9
- export {
10
- createMemoryEnvironment,
11
- createDefaultEnvironment,
12
- } from './environment.js'
13
-
14
- export { CODE_ROUTER, CONFIG_FILE, FILE_ROUTER } from './constants.js'
15
-
16
- export {
17
- DEFAULT_PACKAGE_MANAGER,
18
- SUPPORTED_PACKAGE_MANAGERS,
19
- getPackageManager,
20
- } from './package-manager.js'
21
-
22
- export {
23
- registerFramework,
24
- getFrameworkById,
25
- getFrameworkByName,
26
- getFrameworks,
27
- } from './frameworks.js'
28
-
29
- export {
30
- writeConfigFileToEnvironment,
31
- readConfigFileFromEnvironment,
32
- } from './config-file.js'
33
-
34
- export {
35
- cleanUpFiles,
36
- cleanUpFileArray,
37
- readFileHelper,
38
- getBinaryFile,
39
- recursivelyGatherFiles,
40
- relativePath,
41
- } from './file-helpers.js'
42
-
43
- export { formatCommand } from './utils.js'
44
-
45
- export { initStarter, compileStarter } from './custom-add-ons/starter.js'
46
- export { initAddOn, compileAddOn } from './custom-add-ons/add-on.js'
47
- export {
48
- createAppOptionsFromPersisted,
49
- createSerializedOptionsFromPersisted,
50
- } from './custom-add-ons/shared.js'
51
-
52
- export { createSerializedOptions } from './options.js'
53
-
54
- export {
55
- StarterCompiledSchema,
56
- StatusEvent,
57
- StatusStepType,
58
- StopEvent,
59
- AddOnCompiledSchema,
60
- AddOnInfoSchema,
61
- IntegrationSchema,
62
- } from './types.js'
63
-
64
- export type {
65
- AddOn,
66
- Environment,
67
- FileBundleHandler,
68
- Framework,
69
- FrameworkDefinition,
70
- Mode,
71
- Options,
72
- SerializedOptions,
73
- Starter,
74
- StarterCompiled,
75
- } from './types.js'
76
- export type { PersistedOptions } from './config-file.js'
77
- export type { PackageManager } from './package-manager.js'
1
+ export { cli } from './cli.js'