@angular/cli 20.1.0-next.2 → 20.1.0-rc.0
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/config/schema.json +3 -3
- package/lib/config/workspace-schema.d.ts +3 -4
- package/package.json +15 -14
- package/src/commands/command-config.d.ts +1 -1
- package/src/commands/command-config.js +3 -0
- package/src/commands/mcp/cli.d.ts +16 -0
- package/src/commands/mcp/cli.js +45 -0
- package/src/commands/mcp/instructions/best-practices.md +44 -0
- package/src/commands/mcp/mcp-server.d.ts +12 -0
- package/src/commands/mcp/mcp-server.js +61 -0
- package/src/utilities/version.js +1 -1
package/lib/config/schema.json
CHANGED
|
@@ -1118,7 +1118,7 @@
|
|
|
1118
1118
|
},
|
|
1119
1119
|
"name": {
|
|
1120
1120
|
"type": "string",
|
|
1121
|
-
"description": "The name for the new component. This will be used to create the component's class, template, and stylesheet files. For example, if you provide `my-component`, the files will be named `my-component.
|
|
1121
|
+
"description": "The name for the new component. This will be used to create the component's class, template, and stylesheet files. For example, if you provide `my-component`, the files will be named `my-component.ts`, `my-component.html`, and `my-component.css`.",
|
|
1122
1122
|
"$default": {
|
|
1123
1123
|
"$source": "argv",
|
|
1124
1124
|
"index": 0
|
|
@@ -1131,13 +1131,13 @@
|
|
|
1131
1131
|
"alias": "b"
|
|
1132
1132
|
},
|
|
1133
1133
|
"inlineStyle": {
|
|
1134
|
-
"description": "Include the component's styles directly in the `component.ts` file. By default, a separate stylesheet file (e.g., `my-component.
|
|
1134
|
+
"description": "Include the component's styles directly in the `component.ts` file. By default, a separate stylesheet file (e.g., `my-component.css`) is created.",
|
|
1135
1135
|
"type": "boolean",
|
|
1136
1136
|
"default": false,
|
|
1137
1137
|
"alias": "s"
|
|
1138
1138
|
},
|
|
1139
1139
|
"inlineTemplate": {
|
|
1140
|
-
"description": "Include the component's HTML template directly in the `component.ts` file. By default, a separate template file (e.g., `my-component.
|
|
1140
|
+
"description": "Include the component's HTML template directly in the `component.ts` file. By default, a separate template file (e.g., `my-component.html`) is created.",
|
|
1141
1141
|
"type": "boolean",
|
|
1142
1142
|
"default": false,
|
|
1143
1143
|
"alias": "t"
|
|
@@ -278,12 +278,12 @@ export type AngularComponentOptionsSchema = {
|
|
|
278
278
|
flat?: boolean;
|
|
279
279
|
/**
|
|
280
280
|
* Include the component's styles directly in the `component.ts` file. By default, a
|
|
281
|
-
* separate stylesheet file (e.g., `my-component.
|
|
281
|
+
* separate stylesheet file (e.g., `my-component.css`) is created.
|
|
282
282
|
*/
|
|
283
283
|
inlineStyle?: boolean;
|
|
284
284
|
/**
|
|
285
285
|
* Include the component's HTML template directly in the `component.ts` file. By default, a
|
|
286
|
-
* separate template file (e.g., `my-component.
|
|
286
|
+
* separate template file (e.g., `my-component.html`) is created.
|
|
287
287
|
*/
|
|
288
288
|
inlineTemplate?: boolean;
|
|
289
289
|
/**
|
|
@@ -294,8 +294,7 @@ export type AngularComponentOptionsSchema = {
|
|
|
294
294
|
/**
|
|
295
295
|
* The name for the new component. This will be used to create the component's class,
|
|
296
296
|
* template, and stylesheet files. For example, if you provide `my-component`, the files
|
|
297
|
-
* will be named `my-component.
|
|
298
|
-
* `my-component.component.css`.
|
|
297
|
+
* will be named `my-component.ts`, `my-component.html`, and `my-component.css`.
|
|
299
298
|
*/
|
|
300
299
|
name: string;
|
|
301
300
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular/cli",
|
|
3
|
-
"version": "20.1.0-
|
|
3
|
+
"version": "20.1.0-rc.0",
|
|
4
4
|
"description": "CLI tool for Angular",
|
|
5
5
|
"main": "lib/cli/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -25,12 +25,13 @@
|
|
|
25
25
|
},
|
|
26
26
|
"homepage": "https://github.com/angular/angular-cli",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@angular-devkit/architect": "0.2001.0-
|
|
29
|
-
"@angular-devkit/core": "20.1.0-
|
|
30
|
-
"@angular-devkit/schematics": "20.1.0-
|
|
31
|
-
"@inquirer/prompts": "7.
|
|
28
|
+
"@angular-devkit/architect": "0.2001.0-rc.0",
|
|
29
|
+
"@angular-devkit/core": "20.1.0-rc.0",
|
|
30
|
+
"@angular-devkit/schematics": "20.1.0-rc.0",
|
|
31
|
+
"@inquirer/prompts": "7.6.0",
|
|
32
32
|
"@listr2/prompt-adapter-inquirer": "2.0.22",
|
|
33
|
-
"@
|
|
33
|
+
"@modelcontextprotocol/sdk": "1.13.3",
|
|
34
|
+
"@schematics/angular": "20.1.0-rc.0",
|
|
34
35
|
"@yarnpkg/lockfile": "1.1.0",
|
|
35
36
|
"ini": "5.0.0",
|
|
36
37
|
"jsonc-parser": "3.3.1",
|
|
@@ -45,14 +46,14 @@
|
|
|
45
46
|
"ng-update": {
|
|
46
47
|
"migrations": "@schematics/angular/migrations/migration-collection.json",
|
|
47
48
|
"packageGroup": {
|
|
48
|
-
"@angular/cli": "20.1.0-
|
|
49
|
-
"@angular/build": "20.1.0-
|
|
50
|
-
"@angular/ssr": "20.1.0-
|
|
51
|
-
"@angular-devkit/architect": "0.2001.0-
|
|
52
|
-
"@angular-devkit/build-angular": "20.1.0-
|
|
53
|
-
"@angular-devkit/build-webpack": "0.2001.0-
|
|
54
|
-
"@angular-devkit/core": "20.1.0-
|
|
55
|
-
"@angular-devkit/schematics": "20.1.0-
|
|
49
|
+
"@angular/cli": "20.1.0-rc.0",
|
|
50
|
+
"@angular/build": "20.1.0-rc.0",
|
|
51
|
+
"@angular/ssr": "20.1.0-rc.0",
|
|
52
|
+
"@angular-devkit/architect": "0.2001.0-rc.0",
|
|
53
|
+
"@angular-devkit/build-angular": "20.1.0-rc.0",
|
|
54
|
+
"@angular-devkit/build-webpack": "0.2001.0-rc.0",
|
|
55
|
+
"@angular-devkit/core": "20.1.0-rc.0",
|
|
56
|
+
"@angular-devkit/schematics": "20.1.0-rc.0"
|
|
56
57
|
}
|
|
57
58
|
},
|
|
58
59
|
"packageManager": "pnpm@9.15.9",
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import { CommandModuleConstructor } from '../command-builder/utilities/command';
|
|
9
|
-
export type CommandNames = 'add' | 'analytics' | 'build' | 'cache' | 'completion' | 'config' | 'deploy' | 'e2e' | 'extract-i18n' | 'generate' | 'lint' | 'make-this-awesome' | 'new' | 'run' | 'serve' | 'test' | 'update' | 'version';
|
|
9
|
+
export type CommandNames = 'add' | 'analytics' | 'build' | 'cache' | 'completion' | 'config' | 'deploy' | 'e2e' | 'extract-i18n' | 'generate' | 'lint' | 'make-this-awesome' | 'mcp' | 'new' | 'run' | 'serve' | 'test' | 'update' | 'version';
|
|
10
10
|
export interface CommandConfig {
|
|
11
11
|
aliases?: string[];
|
|
12
12
|
factory: () => Promise<{
|
|
@@ -81,6 +81,9 @@ exports.RootCommands = {
|
|
|
81
81
|
'make-this-awesome': {
|
|
82
82
|
factory: () => Promise.resolve().then(() => __importStar(require('./make-this-awesome/cli'))),
|
|
83
83
|
},
|
|
84
|
+
'mcp': {
|
|
85
|
+
factory: () => Promise.resolve().then(() => __importStar(require('./mcp/cli'))),
|
|
86
|
+
},
|
|
84
87
|
'new': {
|
|
85
88
|
factory: () => Promise.resolve().then(() => __importStar(require('./new/cli'))),
|
|
86
89
|
aliases: ['n'],
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.dev/license
|
|
7
|
+
*/
|
|
8
|
+
import { Argv } from 'yargs';
|
|
9
|
+
import { CommandModule, CommandModuleImplementation } from '../../command-builder/command-module';
|
|
10
|
+
export default class McpCommandModule extends CommandModule implements CommandModuleImplementation {
|
|
11
|
+
command: string;
|
|
12
|
+
describe: false;
|
|
13
|
+
longDescriptionPath: undefined;
|
|
14
|
+
builder(localYargs: Argv): Argv;
|
|
15
|
+
run(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://angular.dev/license
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
11
|
+
const command_module_1 = require("../../command-builder/command-module");
|
|
12
|
+
const tty_1 = require("../../utilities/tty");
|
|
13
|
+
const mcp_server_1 = require("./mcp-server");
|
|
14
|
+
const INTERACTIVE_MESSAGE = `
|
|
15
|
+
To start using the Angular CLI MCP Server, add this configuration to your host:
|
|
16
|
+
|
|
17
|
+
{
|
|
18
|
+
"mcpServers": {
|
|
19
|
+
"angular-cli": {
|
|
20
|
+
"command": "npx",
|
|
21
|
+
"args": ["@angular/cli", "mcp"]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
Exact configuration may differ depending on the host.
|
|
27
|
+
`;
|
|
28
|
+
class McpCommandModule extends command_module_1.CommandModule {
|
|
29
|
+
command = 'mcp';
|
|
30
|
+
describe = false;
|
|
31
|
+
longDescriptionPath = undefined;
|
|
32
|
+
builder(localYargs) {
|
|
33
|
+
return localYargs;
|
|
34
|
+
}
|
|
35
|
+
async run() {
|
|
36
|
+
if ((0, tty_1.isTTY)()) {
|
|
37
|
+
this.context.logger.info(INTERACTIVE_MESSAGE);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const server = await (0, mcp_server_1.createMcpServer)({ workspace: this.context.workspace });
|
|
41
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
42
|
+
await server.connect(transport);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.default = McpCommandModule;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
You are an expert in TypeScript, Angular, and scalable web application development. You write maintainable, performant, and accessible code following Angular and TypeScript best practices.
|
|
2
|
+
|
|
3
|
+
## TypeScript Best Practices
|
|
4
|
+
|
|
5
|
+
- Use strict type checking
|
|
6
|
+
- Prefer type inference when the type is obvious
|
|
7
|
+
- Avoid the `any` type; use `unknown` when type is uncertain
|
|
8
|
+
|
|
9
|
+
## Angular Best Practices
|
|
10
|
+
|
|
11
|
+
- Always use standalone components over NgModules
|
|
12
|
+
- Don't use explicit `standalone: true` (it is implied by default)
|
|
13
|
+
- Use signals for state management
|
|
14
|
+
- Implement lazy loading for feature routes
|
|
15
|
+
- Use `NgOptimizedImage` for all static images.
|
|
16
|
+
|
|
17
|
+
## Components
|
|
18
|
+
|
|
19
|
+
- Keep components small and focused on a single responsibility
|
|
20
|
+
- Use `input()` and `output()` functions instead of decorators
|
|
21
|
+
- Use `computed()` for derived state
|
|
22
|
+
- Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator
|
|
23
|
+
- Prefer inline templates for small components
|
|
24
|
+
- Prefer Reactive forms instead of Template-driven ones
|
|
25
|
+
- Do NOT use `ngClass`, use `class` bindings instead
|
|
26
|
+
- DO NOT use `ngStyle`, use `style` bindings instead
|
|
27
|
+
|
|
28
|
+
## State Management
|
|
29
|
+
|
|
30
|
+
- Use signals for local component state
|
|
31
|
+
- Use `computed()` for derived state
|
|
32
|
+
- Keep state transformations pure and predictable
|
|
33
|
+
|
|
34
|
+
## Templates
|
|
35
|
+
|
|
36
|
+
- Keep templates simple and avoid complex logic
|
|
37
|
+
- Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
|
|
38
|
+
- Use the async pipe to handle observables
|
|
39
|
+
|
|
40
|
+
## Services
|
|
41
|
+
|
|
42
|
+
- Design services around a single responsibility
|
|
43
|
+
- Use the `providedIn: 'root'` option for singleton services
|
|
44
|
+
- Use the `inject()` function instead of constructor injection
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.dev/license
|
|
7
|
+
*/
|
|
8
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
9
|
+
import type { AngularWorkspace } from '../../utilities/config';
|
|
10
|
+
export declare function createMcpServer(context: {
|
|
11
|
+
workspace?: AngularWorkspace;
|
|
12
|
+
}): Promise<McpServer>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://angular.dev/license
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.createMcpServer = createMcpServer;
|
|
14
|
+
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
15
|
+
const promises_1 = require("node:fs/promises");
|
|
16
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
17
|
+
const version_1 = require("../../utilities/version");
|
|
18
|
+
async function createMcpServer(context) {
|
|
19
|
+
const server = new mcp_js_1.McpServer({
|
|
20
|
+
name: 'angular-cli-server',
|
|
21
|
+
version: version_1.VERSION.full,
|
|
22
|
+
capabilities: {
|
|
23
|
+
resources: {},
|
|
24
|
+
tools: {},
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
server.registerResource('instructions', 'instructions://best-practices', {
|
|
28
|
+
title: 'Angular System Instructions',
|
|
29
|
+
description: 'A set of instructions to help LLMs generate correct code that follows Angular best practices.',
|
|
30
|
+
mimeType: 'text/markdown',
|
|
31
|
+
}, async () => {
|
|
32
|
+
const text = await (0, promises_1.readFile)(node_path_1.default.join(__dirname, 'instructions', 'best-practices.md'), 'utf-8');
|
|
33
|
+
return { contents: [{ uri: 'instructions://best-practices', text }] };
|
|
34
|
+
});
|
|
35
|
+
server.registerTool('list_projects', {
|
|
36
|
+
title: 'List projects',
|
|
37
|
+
description: 'List projects within an Angular workspace.' +
|
|
38
|
+
' This information is read from the `angular.json` file at the root path of the Angular workspace',
|
|
39
|
+
}, () => {
|
|
40
|
+
if (!context.workspace) {
|
|
41
|
+
return {
|
|
42
|
+
content: [
|
|
43
|
+
{
|
|
44
|
+
type: 'text',
|
|
45
|
+
text: 'Not within an Angular project.',
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
content: [
|
|
52
|
+
{
|
|
53
|
+
type: 'text',
|
|
54
|
+
text: 'Projects in the Angular workspace: ' +
|
|
55
|
+
[...context.workspace.projects.keys()].join(','),
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
return server;
|
|
61
|
+
}
|
package/src/utilities/version.js
CHANGED