@tanstack/cta-engine 0.10.0-alpha.17 → 0.10.0-alpha.19

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 (314) 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 +67 -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 +10 -1
  10. package/dist/integrations/git.js +4 -0
  11. package/dist/integrations/shadcn.js +27 -0
  12. package/dist/package-json.js +45 -0
  13. package/dist/package-manager.js +51 -6
  14. package/dist/template-file.js +122 -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 +13 -1
  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 +85 -63
  28. package/dist/types/utils.d.ts +5 -0
  29. package/dist/utils.js +9 -0
  30. package/package.json +4 -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 +125 -736
  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 +42 -1
  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 +165 -0
  45. package/src/types.ts +100 -69
  46. package/src/utils.ts +17 -0
  47. package/tests/add-ons.test.ts +67 -0
  48. package/tests/config-file.test.ts +64 -0
  49. package/tests/create-app.test.ts +144 -0
  50. package/tests/environment.test.ts +96 -0
  51. package/tests/file-helper.test.ts +90 -0
  52. package/tests/frameworks.test.ts +95 -0
  53. package/tests/index.test.ts +9 -0
  54. package/tests/integrations/git.test.ts +20 -0
  55. package/tests/integrations/shadcn.test.ts +106 -0
  56. package/tests/package-json.test.ts +63 -0
  57. package/tests/package-manager.test.ts +154 -0
  58. package/tests/template-file.test.ts +215 -0
  59. package/tests/utils.test.ts +23 -0
  60. package/vitest.config.ts +19 -0
  61. package/dist/cli.js +0 -125
  62. package/dist/custom-add-on.js +0 -254
  63. package/dist/file-helper.js +0 -18
  64. package/dist/mcp.js +0 -229
  65. package/dist/options.js +0 -330
  66. package/dist/templates.js +0 -6
  67. package/dist/toolchain.js +0 -6
  68. package/dist/types/add.d.ts +0 -3
  69. package/dist/types/cli.d.ts +0 -7
  70. package/dist/types/custom-add-on.d.ts +0 -3
  71. package/dist/types/file-helper.d.ts +0 -2
  72. package/dist/types/mcp.d.ts +0 -7
  73. package/dist/types/options.d.ts +0 -6
  74. package/dist/types/templates.d.ts +0 -1
  75. package/dist/types/toolchain.d.ts +0 -3
  76. package/src/cli.ts +0 -196
  77. package/src/custom-add-on.ts +0 -325
  78. package/src/file-helper.ts +0 -20
  79. package/src/mcp.ts +0 -302
  80. package/src/options.ts +0 -410
  81. package/src/templates.ts +0 -7
  82. package/src/toolchain.ts +0 -7
  83. package/templates/react/add-on/clerk/README.md +0 -3
  84. package/templates/react/add-on/clerk/assets/_dot_env.local.append +0 -2
  85. package/templates/react/add-on/clerk/assets/src/integrations/clerk/header-user.tsx +0 -19
  86. package/templates/react/add-on/clerk/assets/src/integrations/clerk/provider.tsx +0 -18
  87. package/templates/react/add-on/clerk/assets/src/routes/demo.clerk.tsx +0 -20
  88. package/templates/react/add-on/clerk/info.json +0 -13
  89. package/templates/react/add-on/clerk/package.json +0 -5
  90. package/templates/react/add-on/convex/README.md +0 -4
  91. package/templates/react/add-on/convex/assets/_dot_cursorrules.append +0 -93
  92. package/templates/react/add-on/convex/assets/_dot_env.local.append +0 -3
  93. package/templates/react/add-on/convex/assets/convex/products.ts +0 -8
  94. package/templates/react/add-on/convex/assets/convex/schema.ts +0 -10
  95. package/templates/react/add-on/convex/assets/src/integrations/convex/provider.tsx +0 -20
  96. package/templates/react/add-on/convex/assets/src/routes/demo.convex.tsx +0 -33
  97. package/templates/react/add-on/convex/info.json +0 -13
  98. package/templates/react/add-on/convex/package.json +0 -6
  99. package/templates/react/add-on/form/assets/src/components/demo.FormComponents.tsx.ejs +0 -300
  100. package/templates/react/add-on/form/assets/src/hooks/demo.form-context.ts +0 -4
  101. package/templates/react/add-on/form/assets/src/hooks/demo.form.ts +0 -22
  102. package/templates/react/add-on/form/assets/src/routes/demo.form.address.tsx.ejs +0 -213
  103. package/templates/react/add-on/form/assets/src/routes/demo.form.simple.tsx.ejs +0 -77
  104. package/templates/react/add-on/form/info.json +0 -26
  105. package/templates/react/add-on/form/package.json +0 -6
  106. package/templates/react/add-on/module-federation/assets/module-federation.config.js.ejs +0 -31
  107. package/templates/react/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
  108. package/templates/react/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -11
  109. package/templates/react/add-on/module-federation/info.json +0 -7
  110. package/templates/react/add-on/module-federation/package.json +0 -5
  111. package/templates/react/add-on/netlify/README.md +0 -11
  112. package/templates/react/add-on/netlify/info.json +0 -7
  113. package/templates/react/add-on/sentry/assets/_dot_cursorrules.append +0 -22
  114. package/templates/react/add-on/sentry/assets/_dot_env.local.append +0 -2
  115. package/templates/react/add-on/sentry/assets/src/app/global-middleware.ts +0 -25
  116. package/templates/react/add-on/sentry/assets/src/routes/demo.sentry.testing.tsx +0 -480
  117. package/templates/react/add-on/sentry/info.json +0 -14
  118. package/templates/react/add-on/sentry/package.json +0 -7
  119. package/templates/react/add-on/shadcn/README.md +0 -7
  120. package/templates/react/add-on/shadcn/assets/_dot_cursorrules.append +0 -7
  121. package/templates/react/add-on/shadcn/assets/components.json +0 -21
  122. package/templates/react/add-on/shadcn/assets/src/lib/utils.ts +0 -6
  123. package/templates/react/add-on/shadcn/assets/src/styles.css +0 -138
  124. package/templates/react/add-on/shadcn/info.json +0 -7
  125. package/templates/react/add-on/shadcn/package.json +0 -9
  126. package/templates/react/add-on/start/assets/_dot_gitignore.append +0 -2
  127. package/templates/react/add-on/start/assets/app.config.ts.ejs +0 -19
  128. package/templates/react/add-on/start/assets/src/api.ts +0 -6
  129. package/templates/react/add-on/start/assets/src/client.tsx +0 -8
  130. package/templates/react/add-on/start/assets/src/router.tsx.ejs +0 -77
  131. package/templates/react/add-on/start/assets/src/routes/api.demo-names.ts +0 -11
  132. package/templates/react/add-on/start/assets/src/routes/demo.start.api-request.tsx.ejs +0 -33
  133. package/templates/react/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +0 -50
  134. package/templates/react/add-on/start/assets/src/ssr.tsx +0 -12
  135. package/templates/react/add-on/start/info.json +0 -18
  136. package/templates/react/add-on/start/package.json +0 -13
  137. package/templates/react/add-on/store/assets/src/lib/demo-store.ts +0 -13
  138. package/templates/react/add-on/store/assets/src/routes/demo.store.tsx.ejs +0 -75
  139. package/templates/react/add-on/store/info.json +0 -13
  140. package/templates/react/add-on/store/package.json +0 -6
  141. package/templates/react/add-on/t3env/README.md +0 -16
  142. package/templates/react/add-on/t3env/assets/src/env.ts +0 -39
  143. package/templates/react/add-on/t3env/info.json +0 -10
  144. package/templates/react/add-on/t3env/package.json +0 -6
  145. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/init.ts +0 -9
  146. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/react.ts +0 -4
  147. package/templates/react/add-on/tRPC/assets/src/integrations/trpc/router.ts +0 -18
  148. package/templates/react/add-on/tRPC/assets/src/routes/api.trpc.$.tsx +0 -16
  149. package/templates/react/add-on/tRPC/info.json +0 -9
  150. package/templates/react/add-on/tRPC/package.json +0 -9
  151. package/templates/react/add-on/table/assets/src/data/demo-table-data.ts +0 -50
  152. package/templates/react/add-on/table/assets/src/routes/demo.table.tsx.ejs +0 -373
  153. package/templates/react/add-on/table/info.json +0 -13
  154. package/templates/react/add-on/table/package.json +0 -7
  155. package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/layout.tsx +0 -5
  156. package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/root-provider.tsx.ejs +0 -70
  157. package/templates/react/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx.ejs +0 -53
  158. package/templates/react/add-on/tanstack-query/info.json +0 -13
  159. package/templates/react/add-on/tanstack-query/package.json +0 -6
  160. package/templates/react/base/README.md.ejs +0 -558
  161. package/templates/react/base/_dot_gitignore +0 -5
  162. package/templates/react/base/_dot_vscode/settings.biome.json +0 -38
  163. package/templates/react/base/_dot_vscode/settings.json +0 -11
  164. package/templates/react/base/index.html.ejs +0 -20
  165. package/templates/react/base/package.biome.json +0 -10
  166. package/templates/react/base/package.eslintprettier.json +0 -11
  167. package/templates/react/base/package.json +0 -30
  168. package/templates/react/base/package.ts.json +0 -7
  169. package/templates/react/base/package.tw.json +0 -6
  170. package/templates/react/base/public/favicon.ico +0 -0
  171. package/templates/react/base/public/logo192.png +0 -0
  172. package/templates/react/base/public/logo512.png +0 -0
  173. package/templates/react/base/public/manifest.json +0 -25
  174. package/templates/react/base/public/robots.txt +0 -3
  175. package/templates/react/base/src/App.css +0 -38
  176. package/templates/react/base/src/App.test.tsx.ejs +0 -10
  177. package/templates/react/base/src/App.tsx.ejs +0 -74
  178. package/templates/react/base/src/components/Header.tsx.ejs +0 -27
  179. package/templates/react/base/src/logo.svg +0 -44
  180. package/templates/react/base/src/reportWebVitals.ts.ejs +0 -28
  181. package/templates/react/base/src/styles.css.ejs +0 -15
  182. package/templates/react/base/toolchain/.prettierignore +0 -3
  183. package/templates/react/base/toolchain/biome.json +0 -31
  184. package/templates/react/base/toolchain/eslint.config.js +0 -5
  185. package/templates/react/base/toolchain/prettier.config.js +0 -10
  186. package/templates/react/base/tsconfig.json.ejs +0 -29
  187. package/templates/react/base/vite.config.js.ejs +0 -23
  188. package/templates/react/code-router/src/main.tsx.ejs +0 -92
  189. package/templates/react/example/tanchat/README.md +0 -37
  190. package/templates/react/example/tanchat/assets/_dot_env.local.append +0 -2
  191. package/templates/react/example/tanchat/assets/public/example-guitar-flowers.jpg +0 -0
  192. package/templates/react/example/tanchat/assets/public/example-guitar-motherboard.jpg +0 -0
  193. package/templates/react/example/tanchat/assets/public/example-guitar-racing.jpg +0 -0
  194. package/templates/react/example/tanchat/assets/public/example-guitar-steamer-trunk.jpg +0 -0
  195. package/templates/react/example/tanchat/assets/public/example-guitar-superhero.jpg +0 -0
  196. package/templates/react/example/tanchat/assets/public/example-guitar-traveling.jpg +0 -0
  197. package/templates/react/example/tanchat/assets/public/example-guitar-video-games.jpg +0 -0
  198. package/templates/react/example/tanchat/assets/src/components/example-AIAssistant.tsx +0 -173
  199. package/templates/react/example/tanchat/assets/src/components/example-GuitarRecommendation.tsx +0 -47
  200. package/templates/react/example/tanchat/assets/src/data/example-guitars.ts +0 -83
  201. package/templates/react/example/tanchat/assets/src/demo.index.css +0 -220
  202. package/templates/react/example/tanchat/assets/src/integrations/tanchat/header-user.tsx +0 -5
  203. package/templates/react/example/tanchat/assets/src/routes/api.messages.ts +0 -24
  204. package/templates/react/example/tanchat/assets/src/routes/api.sse.ts +0 -23
  205. package/templates/react/example/tanchat/assets/src/routes/example.chat.tsx +0 -159
  206. package/templates/react/example/tanchat/assets/src/routes/example.guitars/$guitarId.tsx +0 -50
  207. package/templates/react/example/tanchat/assets/src/routes/example.guitars/index.tsx +0 -54
  208. package/templates/react/example/tanchat/assets/src/store/example-assistant.ts +0 -3
  209. package/templates/react/example/tanchat/assets/src/utils/demo.ai.ts +0 -62
  210. package/templates/react/example/tanchat/assets/src/utils/demo.sse.ts +0 -31
  211. package/templates/react/example/tanchat/assets/src/utils/demo.tools.ts +0 -47
  212. package/templates/react/example/tanchat/info.json +0 -19
  213. package/templates/react/example/tanchat/package.json +0 -16
  214. package/templates/react/file-router/package.fr.json +0 -5
  215. package/templates/react/file-router/src/main.tsx.ejs +0 -55
  216. package/templates/react/file-router/src/routes/__root.tsx.ejs +0 -82
  217. package/templates/solid/add-on/form/assets/src/routes/demo.form.tsx.ejs +0 -352
  218. package/templates/solid/add-on/form/info.json +0 -13
  219. package/templates/solid/add-on/form/package.json +0 -5
  220. package/templates/solid/add-on/module-federation/assets/module-federation.config.js.ejs +0 -27
  221. package/templates/solid/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
  222. package/templates/solid/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -9
  223. package/templates/solid/add-on/module-federation/info.json +0 -7
  224. package/templates/solid/add-on/module-federation/package.json +0 -5
  225. package/templates/solid/add-on/sentry/assets/_dot_cursorrules.append +0 -22
  226. package/templates/solid/add-on/sentry/assets/_dot_env.local.append +0 -2
  227. package/templates/solid/add-on/sentry/assets/src/routes/demo.sentry.bad-event-handler.tsx +0 -20
  228. package/templates/solid/add-on/sentry/info.json +0 -13
  229. package/templates/solid/add-on/sentry/package.json +0 -5
  230. package/templates/solid/add-on/solid-ui/README.md +0 -9
  231. package/templates/solid/add-on/solid-ui/assets/src/lib/utils.ts +0 -6
  232. package/templates/solid/add-on/solid-ui/assets/src/styles.css +0 -138
  233. package/templates/solid/add-on/solid-ui/assets/ui.config.json +0 -13
  234. package/templates/solid/add-on/solid-ui/info.json +0 -11
  235. package/templates/solid/add-on/solid-ui/package.json +0 -9
  236. package/templates/solid/add-on/start/assets/app.config.ts +0 -16
  237. package/templates/solid/add-on/start/assets/src/api.ts +0 -6
  238. package/templates/solid/add-on/start/assets/src/client.tsx +0 -7
  239. package/templates/solid/add-on/start/assets/src/router.tsx.ejs +0 -24
  240. package/templates/solid/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +0 -49
  241. package/templates/solid/add-on/start/assets/src/ssr.tsx +0 -12
  242. package/templates/solid/add-on/start/info.json +0 -14
  243. package/templates/solid/add-on/start/package.json +0 -12
  244. package/templates/solid/add-on/store/assets/src/lib/demo-store.ts +0 -13
  245. package/templates/solid/add-on/store/assets/src/routes/demo.store.tsx.ejs +0 -77
  246. package/templates/solid/add-on/store/info.json +0 -13
  247. package/templates/solid/add-on/store/package.json +0 -6
  248. package/templates/solid/add-on/t3env/README.md +0 -16
  249. package/templates/solid/add-on/t3env/assets/src/env.ts +0 -39
  250. package/templates/solid/add-on/t3env/info.json +0 -10
  251. package/templates/solid/add-on/t3env/package.json +0 -6
  252. package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/header-user.tsx +0 -5
  253. package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/provider.tsx +0 -15
  254. package/templates/solid/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx +0 -30
  255. package/templates/solid/add-on/tanstack-query/info.json +0 -13
  256. package/templates/solid/add-on/tanstack-query/package.json +0 -6
  257. package/templates/solid/base/README.md.ejs +0 -215
  258. package/templates/solid/base/_dot_cursorrules.append +0 -35
  259. package/templates/solid/base/_dot_gitignore +0 -5
  260. package/templates/solid/base/_dot_vscode/settings.biome.json +0 -38
  261. package/templates/solid/base/_dot_vscode/settings.json +0 -11
  262. package/templates/solid/base/index.html.ejs +0 -20
  263. package/templates/solid/base/package.biome.json +0 -10
  264. package/templates/solid/base/package.eslintprettier.json +0 -11
  265. package/templates/solid/base/package.json +0 -23
  266. package/templates/solid/base/package.ts.json +0 -5
  267. package/templates/solid/base/package.tw.json +0 -6
  268. package/templates/solid/base/public/favicon.ico +0 -0
  269. package/templates/solid/base/public/logo192.png +0 -0
  270. package/templates/solid/base/public/logo512.png +0 -0
  271. package/templates/solid/base/public/manifest.json +0 -25
  272. package/templates/solid/base/public/robots.txt +0 -3
  273. package/templates/solid/base/src/App.css +0 -0
  274. package/templates/solid/base/src/App.tsx.ejs +0 -47
  275. package/templates/solid/base/src/components/Header.tsx.ejs +0 -26
  276. package/templates/solid/base/src/logo.svg +0 -120
  277. package/templates/solid/base/src/styles.css.ejs +0 -15
  278. package/templates/solid/base/toolchain/.prettierignore +0 -3
  279. package/templates/solid/base/toolchain/biome.json +0 -31
  280. package/templates/solid/base/toolchain/eslint.config.js +0 -5
  281. package/templates/solid/base/toolchain/prettier.config.js +0 -10
  282. package/templates/solid/base/tsconfig.json.ejs +0 -31
  283. package/templates/solid/base/vite.config.js.ejs +0 -22
  284. package/templates/solid/code-router/src/main.tsx.ejs +0 -71
  285. package/templates/solid/example/tanchat/README.md +0 -52
  286. package/templates/solid/example/tanchat/assets/ai-streaming-server/README.md +0 -110
  287. package/templates/solid/example/tanchat/assets/ai-streaming-server/_dot_env.example +0 -1
  288. package/templates/solid/example/tanchat/assets/ai-streaming-server/package.json +0 -26
  289. package/templates/solid/example/tanchat/assets/ai-streaming-server/src/index.ts +0 -102
  290. package/templates/solid/example/tanchat/assets/ai-streaming-server/tsconfig.json +0 -15
  291. package/templates/solid/example/tanchat/assets/src/components/demo.SettingsDialog.tsx +0 -149
  292. package/templates/solid/example/tanchat/assets/src/demo.index.css +0 -227
  293. package/templates/solid/example/tanchat/assets/src/lib/demo-store.ts +0 -13
  294. package/templates/solid/example/tanchat/assets/src/routes/example.chat.tsx +0 -435
  295. package/templates/solid/example/tanchat/assets/src/store/demo.hooks.ts +0 -17
  296. package/templates/solid/example/tanchat/assets/src/store/demo.store.ts +0 -133
  297. package/templates/solid/example/tanchat/info.json +0 -14
  298. package/templates/solid/example/tanchat/package.json +0 -7
  299. package/templates/solid/file-router/package.fr.json +0 -5
  300. package/templates/solid/file-router/src/main.tsx.ejs +0 -47
  301. package/templates/solid/file-router/src/routes/__root.tsx.ejs +0 -41
  302. package/templates/solid/file-router/src/routes/index.tsx +0 -43
  303. package/tests/cra.test.ts +0 -293
  304. package/tests/snapshots/cra/cr-js-npm.json +0 -33
  305. package/tests/snapshots/cra/cr-ts-npm.json +0 -34
  306. package/tests/snapshots/cra/cr-ts-start-npm.json +0 -38
  307. package/tests/snapshots/cra/fr-ts-npm.json +0 -34
  308. package/tests/snapshots/cra/fr-ts-tw-npm.json +0 -33
  309. package/tests/snapshots/cra/solid-cr-js-npm.json +0 -31
  310. package/tests/snapshots/cra/solid-cr-ts-npm.json +0 -32
  311. package/tests/snapshots/cra/solid-cr-ts-start-npm.json +0 -36
  312. package/tests/snapshots/cra/solid-fr-ts-npm.json +0 -33
  313. package/tests/snapshots/cra/solid-fr-ts-tw-npm.json +0 -32
  314. package/tests/test-utilities.ts +0 -87
@@ -0,0 +1,59 @@
1
+ import { readFileSync, readdirSync, statSync } from 'node:fs';
2
+ import { basename, extname, resolve } from 'node:path';
3
+ const BINARY_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico'];
4
+ export function readFileHelper(path) {
5
+ if (BINARY_EXTENSIONS.includes(extname(path))) {
6
+ return `base64::${readFileSync(path).toString('base64')}`;
7
+ }
8
+ else {
9
+ return readFileSync(path, 'utf-8').toString();
10
+ }
11
+ }
12
+ export function getBinaryFile(content) {
13
+ if (content.startsWith('base64::')) {
14
+ const binaryContent = Buffer.from(content.replace('base64::', ''), 'base64');
15
+ return binaryContent;
16
+ }
17
+ return null;
18
+ }
19
+ export function relativePath(from, to) {
20
+ const cleanedFrom = from.startsWith('./') ? from.slice(2) : from;
21
+ const cleanedTo = to.startsWith('./') ? to.slice(2) : to;
22
+ const fromSegments = cleanedFrom.split('/');
23
+ const toSegments = cleanedTo.split('/');
24
+ fromSegments.pop();
25
+ toSegments.pop();
26
+ let commonIndex = 0;
27
+ while (commonIndex < fromSegments.length &&
28
+ commonIndex < toSegments.length &&
29
+ fromSegments[commonIndex] === toSegments[commonIndex]) {
30
+ commonIndex++;
31
+ }
32
+ const upLevels = fromSegments.length - commonIndex;
33
+ const downLevels = toSegments.slice(commonIndex);
34
+ if (upLevels === 0 && downLevels.length === 0) {
35
+ return `./${basename(to)}`;
36
+ }
37
+ else if (upLevels === 0 && downLevels.length > 0) {
38
+ return `./${downLevels.join('/')}/${basename(to)}`;
39
+ }
40
+ else {
41
+ const relativePath = [...Array(upLevels).fill('..'), ...downLevels].join('/');
42
+ return `${relativePath}/${basename(to)}`;
43
+ }
44
+ }
45
+ export function isDirectory(path) {
46
+ return statSync(path).isDirectory();
47
+ }
48
+ export function findFilesRecursively(path, files) {
49
+ const dirFiles = readdirSync(path);
50
+ for (const file of dirFiles) {
51
+ const filePath = resolve(path, file);
52
+ if (isDirectory(filePath)) {
53
+ findFilesRecursively(filePath, files);
54
+ }
55
+ else {
56
+ files[filePath] = readFileHelper(filePath);
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,78 @@
1
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { findFilesRecursively, isDirectory, readFileHelper, } from './file-helpers.js';
4
+ const frameworks = [];
5
+ function getAddOns(framework) {
6
+ const addOns = [];
7
+ for (const addOnsBase of framework.addOnsDirectories) {
8
+ for (const dir of readdirSync(addOnsBase).filter((file) => isDirectory(resolve(addOnsBase, file)))) {
9
+ const filePath = resolve(addOnsBase, dir, 'info.json');
10
+ const fileContent = readFileSync(filePath, 'utf-8');
11
+ const info = JSON.parse(fileContent);
12
+ let packageAdditions = {};
13
+ if (existsSync(resolve(addOnsBase, dir, 'package.json'))) {
14
+ packageAdditions = JSON.parse(readFileSync(resolve(addOnsBase, dir, 'package.json'), 'utf-8'));
15
+ }
16
+ let readme;
17
+ if (existsSync(resolve(addOnsBase, dir, 'README.md'))) {
18
+ readme = readFileSync(resolve(addOnsBase, dir, 'README.md'), 'utf-8');
19
+ }
20
+ const absoluteFiles = {};
21
+ const assetsDir = resolve(addOnsBase, dir, 'assets');
22
+ if (existsSync(assetsDir)) {
23
+ findFilesRecursively(assetsDir, absoluteFiles);
24
+ }
25
+ const files = {};
26
+ for (const file of Object.keys(absoluteFiles)) {
27
+ files[file.replace(assetsDir, '.')] = readFileHelper(file);
28
+ }
29
+ const getFiles = () => {
30
+ return Promise.resolve(Object.keys(files));
31
+ };
32
+ const getFileContents = (path) => {
33
+ return Promise.resolve(files[path]);
34
+ };
35
+ addOns.push({
36
+ ...info,
37
+ id: dir,
38
+ packageAdditions,
39
+ readme,
40
+ files,
41
+ deletedFiles: [],
42
+ getFiles,
43
+ getFileContents,
44
+ });
45
+ }
46
+ }
47
+ return addOns;
48
+ }
49
+ export function registerFramework(framework) {
50
+ const baseAssetsDirectory = resolve(framework.baseDirectory, 'base');
51
+ const basePackageJSON = JSON.parse(readFileSync(resolve(baseAssetsDirectory, 'package.json'), 'utf8'));
52
+ const optionalPackages = JSON.parse(readFileSync(resolve(framework.baseDirectory, 'packages.json'), 'utf8'));
53
+ const addOns = getAddOns(framework);
54
+ const frameworkWithBundler = {
55
+ ...framework,
56
+ getFiles: () => {
57
+ const files = {};
58
+ findFilesRecursively(baseAssetsDirectory, files);
59
+ return Promise.resolve(Object.keys(files).map((path) => path.replace(baseAssetsDirectory, '.')));
60
+ },
61
+ getFileContents: (path) => {
62
+ return Promise.resolve(readFileHelper(resolve(baseAssetsDirectory, path)));
63
+ },
64
+ basePackageJSON,
65
+ optionalPackages,
66
+ getAddOns: () => addOns,
67
+ };
68
+ frameworks.push(frameworkWithBundler);
69
+ }
70
+ export function getFrameworkById(id) {
71
+ return frameworks.find((framework) => framework.id === id);
72
+ }
73
+ export function getFrameworkByName(name) {
74
+ return frameworks.find((framework) => framework.name === name);
75
+ }
76
+ export function getFrameworks() {
77
+ return frameworks;
78
+ }
package/dist/index.js CHANGED
@@ -1 +1,10 @@
1
- export { cli } from './cli.js';
1
+ export { createApp } from './create-app.js';
2
+ export { addToApp } from './add-to-app.js';
3
+ export { finalizeAddOns, getAllAddOns, loadRemoteAddOn } from './add-ons.js';
4
+ export { createMemoryEnvironment, createDefaultEnvironment, } from './environment.js';
5
+ export { CODE_ROUTER, CONFIG_FILE, FILE_ROUTER } from './constants.js';
6
+ export { DEFAULT_PACKAGE_MANAGER, SUPPORTED_PACKAGE_MANAGERS, getPackageManager, getPackageManagerInstallCommand, getPackageManagerExecuteCommand, getPackageManagerScriptCommand, packageManagerInstall, packageManagerExecute, } from './package-manager.js';
7
+ export { registerFramework, getFrameworkById, getFrameworkByName, getFrameworks, } from './frameworks.js';
8
+ export { formatCommand, jsSafeName, sortObject } from './utils.js';
9
+ export { writeConfigFile, readConfigFile } from './config-file.js';
10
+ export { readFileHelper, getBinaryFile, relativePath } from './file-helpers.js';
@@ -0,0 +1,4 @@
1
+ import { resolve } from 'node:path';
2
+ export async function setupGit(environment, targetDir) {
3
+ await environment.execute('git', ['init'], resolve(targetDir));
4
+ }
@@ -0,0 +1,27 @@
1
+ import { resolve } from 'node:path';
2
+ import { packageManagerExecute } from '../package-manager.js';
3
+ export async function installShadcnComponents(environment, targetDir, options, silent) {
4
+ const s = silent ? null : environment.spinner();
5
+ if (options.chosenAddOns.find((a) => a.id === 'shadcn')) {
6
+ const shadcnComponents = new Set();
7
+ for (const addOn of options.chosenAddOns) {
8
+ if (addOn.shadcnComponents) {
9
+ for (const component of addOn.shadcnComponents) {
10
+ shadcnComponents.add(component);
11
+ }
12
+ }
13
+ }
14
+ if (options.starter) {
15
+ if (options.starter.shadcnComponents) {
16
+ for (const component of options.starter.shadcnComponents) {
17
+ shadcnComponents.add(component);
18
+ }
19
+ }
20
+ }
21
+ if (shadcnComponents.size > 0) {
22
+ s?.start(`Installing shadcn components (${Array.from(shadcnComponents).join(', ')})...`);
23
+ await packageManagerExecute(environment, resolve(targetDir), options.packageManager, 'shadcn@latest', ['add', '--silent', '--yes', ...Array.from(shadcnComponents)]);
24
+ s?.stop(`Installed additional shadcn components`);
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,45 @@
1
+ import { FILE_ROUTER } from './constants.js';
2
+ import { sortObject } from './utils.js';
3
+ function mergePackageJSON(packageJSON, overlayPackageJSON) {
4
+ return {
5
+ ...packageJSON,
6
+ dependencies: {
7
+ ...packageJSON.dependencies,
8
+ ...overlayPackageJSON.dependencies,
9
+ },
10
+ devDependencies: {
11
+ ...packageJSON.devDependencies,
12
+ ...overlayPackageJSON.devDependencies,
13
+ },
14
+ scripts: {
15
+ ...packageJSON.scripts,
16
+ ...overlayPackageJSON.scripts,
17
+ },
18
+ };
19
+ }
20
+ export function createPackageJSON(options) {
21
+ let packageJSON = {
22
+ ...JSON.parse(JSON.stringify(options.framework.basePackageJSON)),
23
+ name: options.projectName,
24
+ };
25
+ const additions = [
26
+ options.typescript
27
+ ? options.framework.optionalPackages.typescript
28
+ : undefined,
29
+ options.tailwind
30
+ ? options.framework.optionalPackages.tailwindcss
31
+ : undefined,
32
+ options.mode === FILE_ROUTER
33
+ ? options.framework.optionalPackages['file-router']
34
+ : undefined,
35
+ ];
36
+ for (const addition of additions.filter(Boolean)) {
37
+ packageJSON = mergePackageJSON(packageJSON, addition);
38
+ }
39
+ for (const addOn of options.chosenAddOns.map((addOn) => addOn.packageAdditions)) {
40
+ packageJSON = mergePackageJSON(packageJSON, addOn);
41
+ }
42
+ packageJSON.dependencies = sortObject((packageJSON.dependencies ?? {}));
43
+ packageJSON.devDependencies = sortObject((packageJSON.devDependencies ?? {}));
44
+ return packageJSON;
45
+ }
@@ -14,17 +14,62 @@ export function getPackageManager() {
14
14
  const packageManager = SUPPORTED_PACKAGE_MANAGERS.find((manager) => userAgent.startsWith(manager));
15
15
  return packageManager;
16
16
  }
17
- export function packageManagerExecute(environment, packagerManager, pkg, args, cwd) {
17
+ export function getPackageManagerScriptCommand(packagerManager, args = []) {
18
18
  switch (packagerManager) {
19
19
  case 'yarn':
20
- return environment.execute('yarn', ['dlx', pkg, ...args], cwd);
20
+ return { command: 'yarn', args: ['run', ...args] };
21
21
  case 'pnpm':
22
- return environment.execute('pnpx', [pkg, ...args], cwd);
22
+ return { command: 'pnpm', args: [...args] };
23
23
  case 'bun':
24
- return environment.execute('bunx', ['--bun', pkg, ...args], cwd);
24
+ return { command: 'bunx', args: ['--bun', 'run', ...args] };
25
25
  case 'deno':
26
- return environment.execute('deno', ['run', `npm:${pkg}`, ...args], cwd);
26
+ return { command: 'deno', args: ['task', ...args] };
27
27
  default:
28
- return environment.execute('npx', [pkg, ...args], cwd);
28
+ return { command: 'npm', args: ['run', ...args] };
29
29
  }
30
30
  }
31
+ export function getPackageManagerExecuteCommand(packagerManager, pkg, args = []) {
32
+ switch (packagerManager) {
33
+ case 'yarn':
34
+ return { command: 'yarn', args: ['dlx', pkg, ...args] };
35
+ case 'pnpm':
36
+ return { command: 'pnpx', args: [pkg, ...args] };
37
+ case 'bun':
38
+ return { command: 'bunx', args: ['--bun', pkg, ...args] };
39
+ case 'deno':
40
+ return { command: 'deno', args: ['run', `npm:${pkg}`, ...args] };
41
+ default:
42
+ return { command: 'npx', args: [pkg, ...args] };
43
+ }
44
+ }
45
+ export function getPackageManagerInstallCommand(packagerManager, pkg, isDev = false) {
46
+ if (pkg) {
47
+ switch (packagerManager) {
48
+ case 'yarn':
49
+ case 'pnpm':
50
+ return {
51
+ command: packagerManager,
52
+ args: ['add', pkg, isDev ? '--dev' : ''],
53
+ };
54
+ default:
55
+ return {
56
+ command: packagerManager,
57
+ args: ['install', pkg, isDev ? '-D' : ''],
58
+ };
59
+ }
60
+ }
61
+ else {
62
+ return {
63
+ command: packagerManager,
64
+ args: ['install'],
65
+ };
66
+ }
67
+ }
68
+ export function packageManagerInstall(environment, cwd, packagerManager, pkg) {
69
+ const { command, args: commandArgs } = getPackageManagerInstallCommand(packagerManager, pkg);
70
+ return environment.execute(command, commandArgs, cwd);
71
+ }
72
+ export function packageManagerExecute(environment, cwd, packagerManager, pkg, args) {
73
+ const { command, args: commandArgs } = getPackageManagerExecuteCommand(packagerManager, pkg, args);
74
+ return environment.execute(command, commandArgs, cwd);
75
+ }
@@ -0,0 +1,122 @@
1
+ import { resolve } from 'node:path';
2
+ import { render } from 'ejs';
3
+ import { format } from 'prettier';
4
+ import { CODE_ROUTER, FILE_ROUTER } from './constants.js';
5
+ import { formatCommand } from './utils.js';
6
+ import { getPackageManagerInstallCommand, getPackageManagerScriptCommand, } from './package-manager.js';
7
+ import { relativePath } from './file-helpers.js';
8
+ function convertDotFilesAndPaths(path) {
9
+ return path
10
+ .split('/')
11
+ .map((segment) => segment.replace(/^_dot_/, '.'))
12
+ .join('/');
13
+ }
14
+ export function createTemplateFile(environment, options, targetDir) {
15
+ function getPackageManagerAddScript(packageName, isDev = false) {
16
+ return formatCommand(getPackageManagerInstallCommand(options.packageManager, packageName, isDev));
17
+ }
18
+ function getPackageManagerRunScript(scriptName, args = []) {
19
+ return formatCommand(getPackageManagerScriptCommand(options.packageManager, [
20
+ scriptName,
21
+ ...args,
22
+ ]));
23
+ }
24
+ class IgnoreFileError extends Error {
25
+ constructor() {
26
+ super('ignoreFile');
27
+ this.name = 'IgnoreFileError';
28
+ }
29
+ }
30
+ const integrations = [];
31
+ for (const addOn of options.chosenAddOns) {
32
+ if (addOn.integrations) {
33
+ for (const integration of addOn.integrations) {
34
+ integrations.push(integration);
35
+ }
36
+ }
37
+ }
38
+ const routes = [];
39
+ for (const addOn of options.chosenAddOns) {
40
+ if (addOn.routes) {
41
+ routes.push(...addOn.routes);
42
+ }
43
+ }
44
+ const variables = {
45
+ ...options.variableValues,
46
+ ...options.chosenAddOns.reduce((acc, addOn) => {
47
+ return {
48
+ ...acc,
49
+ ...addOn.variables,
50
+ };
51
+ }, {}),
52
+ };
53
+ const addOnEnabled = options.chosenAddOns.reduce((acc, addOn) => {
54
+ acc[addOn.id] = true;
55
+ return acc;
56
+ }, {});
57
+ return async function templateFile(file, content) {
58
+ const templateValues = {
59
+ packageManager: options.packageManager,
60
+ projectName: options.projectName,
61
+ typescript: options.typescript,
62
+ tailwind: options.tailwind,
63
+ js: options.typescript ? 'ts' : 'js',
64
+ jsx: options.typescript ? 'tsx' : 'jsx',
65
+ fileRouter: options.mode === FILE_ROUTER,
66
+ codeRouter: options.mode === CODE_ROUTER,
67
+ addOnEnabled,
68
+ addOns: options.chosenAddOns,
69
+ integrations,
70
+ routes,
71
+ variables,
72
+ getPackageManagerAddScript,
73
+ getPackageManagerRunScript,
74
+ relativePath: (path) => relativePath(file, path),
75
+ ignoreFile: () => {
76
+ throw new IgnoreFileError();
77
+ },
78
+ };
79
+ let ignoreFile = false;
80
+ if (file.endsWith('.ejs')) {
81
+ try {
82
+ content = render(content, templateValues);
83
+ }
84
+ catch (error) {
85
+ if (error instanceof IgnoreFileError) {
86
+ ignoreFile = true;
87
+ }
88
+ else {
89
+ console.error(file, error);
90
+ environment.error(`EJS error in file ${file}`, error?.toString());
91
+ process.exit(1);
92
+ }
93
+ }
94
+ }
95
+ if (ignoreFile) {
96
+ return;
97
+ }
98
+ let target = convertDotFilesAndPaths(file.replace('.ejs', ''));
99
+ let append = false;
100
+ if (target.endsWith('.append')) {
101
+ append = true;
102
+ target = target.replace('.append', '');
103
+ }
104
+ if (target.endsWith('.ts') || target.endsWith('.tsx')) {
105
+ content = await format(content, {
106
+ semi: false,
107
+ singleQuote: true,
108
+ trailingComma: 'all',
109
+ parser: 'typescript',
110
+ });
111
+ }
112
+ if (!options.typescript) {
113
+ target = target.replace(/\.tsx$/, '.jsx').replace(/\.ts$/, '.js');
114
+ }
115
+ if (append) {
116
+ await environment.appendFile(resolve(targetDir, target), content);
117
+ }
118
+ else {
119
+ await environment.writeFile(resolve(targetDir, target), content);
120
+ }
121
+ };
122
+ }
@@ -1,8 +1,4 @@
1
- import type { AddOn, CliOptions, Framework, TemplateOptions } from './types.js';
2
- export declare function getAllAddOns(framework: Framework, template: string): Promise<Array<AddOn>>;
1
+ import type { AddOn, Framework } from './types.js';
2
+ export declare function getAllAddOns(framework: Framework, template: string): Array<AddOn>;
3
3
  export declare function finalizeAddOns(framework: Framework, template: string, chosenAddOnIDs: Array<string>): Promise<Array<AddOn>>;
4
- export declare function listAddOns(options: CliOptions, { forcedMode, forcedAddOns, }: {
5
- forcedMode?: TemplateOptions;
6
- forcedAddOns?: Array<string>;
7
- }): Promise<void>;
8
4
  export declare function loadRemoteAddOn(url: string): Promise<AddOn>;
@@ -0,0 +1,4 @@
1
+ import type { Environment } from './types.js';
2
+ export declare function addToApp(addOns: Array<string>, { silent, }: {
3
+ silent?: boolean;
4
+ } | undefined, environment: Environment): Promise<void>;
@@ -1,5 +1,6 @@
1
- import type { Environment, Options } from './types';
2
- export type PersistedOptions = Exclude<Partial<Options>, 'addOns' | 'chosenAddOns'> & {
1
+ import type { Environment, Options } from './types.js';
2
+ export type PersistedOptions = Omit<Partial<Options>, 'addOns' | 'chosenAddOns' | 'framework'> & {
3
+ framework: string;
3
4
  version: number;
4
5
  existingAddOns: Array<string>;
5
6
  };
@@ -1,6 +1,3 @@
1
- import type { Framework } from './types.js';
2
1
  export declare const CODE_ROUTER = "code-router";
3
2
  export declare const FILE_ROUTER = "file-router";
4
- export declare const SUPPORTED_FRAMEWORKS: Array<Framework>;
5
- export declare const DEFAULT_FRAMEWORK: Framework;
6
3
  export declare const CONFIG_FILE = ".cta.json";
@@ -0,0 +1,5 @@
1
+ export declare function readFileHelper(path: string): string;
2
+ export declare function getBinaryFile(content: string): string | null;
3
+ export declare function relativePath(from: string, to: string): string;
4
+ export declare function isDirectory(path: string): boolean;
5
+ export declare function findFilesRecursively(path: string, files: Record<string, string>): void;
@@ -0,0 +1,5 @@
1
+ import type { Framework, FrameworkDefinition } from './types.js';
2
+ export declare function registerFramework(framework: FrameworkDefinition): void;
3
+ export declare function getFrameworkById(id: string): Framework | undefined;
4
+ export declare function getFrameworkByName(name: string): Framework | undefined;
5
+ export declare function getFrameworks(): Framework[];
@@ -1 +1,13 @@
1
- export { cli } from './cli.js';
1
+ export { createApp } from './create-app.js';
2
+ export { addToApp } from './add-to-app.js';
3
+ export { finalizeAddOns, getAllAddOns, loadRemoteAddOn } from './add-ons.js';
4
+ export { createMemoryEnvironment, createDefaultEnvironment, } from './environment.js';
5
+ export { CODE_ROUTER, CONFIG_FILE, FILE_ROUTER } from './constants.js';
6
+ export { DEFAULT_PACKAGE_MANAGER, SUPPORTED_PACKAGE_MANAGERS, getPackageManager, getPackageManagerInstallCommand, getPackageManagerExecuteCommand, getPackageManagerScriptCommand, packageManagerInstall, packageManagerExecute, } from './package-manager.js';
7
+ export { registerFramework, getFrameworkById, getFrameworkByName, getFrameworks, } from './frameworks.js';
8
+ export { formatCommand, jsSafeName, sortObject } from './utils.js';
9
+ export { writeConfigFile, readConfigFile } from './config-file.js';
10
+ export { readFileHelper, getBinaryFile, relativePath } from './file-helpers.js';
11
+ export type { AddOn, Environment, FileBundleHandler, FrameworkDefinition, Mode, Options, Starter, TemplateOptions, Variable, } from './types.js';
12
+ export type { PersistedOptions } from './config-file.js';
13
+ export type { PackageManager } from './package-manager.js';
@@ -0,0 +1,2 @@
1
+ import type { Environment } from '../types.js';
2
+ export declare function setupGit(environment: Environment, targetDir: string): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { Environment, Options } from '../types.js';
2
+ export declare function installShadcnComponents(environment: Environment, targetDir: string, options: Options, silent: boolean): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { Options } from './types.js';
2
+ export declare function createPackageJSON(options: Options): any;
@@ -3,4 +3,17 @@ export declare const SUPPORTED_PACKAGE_MANAGERS: readonly ["npm", "yarn", "pnpm"
3
3
  export type PackageManager = (typeof SUPPORTED_PACKAGE_MANAGERS)[number];
4
4
  export declare const DEFAULT_PACKAGE_MANAGER: PackageManager;
5
5
  export declare function getPackageManager(): PackageManager | undefined;
6
- export declare function packageManagerExecute(environment: Environment, packagerManager: PackageManager, pkg: string, args: Array<string>, cwd: string): Promise<void>;
6
+ export declare function getPackageManagerScriptCommand(packagerManager: PackageManager, args?: Array<string>): {
7
+ command: string;
8
+ args: string[];
9
+ };
10
+ export declare function getPackageManagerExecuteCommand(packagerManager: PackageManager, pkg: string, args?: Array<string>): {
11
+ command: string;
12
+ args: string[];
13
+ };
14
+ export declare function getPackageManagerInstallCommand(packagerManager: PackageManager, pkg?: string, isDev?: boolean): {
15
+ command: "npm" | "yarn" | "pnpm" | "bun" | "deno";
16
+ args: string[];
17
+ };
18
+ export declare function packageManagerInstall(environment: Environment, cwd: string, packagerManager: PackageManager, pkg?: string): Promise<void>;
19
+ export declare function packageManagerExecute(environment: Environment, cwd: string, packagerManager: PackageManager, pkg: string, args: Array<string>): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { Environment, Options } from './types.js';
2
+ export declare function createTemplateFile(environment: Environment, options: Options, targetDir: string): (file: string, content: string) => Promise<void>;