From e0011b581ca28f50b78d2d99b3d69806c381b3b2 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Tue, 18 Nov 2025 09:18:13 +0000 Subject: [PATCH] refactor: source best practices from `@angular/core` The best practices markdown file is now sourced directly from `@angular/core/resources/best-practices.md`. This change eliminates duplication and ensures consistency across packages. - `packages/angular/cli/src/commands/mcp/resources/best-practices.md` is now generated from the `@angular/core` resource. - `packages/schematics/angular/ai-config/files/__rulesName__.template` is also generated from the `@angular/core` resource, with additional frontmatter. --- packages/angular/cli/BUILD.bazel | 12 +++++ .../commands/mcp/resources/best-practices.md | 47 ------------------ packages/schematics/angular/BUILD.bazel | 16 +++++- .../ai-config/files/__rulesName__.template | 49 ------------------- 4 files changed, 26 insertions(+), 98 deletions(-) delete mode 100644 packages/angular/cli/src/commands/mcp/resources/best-practices.md delete mode 100644 packages/schematics/angular/ai-config/files/__rulesName__.template diff --git a/packages/angular/cli/BUILD.bazel b/packages/angular/cli/BUILD.bazel index e173d31e5413..aeb1878b9d52 100644 --- a/packages/angular/cli/BUILD.bazel +++ b/packages/angular/cli/BUILD.bazel @@ -15,6 +15,17 @@ package(default_visibility = ["//visibility:public"]) npm_link_all_packages() +genrule( + name = "angular_best_practices", + srcs = [ + "//:node_modules/@angular/core/dir", + ], + outs = ["src/commands/mcp/resources/best-practices.md"], + cmd = """ + cp "$(location //:node_modules/@angular/core/dir)/resources/best-practices.md" $@ + """, +) + RUNTIME_ASSETS = glob( include = [ "bin/**/*", @@ -27,6 +38,7 @@ RUNTIME_ASSETS = glob( ) + [ "//packages/angular/cli:lib/config/schema.json", "//packages/angular/cli:lib/code-examples.db", + ":angular_best_practices", ] ts_project( diff --git a/packages/angular/cli/src/commands/mcp/resources/best-practices.md b/packages/angular/cli/src/commands/mcp/resources/best-practices.md deleted file mode 100644 index e3b246935258..000000000000 --- a/packages/angular/cli/src/commands/mcp/resources/best-practices.md +++ /dev/null @@ -1,47 +0,0 @@ -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. - -## TypeScript Best Practices - -- Use strict type checking -- Prefer type inference when the type is obvious -- Avoid the `any` type; use `unknown` when type is uncertain - -## Angular Best Practices - -- Always use standalone components over NgModules -- Must NOT set `standalone: true` inside Angular decorators. It's the default. -- Use signals for state management -- Implement lazy loading for feature routes -- Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead -- Use `NgOptimizedImage` for all static images. - - `NgOptimizedImage` does not work for inline base64 images. - -## Components - -- Keep components small and focused on a single responsibility -- Use `input()` and `output()` functions instead of decorators -- Use `computed()` for derived state -- Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator -- Prefer inline templates for small components -- Prefer Reactive forms instead of Template-driven ones -- Do NOT use `ngClass`, use `class` bindings instead -- DO NOT use `ngStyle`, use `style` bindings instead - -## State Management - -- Use signals for local component state -- Use `computed()` for derived state -- Keep state transformations pure and predictable -- Do NOT use `mutate` on signals, use `update` or `set` instead - -## Templates - -- Keep templates simple and avoid complex logic -- Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch` -- Use the async pipe to handle observables - -## Services - -- Design services around a single responsibility -- Use the `providedIn: 'root'` option for singleton services -- Use the `inject()` function instead of constructor injection diff --git a/packages/schematics/angular/BUILD.bazel b/packages/schematics/angular/BUILD.bazel index b3fa1e537720..27e1179fa107 100644 --- a/packages/schematics/angular/BUILD.bazel +++ b/packages/schematics/angular/BUILD.bazel @@ -45,11 +45,24 @@ copy_to_bin( srcs = glob(["**/schema.json"]), ) +genrule( + name = "angular_best_practices", + srcs = [ + "//:node_modules/@angular/core/dir", + ], + outs = ["ai-config/files/__rulesName__.template"], + cmd = """ + echo -e "<% if (frontmatter) { %><%= frontmatter %>\\n<% } %>" > $@ + cat "$(location //:node_modules/@angular/core/dir)/resources/best-practices.md" >> $@ + """, +) + RUNTIME_ASSETS = [ "collection.json", "migrations/migration-collection.json", "package.json", "utility/latest-versions/package.json", + ":angular_best_practices", ] + glob( include = [ "*/schema.json", @@ -115,13 +128,12 @@ ts_project( include = [ "**/*_spec.ts", "utility/test/**/*.ts", - "refactor/jasmine-vitest/test-helpers.ts", ], exclude = [ # NB: we need to exclude the nested node_modules that is laid out by yarn workspaces "node_modules/**", ], - ), + ) + ["refactor/jasmine-vitest/test-helpers.ts"], deps = [ ":angular", ":node_modules/@angular-devkit/core", diff --git a/packages/schematics/angular/ai-config/files/__rulesName__.template b/packages/schematics/angular/ai-config/files/__rulesName__.template deleted file mode 100644 index 0d4f1bbf8d41..000000000000 --- a/packages/schematics/angular/ai-config/files/__rulesName__.template +++ /dev/null @@ -1,49 +0,0 @@ -<% if (frontmatter) { %><%= frontmatter %> - -<% } %>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. - -## TypeScript Best Practices - -- Use strict type checking -- Prefer type inference when the type is obvious -- Avoid the `any` type; use `unknown` when type is uncertain - -## Angular Best Practices - -- Always use standalone components over NgModules -- Must NOT set `standalone: true` inside Angular decorators. It's the default. -- Use signals for state management -- Implement lazy loading for feature routes -- Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead -- Use `NgOptimizedImage` for all static images. - - `NgOptimizedImage` does not work for inline base64 images. - -## Components - -- Keep components small and focused on a single responsibility -- Use `input()` and `output()` functions instead of decorators -- Use `computed()` for derived state -- Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator -- Prefer inline templates for small components -- Prefer Reactive forms instead of Template-driven ones -- Do NOT use `ngClass`, use `class` bindings instead -- Do NOT use `ngStyle`, use `style` bindings instead - -## State Management - -- Use signals for local component state -- Use `computed()` for derived state -- Keep state transformations pure and predictable -- Do NOT use `mutate` on signals, use `update` or `set` instead - -## Templates - -- Keep templates simple and avoid complex logic -- Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch` -- Use the async pipe to handle observables - -## Services - -- Design services around a single responsibility -- Use the `providedIn: 'root'` option for singleton services -- Use the `inject()` function instead of constructor injection