@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.
- package/dist/add-ons.js +91 -5
- package/dist/add.js +125 -0
- package/dist/cli.js +132 -0
- package/dist/config-file.js +9 -14
- package/dist/constants.js +2 -0
- package/dist/create-app.js +451 -142
- package/dist/custom-add-on.js +254 -0
- package/dist/environment.js +32 -64
- package/dist/file-helper.js +18 -0
- package/dist/index.js +1 -17
- package/dist/mcp.js +229 -0
- package/dist/options.js +333 -9
- package/dist/package-manager.js +6 -51
- package/dist/templates.js +6 -0
- package/dist/toolchain.js +6 -0
- package/dist/types/add-ons.d.ts +8 -3
- package/dist/types/add.d.ts +3 -0
- package/dist/types/cli.d.ts +7 -0
- package/dist/types/config-file.d.ts +4 -6
- package/dist/types/constants.d.ts +3 -0
- package/dist/types/create-app.d.ts +7 -1
- package/dist/types/custom-add-on.d.ts +3 -0
- package/dist/types/environment.d.ts +1 -2
- package/dist/types/file-helper.d.ts +2 -0
- package/dist/types/index.d.ts +1 -20
- package/dist/types/mcp.d.ts +7 -0
- package/dist/types/options.d.ts +6 -2
- package/dist/types/package-manager.d.ts +1 -18
- package/dist/types/templates.d.ts +1 -0
- package/dist/types/toolchain.d.ts +3 -0
- package/dist/types/types.d.ts +85 -788
- package/dist/types/utils.d.ts +0 -5
- package/dist/types.js +1 -65
- package/dist/utils.js +0 -9
- package/package.json +12 -9
- package/src/add-ons.ts +123 -7
- package/src/add.ts +186 -0
- package/src/cli.ts +210 -0
- package/src/config-file.ts +17 -26
- package/src/constants.ts +5 -0
- package/src/create-app.ts +730 -180
- package/src/custom-add-on.ts +325 -0
- package/src/environment.ts +33 -77
- package/src/file-helper.ts +20 -0
- package/src/index.ts +1 -77
- package/src/mcp.ts +302 -0
- package/src/options.ts +409 -8
- package/src/package-manager.ts +9 -80
- package/src/templates.ts +7 -0
- package/src/toolchain.ts +7 -0
- package/src/types.ts +87 -175
- package/src/utils.ts +0 -17
- package/templates/react/add-on/clerk/README.md +3 -0
- package/templates/react/add-on/clerk/assets/_dot_env.local.append +2 -0
- package/templates/react/add-on/clerk/assets/src/integrations/clerk/header-user.tsx +19 -0
- package/templates/react/add-on/clerk/assets/src/integrations/clerk/provider.tsx +18 -0
- package/templates/react/add-on/clerk/assets/src/routes/demo.clerk.tsx +20 -0
- package/templates/react/add-on/clerk/info.json +13 -0
- package/templates/react/add-on/clerk/package.json +5 -0
- package/templates/react/add-on/convex/README.md +4 -0
- package/templates/react/add-on/convex/assets/_dot_cursorrules.append +93 -0
- package/templates/react/add-on/convex/assets/_dot_env.local.append +3 -0
- package/templates/react/add-on/convex/assets/convex/products.ts +8 -0
- package/templates/react/add-on/convex/assets/convex/schema.ts +10 -0
- package/templates/react/add-on/convex/assets/src/integrations/convex/provider.tsx +20 -0
- package/templates/react/add-on/convex/assets/src/routes/demo.convex.tsx +33 -0
- package/templates/react/add-on/convex/info.json +13 -0
- package/templates/react/add-on/convex/package.json +6 -0
- package/templates/react/add-on/form/assets/src/components/demo.FormComponents.tsx.ejs +300 -0
- package/templates/react/add-on/form/assets/src/hooks/demo.form-context.ts +4 -0
- package/templates/react/add-on/form/assets/src/hooks/demo.form.ts +22 -0
- package/templates/react/add-on/form/assets/src/routes/demo.form.address.tsx.ejs +213 -0
- package/templates/react/add-on/form/assets/src/routes/demo.form.simple.tsx.ejs +77 -0
- package/templates/react/add-on/form/info.json +26 -0
- package/templates/react/add-on/form/package.json +6 -0
- package/templates/react/add-on/module-federation/assets/module-federation.config.js.ejs +31 -0
- package/templates/react/add-on/module-federation/assets/src/demo-mf-component.tsx +3 -0
- package/templates/react/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +11 -0
- package/templates/react/add-on/module-federation/info.json +7 -0
- package/templates/react/add-on/module-federation/package.json +5 -0
- package/templates/react/add-on/netlify/README.md +11 -0
- package/templates/react/add-on/netlify/info.json +7 -0
- package/templates/react/add-on/sentry/assets/_dot_cursorrules.append +22 -0
- package/templates/react/add-on/sentry/assets/_dot_env.local.append +11 -0
- package/templates/react/add-on/sentry/assets/src/app/global-middleware.ts +11 -0
- package/templates/react/add-on/sentry/assets/src/routes/demo.sentry.testing.tsx +489 -0
- package/templates/react/add-on/sentry/info.json +14 -0
- package/templates/react/add-on/sentry/package.json +5 -0
- package/templates/react/add-on/shadcn/README.md +7 -0
- package/templates/react/add-on/shadcn/assets/_dot_cursorrules.append +7 -0
- package/templates/react/add-on/shadcn/assets/components.json +21 -0
- package/templates/react/add-on/shadcn/assets/src/lib/utils.ts +6 -0
- package/templates/react/add-on/shadcn/assets/src/styles.css +138 -0
- package/templates/react/add-on/shadcn/info.json +7 -0
- package/templates/react/add-on/shadcn/package.json +9 -0
- package/templates/react/add-on/start/assets/_dot_gitignore.append +2 -0
- package/templates/react/add-on/start/assets/app.config.ts.ejs +32 -0
- package/templates/react/add-on/start/assets/src/api.ts +6 -0
- package/templates/react/add-on/start/assets/src/client.tsx.ejs +33 -0
- package/templates/react/add-on/start/assets/src/router.tsx.ejs +48 -0
- package/templates/react/add-on/start/assets/src/routes/api.demo-names.ts +11 -0
- package/templates/react/add-on/start/assets/src/routes/demo.start.api-request.tsx.ejs +33 -0
- package/templates/react/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +50 -0
- package/templates/react/add-on/start/assets/src/ssr.tsx.ejs +30 -0
- package/templates/react/add-on/start/info.json +18 -0
- package/templates/react/add-on/start/package.json +13 -0
- package/templates/react/add-on/store/assets/src/lib/demo-store.ts +13 -0
- package/templates/react/add-on/store/assets/src/routes/demo.store.tsx.ejs +75 -0
- package/templates/react/add-on/store/info.json +13 -0
- package/templates/react/add-on/store/package.json +6 -0
- package/templates/react/add-on/t3env/README.md +16 -0
- package/templates/react/add-on/t3env/assets/src/env.ts +39 -0
- package/templates/react/add-on/t3env/info.json +10 -0
- package/templates/react/add-on/t3env/package.json +6 -0
- package/templates/react/add-on/tRPC/assets/src/integrations/trpc/init.ts +9 -0
- package/templates/react/add-on/tRPC/assets/src/integrations/trpc/react.ts +4 -0
- package/templates/react/add-on/tRPC/assets/src/integrations/trpc/router.ts +18 -0
- package/templates/react/add-on/tRPC/assets/src/routes/api.trpc.$.tsx +16 -0
- package/templates/react/add-on/tRPC/info.json +9 -0
- package/templates/react/add-on/tRPC/package.json +9 -0
- package/templates/react/add-on/table/assets/src/data/demo-table-data.ts +50 -0
- package/templates/react/add-on/table/assets/src/routes/demo.table.tsx.ejs +373 -0
- package/templates/react/add-on/table/info.json +13 -0
- package/templates/react/add-on/table/package.json +7 -0
- package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/layout.tsx +5 -0
- package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/root-provider.tsx.ejs +70 -0
- package/templates/react/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx.ejs +53 -0
- package/templates/react/add-on/tanstack-query/info.json +13 -0
- package/templates/react/add-on/tanstack-query/package.json +6 -0
- package/templates/react/base/README.md.ejs +558 -0
- package/templates/react/base/_dot_gitignore +5 -0
- package/templates/react/base/_dot_vscode/settings.biome.json +35 -0
- package/templates/react/base/_dot_vscode/settings.json +11 -0
- package/templates/react/base/index.html.ejs +20 -0
- package/templates/react/base/package.biome.json +10 -0
- package/templates/react/base/package.eslintprettier.json +11 -0
- package/templates/react/base/package.json +30 -0
- package/templates/react/base/package.ts.json +7 -0
- package/templates/react/base/package.tw.json +6 -0
- package/templates/react/base/public/favicon.ico +0 -0
- package/templates/react/base/public/logo192.png +0 -0
- package/templates/react/base/public/logo512.png +0 -0
- package/templates/react/base/public/manifest.json +25 -0
- package/templates/react/base/public/robots.txt +3 -0
- package/templates/react/base/src/App.css +38 -0
- package/templates/react/base/src/App.test.tsx.ejs +10 -0
- package/templates/react/base/src/App.tsx.ejs +74 -0
- package/templates/react/base/src/components/Header.tsx.ejs +27 -0
- package/templates/react/base/src/logo.svg +44 -0
- package/templates/react/base/src/reportWebVitals.ts.ejs +28 -0
- package/templates/react/base/src/styles.css.ejs +15 -0
- package/templates/react/base/toolchain/.prettierignore +3 -0
- package/templates/react/base/toolchain/biome.json +31 -0
- package/templates/react/base/toolchain/eslint.config.js +5 -0
- package/templates/react/base/toolchain/prettier.config.js +10 -0
- package/templates/react/base/tsconfig.json.ejs +29 -0
- package/templates/react/base/vite.config.js.ejs +23 -0
- package/templates/react/code-router/src/main.tsx.ejs +92 -0
- package/templates/react/example/tanchat/README.md +37 -0
- package/templates/react/example/tanchat/assets/_dot_env.local.append +2 -0
- package/templates/react/example/tanchat/assets/public/example-guitar-flowers.jpg +0 -0
- package/templates/react/example/tanchat/assets/public/example-guitar-motherboard.jpg +0 -0
- package/templates/react/example/tanchat/assets/public/example-guitar-racing.jpg +0 -0
- package/templates/react/example/tanchat/assets/public/example-guitar-steamer-trunk.jpg +0 -0
- package/templates/react/example/tanchat/assets/public/example-guitar-superhero.jpg +0 -0
- package/templates/react/example/tanchat/assets/public/example-guitar-traveling.jpg +0 -0
- package/templates/react/example/tanchat/assets/public/example-guitar-video-games.jpg +0 -0
- package/templates/react/example/tanchat/assets/src/components/example-AIAssistant.tsx +173 -0
- package/templates/react/example/tanchat/assets/src/components/example-GuitarRecommendation.tsx +47 -0
- package/templates/react/example/tanchat/assets/src/data/example-guitars.ts +83 -0
- package/templates/react/example/tanchat/assets/src/demo.index.css +220 -0
- package/templates/react/example/tanchat/assets/src/integrations/tanchat/header-user.tsx +5 -0
- package/templates/react/example/tanchat/assets/src/routes/api.messages.ts +24 -0
- package/templates/react/example/tanchat/assets/src/routes/api.sse.ts +23 -0
- package/templates/react/example/tanchat/assets/src/routes/example.chat.tsx +159 -0
- package/templates/react/example/tanchat/assets/src/routes/example.guitars/$guitarId.tsx +50 -0
- package/templates/react/example/tanchat/assets/src/routes/example.guitars/index.tsx +54 -0
- package/templates/react/example/tanchat/assets/src/store/example-assistant.ts +3 -0
- package/templates/react/example/tanchat/assets/src/utils/demo.ai.ts +62 -0
- package/templates/react/example/tanchat/assets/src/utils/demo.sse.ts +31 -0
- package/templates/react/example/tanchat/assets/src/utils/demo.tools.ts +47 -0
- package/templates/react/example/tanchat/info.json +19 -0
- package/templates/react/example/tanchat/package.json +16 -0
- package/templates/react/file-router/package.fr.json +5 -0
- package/templates/react/file-router/src/main.tsx.ejs +55 -0
- package/templates/react/file-router/src/routes/__root.tsx.ejs +82 -0
- package/templates/solid/add-on/form/assets/src/routes/demo.form.tsx.ejs +352 -0
- package/templates/solid/add-on/form/info.json +13 -0
- package/templates/solid/add-on/form/package.json +5 -0
- package/templates/solid/add-on/module-federation/assets/module-federation.config.js.ejs +27 -0
- package/templates/solid/add-on/module-federation/assets/src/demo-mf-component.tsx +3 -0
- package/templates/solid/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +9 -0
- package/templates/solid/add-on/module-federation/info.json +7 -0
- package/templates/solid/add-on/module-federation/package.json +5 -0
- package/templates/solid/add-on/sentry/assets/_dot_cursorrules.append +22 -0
- package/templates/solid/add-on/sentry/assets/_dot_env.local.append +2 -0
- package/templates/solid/add-on/sentry/assets/src/routes/demo.sentry.bad-event-handler.tsx +20 -0
- package/templates/solid/add-on/sentry/info.json +13 -0
- package/templates/solid/add-on/sentry/package.json +5 -0
- package/templates/solid/add-on/solid-ui/README.md +9 -0
- package/templates/solid/add-on/solid-ui/assets/src/lib/utils.ts +6 -0
- package/templates/solid/add-on/solid-ui/assets/src/styles.css +138 -0
- package/templates/solid/add-on/solid-ui/assets/ui.config.json +13 -0
- package/templates/solid/add-on/solid-ui/info.json +11 -0
- package/templates/solid/add-on/solid-ui/package.json +9 -0
- package/templates/solid/add-on/start/assets/app.config.ts +16 -0
- package/templates/solid/add-on/start/assets/src/api.ts +6 -0
- package/templates/solid/add-on/start/assets/src/client.tsx +7 -0
- package/templates/solid/add-on/start/assets/src/router.tsx.ejs +24 -0
- package/templates/solid/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +49 -0
- package/templates/solid/add-on/start/assets/src/ssr.tsx +12 -0
- package/templates/solid/add-on/start/info.json +14 -0
- package/templates/solid/add-on/start/package.json +12 -0
- package/templates/solid/add-on/store/assets/src/lib/demo-store.ts +13 -0
- package/templates/solid/add-on/store/assets/src/routes/demo.store.tsx.ejs +77 -0
- package/templates/solid/add-on/store/info.json +13 -0
- package/templates/solid/add-on/store/package.json +6 -0
- package/templates/solid/add-on/t3env/README.md +16 -0
- package/templates/solid/add-on/t3env/assets/src/env.ts +39 -0
- package/templates/solid/add-on/t3env/info.json +10 -0
- package/templates/solid/add-on/t3env/package.json +6 -0
- package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/header-user.tsx +5 -0
- package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/provider.tsx +15 -0
- package/templates/solid/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx +30 -0
- package/templates/solid/add-on/tanstack-query/info.json +13 -0
- package/templates/solid/add-on/tanstack-query/package.json +6 -0
- package/templates/solid/base/README.md.ejs +215 -0
- package/templates/solid/base/_dot_cursorrules.append +35 -0
- package/templates/solid/base/_dot_gitignore +5 -0
- package/templates/solid/base/_dot_vscode/settings.biome.json +35 -0
- package/templates/solid/base/_dot_vscode/settings.json +11 -0
- package/templates/solid/base/index.html.ejs +20 -0
- package/templates/solid/base/package.biome.json +10 -0
- package/templates/solid/base/package.eslintprettier.json +11 -0
- package/templates/solid/base/package.json +23 -0
- package/templates/solid/base/package.ts.json +5 -0
- package/templates/solid/base/package.tw.json +6 -0
- package/templates/solid/base/public/favicon.ico +0 -0
- package/templates/solid/base/public/logo192.png +0 -0
- package/templates/solid/base/public/logo512.png +0 -0
- package/templates/solid/base/public/manifest.json +25 -0
- package/templates/solid/base/public/robots.txt +3 -0
- package/templates/solid/base/src/App.css +0 -0
- package/templates/solid/base/src/App.tsx.ejs +47 -0
- package/templates/solid/base/src/components/Header.tsx.ejs +26 -0
- package/templates/solid/base/src/logo.svg +120 -0
- package/templates/solid/base/src/styles.css.ejs +15 -0
- package/templates/solid/base/toolchain/.prettierignore +3 -0
- package/templates/solid/base/toolchain/biome.json +31 -0
- package/templates/solid/base/toolchain/eslint.config.js +5 -0
- package/templates/solid/base/toolchain/prettier.config.js +10 -0
- package/templates/solid/base/tsconfig.json.ejs +31 -0
- package/templates/solid/base/vite.config.js.ejs +22 -0
- package/templates/solid/code-router/src/main.tsx.ejs +71 -0
- package/templates/solid/example/tanchat/README.md +52 -0
- package/templates/solid/example/tanchat/assets/ai-streaming-server/README.md +110 -0
- package/templates/solid/example/tanchat/assets/ai-streaming-server/_dot_env.example +1 -0
- package/templates/solid/example/tanchat/assets/ai-streaming-server/package.json +26 -0
- package/templates/solid/example/tanchat/assets/ai-streaming-server/src/index.ts +102 -0
- package/templates/solid/example/tanchat/assets/ai-streaming-server/tsconfig.json +15 -0
- package/templates/solid/example/tanchat/assets/src/components/demo.SettingsDialog.tsx +149 -0
- package/templates/solid/example/tanchat/assets/src/demo.index.css +227 -0
- package/templates/solid/example/tanchat/assets/src/lib/demo-store.ts +13 -0
- package/templates/solid/example/tanchat/assets/src/routes/example.chat.tsx +435 -0
- package/templates/solid/example/tanchat/assets/src/store/demo.hooks.ts +17 -0
- package/templates/solid/example/tanchat/assets/src/store/demo.store.ts +133 -0
- package/templates/solid/example/tanchat/info.json +14 -0
- package/templates/solid/example/tanchat/package.json +7 -0
- package/templates/solid/file-router/package.fr.json +5 -0
- package/templates/solid/file-router/src/main.tsx.ejs +47 -0
- package/templates/solid/file-router/src/routes/__root.tsx.ejs +41 -0
- package/templates/solid/file-router/src/routes/index.tsx +43 -0
- package/tests/cra.test.ts +293 -0
- package/tests/snapshots/cra/cr-js-npm.json +33 -0
- package/tests/snapshots/cra/cr-ts-npm.json +34 -0
- package/tests/snapshots/cra/cr-ts-start-npm.json +38 -0
- package/tests/snapshots/cra/fr-ts-npm.json +34 -0
- package/tests/snapshots/cra/fr-ts-tw-npm.json +33 -0
- package/tests/snapshots/cra/solid-cr-js-npm.json +31 -0
- package/tests/snapshots/cra/solid-cr-ts-npm.json +32 -0
- package/tests/snapshots/cra/solid-cr-ts-start-npm.json +36 -0
- package/tests/snapshots/cra/solid-fr-ts-npm.json +33 -0
- package/tests/snapshots/cra/solid-fr-ts-tw-npm.json +32 -0
- package/tests/test-utilities.ts +87 -0
- package/dist/add-to-app.js +0 -169
- package/dist/custom-add-ons/add-on.js +0 -175
- package/dist/custom-add-ons/shared.js +0 -117
- package/dist/custom-add-ons/starter.js +0 -84
- package/dist/file-helpers.js +0 -165
- package/dist/frameworks.js +0 -92
- package/dist/integrations/git.js +0 -4
- package/dist/integrations/shadcn.js +0 -33
- package/dist/package-json.js +0 -48
- package/dist/special-steps/index.js +0 -24
- package/dist/special-steps/rimraf-node-modules.js +0 -16
- package/dist/template-file.js +0 -112
- package/dist/types/add-to-app.d.ts +0 -17
- package/dist/types/custom-add-ons/add-on.d.ts +0 -69
- package/dist/types/custom-add-ons/shared.d.ts +0 -15
- package/dist/types/custom-add-ons/starter.d.ts +0 -7
- package/dist/types/file-helpers.d.ts +0 -15
- package/dist/types/frameworks.d.ts +0 -7
- package/dist/types/integrations/git.d.ts +0 -2
- package/dist/types/integrations/shadcn.d.ts +0 -2
- package/dist/types/package-json.d.ts +0 -7
- package/dist/types/special-steps/index.d.ts +0 -2
- package/dist/types/special-steps/rimraf-node-modules.d.ts +0 -2
- package/dist/types/template-file.d.ts +0 -2
- package/src/add-to-app.ts +0 -274
- package/src/custom-add-ons/add-on.ts +0 -261
- package/src/custom-add-ons/shared.ts +0 -161
- package/src/custom-add-ons/starter.ts +0 -126
- package/src/file-helpers.ts +0 -235
- package/src/frameworks.ts +0 -134
- package/src/integrations/git.ts +0 -7
- package/src/integrations/shadcn.ts +0 -54
- package/src/package-json.ts +0 -69
- package/src/special-steps/index.ts +0 -36
- package/src/special-steps/rimraf-node-modules.ts +0 -25
- package/src/template-file.ts +0 -150
- package/tests/add-ons.test.ts +0 -67
- package/tests/add-to-app.test.ts +0 -358
- package/tests/config-file.test.ts +0 -68
- package/tests/create-app.test.ts +0 -120
- package/tests/custom-add-ons/add-on.test.ts +0 -12
- package/tests/custom-add-ons/shared.test.ts +0 -257
- package/tests/custom-add-ons/starter.test.ts +0 -58
- package/tests/environment.test.ts +0 -115
- package/tests/file-helper.test.ts +0 -90
- package/tests/frameworks.test.ts +0 -95
- package/tests/index.test.ts +0 -9
- package/tests/integrations/git.test.ts +0 -20
- package/tests/integrations/shadcn.test.ts +0 -91
- package/tests/options.test.ts +0 -42
- package/tests/package-json.test.ts +0 -63
- package/tests/package-manager.test.ts +0 -154
- package/tests/setupVitest.ts +0 -6
- package/tests/template-file.test.ts +0 -178
- package/tests/utils.test.ts +0 -23
- package/vitest.config.ts +0 -21
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { basename, dirname, resolve } from 'node:path';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { createMemoryEnvironment } from './environment.js';
|
|
6
|
+
import { createApp } from './create-app.js';
|
|
7
|
+
import { readConfigFile } from './config-file.js';
|
|
8
|
+
import { finalizeAddOns } from './add-ons.js';
|
|
9
|
+
import { readFileHelper } from './file-helper.js';
|
|
10
|
+
const INFO_FILE = {
|
|
11
|
+
'add-on': '.add-on/info.json',
|
|
12
|
+
overlay: 'overlay-info.json',
|
|
13
|
+
};
|
|
14
|
+
const COMPILED_FILE = {
|
|
15
|
+
'add-on': 'add-on.json',
|
|
16
|
+
overlay: 'overlay.json',
|
|
17
|
+
};
|
|
18
|
+
const ADD_ON_DIR = '.add-on';
|
|
19
|
+
const ASSETS_DIR = 'assets';
|
|
20
|
+
const IGNORE_FILES = [
|
|
21
|
+
ADD_ON_DIR,
|
|
22
|
+
'node_modules',
|
|
23
|
+
'dist',
|
|
24
|
+
'build',
|
|
25
|
+
'.git',
|
|
26
|
+
'pnpm-lock.yaml',
|
|
27
|
+
'package-lock.json',
|
|
28
|
+
'yarn.lock',
|
|
29
|
+
'bun.lockb',
|
|
30
|
+
'bun.lock',
|
|
31
|
+
'deno.lock',
|
|
32
|
+
'add-on.json',
|
|
33
|
+
'add-on-info.json',
|
|
34
|
+
'package.json',
|
|
35
|
+
];
|
|
36
|
+
const ADD_ON_IGNORE_FILES = [
|
|
37
|
+
'main.jsx',
|
|
38
|
+
'App.jsx',
|
|
39
|
+
'main.tsx',
|
|
40
|
+
'App.tsx',
|
|
41
|
+
'routeTree.gen.ts',
|
|
42
|
+
];
|
|
43
|
+
function templatize(routeCode, routeFile) {
|
|
44
|
+
let code = routeCode;
|
|
45
|
+
// Replace the import
|
|
46
|
+
code = code.replace(/import { createFileRoute } from '@tanstack\/react-router'/g, `import { <% if (fileRouter) { %>createFileRoute<% } else { %>createRoute<% } %> } from '@tanstack/react-router'`);
|
|
47
|
+
// Extract route path and definition, then transform the route declaration
|
|
48
|
+
const routeMatch = code.match(/export\s+const\s+Route\s*=\s*createFileRoute\(['"]([^'"]+)['"]\)\s*\(\{([^}]+)\}\)/);
|
|
49
|
+
let path = '';
|
|
50
|
+
if (routeMatch) {
|
|
51
|
+
const fullMatch = routeMatch[0];
|
|
52
|
+
path = routeMatch[1];
|
|
53
|
+
const routeDefinition = routeMatch[2];
|
|
54
|
+
code = code.replace(fullMatch, `<% if (codeRouter) { %>
|
|
55
|
+
import type { RootRoute } from '@tanstack/react-router'
|
|
56
|
+
<% } else { %>
|
|
57
|
+
export const Route = createFileRoute('${path}')({${routeDefinition}})
|
|
58
|
+
<% } %>`);
|
|
59
|
+
code += `
|
|
60
|
+
<% if (codeRouter) { %>
|
|
61
|
+
export default (parentRoute: RootRoute) => createRoute({
|
|
62
|
+
path: '${path}',
|
|
63
|
+
${routeDefinition}
|
|
64
|
+
getParentRoute: () => parentRoute,
|
|
65
|
+
})
|
|
66
|
+
<% } %>
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
console.error(`No route found in the file: ${routeFile}`);
|
|
71
|
+
}
|
|
72
|
+
const name = basename(path)
|
|
73
|
+
.replace('.tsx', '')
|
|
74
|
+
.replace(/^demo/, '')
|
|
75
|
+
.replace('.', ' ')
|
|
76
|
+
.trim();
|
|
77
|
+
return { url: path, code, name };
|
|
78
|
+
}
|
|
79
|
+
async function createOptions(json) {
|
|
80
|
+
return {
|
|
81
|
+
...json,
|
|
82
|
+
chosenAddOns: await finalizeAddOns(json.framework, json.mode, [...json.existingAddOns]),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
async function runCreateApp(options) {
|
|
86
|
+
const { environment, output } = createMemoryEnvironment();
|
|
87
|
+
await createApp(options, {
|
|
88
|
+
silent: true,
|
|
89
|
+
environment,
|
|
90
|
+
cwd: process.cwd(),
|
|
91
|
+
name: 'create-tsrouter-app',
|
|
92
|
+
});
|
|
93
|
+
return output;
|
|
94
|
+
}
|
|
95
|
+
async function recursivelyGatherFiles(path, files) {
|
|
96
|
+
const dirFiles = await readdir(path, { withFileTypes: true });
|
|
97
|
+
for (const file of dirFiles) {
|
|
98
|
+
if (file.isDirectory()) {
|
|
99
|
+
await recursivelyGatherFiles(resolve(path, file.name), files);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
files[resolve(path, file.name)] = readFileHelper(resolve(path, file.name));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async function compareFiles(path, ignore, original, changedFiles) {
|
|
107
|
+
const files = await readdir(path, { withFileTypes: true });
|
|
108
|
+
for (const file of files) {
|
|
109
|
+
const filePath = `${path}/${file.name}`;
|
|
110
|
+
if (!ignore.includes(file.name)) {
|
|
111
|
+
if (file.isDirectory()) {
|
|
112
|
+
await compareFiles(filePath, ignore, original, changedFiles);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
const contents = (await readFile(filePath)).toString();
|
|
116
|
+
const absolutePath = resolve(process.cwd(), filePath);
|
|
117
|
+
if (!original[absolutePath] || original[absolutePath] !== contents) {
|
|
118
|
+
changedFiles[filePath] = contents;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
export async function initAddOn(mode) {
|
|
125
|
+
const persistedOptions = await readConfigFile(process.cwd());
|
|
126
|
+
if (!persistedOptions) {
|
|
127
|
+
console.error(`${chalk.red('There is no .cta.json file in your project.')}
|
|
128
|
+
|
|
129
|
+
This is probably because this was created with an older version of create-tsrouter-app.`);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (mode === 'add-on') {
|
|
133
|
+
if (persistedOptions.mode !== 'file-router') {
|
|
134
|
+
console.error(`${chalk.red('This project is not using file-router mode.')}
|
|
135
|
+
|
|
136
|
+
To create an add-on, the project must be created with the file-router mode.`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (!persistedOptions.tailwind) {
|
|
140
|
+
console.error(`${chalk.red('This project is not using Tailwind CSS.')}
|
|
141
|
+
|
|
142
|
+
To create an add-on, the project must be created with Tailwind CSS.`);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (!persistedOptions.typescript) {
|
|
146
|
+
console.error(`${chalk.red('This project is not using TypeScript.')}
|
|
147
|
+
|
|
148
|
+
To create an add-on, the project must be created with TypeScript.`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const info = existsSync(INFO_FILE[mode])
|
|
153
|
+
? JSON.parse((await readFile(INFO_FILE[mode])).toString())
|
|
154
|
+
: {
|
|
155
|
+
name: `${persistedOptions.projectName}-${mode}`,
|
|
156
|
+
version: '0.0.1',
|
|
157
|
+
description: mode === 'add-on' ? 'Add-on' : 'Project overlay',
|
|
158
|
+
author: 'Jane Smith <jane.smith@example.com>',
|
|
159
|
+
license: 'MIT',
|
|
160
|
+
link: `https://github.com/jane-smith/${persistedOptions.projectName}-${mode}`,
|
|
161
|
+
command: {},
|
|
162
|
+
shadcnComponents: [],
|
|
163
|
+
templates: [persistedOptions.mode],
|
|
164
|
+
routes: [],
|
|
165
|
+
warning: '',
|
|
166
|
+
variables: {},
|
|
167
|
+
phase: 'add-on',
|
|
168
|
+
type: mode,
|
|
169
|
+
packageAdditions: {
|
|
170
|
+
scripts: {},
|
|
171
|
+
dependencies: {},
|
|
172
|
+
devDependencies: {},
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
const compiledInfo = JSON.parse(JSON.stringify(info));
|
|
176
|
+
const originalOutput = await runCreateApp(await createOptions(persistedOptions));
|
|
177
|
+
const originalPackageJson = JSON.parse(originalOutput.files[resolve(process.cwd(), 'package.json')]);
|
|
178
|
+
const currentPackageJson = JSON.parse((await readFile('package.json')).toString());
|
|
179
|
+
for (const script of Object.keys(currentPackageJson.scripts)) {
|
|
180
|
+
if (originalPackageJson.scripts[script] !== currentPackageJson.scripts[script]) {
|
|
181
|
+
info.packageAdditions.scripts[script] = currentPackageJson.scripts[script];
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const dependencies = {};
|
|
185
|
+
for (const dependency of Object.keys(currentPackageJson.dependencies)) {
|
|
186
|
+
if (originalPackageJson.dependencies[dependency] !==
|
|
187
|
+
currentPackageJson.dependencies[dependency]) {
|
|
188
|
+
dependencies[dependency] = currentPackageJson.dependencies[dependency];
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
info.packageAdditions.dependencies = dependencies;
|
|
192
|
+
const devDependencies = {};
|
|
193
|
+
for (const dependency of Object.keys(currentPackageJson.devDependencies)) {
|
|
194
|
+
if (originalPackageJson.devDependencies[dependency] !==
|
|
195
|
+
currentPackageJson.devDependencies[dependency]) {
|
|
196
|
+
devDependencies[dependency] =
|
|
197
|
+
currentPackageJson.devDependencies[dependency];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
info.packageAdditions.devDependencies = devDependencies;
|
|
201
|
+
// Find altered files
|
|
202
|
+
const changedFiles = {};
|
|
203
|
+
await compareFiles('.', IGNORE_FILES, originalOutput.files, changedFiles);
|
|
204
|
+
if (mode === 'overlay') {
|
|
205
|
+
compiledInfo.files = changedFiles;
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
const assetsDir = resolve(ADD_ON_DIR, ASSETS_DIR);
|
|
209
|
+
if (!existsSync(assetsDir)) {
|
|
210
|
+
await compareFiles('.', IGNORE_FILES, originalOutput.files, changedFiles);
|
|
211
|
+
for (const file of Object.keys(changedFiles).filter((file) => !ADD_ON_IGNORE_FILES.includes(basename(file)))) {
|
|
212
|
+
mkdirSync(dirname(resolve(assetsDir, file)), {
|
|
213
|
+
recursive: true,
|
|
214
|
+
});
|
|
215
|
+
if (file.includes('/routes/')) {
|
|
216
|
+
const { url, code, name } = templatize(changedFiles[file], file);
|
|
217
|
+
info.routes.push({
|
|
218
|
+
url,
|
|
219
|
+
name,
|
|
220
|
+
});
|
|
221
|
+
writeFileSync(resolve(assetsDir, `${file}.ejs`), code);
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
writeFileSync(resolve(assetsDir, file), changedFiles[file]);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const addOnFiles = {};
|
|
229
|
+
await recursivelyGatherFiles(assetsDir, addOnFiles);
|
|
230
|
+
compiledInfo.files = Object.keys(addOnFiles).reduce((acc, file) => {
|
|
231
|
+
acc[file.replace(assetsDir, '.')] = addOnFiles[file];
|
|
232
|
+
return acc;
|
|
233
|
+
}, {});
|
|
234
|
+
}
|
|
235
|
+
compiledInfo.routes = info.routes;
|
|
236
|
+
compiledInfo.framework = persistedOptions.framework;
|
|
237
|
+
compiledInfo.addDependencies = persistedOptions.existingAddOns;
|
|
238
|
+
if (mode === 'overlay') {
|
|
239
|
+
compiledInfo.mode = persistedOptions.mode;
|
|
240
|
+
compiledInfo.typescript = persistedOptions.typescript;
|
|
241
|
+
compiledInfo.tailwind = persistedOptions.tailwind;
|
|
242
|
+
compiledInfo.deletedFiles = [];
|
|
243
|
+
for (const file of Object.keys(originalOutput.files)) {
|
|
244
|
+
if (!existsSync(file)) {
|
|
245
|
+
compiledInfo.deletedFiles.push(file.replace(process.cwd(), '.'));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (!existsSync(resolve(INFO_FILE[mode]))) {
|
|
250
|
+
mkdirSync(resolve(dirname(INFO_FILE[mode])), { recursive: true });
|
|
251
|
+
writeFileSync(INFO_FILE[mode], JSON.stringify(info, null, 2));
|
|
252
|
+
}
|
|
253
|
+
writeFileSync(COMPILED_FILE[mode], JSON.stringify(compiledInfo, null, 2));
|
|
254
|
+
}
|
package/dist/environment.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { appendFile, copyFile, mkdir, readFile,
|
|
2
|
-
import { existsSync, statSync } from 'node:fs';
|
|
1
|
+
import { appendFile, copyFile, mkdir, readFile, unlink, writeFile, } from 'node:fs/promises';
|
|
2
|
+
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
3
3
|
import { dirname } from 'node:path';
|
|
4
4
|
import { execa } from 'execa';
|
|
5
5
|
import { memfs } from 'memfs';
|
|
6
|
-
import { rimraf } from 'rimraf';
|
|
7
|
-
import { cleanUpFileArray, cleanUpFiles, getBinaryFile, } from './file-helpers.js';
|
|
8
6
|
export function createDefaultEnvironment() {
|
|
9
7
|
let errors = [];
|
|
10
8
|
return {
|
|
@@ -25,57 +23,33 @@ export function createDefaultEnvironment() {
|
|
|
25
23
|
await mkdir(dirname(path), { recursive: true });
|
|
26
24
|
return writeFile(path, contents);
|
|
27
25
|
},
|
|
28
|
-
writeFileBase64: async (path, base64Contents) => {
|
|
29
|
-
await mkdir(dirname(path), { recursive: true });
|
|
30
|
-
return writeFile(path, getBinaryFile(base64Contents));
|
|
31
|
-
},
|
|
32
26
|
execute: async (command, args, cwd) => {
|
|
33
27
|
try {
|
|
34
|
-
|
|
28
|
+
await execa(command, args, {
|
|
35
29
|
cwd,
|
|
36
30
|
});
|
|
37
|
-
return { stdout: result.stdout };
|
|
38
31
|
}
|
|
39
32
|
catch {
|
|
40
33
|
errors.push(`Command "${command} ${args.join(' ')}" did not run successfully. Please run this manually in your project.`);
|
|
41
|
-
return { stdout: '' };
|
|
42
34
|
}
|
|
43
35
|
},
|
|
44
36
|
deleteFile: async (path) => {
|
|
45
|
-
|
|
46
|
-
await unlink(path);
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
readFile: async (path) => {
|
|
50
|
-
return (await readFile(path)).toString();
|
|
37
|
+
await unlink(path);
|
|
51
38
|
},
|
|
39
|
+
readFile: (path, encoding) => readFile(path, { encoding: encoding || 'utf8' }),
|
|
52
40
|
exists: (path) => existsSync(path),
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
41
|
+
readdir: (path) => readdirSync(path),
|
|
42
|
+
isDirectory: (path) => {
|
|
43
|
+
const stat = statSync(path);
|
|
44
|
+
return stat.isDirectory();
|
|
57
45
|
},
|
|
58
|
-
appName: 'TanStack',
|
|
59
|
-
startStep: () => { },
|
|
60
|
-
finishStep: () => { },
|
|
61
|
-
intro: () => { },
|
|
62
|
-
outro: () => { },
|
|
63
|
-
info: () => { },
|
|
64
|
-
error: () => { },
|
|
65
|
-
warn: () => { },
|
|
66
|
-
confirm: () => Promise.resolve(true),
|
|
67
|
-
spinner: () => ({
|
|
68
|
-
start: () => { },
|
|
69
|
-
stop: () => { },
|
|
70
|
-
}),
|
|
71
46
|
};
|
|
72
47
|
}
|
|
73
|
-
export function createMemoryEnvironment(
|
|
48
|
+
export function createMemoryEnvironment() {
|
|
74
49
|
const environment = createDefaultEnvironment();
|
|
75
50
|
const output = {
|
|
76
51
|
files: {},
|
|
77
52
|
commands: [],
|
|
78
|
-
deletedFiles: [],
|
|
79
53
|
};
|
|
80
54
|
const { fs, vol } = memfs({});
|
|
81
55
|
const cwd = process.cwd();
|
|
@@ -101,49 +75,43 @@ export function createMemoryEnvironment(returnPathsRelativeTo = '') {
|
|
|
101
75
|
command,
|
|
102
76
|
args,
|
|
103
77
|
});
|
|
104
|
-
return Promise.resolve(
|
|
78
|
+
return Promise.resolve();
|
|
105
79
|
};
|
|
106
|
-
environment.readFile = async (path) => {
|
|
107
|
-
|
|
80
|
+
environment.readFile = async (path, encoding) => {
|
|
81
|
+
if (isTemplatePath(path)) {
|
|
82
|
+
return (await readFile(path, encoding)).toString();
|
|
83
|
+
}
|
|
84
|
+
return fs.readFileSync(path, 'utf8').toString();
|
|
108
85
|
};
|
|
109
86
|
environment.writeFile = async (path, contents) => {
|
|
110
87
|
fs.mkdirSync(dirname(path), { recursive: true });
|
|
111
88
|
await fs.writeFileSync(path, contents);
|
|
112
89
|
};
|
|
113
|
-
environment.writeFileBase64 = async (path, contents) => {
|
|
114
|
-
// For the in-memory file system, we are not converting the base64 to binary
|
|
115
|
-
// because it's not needed.
|
|
116
|
-
fs.mkdirSync(dirname(path), { recursive: true });
|
|
117
|
-
await fs.writeFileSync(path, contents);
|
|
118
|
-
};
|
|
119
90
|
environment.deleteFile = async (path) => {
|
|
120
|
-
|
|
121
|
-
if (fs.existsSync(path)) {
|
|
122
|
-
await fs.unlinkSync(path);
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
environment.finishRun = () => {
|
|
126
|
-
output.files = vol.toJSON();
|
|
127
|
-
for (const file of Object.keys(output.files)) {
|
|
128
|
-
if (fs.statSync(file).isDirectory()) {
|
|
129
|
-
delete output.files[file];
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
if (returnPathsRelativeTo.length) {
|
|
133
|
-
output.files = cleanUpFiles(output.files, returnPathsRelativeTo);
|
|
134
|
-
output.deletedFiles = cleanUpFileArray(output.deletedFiles, returnPathsRelativeTo);
|
|
135
|
-
}
|
|
91
|
+
await fs.unlinkSync(path);
|
|
136
92
|
};
|
|
137
93
|
environment.exists = (path) => {
|
|
94
|
+
if (isTemplatePath(path)) {
|
|
95
|
+
return existsSync(path);
|
|
96
|
+
}
|
|
138
97
|
return fs.existsSync(path);
|
|
139
98
|
};
|
|
99
|
+
environment.readdir = (path) => {
|
|
100
|
+
if (isTemplatePath(path)) {
|
|
101
|
+
return readdirSync(path);
|
|
102
|
+
}
|
|
103
|
+
return fs.readdirSync(path).map((file) => file.toString());
|
|
104
|
+
};
|
|
140
105
|
environment.isDirectory = (path) => {
|
|
106
|
+
if (isTemplatePath(path)) {
|
|
107
|
+
const stat = statSync(path);
|
|
108
|
+
return stat.isDirectory();
|
|
109
|
+
}
|
|
141
110
|
return fs.statSync(path).isDirectory();
|
|
142
111
|
};
|
|
143
|
-
environment.
|
|
144
|
-
|
|
112
|
+
environment.finishRun = () => {
|
|
113
|
+
output.files = vol.toJSON();
|
|
145
114
|
};
|
|
146
|
-
environment.rimraf = async () => { };
|
|
147
115
|
return {
|
|
148
116
|
environment,
|
|
149
117
|
output,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { extname } 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
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { addToApp } from './add-to-app.js';
|
|
3
|
-
export { finalizeAddOns, getAllAddOns } from './add-ons.js';
|
|
4
|
-
export { loadRemoteAddOn } from './custom-add-ons/add-on.js';
|
|
5
|
-
export { loadStarter } from './custom-add-ons/starter.js';
|
|
6
|
-
export { createMemoryEnvironment, createDefaultEnvironment, } from './environment.js';
|
|
7
|
-
export { CODE_ROUTER, CONFIG_FILE, FILE_ROUTER } from './constants.js';
|
|
8
|
-
export { DEFAULT_PACKAGE_MANAGER, SUPPORTED_PACKAGE_MANAGERS, getPackageManager, } from './package-manager.js';
|
|
9
|
-
export { registerFramework, getFrameworkById, getFrameworkByName, getFrameworks, } from './frameworks.js';
|
|
10
|
-
export { writeConfigFileToEnvironment, readConfigFileFromEnvironment, } from './config-file.js';
|
|
11
|
-
export { cleanUpFiles, cleanUpFileArray, readFileHelper, getBinaryFile, recursivelyGatherFiles, relativePath, } from './file-helpers.js';
|
|
12
|
-
export { formatCommand } from './utils.js';
|
|
13
|
-
export { initStarter, compileStarter } from './custom-add-ons/starter.js';
|
|
14
|
-
export { initAddOn, compileAddOn } from './custom-add-ons/add-on.js';
|
|
15
|
-
export { createAppOptionsFromPersisted, createSerializedOptionsFromPersisted, } from './custom-add-ons/shared.js';
|
|
16
|
-
export { createSerializedOptions } from './options.js';
|
|
17
|
-
export { StarterCompiledSchema, AddOnCompiledSchema, AddOnInfoSchema, IntegrationSchema, } from './types.js';
|
|
1
|
+
export { cli } from './cli.js';
|
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import express from 'express';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { createApp } from './create-app.js';
|
|
7
|
+
import { finalizeAddOns } from './add-ons.js';
|
|
8
|
+
import { createDefaultEnvironment } from './environment.js';
|
|
9
|
+
const tanStackReactAddOns = [
|
|
10
|
+
{
|
|
11
|
+
id: 'clerk',
|
|
12
|
+
description: 'Enable authentication with Clerk',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
id: 'convex',
|
|
16
|
+
description: 'Enable a database using Convex',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: 'form',
|
|
20
|
+
description: 'Form handling library',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: 'netlify',
|
|
24
|
+
description: 'Enable deployments to Netlify',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'sentry',
|
|
28
|
+
description: 'Enable Sentry error tracking',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: 'shadcn',
|
|
32
|
+
description: 'Enable integration of the Shadcn UI component library',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'start',
|
|
36
|
+
description: 'Set this if you want a TanStack Start application that supports server functions or APIs',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 'tanstack-query',
|
|
40
|
+
description: 'Enable TanStack Query for data fetching',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: 'store',
|
|
44
|
+
description: 'Enable the TanStack Store state management library',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: 'tanchat',
|
|
48
|
+
description: 'Add an AI chatbot example to the application',
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
const tanStackSolidAddOns = [
|
|
52
|
+
{
|
|
53
|
+
id: 'solid-ui',
|
|
54
|
+
description: 'Enable integration of the Solid UI component library',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 'form',
|
|
58
|
+
description: 'Form handling library',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: 'sentry',
|
|
62
|
+
description: 'Enable Sentry error tracking',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: 'store',
|
|
66
|
+
description: 'Enable the TanStack Store state management library',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: 'start',
|
|
70
|
+
description: 'Set this if you want a TanStack Start application that supports server functions or APIs',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: 'tanstack-query',
|
|
74
|
+
description: 'Enable TanStack Query for data fetching',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: 'tanchat',
|
|
78
|
+
description: 'Add an AI chatbot example to the application',
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
function createServer({ appName, forcedAddOns = [], name, }) {
|
|
82
|
+
const server = new McpServer({
|
|
83
|
+
name: `${appName} Application Builder`,
|
|
84
|
+
version: '1.0.0',
|
|
85
|
+
});
|
|
86
|
+
server.tool('listTanStackReactAddOns', {}, () => {
|
|
87
|
+
return {
|
|
88
|
+
content: [{ type: 'text', text: JSON.stringify(tanStackReactAddOns) }],
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
server.tool('createTanStackReactApplication', {
|
|
92
|
+
projectName: z
|
|
93
|
+
.string()
|
|
94
|
+
.describe('The package.json module name of the application (will also be the directory name)'),
|
|
95
|
+
cwd: z.string().describe('The directory to create the application in'),
|
|
96
|
+
addOns: z
|
|
97
|
+
.array(z.enum([
|
|
98
|
+
'clerk',
|
|
99
|
+
'convex',
|
|
100
|
+
'form',
|
|
101
|
+
'netlify',
|
|
102
|
+
'sentry',
|
|
103
|
+
'shadcn',
|
|
104
|
+
'start',
|
|
105
|
+
'store',
|
|
106
|
+
'tanstack-query',
|
|
107
|
+
'tanchat',
|
|
108
|
+
]))
|
|
109
|
+
.describe('The IDs of the add-ons to install'),
|
|
110
|
+
targetDir: z
|
|
111
|
+
.string()
|
|
112
|
+
.describe('The directory to create the application in. Use the absolute path of the directory you want the application to be created in'),
|
|
113
|
+
}, async ({ projectName, addOns, cwd, targetDir }) => {
|
|
114
|
+
try {
|
|
115
|
+
process.chdir(cwd);
|
|
116
|
+
const chosenAddOns = await finalizeAddOns('react', 'file-router', Array.from(new Set([...addOns, ...forcedAddOns])));
|
|
117
|
+
await createApp({
|
|
118
|
+
projectName: projectName.replace(/^\//, './'),
|
|
119
|
+
framework: 'react',
|
|
120
|
+
typescript: true,
|
|
121
|
+
tailwind: true,
|
|
122
|
+
packageManager: 'pnpm',
|
|
123
|
+
toolchain: 'none',
|
|
124
|
+
mode: 'file-router',
|
|
125
|
+
addOns: true,
|
|
126
|
+
chosenAddOns,
|
|
127
|
+
git: true,
|
|
128
|
+
variableValues: {},
|
|
129
|
+
}, {
|
|
130
|
+
silent: true,
|
|
131
|
+
environment: createDefaultEnvironment(),
|
|
132
|
+
name,
|
|
133
|
+
cwd: targetDir,
|
|
134
|
+
});
|
|
135
|
+
return {
|
|
136
|
+
content: [{ type: 'text', text: 'Application created successfully' }],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
return {
|
|
141
|
+
content: [
|
|
142
|
+
{ type: 'text', text: `Error creating application: ${error}` },
|
|
143
|
+
],
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
server.tool('listTanStackSolidAddOns', {}, () => {
|
|
148
|
+
return {
|
|
149
|
+
content: [{ type: 'text', text: JSON.stringify(tanStackSolidAddOns) }],
|
|
150
|
+
};
|
|
151
|
+
});
|
|
152
|
+
server.tool('createTanStackSolidApplication', {
|
|
153
|
+
projectName: z
|
|
154
|
+
.string()
|
|
155
|
+
.describe('The package.json module name of the application (will also be the directory name)'),
|
|
156
|
+
cwd: z.string().describe('The directory to create the application in'),
|
|
157
|
+
addOns: z
|
|
158
|
+
.array(z.enum([
|
|
159
|
+
'solid-ui',
|
|
160
|
+
'form',
|
|
161
|
+
'sentry',
|
|
162
|
+
'store',
|
|
163
|
+
'tanstack-query',
|
|
164
|
+
'tanchat',
|
|
165
|
+
]))
|
|
166
|
+
.describe('The IDs of the add-ons to install'),
|
|
167
|
+
targetDir: z
|
|
168
|
+
.string()
|
|
169
|
+
.describe('The directory to create the application in. Use the absolute path of the directory you want the application to be created in'),
|
|
170
|
+
}, async ({ projectName, addOns, cwd, targetDir }) => {
|
|
171
|
+
try {
|
|
172
|
+
process.chdir(cwd);
|
|
173
|
+
const chosenAddOns = await finalizeAddOns('solid', 'file-router', Array.from(new Set([...addOns, ...forcedAddOns])));
|
|
174
|
+
await createApp({
|
|
175
|
+
projectName: projectName.replace(/^\//, './'),
|
|
176
|
+
framework: 'solid',
|
|
177
|
+
typescript: true,
|
|
178
|
+
tailwind: true,
|
|
179
|
+
packageManager: 'pnpm',
|
|
180
|
+
toolchain: 'none',
|
|
181
|
+
mode: 'file-router',
|
|
182
|
+
addOns: true,
|
|
183
|
+
chosenAddOns,
|
|
184
|
+
git: true,
|
|
185
|
+
variableValues: {},
|
|
186
|
+
}, {
|
|
187
|
+
silent: true,
|
|
188
|
+
environment: createDefaultEnvironment(),
|
|
189
|
+
name,
|
|
190
|
+
cwd: targetDir,
|
|
191
|
+
});
|
|
192
|
+
return {
|
|
193
|
+
content: [{ type: 'text', text: 'Application created successfully' }],
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
return {
|
|
198
|
+
content: [
|
|
199
|
+
{ type: 'text', text: `Error creating application: ${error}` },
|
|
200
|
+
],
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
return server;
|
|
205
|
+
}
|
|
206
|
+
export default async function runServer(sse, { forcedAddOns, appName, name, }) {
|
|
207
|
+
let transport = null;
|
|
208
|
+
const server = createServer({ appName, forcedAddOns, name });
|
|
209
|
+
if (sse) {
|
|
210
|
+
const app = express();
|
|
211
|
+
app.get('/sse', (req, res) => {
|
|
212
|
+
transport = new SSEServerTransport('/messages', res);
|
|
213
|
+
server.connect(transport);
|
|
214
|
+
});
|
|
215
|
+
app.post('/messages', (req, res) => {
|
|
216
|
+
if (transport) {
|
|
217
|
+
transport.handlePostMessage(req, res);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
const port = process.env.PORT || 8080;
|
|
221
|
+
app.listen(port, () => {
|
|
222
|
+
console.log(`Server is running on port http://localhost:${port}/sse`);
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
const transport = new StdioServerTransport();
|
|
227
|
+
await server.connect(transport);
|
|
228
|
+
}
|
|
229
|
+
}
|