Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
dedd060
chore: remove missing logs
Romakita Dec 2, 2025
a04eef4
refactor(cli): update command definitions to use object token syntax
Romakita Dec 10, 2025
2504a8b
refactor(cli-core): remove unused hook decorators and simplify comman…
Romakita Dec 10, 2025
9a26397
refactor(cli): update command definitions to use object shorthand syn…
Romakita Dec 10, 2025
ef55543
refactor(cli-plugins): replace `@OnAdd` decorator usage with `$onAddP…
Romakita Dec 10, 2025
d426538
refactor(cli): restructure MCP commands and tools directories, remove…
Romakita Dec 10, 2025
e44bd12
docs(contributing): add repository guidelines and update contribution…
Romakita Dec 10, 2025
663a64e
test(cli-core): add unit tests for CliFs, CliDockerComposeYaml, CliSe…
Romakita Dec 10, 2025
305c26b
refactor(cli-mcp): remove CLIMCPServer and refactor MCP server lifecy…
Romakita Dec 10, 2025
82bea98
chore(mcp): update integration scripts and add Prisma support in tests
Romakita Dec 10, 2025
07276d5
chore: bump @tsed dependencies to v8.20.0 and update related configur…
Romakita Dec 23, 2025
619d917
refactor(cli): unify feature keys under `orm` and update TypeORM inte…
Romakita Dec 23, 2025
6f1eec0
refactor(cli-core): enhance schema metadata handling and improve comm…
Romakita Dec 23, 2025
966e4b0
feat(cli-core): add input validation via `inputSchema` for commands
Romakita Dec 23, 2025
16ae8da
refactor(cli): replace `InitFileSchema` with `InitSchema` for enhance…
Romakita Dec 23, 2025
a245701
chore: bump @tsed dependencies to v8.20.1 and update related configur…
Romakita Dec 23, 2025
20ddbe0
feat(cli): add `init-options` command to display available init optio…
Romakita Dec 23, 2025
3a956ac
fix: bump @tsed dependencies to v8.21.0 and update related configurat…
Romakita Dec 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Repository Guidelines

## Project Structure & Module Organization

Yarn 4 + Lerna workspaces organize sources under `packages/*`: `cli` hosts command entrypoints and generator templates, `cli-core` handles DI/prompt infrastructure, `cli-mcp` exposes MCP servers and tools, while `cli-plugin-*` packages bundle framework-specific blueprints plus their own tests. `cli-testing` provides shared harnesses, templates live in `packages/cli/templates`, artifacts land in `dist/`, VuePress + TSDoc files stay in `docs/`, and `tools/*` holds automation scripts (TypeScript references, ESLint, Vitest installers).

## Build, Test, and Development Commands

- `yarn build`: runs `monorepo build --verbose` across every workspace.
- `yarn build:references`: refreshes TS project references after renaming or adding packages.
- `yarn test`: executes the Vitest suite once; add `--coverage` for V8 reports.
- `yarn lint` / `yarn lint:fix`: applies the flat ESLint config + Prettier formatting used in CI.
- `yarn docs:serve` / `yarn docs:build`: runs `lerna run build && tsdoc` then serves or builds the VuePress site.

## Coding Style & Naming Conventions

Author TypeScript ES modules with 2-space indentation, double quotes, and trailing commas per the shared Prettier rules. Favor named exports and keep command providers in `packages/cli/src/commands/**/NameCmd.ts`, suffixing classes with `Cmd`. Tests and utilities mirror their source paths, ending in `.spec.ts` or `.integration.spec.ts`. Plugin packages follow `cli-plugin-<feature>` naming; templates underneath use kebab-case folder names. Keep import blocks sorted (enforced by `eslint-plugin-simple-import-sort`) and reserve default exports for entry aggregators such as `packages/cli/src/index.ts`.

## Testing Guidelines

Vitest powers both unit and integration coverage. Co-locate fast tests next to implementation files, while scenario-heavy suites live under `packages/*/test/**`. Use `yarn vitest packages/cli/src/commands/init/InitCmd.spec.ts` to focus a file, prefer `.integration.spec.ts` when exercising generators end-to-end, and ship PRs with `yarn test --coverage` so CI can enforce thresholds. Mock filesystem access via helpers in `cli-testing` instead of touching the real disk.

## Commit & Pull Request Guidelines

Commit messages must satisfy Conventional Commits (see `commitlint.config.js`); scope by workspace, e.g., `feat(cli-plugin-prisma): expand seed template`. Keep subjects under 200 characters and describe behavior, not implementation minutiae. Before opening a pull request, run `yarn build`, `yarn test`, and `yarn lint`, update docs/templates when behavior changes, and link the relevant issue. Summaries should highlight user-facing changes, test evidence, and screenshots or logs when generator output shifts.
17 changes: 11 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# Contributing
# Contributing

## Introduction

First, thank you for considering contributing to Ts.ED! It is people like you that make the open source community such a great community! 😊

We welcome any type of contribution, not just code. You can help with:

- Repository-specific build, testing, and PR expectations are summarized in the [Repository Guidelines](AGENTS.md); please skim them before opening a pull request.

- QA: file bug reports, the more details you can give the better (e.g. screenshots with the console open)
- Marketing: writing blog posts, how to's, printing stickers, ...
- Community: presenting the project at meetups, organizing a dedicated meetup for the local community, ...
Expand All @@ -23,15 +26,15 @@ Code review process
The bigger the pull request, the longer it will take to review and merge. Try to break down large pull requests in smaller chunks that are easier to review and merge. It is also always helpful to have some context for your pull request. What was the purpose? Why does it matter to you?

---

### WARNING

Ts.ED project uses [conventional commits](https://www.conventionalcommits.org/en/v1.0.0-beta.4/) as format commit message.

Release note and tagging version are based on the message commits.
If you don't follow the format, our CI won't be able to increment the version correctly and your feature won't be released on NPM.

To write your commit message, see [convention page here](https://www.conventionalcommits.org/en/v1.0.0-beta.4/)
---
## To write your commit message, see [convention page here](https://www.conventionalcommits.org/en/v1.0.0-beta.4/)

## Financial contributions

Expand All @@ -42,6 +45,7 @@ We also welcome financial contributions in full transparency on our open collect
If you have any questions, create an [issue](https://github.com/tsedio/tsed/issues) (protip: do a quick search first to see if someone else didn't ask the same question before!). You can also reach us at https://gitter.im/Tsed-io/community.

## How to work on Ts.ED

### Setup

Clone your fork of the repository
Expand All @@ -51,6 +55,7 @@ $ git clone https://github.com/YOUR_USERNAME/tsed-cli.git
```

Install npm dependencies with yarn (not with NPM!):

```bash
yarn
```
Expand All @@ -59,7 +64,7 @@ Compile TypeScript:

```bash
yarn build
// or
// or
npm run build
```

Expand Down Expand Up @@ -101,6 +106,7 @@ git commit -m "feat(domain): Your message"
```

Then:

```bash
npm run test
git fetch
Expand Down Expand Up @@ -142,18 +148,17 @@ yarn vuepress:serve
- Feel free to ask for help from other members of the Ts.ED team.

## Credits

### Contributors

<a href="https://github.com/tsedio/ts-express-decorators/graphs/contributors"><img src="https://opencollective.com/tsed/contributors.svg?width=890" /></a>


### Backers

Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/tsed#backer)]

<a href="https://opencollective.com/tsed#backers" target="_blank"><img src="https://opencollective.com/tsed/backers.svg?width=890"></a>


### Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/tsed#sponsor)]
Expand Down
3 changes: 2 additions & 1 deletion commitlint.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export default {
extends: ["@commitlint/config-conventional"],
rules: {
"header-max-length": [2, "always", 200]
"header-max-length": [2, "always", 200],
"body-max-line-length": [2, "always", 300]
}
};
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@
},
"homepage": "https://github.com/tsedio/tsed-cli",
"dependencies": {
"@tsed/core": ">=8.18.0",
"@tsed/di": ">=8.18.0",
"@tsed/core": ">=8.21.0",
"@tsed/di": ">=8.21.0",
"@tsed/logger": ">=8.0.3",
"@tsed/logger-std": ">=8.0.3",
"@tsed/normalize-path": ">=8.18.0",
"@tsed/openspec": ">=8.18.0",
"@tsed/schema": ">=8.18.0",
"@tsed/normalize-path": ">=8.21.0",
"@tsed/openspec": ">=8.21.0",
"@tsed/schema": ">=8.21.0",
"axios": "^1.7.7",
"chalk": "^5.3.0",
"commander": "^12.1.0",
Expand Down
6 changes: 3 additions & 3 deletions packages/cli-core/src/decorators/command.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {command} from "../fn/command.js";
import type {CommandParameters} from "../interfaces/CommandParameters.js";
import type {BaseCommandOptions} from "../interfaces/CommandOptions.js";

export function Command(options: CommandParameters): ClassDecorator {
export function Command<Input = any>(options: BaseCommandOptions<Input>): ClassDecorator {
return (token) => {
command(token, options);
command({...options, token});
};
}
4 changes: 0 additions & 4 deletions packages/cli-core/src/decorators/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
export * from "./command.js";
export * from "./onAdd.js";
export * from "./onExec.js";
export * from "./onPostInstall.js";
export * from "./onPrompt.js";
9 changes: 0 additions & 9 deletions packages/cli-core/src/decorators/on.ts

This file was deleted.

18 changes: 0 additions & 18 deletions packages/cli-core/src/decorators/onAdd.spec.ts

This file was deleted.

6 changes: 0 additions & 6 deletions packages/cli-core/src/decorators/onAdd.ts

This file was deleted.

19 changes: 0 additions & 19 deletions packages/cli-core/src/decorators/onExec.spec.ts

This file was deleted.

6 changes: 0 additions & 6 deletions packages/cli-core/src/decorators/onExec.ts

This file was deleted.

19 changes: 0 additions & 19 deletions packages/cli-core/src/decorators/onPostInstall.spec.ts

This file was deleted.

6 changes: 0 additions & 6 deletions packages/cli-core/src/decorators/onPostInstall.ts

This file was deleted.

19 changes: 0 additions & 19 deletions packages/cli-core/src/decorators/onPrompt.spec.ts

This file was deleted.

6 changes: 0 additions & 6 deletions packages/cli-core/src/decorators/onPrompt.ts

This file was deleted.

7 changes: 0 additions & 7 deletions packages/cli-core/src/domains/CommandStoreKeys.ts

This file was deleted.

75 changes: 75 additions & 0 deletions packages/cli-core/src/fn/command.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {injectable} from "@tsed/di";

import type {CommandOptions} from "../interfaces/CommandOptions.js";
import type {CommandProvider} from "../interfaces/CommandProvider.js";
import {command} from "./command.js";

vi.mock("@tsed/di", () => ({
injectable: vi.fn()
}));

describe("command()", () => {
const createBuilder = () =>
({
type: vi.fn().mockReturnThis(),
set: vi.fn().mockReturnThis(),
factory: vi.fn().mockReturnThis()
}) as any;

beforeEach(() => {
vi.clearAllMocks();
});

it("should register a functional command via factory", () => {
const builder = createBuilder();
vi.mocked(injectable).mockReturnValue(builder);

const handler: CommandProvider["$exec"] = vi.fn();
const prompt: CommandProvider["$prompt"] = vi.fn();
const options: CommandOptions<any> = {
name: "test",
description: "description",
handler,
prompt
};

command(options);

expect(injectable).toHaveBeenCalledWith(Symbol.for("COMMAND_test"));
expect(builder.type).toHaveBeenCalledWith("command");
expect(builder.set).toHaveBeenCalledWith("command", options);
expect(builder.factory).toHaveBeenCalledTimes(1);

const registeredFactory = builder.factory.mock.calls[0][0];
const result = registeredFactory();

expect(result).toMatchObject({
...options,
$exec: handler,
$prompt: prompt
});
expect(result.handler).toBe(handler);
});

it("should register a class-based command with provided token", () => {
const builder = createBuilder();
vi.mocked(injectable).mockReturnValue(builder);

class TestCommand implements CommandProvider {
$exec(): any {}
}

const options: CommandOptions<any> = {
name: "test-class",
description: "description",
token: TestCommand
};

command(options);

expect(injectable).toHaveBeenCalledWith(TestCommand);
expect(builder.type).toHaveBeenCalledWith("command");
expect(builder.set).toHaveBeenCalledWith("command", options);
expect(builder.factory).not.toHaveBeenCalled();
});
});
Loading
Loading