@tanstack/cta-engine 0.10.0-alpha.10 → 0.10.0-alpha.11
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 +3 -4
- package/dist/cli.js +14 -8
- package/dist/create-app.js +2 -2
- package/dist/mcp.js +128 -112
- package/dist/types/add-ons.d.ts +5 -2
- package/dist/types/cli.d.ts +2 -1
- package/dist/types/create-app.d.ts +3 -2
- package/dist/types/mcp.d.ts +7 -1
- package/dist/types/types.d.ts +2 -1
- package/package.json +1 -1
- package/src/add-ons.ts +15 -7
- package/src/cli.ts +15 -7
- package/src/create-app.ts +4 -3
- package/src/mcp.ts +192 -144
- package/src/types.ts +3 -1
package/dist/add-ons.js
CHANGED
|
@@ -91,10 +91,9 @@ export async function finalizeAddOns(framework, template, chosenAddOnIDs) {
|
|
|
91
91
|
const finalAddOns = [...finalAddOnIDs].map((id) => addOns.find((a) => a.id === id));
|
|
92
92
|
return finalAddOns;
|
|
93
93
|
}
|
|
94
|
-
export async function listAddOns(options) {
|
|
95
|
-
const
|
|
96
|
-
const addOns
|
|
97
|
-
for (const addOn of addOns) {
|
|
94
|
+
export async function listAddOns(options, { forcedMode, forcedAddOns = [], }) {
|
|
95
|
+
const addOns = await getAllAddOns(options.framework || DEFAULT_FRAMEWORK, forcedMode || options.template || 'typescript');
|
|
96
|
+
for (const addOn of addOns.filter((a) => !forcedAddOns.includes(a.id))) {
|
|
98
97
|
console.log(`${chalk.bold(addOn.id)}: ${addOn.description}`);
|
|
99
98
|
}
|
|
100
99
|
}
|
package/dist/cli.js
CHANGED
|
@@ -9,11 +9,9 @@ import { listAddOns } from './add-ons.js';
|
|
|
9
9
|
import { DEFAULT_FRAMEWORK, SUPPORTED_FRAMEWORKS } from './constants.js';
|
|
10
10
|
// import { initAddOn } from './custom-add-on.js'
|
|
11
11
|
import { createDefaultEnvironment } from './environment.js';
|
|
12
|
-
export function cli({ name, forcedMode, forcedAddOns, }) {
|
|
12
|
+
export function cli({ name, appName, forcedMode, forcedAddOns, }) {
|
|
13
13
|
const program = new Command();
|
|
14
|
-
program
|
|
15
|
-
.name('create-tsrouter-app')
|
|
16
|
-
.description('CLI to create a new TanStack application');
|
|
14
|
+
program.name(name).description(`CLI to create a new ${appName} application`);
|
|
17
15
|
// program
|
|
18
16
|
// .command('add')
|
|
19
17
|
// .argument('add-on', 'Name of the add-on (or add-ons separated by commas)')
|
|
@@ -78,10 +76,17 @@ export function cli({ name, forcedMode, forcedAddOns, }) {
|
|
|
78
76
|
}
|
|
79
77
|
program.action(async (projectName, options) => {
|
|
80
78
|
if (options.listAddOns) {
|
|
81
|
-
await listAddOns(options
|
|
79
|
+
await listAddOns(options, {
|
|
80
|
+
forcedMode,
|
|
81
|
+
forcedAddOns,
|
|
82
|
+
});
|
|
82
83
|
}
|
|
83
84
|
else if (options.mcp || options.mcpSse) {
|
|
84
|
-
await runServer(!!options.mcpSse
|
|
85
|
+
await runServer(!!options.mcpSse, {
|
|
86
|
+
forcedMode,
|
|
87
|
+
forcedAddOns,
|
|
88
|
+
appName,
|
|
89
|
+
});
|
|
85
90
|
}
|
|
86
91
|
else {
|
|
87
92
|
try {
|
|
@@ -94,10 +99,10 @@ export function cli({ name, forcedMode, forcedAddOns, }) {
|
|
|
94
99
|
}
|
|
95
100
|
let finalOptions = await normalizeOptions(cliOptions, forcedAddOns);
|
|
96
101
|
if (finalOptions) {
|
|
97
|
-
intro(`Creating a new
|
|
102
|
+
intro(`Creating a new ${appName} app in ${projectName}...`);
|
|
98
103
|
}
|
|
99
104
|
else {
|
|
100
|
-
intro(
|
|
105
|
+
intro(`Let's configure your ${appName} application`);
|
|
101
106
|
finalOptions = await promptForOptions(cliOptions, {
|
|
102
107
|
forcedMode,
|
|
103
108
|
forcedAddOns,
|
|
@@ -107,6 +112,7 @@ export function cli({ name, forcedMode, forcedAddOns, }) {
|
|
|
107
112
|
environment: createDefaultEnvironment(),
|
|
108
113
|
cwd: options.targetDir || undefined,
|
|
109
114
|
name,
|
|
115
|
+
appName,
|
|
110
116
|
});
|
|
111
117
|
}
|
|
112
118
|
catch (error) {
|
package/dist/create-app.js
CHANGED
|
@@ -209,7 +209,7 @@ async function copyAddOnFile(environment, content, target, targetPath, templateF
|
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
|
-
export async function createApp(options, { silent = false, environment, cwd,
|
|
212
|
+
export async function createApp(options, { silent = false, environment, cwd, appName = 'TanStack', }) {
|
|
213
213
|
environment.startRun();
|
|
214
214
|
const templateDirBase = resolve(getTemplatesRoot(), options.framework, 'base');
|
|
215
215
|
const templateDirRouter = resolve(getTemplatesRoot(), options.framework, options.mode);
|
|
@@ -480,7 +480,7 @@ ${environment.getErrors().join('\n')}`;
|
|
|
480
480
|
if (options.packageManager === 'deno') {
|
|
481
481
|
startCommand = `deno ${isAddOnEnabled('start') ? 'task dev' : 'start'}`;
|
|
482
482
|
}
|
|
483
|
-
outro(`Your
|
|
483
|
+
outro(`Your ${appName} app is ready in '${basename(targetDir)}'.
|
|
484
484
|
|
|
485
485
|
Use the following commands to start your app:
|
|
486
486
|
% cd ${options.projectName}
|
package/dist/mcp.js
CHANGED
|
@@ -6,10 +6,6 @@ import { z } from 'zod';
|
|
|
6
6
|
import { createApp } from './create-app.js';
|
|
7
7
|
import { finalizeAddOns } from './add-ons.js';
|
|
8
8
|
import { createDefaultEnvironment } from './environment.js';
|
|
9
|
-
const server = new McpServer({
|
|
10
|
-
name: 'Demo',
|
|
11
|
-
version: '1.0.0',
|
|
12
|
-
});
|
|
13
9
|
const tanStackReactAddOns = [
|
|
14
10
|
{
|
|
15
11
|
id: 'clerk',
|
|
@@ -52,63 +48,6 @@ const tanStackReactAddOns = [
|
|
|
52
48
|
description: 'Add an AI chatbot example to the application',
|
|
53
49
|
},
|
|
54
50
|
];
|
|
55
|
-
server.tool('listTanStackReactAddOns', {}, () => {
|
|
56
|
-
return {
|
|
57
|
-
content: [{ type: 'text', text: JSON.stringify(tanStackReactAddOns) }],
|
|
58
|
-
};
|
|
59
|
-
});
|
|
60
|
-
server.tool('createTanStackReactApplication', {
|
|
61
|
-
projectName: z
|
|
62
|
-
.string()
|
|
63
|
-
.describe('The package.json module name of the application (will also be the directory name)'),
|
|
64
|
-
cwd: z.string().describe('The directory to create the application in'),
|
|
65
|
-
addOns: z
|
|
66
|
-
.array(z.enum([
|
|
67
|
-
'clerk',
|
|
68
|
-
'convex',
|
|
69
|
-
'form',
|
|
70
|
-
'netlify',
|
|
71
|
-
'sentry',
|
|
72
|
-
'shadcn',
|
|
73
|
-
'start',
|
|
74
|
-
'store',
|
|
75
|
-
'tanstack-query',
|
|
76
|
-
'tanchat',
|
|
77
|
-
]))
|
|
78
|
-
.describe('The IDs of the add-ons to install'),
|
|
79
|
-
}, async ({ projectName, addOns, cwd }) => {
|
|
80
|
-
try {
|
|
81
|
-
process.chdir(cwd);
|
|
82
|
-
const chosenAddOns = await finalizeAddOns('react', 'file-router', addOns);
|
|
83
|
-
await createApp({
|
|
84
|
-
projectName: projectName.replace(/^\//, './'),
|
|
85
|
-
framework: 'react',
|
|
86
|
-
typescript: true,
|
|
87
|
-
tailwind: true,
|
|
88
|
-
packageManager: 'pnpm',
|
|
89
|
-
toolchain: 'none',
|
|
90
|
-
mode: 'file-router',
|
|
91
|
-
addOns: true,
|
|
92
|
-
chosenAddOns,
|
|
93
|
-
git: true,
|
|
94
|
-
variableValues: {},
|
|
95
|
-
}, {
|
|
96
|
-
silent: true,
|
|
97
|
-
environment: createDefaultEnvironment(),
|
|
98
|
-
name: 'create-tsrouter-app',
|
|
99
|
-
});
|
|
100
|
-
return {
|
|
101
|
-
content: [{ type: 'text', text: 'Application created successfully' }],
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
catch (error) {
|
|
105
|
-
return {
|
|
106
|
-
content: [
|
|
107
|
-
{ type: 'text', text: `Error creating application: ${error}` },
|
|
108
|
-
],
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
51
|
const tanStackSolidAddOns = [
|
|
113
52
|
{
|
|
114
53
|
id: 'solid-ui',
|
|
@@ -126,6 +65,10 @@ const tanStackSolidAddOns = [
|
|
|
126
65
|
id: 'store',
|
|
127
66
|
description: 'Enable the TanStack Store state management library',
|
|
128
67
|
},
|
|
68
|
+
{
|
|
69
|
+
id: 'start',
|
|
70
|
+
description: 'Set this if you want a TanStack Start application that supports server functions or APIs',
|
|
71
|
+
},
|
|
129
72
|
{
|
|
130
73
|
id: 'tanstack-query',
|
|
131
74
|
description: 'Enable TanStack Query for data fetching',
|
|
@@ -135,63 +78,136 @@ const tanStackSolidAddOns = [
|
|
|
135
78
|
description: 'Add an AI chatbot example to the application',
|
|
136
79
|
},
|
|
137
80
|
];
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
});
|
|
143
|
-
server.tool('
|
|
144
|
-
projectName: z
|
|
145
|
-
.string()
|
|
146
|
-
.describe('The package.json module name of the application (will also be the directory name)'),
|
|
147
|
-
cwd: z.string().describe('The directory to create the application in'),
|
|
148
|
-
addOns: z
|
|
149
|
-
.array(z.enum([
|
|
150
|
-
'solid-ui',
|
|
151
|
-
'form',
|
|
152
|
-
'sentry',
|
|
153
|
-
'store',
|
|
154
|
-
'tanstack-query',
|
|
155
|
-
'tanchat',
|
|
156
|
-
]))
|
|
157
|
-
.describe('The IDs of the add-ons to install'),
|
|
158
|
-
}, async ({ projectName, addOns, cwd }) => {
|
|
159
|
-
try {
|
|
160
|
-
process.chdir(cwd);
|
|
161
|
-
const chosenAddOns = await finalizeAddOns('solid', 'file-router', addOns);
|
|
162
|
-
await createApp({
|
|
163
|
-
projectName: projectName.replace(/^\//, './'),
|
|
164
|
-
framework: 'solid',
|
|
165
|
-
typescript: true,
|
|
166
|
-
tailwind: true,
|
|
167
|
-
packageManager: 'pnpm',
|
|
168
|
-
toolchain: 'none',
|
|
169
|
-
mode: 'file-router',
|
|
170
|
-
addOns: true,
|
|
171
|
-
chosenAddOns,
|
|
172
|
-
git: true,
|
|
173
|
-
variableValues: {},
|
|
174
|
-
}, {
|
|
175
|
-
silent: true,
|
|
176
|
-
environment: createDefaultEnvironment(),
|
|
177
|
-
name: 'create-tsrouter-app',
|
|
178
|
-
});
|
|
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', {}, () => {
|
|
179
87
|
return {
|
|
180
|
-
content: [{ type: 'text', text:
|
|
88
|
+
content: [{ type: 'text', text: JSON.stringify(tanStackReactAddOns) }],
|
|
181
89
|
};
|
|
182
|
-
}
|
|
183
|
-
|
|
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', {}, () => {
|
|
184
148
|
return {
|
|
185
|
-
content: [
|
|
186
|
-
{ type: 'text', text: `Error creating application: ${error}` },
|
|
187
|
-
],
|
|
149
|
+
content: [{ type: 'text', text: JSON.stringify(tanStackSolidAddOns) }],
|
|
188
150
|
};
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
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 });
|
|
192
209
|
if (sse) {
|
|
193
210
|
const app = express();
|
|
194
|
-
let transport = null;
|
|
195
211
|
app.get('/sse', (req, res) => {
|
|
196
212
|
transport = new SSEServerTransport('/messages', res);
|
|
197
213
|
server.connect(transport);
|
package/dist/types/add-ons.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import type { AddOn, CliOptions, Framework } from './types.js';
|
|
1
|
+
import type { AddOn, CliOptions, Framework, TemplateOptions } from './types.js';
|
|
2
2
|
export declare function getAllAddOns(framework: Framework, template: string): Promise<Array<AddOn>>;
|
|
3
3
|
export declare function finalizeAddOns(framework: Framework, template: string, chosenAddOnIDs: Array<string>): Promise<Array<AddOn>>;
|
|
4
|
-
export declare function listAddOns(options: CliOptions
|
|
4
|
+
export declare function listAddOns(options: CliOptions, { forcedMode, forcedAddOns, }: {
|
|
5
|
+
forcedMode?: TemplateOptions;
|
|
6
|
+
forcedAddOns?: Array<string>;
|
|
7
|
+
}): Promise<void>;
|
|
5
8
|
export declare function loadRemoteAddOn(url: string): Promise<AddOn>;
|
package/dist/types/cli.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export declare function cli({ name, forcedMode, forcedAddOns, }: {
|
|
1
|
+
export declare function cli({ name, appName, forcedMode, forcedAddOns, }: {
|
|
2
2
|
name: string;
|
|
3
|
+
appName: string;
|
|
3
4
|
forcedMode?: 'typescript' | 'javascript' | 'file-router';
|
|
4
5
|
forcedAddOns?: Array<string>;
|
|
5
6
|
}): void;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Environment, Options } from './types.js';
|
|
2
|
-
export declare function createApp(options: Options, { silent, environment, cwd,
|
|
2
|
+
export declare function createApp(options: Options, { silent, environment, cwd, appName, }: {
|
|
3
3
|
silent?: boolean;
|
|
4
4
|
environment: Environment;
|
|
5
5
|
cwd?: string;
|
|
6
|
-
name
|
|
6
|
+
name?: string;
|
|
7
|
+
appName?: string;
|
|
7
8
|
}): Promise<void>;
|
package/dist/types/mcp.d.ts
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import type { TemplateOptions } from './types.js';
|
|
2
|
+
export default function runServer(sse: boolean, { forcedAddOns, appName, name, }: {
|
|
3
|
+
forcedMode?: TemplateOptions;
|
|
4
|
+
forcedAddOns?: Array<string>;
|
|
5
|
+
appName?: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
}): Promise<void>;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { CODE_ROUTER, FILE_ROUTER } from './constants.js';
|
|
|
2
2
|
import type { PackageManager } from './package-manager.js';
|
|
3
3
|
import type { ToolChain } from './toolchain.js';
|
|
4
4
|
export type Framework = 'solid' | 'react';
|
|
5
|
+
export type TemplateOptions = 'typescript' | 'javascript' | 'file-router';
|
|
5
6
|
export interface Options {
|
|
6
7
|
framework: Framework;
|
|
7
8
|
projectName: string;
|
|
@@ -17,7 +18,7 @@ export interface Options {
|
|
|
17
18
|
overlay?: AddOn | undefined;
|
|
18
19
|
}
|
|
19
20
|
export interface CliOptions {
|
|
20
|
-
template?:
|
|
21
|
+
template?: TemplateOptions;
|
|
21
22
|
framework?: Framework;
|
|
22
23
|
tailwind?: boolean;
|
|
23
24
|
packageManager?: PackageManager;
|
package/package.json
CHANGED
package/src/add-ons.ts
CHANGED
|
@@ -2,10 +2,11 @@ import { readFile } from 'node:fs/promises'
|
|
|
2
2
|
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'
|
|
3
3
|
import { resolve } from 'node:path'
|
|
4
4
|
import chalk from 'chalk'
|
|
5
|
-
import { getTemplatesRoot } from './templates.js'
|
|
6
5
|
|
|
6
|
+
import { getTemplatesRoot } from './templates.js'
|
|
7
7
|
import { DEFAULT_FRAMEWORK } from './constants.js'
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
import type { AddOn, CliOptions, Framework, TemplateOptions } from './types.js'
|
|
9
10
|
|
|
10
11
|
function isDirectory(path: string): boolean {
|
|
11
12
|
return statSync(path).isDirectory()
|
|
@@ -121,14 +122,21 @@ export async function finalizeAddOns(
|
|
|
121
122
|
return finalAddOns
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
export async function listAddOns(
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
export async function listAddOns(
|
|
126
|
+
options: CliOptions,
|
|
127
|
+
{
|
|
128
|
+
forcedMode,
|
|
129
|
+
forcedAddOns = [],
|
|
130
|
+
}: {
|
|
131
|
+
forcedMode?: TemplateOptions
|
|
132
|
+
forcedAddOns?: Array<string>
|
|
133
|
+
},
|
|
134
|
+
) {
|
|
127
135
|
const addOns = await getAllAddOns(
|
|
128
136
|
options.framework || DEFAULT_FRAMEWORK,
|
|
129
|
-
|
|
137
|
+
forcedMode || options.template || 'typescript',
|
|
130
138
|
)
|
|
131
|
-
for (const addOn of addOns) {
|
|
139
|
+
for (const addOn of addOns.filter((a) => !forcedAddOns.includes(a.id))) {
|
|
132
140
|
console.log(`${chalk.bold(addOn.id)}: ${addOn.description}`)
|
|
133
141
|
}
|
|
134
142
|
}
|
package/src/cli.ts
CHANGED
|
@@ -20,18 +20,18 @@ import type { CliOptions, Framework } from './types.js'
|
|
|
20
20
|
|
|
21
21
|
export function cli({
|
|
22
22
|
name,
|
|
23
|
+
appName,
|
|
23
24
|
forcedMode,
|
|
24
25
|
forcedAddOns,
|
|
25
26
|
}: {
|
|
26
27
|
name: string
|
|
28
|
+
appName: string
|
|
27
29
|
forcedMode?: 'typescript' | 'javascript' | 'file-router'
|
|
28
30
|
forcedAddOns?: Array<string>
|
|
29
31
|
}) {
|
|
30
32
|
const program = new Command()
|
|
31
33
|
|
|
32
|
-
program
|
|
33
|
-
.name('create-tsrouter-app')
|
|
34
|
-
.description('CLI to create a new TanStack application')
|
|
34
|
+
program.name(name).description(`CLI to create a new ${appName} application`)
|
|
35
35
|
|
|
36
36
|
// program
|
|
37
37
|
// .command('add')
|
|
@@ -139,9 +139,16 @@ export function cli({
|
|
|
139
139
|
|
|
140
140
|
program.action(async (projectName: string, options: CliOptions) => {
|
|
141
141
|
if (options.listAddOns) {
|
|
142
|
-
await listAddOns(options
|
|
142
|
+
await listAddOns(options, {
|
|
143
|
+
forcedMode,
|
|
144
|
+
forcedAddOns,
|
|
145
|
+
})
|
|
143
146
|
} else if (options.mcp || options.mcpSse) {
|
|
144
|
-
await runServer(!!options.mcpSse
|
|
147
|
+
await runServer(!!options.mcpSse, {
|
|
148
|
+
forcedMode,
|
|
149
|
+
forcedAddOns,
|
|
150
|
+
appName,
|
|
151
|
+
})
|
|
145
152
|
} else {
|
|
146
153
|
try {
|
|
147
154
|
const cliOptions = {
|
|
@@ -155,9 +162,9 @@ export function cli({
|
|
|
155
162
|
|
|
156
163
|
let finalOptions = await normalizeOptions(cliOptions, forcedAddOns)
|
|
157
164
|
if (finalOptions) {
|
|
158
|
-
intro(`Creating a new
|
|
165
|
+
intro(`Creating a new ${appName} app in ${projectName}...`)
|
|
159
166
|
} else {
|
|
160
|
-
intro(
|
|
167
|
+
intro(`Let's configure your ${appName} application`)
|
|
161
168
|
finalOptions = await promptForOptions(cliOptions, {
|
|
162
169
|
forcedMode,
|
|
163
170
|
forcedAddOns,
|
|
@@ -167,6 +174,7 @@ export function cli({
|
|
|
167
174
|
environment: createDefaultEnvironment(),
|
|
168
175
|
cwd: options.targetDir || undefined,
|
|
169
176
|
name,
|
|
177
|
+
appName,
|
|
170
178
|
})
|
|
171
179
|
} catch (error) {
|
|
172
180
|
log.error(
|
package/src/create-app.ts
CHANGED
|
@@ -304,12 +304,13 @@ export async function createApp(
|
|
|
304
304
|
silent = false,
|
|
305
305
|
environment,
|
|
306
306
|
cwd,
|
|
307
|
-
|
|
307
|
+
appName = 'TanStack',
|
|
308
308
|
}: {
|
|
309
309
|
silent?: boolean
|
|
310
310
|
environment: Environment
|
|
311
311
|
cwd?: string
|
|
312
|
-
name
|
|
312
|
+
name?: string
|
|
313
|
+
appName?: string
|
|
313
314
|
},
|
|
314
315
|
) {
|
|
315
316
|
environment.startRun()
|
|
@@ -782,7 +783,7 @@ ${environment.getErrors().join('\n')}`
|
|
|
782
783
|
startCommand = `deno ${isAddOnEnabled('start') ? 'task dev' : 'start'}`
|
|
783
784
|
}
|
|
784
785
|
|
|
785
|
-
outro(`Your
|
|
786
|
+
outro(`Your ${appName} app is ready in '${basename(targetDir)}'.
|
|
786
787
|
|
|
787
788
|
Use the following commands to start your app:
|
|
788
789
|
% cd ${options.projectName}
|
package/src/mcp.ts
CHANGED
|
@@ -8,10 +8,7 @@ import { createApp } from './create-app.js'
|
|
|
8
8
|
import { finalizeAddOns } from './add-ons.js'
|
|
9
9
|
import { createDefaultEnvironment } from './environment.js'
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
name: 'Demo',
|
|
13
|
-
version: '1.0.0',
|
|
14
|
-
})
|
|
11
|
+
import type { TemplateOptions } from './types.js'
|
|
15
12
|
|
|
16
13
|
const tanStackReactAddOns = [
|
|
17
14
|
{
|
|
@@ -57,79 +54,6 @@ const tanStackReactAddOns = [
|
|
|
57
54
|
},
|
|
58
55
|
]
|
|
59
56
|
|
|
60
|
-
server.tool('listTanStackReactAddOns', {}, () => {
|
|
61
|
-
return {
|
|
62
|
-
content: [{ type: 'text', text: JSON.stringify(tanStackReactAddOns) }],
|
|
63
|
-
}
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
server.tool(
|
|
67
|
-
'createTanStackReactApplication',
|
|
68
|
-
{
|
|
69
|
-
projectName: z
|
|
70
|
-
.string()
|
|
71
|
-
.describe(
|
|
72
|
-
'The package.json module name of the application (will also be the directory name)',
|
|
73
|
-
),
|
|
74
|
-
cwd: z.string().describe('The directory to create the application in'),
|
|
75
|
-
addOns: z
|
|
76
|
-
.array(
|
|
77
|
-
z.enum([
|
|
78
|
-
'clerk',
|
|
79
|
-
'convex',
|
|
80
|
-
'form',
|
|
81
|
-
'netlify',
|
|
82
|
-
'sentry',
|
|
83
|
-
'shadcn',
|
|
84
|
-
'start',
|
|
85
|
-
'store',
|
|
86
|
-
'tanstack-query',
|
|
87
|
-
'tanchat',
|
|
88
|
-
]),
|
|
89
|
-
)
|
|
90
|
-
.describe('The IDs of the add-ons to install'),
|
|
91
|
-
},
|
|
92
|
-
async ({ projectName, addOns, cwd }) => {
|
|
93
|
-
try {
|
|
94
|
-
process.chdir(cwd)
|
|
95
|
-
const chosenAddOns = await finalizeAddOns(
|
|
96
|
-
'react',
|
|
97
|
-
'file-router',
|
|
98
|
-
addOns as unknown as Array<string>,
|
|
99
|
-
)
|
|
100
|
-
await createApp(
|
|
101
|
-
{
|
|
102
|
-
projectName: projectName.replace(/^\//, './'),
|
|
103
|
-
framework: 'react',
|
|
104
|
-
typescript: true,
|
|
105
|
-
tailwind: true,
|
|
106
|
-
packageManager: 'pnpm',
|
|
107
|
-
toolchain: 'none',
|
|
108
|
-
mode: 'file-router',
|
|
109
|
-
addOns: true,
|
|
110
|
-
chosenAddOns,
|
|
111
|
-
git: true,
|
|
112
|
-
variableValues: {},
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
silent: true,
|
|
116
|
-
environment: createDefaultEnvironment(),
|
|
117
|
-
name: 'create-tsrouter-app',
|
|
118
|
-
},
|
|
119
|
-
)
|
|
120
|
-
return {
|
|
121
|
-
content: [{ type: 'text', text: 'Application created successfully' }],
|
|
122
|
-
}
|
|
123
|
-
} catch (error) {
|
|
124
|
-
return {
|
|
125
|
-
content: [
|
|
126
|
-
{ type: 'text', text: `Error creating application: ${error}` },
|
|
127
|
-
],
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
)
|
|
132
|
-
|
|
133
57
|
const tanStackSolidAddOns = [
|
|
134
58
|
{
|
|
135
59
|
id: 'solid-ui',
|
|
@@ -147,6 +71,11 @@ const tanStackSolidAddOns = [
|
|
|
147
71
|
id: 'store',
|
|
148
72
|
description: 'Enable the TanStack Store state management library',
|
|
149
73
|
},
|
|
74
|
+
{
|
|
75
|
+
id: 'start',
|
|
76
|
+
description:
|
|
77
|
+
'Set this if you want a TanStack Start application that supports server functions or APIs',
|
|
78
|
+
},
|
|
150
79
|
{
|
|
151
80
|
id: 'tanstack-query',
|
|
152
81
|
description: 'Enable TanStack Query for data fetching',
|
|
@@ -157,81 +86,200 @@ const tanStackSolidAddOns = [
|
|
|
157
86
|
},
|
|
158
87
|
]
|
|
159
88
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
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
|
+
})
|
|
165
102
|
|
|
166
|
-
server.tool(
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
'
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
+
}
|
|
224
180
|
}
|
|
181
|
+
},
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
server.tool('listTanStackSolidAddOns', {}, () => {
|
|
185
|
+
return {
|
|
186
|
+
content: [{ type: 'text', text: JSON.stringify(tanStackSolidAddOns) }],
|
|
225
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
|
|
226
275
|
},
|
|
227
|
-
)
|
|
276
|
+
) {
|
|
277
|
+
let transport: SSEServerTransport | null = null
|
|
228
278
|
|
|
229
|
-
|
|
279
|
+
const server = createServer({ appName, forcedAddOns, name })
|
|
230
280
|
if (sse) {
|
|
231
281
|
const app = express()
|
|
232
282
|
|
|
233
|
-
let transport: SSEServerTransport | null = null
|
|
234
|
-
|
|
235
283
|
app.get('/sse', (req, res) => {
|
|
236
284
|
transport = new SSEServerTransport('/messages', res)
|
|
237
285
|
server.connect(transport)
|
package/src/types.ts
CHANGED
|
@@ -4,6 +4,8 @@ import type { ToolChain } from './toolchain.js'
|
|
|
4
4
|
|
|
5
5
|
export type Framework = 'solid' | 'react'
|
|
6
6
|
|
|
7
|
+
export type TemplateOptions = 'typescript' | 'javascript' | 'file-router'
|
|
8
|
+
|
|
7
9
|
export interface Options {
|
|
8
10
|
framework: Framework
|
|
9
11
|
projectName: string
|
|
@@ -20,7 +22,7 @@ export interface Options {
|
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export interface CliOptions {
|
|
23
|
-
template?:
|
|
25
|
+
template?: TemplateOptions
|
|
24
26
|
framework?: Framework
|
|
25
27
|
tailwind?: boolean
|
|
26
28
|
packageManager?: PackageManager
|