@tanstack/cta-engine 0.10.0-alpha.15 → 0.10.0-alpha.16

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 (294) hide show
  1. package/dist/add-ons.js +8 -73
  2. package/dist/{add.js → add-to-app.js} +19 -19
  3. package/dist/config-file.js +6 -3
  4. package/dist/constants.js +0 -2
  5. package/dist/create-app.js +76 -460
  6. package/dist/environment.js +11 -26
  7. package/dist/file-helpers.js +59 -0
  8. package/dist/frameworks.js +78 -0
  9. package/dist/index.js +8 -3
  10. package/dist/integrations/git.js +4 -0
  11. package/dist/integrations/shadcn.js +27 -0
  12. package/dist/package-json.js +46 -0
  13. package/dist/package-manager.js +51 -6
  14. package/dist/template-file.js +108 -0
  15. package/dist/types/add-ons.d.ts +2 -6
  16. package/dist/types/add-to-app.d.ts +4 -0
  17. package/dist/types/config-file.d.ts +3 -2
  18. package/dist/types/constants.d.ts +0 -3
  19. package/dist/types/file-helpers.d.ts +5 -0
  20. package/dist/types/frameworks.d.ts +5 -0
  21. package/dist/types/index.d.ts +10 -4
  22. package/dist/types/integrations/git.d.ts +2 -0
  23. package/dist/types/integrations/shadcn.d.ts +2 -0
  24. package/dist/types/package-json.d.ts +2 -0
  25. package/dist/types/package-manager.d.ts +14 -1
  26. package/dist/types/template-file.d.ts +2 -0
  27. package/dist/types/types.d.ts +83 -62
  28. package/dist/types/utils.d.ts +5 -0
  29. package/dist/utils.js +9 -0
  30. package/package.json +3 -13
  31. package/src/add-ons.ts +11 -104
  32. package/src/{add.ts → add-to-app.ts} +29 -35
  33. package/src/config-file.ts +12 -6
  34. package/src/constants.ts +0 -5
  35. package/src/create-app.ts +126 -727
  36. package/src/environment.ts +12 -27
  37. package/src/file-helpers.ts +73 -0
  38. package/src/frameworks.ts +114 -0
  39. package/src/index.ts +35 -4
  40. package/src/integrations/git.ts +7 -0
  41. package/src/integrations/shadcn.ts +44 -0
  42. package/src/package-json.ts +62 -0
  43. package/src/package-manager.ts +80 -9
  44. package/src/template-file.ts +146 -0
  45. package/src/types.ts +97 -68
  46. package/src/utils.ts +17 -0
  47. package/tests/file-helper.test.ts +37 -0
  48. package/tests/package-manager.test.ts +154 -0
  49. package/dist/cli.js +0 -126
  50. package/dist/custom-add-on.js +0 -256
  51. package/dist/file-helper.js +0 -18
  52. package/dist/mcp.js +0 -229
  53. package/dist/options.js +0 -328
  54. package/dist/templates.js +0 -6
  55. package/dist/toolchain.js +0 -6
  56. package/dist/types/add.d.ts +0 -3
  57. package/dist/types/cli.d.ts +0 -6
  58. package/dist/types/custom-add-on.d.ts +0 -6
  59. package/dist/types/file-helper.d.ts +0 -2
  60. package/dist/types/mcp.d.ts +0 -7
  61. package/dist/types/options.d.ts +0 -6
  62. package/dist/types/templates.d.ts +0 -1
  63. package/dist/types/toolchain.d.ts +0 -3
  64. package/src/cli.ts +0 -196
  65. package/src/custom-add-on.ts +0 -327
  66. package/src/file-helper.ts +0 -20
  67. package/src/mcp.ts +0 -302
  68. package/src/options.ts +0 -399
  69. package/src/templates.ts +0 -7
  70. package/src/toolchain.ts +0 -7
  71. package/templates/react/add-on/clerk/README.md +0 -3
  72. package/templates/react/add-on/clerk/assets/_dot_env.local.append +0 -2
  73. package/templates/react/add-on/clerk/assets/src/integrations/clerk/header-user.tsx +0 -19
  74. package/templates/react/add-on/clerk/assets/src/integrations/clerk/provider.tsx +0 -18
  75. package/templates/react/add-on/clerk/assets/src/routes/demo.clerk.tsx +0 -20
  76. package/templates/react/add-on/clerk/info.json +0 -13
  77. package/templates/react/add-on/clerk/package.json +0 -5
  78. package/templates/react/add-on/convex/README.md +0 -4
  79. package/templates/react/add-on/convex/assets/_dot_cursorrules.append +0 -93
  80. package/templates/react/add-on/convex/assets/_dot_env.local.append +0 -3
  81. package/templates/react/add-on/convex/assets/convex/products.ts +0 -8
  82. package/templates/react/add-on/convex/assets/convex/schema.ts +0 -10
  83. package/templates/react/add-on/convex/assets/src/integrations/convex/provider.tsx +0 -20
  84. package/templates/react/add-on/convex/assets/src/routes/demo.convex.tsx +0 -33
  85. package/templates/react/add-on/convex/info.json +0 -13
  86. package/templates/react/add-on/convex/package.json +0 -6
  87. package/templates/react/add-on/form/assets/src/components/demo.FormComponents.tsx.ejs +0 -300
  88. package/templates/react/add-on/form/assets/src/hooks/demo.form-context.ts +0 -4
  89. package/templates/react/add-on/form/assets/src/hooks/demo.form.ts +0 -22
  90. package/templates/react/add-on/form/assets/src/routes/demo.form.address.tsx.ejs +0 -213
  91. package/templates/react/add-on/form/assets/src/routes/demo.form.simple.tsx.ejs +0 -77
  92. package/templates/react/add-on/form/info.json +0 -26
  93. package/templates/react/add-on/form/package.json +0 -6
  94. package/templates/react/add-on/module-federation/assets/module-federation.config.js.ejs +0 -31
  95. package/templates/react/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
  96. package/templates/react/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -11
  97. package/templates/react/add-on/module-federation/info.json +0 -7
  98. package/templates/react/add-on/module-federation/package.json +0 -5
  99. package/templates/react/add-on/netlify/README.md +0 -11
  100. package/templates/react/add-on/netlify/info.json +0 -7
  101. package/templates/react/add-on/sentry/assets/_dot_cursorrules.append +0 -22
  102. package/templates/react/add-on/sentry/assets/_dot_env.local.append +0 -2
  103. package/templates/react/add-on/sentry/assets/src/app/global-middleware.ts +0 -25
  104. package/templates/react/add-on/sentry/assets/src/routes/demo.sentry.testing.tsx +0 -480
  105. package/templates/react/add-on/sentry/info.json +0 -14
  106. package/templates/react/add-on/sentry/package.json +0 -7
  107. package/templates/react/add-on/shadcn/README.md +0 -7
  108. package/templates/react/add-on/shadcn/assets/_dot_cursorrules.append +0 -7
  109. package/templates/react/add-on/shadcn/assets/components.json +0 -21
  110. package/templates/react/add-on/shadcn/assets/src/lib/utils.ts +0 -6
  111. package/templates/react/add-on/shadcn/assets/src/styles.css +0 -138
  112. package/templates/react/add-on/shadcn/info.json +0 -7
  113. package/templates/react/add-on/shadcn/package.json +0 -9
  114. package/templates/react/add-on/start/assets/_dot_gitignore.append +0 -2
  115. package/templates/react/add-on/start/assets/app.config.ts.ejs +0 -19
  116. package/templates/react/add-on/start/assets/src/api.ts +0 -6
  117. package/templates/react/add-on/start/assets/src/client.tsx +0 -8
  118. package/templates/react/add-on/start/assets/src/router.tsx.ejs +0 -77
  119. package/templates/react/add-on/start/assets/src/routes/api.demo-names.ts +0 -11
  120. package/templates/react/add-on/start/assets/src/routes/demo.start.api-request.tsx.ejs +0 -33
  121. package/templates/react/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +0 -50
  122. package/templates/react/add-on/start/assets/src/ssr.tsx +0 -12
  123. package/templates/react/add-on/start/info.json +0 -18
  124. package/templates/react/add-on/start/package.json +0 -13
  125. package/templates/react/add-on/store/assets/src/lib/demo-store.ts +0 -13
  126. package/templates/react/add-on/store/assets/src/routes/demo.store.tsx.ejs +0 -75
  127. package/templates/react/add-on/store/info.json +0 -13
  128. package/templates/react/add-on/store/package.json +0 -6
  129. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/init.ts +0 -9
  130. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/react.ts +0 -4
  131. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/router.ts +0 -18
  132. package/templates/react/add-on/tRPC/assets/src/routes/api.trpc.$.tsx +0 -16
  133. package/templates/react/add-on/tRPC/info.json +0 -9
  134. package/templates/react/add-on/tRPC/package.json +0 -9
  135. package/templates/react/add-on/table/assets/src/data/demo-table-data.ts +0 -50
  136. package/templates/react/add-on/table/assets/src/routes/demo.table.tsx.ejs +0 -373
  137. package/templates/react/add-on/table/info.json +0 -13
  138. package/templates/react/add-on/table/package.json +0 -7
  139. package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/layout.tsx +0 -5
  140. package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/root-provider.tsx.ejs +0 -70
  141. package/templates/react/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx.ejs +0 -53
  142. package/templates/react/add-on/tanstack-query/info.json +0 -13
  143. package/templates/react/add-on/tanstack-query/package.json +0 -6
  144. package/templates/react/base/README.md.ejs +0 -558
  145. package/templates/react/base/_dot_gitignore +0 -5
  146. package/templates/react/base/_dot_vscode/settings.biome.json +0 -38
  147. package/templates/react/base/_dot_vscode/settings.json +0 -11
  148. package/templates/react/base/index.html.ejs +0 -20
  149. package/templates/react/base/package.biome.json +0 -10
  150. package/templates/react/base/package.eslintprettier.json +0 -11
  151. package/templates/react/base/package.json +0 -29
  152. package/templates/react/base/package.ts.json +0 -7
  153. package/templates/react/base/package.tw.json +0 -6
  154. package/templates/react/base/public/favicon.ico +0 -0
  155. package/templates/react/base/public/logo192.png +0 -0
  156. package/templates/react/base/public/logo512.png +0 -0
  157. package/templates/react/base/public/manifest.json +0 -25
  158. package/templates/react/base/public/robots.txt +0 -3
  159. package/templates/react/base/src/App.css +0 -38
  160. package/templates/react/base/src/App.test.tsx.ejs +0 -10
  161. package/templates/react/base/src/App.tsx.ejs +0 -74
  162. package/templates/react/base/src/components/Header.tsx.ejs +0 -27
  163. package/templates/react/base/src/logo.svg +0 -44
  164. package/templates/react/base/src/reportWebVitals.ts.ejs +0 -28
  165. package/templates/react/base/src/styles.css.ejs +0 -15
  166. package/templates/react/base/toolchain/.prettierignore +0 -3
  167. package/templates/react/base/toolchain/biome.json +0 -31
  168. package/templates/react/base/toolchain/eslint.config.js +0 -5
  169. package/templates/react/base/toolchain/prettier.config.js +0 -10
  170. package/templates/react/base/tsconfig.json.ejs +0 -29
  171. package/templates/react/base/vite.config.js.ejs +0 -23
  172. package/templates/react/code-router/src/main.tsx.ejs +0 -92
  173. package/templates/react/example/tanchat/README.md +0 -37
  174. package/templates/react/example/tanchat/assets/_dot_env.local.append +0 -2
  175. package/templates/react/example/tanchat/assets/public/example-guitar-flowers.jpg +0 -0
  176. package/templates/react/example/tanchat/assets/public/example-guitar-motherboard.jpg +0 -0
  177. package/templates/react/example/tanchat/assets/public/example-guitar-racing.jpg +0 -0
  178. package/templates/react/example/tanchat/assets/public/example-guitar-steamer-trunk.jpg +0 -0
  179. package/templates/react/example/tanchat/assets/public/example-guitar-superhero.jpg +0 -0
  180. package/templates/react/example/tanchat/assets/public/example-guitar-traveling.jpg +0 -0
  181. package/templates/react/example/tanchat/assets/public/example-guitar-video-games.jpg +0 -0
  182. package/templates/react/example/tanchat/assets/src/components/example-AIAssistant.tsx +0 -173
  183. package/templates/react/example/tanchat/assets/src/components/example-GuitarRecommendation.tsx +0 -47
  184. package/templates/react/example/tanchat/assets/src/data/example-guitars.ts +0 -83
  185. package/templates/react/example/tanchat/assets/src/demo.index.css +0 -220
  186. package/templates/react/example/tanchat/assets/src/integrations/tanchat/header-user.tsx +0 -5
  187. package/templates/react/example/tanchat/assets/src/routes/api.messages.ts +0 -24
  188. package/templates/react/example/tanchat/assets/src/routes/api.sse.ts +0 -23
  189. package/templates/react/example/tanchat/assets/src/routes/example.chat.tsx +0 -159
  190. package/templates/react/example/tanchat/assets/src/routes/example.guitars/$guitarId.tsx +0 -50
  191. package/templates/react/example/tanchat/assets/src/routes/example.guitars/index.tsx +0 -54
  192. package/templates/react/example/tanchat/assets/src/store/example-assistant.ts +0 -3
  193. package/templates/react/example/tanchat/assets/src/utils/demo.ai.ts +0 -62
  194. package/templates/react/example/tanchat/assets/src/utils/demo.sse.ts +0 -31
  195. package/templates/react/example/tanchat/assets/src/utils/demo.tools.ts +0 -47
  196. package/templates/react/example/tanchat/info.json +0 -19
  197. package/templates/react/example/tanchat/package.json +0 -16
  198. package/templates/react/file-router/package.fr.json +0 -5
  199. package/templates/react/file-router/src/main.tsx.ejs +0 -55
  200. package/templates/react/file-router/src/routes/__root.tsx.ejs +0 -82
  201. package/templates/solid/add-on/form/assets/src/routes/demo.form.tsx.ejs +0 -352
  202. package/templates/solid/add-on/form/info.json +0 -13
  203. package/templates/solid/add-on/form/package.json +0 -5
  204. package/templates/solid/add-on/module-federation/assets/module-federation.config.js.ejs +0 -27
  205. package/templates/solid/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
  206. package/templates/solid/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -9
  207. package/templates/solid/add-on/module-federation/info.json +0 -7
  208. package/templates/solid/add-on/module-federation/package.json +0 -5
  209. package/templates/solid/add-on/sentry/assets/_dot_cursorrules.append +0 -22
  210. package/templates/solid/add-on/sentry/assets/_dot_env.local.append +0 -2
  211. package/templates/solid/add-on/sentry/assets/src/routes/demo.sentry.bad-event-handler.tsx +0 -20
  212. package/templates/solid/add-on/sentry/info.json +0 -13
  213. package/templates/solid/add-on/sentry/package.json +0 -5
  214. package/templates/solid/add-on/solid-ui/README.md +0 -9
  215. package/templates/solid/add-on/solid-ui/assets/src/lib/utils.ts +0 -6
  216. package/templates/solid/add-on/solid-ui/assets/src/styles.css +0 -138
  217. package/templates/solid/add-on/solid-ui/assets/ui.config.json +0 -13
  218. package/templates/solid/add-on/solid-ui/info.json +0 -11
  219. package/templates/solid/add-on/solid-ui/package.json +0 -9
  220. package/templates/solid/add-on/start/assets/app.config.ts +0 -16
  221. package/templates/solid/add-on/start/assets/src/api.ts +0 -6
  222. package/templates/solid/add-on/start/assets/src/client.tsx +0 -7
  223. package/templates/solid/add-on/start/assets/src/router.tsx.ejs +0 -24
  224. package/templates/solid/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +0 -49
  225. package/templates/solid/add-on/start/assets/src/ssr.tsx +0 -12
  226. package/templates/solid/add-on/start/info.json +0 -14
  227. package/templates/solid/add-on/start/package.json +0 -12
  228. package/templates/solid/add-on/store/assets/src/lib/demo-store.ts +0 -13
  229. package/templates/solid/add-on/store/assets/src/routes/demo.store.tsx.ejs +0 -77
  230. package/templates/solid/add-on/store/info.json +0 -13
  231. package/templates/solid/add-on/store/package.json +0 -6
  232. package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/header-user.tsx +0 -5
  233. package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/provider.tsx +0 -15
  234. package/templates/solid/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx +0 -30
  235. package/templates/solid/add-on/tanstack-query/info.json +0 -13
  236. package/templates/solid/add-on/tanstack-query/package.json +0 -6
  237. package/templates/solid/base/README.md.ejs +0 -215
  238. package/templates/solid/base/_dot_cursorrules.append +0 -35
  239. package/templates/solid/base/_dot_gitignore +0 -5
  240. package/templates/solid/base/_dot_vscode/settings.biome.json +0 -38
  241. package/templates/solid/base/_dot_vscode/settings.json +0 -11
  242. package/templates/solid/base/index.html.ejs +0 -20
  243. package/templates/solid/base/package.biome.json +0 -10
  244. package/templates/solid/base/package.eslintprettier.json +0 -11
  245. package/templates/solid/base/package.json +0 -22
  246. package/templates/solid/base/package.ts.json +0 -5
  247. package/templates/solid/base/package.tw.json +0 -6
  248. package/templates/solid/base/public/favicon.ico +0 -0
  249. package/templates/solid/base/public/logo192.png +0 -0
  250. package/templates/solid/base/public/logo512.png +0 -0
  251. package/templates/solid/base/public/manifest.json +0 -25
  252. package/templates/solid/base/public/robots.txt +0 -3
  253. package/templates/solid/base/src/App.css +0 -0
  254. package/templates/solid/base/src/App.tsx.ejs +0 -47
  255. package/templates/solid/base/src/components/Header.tsx.ejs +0 -26
  256. package/templates/solid/base/src/logo.svg +0 -120
  257. package/templates/solid/base/src/styles.css.ejs +0 -15
  258. package/templates/solid/base/toolchain/.prettierignore +0 -3
  259. package/templates/solid/base/toolchain/biome.json +0 -31
  260. package/templates/solid/base/toolchain/eslint.config.js +0 -5
  261. package/templates/solid/base/toolchain/prettier.config.js +0 -10
  262. package/templates/solid/base/tsconfig.json.ejs +0 -31
  263. package/templates/solid/base/vite.config.js.ejs +0 -22
  264. package/templates/solid/code-router/src/main.tsx.ejs +0 -71
  265. package/templates/solid/example/tanchat/README.md +0 -52
  266. package/templates/solid/example/tanchat/assets/ai-streaming-server/README.md +0 -110
  267. package/templates/solid/example/tanchat/assets/ai-streaming-server/_dot_env.example +0 -1
  268. package/templates/solid/example/tanchat/assets/ai-streaming-server/package.json +0 -26
  269. package/templates/solid/example/tanchat/assets/ai-streaming-server/src/index.ts +0 -102
  270. package/templates/solid/example/tanchat/assets/ai-streaming-server/tsconfig.json +0 -15
  271. package/templates/solid/example/tanchat/assets/src/components/demo.SettingsDialog.tsx +0 -149
  272. package/templates/solid/example/tanchat/assets/src/demo.index.css +0 -227
  273. package/templates/solid/example/tanchat/assets/src/lib/demo-store.ts +0 -13
  274. package/templates/solid/example/tanchat/assets/src/routes/example.chat.tsx +0 -435
  275. package/templates/solid/example/tanchat/assets/src/store/demo.hooks.ts +0 -17
  276. package/templates/solid/example/tanchat/assets/src/store/demo.store.ts +0 -133
  277. package/templates/solid/example/tanchat/info.json +0 -14
  278. package/templates/solid/example/tanchat/package.json +0 -7
  279. package/templates/solid/file-router/package.fr.json +0 -5
  280. package/templates/solid/file-router/src/main.tsx.ejs +0 -47
  281. package/templates/solid/file-router/src/routes/__root.tsx.ejs +0 -41
  282. package/templates/solid/file-router/src/routes/index.tsx +0 -43
  283. package/tests/cra.test.ts +0 -293
  284. package/tests/snapshots/cra/cr-js-npm.json +0 -33
  285. package/tests/snapshots/cra/cr-ts-npm.json +0 -34
  286. package/tests/snapshots/cra/cr-ts-start-npm.json +0 -38
  287. package/tests/snapshots/cra/fr-ts-npm.json +0 -34
  288. package/tests/snapshots/cra/fr-ts-tw-npm.json +0 -33
  289. package/tests/snapshots/cra/solid-cr-js-npm.json +0 -31
  290. package/tests/snapshots/cra/solid-cr-ts-npm.json +0 -32
  291. package/tests/snapshots/cra/solid-cr-ts-start-npm.json +0 -36
  292. package/tests/snapshots/cra/solid-fr-ts-npm.json +0 -33
  293. package/tests/snapshots/cra/solid-fr-ts-tw-npm.json +0 -32
  294. package/tests/test-utilities.ts +0 -87
@@ -1,16 +1,80 @@
1
1
  import type { CODE_ROUTER, FILE_ROUTER } from './constants.js';
2
2
  import type { PackageManager } from './package-manager.js';
3
- import type { ToolChain } from './toolchain.js';
4
- export type Framework = 'solid' | 'react';
5
3
  export type TemplateOptions = 'typescript' | 'javascript' | 'file-router';
6
4
  export type Mode = typeof CODE_ROUTER | typeof FILE_ROUTER;
5
+ export type FileBundleHandler = {
6
+ getFiles: () => Promise<Array<string>>;
7
+ getFileContents: (path: string) => Promise<string>;
8
+ };
9
+ export type AddOnDefinition = {
10
+ id: string;
11
+ name: string;
12
+ description: string;
13
+ type: 'add-on' | 'example' | 'starter' | 'toolchain';
14
+ link: string;
15
+ templates: Array<string>;
16
+ routes?: Array<{
17
+ url: string;
18
+ name: string;
19
+ path: string;
20
+ jsName: string;
21
+ }>;
22
+ packageAdditions: {
23
+ dependencies?: Record<string, string>;
24
+ devDependencies?: Record<string, string>;
25
+ scripts?: Record<string, string>;
26
+ };
27
+ command?: {
28
+ command: string;
29
+ args?: Array<string>;
30
+ };
31
+ readme?: string;
32
+ phase: 'setup' | 'add-on';
33
+ shadcnComponents?: Array<string>;
34
+ warning?: string;
35
+ dependsOn?: Array<string>;
36
+ integrations?: Array<{
37
+ type: 'provider' | 'root-provider' | 'layout' | 'header-user';
38
+ path: string;
39
+ jsName: string;
40
+ }>;
41
+ variables?: Array<Variable>;
42
+ files?: Record<string, string>;
43
+ deletedFiles?: Array<string>;
44
+ };
45
+ export type StarterDefinition = AddOnDefinition & {
46
+ type: 'starter';
47
+ version: string;
48
+ author: string;
49
+ link: string;
50
+ license: string;
51
+ mode: Mode;
52
+ framework: string;
53
+ typescript: boolean;
54
+ tailwind: boolean;
55
+ };
56
+ export type AddOn = AddOnDefinition & FileBundleHandler;
57
+ export type Starter = StarterDefinition & FileBundleHandler;
58
+ export type FrameworkDefinition = {
59
+ id: string;
60
+ name: string;
61
+ description: string;
62
+ version: string;
63
+ baseDirectory: string;
64
+ addOnsDirectories: Array<string>;
65
+ examplesDirectory: string;
66
+ };
67
+ export type Framework = FrameworkDefinition & FileBundleHandler & {
68
+ basePackageJSON: Record<string, any>;
69
+ optionalPackages: Record<string, any>;
70
+ getAddOns: () => Array<AddOn>;
71
+ };
7
72
  export interface Options {
8
73
  framework: Framework;
9
74
  projectName: string;
10
75
  typescript: boolean;
11
76
  tailwind: boolean;
12
77
  packageManager: PackageManager;
13
- toolchain: ToolChain;
14
78
  mode: Mode;
15
79
  addOns: boolean;
16
80
  chosenAddOns: Array<AddOn>;
@@ -18,35 +82,32 @@ export interface Options {
18
82
  variableValues: Record<string, string | number | boolean>;
19
83
  starter?: AddOn | undefined;
20
84
  }
21
- export interface CliOptions {
22
- template?: TemplateOptions;
23
- framework?: Framework;
24
- tailwind?: boolean;
25
- packageManager?: PackageManager;
26
- toolchain?: ToolChain;
27
- projectName?: string;
28
- git?: boolean;
29
- addOns?: Array<string> | boolean;
30
- listAddOns?: boolean;
31
- mcp?: boolean;
32
- mcpSse?: boolean;
33
- starter?: string;
34
- targetDir?: string;
35
- }
36
- export type Environment = {
85
+ type ProjectEnvironment = {
37
86
  startRun: () => void;
38
87
  finishRun: () => void;
39
88
  getErrors: () => Array<string>;
89
+ };
90
+ type FileEnvironment = {
40
91
  appendFile: (path: string, contents: string) => Promise<void>;
41
92
  copyFile: (from: string, to: string) => Promise<void>;
42
93
  writeFile: (path: string, contents: string) => Promise<void>;
43
94
  execute: (command: string, args: Array<string>, cwd: string) => Promise<void>;
44
95
  deleteFile: (path: string) => Promise<void>;
45
- readFile: (path: string, encoding?: BufferEncoding) => Promise<string>;
46
96
  exists: (path: string) => boolean;
47
- readdir: (path: string) => Array<string>;
48
- isDirectory: (path: string) => boolean;
49
97
  };
98
+ type UIEnvironment = {
99
+ intro: (message: string) => void;
100
+ outro: (message: string) => void;
101
+ info: (title?: string, message?: string) => void;
102
+ error: (title?: string, message?: string) => void;
103
+ warn: (title?: string, message?: string) => void;
104
+ spinner: () => {
105
+ start: (message: string) => void;
106
+ stop: (message: string) => void;
107
+ };
108
+ confirm: (message: string) => Promise<boolean>;
109
+ };
110
+ export type Environment = ProjectEnvironment & FileEnvironment & UIEnvironment;
50
111
  type BooleanVariable = {
51
112
  name: string;
52
113
  default: boolean;
@@ -66,44 +127,4 @@ type StringVariable = {
66
127
  type: 'string';
67
128
  };
68
129
  export type Variable = BooleanVariable | NumberVariable | StringVariable;
69
- export type AddOn = {
70
- id: string;
71
- name: string;
72
- description: string;
73
- type: 'add-on' | 'example' | 'starter';
74
- link: string;
75
- templates: Array<string>;
76
- routes: Array<{
77
- url: string;
78
- name: string;
79
- }>;
80
- packageAdditions: {
81
- dependencies?: Record<string, string>;
82
- devDependencies?: Record<string, string>;
83
- scripts?: Record<string, string>;
84
- };
85
- command?: {
86
- command: string;
87
- args?: Array<string>;
88
- };
89
- readme?: string;
90
- phase: 'setup' | 'add-on';
91
- shadcnComponents?: Array<string>;
92
- warning?: string;
93
- dependsOn?: Array<string>;
94
- variables?: Array<Variable>;
95
- files?: Record<string, string>;
96
- deletedFiles?: Array<string>;
97
- };
98
- export type Starter = AddOn & {
99
- type: 'starter';
100
- version: string;
101
- author: string;
102
- link: string;
103
- license: string;
104
- mode: Mode;
105
- framework: Framework;
106
- typescript: boolean;
107
- tailwind: boolean;
108
- };
109
130
  export {};
@@ -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/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.15",
3
+ "version": "0.10.0-alpha.16",
4
4
  "description": "Tanstack Application Builder Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -15,33 +15,23 @@
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",
33
27
  "memfs": "^4.17.0",
34
- "prettier": "^3.5.0",
35
- "zod": "^3.24.2"
28
+ "prettier": "^3.5.0"
36
29
  },
37
30
  "devDependencies": {
38
31
  "@tanstack/config": "^0.16.2",
39
32
  "@types/ejs": "^3.1.5",
40
- "@types/express": "^5.0.0",
41
33
  "@types/node": "^22.13.4",
42
34
  "eslint": "^9.20.0",
43
- "eslint-plugin-react-hooks": "^5.1.0",
44
- "eslint-plugin-unused-imports": "^4.1.4",
45
35
  "typescript": "^5.6.3",
46
36
  "vitest": "^3.0.8"
47
37
  },
package/src/add-ons.ts CHANGED
@@ -1,89 +1,10 @@
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 type { AddOn, Framework } from './types.js'
5
2
 
6
- import { getTemplatesRoot } from './templates.js'
7
- import { DEFAULT_FRAMEWORK } from './constants.js'
8
- import { readFileHelper } from './file-helper.js'
9
-
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(
3
+ export function getAllAddOns(
29
4
  framework: Framework,
30
5
  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
6
+ ): Array<AddOn> {
7
+ return framework.getAddOns().filter((a) => a.templates.includes(template))
87
8
  }
88
9
 
89
10
  // Turn the list of chosen add-on IDs into a final list of add-ons by resolving dependencies
@@ -94,7 +15,7 @@ export async function finalizeAddOns(
94
15
  ): Promise<Array<AddOn>> {
95
16
  const finalAddOnIDs = new Set(chosenAddOnIDs)
96
17
 
97
- const addOns = await getAllAddOns(framework, template)
18
+ const addOns = getAllAddOns(framework, template)
98
19
 
99
20
  for (const addOnID of finalAddOnIDs) {
100
21
  let addOn: AddOn | undefined
@@ -120,26 +41,8 @@ export async function finalizeAddOns(
120
41
  const finalAddOns = [...finalAddOnIDs].map(
121
42
  (id) => addOns.find((a) => a.id === id)!,
122
43
  )
123
- return finalAddOns
124
- }
125
44
 
126
- export async function listAddOns(
127
- options: CliOptions,
128
- {
129
- forcedMode,
130
- forcedAddOns = [],
131
- }: {
132
- forcedMode?: TemplateOptions
133
- forcedAddOns?: Array<string>
134
- },
135
- ) {
136
- const addOns = await getAllAddOns(
137
- options.framework || DEFAULT_FRAMEWORK,
138
- forcedMode || options.template || 'typescript',
139
- )
140
- for (const addOn of addOns.filter((a) => !forcedAddOns.includes(a.id))) {
141
- console.log(`${chalk.bold(addOn.id)}: ${addOn.description}`)
142
- }
45
+ return finalAddOns
143
46
  }
144
47
 
145
48
  function loadAddOn(addOn: AddOn): AddOn {
@@ -150,5 +53,9 @@ export async function loadRemoteAddOn(url: string): Promise<AddOn> {
150
53
  const response = await fetch(url)
151
54
  const fileContent = await response.json()
152
55
  fileContent.id = url
153
- return fileContent
56
+ return {
57
+ ...fileContent,
58
+ getFiles: () => Promise.resolve(Object.keys(fileContent.files)),
59
+ getFileContents: (path: string) => Promise.resolve(fileContent.files[path]),
60
+ }
154
61
  }
@@ -1,32 +1,22 @@
1
1
  import { mkdir, readFile, writeFile } from 'node:fs/promises'
2
2
  import { existsSync, statSync } from 'node:fs'
3
3
  import { basename, dirname, resolve } from 'node:path'
4
- import chalk from 'chalk'
5
4
  import { execa, execaSync } from 'execa'
6
- import {
7
- cancel,
8
- confirm,
9
- intro,
10
- isCancel,
11
- log,
12
- outro,
13
- spinner,
14
- } from '@clack/prompts'
15
5
 
16
6
  import { CONFIG_FILE } from './constants.js'
7
+ import { finalizeAddOns } from './add-ons.js'
8
+ import { getFrameworkById } from './frameworks.js'
17
9
  import {
18
10
  createDefaultEnvironment,
19
11
  createMemoryEnvironment,
20
12
  } from './environment.js'
21
13
  import { createApp } from './create-app.js'
22
- import { finalizeAddOns } from './add-ons.js'
23
- import { sortObject } from './utils.js'
24
14
  import { readConfigFile, writeConfigFile } from './config-file.js'
15
+ import { sortObject } from './utils.js'
25
16
 
17
+ import type { Environment, Options } from './types.js'
26
18
  import type { PersistedOptions } from './config-file.js'
27
19
 
28
- import type { Framework, Options } from './types.js'
29
-
30
20
  function isDirectory(path: string) {
31
21
  return statSync(path).isDirectory()
32
22
  }
@@ -40,14 +30,17 @@ async function createOptions(
40
30
  json: PersistedOptions,
41
31
  addOns: Array<string>,
42
32
  ): Promise<Required<Options>> {
33
+ const framework = getFrameworkById(json.framework)
34
+
43
35
  return {
44
36
  ...json,
37
+ framework,
45
38
  tailwind: true,
46
- chosenAddOns: await finalizeAddOns(
47
- json.framework as Framework,
48
- json.mode as string,
49
- [...json.existingAddOns, ...addOns],
50
- ),
39
+ addOns: true,
40
+ chosenAddOns: await finalizeAddOns(framework!, json.mode as string, [
41
+ ...json.existingAddOns,
42
+ ...addOns,
43
+ ]),
51
44
  } as Required<Options>
52
45
  }
53
46
 
@@ -62,29 +55,32 @@ async function runCreateApp(options: Required<Options>) {
62
55
  return output
63
56
  }
64
57
 
65
- export async function add(
58
+ export async function addToApp(
66
59
  addOns: Array<string>,
67
60
  {
68
61
  silent = false,
69
62
  }: {
70
63
  silent?: boolean
71
64
  } = {},
65
+ environment: Environment,
72
66
  ) {
73
67
  const persistedOptions = await readConfigFile(process.cwd())
74
68
  if (!persistedOptions) {
75
- console.error(`${chalk.red('There is no .cta.json file in your project.')}
76
-
77
- This is probably because this was created with an older version of create-tsrouter-app.`)
69
+ environment.error(
70
+ 'There is no .cta.json file in your project.',
71
+ 'This is probably because this was created with an older version of create-tsrouter-app.',
72
+ )
78
73
  return
79
74
  }
80
75
 
81
76
  if (!silent) {
82
- intro(`Adding ${addOns.join(', ')} to the project...`)
77
+ environment.intro(`Adding ${addOns.join(', ')} to the project...`)
83
78
  }
84
79
 
85
80
  if (await hasPendingGitChanges()) {
86
- log.error(
87
- `${chalk.red('You have pending git changes.')} Please commit or stash them before adding add-ons.`,
81
+ environment.error(
82
+ 'You have pending git changes.',
83
+ 'Please commit or stash them before adding add-ons.',
88
84
  )
89
85
  return
90
86
  }
@@ -116,14 +112,12 @@ This is probably because this was created with an older version of create-tsrout
116
112
  }
117
113
 
118
114
  if (overwrittenFiles.length > 0 && !silent) {
119
- log.warn(
120
- `${chalk.yellow('The following will be overwritten:')}\n${overwrittenFiles.join('\n')}`,
115
+ environment.warn(
116
+ 'The following will be overwritten:',
117
+ overwrittenFiles.join('\n'),
121
118
  )
122
- const shouldContinue = await confirm({
123
- message: 'Do you want to continue?',
124
- })
125
- if (isCancel(shouldContinue)) {
126
- cancel('Operation cancelled.')
119
+ const shouldContinue = await environment.confirm('Do you want to continue?')
120
+ if (!shouldContinue) {
127
121
  process.exit(0)
128
122
  }
129
123
  }
@@ -171,7 +165,7 @@ This is probably because this was created with an older version of create-tsrout
171
165
  const realEnvironment = createDefaultEnvironment()
172
166
  writeConfigFile(realEnvironment, process.cwd(), newOptions)
173
167
 
174
- const s = silent ? null : spinner()
168
+ const s = silent ? null : environment.spinner()
175
169
  s?.start(`Installing dependencies via ${newOptions.packageManager}...`)
176
170
  await realEnvironment.execute(
177
171
  newOptions.packageManager,
@@ -181,6 +175,6 @@ This is probably because this was created with an older version of create-tsrout
181
175
  s?.stop(`Installed dependencies`)
182
176
 
183
177
  if (!silent) {
184
- outro('Add-ons added successfully!')
178
+ environment.outro('Add-ons added successfully!')
185
179
  }
186
180
  }
@@ -3,12 +3,13 @@ import { resolve } from 'node:path'
3
3
 
4
4
  import { CONFIG_FILE } from './constants.js'
5
5
 
6
- import type { Environment, Options } from './types'
6
+ import type { Environment, Options } from './types.js'
7
7
 
8
- export type PersistedOptions = Exclude<
8
+ export type PersistedOptions = Omit<
9
9
  Partial<Options>,
10
- 'addOns' | 'chosenAddOns'
10
+ 'addOns' | 'chosenAddOns' | 'framework'
11
11
  > & {
12
+ framework: string
12
13
  version: number
13
14
  existingAddOns: Array<string>
14
15
  }
@@ -18,13 +19,15 @@ export async function writeConfigFile(
18
19
  targetDir: string,
19
20
  options: Options,
20
21
  ) {
22
+ /* eslint-disable unused-imports/no-unused-vars */
23
+ const { addOns, chosenAddOns, framework, ...rest } = options
24
+ /* eslint-enable unused-imports/no-unused-vars */
21
25
  const persistedOptions: PersistedOptions = {
22
- ...options,
26
+ ...rest,
23
27
  version: 1,
28
+ framework: options.framework.id,
24
29
  existingAddOns: options.chosenAddOns.map((addOn) => addOn.id),
25
30
  }
26
- delete persistedOptions.addOns
27
- delete persistedOptions.chosenAddOns
28
31
 
29
32
  await environment.writeFile(
30
33
  resolve(targetDir, CONFIG_FILE),
@@ -38,6 +41,9 @@ export async function readConfigFile(
38
41
  try {
39
42
  const configFile = resolve(targetDir, CONFIG_FILE)
40
43
  const config = await readFile(configFile, 'utf8')
44
+
45
+ // TODO: Look for old config files and convert them to the new format
46
+
41
47
  return JSON.parse(config)
42
48
  } catch {
43
49
  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'