@tanstack/cta-cli 0.10.0-alpha.19 → 0.10.0-alpha.21
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/cli.js +82 -33
- package/dist/command-line.js +75 -0
- package/dist/mcp.js +170 -0
- package/dist/options.js +40 -331
- package/dist/types/cli.d.ts +3 -1
- package/dist/types/command-line.d.ts +3 -0
- package/dist/types/mcp.d.ts +7 -0
- package/dist/types/options.d.ts +2 -3
- package/dist/types/types.d.ts +3 -1
- package/dist/types/ui-environment.d.ts +1 -1
- package/dist/types/ui-prompts.d.ts +10 -0
- package/dist/types/utils.d.ts +3 -0
- package/dist/ui-environment.js +45 -42
- package/dist/ui-prompts.js +140 -0
- package/dist/utils.js +7 -0
- package/package.json +10 -6
- package/src/cli.ts +102 -46
- package/src/command-line.ts +111 -0
- package/src/mcp.ts +247 -0
- package/src/options.ts +69 -395
- package/src/types.ts +4 -1
- package/src/ui-environment.ts +54 -44
- package/src/ui-prompts.ts +187 -0
- package/src/utils.ts +11 -0
- package/tests/command-line.test.ts +205 -0
- package/tests/index.test.ts +9 -0
- package/tests/options.test.ts +287 -0
- package/tests/setupVitest.ts +6 -0
- package/tests/ui-environment.test.ts +97 -0
- package/tests/ui-prompts.test.ts +233 -0
- package/vitest.config.js +7 -0
package/src/mcp.ts
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
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 {
|
|
8
|
+
createApp,
|
|
9
|
+
createDefaultEnvironment,
|
|
10
|
+
finalizeAddOns,
|
|
11
|
+
getFrameworkById,
|
|
12
|
+
} from '@tanstack/cta-engine'
|
|
13
|
+
|
|
14
|
+
import type { Mode } from '@tanstack/cta-engine'
|
|
15
|
+
|
|
16
|
+
function createServer({
|
|
17
|
+
appName,
|
|
18
|
+
forcedAddOns = [],
|
|
19
|
+
}: {
|
|
20
|
+
appName?: string
|
|
21
|
+
forcedAddOns?: Array<string>
|
|
22
|
+
name?: string
|
|
23
|
+
}) {
|
|
24
|
+
const server = new McpServer({
|
|
25
|
+
name: `${appName} Application Builder`,
|
|
26
|
+
version: '1.0.0',
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
server.tool(
|
|
30
|
+
'listTanStackReactAddOns',
|
|
31
|
+
'List the available add-ons for creating TanStack React applications',
|
|
32
|
+
{},
|
|
33
|
+
() => {
|
|
34
|
+
const framework = getFrameworkById('react-cra')!
|
|
35
|
+
return {
|
|
36
|
+
content: [
|
|
37
|
+
{
|
|
38
|
+
type: 'text',
|
|
39
|
+
text: JSON.stringify(
|
|
40
|
+
framework
|
|
41
|
+
.getAddOns()
|
|
42
|
+
.filter((addOn) => addOn.modes.includes('file-router'))
|
|
43
|
+
.map((addOn) => ({
|
|
44
|
+
id: addOn.id,
|
|
45
|
+
description: addOn.description,
|
|
46
|
+
})),
|
|
47
|
+
),
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
server.tool(
|
|
55
|
+
'createTanStackReactApplication',
|
|
56
|
+
'Create a new TanStack React application',
|
|
57
|
+
{
|
|
58
|
+
projectName: z
|
|
59
|
+
.string()
|
|
60
|
+
.describe(
|
|
61
|
+
'The package.json module name of the application (will also be the directory name)',
|
|
62
|
+
),
|
|
63
|
+
cwd: z.string().describe('The directory to create the application in'),
|
|
64
|
+
addOns: z.array(z.string()).describe('The IDs of the add-ons to install'),
|
|
65
|
+
targetDir: z
|
|
66
|
+
.string()
|
|
67
|
+
.describe(
|
|
68
|
+
'The directory to create the application in. Use the absolute path of the directory you want the application to be created in',
|
|
69
|
+
),
|
|
70
|
+
},
|
|
71
|
+
async ({ projectName, addOns, cwd, targetDir }) => {
|
|
72
|
+
const framework = getFrameworkById('react-cra')!
|
|
73
|
+
try {
|
|
74
|
+
process.chdir(cwd)
|
|
75
|
+
try {
|
|
76
|
+
const chosenAddOns = await finalizeAddOns(
|
|
77
|
+
framework,
|
|
78
|
+
'file-router',
|
|
79
|
+
Array.from(
|
|
80
|
+
new Set([
|
|
81
|
+
...(addOns as unknown as Array<string>),
|
|
82
|
+
...forcedAddOns,
|
|
83
|
+
]),
|
|
84
|
+
),
|
|
85
|
+
)
|
|
86
|
+
await createApp(createDefaultEnvironment(), {
|
|
87
|
+
projectName: projectName.replace(/^\//, './'),
|
|
88
|
+
targetDir,
|
|
89
|
+
framework,
|
|
90
|
+
typescript: true,
|
|
91
|
+
tailwind: true,
|
|
92
|
+
packageManager: 'pnpm',
|
|
93
|
+
mode: 'file-router',
|
|
94
|
+
chosenAddOns,
|
|
95
|
+
git: true,
|
|
96
|
+
})
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error(error)
|
|
99
|
+
return {
|
|
100
|
+
content: [
|
|
101
|
+
{ type: 'text', text: `Error creating application: ${error}` },
|
|
102
|
+
],
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
content: [{ type: 'text', text: 'Application created successfully' }],
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
return {
|
|
110
|
+
content: [
|
|
111
|
+
{ type: 'text', text: `Error creating application: ${error}` },
|
|
112
|
+
],
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
server.tool(
|
|
119
|
+
'listTanStackSolidAddOns',
|
|
120
|
+
'List the available add-ons for creating TanStack Solid applications',
|
|
121
|
+
{},
|
|
122
|
+
() => {
|
|
123
|
+
const framework = getFrameworkById('solid')!
|
|
124
|
+
return {
|
|
125
|
+
content: [
|
|
126
|
+
{
|
|
127
|
+
type: 'text',
|
|
128
|
+
text: JSON.stringify(
|
|
129
|
+
framework
|
|
130
|
+
.getAddOns()
|
|
131
|
+
.filter((addOn) => addOn.modes.includes('file-router'))
|
|
132
|
+
.map((addOn) => ({
|
|
133
|
+
id: addOn.id,
|
|
134
|
+
description: addOn.description,
|
|
135
|
+
})),
|
|
136
|
+
),
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
server.tool(
|
|
144
|
+
'createTanStackSolidApplication',
|
|
145
|
+
'Create a new TanStack Solid application',
|
|
146
|
+
{
|
|
147
|
+
projectName: z
|
|
148
|
+
.string()
|
|
149
|
+
.describe(
|
|
150
|
+
'The package.json module name of the application (will also be the directory name)',
|
|
151
|
+
),
|
|
152
|
+
cwd: z.string().describe('The directory to create the application in'),
|
|
153
|
+
addOns: z.array(z.string()).describe('The IDs of the add-ons to install'),
|
|
154
|
+
targetDir: z
|
|
155
|
+
.string()
|
|
156
|
+
.describe(
|
|
157
|
+
'The directory to create the application in. Use the absolute path of the directory you want the application to be created in',
|
|
158
|
+
),
|
|
159
|
+
},
|
|
160
|
+
async ({ projectName, addOns, cwd, targetDir }) => {
|
|
161
|
+
const framework = getFrameworkById('solid')!
|
|
162
|
+
try {
|
|
163
|
+
process.chdir(cwd)
|
|
164
|
+
try {
|
|
165
|
+
const chosenAddOns = await finalizeAddOns(
|
|
166
|
+
framework,
|
|
167
|
+
'file-router',
|
|
168
|
+
Array.from(
|
|
169
|
+
new Set([
|
|
170
|
+
...(addOns as unknown as Array<string>),
|
|
171
|
+
...forcedAddOns,
|
|
172
|
+
]),
|
|
173
|
+
),
|
|
174
|
+
)
|
|
175
|
+
await createApp(createDefaultEnvironment(), {
|
|
176
|
+
projectName: projectName.replace(/^\//, './'),
|
|
177
|
+
targetDir,
|
|
178
|
+
framework,
|
|
179
|
+
typescript: true,
|
|
180
|
+
tailwind: true,
|
|
181
|
+
packageManager: 'pnpm',
|
|
182
|
+
mode: 'file-router',
|
|
183
|
+
chosenAddOns,
|
|
184
|
+
git: true,
|
|
185
|
+
})
|
|
186
|
+
} catch (error) {
|
|
187
|
+
return {
|
|
188
|
+
content: [
|
|
189
|
+
{ type: 'text', text: `Error creating application: ${error}` },
|
|
190
|
+
],
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
content: [{ type: 'text', text: 'Application created successfully' }],
|
|
195
|
+
}
|
|
196
|
+
} catch (error) {
|
|
197
|
+
return {
|
|
198
|
+
content: [
|
|
199
|
+
{ type: 'text', text: `Error creating application: ${error}` },
|
|
200
|
+
],
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
return server
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export async function runMCPServer(
|
|
210
|
+
sse: boolean,
|
|
211
|
+
{
|
|
212
|
+
forcedAddOns,
|
|
213
|
+
appName,
|
|
214
|
+
name,
|
|
215
|
+
}: {
|
|
216
|
+
forcedMode?: Mode
|
|
217
|
+
forcedAddOns?: Array<string>
|
|
218
|
+
appName?: string
|
|
219
|
+
name?: string
|
|
220
|
+
},
|
|
221
|
+
) {
|
|
222
|
+
let transport: SSEServerTransport | null = null
|
|
223
|
+
|
|
224
|
+
const server = createServer({ appName, forcedAddOns, name })
|
|
225
|
+
if (sse) {
|
|
226
|
+
const app = express()
|
|
227
|
+
|
|
228
|
+
app.get('/sse', (req, res) => {
|
|
229
|
+
transport = new SSEServerTransport('/messages', res)
|
|
230
|
+
server.connect(transport)
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
app.post('/messages', (req, res) => {
|
|
234
|
+
if (transport) {
|
|
235
|
+
transport.handlePostMessage(req, res)
|
|
236
|
+
}
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
const port = process.env.PORT || 8080
|
|
240
|
+
app.listen(port, () => {
|
|
241
|
+
console.log(`Server is running on port http://localhost:${port}/sse`)
|
|
242
|
+
})
|
|
243
|
+
} else {
|
|
244
|
+
const transport = new StdioServerTransport()
|
|
245
|
+
await server.connect(transport)
|
|
246
|
+
}
|
|
247
|
+
}
|