@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,47 @@
|
|
|
1
|
+
import { defineTool } from "@tsed/cli-mcp";
|
|
2
|
+
import { inject } from "@tsed/di";
|
|
3
|
+
import { s } from "@tsed/schema";
|
|
4
|
+
import { CliTemplatesService } from "../../../services/CliTemplatesService.js";
|
|
5
|
+
import { resolveSchema } from "../../../utils/resolveSchema.js";
|
|
6
|
+
export const getTemplateTool = defineTool({
|
|
7
|
+
name: "get-template",
|
|
8
|
+
title: "Get template",
|
|
9
|
+
description: "Return full information for a template including its JSON schema (if provided).",
|
|
10
|
+
inputSchema: s.object({
|
|
11
|
+
id: s.string().required().description("Template id (e.g., 'controller', 'service')")
|
|
12
|
+
}),
|
|
13
|
+
outputSchema: s.object({
|
|
14
|
+
id: s.string().description("Template id"),
|
|
15
|
+
label: s.string().description("Template label"),
|
|
16
|
+
description: s.string().optional().description("Template description"),
|
|
17
|
+
schema: s
|
|
18
|
+
.object()
|
|
19
|
+
.optional()
|
|
20
|
+
.description("Additional properties to provide to generate-file tool for this template (beyond the global 'id' and 'name' fields)")
|
|
21
|
+
}),
|
|
22
|
+
async handler(args) {
|
|
23
|
+
const { id } = args;
|
|
24
|
+
const templates = inject(CliTemplatesService);
|
|
25
|
+
const tpl = templates.get(id);
|
|
26
|
+
if (!tpl) {
|
|
27
|
+
return {
|
|
28
|
+
content: [],
|
|
29
|
+
isError: true,
|
|
30
|
+
structuredContent: {
|
|
31
|
+
code: "E_TEMPLATE_UNKNOWN",
|
|
32
|
+
message: `Unknown template id '${id}'.`,
|
|
33
|
+
suggestion: "Use 'list-templates' to discover available template types."
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
content: [],
|
|
39
|
+
structuredContent: {
|
|
40
|
+
id: tpl.id,
|
|
41
|
+
label: tpl.label,
|
|
42
|
+
description: tpl.description,
|
|
43
|
+
schema: await resolveSchema(tpl.schema)
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { generateTool } from "./generateTool.js";
|
|
2
|
+
import { getTemplateTool } from "./getTemplateTool.js";
|
|
3
|
+
import { initProjectTool } from "./initProjectTool.js";
|
|
4
|
+
import { listTemplatesTool } from "./listTemplatesTool.js";
|
|
5
|
+
import { setWorkspaceTool } from "./setWorkspaceTool.js";
|
|
6
|
+
export default [setWorkspaceTool, listTemplatesTool, getTemplateTool, generateTool, initProjectTool];
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { CliService, ProjectPackageJson } from "@tsed/cli-core";
|
|
2
|
+
import { defineTool } from "@tsed/cli-mcp";
|
|
3
|
+
import { context, inject } from "@tsed/di";
|
|
4
|
+
import { s } from "@tsed/schema";
|
|
5
|
+
import { CliTemplatesService } from "../../../services/CliTemplatesService.js";
|
|
6
|
+
import { InitMCPSchema } from "../schema/InitMCPSchema.js";
|
|
7
|
+
export const initProjectTool = defineTool({
|
|
8
|
+
name: "init-project",
|
|
9
|
+
title: "Initialize Ts.ED project",
|
|
10
|
+
description: "Initialize a new Ts.ED project in the current workspace. Fetch `tsed://init/options`, ask the user which platform, features, and other options they want, then pass the selected values here along with `cwd`.",
|
|
11
|
+
inputSchema: InitMCPSchema,
|
|
12
|
+
outputSchema: s.object({
|
|
13
|
+
files: s.array().items(s.string()).description("List of generated files."),
|
|
14
|
+
count: s.number().description("Number of files generated."),
|
|
15
|
+
projectName: s.string().optional().description("Resolved project name."),
|
|
16
|
+
cwd: s.string().optional().description("Resolved workspace directory in which the project was initialized."),
|
|
17
|
+
logs: s.array().items(s.string()).optional().description("Execution logs"),
|
|
18
|
+
warnings: s.array().items(s.string()).optional().description("Non blocking warnings")
|
|
19
|
+
}),
|
|
20
|
+
async handler(input) {
|
|
21
|
+
const cliService = inject(CliService);
|
|
22
|
+
const projectPackage = inject(ProjectPackageJson);
|
|
23
|
+
const templates = inject(CliTemplatesService);
|
|
24
|
+
projectPackage.setCWD(input.cwd);
|
|
25
|
+
// If the current workspace already looks initialized, block to prevent accidental re-init
|
|
26
|
+
if (projectPackage.preferences?.packageManager) {
|
|
27
|
+
return {
|
|
28
|
+
content: [],
|
|
29
|
+
isError: true,
|
|
30
|
+
structuredContent: {
|
|
31
|
+
code: "E_PROJECT_ALREADY_INITIALIZED",
|
|
32
|
+
message: "This workspace already appears to be an initialized Ts.ED project.",
|
|
33
|
+
suggestion: "Use 'generate-file' to add new files, or call 'set-workspace' with a different folder to initialize a new project."
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const warnings = [];
|
|
38
|
+
// Build options and map context (skip prompts by default)
|
|
39
|
+
const initialOptions = {
|
|
40
|
+
skipPrompt: true,
|
|
41
|
+
...input
|
|
42
|
+
};
|
|
43
|
+
await cliService.exec("init", initialOptions, context());
|
|
44
|
+
// Collect rendered files from templates service (same pattern as generateTool)
|
|
45
|
+
const rendered = templates.getRenderedFiles();
|
|
46
|
+
const files = rendered.map((f) => f.outputPath);
|
|
47
|
+
const logs = [
|
|
48
|
+
`init:root:${projectPackage.cwd ?? "."}`,
|
|
49
|
+
`init:platform:${projectPackage.preferences.platform}`,
|
|
50
|
+
`files:${files.length}`
|
|
51
|
+
];
|
|
52
|
+
return {
|
|
53
|
+
content: [],
|
|
54
|
+
structuredContent: {
|
|
55
|
+
files,
|
|
56
|
+
count: files.length,
|
|
57
|
+
projectName: projectPackage.name,
|
|
58
|
+
cwd: projectPackage.cwd,
|
|
59
|
+
logs,
|
|
60
|
+
warnings: warnings.length ? warnings : undefined
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { defineTool } from "@tsed/cli-mcp";
|
|
2
|
+
import { inject } from "@tsed/di";
|
|
3
|
+
import { array, object, string } from "@tsed/schema";
|
|
4
|
+
import { CliTemplatesService } from "../../../services/CliTemplatesService.js";
|
|
5
|
+
import { summarizeSchema } from "../../../utils/summarizeSchema.js";
|
|
6
|
+
export const listTemplatesTool = defineTool({
|
|
7
|
+
name: "list-templates",
|
|
8
|
+
title: "List templates",
|
|
9
|
+
description: "List available Ts.ED templates for generation (tsed generate). Optionally filter by type substring.",
|
|
10
|
+
inputSchema: object({
|
|
11
|
+
search: string().description("Filter by template id/label substring (case-insensitive).")
|
|
12
|
+
}),
|
|
13
|
+
outputSchema: object({
|
|
14
|
+
items: array().items(object({
|
|
15
|
+
id: string(),
|
|
16
|
+
label: string().optional(),
|
|
17
|
+
description: string().optional(),
|
|
18
|
+
required: array().items(string()).optional(),
|
|
19
|
+
properties: object().optional()
|
|
20
|
+
}))
|
|
21
|
+
}),
|
|
22
|
+
async handler(args) {
|
|
23
|
+
const { search } = args || {};
|
|
24
|
+
const templates = inject(CliTemplatesService);
|
|
25
|
+
return {
|
|
26
|
+
content: [],
|
|
27
|
+
structuredContent: {
|
|
28
|
+
items: templates.find(search).map((tpl) => ({
|
|
29
|
+
id: tpl.id,
|
|
30
|
+
label: tpl.label,
|
|
31
|
+
description: tpl.description,
|
|
32
|
+
...summarizeSchema(tpl)
|
|
33
|
+
}))
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { isAbsolute, normalize, resolve } from "node:path";
|
|
3
|
+
import { CliFs, PackageManager, ProjectPackageJson } from "@tsed/cli-core";
|
|
4
|
+
import { defineTool } from "@tsed/cli-mcp";
|
|
5
|
+
import { inject } from "@tsed/di";
|
|
6
|
+
import { s } from "@tsed/schema";
|
|
7
|
+
import { ProjectPreferenceSchema } from "../schema/ProjectPreferencesSchema.js";
|
|
8
|
+
function normalizeCwd(input) {
|
|
9
|
+
const abs = isAbsolute(input) ? input : resolve(process.cwd(), input);
|
|
10
|
+
return normalize(abs);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Simplified behavior per MVP:
|
|
14
|
+
* - If the provided cwd exists: set it, resolve the nearest package.json root via ProjectPackageJson, return that resolved cwd.
|
|
15
|
+
* - If the provided cwd does not exist: do not create anything; return an error suggesting to confirm creation and run init-project.
|
|
16
|
+
*/
|
|
17
|
+
export const setWorkspaceTool = defineTool({
|
|
18
|
+
name: "set-workspace",
|
|
19
|
+
title: "Set workspace",
|
|
20
|
+
description: "Define the workspace (current working directory) for subsequent operations. Mirrors the -r option of tsed CLI. If the path exists, returns the resolved project root (nearest package.json). If it doesn't, asks to confirm creation and use init-project.",
|
|
21
|
+
inputSchema: s.object({
|
|
22
|
+
cwd: s.string().required().description("Absolute or relative path to use as workspace root.")
|
|
23
|
+
}),
|
|
24
|
+
outputSchema: s.object({
|
|
25
|
+
cwd: s.string().description("Resolved project root (nearest package.json directory or the provided path)."),
|
|
26
|
+
packageJson: s.object().optional().description("Resolved package json"),
|
|
27
|
+
preferences: ProjectPreferenceSchema
|
|
28
|
+
}),
|
|
29
|
+
async handler(args) {
|
|
30
|
+
const { cwd: raw } = args;
|
|
31
|
+
const cwd = normalizeCwd(raw);
|
|
32
|
+
const fs = inject(CliFs);
|
|
33
|
+
const projectPackage = inject(ProjectPackageJson);
|
|
34
|
+
if (fs.exists(cwd)) {
|
|
35
|
+
// Set the base CWD for the CLI services (this resolves to nearest package.json)
|
|
36
|
+
projectPackage.setCWD(cwd);
|
|
37
|
+
// Resolved project root
|
|
38
|
+
const resolved = projectPackage.cwd;
|
|
39
|
+
return {
|
|
40
|
+
content: [],
|
|
41
|
+
structuredContent: {
|
|
42
|
+
cwd: resolved,
|
|
43
|
+
pkg: projectPackage.toJSON(),
|
|
44
|
+
preferences: {
|
|
45
|
+
convention: projectPackage.preferences.convention,
|
|
46
|
+
packageManager: projectPackage.preferences.packageManager,
|
|
47
|
+
platform: projectPackage.preferences.platform,
|
|
48
|
+
runtime: projectPackage.preferences.runtime
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
content: [],
|
|
55
|
+
isError: true,
|
|
56
|
+
structuredContent: {
|
|
57
|
+
cwd,
|
|
58
|
+
code: "E_CWD_NOT_FOUND",
|
|
59
|
+
message: `Directory '${cwd}' does not exist.`,
|
|
60
|
+
suggestion: "Confirm you want to create this folder, then call 'init-project' with { cwd: '<path>', ... } to scaffold a new Ts.ED project."
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CliFs, command, inject, normalizePath, ProjectPackageJson } from "@tsed/cli-core";
|
|
2
|
+
import { logger } from "@tsed/di";
|
|
2
3
|
import { CliRunScript } from "../../services/CliRunScript.js";
|
|
3
4
|
export class RunCmd {
|
|
4
5
|
constructor() {
|
|
@@ -10,13 +11,15 @@ export class RunCmd {
|
|
|
10
11
|
const cmd = "node";
|
|
11
12
|
const args = ["--import", "@swc-node/register/esm-register"];
|
|
12
13
|
const path = normalizePath("src/bin/index.ts");
|
|
14
|
+
logger().info(`Run ${cmd} ${[...args, path, ctx.command, ...ctx.rawArgs].join(" ")}`);
|
|
13
15
|
await this.runScript.run(cmd, [...args, path, ctx.command, ...ctx.rawArgs], {
|
|
14
16
|
env: process.env
|
|
15
17
|
});
|
|
16
18
|
return [];
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
|
-
command(
|
|
21
|
+
command({
|
|
22
|
+
token: RunCmd,
|
|
20
23
|
name: "run",
|
|
21
24
|
description: "Run a project level command",
|
|
22
25
|
args: {
|
|
@@ -97,9 +97,8 @@ export class UpdateCmd {
|
|
|
97
97
|
return version && isGreaterThan(version, this.cliPackage.version) ? version : this.cliPackage.version;
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
-
command(
|
|
100
|
+
command({
|
|
101
|
+
token: UpdateCmd,
|
|
101
102
|
name: "update",
|
|
102
|
-
description: "Update all Ts.ED packages used by your project"
|
|
103
|
-
args: {},
|
|
104
|
-
options: {}
|
|
103
|
+
description: "Update all Ts.ED packages used by your project"
|
|
105
104
|
});
|
package/lib/esm/index.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
import "@tsed/logger-std";
|
|
1
2
|
import "./templates/index.js";
|
|
2
|
-
|
|
3
|
+
import "./services/CliStats.js";
|
|
3
4
|
export * from "./commands/add/AddCmd.js";
|
|
4
5
|
export * from "./commands/generate/GenerateCmd.js";
|
|
6
|
+
export { default as commands } from "./commands/index.js";
|
|
5
7
|
export * from "./commands/init/config/FeaturesPrompt.js";
|
|
6
8
|
export * from "./commands/init/config/FeaturesPrompt.js";
|
|
7
9
|
export * from "./commands/init/InitCmd.js";
|
|
8
10
|
export * from "./commands/init/prompts/getFeaturesPrompt.js";
|
|
11
|
+
export { default as resources } from "./commands/mcp/resources/index.js";
|
|
12
|
+
export { default as tools } from "./commands/mcp/tools/index.js";
|
|
9
13
|
export * from "./commands/update/UpdateCmd.js";
|
|
10
14
|
export * from "./constants/index.js";
|
|
11
15
|
export * from "./fn/exec.js";
|
|
@@ -17,3 +21,4 @@ export * from "./services/CliProjectService.js";
|
|
|
17
21
|
export * from "./services/CliTemplatesService.js";
|
|
18
22
|
export * from "./services/ProjectClient.js";
|
|
19
23
|
export * from "./utils/defineTemplate.js";
|
|
24
|
+
export { CliCore } from "@tsed/cli-core";
|
|
@@ -49,12 +49,10 @@ export function transformServerFile(project, data) {
|
|
|
49
49
|
});
|
|
50
50
|
project.addNamespaceImport(sourceFile, isFeature ? "./rest/index.js" : "./controllers/rest/index.js", "rest");
|
|
51
51
|
project.addMountPath(data.route || "/rest", "...Object.values(rest)");
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
project.addMountPath("/", "...Object.values(pages)");
|
|
58
|
-
}
|
|
52
|
+
sourceFile.addImportDeclaration({
|
|
53
|
+
moduleSpecifier: isFeature ? "./pages/index.js" : "./controllers/pages/index.js",
|
|
54
|
+
namespaceImport: "pages"
|
|
55
|
+
});
|
|
56
|
+
project.addMountPath("/", "...Object.values(pages)");
|
|
59
57
|
}
|
|
60
58
|
}
|
|
@@ -15,7 +15,9 @@ import { CliTemplatesService } from "./CliTemplatesService.js";
|
|
|
15
15
|
export class CliProjectService {
|
|
16
16
|
constructor() {
|
|
17
17
|
this.templates = inject(CliTemplatesService);
|
|
18
|
-
|
|
18
|
+
}
|
|
19
|
+
get rootDir() {
|
|
20
|
+
return constant("project.rootDir", "");
|
|
19
21
|
}
|
|
20
22
|
get srcDir() {
|
|
21
23
|
return join(...[this.rootDir, constant("project.srcDir")].filter(Boolean));
|
|
@@ -32,8 +34,10 @@ export class CliProjectService {
|
|
|
32
34
|
this.project = new ProjectClient({
|
|
33
35
|
rootDir: this.rootDir
|
|
34
36
|
});
|
|
35
|
-
const files = fs.globSync(["
|
|
36
|
-
files
|
|
37
|
+
const files = fs.globSync([join(this.rootDir, "**/*.ts"), "!node_modules", "!node_modules/**", "!**/node_modules/**"]);
|
|
38
|
+
files
|
|
39
|
+
.filter((file) => !file.includes("node_modules"))
|
|
40
|
+
.forEach((file) => {
|
|
37
41
|
this.project.createSourceFile(file, fs.readFileSync(file, "utf8"), {
|
|
38
42
|
overwrite: true
|
|
39
43
|
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { CliHttpClient, ProjectPackageJson } from "@tsed/cli-core";
|
|
2
|
+
import { constant, inject, injectable } from "@tsed/di";
|
|
3
|
+
import * as os from "os";
|
|
4
|
+
export class CliStats extends CliHttpClient {
|
|
5
|
+
constructor() {
|
|
6
|
+
super(...arguments);
|
|
7
|
+
this.disabled = constant("stats.disabled", false);
|
|
8
|
+
this.host = constant("stats.url", "https://api.tsed.dev");
|
|
9
|
+
this.projectPackage = inject(ProjectPackageJson);
|
|
10
|
+
}
|
|
11
|
+
sendInit(opts) {
|
|
12
|
+
if (!this.disabled) {
|
|
13
|
+
const data = {
|
|
14
|
+
features: [],
|
|
15
|
+
is_success: true,
|
|
16
|
+
...opts,
|
|
17
|
+
os: os.type(),
|
|
18
|
+
convention: this.projectPackage.preferences.convention === "conv_default" ? "tsed" : "angular",
|
|
19
|
+
platform: this.projectPackage.preferences.platform,
|
|
20
|
+
package_manager: this.projectPackage.preferences.packageManager,
|
|
21
|
+
runtime: this.projectPackage.preferences.runtime,
|
|
22
|
+
channel: opts.channel || "cli",
|
|
23
|
+
cli_version: constant("version", ""),
|
|
24
|
+
tsed_version: this.projectPackage.dependencies["@tsed/platform-http"]
|
|
25
|
+
};
|
|
26
|
+
return this.post("/rest/cli/stats", {
|
|
27
|
+
data
|
|
28
|
+
}).catch((er) => {
|
|
29
|
+
return null;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
$onFinish(data, er) {
|
|
34
|
+
if (data.commandName === "init") {
|
|
35
|
+
return this.sendInit({
|
|
36
|
+
channel: "cli",
|
|
37
|
+
is_success: !er,
|
|
38
|
+
features: data.features
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
onSuccess(options) { }
|
|
43
|
+
onError(error, options) { }
|
|
44
|
+
}
|
|
45
|
+
injectable(CliStats);
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { CliFs } from "@tsed/cli-core";
|
|
3
|
-
import { constant, inject, injectable, injectMany, logger } from "@tsed/di";
|
|
3
|
+
import { constant, context, inject, injectable, injectMany, logger } from "@tsed/di";
|
|
4
4
|
import { globby } from "globby";
|
|
5
5
|
import { TEMPLATE_DIR } from "../constants/index.js";
|
|
6
6
|
import { mapDefaultTemplateOptions } from "./mappers/mapDefaultTemplateOptions.js";
|
|
7
7
|
export class CliTemplatesService {
|
|
8
8
|
constructor() {
|
|
9
|
-
this.rootDir = constant("project.rootDir", process.cwd());
|
|
10
9
|
this.fs = inject(CliFs);
|
|
11
|
-
this.#templates = new Map();
|
|
12
10
|
}
|
|
11
|
+
// readonly renderedFiles: TemplateRenderReturnType[] = [];
|
|
13
12
|
#customTemplates;
|
|
14
|
-
|
|
13
|
+
get rootDir() {
|
|
14
|
+
return constant("project.rootDir", "");
|
|
15
|
+
}
|
|
15
16
|
get srcDir() {
|
|
16
17
|
return join(...[this.rootDir, constant("project.srcDir")].filter(Boolean));
|
|
17
18
|
}
|
|
@@ -89,7 +90,7 @@ export class CliTemplatesService {
|
|
|
89
90
|
template.fileName?.replace("{{symbolName}}", opts.symbolName)?.replace("{{srcDir}}", this.srcDir) ||
|
|
90
91
|
opts.symbolName;
|
|
91
92
|
const outputPath = `${filePath}${template.ext ? "." + template.ext : ""}`;
|
|
92
|
-
return {
|
|
93
|
+
return this.pushRenderResult({
|
|
93
94
|
templateId,
|
|
94
95
|
content: render,
|
|
95
96
|
outputPath,
|
|
@@ -97,20 +98,31 @@ export class CliTemplatesService {
|
|
|
97
98
|
symbolName: opts.symbolName,
|
|
98
99
|
symbolPath: opts.symbolPath,
|
|
99
100
|
symbolPathBasename: opts.symbolPathBasename
|
|
100
|
-
};
|
|
101
|
+
});
|
|
101
102
|
}
|
|
102
103
|
else {
|
|
103
104
|
const from = data.from || TEMPLATE_DIR;
|
|
104
105
|
const fromPath = join(from, templateId.replace("{{srcDir}}", "src"));
|
|
105
106
|
if (await this.fs.fileExists(fromPath)) {
|
|
106
107
|
const content = await inject(CliFs).readFile(fromPath);
|
|
107
|
-
return {
|
|
108
|
+
return this.pushRenderResult({
|
|
108
109
|
templateId,
|
|
109
110
|
content,
|
|
110
111
|
outputPath: templateId.replace("{{srcDir}}", constant("project.srcDir", ""))
|
|
111
|
-
};
|
|
112
|
+
});
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
}
|
|
116
|
+
getRenderedFiles() {
|
|
117
|
+
const $ctx = context();
|
|
118
|
+
if (!$ctx?.has("renderedFiles")) {
|
|
119
|
+
$ctx?.set("renderedFiles", []);
|
|
120
|
+
}
|
|
121
|
+
return $ctx?.get("renderedFiles") || [];
|
|
122
|
+
}
|
|
123
|
+
pushRenderResult(renderedFile) {
|
|
124
|
+
this.getRenderedFiles().push(renderedFile);
|
|
125
|
+
return renderedFile;
|
|
126
|
+
}
|
|
115
127
|
}
|
|
116
128
|
injectable(CliTemplatesService);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineTemplate } from "../utils/defineTemplate.js";
|
|
2
|
+
import { CliHttpClient } from "@tsed/cli-core";
|
|
3
|
+
import { inject } from "@tsed/di";
|
|
4
|
+
export default defineTemplate({
|
|
5
|
+
id: "agents",
|
|
6
|
+
label: "AGENTS.md",
|
|
7
|
+
description: "Create AGENTS.md designed for AI project and Ts.ED",
|
|
8
|
+
fileName: "AGENTS",
|
|
9
|
+
ext: "md",
|
|
10
|
+
outputDir: ".",
|
|
11
|
+
hidden: true,
|
|
12
|
+
preserveCase: true,
|
|
13
|
+
async render() {
|
|
14
|
+
const httpClient = inject(CliHttpClient);
|
|
15
|
+
return httpClient.get("https://tsed.dev/ai/AGENTS.md");
|
|
16
|
+
}
|
|
17
|
+
});
|
|
@@ -3,12 +3,13 @@ import { camelCase, pascalCase } from "change-case";
|
|
|
3
3
|
export default defineTemplate({
|
|
4
4
|
id: "async.factory",
|
|
5
5
|
label: "Async Factory",
|
|
6
|
+
description: "Generate an async factory token for Ts.ED DI in src/services.",
|
|
6
7
|
fileName: "{{symbolName}}.factory?",
|
|
7
8
|
outputDir: "{{srcDir}}/services",
|
|
8
9
|
render(symbolName) {
|
|
9
10
|
const camelName = camelCase(symbolName);
|
|
10
11
|
const optName = pascalCase(symbolName + "Options");
|
|
11
|
-
return `import {injectable} from "@tsed/di";
|
|
12
|
+
return `import {injectable, constant} from "@tsed/di";
|
|
12
13
|
|
|
13
14
|
interface ${optName} {
|
|
14
15
|
|
|
@@ -17,7 +18,7 @@ interface ${optName} {
|
|
|
17
18
|
declare global {
|
|
18
19
|
namespace TsED {
|
|
19
20
|
interface Configuration extends Record<string, any> {
|
|
20
|
-
${camelName}:
|
|
21
|
+
${camelName}: ${optName};
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
}
|
|
@@ -33,6 +34,6 @@ export const ${symbolName} = injectable(Symbol.for("${symbolName}"))
|
|
|
33
34
|
})
|
|
34
35
|
.token();
|
|
35
36
|
|
|
36
|
-
export type {
|
|
37
|
+
export type ${symbolName} = typeof ${symbolName};`;
|
|
37
38
|
}
|
|
38
39
|
});
|
|
@@ -9,16 +9,9 @@ export default defineTemplate({
|
|
|
9
9
|
outputDir: ".",
|
|
10
10
|
hidden: true,
|
|
11
11
|
preserveCase: true,
|
|
12
|
-
prompts() {
|
|
13
|
-
return [];
|
|
14
|
-
},
|
|
15
12
|
render(_, context) {
|
|
16
13
|
const barrels = $alter("$alterBarrels", {
|
|
17
|
-
directory: [
|
|
18
|
-
"./src/controllers/rest",
|
|
19
|
-
context.commands && "./src/bin/commands",
|
|
20
|
-
(context.swagger || context.oidc) && "./src/controllers/pages"
|
|
21
|
-
].filter(Boolean),
|
|
14
|
+
directory: ["./src/controllers/rest", context.commands && "./src/bin/commands", "./src/controllers/pages"].filter(Boolean),
|
|
22
15
|
exclude: ["**/__mock__", "**/__mocks__", "**/*.spec.ts"],
|
|
23
16
|
delete: true
|
|
24
17
|
});
|
|
@@ -3,6 +3,7 @@ import { kebabCase } from "change-case";
|
|
|
3
3
|
export default defineTemplate({
|
|
4
4
|
id: "command",
|
|
5
5
|
label: "Command",
|
|
6
|
+
description: "Create a CLI command provider with prompts, context mapping and tasks in src/bin/commands.",
|
|
6
7
|
fileName: "{{symbolName}}.command",
|
|
7
8
|
outputDir: "{{srcDir}}/bin/commands",
|
|
8
9
|
render(symbolName) {
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { defineTemplate } from "../utils/defineTemplate.js";
|
|
2
|
+
import { object, string } from "@tsed/schema";
|
|
2
3
|
export default defineTemplate({
|
|
3
4
|
id: "controller",
|
|
4
5
|
label: "Controller",
|
|
6
|
+
description: "Create a new controller class with a sample GET endpoint in src/controllers.",
|
|
5
7
|
fileName: "{{symbolName}}.controller",
|
|
6
8
|
outputDir: "{{srcDir}}/controllers",
|
|
9
|
+
// Validation schema specific to this template (do not include global fields `type` and `name`)
|
|
10
|
+
schema: object({
|
|
11
|
+
route: string().pattern(/^\//).description("Route starting with '/' (e.g., '/users')"),
|
|
12
|
+
directory: string().description("Sub-directory under src/controllers")
|
|
13
|
+
}),
|
|
7
14
|
prompts(context) {
|
|
8
15
|
return [
|
|
9
16
|
{
|
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
import { defineTemplate } from "../utils/defineTemplate.js";
|
|
2
|
+
import { s } from "@tsed/schema";
|
|
3
|
+
const choices = [
|
|
4
|
+
{ name: "Class Decorator", value: "class" },
|
|
5
|
+
{ name: "Generic Decorator (class, property)", value: "generic" },
|
|
6
|
+
{ name: "Method Decorator", value: "method" },
|
|
7
|
+
{ name: "Parameter Decorator", value: "param" },
|
|
8
|
+
{ name: "Property Decorator", value: "property" },
|
|
9
|
+
{ name: "Property Decorator (with @Property)", value: "prop" },
|
|
10
|
+
{ name: "Parameters Decorator", value: "parameters" },
|
|
11
|
+
{ name: "Endpoint Decorator", value: "endpoint" },
|
|
12
|
+
{ name: "Middleware Decorator", value: "middleware" }
|
|
13
|
+
];
|
|
2
14
|
export default defineTemplate({
|
|
3
15
|
id: "decorator",
|
|
4
16
|
label: "Decorator",
|
|
17
|
+
description: "Scaffold a custom decorator with variants (class, generic, method, parameter, property, endpoint, middleware) in src/decorators.",
|
|
5
18
|
fileName: "{{symbolName}}",
|
|
6
19
|
outputDir: "{{srcDir}}/decorators",
|
|
20
|
+
schema: s.object({
|
|
21
|
+
templateType: s
|
|
22
|
+
.string()
|
|
23
|
+
.enum("class", "generic", "method", "param", "property", "prop", "parameters", "endpoint", "middleware")
|
|
24
|
+
.customKey("x-choices", choices)
|
|
25
|
+
.default("class")
|
|
26
|
+
.description("sub-type of the template to generate the decorator")
|
|
27
|
+
}),
|
|
7
28
|
prompts(context) {
|
|
8
29
|
return [
|
|
9
30
|
{
|
|
@@ -13,17 +34,7 @@ export default defineTemplate({
|
|
|
13
34
|
when(state) {
|
|
14
35
|
return !!(["decorator"].includes(state.type || context.type) || context.templateType);
|
|
15
36
|
},
|
|
16
|
-
choices
|
|
17
|
-
{ name: "Class Decorator", value: "class" },
|
|
18
|
-
{ name: "Generic Decorator (class, property)", value: "generic" },
|
|
19
|
-
{ name: "Method Decorator", value: "method" },
|
|
20
|
-
{ name: "Parameter Decorator", value: "param" },
|
|
21
|
-
{ name: "Property Decorator", value: "property" },
|
|
22
|
-
{ name: "Property Decorator (with @Property)", value: "prop" },
|
|
23
|
-
{ name: "Parameters Decorator", value: "parameters" },
|
|
24
|
-
{ name: "Endpoint Decorator", value: "endpoint" },
|
|
25
|
-
{ name: "Middleware Decorator", value: "middleware" }
|
|
26
|
-
],
|
|
37
|
+
choices,
|
|
27
38
|
default: "class"
|
|
28
39
|
}
|
|
29
40
|
];
|
|
@@ -33,6 +33,7 @@ ENV NODE_ENV production`;
|
|
|
33
33
|
defineTemplate({
|
|
34
34
|
id: "dockerfile.yarn",
|
|
35
35
|
label: "Dockerfile (Yarn classic)",
|
|
36
|
+
description: "Generate a multi-stage Dockerfile for production builds using Yarn classic.",
|
|
36
37
|
fileName: "Dockerfile",
|
|
37
38
|
outputDir: ".",
|
|
38
39
|
ext: null,
|
|
@@ -72,6 +73,7 @@ CMD ["pm2-runtime", "start", "processes.config.cjs", "--env", "production"]
|
|
|
72
73
|
defineTemplate({
|
|
73
74
|
id: "dockerfile.yarn_berry",
|
|
74
75
|
label: "Dockerfile (Yarn Berry)",
|
|
76
|
+
description: "Generate a multi-stage Dockerfile for production builds using Yarn Berry (modern Yarn).",
|
|
75
77
|
fileName: "Dockerfile",
|
|
76
78
|
outputDir: ".",
|
|
77
79
|
ext: null,
|
|
@@ -114,6 +116,7 @@ CMD ["pm2-runtime", "start", "processes.config.cjs", "--env", "production"]
|
|
|
114
116
|
defineTemplate({
|
|
115
117
|
id: "dockerfile.npm",
|
|
116
118
|
label: "Dockerfile (NPM)",
|
|
119
|
+
description: "Generate a multi-stage Dockerfile for production builds using NPM.",
|
|
117
120
|
fileName: "Dockerfile",
|
|
118
121
|
outputDir: ".",
|
|
119
122
|
ext: null,
|
|
@@ -152,6 +155,7 @@ CMD ["pm2-runtime", "start", "processes.config.cjs", "--env", "production"]`;
|
|
|
152
155
|
defineTemplate({
|
|
153
156
|
id: "dockerfile.pnpm",
|
|
154
157
|
label: "Dockerfile (PNPM)",
|
|
158
|
+
description: "Generate a multi-stage Dockerfile for production builds using PNPM.",
|
|
155
159
|
fileName: "Dockerfile",
|
|
156
160
|
outputDir: ".",
|
|
157
161
|
ext: null,
|
|
@@ -191,6 +195,7 @@ CMD ["pm2-runtime", "start", "processes.config.cjs", "--env", "production"]
|
|
|
191
195
|
defineTemplate({
|
|
192
196
|
id: "dockerfile.bun",
|
|
193
197
|
label: "Dockerfile (Bun)",
|
|
198
|
+
description: "Generate a multi-stage Dockerfile for production builds using Bun.",
|
|
194
199
|
fileName: "Dockerfile",
|
|
195
200
|
outputDir: ".",
|
|
196
201
|
ext: null,
|
|
@@ -2,6 +2,7 @@ import { defineTemplate } from "../utils/defineTemplate.js";
|
|
|
2
2
|
export default defineTemplate({
|
|
3
3
|
id: "exception-filter",
|
|
4
4
|
label: "Exception Filter",
|
|
5
|
+
description: "Create an exception filter class annotated with @Catch to handle thrown errors in src/filters.",
|
|
5
6
|
fileName: "{{symbolName}}.exception-filter",
|
|
6
7
|
outputDir: "{{srcDir}}/filters",
|
|
7
8
|
render(symbolName) {
|