@tsed/cli 7.0.0-alpha.9 → 7.0.0-beta.10
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/lib/esm/bin/ts-mode.js +10 -0
- package/lib/esm/bin/tsed.js +25 -3
- package/lib/esm/commands/add/AddCmd.js +2 -1
- package/lib/esm/commands/generate/GenerateCmd.js +2 -1
- package/lib/esm/commands/index.js +3 -1
- package/lib/esm/commands/init/InitCmd.js +20 -113
- package/lib/esm/commands/init/InitOptionsCmd.js +17 -0
- package/lib/esm/commands/init/config/FeaturesPrompt.js +35 -36
- package/lib/esm/commands/init/config/InitSchema.js +337 -0
- package/lib/esm/commands/init/prompts/getFeaturesPrompt.js +1 -1
- package/lib/esm/commands/mcp/McpCommand.js +15 -0
- package/lib/esm/commands/mcp/resources/index.js +4 -0
- package/lib/esm/commands/mcp/resources/initOptionsResource.js +93 -0
- package/lib/esm/commands/mcp/resources/projectInfoResource.js +43 -0
- package/lib/esm/commands/mcp/resources/serverInfoResource.js +40 -0
- package/lib/esm/commands/mcp/schema/InitMCPSchema.js +9 -0
- package/lib/esm/commands/mcp/schema/ProjectPreferencesSchema.js +16 -0
- package/lib/esm/commands/mcp/tools/generateTool.js +105 -0
- package/lib/esm/commands/mcp/tools/getTemplateTool.js +47 -0
- package/lib/esm/commands/mcp/tools/index.js +6 -0
- package/lib/esm/commands/mcp/tools/initProjectTool.js +64 -0
- package/lib/esm/commands/mcp/tools/listTemplatesTool.js +37 -0
- package/lib/esm/commands/mcp/tools/setWorkspaceTool.js +64 -0
- package/lib/esm/commands/run/RunCmd.js +4 -1
- package/lib/esm/commands/template/CreateTemplateCommand.js +2 -1
- package/lib/esm/commands/update/UpdateCmd.js +3 -4
- package/lib/esm/index.js +6 -1
- package/lib/esm/processors/transformConfigFile.js +1 -1
- package/lib/esm/processors/transformServerFile.js +5 -7
- package/lib/esm/services/CliProjectService.js +7 -3
- package/lib/esm/services/CliStats.js +45 -0
- package/lib/esm/services/CliTemplatesService.js +20 -8
- package/lib/esm/templates/agents.template.js +17 -0
- package/lib/esm/templates/asyncFactory.template.js +4 -3
- package/lib/esm/templates/barrels.template.js +1 -8
- package/lib/esm/templates/command.template.js +1 -0
- package/lib/esm/templates/controller.template.js +7 -0
- package/lib/esm/templates/decorator.template.js +22 -11
- package/lib/esm/templates/dockerfile.template.js +5 -0
- package/lib/esm/templates/exception-filter.template.js +1 -0
- package/lib/esm/templates/factory.template.js +4 -3
- package/lib/esm/templates/index.command.template.js +1 -1
- package/lib/esm/templates/index.controller.template.js +12 -8
- package/lib/esm/templates/index.js +1 -0
- package/lib/esm/templates/index.logger.template.js +0 -1
- package/lib/esm/templates/interceptor.template.js +1 -0
- package/lib/esm/templates/interface.template.js +1 -0
- package/lib/esm/templates/middleware.template.js +14 -4
- package/lib/esm/templates/model.template.js +1 -0
- package/lib/esm/templates/module.template.js +1 -0
- package/lib/esm/templates/pipe.template.js +1 -0
- package/lib/esm/templates/prisma.service.template.js +1 -0
- package/lib/esm/templates/repository.template.js +1 -0
- package/lib/esm/templates/response-filter.template.js +1 -0
- package/lib/esm/templates/service.template.js +1 -0
- package/lib/esm/templates/value.template.js +1 -0
- package/lib/esm/utils/resolveSchema.js +17 -0
- package/lib/esm/utils/summarizeSchema.js +24 -0
- package/lib/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/types/bin/ts-mode.d.ts +1 -0
- package/lib/types/bin/tsed.d.ts +1 -1
- package/lib/types/commands/generate/GenerateCmd.d.ts +38 -1
- package/lib/types/commands/index.d.ts +103 -1
- package/lib/types/commands/init/InitCmd.d.ts +2 -5
- package/lib/types/commands/init/InitOptionsCmd.d.ts +52 -0
- package/lib/types/commands/init/config/FeaturesPrompt.d.ts +26 -32
- package/lib/types/commands/init/config/InitSchema.d.ts +18 -0
- package/lib/types/commands/mcp/McpCommand.d.ts +52 -0
- package/lib/types/commands/mcp/resources/index.d.ts +2 -0
- package/lib/types/commands/mcp/resources/initOptionsResource.d.ts +1 -0
- package/lib/types/commands/mcp/resources/projectInfoResource.d.ts +1 -0
- package/lib/types/commands/mcp/resources/serverInfoResource.d.ts +1 -0
- package/lib/types/commands/mcp/schema/InitMCPSchema.d.ts +5 -0
- package/lib/types/commands/mcp/schema/ProjectPreferencesSchema.d.ts +9 -0
- package/lib/types/commands/mcp/tools/generateTool.d.ts +116 -0
- package/lib/types/commands/mcp/tools/getTemplateTool.d.ts +114 -0
- package/lib/types/commands/mcp/tools/index.d.ts +345 -0
- package/lib/types/commands/mcp/tools/initProjectTool.d.ts +116 -0
- package/lib/types/commands/mcp/tools/listTemplatesTool.d.ts +114 -0
- package/lib/types/commands/mcp/tools/setWorkspaceTool.d.ts +119 -0
- package/lib/types/index.d.ts +6 -1
- package/lib/types/interfaces/InitCmdOptions.d.ts +1 -1
- package/lib/types/pipes/SymbolNamePipe.d.ts +1 -1
- package/lib/types/services/CliProjectService.d.ts +1 -1
- package/lib/types/services/CliStats.d.ts +36 -0
- package/lib/types/services/CliTemplatesService.d.ts +7 -4
- package/lib/types/templates/agents.template.d.ts +17 -0
- package/lib/types/templates/asyncFactory.template.d.ts +1 -0
- package/lib/types/templates/barrels.template.d.ts +1 -0
- package/lib/types/templates/command.template.d.ts +1 -0
- package/lib/types/templates/config.template.d.ts +1 -0
- package/lib/types/templates/controller.template.d.ts +1 -0
- package/lib/types/templates/decorator.template.d.ts +1 -0
- package/lib/types/templates/docker-compose.template.d.ts +1 -0
- package/lib/types/templates/exception-filter.template.d.ts +1 -0
- package/lib/types/templates/factory.template.d.ts +1 -0
- package/lib/types/templates/index.command.template.d.ts +1 -0
- package/lib/types/templates/index.config.utils.template.d.ts +1 -0
- package/lib/types/templates/index.controller.template.d.ts +1 -0
- package/lib/types/templates/index.d.ts +1 -0
- package/lib/types/templates/index.logger.template.d.ts +3 -2
- package/lib/types/templates/index.template.d.ts +1 -0
- package/lib/types/templates/interceptor.template.d.ts +1 -0
- package/lib/types/templates/interface.template.d.ts +1 -0
- package/lib/types/templates/middleware.template.d.ts +1 -0
- package/lib/types/templates/model.template.d.ts +1 -0
- package/lib/types/templates/module.template.d.ts +1 -0
- package/lib/types/templates/pipe.template.d.ts +1 -0
- package/lib/types/templates/prisma.service.template.d.ts +1 -0
- package/lib/types/templates/readme.template.d.ts +1 -0
- package/lib/types/templates/repository.template.d.ts +1 -0
- package/lib/types/templates/response-filter.template.d.ts +1 -0
- package/lib/types/templates/server.template.d.ts +1 -0
- package/lib/types/templates/service.template.d.ts +1 -0
- package/lib/types/templates/tsconfig.spec.template.d.ts +1 -0
- package/lib/types/templates/value.template.d.ts +1 -0
- package/lib/types/utils/defineTemplate.d.ts +11 -0
- package/lib/types/utils/resolveSchema.d.ts +2 -0
- package/lib/types/utils/summarizeSchema.d.ts +8 -0
- package/package.json +19 -14
- package/templates/views/home.ejs +347 -0
- package/lib/esm/Cli.js +0 -58
- package/lib/esm/commands/init/config/InitFileSchema.js +0 -49
- package/lib/types/Cli.d.ts +0 -27
- package/lib/types/commands/init/config/InitFileSchema.d.ts +0 -49
- package/templates/views/swagger.ejs +0 -100
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { PackageManager, PackageManagersModule } from "@tsed/cli-core";
|
|
2
|
+
import { inject } from "@tsed/di";
|
|
3
|
+
import { s } from "@tsed/schema";
|
|
4
|
+
import { DEFAULT_TSED_TAGS } from "../../../constants/index.js";
|
|
5
|
+
import { ArchitectureConvention, PlatformType, ProjectConvention } from "../../../interfaces/index.js";
|
|
6
|
+
import { RuntimesModule } from "../../../runtimes/RuntimesModule.js";
|
|
7
|
+
import { FeatureType } from "../../init/config/FeaturesPrompt.js";
|
|
8
|
+
export const InitSchema = () => {
|
|
9
|
+
const availablePackageManagers = inject(PackageManagersModule).list();
|
|
10
|
+
const availableRuntimes = inject(RuntimesModule).list();
|
|
11
|
+
return s
|
|
12
|
+
.object({
|
|
13
|
+
root: s.string().description("Current working directory to initialize Ts.ED project").default("."),
|
|
14
|
+
projectName: s
|
|
15
|
+
.string()
|
|
16
|
+
.optional()
|
|
17
|
+
.prompt("What is your project name")
|
|
18
|
+
.when((ctx) => ctx.root !== ".")
|
|
19
|
+
.description("Set the project name. By default, the project is the same as the name directory.")
|
|
20
|
+
.opt("-n, --project-name <projectName>"),
|
|
21
|
+
platform: s
|
|
22
|
+
.enums(PlatformType)
|
|
23
|
+
.default(PlatformType.EXPRESS)
|
|
24
|
+
.prompt("Choose the target Framework:")
|
|
25
|
+
.choices([
|
|
26
|
+
{
|
|
27
|
+
label: "Express.js",
|
|
28
|
+
value: PlatformType.EXPRESS,
|
|
29
|
+
checked: (options) => options.platform === PlatformType.EXPRESS || !options.platform // todo maybe it can be infered by default() and item value()
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
label: "Koa.js",
|
|
33
|
+
value: PlatformType.KOA,
|
|
34
|
+
checked: (options) => options.platform === PlatformType.KOA || !options.platform
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
label: "Fastify.js (beta)",
|
|
38
|
+
value: PlatformType.KOA,
|
|
39
|
+
checked: (options) => options.platform === PlatformType.KOA || !options.platform
|
|
40
|
+
}
|
|
41
|
+
])
|
|
42
|
+
.description("Set the default platform for Ts.ED (Express.js, Koa.js or Fastify.js)")
|
|
43
|
+
.opt("-p, --platform <platform>"),
|
|
44
|
+
architecture: s
|
|
45
|
+
.string()
|
|
46
|
+
.enum(ArchitectureConvention)
|
|
47
|
+
.default(ArchitectureConvention.DEFAULT)
|
|
48
|
+
.prompt("Choose the architecture for your project:")
|
|
49
|
+
.description("Architecture convention for tree directory")
|
|
50
|
+
.choices([
|
|
51
|
+
{
|
|
52
|
+
label: "Ts.ED",
|
|
53
|
+
value: ArchitectureConvention.DEFAULT
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
label: "Feature",
|
|
57
|
+
value: ArchitectureConvention.FEATURE
|
|
58
|
+
}
|
|
59
|
+
])
|
|
60
|
+
.opt("-a, --arch <architecture>"),
|
|
61
|
+
convention: s
|
|
62
|
+
.enums(ProjectConvention)
|
|
63
|
+
.default(ProjectConvention.DEFAULT)
|
|
64
|
+
.prompt("Choose the file naming convention:")
|
|
65
|
+
.description("Set the default file naming convention (Ts.ED, Angular).")
|
|
66
|
+
.choices([
|
|
67
|
+
{
|
|
68
|
+
label: "Ts.ED",
|
|
69
|
+
value: ProjectConvention.DEFAULT
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
label: "Angular",
|
|
73
|
+
value: ProjectConvention.ANGULAR
|
|
74
|
+
}
|
|
75
|
+
])
|
|
76
|
+
.opt("-c, --convention <convention>"),
|
|
77
|
+
features: s
|
|
78
|
+
.array()
|
|
79
|
+
.items(s.enums(FeatureType))
|
|
80
|
+
.prompt("Choose the features needed for your project")
|
|
81
|
+
.description("List of features to enable (swagger, graphql, prisma, etc.).")
|
|
82
|
+
.choices([
|
|
83
|
+
{
|
|
84
|
+
label: "Commands",
|
|
85
|
+
value: FeatureType.COMMANDS
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
label: "Configuration sources",
|
|
89
|
+
value: FeatureType.CONFIG,
|
|
90
|
+
items: [
|
|
91
|
+
{
|
|
92
|
+
label: "Envs",
|
|
93
|
+
value: FeatureType.CONFIG_ENVS
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
label: "Dotenv",
|
|
97
|
+
value: FeatureType.CONFIG_DOTENV
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
label: "JSON",
|
|
101
|
+
value: FeatureType.CONFIG_JSON
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
label: "YAML",
|
|
105
|
+
value: FeatureType.CONFIG_YAML
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
label: "AWS Secrets Manager (Premium)",
|
|
109
|
+
value: FeatureType.CONFIG_AWS_SECRETS
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
label: "IORedis (Premium)",
|
|
113
|
+
value: FeatureType.CONFIG_IOREDIS
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
label: "MongoDB (Premium)",
|
|
117
|
+
value: FeatureType.CONFIG_MONGO
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
label: "Vault (Premium)",
|
|
121
|
+
value: FeatureType.CONFIG_VAULT
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
label: "Postgres (Premium)",
|
|
125
|
+
value: FeatureType.CONFIG_POSTGRES
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
label: "ORM",
|
|
131
|
+
value: FeatureType.ORM,
|
|
132
|
+
items: [
|
|
133
|
+
{
|
|
134
|
+
label: "Prisma",
|
|
135
|
+
value: FeatureType.PRISMA
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
label: "Mongoose",
|
|
139
|
+
value: FeatureType.MONGOOSE
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
label: "TypeORM",
|
|
143
|
+
value: FeatureType.TYPEORM,
|
|
144
|
+
items: [
|
|
145
|
+
{
|
|
146
|
+
label: "MySQL",
|
|
147
|
+
value: FeatureType.TYPEORM_MYSQL
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
label: "MariaDB",
|
|
151
|
+
value: FeatureType.TYPEORM_MARIADB
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
label: "Postgres",
|
|
155
|
+
value: FeatureType.TYPEORM_POSTGRES
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
label: "CockRoachDB",
|
|
159
|
+
value: FeatureType.TYPEORM_COCKROACHDB
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
label: "SQLite",
|
|
163
|
+
value: FeatureType.TYPEORM_SQLITE
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
label: "Better SQLite3",
|
|
167
|
+
value: FeatureType.TYPEORM_BETTER_SQLITE3
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
label: "Cordova",
|
|
171
|
+
value: FeatureType.TYPEORM_CORDOVA
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
label: "NativeScript",
|
|
175
|
+
value: FeatureType.TYPEORM_NATIVESCRIPT
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
label: "Oracle",
|
|
179
|
+
value: FeatureType.TYPEORM_ORACLE
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
label: "MsSQL",
|
|
183
|
+
value: FeatureType.TYPEORM_MSSQL
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
label: "MongoDB",
|
|
187
|
+
value: FeatureType.TYPEORM_MONGODB
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
label: "SQL.js",
|
|
191
|
+
value: FeatureType.TYPEORM_SQLJS
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
label: "ReactNative",
|
|
195
|
+
value: FeatureType.TYPEORM_REACTNATIVE
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
label: "Expo",
|
|
199
|
+
value: FeatureType.TYPEORM_EXPO
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
label: "Documentation",
|
|
207
|
+
value: "doc",
|
|
208
|
+
items: [
|
|
209
|
+
{
|
|
210
|
+
label: "Swagger",
|
|
211
|
+
value: "doc:swagger"
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
label: "Scalar",
|
|
215
|
+
value: "doc:scalar"
|
|
216
|
+
}
|
|
217
|
+
]
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
label: "TypeGraphQL",
|
|
221
|
+
value: "graphql",
|
|
222
|
+
items: []
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
label: "Linter",
|
|
226
|
+
value: FeatureType.LINTER,
|
|
227
|
+
items: [
|
|
228
|
+
{
|
|
229
|
+
label: "EsLint",
|
|
230
|
+
value: FeatureType.ESLINT
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
label: "Prettier",
|
|
234
|
+
value: FeatureType.PRETTIER
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
label: "Lint on commit",
|
|
238
|
+
value: FeatureType.LINT_STAGED
|
|
239
|
+
}
|
|
240
|
+
]
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
label: "OpenID Connect provider",
|
|
244
|
+
value: FeatureType.OIDC,
|
|
245
|
+
items: []
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
label: "Passport.js",
|
|
249
|
+
value: FeatureType.PASSPORTJS,
|
|
250
|
+
items: []
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
label: "Socket.io",
|
|
254
|
+
value: FeatureType.SOCKETIO,
|
|
255
|
+
items: []
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
label: "Testing",
|
|
259
|
+
value: FeatureType.TESTING,
|
|
260
|
+
items: [
|
|
261
|
+
{
|
|
262
|
+
label: "Vitest",
|
|
263
|
+
value: FeatureType.VITEST
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
label: "Jest (unstable with ESM)",
|
|
267
|
+
value: FeatureType.JEST
|
|
268
|
+
}
|
|
269
|
+
]
|
|
270
|
+
}
|
|
271
|
+
])
|
|
272
|
+
.opt("--features <features...>"),
|
|
273
|
+
runtime: s
|
|
274
|
+
.enums(availableRuntimes)
|
|
275
|
+
.prompt("Choose the runtime:")
|
|
276
|
+
.choices([
|
|
277
|
+
{
|
|
278
|
+
label: "Node.js + SWC",
|
|
279
|
+
value: "node"
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
label: "Node.js + Babel",
|
|
283
|
+
value: "babel"
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
label: "Node.js + Webpack",
|
|
287
|
+
value: "webpack"
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
label: "Bun",
|
|
291
|
+
value: "bun"
|
|
292
|
+
}
|
|
293
|
+
].filter((o) => availableRuntimes.includes(o.value)))
|
|
294
|
+
.default("node")
|
|
295
|
+
.description("Runtime (node, bun, ...).")
|
|
296
|
+
.opt("--runtime <runtime>"),
|
|
297
|
+
packageManager: s
|
|
298
|
+
.enums(availablePackageManagers)
|
|
299
|
+
.prompt("Choose the package manager:")
|
|
300
|
+
.when((answers) => answers.runtime !== "bun")
|
|
301
|
+
.default(PackageManager.NPM)
|
|
302
|
+
.choices([
|
|
303
|
+
{
|
|
304
|
+
label: "NPM",
|
|
305
|
+
value: PackageManager.NPM
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
label: "Yarn Berry",
|
|
309
|
+
value: PackageManager.YARN_BERRY
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
label: "PNPM",
|
|
313
|
+
value: PackageManager.PNPM
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
label: "Bun.js",
|
|
317
|
+
value: PackageManager.BUN
|
|
318
|
+
}
|
|
319
|
+
].filter((o) => availablePackageManagers.includes(o.value)))
|
|
320
|
+
.description("Package manager (npm, pnpm, yarn, bun).")
|
|
321
|
+
.opt("-m, --package-manager <packageManager>"),
|
|
322
|
+
GH_TOKEN: s
|
|
323
|
+
.string()
|
|
324
|
+
.optional()
|
|
325
|
+
.description("GitHub token to install premium plugins. For example config:aws_secrets:premium or all features endings by `:premium` needs a GH_TOKEN")
|
|
326
|
+
.opt("--gh-token <ghToken>"),
|
|
327
|
+
tsedVersion: s
|
|
328
|
+
.string()
|
|
329
|
+
.optional()
|
|
330
|
+
.default(DEFAULT_TSED_TAGS)
|
|
331
|
+
.description("Use a specific version of Ts.ED (format: x.x.x).")
|
|
332
|
+
.opt("-t, --tsed-version <version>"),
|
|
333
|
+
file: s.string().optional().description("Location of a file in which the features are defined.").opt("-f, --file <file>"),
|
|
334
|
+
skipPrompt: s.boolean().optional().default(false).description("Skip the prompt installation").opt("-s, --skip-prompt")
|
|
335
|
+
})
|
|
336
|
+
.unknown();
|
|
337
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cleanObject, isFunction } from "@tsed/core";
|
|
2
|
-
import { FeaturesMap, FeaturesPrompt
|
|
2
|
+
import { FeaturesMap, FeaturesPrompt } from "../config/FeaturesPrompt.js";
|
|
3
3
|
function mapChoices(item, options) {
|
|
4
4
|
return item.choices.map((choice) => {
|
|
5
5
|
const { checked } = FeaturesMap[choice];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { command } from "@tsed/cli-core";
|
|
2
|
+
import { MCP_SERVER } from "@tsed/cli-mcp";
|
|
3
|
+
import { inject } from "@tsed/di";
|
|
4
|
+
import { s } from "@tsed/schema";
|
|
5
|
+
const McpSchema = s.object({
|
|
6
|
+
http: s.boolean().default(false).description("Run MCP using HTTP server").opt("--http")
|
|
7
|
+
});
|
|
8
|
+
export const McpCommand = command({
|
|
9
|
+
name: "mcp",
|
|
10
|
+
description: "Run a MCP server",
|
|
11
|
+
inputSchema: McpSchema,
|
|
12
|
+
handler(data) {
|
|
13
|
+
return inject(MCP_SERVER).connect(data.http ? "streamable-http" : "stdio");
|
|
14
|
+
}
|
|
15
|
+
}).token();
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { initOptionsResource } from "./initOptionsResource.js";
|
|
2
|
+
import { projectInfoResource } from "./projectInfoResource.js";
|
|
3
|
+
import { serverInfoResource } from "./serverInfoResource.js";
|
|
4
|
+
export default [serverInfoResource, projectInfoResource, initOptionsResource];
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { defineResource } from "@tsed/cli-mcp";
|
|
2
|
+
import { InitMCPSchema } from "../schema/InitMCPSchema.js";
|
|
3
|
+
function stripCliFlags(payload) {
|
|
4
|
+
if (Array.isArray(payload)) {
|
|
5
|
+
return payload.map(stripCliFlags);
|
|
6
|
+
}
|
|
7
|
+
if (payload && typeof payload === "object") {
|
|
8
|
+
return Object.entries(payload).reduce((acc, [key, value]) => {
|
|
9
|
+
if (key === "x-opt") {
|
|
10
|
+
return acc;
|
|
11
|
+
}
|
|
12
|
+
acc[key] = stripCliFlags(value);
|
|
13
|
+
return acc;
|
|
14
|
+
}, {});
|
|
15
|
+
}
|
|
16
|
+
return payload;
|
|
17
|
+
}
|
|
18
|
+
function buildSection(key, property) {
|
|
19
|
+
const title = property["x-label"] || "";
|
|
20
|
+
if (!title) {
|
|
21
|
+
return "";
|
|
22
|
+
}
|
|
23
|
+
const choices = property["x-choices"] || property["items"]?.["x-choices"] || property["enum"] || [];
|
|
24
|
+
if (!choices.length) {
|
|
25
|
+
return `${title}?\n`;
|
|
26
|
+
}
|
|
27
|
+
const lines = [title + (property.type === "array" ? "(multiple choices possible)" : "")];
|
|
28
|
+
const loop = (items, indent) => {
|
|
29
|
+
if (!Array.isArray(items)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
for (const entry of items) {
|
|
33
|
+
const label = entry.label || entry.value;
|
|
34
|
+
if (!label) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
lines.push(`${" ".repeat(indent)}- ${label}`);
|
|
38
|
+
if (entry.items?.length) {
|
|
39
|
+
loop(entry.items, indent + 4);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
loop(choices, 4);
|
|
44
|
+
lines.push("");
|
|
45
|
+
const xSchemaPath = `#/schema.properties.${key}`;
|
|
46
|
+
if (property["x-choices"] || property["items"]?.["x-choices"]) {
|
|
47
|
+
const xChoicesPath = property.type === "array" ? `${xSchemaPath}.items.x-choices` : `${xSchemaPath}.x-choices`;
|
|
48
|
+
lines.push(`> LLM note only: labels/values mapping is here \`${xChoicesPath}\` and schema is here \`${xSchemaPath}\``);
|
|
49
|
+
lines.push("");
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
lines.push(`> LLM note only: schema is here \`${xSchemaPath}\``);
|
|
53
|
+
lines.push("");
|
|
54
|
+
}
|
|
55
|
+
return lines.join("\n");
|
|
56
|
+
}
|
|
57
|
+
function buildInstructions(schema) {
|
|
58
|
+
const properties = schema.properties || {};
|
|
59
|
+
return Object.entries(properties)
|
|
60
|
+
.map(([key, definition], index) => {
|
|
61
|
+
const property = definition;
|
|
62
|
+
const result = buildSection(key, property);
|
|
63
|
+
return result ? `${index + 1}) ${result}` : property;
|
|
64
|
+
})
|
|
65
|
+
.join("\n");
|
|
66
|
+
}
|
|
67
|
+
export const initOptionsResource = defineResource({
|
|
68
|
+
name: "init-options",
|
|
69
|
+
uri: "tsed://init/options",
|
|
70
|
+
title: "Inspect Ts.ED init options",
|
|
71
|
+
description: "Returns curated Ts.ED init instructions plus the machine-readable schema so assistants can gather user preferences then call `init-project`. Show humans only the labels; use the provided mapping to translate back to enum values.",
|
|
72
|
+
mimeType: "application/json",
|
|
73
|
+
async handler(uri) {
|
|
74
|
+
const rawSchema = InitMCPSchema().omit("cwd", "tsedVersion").toJSON({
|
|
75
|
+
useAlias: false,
|
|
76
|
+
customKeys: true
|
|
77
|
+
});
|
|
78
|
+
const schema = stripCliFlags(rawSchema);
|
|
79
|
+
const payload = {
|
|
80
|
+
instructions: buildInstructions(schema),
|
|
81
|
+
schema
|
|
82
|
+
};
|
|
83
|
+
return {
|
|
84
|
+
contents: [
|
|
85
|
+
{
|
|
86
|
+
uri: uri.href,
|
|
87
|
+
mimeType: "application/json",
|
|
88
|
+
text: JSON.stringify(payload, null, 2)
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { isAbsolute, normalize, resolve } from "node:path";
|
|
3
|
+
import { ProjectPackageJson } from "@tsed/cli-core";
|
|
4
|
+
import { defineResource, defineTool } from "@tsed/cli-mcp";
|
|
5
|
+
import { constant, inject } from "@tsed/di";
|
|
6
|
+
import { array, object, s, string } from "@tsed/schema";
|
|
7
|
+
import { ProjectPreferenceSchema } from "../schema/ProjectPreferencesSchema.js";
|
|
8
|
+
function resolveCwd(cwd) {
|
|
9
|
+
const projectPackage = inject(ProjectPackageJson);
|
|
10
|
+
const base = cwd || projectPackage.cwd || process.cwd();
|
|
11
|
+
const abs = isAbsolute(base) ? base : resolve(process.cwd(), base);
|
|
12
|
+
return normalize(abs);
|
|
13
|
+
}
|
|
14
|
+
export const projectInfoResource = defineResource({
|
|
15
|
+
name: "project-info",
|
|
16
|
+
uri: "tsed://project/info",
|
|
17
|
+
title: "Inspect project information",
|
|
18
|
+
description: "Read project information like cwd, package.json, preferences and if it's an initialised Ts.ED",
|
|
19
|
+
mimeType: "application/json",
|
|
20
|
+
async handler(uri) {
|
|
21
|
+
const projectPackage = inject(ProjectPackageJson);
|
|
22
|
+
const info = {
|
|
23
|
+
cwd: projectPackage.cwd,
|
|
24
|
+
pkg: projectPackage.toJSON(),
|
|
25
|
+
isInitialized: !!projectPackage.preferences?.packageManager,
|
|
26
|
+
preferences: {
|
|
27
|
+
convention: projectPackage.preferences.convention,
|
|
28
|
+
packageManager: projectPackage.preferences.packageManager,
|
|
29
|
+
platform: projectPackage.preferences.platform,
|
|
30
|
+
runtime: projectPackage.preferences.runtime
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
contents: [
|
|
35
|
+
{
|
|
36
|
+
uri: uri.href,
|
|
37
|
+
mimeType: "application/json",
|
|
38
|
+
text: JSON.stringify(info, null, 2)
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ProjectPackageJson } from "@tsed/cli-core";
|
|
2
|
+
import { defineResource } from "@tsed/cli-mcp";
|
|
3
|
+
import { constant, inject } from "@tsed/di";
|
|
4
|
+
async function getMcpVersion() {
|
|
5
|
+
try {
|
|
6
|
+
// best effort: resolve MCP SDK version via package.json resolution
|
|
7
|
+
const mcpPkg = await import("@modelcontextprotocol/sdk/package.json", { with: { type: "json" } }).catch(() => undefined);
|
|
8
|
+
return mcpPkg?.version;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
// ignore
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export const serverInfoResource = defineResource({
|
|
15
|
+
name: "server-info",
|
|
16
|
+
uri: "tsed://server/info",
|
|
17
|
+
title: "Server information",
|
|
18
|
+
description: "Process and environment information for the Ts.ED MCP server.",
|
|
19
|
+
mimeType: "application/json",
|
|
20
|
+
async handler(uri) {
|
|
21
|
+
const projectPackage = inject(ProjectPackageJson);
|
|
22
|
+
const info = {
|
|
23
|
+
pid: process.pid,
|
|
24
|
+
serverCwd: process.cwd(),
|
|
25
|
+
projectCwd: inject(ProjectPackageJson).cwd,
|
|
26
|
+
tsedCliVersion: constant("version"),
|
|
27
|
+
mcpSdkVersion: await getMcpVersion(),
|
|
28
|
+
projectExists: !!projectPackage.preferences?.packageManager
|
|
29
|
+
};
|
|
30
|
+
return {
|
|
31
|
+
contents: [
|
|
32
|
+
{
|
|
33
|
+
uri: uri.href,
|
|
34
|
+
mimeType: "application/json",
|
|
35
|
+
text: JSON.stringify(info, null, 2)
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { s } from "@tsed/schema";
|
|
2
|
+
import { InitSchema } from "../../init/config/InitSchema.js";
|
|
3
|
+
export const InitMCPSchema = () => {
|
|
4
|
+
return s
|
|
5
|
+
.object({
|
|
6
|
+
cwd: s.string().required().description("Current working directory to initialize Ts.ED project")
|
|
7
|
+
})
|
|
8
|
+
.merge(InitSchema().omit("root", "skipPrompt", "file", "GH_TOKEN"));
|
|
9
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { PackageManager } from "@tsed/cli-core";
|
|
2
|
+
import { s } from "@tsed/schema";
|
|
3
|
+
import { PlatformType } from "../../../interfaces/PlatformType.js";
|
|
4
|
+
import { ProjectConvention } from "../../../interfaces/ProjectConvention.js";
|
|
5
|
+
export const ProjectPreferenceSchema = s
|
|
6
|
+
.object({
|
|
7
|
+
convention: s.string().enum(ProjectConvention).description("Project convention (Ts.ED or Angular style)"),
|
|
8
|
+
packageManager: s.string().enum(PackageManager).description("Used project manager to install dependencies"),
|
|
9
|
+
runtime: s
|
|
10
|
+
.string()
|
|
11
|
+
.enum("node", "babel", "swc", "webpack", "bun")
|
|
12
|
+
.description("The javascript runtime used to start application (node, node + webpack, node + swc, node + babel, bun)"),
|
|
13
|
+
platform: s.string().enum(PlatformType).description("Node.js framework used to run server (Express, Koa, Fastify)")
|
|
14
|
+
})
|
|
15
|
+
.optional()
|
|
16
|
+
.description("Resolved project preferences");
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { ProjectPackageJson, validate } from "@tsed/cli-core";
|
|
2
|
+
import { defineTool } from "@tsed/cli-mcp";
|
|
3
|
+
import { inject } from "@tsed/di";
|
|
4
|
+
import { array, number, object, string } from "@tsed/schema";
|
|
5
|
+
import { CliProjectService } from "../../../services/CliProjectService.js";
|
|
6
|
+
import { CliTemplatesService } from "../../../services/CliTemplatesService.js";
|
|
7
|
+
import { mapDefaultTemplateOptions } from "../../../services/mappers/mapDefaultTemplateOptions.js";
|
|
8
|
+
export const generateTool = defineTool({
|
|
9
|
+
name: "generate-file",
|
|
10
|
+
title: "Generate file",
|
|
11
|
+
description: "Generate a new Ts.ED provider class depending on the given parameters.",
|
|
12
|
+
inputSchema: object({
|
|
13
|
+
id: string().required().description("The template id of the file to generate (e.g., 'controller', 'service', 'model')."),
|
|
14
|
+
name: string().required().description("The name of the class to generate."),
|
|
15
|
+
properties: object()
|
|
16
|
+
.unknown()
|
|
17
|
+
.optional()
|
|
18
|
+
.description("Additional properties to generate file depending on the given template id. For example controller accept extra properties. Run 'list-templates' and/or 'get-template' to discover extra properties available for the template.")
|
|
19
|
+
.default({})
|
|
20
|
+
}),
|
|
21
|
+
outputSchema: object({
|
|
22
|
+
files: array().items(string()).description("List of generated files."),
|
|
23
|
+
count: number().description("Number of files generated."),
|
|
24
|
+
symbolPath: string().optional().description("Main generated symbol path"),
|
|
25
|
+
logs: array().items(string()).optional().description("Execution logs"),
|
|
26
|
+
warnings: array().items(string()).optional().description("Non blocking warnings")
|
|
27
|
+
}),
|
|
28
|
+
async handler({ id, name, properties }) {
|
|
29
|
+
const projectService = inject(CliProjectService);
|
|
30
|
+
const templates = inject(CliTemplatesService);
|
|
31
|
+
const projectPackage = inject(ProjectPackageJson);
|
|
32
|
+
// Pre-checks
|
|
33
|
+
const warnings = [];
|
|
34
|
+
if (!projectPackage.cwd) {
|
|
35
|
+
return {
|
|
36
|
+
content: [],
|
|
37
|
+
isError: true,
|
|
38
|
+
structuredContent: {
|
|
39
|
+
code: "E_CWD_NOT_SET",
|
|
40
|
+
message: "Workspace is not set. Call set-workspace first to define the project root.",
|
|
41
|
+
suggestion: "Call 'set-workspace' with the project directory, then retry 'generate-file'."
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (!projectPackage.preferences?.packageManager) {
|
|
46
|
+
return {
|
|
47
|
+
content: [],
|
|
48
|
+
isError: true,
|
|
49
|
+
structuredContent: {
|
|
50
|
+
code: "E_PROJECT_NOT_INITIALIZED",
|
|
51
|
+
message: "The target directory does not appear to be an initialized Ts.ED project.",
|
|
52
|
+
suggestion: "Run 'init-project' to initialize a Ts.ED project in this workspace before generating files, or use 'set-workspace' to configure the tool to point to the appropriate working directory."
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const ctx = mapDefaultTemplateOptions({ ...properties, type: id, name });
|
|
57
|
+
const { type } = ctx;
|
|
58
|
+
// Validate template exists
|
|
59
|
+
const template = inject(CliTemplatesService).get(type);
|
|
60
|
+
if (!template) {
|
|
61
|
+
return {
|
|
62
|
+
content: [],
|
|
63
|
+
isError: true,
|
|
64
|
+
structuredContent: {
|
|
65
|
+
code: "E_TEMPLATE_UNKNOWN",
|
|
66
|
+
message: `Unknown template type '${type}'.`,
|
|
67
|
+
suggestion: "Use 'list-templates' to discover available template types."
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// validate the schema of the resolved template
|
|
72
|
+
if (template.schema && properties) {
|
|
73
|
+
const { isValid, errors } = validate(properties, template.schema);
|
|
74
|
+
if (!isValid) {
|
|
75
|
+
return {
|
|
76
|
+
content: [],
|
|
77
|
+
isError: true,
|
|
78
|
+
structuredContent: {
|
|
79
|
+
code: "E_ARGS_INVALID",
|
|
80
|
+
message: `Invalid arguments for template '${type}'.`,
|
|
81
|
+
suggestion: "Call 'get-template' to inspect required fields and formats, then retry.",
|
|
82
|
+
details: { errors }
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
await projectService.createFromTemplate(type, ctx);
|
|
88
|
+
await projectService.transformFiles(ctx);
|
|
89
|
+
const rendered = templates.getRenderedFiles();
|
|
90
|
+
const files = rendered.map((f) => f.outputPath);
|
|
91
|
+
const count = files.length;
|
|
92
|
+
const symbolPath = ctx.symbolPath || rendered[0]?.symbolPath || rendered[0]?.outputPath;
|
|
93
|
+
const logs = [`createFromTemplate:${type}`, `transformFiles:done`, `files:${count}`];
|
|
94
|
+
return {
|
|
95
|
+
content: [],
|
|
96
|
+
structuredContent: {
|
|
97
|
+
files,
|
|
98
|
+
count,
|
|
99
|
+
symbolPath,
|
|
100
|
+
logs,
|
|
101
|
+
warnings: warnings.length ? warnings : undefined
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
});
|