From 5833e3b74ff4b0a5c2b7f348ac5b7470f46b518e Mon Sep 17 00:00:00 2001 From: Romain Lenzotti Date: Sat, 3 Oct 2026 18:10:30 +0200 Subject: [PATCH] fix(cli): align the set-workspace output schema with the returned payload The tool returned pkg while its output schema declared packageJson. Also fix two commands in the docs: the generator name is positional and templates are scaffolded with tsed template. Co-Authored-By: Claude Opus 5.5 --- docs/guide/cli/templates.md | 4 +- docs/introduction/whats-new-v7.md | 2 +- .../mcp/tools/setWorkspaceTool.spec.ts | 70 +++++++++++++++++++ .../commands/mcp/tools/setWorkspaceTool.ts | 2 +- 4 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 packages/cli/src/commands/mcp/tools/setWorkspaceTool.spec.ts diff --git a/docs/guide/cli/templates.md b/docs/guide/cli/templates.md index 4c1ab817f..62af145b6 100644 --- a/docs/guide/cli/templates.md +++ b/docs/guide/cli/templates.md @@ -23,13 +23,13 @@ export default defineTemplate({ }); ``` -Run it with `tsed generate service --name Logger`. +Run it with `tsed generate service Logger`. ::: tip Need a starting point? To scaffold a boilerplate file in `.templates/`, run: ```bash -tsed generate template +tsed template ``` ::: diff --git a/docs/introduction/whats-new-v7.md b/docs/introduction/whats-new-v7.md index 050d58f1b..c62de6ce9 100644 --- a/docs/introduction/whats-new-v7.md +++ b/docs/introduction/whats-new-v7.md @@ -56,7 +56,7 @@ export default defineTemplate({ ``` - Hooks (`$afterCreateSourceFile`) integrate with `ts-morph` to auto-format or inject imports post-generation. -- `tsed generate template` scaffolds boilerplate TypeScript templates in `.templates/`, replacing legacy Handlebars snippets with native template literals. +- `tsed template` scaffolds boilerplate TypeScript templates in `.templates/`, replacing legacy Handlebars snippets with native template literals. Templates currently target the functional API exclusively; decorate classes aren’t required. diff --git a/packages/cli/src/commands/mcp/tools/setWorkspaceTool.spec.ts b/packages/cli/src/commands/mcp/tools/setWorkspaceTool.spec.ts new file mode 100644 index 000000000..0c5e8f30d --- /dev/null +++ b/packages/cli/src/commands/mcp/tools/setWorkspaceTool.spec.ts @@ -0,0 +1,70 @@ +import {CliFs, ProjectPackageJson} from "@tsed/cli-core"; +import {DITest, injector} from "@tsed/di"; +import {afterEach, beforeEach, describe, expect, it, vi} from "vitest"; + +import {setWorkspaceTool} from "./setWorkspaceTool.js"; + +describe("setWorkspaceTool", () => { + let fs: {exists: ReturnType}; + let projectPackage: any; + + beforeEach(() => { + DITest.create({env: "test"}); + + fs = { + exists: vi.fn().mockReturnValue(true) + }; + projectPackage = { + cwd: "/project", + preferences: { + convention: "conv_default", + packageManager: "yarn", + platform: "express", + runtime: "node" + }, + setCWD: vi.fn(), + toJSON: vi.fn().mockReturnValue({name: "tsed-app"}) + }; + + injector() + .addProvider(CliFs, { + useValue: fs + }) + .addProvider(ProjectPackageJson, { + useValue: projectPackage + }); + }); + afterEach(() => DITest.reset()); + + it("should return a structured content that matches the declared output schema", async () => { + const instance = injector().invoke(setWorkspaceTool); + + const result: any = await instance.handler({cwd: "/project"} as any, {} as any); + const outputSchema = (instance.outputSchema as any)["~standard"].jsonSchema.output({target: "draft-2020-12"}); + const declared = Object.keys(outputSchema.properties); + + expect(projectPackage.setCWD).toHaveBeenCalledWith("/project"); + expect(result.structuredContent).toEqual({ + cwd: "/project", + pkg: {name: "tsed-app"}, + preferences: { + convention: "conv_default", + packageManager: "yarn", + platform: "express", + runtime: "node" + } + }); + expect(Object.keys(result.structuredContent).every((key) => declared.includes(key))).toBe(true); + }); + + it("should return an error when the directory does not exist", async () => { + fs.exists.mockReturnValue(false); + + const instance = injector().invoke(setWorkspaceTool); + const result: any = await instance.handler({cwd: "/missing"} as any, {} as any); + + expect(projectPackage.setCWD).not.toHaveBeenCalled(); + expect(result.isError).toBe(true); + expect(result.structuredContent.code).toBe("E_CWD_NOT_FOUND"); + }); +}); diff --git a/packages/cli/src/commands/mcp/tools/setWorkspaceTool.ts b/packages/cli/src/commands/mcp/tools/setWorkspaceTool.ts index 359ddaac7..a3bbfc614 100644 --- a/packages/cli/src/commands/mcp/tools/setWorkspaceTool.ts +++ b/packages/cli/src/commands/mcp/tools/setWorkspaceTool.ts @@ -27,7 +27,7 @@ export const setWorkspaceTool = defineTool({ }), outputSchema: s.object({ cwd: s.string().description("Resolved project root (nearest package.json directory or the provided path)."), - packageJson: s.object().optional().description("Resolved package json"), + pkg: s.object().optional().description("Resolved package.json content"), preferences: ProjectPreferenceSchema }), async handler(args) {