@tanstack/cta-engine 0.10.0-alpha.16 → 0.10.0-alpha.17
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 +73 -8
- package/dist/{add-to-app.js → add.js} +19 -19
- package/dist/cli.js +125 -0
- package/dist/config-file.js +3 -6
- package/dist/constants.js +2 -0
- package/dist/create-app.js +460 -76
- package/dist/custom-add-on.js +254 -0
- package/dist/environment.js +26 -11
- package/dist/file-helper.js +18 -0
- package/dist/index.js +1 -10
- package/dist/mcp.js +229 -0
- package/dist/options.js +330 -0
- 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 +6 -2
- package/dist/types/add.d.ts +3 -0
- package/dist/types/cli.d.ts +7 -0
- package/dist/types/config-file.d.ts +2 -3
- package/dist/types/constants.d.ts +3 -0
- package/dist/types/custom-add-on.d.ts +3 -0
- package/dist/types/file-helper.d.ts +2 -0
- package/dist/types/index.d.ts +1 -13
- package/dist/types/mcp.d.ts +7 -0
- package/dist/types/options.d.ts +6 -0
- package/dist/types/package-manager.d.ts +1 -14
- package/dist/types/templates.d.ts +1 -0
- package/dist/types/toolchain.d.ts +3 -0
- package/dist/types/types.d.ts +63 -84
- package/dist/types/utils.d.ts +0 -5
- package/dist/utils.js +0 -9
- package/package.json +13 -3
- package/src/add-ons.ts +104 -11
- package/src/{add-to-app.ts → add.ts} +35 -29
- package/src/cli.ts +196 -0
- package/src/config-file.ts +6 -12
- package/src/constants.ts +5 -0
- package/src/create-app.ts +727 -126
- package/src/custom-add-on.ts +325 -0
- package/src/environment.ts +27 -12
- package/src/file-helper.ts +20 -0
- package/src/index.ts +1 -42
- package/src/mcp.ts +302 -0
- package/src/options.ts +410 -0
- package/src/package-manager.ts +9 -80
- package/src/templates.ts +7 -0
- package/src/toolchain.ts +7 -0
- package/src/types.ts +69 -98
- 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 +2 -0
- package/templates/react/add-on/sentry/assets/src/app/global-middleware.ts +25 -0
- package/templates/react/add-on/sentry/assets/src/routes/demo.sentry.testing.tsx +480 -0
- package/templates/react/add-on/sentry/info.json +14 -0
- package/templates/react/add-on/sentry/package.json +7 -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 +19 -0
- package/templates/react/add-on/start/assets/src/api.ts +6 -0
- package/templates/react/add-on/start/assets/src/client.tsx +8 -0
- package/templates/react/add-on/start/assets/src/router.tsx.ejs +77 -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 +12 -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 +38 -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 +38 -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/file-helpers.js +0 -59
- package/dist/frameworks.js +0 -78
- package/dist/integrations/git.js +0 -4
- package/dist/integrations/shadcn.js +0 -27
- package/dist/package-json.js +0 -46
- package/dist/template-file.js +0 -108
- package/dist/types/add-to-app.d.ts +0 -4
- package/dist/types/file-helpers.d.ts +0 -5
- package/dist/types/frameworks.d.ts +0 -5
- 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 -2
- package/dist/types/template-file.d.ts +0 -2
- package/src/file-helpers.ts +0 -73
- package/src/frameworks.ts +0 -114
- package/src/integrations/git.ts +0 -7
- package/src/integrations/shadcn.ts +0 -44
- package/src/package-json.ts +0 -62
- package/src/template-file.ts +0 -146
- package/tests/file-helper.test.ts +0 -37
- package/tests/package-manager.test.ts +0 -154
package/src/mcp.ts
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
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
|
+
|
|
7
|
+
import { createApp } from './create-app.js'
|
|
8
|
+
import { finalizeAddOns } from './add-ons.js'
|
|
9
|
+
import { createDefaultEnvironment } from './environment.js'
|
|
10
|
+
|
|
11
|
+
import type { TemplateOptions } from './types.js'
|
|
12
|
+
|
|
13
|
+
const tanStackReactAddOns = [
|
|
14
|
+
{
|
|
15
|
+
id: 'clerk',
|
|
16
|
+
description: 'Enable authentication with Clerk',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: 'convex',
|
|
20
|
+
description: 'Enable a database using Convex',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: 'form',
|
|
24
|
+
description: 'Form handling library',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'netlify',
|
|
28
|
+
description: 'Enable deployments to Netlify',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: 'sentry',
|
|
32
|
+
description: 'Enable Sentry error tracking',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'shadcn',
|
|
36
|
+
description: 'Enable integration of the Shadcn UI component library',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 'start',
|
|
40
|
+
description:
|
|
41
|
+
'Set this if you want a TanStack Start application that supports server functions or APIs',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: 'tanstack-query',
|
|
45
|
+
description: 'Enable TanStack Query for data fetching',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'store',
|
|
49
|
+
description: 'Enable the TanStack Store state management library',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: 'tanchat',
|
|
53
|
+
description: 'Add an AI chatbot example to the application',
|
|
54
|
+
},
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
const tanStackSolidAddOns = [
|
|
58
|
+
{
|
|
59
|
+
id: 'solid-ui',
|
|
60
|
+
description: 'Enable integration of the Solid UI component library',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: 'form',
|
|
64
|
+
description: 'Form handling library',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: 'sentry',
|
|
68
|
+
description: 'Enable Sentry error tracking',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: 'store',
|
|
72
|
+
description: 'Enable the TanStack Store state management library',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: 'start',
|
|
76
|
+
description:
|
|
77
|
+
'Set this if you want a TanStack Start application that supports server functions or APIs',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'tanstack-query',
|
|
81
|
+
description: 'Enable TanStack Query for data fetching',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: 'tanchat',
|
|
85
|
+
description: 'Add an AI chatbot example to the application',
|
|
86
|
+
},
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
function createServer({
|
|
90
|
+
appName,
|
|
91
|
+
forcedAddOns = [],
|
|
92
|
+
name,
|
|
93
|
+
}: {
|
|
94
|
+
appName?: string
|
|
95
|
+
forcedAddOns?: Array<string>
|
|
96
|
+
name?: string
|
|
97
|
+
}) {
|
|
98
|
+
const server = new McpServer({
|
|
99
|
+
name: `${appName} Application Builder`,
|
|
100
|
+
version: '1.0.0',
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
server.tool('listTanStackReactAddOns', {}, () => {
|
|
104
|
+
return {
|
|
105
|
+
content: [{ type: 'text', text: JSON.stringify(tanStackReactAddOns) }],
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
server.tool(
|
|
110
|
+
'createTanStackReactApplication',
|
|
111
|
+
{
|
|
112
|
+
projectName: z
|
|
113
|
+
.string()
|
|
114
|
+
.describe(
|
|
115
|
+
'The package.json module name of the application (will also be the directory name)',
|
|
116
|
+
),
|
|
117
|
+
cwd: z.string().describe('The directory to create the application in'),
|
|
118
|
+
addOns: z
|
|
119
|
+
.array(
|
|
120
|
+
z.enum([
|
|
121
|
+
'clerk',
|
|
122
|
+
'convex',
|
|
123
|
+
'form',
|
|
124
|
+
'netlify',
|
|
125
|
+
'sentry',
|
|
126
|
+
'shadcn',
|
|
127
|
+
'start',
|
|
128
|
+
'store',
|
|
129
|
+
'tanstack-query',
|
|
130
|
+
'tanchat',
|
|
131
|
+
]),
|
|
132
|
+
)
|
|
133
|
+
.describe('The IDs of the add-ons to install'),
|
|
134
|
+
targetDir: z
|
|
135
|
+
.string()
|
|
136
|
+
.describe(
|
|
137
|
+
'The directory to create the application in. Use the absolute path of the directory you want the application to be created in',
|
|
138
|
+
),
|
|
139
|
+
},
|
|
140
|
+
async ({ projectName, addOns, cwd, targetDir }) => {
|
|
141
|
+
try {
|
|
142
|
+
process.chdir(cwd)
|
|
143
|
+
const chosenAddOns = await finalizeAddOns(
|
|
144
|
+
'react',
|
|
145
|
+
'file-router',
|
|
146
|
+
Array.from(
|
|
147
|
+
new Set([...(addOns as unknown as Array<string>), ...forcedAddOns]),
|
|
148
|
+
),
|
|
149
|
+
)
|
|
150
|
+
await createApp(
|
|
151
|
+
{
|
|
152
|
+
projectName: projectName.replace(/^\//, './'),
|
|
153
|
+
framework: 'react',
|
|
154
|
+
typescript: true,
|
|
155
|
+
tailwind: true,
|
|
156
|
+
packageManager: 'pnpm',
|
|
157
|
+
toolchain: 'none',
|
|
158
|
+
mode: 'file-router',
|
|
159
|
+
addOns: true,
|
|
160
|
+
chosenAddOns,
|
|
161
|
+
git: true,
|
|
162
|
+
variableValues: {},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
silent: true,
|
|
166
|
+
environment: createDefaultEnvironment(),
|
|
167
|
+
name,
|
|
168
|
+
cwd: targetDir,
|
|
169
|
+
},
|
|
170
|
+
)
|
|
171
|
+
return {
|
|
172
|
+
content: [{ type: 'text', text: 'Application created successfully' }],
|
|
173
|
+
}
|
|
174
|
+
} catch (error) {
|
|
175
|
+
return {
|
|
176
|
+
content: [
|
|
177
|
+
{ type: 'text', text: `Error creating application: ${error}` },
|
|
178
|
+
],
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
server.tool('listTanStackSolidAddOns', {}, () => {
|
|
185
|
+
return {
|
|
186
|
+
content: [{ type: 'text', text: JSON.stringify(tanStackSolidAddOns) }],
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
server.tool(
|
|
191
|
+
'createTanStackSolidApplication',
|
|
192
|
+
{
|
|
193
|
+
projectName: z
|
|
194
|
+
.string()
|
|
195
|
+
.describe(
|
|
196
|
+
'The package.json module name of the application (will also be the directory name)',
|
|
197
|
+
),
|
|
198
|
+
cwd: z.string().describe('The directory to create the application in'),
|
|
199
|
+
addOns: z
|
|
200
|
+
.array(
|
|
201
|
+
z.enum([
|
|
202
|
+
'solid-ui',
|
|
203
|
+
'form',
|
|
204
|
+
'sentry',
|
|
205
|
+
'store',
|
|
206
|
+
'tanstack-query',
|
|
207
|
+
'tanchat',
|
|
208
|
+
]),
|
|
209
|
+
)
|
|
210
|
+
.describe('The IDs of the add-ons to install'),
|
|
211
|
+
targetDir: z
|
|
212
|
+
.string()
|
|
213
|
+
.describe(
|
|
214
|
+
'The directory to create the application in. Use the absolute path of the directory you want the application to be created in',
|
|
215
|
+
),
|
|
216
|
+
},
|
|
217
|
+
async ({ projectName, addOns, cwd, targetDir }) => {
|
|
218
|
+
try {
|
|
219
|
+
process.chdir(cwd)
|
|
220
|
+
const chosenAddOns = await finalizeAddOns(
|
|
221
|
+
'solid',
|
|
222
|
+
'file-router',
|
|
223
|
+
Array.from(
|
|
224
|
+
new Set([...(addOns as unknown as Array<string>), ...forcedAddOns]),
|
|
225
|
+
),
|
|
226
|
+
)
|
|
227
|
+
await createApp(
|
|
228
|
+
{
|
|
229
|
+
projectName: projectName.replace(/^\//, './'),
|
|
230
|
+
framework: 'solid',
|
|
231
|
+
typescript: true,
|
|
232
|
+
tailwind: true,
|
|
233
|
+
packageManager: 'pnpm',
|
|
234
|
+
toolchain: 'none',
|
|
235
|
+
mode: 'file-router',
|
|
236
|
+
addOns: true,
|
|
237
|
+
chosenAddOns,
|
|
238
|
+
git: true,
|
|
239
|
+
variableValues: {},
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
silent: true,
|
|
243
|
+
environment: createDefaultEnvironment(),
|
|
244
|
+
name,
|
|
245
|
+
cwd: targetDir,
|
|
246
|
+
},
|
|
247
|
+
)
|
|
248
|
+
return {
|
|
249
|
+
content: [{ type: 'text', text: 'Application created successfully' }],
|
|
250
|
+
}
|
|
251
|
+
} catch (error) {
|
|
252
|
+
return {
|
|
253
|
+
content: [
|
|
254
|
+
{ type: 'text', text: `Error creating application: ${error}` },
|
|
255
|
+
],
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
return server
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export default async function runServer(
|
|
265
|
+
sse: boolean,
|
|
266
|
+
{
|
|
267
|
+
forcedAddOns,
|
|
268
|
+
appName,
|
|
269
|
+
name,
|
|
270
|
+
}: {
|
|
271
|
+
forcedMode?: TemplateOptions
|
|
272
|
+
forcedAddOns?: Array<string>
|
|
273
|
+
appName?: string
|
|
274
|
+
name?: string
|
|
275
|
+
},
|
|
276
|
+
) {
|
|
277
|
+
let transport: SSEServerTransport | null = null
|
|
278
|
+
|
|
279
|
+
const server = createServer({ appName, forcedAddOns, name })
|
|
280
|
+
if (sse) {
|
|
281
|
+
const app = express()
|
|
282
|
+
|
|
283
|
+
app.get('/sse', (req, res) => {
|
|
284
|
+
transport = new SSEServerTransport('/messages', res)
|
|
285
|
+
server.connect(transport)
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
app.post('/messages', (req, res) => {
|
|
289
|
+
if (transport) {
|
|
290
|
+
transport.handlePostMessage(req, res)
|
|
291
|
+
}
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
const port = process.env.PORT || 8080
|
|
295
|
+
app.listen(port, () => {
|
|
296
|
+
console.log(`Server is running on port http://localhost:${port}/sse`)
|
|
297
|
+
})
|
|
298
|
+
} else {
|
|
299
|
+
const transport = new StdioServerTransport()
|
|
300
|
+
await server.connect(transport)
|
|
301
|
+
}
|
|
302
|
+
}
|
package/src/options.ts
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cancel,
|
|
3
|
+
confirm,
|
|
4
|
+
isCancel,
|
|
5
|
+
multiselect,
|
|
6
|
+
select,
|
|
7
|
+
text,
|
|
8
|
+
} from '@clack/prompts'
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
DEFAULT_PACKAGE_MANAGER,
|
|
12
|
+
SUPPORTED_PACKAGE_MANAGERS,
|
|
13
|
+
getPackageManager,
|
|
14
|
+
} from './package-manager.js'
|
|
15
|
+
import { DEFAULT_TOOLCHAIN, SUPPORTED_TOOLCHAINS } from './toolchain.js'
|
|
16
|
+
import { CODE_ROUTER, DEFAULT_FRAMEWORK, FILE_ROUTER } from './constants.js'
|
|
17
|
+
import { finalizeAddOns, getAllAddOns, loadRemoteAddOn } from './add-ons.js'
|
|
18
|
+
|
|
19
|
+
import type {
|
|
20
|
+
AddOn,
|
|
21
|
+
CliOptions,
|
|
22
|
+
Mode,
|
|
23
|
+
Options,
|
|
24
|
+
Overlay,
|
|
25
|
+
TemplateOptions,
|
|
26
|
+
Variable,
|
|
27
|
+
} from './types.js'
|
|
28
|
+
|
|
29
|
+
// If all CLI options are provided, use them directly
|
|
30
|
+
export async function normalizeOptions(
|
|
31
|
+
cliOptions: CliOptions,
|
|
32
|
+
forcedMode?: Mode,
|
|
33
|
+
forcedAddOns?: Array<string>,
|
|
34
|
+
): Promise<Options | undefined> {
|
|
35
|
+
// in some cases, if you use windows/powershell, the argument for addons
|
|
36
|
+
// if sepparated by comma is not really passed as an array, but as a string
|
|
37
|
+
// with spaces, We need to normalize this edge case.
|
|
38
|
+
if (Array.isArray(cliOptions.addOns) && cliOptions.addOns.length === 1) {
|
|
39
|
+
const parseSeparatedArgs = cliOptions.addOns[0].split(' ')
|
|
40
|
+
if (parseSeparatedArgs.length > 1) {
|
|
41
|
+
cliOptions.addOns = parseSeparatedArgs
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (cliOptions.projectName) {
|
|
46
|
+
let typescript =
|
|
47
|
+
cliOptions.template === 'typescript' ||
|
|
48
|
+
cliOptions.template === 'file-router' ||
|
|
49
|
+
cliOptions.framework === 'solid'
|
|
50
|
+
|
|
51
|
+
let tailwind = !!cliOptions.tailwind
|
|
52
|
+
if (cliOptions.framework === 'solid') {
|
|
53
|
+
tailwind = true
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let mode: typeof FILE_ROUTER | typeof CODE_ROUTER =
|
|
57
|
+
cliOptions.template === 'file-router' ? FILE_ROUTER : CODE_ROUTER
|
|
58
|
+
|
|
59
|
+
const overlay = cliOptions.overlay
|
|
60
|
+
? ((await loadRemoteAddOn(cliOptions.overlay)) as Overlay)
|
|
61
|
+
: undefined
|
|
62
|
+
|
|
63
|
+
if (overlay) {
|
|
64
|
+
tailwind = overlay.tailwind
|
|
65
|
+
typescript = overlay.typescript
|
|
66
|
+
cliOptions.framework = overlay.framework
|
|
67
|
+
mode = overlay.mode
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let addOns = false
|
|
71
|
+
let chosenAddOns: Array<AddOn> = []
|
|
72
|
+
if (
|
|
73
|
+
Array.isArray(cliOptions.addOns) ||
|
|
74
|
+
overlay?.dependsOn ||
|
|
75
|
+
forcedAddOns
|
|
76
|
+
) {
|
|
77
|
+
addOns = true
|
|
78
|
+
let finalAddOns = Array.from(
|
|
79
|
+
new Set([...(overlay?.dependsOn || []), ...(forcedAddOns || [])]),
|
|
80
|
+
)
|
|
81
|
+
if (cliOptions.addOns && Array.isArray(cliOptions.addOns)) {
|
|
82
|
+
finalAddOns = Array.from(
|
|
83
|
+
new Set([
|
|
84
|
+
...(forcedAddOns || []),
|
|
85
|
+
...finalAddOns,
|
|
86
|
+
...cliOptions.addOns,
|
|
87
|
+
]),
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
chosenAddOns = await finalizeAddOns(
|
|
91
|
+
cliOptions.framework || DEFAULT_FRAMEWORK,
|
|
92
|
+
forcedMode || cliOptions.template === 'file-router'
|
|
93
|
+
? FILE_ROUTER
|
|
94
|
+
: CODE_ROUTER,
|
|
95
|
+
finalAddOns,
|
|
96
|
+
)
|
|
97
|
+
tailwind = true
|
|
98
|
+
typescript = true
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
framework: cliOptions.framework || 'react',
|
|
103
|
+
projectName: cliOptions.projectName,
|
|
104
|
+
typescript,
|
|
105
|
+
tailwind,
|
|
106
|
+
packageManager:
|
|
107
|
+
cliOptions.packageManager ||
|
|
108
|
+
getPackageManager() ||
|
|
109
|
+
DEFAULT_PACKAGE_MANAGER,
|
|
110
|
+
toolchain: cliOptions.toolchain || DEFAULT_TOOLCHAIN,
|
|
111
|
+
mode,
|
|
112
|
+
git: !!cliOptions.git,
|
|
113
|
+
addOns,
|
|
114
|
+
chosenAddOns,
|
|
115
|
+
variableValues: {},
|
|
116
|
+
overlay,
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function collectVariables(
|
|
122
|
+
variables: Array<Variable>,
|
|
123
|
+
): Promise<Record<string, string | number | boolean>> {
|
|
124
|
+
const responses: Record<string, string | number | boolean> = {}
|
|
125
|
+
for (const variable of variables) {
|
|
126
|
+
if (variable.type === 'string') {
|
|
127
|
+
const response = await text({
|
|
128
|
+
message: variable.description,
|
|
129
|
+
initialValue: variable.default,
|
|
130
|
+
})
|
|
131
|
+
if (isCancel(response)) {
|
|
132
|
+
cancel('Operation cancelled.')
|
|
133
|
+
process.exit(0)
|
|
134
|
+
}
|
|
135
|
+
responses[variable.name] = response
|
|
136
|
+
} else if (variable.type === 'number') {
|
|
137
|
+
const response = await text({
|
|
138
|
+
message: variable.description,
|
|
139
|
+
initialValue: variable.default.toString(),
|
|
140
|
+
})
|
|
141
|
+
if (isCancel(response)) {
|
|
142
|
+
cancel('Operation cancelled.')
|
|
143
|
+
process.exit(0)
|
|
144
|
+
}
|
|
145
|
+
responses[variable.name] = Number(response)
|
|
146
|
+
} else {
|
|
147
|
+
const response = await confirm({
|
|
148
|
+
message: variable.description,
|
|
149
|
+
initialValue: variable.default === true,
|
|
150
|
+
})
|
|
151
|
+
if (isCancel(response)) {
|
|
152
|
+
cancel('Operation cancelled.')
|
|
153
|
+
process.exit(0)
|
|
154
|
+
}
|
|
155
|
+
responses[variable.name] = response
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return responses
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export async function promptForOptions(
|
|
162
|
+
cliOptions: CliOptions,
|
|
163
|
+
{
|
|
164
|
+
forcedAddOns = [],
|
|
165
|
+
forcedMode,
|
|
166
|
+
}: {
|
|
167
|
+
forcedAddOns?: Array<string>
|
|
168
|
+
forcedMode?: TemplateOptions
|
|
169
|
+
},
|
|
170
|
+
): Promise<Required<Options>> {
|
|
171
|
+
const options = {} as Required<Options>
|
|
172
|
+
|
|
173
|
+
options.framework = cliOptions.framework || DEFAULT_FRAMEWORK
|
|
174
|
+
if (options.framework === 'solid') {
|
|
175
|
+
options.typescript = true
|
|
176
|
+
options.tailwind = true
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (cliOptions.addOns) {
|
|
180
|
+
options.typescript = true
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (!cliOptions.projectName) {
|
|
184
|
+
const value = await text({
|
|
185
|
+
message: 'What would you like to name your project?',
|
|
186
|
+
defaultValue: 'my-app',
|
|
187
|
+
validate(value) {
|
|
188
|
+
if (!value) {
|
|
189
|
+
return 'Please enter a name'
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
})
|
|
193
|
+
if (isCancel(value)) {
|
|
194
|
+
cancel('Operation cancelled.')
|
|
195
|
+
process.exit(0)
|
|
196
|
+
}
|
|
197
|
+
options.projectName = value
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Router type selection
|
|
201
|
+
if (!cliOptions.template && !forcedMode) {
|
|
202
|
+
const routerType = await select({
|
|
203
|
+
message: 'Select the router type:',
|
|
204
|
+
options: [
|
|
205
|
+
{
|
|
206
|
+
value: FILE_ROUTER,
|
|
207
|
+
label: 'File Router - File-based routing structure',
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
value: CODE_ROUTER,
|
|
211
|
+
label: 'Code Router - Traditional code-based routing',
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
initialValue: FILE_ROUTER,
|
|
215
|
+
})
|
|
216
|
+
if (isCancel(routerType)) {
|
|
217
|
+
cancel('Operation cancelled.')
|
|
218
|
+
process.exit(0)
|
|
219
|
+
}
|
|
220
|
+
options.mode = routerType as typeof CODE_ROUTER | typeof FILE_ROUTER
|
|
221
|
+
} else if (forcedMode) {
|
|
222
|
+
options.mode = forcedMode === 'file-router' ? FILE_ROUTER : CODE_ROUTER
|
|
223
|
+
options.typescript = options.mode === FILE_ROUTER
|
|
224
|
+
} else {
|
|
225
|
+
options.mode =
|
|
226
|
+
cliOptions.template === 'file-router' ? FILE_ROUTER : CODE_ROUTER
|
|
227
|
+
if (options.mode === FILE_ROUTER) {
|
|
228
|
+
options.typescript = true
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// TypeScript selection (if using Code Router)
|
|
233
|
+
if (!options.typescript) {
|
|
234
|
+
if (options.mode === CODE_ROUTER) {
|
|
235
|
+
const typescriptEnable = await confirm({
|
|
236
|
+
message: 'Would you like to use TypeScript?',
|
|
237
|
+
initialValue: true,
|
|
238
|
+
})
|
|
239
|
+
if (isCancel(typescriptEnable)) {
|
|
240
|
+
cancel('Operation cancelled.')
|
|
241
|
+
process.exit(0)
|
|
242
|
+
}
|
|
243
|
+
options.typescript = typescriptEnable
|
|
244
|
+
} else {
|
|
245
|
+
options.typescript = true
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Tailwind selection
|
|
250
|
+
if (!cliOptions.tailwind && options.framework === 'react') {
|
|
251
|
+
const tailwind = await confirm({
|
|
252
|
+
message: 'Would you like to use Tailwind CSS?',
|
|
253
|
+
initialValue: true,
|
|
254
|
+
})
|
|
255
|
+
if (isCancel(tailwind)) {
|
|
256
|
+
cancel('Operation cancelled.')
|
|
257
|
+
process.exit(0)
|
|
258
|
+
}
|
|
259
|
+
options.tailwind = tailwind
|
|
260
|
+
} else {
|
|
261
|
+
options.tailwind = options.framework === 'solid' || !!cliOptions.tailwind
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Package manager selection
|
|
265
|
+
if (cliOptions.packageManager === undefined) {
|
|
266
|
+
const detectedPackageManager = getPackageManager()
|
|
267
|
+
if (!detectedPackageManager) {
|
|
268
|
+
const pm = await select({
|
|
269
|
+
message: 'Select package manager:',
|
|
270
|
+
options: SUPPORTED_PACKAGE_MANAGERS.map((pm) => ({
|
|
271
|
+
value: pm,
|
|
272
|
+
label: pm,
|
|
273
|
+
})),
|
|
274
|
+
initialValue: DEFAULT_PACKAGE_MANAGER,
|
|
275
|
+
})
|
|
276
|
+
if (isCancel(pm)) {
|
|
277
|
+
cancel('Operation cancelled.')
|
|
278
|
+
process.exit(0)
|
|
279
|
+
}
|
|
280
|
+
options.packageManager = pm
|
|
281
|
+
} else {
|
|
282
|
+
options.packageManager = detectedPackageManager
|
|
283
|
+
}
|
|
284
|
+
} else {
|
|
285
|
+
options.packageManager = cliOptions.packageManager
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Toolchain selection
|
|
289
|
+
if (cliOptions.toolchain === undefined) {
|
|
290
|
+
const tc = await select({
|
|
291
|
+
message: 'Select toolchain',
|
|
292
|
+
options: SUPPORTED_TOOLCHAINS.map((tc) => ({
|
|
293
|
+
value: tc,
|
|
294
|
+
label: tc,
|
|
295
|
+
})),
|
|
296
|
+
initialValue: DEFAULT_TOOLCHAIN,
|
|
297
|
+
})
|
|
298
|
+
if (isCancel(tc)) {
|
|
299
|
+
cancel('Operation cancelled.')
|
|
300
|
+
process.exit(0)
|
|
301
|
+
}
|
|
302
|
+
options.toolchain = tc
|
|
303
|
+
} else {
|
|
304
|
+
options.toolchain = cliOptions.toolchain
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
options.chosenAddOns = []
|
|
308
|
+
if (Array.isArray(cliOptions.addOns)) {
|
|
309
|
+
options.chosenAddOns = await finalizeAddOns(
|
|
310
|
+
options.framework,
|
|
311
|
+
options.mode,
|
|
312
|
+
Array.from(new Set([...cliOptions.addOns, ...forcedAddOns])),
|
|
313
|
+
)
|
|
314
|
+
options.tailwind = true
|
|
315
|
+
} else if (cliOptions.addOns) {
|
|
316
|
+
// Select any add-ons
|
|
317
|
+
const allAddOns = await getAllAddOns(options.framework, options.mode)
|
|
318
|
+
const addOns = allAddOns.filter((addOn) => addOn.type === 'add-on')
|
|
319
|
+
let selectedAddOns: Array<string> = []
|
|
320
|
+
if (options.typescript && addOns.length > 0) {
|
|
321
|
+
const value = await multiselect({
|
|
322
|
+
message: 'What add-ons would you like for your project:',
|
|
323
|
+
options: addOns
|
|
324
|
+
.filter((addOn) => !forcedAddOns.includes(addOn.id))
|
|
325
|
+
.map((addOn) => ({
|
|
326
|
+
value: addOn.id,
|
|
327
|
+
label: addOn.name,
|
|
328
|
+
hint: addOn.description,
|
|
329
|
+
})),
|
|
330
|
+
required: false,
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
if (isCancel(value)) {
|
|
334
|
+
cancel('Operation cancelled.')
|
|
335
|
+
process.exit(0)
|
|
336
|
+
}
|
|
337
|
+
selectedAddOns = value
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Select any examples
|
|
341
|
+
let selectedExamples: Array<string> = []
|
|
342
|
+
const examples = allAddOns.filter((addOn) => addOn.type === 'example')
|
|
343
|
+
if (options.typescript && examples.length > 0) {
|
|
344
|
+
const value = await multiselect({
|
|
345
|
+
message: 'Would you like any examples?',
|
|
346
|
+
options: examples
|
|
347
|
+
.filter((addOn) => !forcedAddOns.includes(addOn.id))
|
|
348
|
+
.map((addOn) => ({
|
|
349
|
+
value: addOn.id,
|
|
350
|
+
label: addOn.name,
|
|
351
|
+
hint: addOn.description,
|
|
352
|
+
})),
|
|
353
|
+
required: false,
|
|
354
|
+
})
|
|
355
|
+
|
|
356
|
+
if (isCancel(value)) {
|
|
357
|
+
cancel('Operation cancelled.')
|
|
358
|
+
process.exit(0)
|
|
359
|
+
}
|
|
360
|
+
selectedExamples = value
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (
|
|
364
|
+
selectedAddOns.length > 0 ||
|
|
365
|
+
selectedExamples.length > 0 ||
|
|
366
|
+
forcedAddOns.length > 0
|
|
367
|
+
) {
|
|
368
|
+
options.chosenAddOns = await finalizeAddOns(
|
|
369
|
+
options.framework,
|
|
370
|
+
options.mode,
|
|
371
|
+
Array.from(
|
|
372
|
+
new Set([...selectedAddOns, ...selectedExamples, ...forcedAddOns]),
|
|
373
|
+
),
|
|
374
|
+
)
|
|
375
|
+
options.tailwind = true
|
|
376
|
+
}
|
|
377
|
+
} else if (forcedAddOns.length > 0) {
|
|
378
|
+
options.chosenAddOns = await finalizeAddOns(
|
|
379
|
+
options.framework,
|
|
380
|
+
options.mode,
|
|
381
|
+
forcedAddOns,
|
|
382
|
+
)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Collect variables
|
|
386
|
+
const variables: Array<Variable> = []
|
|
387
|
+
for (const addOn of options.chosenAddOns) {
|
|
388
|
+
for (const variable of addOn.variables ?? []) {
|
|
389
|
+
variables.push(variable)
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
options.variableValues = await collectVariables(variables)
|
|
393
|
+
|
|
394
|
+
// Git selection
|
|
395
|
+
if (cliOptions.git === undefined) {
|
|
396
|
+
const git = await confirm({
|
|
397
|
+
message: 'Would you like to initialize a new git repository?',
|
|
398
|
+
initialValue: true,
|
|
399
|
+
})
|
|
400
|
+
if (isCancel(git)) {
|
|
401
|
+
cancel('Operation cancelled.')
|
|
402
|
+
process.exit(0)
|
|
403
|
+
}
|
|
404
|
+
options.git = git
|
|
405
|
+
} else {
|
|
406
|
+
options.git = !!cliOptions.git
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
return options
|
|
410
|
+
}
|