@angular/cli 20.1.0-next.1 → 20.1.0-next.3

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.
@@ -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.component.ts`, `my-component.component.html`, and `my-component.component.css`.",
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.component.css`) is created.",
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.component.html`) is created.",
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"
@@ -4365,7 +4365,9 @@
4365
4365
  "lcovonly",
4366
4366
  "text",
4367
4367
  "text-summary",
4368
- "cobertura"
4368
+ "cobertura",
4369
+ "json",
4370
+ "json-summary"
4369
4371
  ]
4370
4372
  }
4371
4373
  }
@@ -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.component.css`) is created.
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.component.html`) is created.
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.component.ts`, `my-component.component.html`, and
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-next.1",
3
+ "version": "20.1.0-next.3",
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-next.1",
29
- "@angular-devkit/core": "20.1.0-next.1",
30
- "@angular-devkit/schematics": "20.1.0-next.1",
28
+ "@angular-devkit/architect": "0.2001.0-next.3",
29
+ "@angular-devkit/core": "20.1.0-next.3",
30
+ "@angular-devkit/schematics": "20.1.0-next.3",
31
31
  "@inquirer/prompts": "7.5.3",
32
32
  "@listr2/prompt-adapter-inquirer": "2.0.22",
33
- "@schematics/angular": "20.1.0-next.1",
33
+ "@modelcontextprotocol/sdk": "1.13.1",
34
+ "@schematics/angular": "20.1.0-next.3",
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-next.1",
49
- "@angular/build": "20.1.0-next.1",
50
- "@angular/ssr": "20.1.0-next.1",
51
- "@angular-devkit/architect": "0.2001.0-next.1",
52
- "@angular-devkit/build-angular": "20.1.0-next.1",
53
- "@angular-devkit/build-webpack": "0.2001.0-next.1",
54
- "@angular-devkit/core": "20.1.0-next.1",
55
- "@angular-devkit/schematics": "20.1.0-next.1"
49
+ "@angular/cli": "20.1.0-next.3",
50
+ "@angular/build": "20.1.0-next.3",
51
+ "@angular/ssr": "20.1.0-next.3",
52
+ "@angular-devkit/architect": "0.2001.0-next.3",
53
+ "@angular-devkit/build-angular": "20.1.0-next.3",
54
+ "@angular-devkit/build-webpack": "0.2001.0-next.3",
55
+ "@angular-devkit/core": "20.1.0-next.3",
56
+ "@angular-devkit/schematics": "20.1.0-next.3"
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
+ }
@@ -22,4 +22,4 @@ class Version {
22
22
  this.patch = patch;
23
23
  }
24
24
  }
25
- exports.VERSION = new Version('20.1.0-next.1');
25
+ exports.VERSION = new Version('20.1.0-next.3');