@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,9 @@
1
+ import { initTRPC } from "@trpc/server";
2
+ import superjson from "superjson";
3
+
4
+ const t = initTRPC.create({
5
+ transformer: superjson,
6
+ });
7
+
8
+ export const createTRPCRouter = t.router;
9
+ export const publicProcedure = t.procedure;
@@ -0,0 +1,4 @@
1
+ import { createTRPCContext } from "@trpc/tanstack-react-query";
2
+ import type { TRPCRouter } from "@/integrations/trpc/router";
3
+
4
+ export const { TRPCProvider, useTRPC } = createTRPCContext<TRPCRouter>();
@@ -0,0 +1,18 @@
1
+ import { TRPCError } from '@trpc/server'
2
+ import type { TRPCRouterRecord } from '@trpc/server'
3
+ // import { z } from 'zod'
4
+
5
+ import { createTRPCRouter, publicProcedure } from './init'
6
+
7
+ const peopleRouter = {
8
+ list: publicProcedure.query(async () =>
9
+ fetch('https://swapi.dev/api/people')
10
+ .then((res) => res.json())
11
+ .then((d) => d.results as { name: string }[]),
12
+ ),
13
+ } satisfies TRPCRouterRecord
14
+
15
+ export const trpcRouter = createTRPCRouter({
16
+ people: peopleRouter,
17
+ })
18
+ export type TRPCRouter = typeof trpcRouter
@@ -0,0 +1,16 @@
1
+ import { createAPIFileRoute } from '@tanstack/react-start/api'
2
+ import { fetchRequestHandler } from '@trpc/server/adapters/fetch'
3
+ import { trpcRouter } from '@/integrations/trpc/router'
4
+
5
+ function handler({ request }: { request: Request }) {
6
+ return fetchRequestHandler({
7
+ req: request,
8
+ router: trpcRouter,
9
+ endpoint: '/api/trpc',
10
+ })
11
+ }
12
+
13
+ export const APIRoute = createAPIFileRoute('/api/trpc/$')({
14
+ GET: handler,
15
+ POST: handler,
16
+ })
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "tRPC",
3
+ "description": "Integrate tRPC into your application.",
4
+ "phase": "add-on",
5
+ "templates": ["file-router"],
6
+ "link": "https://trpc.io/",
7
+ "routes": [],
8
+ "dependsOn": ["tanstack-query", "start"]
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "dependencies": {
3
+ "@trpc/client": "^11.0.0",
4
+ "@trpc/server": "^11.0.0",
5
+ "@trpc/tanstack-react-query": "^11.0.0",
6
+ "superjson": "^2.2.2",
7
+ "zod": "^3.24.2"
8
+ }
9
+ }
@@ -0,0 +1,50 @@
1
+ import { faker } from '@faker-js/faker'
2
+
3
+ export type Person = {
4
+ id: number
5
+ firstName: string
6
+ lastName: string
7
+ age: number
8
+ visits: number
9
+ progress: number
10
+ status: 'relationship' | 'complicated' | 'single'
11
+ subRows?: Person[]
12
+ }
13
+
14
+ const range = (len: number) => {
15
+ const arr: number[] = []
16
+ for (let i = 0; i < len; i++) {
17
+ arr.push(i)
18
+ }
19
+ return arr
20
+ }
21
+
22
+ const newPerson = (num: number): Person => {
23
+ return {
24
+ id: num,
25
+ firstName: faker.person.firstName(),
26
+ lastName: faker.person.lastName(),
27
+ age: faker.number.int(40),
28
+ visits: faker.number.int(1000),
29
+ progress: faker.number.int(100),
30
+ status: faker.helpers.shuffle<Person['status']>([
31
+ 'relationship',
32
+ 'complicated',
33
+ 'single',
34
+ ])[0]!,
35
+ }
36
+ }
37
+
38
+ export function makeData(...lens: number[]) {
39
+ const makeDataLevel = (depth = 0): Person[] => {
40
+ const len = lens[depth]!
41
+ return range(len).map((index): Person => {
42
+ return {
43
+ ...newPerson(index),
44
+ subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined,
45
+ }
46
+ })
47
+ }
48
+
49
+ return makeDataLevel()
50
+ }
@@ -0,0 +1,373 @@
1
+ import React from 'react'
2
+ import { <% if (fileRouter) { %>createFileRoute<% } else { %>createRoute<% } %> } from '@tanstack/react-router'
3
+ import {
4
+ flexRender,
5
+ getCoreRowModel,
6
+ getFilteredRowModel,
7
+ getPaginationRowModel,
8
+ getSortedRowModel,
9
+ sortingFns,
10
+ useReactTable,
11
+ } from '@tanstack/react-table'
12
+ import { compareItems, rankItem } from '@tanstack/match-sorter-utils'
13
+
14
+ import { makeData } from '../data/demo-table-data'
15
+
16
+ import type {
17
+ Column,
18
+ ColumnDef,
19
+ ColumnFiltersState,
20
+ FilterFn,
21
+ SortingFn,
22
+ } from '@tanstack/react-table'
23
+ import type { RankingInfo } from '@tanstack/match-sorter-utils'
24
+ <% if (codeRouter) { %>
25
+ import type { RootRoute } from '@tanstack/react-router'
26
+ <% } %>
27
+ import type { Person } from '../data/demo-table-data'
28
+ <% if (fileRouter) { %>
29
+ export const Route = createFileRoute('/demo/table')({
30
+ component: TableDemo,
31
+ })
32
+ <% } %>
33
+
34
+ declare module '@tanstack/react-table' {
35
+ interface FilterFns {
36
+ fuzzy: FilterFn<unknown>
37
+ }
38
+ interface FilterMeta {
39
+ itemRank: RankingInfo
40
+ }
41
+ }
42
+
43
+ // Define a custom fuzzy filter function that will apply ranking info to rows (using match-sorter utils)
44
+ const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {
45
+ // Rank the item
46
+ const itemRank = rankItem(row.getValue(columnId), value)
47
+
48
+ // Store the itemRank info
49
+ addMeta({
50
+ itemRank,
51
+ })
52
+
53
+ // Return if the item should be filtered in/out
54
+ return itemRank.passed
55
+ }
56
+
57
+ // Define a custom fuzzy sort function that will sort by rank if the row has ranking information
58
+ const fuzzySort: SortingFn<any> = (rowA, rowB, columnId) => {
59
+ let dir = 0
60
+
61
+ // Only sort by rank if the column has ranking information
62
+ if (rowA.columnFiltersMeta[columnId]) {
63
+ dir = compareItems(
64
+ rowA.columnFiltersMeta[columnId]?.itemRank!,
65
+ rowB.columnFiltersMeta[columnId]?.itemRank!,
66
+ )
67
+ }
68
+
69
+ // Provide an alphanumeric fallback for when the item ranks are equal
70
+ return dir === 0 ? sortingFns.alphanumeric(rowA, rowB, columnId) : dir
71
+ }
72
+
73
+ function TableDemo() {
74
+ const rerender = React.useReducer(() => ({}), {})[1]
75
+
76
+ const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
77
+ [],
78
+ )
79
+ const [globalFilter, setGlobalFilter] = React.useState('')
80
+
81
+ const columns = React.useMemo<ColumnDef<Person, any>[]>(
82
+ () => [
83
+ {
84
+ accessorKey: 'id',
85
+ filterFn: 'equalsString', //note: normal non-fuzzy filter column - exact match required
86
+ },
87
+ {
88
+ accessorKey: 'firstName',
89
+ cell: (info) => info.getValue(),
90
+ filterFn: 'includesStringSensitive', //note: normal non-fuzzy filter column - case sensitive
91
+ },
92
+ {
93
+ accessorFn: (row) => row.lastName,
94
+ id: 'lastName',
95
+ cell: (info) => info.getValue(),
96
+ header: () => <span>Last Name</span>,
97
+ filterFn: 'includesString', //note: normal non-fuzzy filter column - case insensitive
98
+ },
99
+ {
100
+ accessorFn: (row) => `${row.firstName} ${row.lastName}`,
101
+ id: 'fullName',
102
+ header: 'Full Name',
103
+ cell: (info) => info.getValue(),
104
+ filterFn: 'fuzzy', //using our custom fuzzy filter function
105
+ // filterFn: fuzzyFilter, //or just define with the function
106
+ sortingFn: fuzzySort, //sort by fuzzy rank (falls back to alphanumeric)
107
+ },
108
+ ],
109
+ [],
110
+ )
111
+
112
+ const [data, setData] = React.useState<Person[]>(() => makeData(5_000))
113
+ const refreshData = () => setData((_old) => makeData(50_000)) //stress test
114
+
115
+ const table = useReactTable({
116
+ data,
117
+ columns,
118
+ filterFns: {
119
+ fuzzy: fuzzyFilter, //define as a filter function that can be used in column definitions
120
+ },
121
+ state: {
122
+ columnFilters,
123
+ globalFilter,
124
+ },
125
+ onColumnFiltersChange: setColumnFilters,
126
+ onGlobalFilterChange: setGlobalFilter,
127
+ globalFilterFn: 'fuzzy', //apply fuzzy filter to the global filter (most common use case for fuzzy filter)
128
+ getCoreRowModel: getCoreRowModel(),
129
+ getFilteredRowModel: getFilteredRowModel(), //client side filtering
130
+ getSortedRowModel: getSortedRowModel(),
131
+ getPaginationRowModel: getPaginationRowModel(),
132
+ debugTable: true,
133
+ debugHeaders: true,
134
+ debugColumns: false,
135
+ })
136
+
137
+ //apply the fuzzy sort if the fullName column is being filtered
138
+ React.useEffect(() => {
139
+ if (table.getState().columnFilters[0]?.id === 'fullName') {
140
+ if (table.getState().sorting[0]?.id !== 'fullName') {
141
+ table.setSorting([{ id: 'fullName', desc: false }])
142
+ }
143
+ }
144
+ }, [table.getState().columnFilters[0]?.id])
145
+
146
+ return (
147
+ <div className="min-h-screen bg-gray-900 p-6">
148
+ <div>
149
+ <DebouncedInput
150
+ value={globalFilter ?? ''}
151
+ onChange={(value) => setGlobalFilter(String(value))}
152
+ className="w-full p-3 bg-gray-800 text-white rounded-lg border border-gray-700 focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none"
153
+ placeholder="Search all columns..."
154
+ />
155
+ </div>
156
+ <div className="h-4" />
157
+ <div className="overflow-x-auto rounded-lg border border-gray-700">
158
+ <table className="w-full text-sm text-gray-200">
159
+ <thead className="bg-gray-800 text-gray-100">
160
+ {table.getHeaderGroups().map((headerGroup) => (
161
+ <tr key={headerGroup.id}>
162
+ {headerGroup.headers.map((header) => {
163
+ return (
164
+ <th
165
+ key={header.id}
166
+ colSpan={header.colSpan}
167
+ className="px-4 py-3 text-left"
168
+ >
169
+ {header.isPlaceholder ? null : (
170
+ <>
171
+ <div
172
+ {...{
173
+ className: header.column.getCanSort()
174
+ ? 'cursor-pointer select-none hover:text-blue-400 transition-colors'
175
+ : '',
176
+ onClick: header.column.getToggleSortingHandler(),
177
+ }}
178
+ >
179
+ {flexRender(
180
+ header.column.columnDef.header,
181
+ header.getContext(),
182
+ )}
183
+ {{
184
+ asc: ' 🔼',
185
+ desc: ' 🔽',
186
+ }[header.column.getIsSorted() as string] ?? null}
187
+ </div>
188
+ {header.column.getCanFilter() ? (
189
+ <div className="mt-2">
190
+ <Filter column={header.column} />
191
+ </div>
192
+ ) : null}
193
+ </>
194
+ )}
195
+ </th>
196
+ )
197
+ })}
198
+ </tr>
199
+ ))}
200
+ </thead>
201
+ <tbody className="divide-y divide-gray-700">
202
+ {table.getRowModel().rows.map((row) => {
203
+ return (
204
+ <tr
205
+ key={row.id}
206
+ className="hover:bg-gray-800 transition-colors"
207
+ >
208
+ {row.getVisibleCells().map((cell) => {
209
+ return (
210
+ <td key={cell.id} className="px-4 py-3">
211
+ {flexRender(
212
+ cell.column.columnDef.cell,
213
+ cell.getContext(),
214
+ )}
215
+ </td>
216
+ )
217
+ })}
218
+ </tr>
219
+ )
220
+ })}
221
+ </tbody>
222
+ </table>
223
+ </div>
224
+ <div className="h-4" />
225
+ <div className="flex flex-wrap items-center gap-2 text-gray-200">
226
+ <button
227
+ className="px-3 py-1 bg-gray-800 rounded-md hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
228
+ onClick={() => table.setPageIndex(0)}
229
+ disabled={!table.getCanPreviousPage()}
230
+ >
231
+ {'<<'}
232
+ </button>
233
+ <button
234
+ className="px-3 py-1 bg-gray-800 rounded-md hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
235
+ onClick={() => table.previousPage()}
236
+ disabled={!table.getCanPreviousPage()}
237
+ >
238
+ {'<'}
239
+ </button>
240
+ <button
241
+ className="px-3 py-1 bg-gray-800 rounded-md hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
242
+ onClick={() => table.nextPage()}
243
+ disabled={!table.getCanNextPage()}
244
+ >
245
+ {'>'}
246
+ </button>
247
+ <button
248
+ className="px-3 py-1 bg-gray-800 rounded-md hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
249
+ onClick={() => table.setPageIndex(table.getPageCount() - 1)}
250
+ disabled={!table.getCanNextPage()}
251
+ >
252
+ {'>>'}
253
+ </button>
254
+ <span className="flex items-center gap-1">
255
+ <div>Page</div>
256
+ <strong>
257
+ {table.getState().pagination.pageIndex + 1} of{' '}
258
+ {table.getPageCount()}
259
+ </strong>
260
+ </span>
261
+ <span className="flex items-center gap-1">
262
+ | Go to page:
263
+ <input
264
+ type="number"
265
+ defaultValue={table.getState().pagination.pageIndex + 1}
266
+ onChange={(e) => {
267
+ const page = e.target.value ? Number(e.target.value) - 1 : 0
268
+ table.setPageIndex(page)
269
+ }}
270
+ className="w-16 px-2 py-1 bg-gray-800 rounded-md border border-gray-700 focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none"
271
+ />
272
+ </span>
273
+ <select
274
+ value={table.getState().pagination.pageSize}
275
+ onChange={(e) => {
276
+ table.setPageSize(Number(e.target.value))
277
+ }}
278
+ className="px-2 py-1 bg-gray-800 rounded-md border border-gray-700 focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none"
279
+ >
280
+ {[10, 20, 30, 40, 50].map((pageSize) => (
281
+ <option key={pageSize} value={pageSize}>
282
+ Show {pageSize}
283
+ </option>
284
+ ))}
285
+ </select>
286
+ </div>
287
+ <div className="mt-4 text-gray-400">
288
+ {table.getPrePaginationRowModel().rows.length} Rows
289
+ </div>
290
+ <div className="mt-4 flex gap-2">
291
+ <button
292
+ onClick={() => rerender()}
293
+ className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
294
+ >
295
+ Force Rerender
296
+ </button>
297
+ <button
298
+ onClick={() => refreshData()}
299
+ className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
300
+ >
301
+ Refresh Data
302
+ </button>
303
+ </div>
304
+ <pre className="mt-4 p-4 bg-gray-800 rounded-lg text-gray-300 overflow-auto">
305
+ {JSON.stringify(
306
+ {
307
+ columnFilters: table.getState().columnFilters,
308
+ globalFilter: table.getState().globalFilter,
309
+ },
310
+ null,
311
+ 2,
312
+ )}
313
+ </pre>
314
+ </div>
315
+ )
316
+ }
317
+
318
+ function Filter({ column }: { column: Column<any, unknown> }) {
319
+ const columnFilterValue = column.getFilterValue()
320
+
321
+ return (
322
+ <DebouncedInput
323
+ type="text"
324
+ value={(columnFilterValue ?? '') as string}
325
+ onChange={(value) => column.setFilterValue(value)}
326
+ placeholder={`Search...`}
327
+ className="w-full px-2 py-1 bg-gray-700 text-white rounded-md border border-gray-600 focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none"
328
+ />
329
+ )
330
+ }
331
+
332
+ // A typical debounced input react component
333
+ function DebouncedInput({
334
+ value: initialValue,
335
+ onChange,
336
+ debounce = 500,
337
+ ...props
338
+ }: {
339
+ value: string | number
340
+ onChange: (value: string | number) => void
341
+ debounce?: number
342
+ } & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'>) {
343
+ const [value, setValue] = React.useState(initialValue)
344
+
345
+ React.useEffect(() => {
346
+ setValue(initialValue)
347
+ }, [initialValue])
348
+
349
+ React.useEffect(() => {
350
+ const timeout = setTimeout(() => {
351
+ onChange(value)
352
+ }, debounce)
353
+
354
+ return () => clearTimeout(timeout)
355
+ }, [value])
356
+
357
+ return (
358
+ <input
359
+ {...props}
360
+ value={value}
361
+ onChange={(e) => setValue(e.target.value)}
362
+ />
363
+ )
364
+ }
365
+
366
+ <% if (codeRouter) { %>
367
+ export default (parentRoute: RootRoute) => createRoute({
368
+ path: '/demo/table',
369
+ component: TableDemo,
370
+ getParentRoute: () => parentRoute,
371
+ })
372
+ <% } %>
373
+
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "Table",
3
+ "description": "Integrate TanStack Table into your application.",
4
+ "phase": "add-on",
5
+ "templates": ["file-router", "code-router"],
6
+ "link": "https://tanstack.com/table/latest",
7
+ "routes": [
8
+ {
9
+ "url": "/demo/table",
10
+ "name": "TanStack Table"
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "dependencies": {
3
+ "@faker-js/faker": "^9.6.0",
4
+ "@tanstack/match-sorter-utils": "^8.19.4",
5
+ "@tanstack/react-table": "^8.21.2"
6
+ }
7
+ }
@@ -0,0 +1,5 @@
1
+ import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
2
+
3
+ export default function LayoutAddition() {
4
+ return <ReactQueryDevtools buttonPosition="bottom-right" />
5
+ }
@@ -0,0 +1,70 @@
1
+ <% if (addOnEnabled.tRPC) { %>
2
+ import { QueryClient } from "@tanstack/react-query";
3
+ import superjson from "superjson";
4
+ import { createTRPCClient, httpBatchStreamLink } from "@trpc/client";
5
+ import { createTRPCOptionsProxy } from "@trpc/tanstack-react-query";
6
+
7
+ import { TRPCProvider } from "@/integrations/trpc/react";
8
+
9
+ import type { TRPCRouter } from "@/integrations/trpc/router";
10
+
11
+ function getUrl() {
12
+ const base = (() => {
13
+ if (typeof window !== "undefined") return "";
14
+ return `http://localhost:${process.env.PORT ?? 3000}`;
15
+ })();
16
+ return `${base}/api/trpc`;
17
+ }
18
+
19
+ export const trpcClient = createTRPCClient<TRPCRouter>({
20
+ links: [
21
+ httpBatchStreamLink({
22
+ transformer: superjson,
23
+ url: getUrl(),
24
+ }),
25
+ ],
26
+ });
27
+
28
+ const queryClient = new QueryClient({
29
+ defaultOptions: {
30
+ dehydrate: { serializeData: superjson.serialize },
31
+ hydrate: { deserializeData: superjson.deserialize },
32
+ },
33
+ });
34
+
35
+ const serverHelpers = createTRPCOptionsProxy({
36
+ client: trpcClient,
37
+ queryClient: queryClient,
38
+ });
39
+
40
+ export function getContext() {
41
+ return {
42
+ queryClient,
43
+ trpc: serverHelpers,
44
+ };
45
+ }
46
+
47
+ export function Provider({ children }: { children: React.ReactNode }) {
48
+ return (
49
+ <TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>
50
+ {children}
51
+ </TRPCProvider>
52
+ );
53
+ }
54
+ <% } else { %>
55
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
56
+
57
+ const queryClient = new QueryClient()
58
+
59
+ export function getContext() {
60
+ return {
61
+ queryClient,
62
+ }
63
+ }
64
+
65
+ export function Provider({ children }: { children: React.ReactNode }) {
66
+ return (
67
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
68
+ )
69
+ }
70
+ <% } %>
@@ -0,0 +1,53 @@
1
+ import { <% if (fileRouter) { %>createFileRoute<% } else { %>createRoute<% } %> } from '@tanstack/react-router'
2
+ import { useQuery } from '@tanstack/react-query'
3
+ <% if (addOnEnabled.tRPC) { %>
4
+ import { useTRPC } from "@/integrations/trpc/react";
5
+ <% } %>
6
+ <% if (codeRouter) { %>
7
+ import type { RootRoute } from '@tanstack/react-router'
8
+ <% } else { %>
9
+ export const Route = createFileRoute('/demo/tanstack-query')({
10
+ <% if (addOnEnabled.tRPC) { %>
11
+ loader: async ({ context }) => {
12
+ await context.queryClient.prefetchQuery(
13
+ context.trpc.people.list.queryOptions()
14
+ );
15
+ },
16
+ <% } %>
17
+ component: TanStackQueryDemo,
18
+ })
19
+ <% } %>
20
+ function TanStackQueryDemo() {
21
+ <% if (addOnEnabled.tRPC) { %>
22
+ const trpc = useTRPC();
23
+ const { data } = useQuery(trpc.people.list.queryOptions());
24
+ <% } else { %>
25
+ const { data } = useQuery({
26
+ queryKey: ['people'],
27
+ queryFn: () => Promise.resolve([
28
+ { name: 'John Doe' },
29
+ { name: 'Jane Doe' },
30
+ ]),
31
+ initialData: [],
32
+ })
33
+ <% } %>
34
+
35
+ return (
36
+ <div className="p-4">
37
+ <h1 className="text-2xl mb-4">People list from Swapi</h1>
38
+ <ul>
39
+ {data.map((person) => (
40
+ <li key={person.name}>{person.name}</li>
41
+ ))}
42
+ </ul>
43
+ </div>
44
+ )
45
+ }
46
+
47
+ <% if (codeRouter) { %>
48
+ export default (parentRoute: RootRoute) => createRoute({
49
+ path: '/demo/tanstack-query',
50
+ component: TanStackQueryDemo,
51
+ getParentRoute: () => parentRoute,
52
+ })
53
+ <% } %>
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "TanStack Query",
3
+ "description": "Integrate TanStack Query into your application.",
4
+ "phase": "add-on",
5
+ "templates": ["file-router", "code-router"],
6
+ "link": "https://tanstack.com/query/latest",
7
+ "routes": [
8
+ {
9
+ "url": "/demo/tanstack-query",
10
+ "name": "TanStack Query"
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "dependencies": {
3
+ "@tanstack/react-query": "^5.66.5",
4
+ "@tanstack/react-query-devtools": "^5.66.5"
5
+ }
6
+ }