Browse Source

Unify ABP + Angular full-stack guidelines across AIs

Replaces individual AI-specific Angular and ABP Framework rules with a single, comprehensive set of full-stack development guidelines. The new rules emphasize modular architecture, strict typing, best practices for both .NET (ABP) and Angular, and ensure consistency, maintainability, and performance across backend and frontend. This change standardizes expectations and coding conventions for all AI assistants in the project.
pull/23910/head
Fahri Gedik 12 months ago
parent
commit
c7a4557235
  1. 258
      npm/ng-packs/packages/schematics/src/commands/ai-config/files/claude/.claude/CLAUDE.md
  2. 306
      npm/ng-packs/packages/schematics/src/commands/ai-config/files/copilot/.github/copilot-instructions.md
  3. 427
      npm/ng-packs/packages/schematics/src/commands/ai-config/files/cursor/.cursor/rules/cursor.mdc
  4. 388
      npm/ng-packs/packages/schematics/src/commands/ai-config/files/gemini/.gemini/GEMINI.md
  5. 508
      npm/ng-packs/packages/schematics/src/commands/ai-config/files/junie/.junie/guidelines.md
  6. 776
      npm/ng-packs/packages/schematics/src/commands/ai-config/files/windsurf/.windsurf/rules/guidelines.md

258
npm/ng-packs/packages/schematics/src/commands/ai-config/files/claude/.claude/CLAUDE.md

@ -1,106 +1,156 @@
# Angular & ABP Framework Development Rules for Claude # 💻 ABP Full-Stack Development Rules
_Expert Guidelines for .NET Backend (ABP) and Angular Frontend Development_
## Project Context
This is an Angular application built with the ABP Framework. Follow these rules to generate high-quality, maintainable code. You are a **senior full-stack developer** specializing in **ABP Framework (.NET)** and **Angular (TypeScript)**.
You write **clean, maintainable, and modular** code following **ABP, ASP.NET Core, and Angular best practices**.
## Angular Best Practices
---
### Component Development
- Use OnPush change detection strategy by default ## 🧩 1. General Principles
- Implement OnDestroy and unsubscribe from observables - Maintain a clear separation between backend (ABP/.NET) and frontend (Angular) layers.
- Keep components focused on presentation logic - Follow **modular architecture** — each layer or feature should be independently testable and reusable.
- Use smart/dumb component pattern - Always adhere to **official ABP documentation** ([docs.abp.io](https://docs.abp.io)) and **Angular official guides**.
- Prefer standalone components in new code - Prioritize **readability, maintainability, and performance**.
- Use proper TypeScript typing, avoid `any` - Write **idiomatic** and **self-documenting** code.
### Service Development ---
- Make services injectable with `providedIn: 'root'` when possible
- Use dependency injection properly ## ⚙️ 2. ABP / .NET Development Rules
- Handle errors appropriately with RxJS operators
- Return observables for async operations ### Code Style and Structure
- Keep services focused on single responsibility - Follow ABP’s standard folder structure:
- `*.Application`, `*.Domain`, `*.EntityFrameworkCore`, `*.HttpApi`
### RxJS Best Practices - Write concise, idiomatic C# code using modern language features.
- Use proper operators: `switchMap`, `mergeMap`, `concatMap`, `exhaustMap` - Apply **modular and layered design** (Domain, Application, Infrastructure, UI).
- Always unsubscribe using `takeUntil`, `take`, or async pipe - Prefer **LINQ** and **lambda expressions** for collection operations.
- Avoid nested subscriptions - Use **descriptive method and variable names** (`GetActiveUsers`, `CalculateTotalAmount`).
- Use `shareReplay` for shared streams
- Handle errors with `catchError` ### Naming Conventions
- **PascalCase** → Classes, Methods, Properties
### Template Best Practices - **camelCase** → Local variables and private fields
- Use async pipe for observables - **UPPER_CASE** → Constants
- Avoid complex logic in templates - Prefix interfaces with **`I`** (e.g., `IUserRepository`).
- Use trackBy with *ngFor
- Use proper change detection ### C# and .NET Usage
- Follow accessibility guidelines (ARIA attributes) - Use **C# 10+ features** (records, pattern matching, null-coalescing assignment).
- Utilize **ABP modules** (Permission Management, Setting Management, Audit Logging).
## ABP Framework Specific Rules - Integrate **Entity Framework Core** with ABP’s repository abstractions.
### Module Structure ### Syntax and Formatting
- Follow ABP's modular architecture - Follow [Microsoft C# Coding Conventions](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions).
- Use feature modules appropriately - Use `var` when the type is clear.
- Leverage ABP's configuration services - Use `string interpolation` and null-conditional operators.
- Use ABP's localization system - Keep code consistent and well-formatted.
### Error Handling and Validation
- Use exceptions only for exceptional cases.
- Log errors via ABP’s built-in logging or a compatible provider.
- Validate models with **DataAnnotations** or **FluentValidation**.
- Rely on ABP’s global exception middleware for unified responses.
- Return consistent HTTP status codes and error DTOs.
### API Design
- Build RESTful APIs via `HttpApi` layer and **ABP conventional controllers**.
- Use **attribute-based routing** and versioning when needed.
- Apply **action filters/middleware** for cross-cutting concerns (auditing, authorization).
### Performance Optimization
- Use `async/await` for I/O operations.
- Use `IDistributedCache` over `IMemoryCache`.
- Avoid N+1 queries — include relations explicitly.
- Implement pagination with `PagedResultDto`.
### Key Conventions
- Use **Dependency Injection** via ABP’s DI system.
- Apply **repository pattern** or EF Core directly as needed.
- Use **AutoMapper** or ABP object mapping for DTOs.
- Implement **background jobs** with ABP’s job system or `IHostedService`.
- Follow **domain-driven design (DDD)** principles:
- Business rules in Domain layer.
- Use `AuditedAggregateRoot`, `FullAuditedEntity`, etc.
- Avoid unnecessary dependencies between layers.
### Testing
- Use **xUnit**, **Shouldly**, and **NSubstitute** for testing.
- Write **unit and integration tests** per module (`Application.Tests`, `Domain.Tests`).
- Mock dependencies properly and use ABP’s test base classes.
### Security
- Use **OpenIddict** for authentication & authorization.
- Implement permission checks through ABP’s infrastructure.
- Enforce **HTTPS** and properly configure **CORS**.
### API Documentation
- Use **Swagger / OpenAPI** (Swashbuckle or NSwag).
- Add XML comments to controllers and DTOs.
- Follow ABP’s documentation conventions for module APIs.
**Reference Best Practices:**
- [Domain Services](https://abp.io/docs/latest/framework/architecture/best-practices/domain-services)
- [Repositories](https://abp.io/docs/latest/framework/architecture/best-practices/repositories)
- [Entities](https://abp.io/docs/latest/framework/architecture/best-practices/entities)
- [Application Services](https://abp.io/docs/latest/framework/architecture/best-practices/application-services)
- [DTOs](https://abp.io/docs/latest/framework/architecture/best-practices/data-transfer-objects)
- [Entity Framework Integration](https://abp.io/docs/latest/framework/architecture/best-practices/entity-framework-core-integration)
---
## 🌐 3. Angular / TypeScript Development Rules
### TypeScript Best Practices
- Enable **strict type checking** in `tsconfig.json`.
- Use **type inference** when the type is obvious.
- Avoid `any`; use `unknown` or generics instead.
- Use interfaces and types for clarity and structure.
### Angular Best Practices
- Prefer **standalone components** (no `NgModules`).
- Do **NOT** set `standalone: true` manually — it’s default.
- Use **signals** for state management.
- Implement **lazy loading** for feature routes.
- Avoid `@HostBinding` / `@HostListener`; use `host` object in decorators.
- Use **`NgOptimizedImage`** for static images (not base64).
### Components
- Keep components small, focused, and reusable.
- Use `input()` and `output()` functions instead of decorators.
- Use `computed()` for derived state.
- Always set `changeDetection: ChangeDetectionStrategy.OnPush`.
- Use **inline templates** for small components.
- Prefer **Reactive Forms** over template-driven forms.
- Avoid `ngClass` → use `[class]` bindings.
- Avoid `ngStyle` → use `[style]` bindings.
### State Management ### State Management
- Use ABP's state management patterns - Manage **local component state** with signals.
- Leverage NGXS for complex state - Use **`computed()`** for derived data.
- Use ABP's store decorators properly - Keep state transformations **pure and predictable**.
- Avoid `mutate()` on signals — use `update()` or `set()`.
### API Integration
- Use ABP's generated proxy services ### Templates
- Follow ABP's REST API conventions - Use **native control flow** (`@if`, `@for`, `@switch`) instead of structural directives.
- Handle ABP's error responses - Keep templates minimal and declarative.
- Use ABP's permission system - Use the **async pipe** for observable bindings.
### Localization ### Services
- Use ABP's localization pipes and services - Design services for **single responsibility**.
- Define localization keys in resource files - Provide services using `providedIn: 'root'`.
- Follow ABP's localization naming conventions - Use the **`inject()` function** instead of constructor injection.
### Authentication & Authorization ---
- Use ABP's auth guards
- Leverage permission directives ## 🔒 4. Combined Full-Stack Practices
- Handle ABP's multi-tenancy - Ensure backend and frontend follow consistent **DTO contracts** and **naming conventions**.
- Maintain shared models (e.g., via a `contracts` package or OpenAPI generation).
## Code Style - Version APIs carefully and handle changes in Angular clients.
- Follow Angular style guide - Use ABP’s **CORS**, **Swagger**, and **Identity** modules to simplify frontend integration.
- Use meaningful variable and function names - Apply **global error handling** and consistent response wrappers in both layers.
- Add JSDoc comments for complex logic - Monitor performance with tools like **Application Insights**, **ABP auditing**, or **Angular profiler**.
- Keep functions small and focused
- Use TypeScript strict mode ---
- Format code with Prettier
## ✅ Summary
## Testing This document defines a unified standard for developing **ABP + Angular full-stack applications**, ensuring:
- Write unit tests for services and components - Code is **modular**, **performant**, and **maintainable**.
- Use Jest for testing - Teams follow **consistent conventions** across backend and frontend.
- Mock dependencies properly - Every layer (Domain, Application, UI) is **clean, testable, and scalable**.
- Aim for good test coverage
- Test error scenarios
## File Organization
- Follow Nx workspace conventions
- Use proper folder structure
- Group related files together
- Use barrel exports (index.ts)
## Performance
- Lazy load feature modules
- Use OnPush change detection
- Optimize bundle size
- Use production builds
- Implement proper caching strategies
## Security
- Sanitize user inputs
- Use proper Content Security Policy
- Follow OWASP guidelines
- Validate data on client and server
## Git Practices
- Write meaningful commit messages
- Keep commits atomic
- Follow conventional commits
- Create feature branches
When generating code, always consider these rules and the context of the ABP Framework and Angular ecosystem.

306
npm/ng-packs/packages/schematics/src/commands/ai-config/files/copilot/.github/copilot-instructions.md

@ -1,158 +1,156 @@
# GitHub Copilot Instructions for Angular & ABP Framework # 💻 ABP Full-Stack Development Rules
_Expert Guidelines for .NET Backend (ABP) and Angular Frontend Development_
You are an expert Angular and ABP Framework developer. Follow these guidelines when generating code suggestions.
You are a **senior full-stack developer** specializing in **ABP Framework (.NET)** and **Angular (TypeScript)**.
## Angular Development Standards You write **clean, maintainable, and modular** code following **ABP, ASP.NET Core, and Angular best practices**.
---
## 🧩 1. General Principles
- Maintain a clear separation between backend (ABP/.NET) and frontend (Angular) layers.
- Follow **modular architecture** — each layer or feature should be independently testable and reusable.
- Always adhere to **official ABP documentation** ([docs.abp.io](https://docs.abp.io)) and **Angular official guides**.
- Prioritize **readability, maintainability, and performance**.
- Write **idiomatic** and **self-documenting** code.
---
## ⚙️ 2. ABP / .NET Development Rules
### Code Style and Structure
- Follow ABP’s standard folder structure:
- `*.Application`, `*.Domain`, `*.EntityFrameworkCore`, `*.HttpApi`
- Write concise, idiomatic C# code using modern language features.
- Apply **modular and layered design** (Domain, Application, Infrastructure, UI).
- Prefer **LINQ** and **lambda expressions** for collection operations.
- Use **descriptive method and variable names** (`GetActiveUsers`, `CalculateTotalAmount`).
### Naming Conventions
- **PascalCase** → Classes, Methods, Properties
- **camelCase** → Local variables and private fields
- **UPPER_CASE** → Constants
- Prefix interfaces with **`I`** (e.g., `IUserRepository`).
### C# and .NET Usage
- Use **C# 10+ features** (records, pattern matching, null-coalescing assignment).
- Utilize **ABP modules** (Permission Management, Setting Management, Audit Logging).
- Integrate **Entity Framework Core** with ABP’s repository abstractions.
### Syntax and Formatting
- Follow [Microsoft C# Coding Conventions](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions).
- Use `var` when the type is clear.
- Use `string interpolation` and null-conditional operators.
- Keep code consistent and well-formatted.
### Error Handling and Validation
- Use exceptions only for exceptional cases.
- Log errors via ABP’s built-in logging or a compatible provider.
- Validate models with **DataAnnotations** or **FluentValidation**.
- Rely on ABP’s global exception middleware for unified responses.
- Return consistent HTTP status codes and error DTOs.
### API Design
- Build RESTful APIs via `HttpApi` layer and **ABP conventional controllers**.
- Use **attribute-based routing** and versioning when needed.
- Apply **action filters/middleware** for cross-cutting concerns (auditing, authorization).
### Performance Optimization
- Use `async/await` for I/O operations.
- Use `IDistributedCache` over `IMemoryCache`.
- Avoid N+1 queries — include relations explicitly.
- Implement pagination with `PagedResultDto`.
### Key Conventions
- Use **Dependency Injection** via ABP’s DI system.
- Apply **repository pattern** or EF Core directly as needed.
- Use **AutoMapper** or ABP object mapping for DTOs.
- Implement **background jobs** with ABP’s job system or `IHostedService`.
- Follow **domain-driven design (DDD)** principles:
- Business rules in Domain layer.
- Use `AuditedAggregateRoot`, `FullAuditedEntity`, etc.
- Avoid unnecessary dependencies between layers.
### Testing
- Use **xUnit**, **Shouldly**, and **NSubstitute** for testing.
- Write **unit and integration tests** per module (`Application.Tests`, `Domain.Tests`).
- Mock dependencies properly and use ABP’s test base classes.
### Security
- Use **OpenIddict** for authentication & authorization.
- Implement permission checks through ABP’s infrastructure.
- Enforce **HTTPS** and properly configure **CORS**.
### API Documentation
- Use **Swagger / OpenAPI** (Swashbuckle or NSwag).
- Add XML comments to controllers and DTOs.
- Follow ABP’s documentation conventions for module APIs.
**Reference Best Practices:**
- [Domain Services](https://abp.io/docs/latest/framework/architecture/best-practices/domain-services)
- [Repositories](https://abp.io/docs/latest/framework/architecture/best-practices/repositories)
- [Entities](https://abp.io/docs/latest/framework/architecture/best-practices/entities)
- [Application Services](https://abp.io/docs/latest/framework/architecture/best-practices/application-services)
- [DTOs](https://abp.io/docs/latest/framework/architecture/best-practices/data-transfer-objects)
- [Entity Framework Integration](https://abp.io/docs/latest/framework/architecture/best-practices/entity-framework-core-integration)
---
## 🌐 3. Angular / TypeScript Development Rules
### TypeScript Best Practices
- Enable **strict type checking** in `tsconfig.json`.
- Use **type inference** when the type is obvious.
- Avoid `any`; use `unknown` or generics instead.
- Use interfaces and types for clarity and structure.
### Angular Best Practices
- Prefer **standalone components** (no `NgModules`).
- Do **NOT** set `standalone: true` manually — it’s default.
- Use **signals** for state management.
- Implement **lazy loading** for feature routes.
- Avoid `@HostBinding` / `@HostListener`; use `host` object in decorators.
- Use **`NgOptimizedImage`** for static images (not base64).
### Components ### Components
- Create components with OnPush change detection strategy - Keep components small, focused, and reusable.
- Implement lifecycle hooks properly (OnInit, OnDestroy) - Use `input()` and `output()` functions instead of decorators.
- Use standalone components for new features - Use `computed()` for derived state.
- Follow smart/dumb component pattern - Always set `changeDetection: ChangeDetectionStrategy.OnPush`.
- Unsubscribe from observables using takeUntil pattern or async pipe - Use **inline templates** for small components.
- Prefer **Reactive Forms** over template-driven forms.
Example: - Avoid `ngClass` → use `[class]` bindings.
```typescript - Avoid `ngStyle` → use `[style]` bindings.
@Component({
selector: 'app-example', ### State Management
standalone: true, - Manage **local component state** with signals.
changeDetection: ChangeDetectionStrategy.OnPush, - Use **`computed()`** for derived data.
imports: [CommonModule, ReactiveFormsModule] - Keep state transformations **pure and predictable**.
}) - Avoid `mutate()` on signals — use `update()` or `set()`.
export class ExampleComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>(); ### Templates
- Use **native control flow** (`@if`, `@for`, `@switch`) instead of structural directives.
ngOnDestroy(): void { - Keep templates minimal and declarative.
this.destroy$.next(); - Use the **async pipe** for observable bindings.
this.destroy$.complete();
}
}
```
### Services ### Services
- Use providedIn: 'root' for singleton services - Design services for **single responsibility**.
- Return Observables for async operations - Provide services using `providedIn: 'root'`.
- Handle errors with proper RxJS operators - Use the **`inject()` function** instead of constructor injection.
- Keep services focused on single responsibility
---
Example:
```typescript ## 🔒 4. Combined Full-Stack Practices
@Injectable({ providedIn: 'root' }) - Ensure backend and frontend follow consistent **DTO contracts** and **naming conventions**.
export class DataService { - Maintain shared models (e.g., via a `contracts` package or OpenAPI generation).
constructor(private http: HttpClient) {} - Version APIs carefully and handle changes in Angular clients.
- Use ABP’s **CORS**, **Swagger**, and **Identity** modules to simplify frontend integration.
getData(): Observable<Data[]> { - Apply **global error handling** and consistent response wrappers in both layers.
return this.http.get<Data[]>('/api/data').pipe( - Monitor performance with tools like **Application Insights**, **ABP auditing**, or **Angular profiler**.
catchError(this.handleError)
); ---
}
} ## ✅ Summary
``` This document defines a unified standard for developing **ABP + Angular full-stack applications**, ensuring:
- Code is **modular**, **performant**, and **maintainable**.
### RxJS Patterns - Teams follow **consistent conventions** across backend and frontend.
- Use async pipe in templates instead of manual subscriptions - Every layer (Domain, Application, UI) is **clean, testable, and scalable**.
- Use switchMap for dependent API calls
- Use shareReplay for shared streams
- Avoid nested subscriptions
### Forms
- Use Reactive Forms over Template-driven forms
- Implement custom validators when needed
- Use FormBuilder for cleaner form creation
- Handle form validation properly
## ABP Framework Integration
### Using ABP Services
```typescript
import { ConfigStateService, LocalizationService } from '@abp/ng.core';
constructor(
private config: ConfigStateService,
private localization: LocalizationService
) {}
```
### Localization
```typescript
// In component
this.localization.instant('::LocalizationKey')
// In template
{{ '::LocalizationKey' | abpLocalization }}
```
### Permissions
```typescript
// In template
<button *abpPermission="'MyApp.MyPermission'">Action</button>
// In component
if (this.config.getGrantedPolicy('MyApp.MyPermission')) {
// do something
}
```
### API Proxy Integration
- Use ABP's generated proxy services
- Don't create manual HTTP calls for ABP APIs
- Follow ABP's DTOs and service patterns
### State Management with NGXS
```typescript
@State<MyStateModel>({
name: 'MyState',
defaults: { items: [] }
})
@Injectable()
export class MyState {
@Action(GetItems)
getItems(ctx: StateContext<MyStateModel>) {
return this.service.getItems().pipe(
tap(items => ctx.patchState({ items }))
);
}
}
```
## Code Quality Standards
- Use TypeScript strict mode
- Avoid using `any` type
- Implement proper error handling
- Write meaningful variable and function names
- Add comments for complex logic
- Follow SOLID principles
## Testing
- Write unit tests for components and services
- Use Jest testing framework
- Mock dependencies properly
- Test both success and error scenarios
## File Structure
Follow Nx workspace structure:
```
libs/
feature-name/
src/
lib/
components/
services/
models/
state/
```
## Performance
- Use OnPush change detection
- Lazy load feature modules
- Use trackBy in *ngFor
- Optimize bundle size
- Avoid memory leaks
## Security
- Never commit sensitive data
- Sanitize user inputs
- Use proper authentication guards
- Follow ABP's security patterns
Always prioritize code maintainability, readability, and following Angular and ABP best practices.

427
npm/ng-packs/packages/schematics/src/commands/ai-config/files/cursor/.cursor/rules/cursor.mdc

@ -1,271 +1,156 @@
# Cursor AI Rules for Angular & ABP Framework Development # 💻 ABP Full-Stack Development Rules
_Expert Guidelines for .NET Backend (ABP) and Angular Frontend Development_
## Core Principles
- Write clean, maintainable, and testable code You are a **senior full-stack developer** specializing in **ABP Framework (.NET)** and **Angular (TypeScript)**.
- Follow Angular style guide and ABP conventions You write **clean, maintainable, and modular** code following **ABP, ASP.NET Core, and Angular best practices**.
- Use TypeScript strict mode
- Prioritize code readability over cleverness ---
## Angular Component Guidelines ## 🧩 1. General Principles
- Maintain a clear separation between backend (ABP/.NET) and frontend (Angular) layers.
### Component Structure - Follow **modular architecture** — each layer or feature should be independently testable and reusable.
```typescript - Always adhere to **official ABP documentation** ([docs.abp.io](https://docs.abp.io)) and **Angular official guides**.
import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; - Prioritize **readability, maintainability, and performance**.
import { CommonModule } from '@angular/common'; - Write **idiomatic** and **self-documenting** code.
import { Subject, takeUntil } from 'rxjs';
---
@Component({
selector: 'app-feature-name', ## ⚙️ 2. ABP / .NET Development Rules
standalone: true,
imports: [CommonModule], ### Code Style and Structure
templateUrl: './feature-name.component.html', - Follow ABP’s standard folder structure:
styleUrls: ['./feature-name.component.scss'], - `*.Application`, `*.Domain`, `*.EntityFrameworkCore`, `*.HttpApi`
changeDetection: ChangeDetectionStrategy.OnPush - Write concise, idiomatic C# code using modern language features.
}) - Apply **modular and layered design** (Domain, Application, Infrastructure, UI).
export class FeatureNameComponent implements OnInit, OnDestroy { - Prefer **LINQ** and **lambda expressions** for collection operations.
private destroy$ = new Subject<void>(); - Use **descriptive method and variable names** (`GetActiveUsers`, `CalculateTotalAmount`).
ngOnInit(): void { ### Naming Conventions
// Initialization logic - **PascalCase** → Classes, Methods, Properties
} - **camelCase** → Local variables and private fields
- **UPPER_CASE** → Constants
ngOnDestroy(): void { - Prefix interfaces with **`I`** (e.g., `IUserRepository`).
this.destroy$.next();
this.destroy$.complete(); ### C# and .NET Usage
} - Use **C# 10+ features** (records, pattern matching, null-coalescing assignment).
} - Utilize **ABP modules** (Permission Management, Setting Management, Audit Logging).
``` - Integrate **Entity Framework Core** with ABP’s repository abstractions.
### Always: ### Syntax and Formatting
- Use OnPush change detection strategy - Follow [Microsoft C# Coding Conventions](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions).
- Implement OnDestroy for cleanup - Use `var` when the type is clear.
- Use standalone components for new code - Use `string interpolation` and null-conditional operators.
- Type everything properly, avoid `any` - Keep code consistent and well-formatted.
- Use async pipe in templates
### Error Handling and Validation
### Never: - Use exceptions only for exceptional cases.
- Mutate state directly - Log errors via ABP’s built-in logging or a compatible provider.
- Forget to unsubscribe from observables - Validate models with **DataAnnotations** or **FluentValidation**.
- Use nested subscriptions - Rely on ABP’s global exception middleware for unified responses.
- Put business logic in components - Return consistent HTTP status codes and error DTOs.
## Service Patterns ### API Design
- Build RESTful APIs via `HttpApi` layer and **ABP conventional controllers**.
```typescript - Use **attribute-based routing** and versioning when needed.
import { Injectable } from '@angular/core'; - Apply **action filters/middleware** for cross-cutting concerns (auditing, authorization).
import { Observable, catchError, map, shareReplay } from 'rxjs';
import { HttpClient } from '@angular/common/http'; ### Performance Optimization
- Use `async/await` for I/O operations.
@Injectable({ providedIn: 'root' }) - Use `IDistributedCache` over `IMemoryCache`.
export class DataService { - Avoid N+1 queries — include relations explicitly.
private cache$ = new Map<string, Observable<any>>(); - Implement pagination with `PagedResultDto`.
constructor(private http: HttpClient) {} ### Key Conventions
- Use **Dependency Injection** via ABP’s DI system.
getData(id: string): Observable<Data> { - Apply **repository pattern** or EF Core directly as needed.
if (!this.cache$.has(id)) { - Use **AutoMapper** or ABP object mapping for DTOs.
this.cache$.set( - Implement **background jobs** with ABP’s job system or `IHostedService`.
id, - Follow **domain-driven design (DDD)** principles:
this.http.get<Data>(`/api/data/${id}`).pipe( - Business rules in Domain layer.
shareReplay(1), - Use `AuditedAggregateRoot`, `FullAuditedEntity`, etc.
catchError(this.handleError) - Avoid unnecessary dependencies between layers.
)
); ### Testing
} - Use **xUnit**, **Shouldly**, and **NSubstitute** for testing.
return this.cache$.get(id)!; - Write **unit and integration tests** per module (`Application.Tests`, `Domain.Tests`).
} - Mock dependencies properly and use ABP’s test base classes.
private handleError(error: any): Observable<never> { ### Security
console.error('An error occurred:', error); - Use **OpenIddict** for authentication & authorization.
throw error; - Implement permission checks through ABP’s infrastructure.
} - Enforce **HTTPS** and properly configure **CORS**.
}
``` ### API Documentation
- Use **Swagger / OpenAPI** (Swashbuckle or NSwag).
## RxJS Best Practices - Add XML comments to controllers and DTOs.
- Follow ABP’s documentation conventions for module APIs.
### Use Proper Operators
- `switchMap`: Cancel previous request (search, navigation) **Reference Best Practices:**
- `mergeMap`: Parallel requests (batch operations) - [Domain Services](https://abp.io/docs/latest/framework/architecture/best-practices/domain-services)
- `concatMap`: Sequential requests (ordered operations) - [Repositories](https://abp.io/docs/latest/framework/architecture/best-practices/repositories)
- `exhaustMap`: Ignore new requests until current completes (form submit) - [Entities](https://abp.io/docs/latest/framework/architecture/best-practices/entities)
- [Application Services](https://abp.io/docs/latest/framework/architecture/best-practices/application-services)
### Memory Management - [DTOs](https://abp.io/docs/latest/framework/architecture/best-practices/data-transfer-objects)
```typescript - [Entity Framework Integration](https://abp.io/docs/latest/framework/architecture/best-practices/entity-framework-core-integration)
// Good: Using takeUntil
this.dataService.getData() ---
.pipe(takeUntil(this.destroy$))
.subscribe(data => this.data = data); ## 🌐 3. Angular / TypeScript Development Rules
// Better: Using async pipe ### TypeScript Best Practices
data$ = this.dataService.getData(); - Enable **strict type checking** in `tsconfig.json`.
// Template: {{ data$ | async }} - Use **type inference** when the type is obvious.
``` - Avoid `any`; use `unknown` or generics instead.
- Use interfaces and types for clarity and structure.
## ABP Framework Integration
### Angular Best Practices
### Service Injection - Prefer **standalone components** (no `NgModules`).
```typescript - Do **NOT** set `standalone: true` manually — it’s default.
import { - Use **signals** for state management.
ConfigStateService, - Implement **lazy loading** for feature routes.
LocalizationService, - Avoid `@HostBinding` / `@HostListener`; use `host` object in decorators.
PermissionService - Use **`NgOptimizedImage`** for static images (not base64).
} from '@abp/ng.core';
### Components
constructor( - Keep components small, focused, and reusable.
private config: ConfigStateService, - Use `input()` and `output()` functions instead of decorators.
private localization: LocalizationService, - Use `computed()` for derived state.
private permission: PermissionService - Always set `changeDetection: ChangeDetectionStrategy.OnPush`.
) {} - Use **inline templates** for small components.
``` - Prefer **Reactive Forms** over template-driven forms.
- Avoid `ngClass` → use `[class]` bindings.
### Localization Usage - Avoid `ngStyle` → use `[style]` bindings.
```typescript
// Component ### State Management
readonly localizationKeys = { - Manage **local component state** with signals.
title: this.localization.instant('::PageTitle'), - Use **`computed()`** for derived data.
save: this.localization.instant('::Save'), - Keep state transformations **pure and predictable**.
cancel: this.localization.instant('::Cancel') - Avoid `mutate()` on signals — use `update()` or `set()`.
};
### Templates
// Template - Use **native control flow** (`@if`, `@for`, `@switch`) instead of structural directives.
<h1>{{ '::PageTitle' | abpLocalization }}</h1> - Keep templates minimal and declarative.
``` - Use the **async pipe** for observable bindings.
### Permission Checks ### Services
```typescript - Design services for **single responsibility**.
// Template - Provide services using `providedIn: 'root'`.
<button - Use the **`inject()` function** instead of constructor injection.
*abpPermission="'MyApp.Users.Create'"
(click)="create()"> ---
New User
</button> ## 🔒 4. Combined Full-Stack Practices
- Ensure backend and frontend follow consistent **DTO contracts** and **naming conventions**.
// Component - Maintain shared models (e.g., via a `contracts` package or OpenAPI generation).
canCreate$ = this.config.getGrantedPolicy$('MyApp.Users.Create'); - Version APIs carefully and handle changes in Angular clients.
``` - Use ABP’s **CORS**, **Swagger**, and **Identity** modules to simplify frontend integration.
- Apply **global error handling** and consistent response wrappers in both layers.
### Using ABP Proxy Services - Monitor performance with tools like **Application Insights**, **ABP auditing**, or **Angular profiler**.
```typescript
import { UserService } from '@proxy/users'; ---
constructor(private userService: UserService) {} ## ✅ Summary
This document defines a unified standard for developing **ABP + Angular full-stack applications**, ensuring:
ngOnInit(): void { - Code is **modular**, **performant**, and **maintainable**.
this.users$ = this.userService.getList({ maxResultCount: 10 }); - Teams follow **consistent conventions** across backend and frontend.
} - Every layer (Domain, Application, UI) is **clean, testable, and scalable**.
```
## State Management (NGXS)
```typescript
import { State, Action, StateContext, Selector } from '@ngxs/store';
import { tap } from 'rxjs';
export class GetUsers {
static readonly type = '[Users] Get Users';
}
export interface UsersStateModel {
users: User[];
loading: boolean;
}
@State<UsersStateModel>({
name: 'users',
defaults: {
users: [],
loading: false
}
})
@Injectable()
export class UsersState {
constructor(private userService: UserService) {}
@Selector()
static getUsers(state: UsersStateModel) {
return state.users;
}
@Action(GetUsers)
getUsers(ctx: StateContext<UsersStateModel>) {
ctx.patchState({ loading: true });
return this.userService.getList().pipe(
tap(response => {
ctx.patchState({
users: response.items,
loading: false
});
})
);
}
}
```
## Form Handling
```typescript
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
export class FormComponent implements OnInit {
form!: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.form = this.fb.group({
name: ['', [Validators.required, Validators.minLength(3)]],
email: ['', [Validators.required, Validators.email]],
age: [null, [Validators.min(18), Validators.max(100)]]
});
}
onSubmit(): void {
if (this.form.valid) {
const formValue = this.form.getRawValue();
// Submit logic
}
}
}
```
## Template Best Practices
```html
<!-- Use async pipe -->
<div *ngIf="data$ | async as data">
{{ data.name }}
</div>
<!-- Use trackBy with ngFor -->
<div *ngFor="let item of items; trackBy: trackByFn">
{{ item.name }}
</div>
<!-- Accessibility -->
<button
type="button"
[attr.aria-label]="'::Close' | abpLocalization"
(click)="close()">
<i class="fa fa-times"></i>
</button>
```
## Common Patterns to Avoid
❌ Manual subscriptions without cleanup
❌ Logic in templates
❌ Mutating input properties
❌ Using `any` type
❌ Nested subscriptions
❌ Missing error handling
## Common Patterns to Use
✅ Async pipe in templates
✅ OnPush change detection
✅ Reactive forms
✅ Smart/dumb components
✅ Dependency injection
✅ RxJS operators
✅ Proper typing
Follow these rules consistently to maintain high code quality.

388
npm/ng-packs/packages/schematics/src/commands/ai-config/files/gemini/.gemini/GEMINI.md

@ -1,240 +1,156 @@
# Gemini AI - Angular & ABP Framework Development Guidelines # 💻 ABP Full-Stack Development Rules
_Expert Guidelines for .NET Backend (ABP) and Angular Frontend Development_
## Project Overview
This is an enterprise Angular application using the ABP Framework with Nx workspace structure and NGXS for state management. You are a **senior full-stack developer** specializing in **ABP Framework (.NET)** and **Angular (TypeScript)**.
You write **clean, maintainable, and modular** code following **ABP, ASP.NET Core, and Angular best practices**.
## Angular Development Standards
---
### Component Architecture
Always create components with: ## 🧩 1. General Principles
- OnPush change detection strategy - Maintain a clear separation between backend (ABP/.NET) and frontend (Angular) layers.
- Proper lifecycle hook implementation (OnDestroy for cleanup) - Follow **modular architecture** — each layer or feature should be independently testable and reusable.
- Standalone components for new features - Always adhere to **official ABP documentation** ([docs.abp.io](https://docs.abp.io)) and **Angular official guides**.
- TypeScript strict typing (avoid `any`) - Prioritize **readability, maintainability, and performance**.
- Write **idiomatic** and **self-documenting** code.
```typescript
@Component({ ---
selector: 'app-example',
standalone: true, ## ⚙️ 2. ABP / .NET Development Rules
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule, ReactiveFormsModule] ### Code Style and Structure
}) - Follow ABP’s standard folder structure:
export class ExampleComponent implements OnInit, OnDestroy { - `*.Application`, `*.Domain`, `*.EntityFrameworkCore`, `*.HttpApi`
private destroy$ = new Subject<void>(); - Write concise, idiomatic C# code using modern language features.
- Apply **modular and layered design** (Domain, Application, Infrastructure, UI).
ngOnDestroy(): void { - Prefer **LINQ** and **lambda expressions** for collection operations.
this.destroy$.next(); - Use **descriptive method and variable names** (`GetActiveUsers`, `CalculateTotalAmount`).
this.destroy$.complete();
} ### Naming Conventions
} - **PascalCase** → Classes, Methods, Properties
``` - **camelCase** → Local variables and private fields
- **UPPER_CASE** → Constants
### Service Development - Prefix interfaces with **`I`** (e.g., `IUserRepository`).
- Use `providedIn: 'root'` for singleton services
- Return Observables for async operations ### C# and .NET Usage
- Implement proper error handling with RxJS operators - Use **C# 10+ features** (records, pattern matching, null-coalescing assignment).
- Use dependency injection properly - Utilize **ABP modules** (Permission Management, Setting Management, Audit Logging).
- Integrate **Entity Framework Core** with ABP’s repository abstractions.
```typescript
@Injectable({ providedIn: 'root' }) ### Syntax and Formatting
export class DataService { - Follow [Microsoft C# Coding Conventions](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions).
constructor(private http: HttpClient) {} - Use `var` when the type is clear.
- Use `string interpolation` and null-conditional operators.
getData(): Observable<Data[]> { - Keep code consistent and well-formatted.
return this.http.get<Data[]>('/api/data').pipe(
retry(2), ### Error Handling and Validation
catchError(this.handleError), - Use exceptions only for exceptional cases.
shareReplay(1) - Log errors via ABP’s built-in logging or a compatible provider.
); - Validate models with **DataAnnotations** or **FluentValidation**.
} - Rely on ABP’s global exception middleware for unified responses.
} - Return consistent HTTP status codes and error DTOs.
```
### API Design
### RxJS Patterns - Build RESTful APIs via `HttpApi` layer and **ABP conventional controllers**.
- **switchMap**: For search/navigation (cancels previous) - Use **attribute-based routing** and versioning when needed.
- **mergeMap**: For parallel operations - Apply **action filters/middleware** for cross-cutting concerns (auditing, authorization).
- **concatMap**: For sequential operations
- **exhaustMap**: For form submissions (ignores new until complete) ### Performance Optimization
- Use `async/await` for I/O operations.
Always unsubscribe using: - Use `IDistributedCache` over `IMemoryCache`.
- `takeUntil(this.destroy$)` pattern - Avoid N+1 queries — include relations explicitly.
- `async` pipe in templates (preferred) - Implement pagination with `PagedResultDto`.
- `take(1)` for single emissions
### Key Conventions
### Template Best Practices - Use **Dependency Injection** via ABP’s DI system.
```html - Apply **repository pattern** or EF Core directly as needed.
<!-- ✅ DO: Use async pipe --> - Use **AutoMapper** or ABP object mapping for DTOs.
<div *ngIf="data$ | async as data"> - Implement **background jobs** with ABP’s job system or `IHostedService`.
<div *ngFor="let item of data.items; trackBy: trackById"> - Follow **domain-driven design (DDD)** principles:
{{ item.name }} - Business rules in Domain layer.
</div> - Use `AuditedAggregateRoot`, `FullAuditedEntity`, etc.
</div> - Avoid unnecessary dependencies between layers.
<!-- ❌ DON'T: Manual subscription -->
```
## ABP Framework Integration
### Localization
```typescript
// Component
this.localization.instant('::LocalizationKey')
// Template
{{ '::WelcomeMessage' | abpLocalization }}
```
### Permissions
```typescript
// Template
<button *abpPermission="'MyApp.Books.Create'">Create</button>
// Component
canEdit$ = this.config.getGrantedPolicy$('MyApp.Books.Edit');
```
### API Proxy Services
Always use ABP's generated proxy services instead of manual HTTP calls:
```typescript
import { BookService } from '@proxy/books';
constructor(private bookService: BookService) {}
getBooks(): Observable<PagedResultDto<BookDto>> {
return this.bookService.getList({ maxResultCount: 10 });
}
```
### State Management (NGXS)
```typescript
@State<BooksStateModel>({
name: 'books',
defaults: { books: [], loading: false }
})
@Injectable()
export class BooksState {
@Selector()
static getBooks(state: BooksStateModel) {
return state.books;
}
@Action(GetBooks)
getBooks(ctx: StateContext<BooksStateModel>) {
ctx.patchState({ loading: true });
return this.bookService.getList().pipe(
tap(response => {
ctx.patchState({
books: response.items,
loading: false
});
})
);
}
}
```
## Code Quality Standards
### TypeScript
- Use strict mode
- Avoid `any` type
- Use interfaces and types properly
- Implement proper null checks
### Testing ### Testing
- Write unit tests with Jest - Use **xUnit**, **Shouldly**, and **NSubstitute** for testing.
- Mock dependencies properly - Write **unit and integration tests** per module (`Application.Tests`, `Domain.Tests`).
- Test both success and error scenarios - Mock dependencies properly and use ABP’s test base classes.
- Aim for good coverage
### Performance
- Use OnPush change detection
- Lazy load feature modules
- Implement trackBy for lists
- Use production builds
- Avoid memory leaks
### Security ### Security
- Sanitize user inputs - Use **OpenIddict** for authentication & authorization.
- Use Angular's built-in XSS protection - Implement permission checks through ABP’s infrastructure.
- Validate on client and server - Enforce **HTTPS** and properly configure **CORS**.
- Follow ABP's security patterns
- Never expose sensitive data ### API Documentation
- Use **Swagger / OpenAPI** (Swashbuckle or NSwag).
## File Structure (Nx Workspace) - Add XML comments to controllers and DTOs.
``` - Follow ABP’s documentation conventions for module APIs.
libs/
feature-name/ **Reference Best Practices:**
src/ - [Domain Services](https://abp.io/docs/latest/framework/architecture/best-practices/domain-services)
lib/ - [Repositories](https://abp.io/docs/latest/framework/architecture/best-practices/repositories)
components/ - [Entities](https://abp.io/docs/latest/framework/architecture/best-practices/entities)
services/ - [Application Services](https://abp.io/docs/latest/framework/architecture/best-practices/application-services)
models/ - [DTOs](https://abp.io/docs/latest/framework/architecture/best-practices/data-transfer-objects)
state/ - [Entity Framework Integration](https://abp.io/docs/latest/framework/architecture/best-practices/entity-framework-core-integration)
guards/
``` ---
## Common Patterns ## 🌐 3. Angular / TypeScript Development Rules
### Smart/Dumb Components ### TypeScript Best Practices
```typescript - Enable **strict type checking** in `tsconfig.json`.
// Smart (Container) - Use **type inference** when the type is obvious.
@Component({ - Avoid `any`; use `unknown` or generics instead.
template: ` - Use interfaces and types for clarity and structure.
<app-list
[items]="items$ | async" ### Angular Best Practices
(itemSelected)="onSelect($event)"> - Prefer **standalone components** (no `NgModules`).
</app-list> - Do **NOT** set `standalone: true` manually — it’s default.
` - Use **signals** for state management.
}) - Implement **lazy loading** for feature routes.
export class ContainerComponent { - Avoid `@HostBinding` / `@HostListener`; use `host` object in decorators.
items$ = this.store.select(getItems); - Use **`NgOptimizedImage`** for static images (not base64).
constructor(private store: Store) {}
} ### Components
- Keep components small, focused, and reusable.
// Dumb (Presentational) - Use `input()` and `output()` functions instead of decorators.
@Component({ - Use `computed()` for derived state.
changeDetection: ChangeDetectionStrategy.OnPush - Always set `changeDetection: ChangeDetectionStrategy.OnPush`.
}) - Use **inline templates** for small components.
export class ListComponent { - Prefer **Reactive Forms** over template-driven forms.
@Input() items: Item[] = []; - Avoid `ngClass` → use `[class]` bindings.
@Output() itemSelected = new EventEmitter<Item>(); - Avoid `ngStyle` → use `[style]` bindings.
}
``` ### State Management
- Manage **local component state** with signals.
### Reactive Forms - Use **`computed()`** for derived data.
```typescript - Keep state transformations **pure and predictable**.
form = this.fb.group({ - Avoid `mutate()` on signals — use `update()` or `set()`.
name: ['', [Validators.required, Validators.minLength(3)]],
email: ['', [Validators.required, Validators.email]] ### Templates
}); - Use **native control flow** (`@if`, `@for`, `@switch`) instead of structural directives.
``` - Keep templates minimal and declarative.
- Use the **async pipe** for observable bindings.
## Best Practices Checklist
✅ OnPush change detection ### Services
✅ Proper unsubscription - Design services for **single responsibility**.
✅ Async pipe in templates - Provide services using `providedIn: 'root'`.
✅ TypeScript strict typing - Use the **`inject()` function** instead of constructor injection.
✅ Error handling
✅ Unit tests ---
✅ Localization (no hardcoded strings)
✅ Permission checks ## 🔒 4. Combined Full-Stack Practices
✅ Accessibility attributes - Ensure backend and frontend follow consistent **DTO contracts** and **naming conventions**.
✅ Performance optimization - Maintain shared models (e.g., via a `contracts` package or OpenAPI generation).
- Version APIs carefully and handle changes in Angular clients.
## Anti-Patterns to Avoid - Use ABP’s **CORS**, **Swagger**, and **Identity** modules to simplify frontend integration.
❌ Using `any` type - Apply **global error handling** and consistent response wrappers in both layers.
❌ Manual subscriptions without cleanup - Monitor performance with tools like **Application Insights**, **ABP auditing**, or **Angular profiler**.
❌ Logic in templates
❌ Nested subscriptions ---
❌ Mutating state directly
❌ Missing error handling ## ✅ Summary
❌ Hardcoded strings This document defines a unified standard for developing **ABP + Angular full-stack applications**, ensuring:
- Code is **modular**, **performant**, and **maintainable**.
## Resources - Teams follow **consistent conventions** across backend and frontend.
- Angular Style Guide: https://angular.io/guide/styleguide - Every layer (Domain, Application, UI) is **clean, testable, and scalable**.
- ABP Documentation: https://docs.abp.io
- RxJS Operators: https://rxjs.dev/guide/operators
Always prioritize code maintainability, readability, and following Angular and ABP Framework best practices.

508
npm/ng-packs/packages/schematics/src/commands/ai-config/files/junie/.junie/guidelines.md

@ -1,352 +1,156 @@
# Junie AI Guidelines - Angular & ABP Framework # 💻 ABP Full-Stack Development Rules
_Expert Guidelines for .NET Backend (ABP) and Angular Frontend Development_
## Introduction
You are assisting with an Angular application built on the ABP Framework. Follow these guidelines to generate high-quality, maintainable code that adheres to best practices. You are a **senior full-stack developer** specializing in **ABP Framework (.NET)** and **Angular (TypeScript)**.
You write **clean, maintainable, and modular** code following **ABP, ASP.NET Core, and Angular best practices**.
## Core Principles
1. **Type Safety**: Use TypeScript strict mode, avoid `any` ---
2. **Performance**: OnPush change detection, lazy loading
3. **Maintainability**: Clean, readable, well-documented code ## 🧩 1. General Principles
4. **Security**: Input validation, proper authentication/authorization - Maintain a clear separation between backend (ABP/.NET) and frontend (Angular) layers.
5. **Accessibility**: WCAG 2.1 compliance, ARIA attributes - Follow **modular architecture** — each layer or feature should be independently testable and reusable.
- Always adhere to **official ABP documentation** ([docs.abp.io](https://docs.abp.io)) and **Angular official guides**.
## Angular Component Guidelines - Prioritize **readability, maintainability, and performance**.
- Write **idiomatic** and **self-documenting** code.
### Component Structure
```typescript ---
import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common'; ## ⚙️ 2. ABP / .NET Development Rules
import { Subject, takeUntil } from 'rxjs';
### Code Style and Structure
@Component({ - Follow ABP’s standard folder structure:
selector: 'app-feature', - `*.Application`, `*.Domain`, `*.EntityFrameworkCore`, `*.HttpApi`
standalone: true, - Write concise, idiomatic C# code using modern language features.
imports: [CommonModule], - Apply **modular and layered design** (Domain, Application, Infrastructure, UI).
templateUrl: './feature.component.html', - Prefer **LINQ** and **lambda expressions** for collection operations.
styleUrls: ['./feature.component.scss'], - Use **descriptive method and variable names** (`GetActiveUsers`, `CalculateTotalAmount`).
changeDetection: ChangeDetectionStrategy.OnPush
}) ### Naming Conventions
export class FeatureComponent implements OnInit, OnDestroy { - **PascalCase** → Classes, Methods, Properties
private readonly destroy$ = new Subject<void>(); - **camelCase** → Local variables and private fields
- **UPPER_CASE** → Constants
ngOnInit(): void { - Prefix interfaces with **`I`** (e.g., `IUserRepository`).
// Initialization
} ### C# and .NET Usage
- Use **C# 10+ features** (records, pattern matching, null-coalescing assignment).
ngOnDestroy(): void { - Utilize **ABP modules** (Permission Management, Setting Management, Audit Logging).
this.destroy$.next(); - Integrate **Entity Framework Core** with ABP’s repository abstractions.
this.destroy$.complete();
} ### Syntax and Formatting
} - Follow [Microsoft C# Coding Conventions](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions).
``` - Use `var` when the type is clear.
- Use `string interpolation` and null-conditional operators.
### Key Requirements - Keep code consistent and well-formatted.
- ✅ Use OnPush change detection
- ✅ Implement OnDestroy for cleanup ### Error Handling and Validation
- ✅ Prefer standalone components - Use exceptions only for exceptional cases.
- ✅ Use proper TypeScript types - Log errors via ABP’s built-in logging or a compatible provider.
- ✅ Follow smart/dumb component pattern - Validate models with **DataAnnotations** or **FluentValidation**.
- Rely on ABP’s global exception middleware for unified responses.
## Service Development - Return consistent HTTP status codes and error DTOs.
```typescript ### API Design
@Injectable({ providedIn: 'root' }) - Build RESTful APIs via `HttpApi` layer and **ABP conventional controllers**.
export class DataService { - Use **attribute-based routing** and versioning when needed.
constructor(private http: HttpClient) {} - Apply **action filters/middleware** for cross-cutting concerns (auditing, authorization).
getData(): Observable<Data[]> { ### Performance Optimization
return this.http.get<Data[]>('/api/data').pipe( - Use `async/await` for I/O operations.
retry(2), - Use `IDistributedCache` over `IMemoryCache`.
catchError(this.handleError), - Avoid N+1 queries — include relations explicitly.
shareReplay(1) - Implement pagination with `PagedResultDto`.
);
} ### Key Conventions
- Use **Dependency Injection** via ABP’s DI system.
private handleError(error: HttpErrorResponse): Observable<never> { - Apply **repository pattern** or EF Core directly as needed.
console.error('Service error:', error); - Use **AutoMapper** or ABP object mapping for DTOs.
return throwError(() => new Error('Operation failed')); - Implement **background jobs** with ABP’s job system or `IHostedService`.
} - Follow **domain-driven design (DDD)** principles:
} - Business rules in Domain layer.
``` - Use `AuditedAggregateRoot`, `FullAuditedEntity`, etc.
- Avoid unnecessary dependencies between layers.
## RxJS Best Practices
### Testing
### Operator Selection - Use **xUnit**, **Shouldly**, and **NSubstitute** for testing.
| Operator | Use Case | Example | - Write **unit and integration tests** per module (`Application.Tests`, `Domain.Tests`).
|----------|----------|---------| - Mock dependencies properly and use ABP’s test base classes.
| `switchMap` | Search, navigation (cancel previous) | Search input |
| `mergeMap` | Parallel operations | Batch API calls | ### Security
| `concatMap` | Sequential operations | Ordered processing | - Use **OpenIddict** for authentication & authorization.
| `exhaustMap` | Ignore until complete | Form submission | - Implement permission checks through ABP’s infrastructure.
- Enforce **HTTPS** and properly configure **CORS**.
### Subscription Management
```typescript ### API Documentation
// ✅ BEST: Use async pipe - Use **Swagger / OpenAPI** (Swashbuckle or NSwag).
data$ = this.service.getData(); - Add XML comments to controllers and DTOs.
- Follow ABP’s documentation conventions for module APIs.
// ✅ GOOD: Use takeUntil
this.service.getData() **Reference Best Practices:**
.pipe(takeUntil(this.destroy$)) - [Domain Services](https://abp.io/docs/latest/framework/architecture/best-practices/domain-services)
.subscribe(data => this.handleData(data)); - [Repositories](https://abp.io/docs/latest/framework/architecture/best-practices/repositories)
- [Entities](https://abp.io/docs/latest/framework/architecture/best-practices/entities)
// ❌ BAD: No unsubscription - [Application Services](https://abp.io/docs/latest/framework/architecture/best-practices/application-services)
this.service.getData().subscribe(data => this.data = data); - [DTOs](https://abp.io/docs/latest/framework/architecture/best-practices/data-transfer-objects)
``` - [Entity Framework Integration](https://abp.io/docs/latest/framework/architecture/best-practices/entity-framework-core-integration)
## ABP Framework Integration ---
### Localization ## 🌐 3. Angular / TypeScript Development Rules
```typescript
// Service injection ### TypeScript Best Practices
constructor(private localization: LocalizationService) {} - Enable **strict type checking** in `tsconfig.json`.
- Use **type inference** when the type is obvious.
// Usage in component - Avoid `any`; use `unknown` or generics instead.
getTranslation(key: string): string { - Use interfaces and types for clarity and structure.
return this.localization.instant(`::${key}`);
} ### Angular Best Practices
- Prefer **standalone components** (no `NgModules`).
// Template usage - Do **NOT** set `standalone: true` manually — it’s default.
{{ '::PageTitle' | abpLocalization }} - Use **signals** for state management.
``` - Implement **lazy loading** for feature routes.
- Avoid `@HostBinding` / `@HostListener`; use `host` object in decorators.
### Permission System - Use **`NgOptimizedImage`** for static images (not base64).
```typescript
// Directive in template ### Components
<button *abpPermission="'MyApp.Books.Create'">Create Book</button> - Keep components small, focused, and reusable.
- Use `input()` and `output()` functions instead of decorators.
// Check in component - Use `computed()` for derived state.
canEdit(): boolean { - Always set `changeDetection: ChangeDetectionStrategy.OnPush`.
return this.config.getGrantedPolicy('MyApp.Books.Edit'); - Use **inline templates** for small components.
} - Prefer **Reactive Forms** over template-driven forms.
- Avoid `ngClass` → use `[class]` bindings.
// Observable permission - Avoid `ngStyle` → use `[style]` bindings.
canEdit$ = this.config.getGrantedPolicy$('MyApp.Books.Edit');
``` ### State Management
- Manage **local component state** with signals.
### API Proxy Services - Use **`computed()`** for derived data.
```typescript - Keep state transformations **pure and predictable**.
// ✅ DO: Use generated proxy - Avoid `mutate()` on signals — use `update()` or `set()`.
import { BookService } from '@proxy/books';
### Templates
constructor(private bookService: BookService) {} - Use **native control flow** (`@if`, `@for`, `@switch`) instead of structural directives.
- Keep templates minimal and declarative.
loadBooks(): void { - Use the **async pipe** for observable bindings.
this.books$ = this.bookService.getList({ maxResultCount: 10 });
} ### Services
- Design services for **single responsibility**.
// ❌ DON'T: Manual HTTP calls for ABP APIs - Provide services using `providedIn: 'root'`.
``` - Use the **`inject()` function** instead of constructor injection.
### State Management (NGXS) ---
```typescript
// Actions ## 🔒 4. Combined Full-Stack Practices
export class LoadBooks { - Ensure backend and frontend follow consistent **DTO contracts** and **naming conventions**.
static readonly type = '[Books] Load Books'; - Maintain shared models (e.g., via a `contracts` package or OpenAPI generation).
} - Version APIs carefully and handle changes in Angular clients.
- Use ABP’s **CORS**, **Swagger**, and **Identity** modules to simplify frontend integration.
// State - Apply **global error handling** and consistent response wrappers in both layers.
@State<BooksStateModel>({ - Monitor performance with tools like **Application Insights**, **ABP auditing**, or **Angular profiler**.
name: 'books',
defaults: { books: [], loading: false } ---
})
@Injectable() ## ✅ Summary
export class BooksState { This document defines a unified standard for developing **ABP + Angular full-stack applications**, ensuring:
constructor(private bookService: BookService) {} - Code is **modular**, **performant**, and **maintainable**.
- Teams follow **consistent conventions** across backend and frontend.
@Selector() - Every layer (Domain, Application, UI) is **clean, testable, and scalable**.
static books(state: BooksStateModel) {
return state.books;
}
@Action(LoadBooks)
loadBooks(ctx: StateContext<BooksStateModel>) {
ctx.patchState({ loading: true });
return this.bookService.getList().pipe(
tap(response => ctx.patchState({
books: response.items,
loading: false
}))
);
}
}
```
## Forms
### Reactive Forms
```typescript
export class FormComponent implements OnInit {
form: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.form = this.fb.group({
name: ['', [Validators.required, Validators.maxLength(100)]],
email: ['', [Validators.required, Validators.email]],
age: [null, [Validators.min(0), Validators.max(120)]]
});
}
onSubmit(): void {
if (this.form.valid) {
const formData = this.form.getRawValue();
this.submitData(formData);
}
}
}
```
## Template Best Practices
```html
<!-- ✅ Use async pipe -->
<div *ngIf="users$ | async as users">
<div *ngFor="let user of users; trackBy: trackByUserId">
<h3>{{ user.name }}</h3>
<p>{{ user.email }}</p>
</div>
</div>
<!-- ✅ Accessibility -->
<button
type="button"
[attr.aria-label]="'::Close' | abpLocalization"
(click)="close()">
<i class="fa fa-times" aria-hidden="true"></i>
</button>
<!-- ✅ Localization -->
<h1>{{ '::WelcomeMessage' | abpLocalization }}</h1>
```
## Testing
```typescript
describe('BookService', () => {
let service: BookService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [BookService]
});
service = TestBed.inject(BookService);
httpMock = TestBed.inject(HttpTestingController);
});
it('should fetch books', () => {
const mockBooks = [{ id: 1, title: 'Test' }];
service.getList().subscribe(books => {
expect(books).toEqual(mockBooks);
});
const req = httpMock.expectOne('/api/app/books');
req.flush(mockBooks);
});
});
```
## Performance Optimization
### Change Detection
- Use OnPush strategy everywhere possible
- Avoid function calls in templates
- Use pure pipes
- Implement trackBy for lists
### Lazy Loading
```typescript
const routes: Routes = [
{
path: 'books',
loadChildren: () => import('./books/books.module')
.then(m => m.BooksModule)
}
];
```
### Bundle Optimization
- Use standalone components
- Implement lazy loading
- Use dynamic imports
- Tree-shake unused code
## Security Best Practices
1. **Input Validation**: Always validate user input
2. **Sanitization**: Use DomSanitizer when needed
3. **XSS Prevention**: Leverage Angular's built-in protection
4. **Authentication**: Use ABP's auth system
5. **Authorization**: Check permissions properly
6. **Data Protection**: Never expose sensitive data in client
## Code Quality Checklist
Before submitting code, ensure:
- [ ] TypeScript strict mode enabled
- [ ] No `any` types used
- [ ] OnPush change detection applied
- [ ] Proper unsubscription implemented
- [ ] Error handling in place
- [ ] Unit tests written
- [ ] Localization keys used (no hardcoded text)
- [ ] Permission checks added
- [ ] Accessibility attributes included
- [ ] Performance optimized
## File Organization (Nx Workspace)
```
libs/
feature-name/
src/
lib/
components/
component-name/
component-name.component.ts
component-name.component.html
component-name.component.scss
component-name.component.spec.ts
services/
models/
state/
guards/
pipes/
directives/
index.ts (public API)
```
## Common Patterns
### Smart/Dumb Components
- **Smart**: Container with business logic, state management
- **Dumb**: Presentational with @Input/@Output, OnPush
### Service Layer
- **API Services**: Backend communication
- **Business Services**: Business logic
- **Utility Services**: Helper functions
## Anti-Patterns to Avoid
❌ Using `any` type
❌ Forgetting to unsubscribe
❌ Complex logic in templates
❌ Nested subscriptions
❌ Direct state mutation
❌ Missing error handling
❌ Hardcoded strings
❌ Skipping unit tests
## Additional Resources
- Angular Style Guide: https://angular.io/guide/styleguide
- ABP Framework Docs: https://docs.abp.io
- RxJS Documentation: https://rxjs.dev
- Nx Documentation: https://nx.dev
- NGXS Documentation: https://www.ngxs.io
Follow these guidelines consistently to produce high-quality, maintainable Angular applications with ABP Framework.

776
npm/ng-packs/packages/schematics/src/commands/ai-config/files/windsurf/.windsurf/rules/guidelines.md

@ -1,652 +1,156 @@
# Windsurf AI Development Guidelines - Angular & ABP Framework # 💻 ABP Full-Stack Development Rules
_Expert Guidelines for .NET Backend (ABP) and Angular Frontend Development_
## Project Context You are a **senior full-stack developer** specializing in **ABP Framework (.NET)** and **Angular (TypeScript)**.
This is an enterprise-grade Angular application built on the ABP Framework, using Nx for workspace management and NGXS for state management. Follow these comprehensive guidelines to generate production-ready code. You write **clean, maintainable, and modular** code following **ABP, ASP.NET Core, and Angular best practices**.
--- ---
## 🎯 Core Development Principles ## 🧩 1. General Principles
- Maintain a clear separation between backend (ABP/.NET) and frontend (Angular) layers.
### 1. Type Safety First - Follow **modular architecture** — each layer or feature should be independently testable and reusable.
- **Always** use TypeScript strict mode - Always adhere to **official ABP documentation** ([docs.abp.io](https://docs.abp.io)) and **Angular official guides**.
- **Never** use `any` type - use `unknown` if type is truly unknown - Prioritize **readability, maintainability, and performance**.
- Define interfaces and types for all data structures - Write **idiomatic** and **self-documenting** code.
- Use proper generic types
### 2. Performance Optimization
- Use OnPush change detection strategy by default
- Implement lazy loading for feature modules
- Use trackBy with *ngFor directives
- Leverage async pipe for observables
- Avoid memory leaks with proper cleanup
### 3. Code Maintainability
- Follow SOLID principles
- Write self-documenting code with clear naming
- Keep functions small (<20 lines ideally)
- Add JSDoc comments for complex logic
- Use meaningful variable and function names
### 4. Security
- Validate all user inputs
- Sanitize data when necessary (DomSanitizer)
- Use ABP's permission system
- Never expose sensitive data in client code
- Follow OWASP security guidelines
### 5. Accessibility
- Include ARIA attributes
- Support keyboard navigation
- Use semantic HTML
- Follow WCAG 2.1 AA standards
---
## 📦 Angular Component Architecture
### Standard Component Structure
```typescript
import {
ChangeDetectionStrategy,
Component,
OnDestroy,
OnInit,
inject
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { Subject, takeUntil } from 'rxjs';
@Component({
selector: 'app-feature-name',
standalone: true,
imports: [CommonModule],
templateUrl: './feature-name.component.html',
styleUrls: ['./feature-name.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FeatureNameComponent implements OnInit, OnDestroy {
// Use inject() function (Angular 14+)
private readonly dataService = inject(DataService);
private readonly destroy$ = new Subject<void>();
// Observable streams with $ suffix
data$ = this.dataService.getData();
ngOnInit(): void {
// Initialization logic
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
}
```
### Component Best Practices
✅ **DO:**
- Use OnPush change detection
- Implement OnDestroy for cleanup
- Use standalone components for new code
- Prefer async pipe over manual subscriptions
- Use readonly for immutable properties
- Use inject() function for dependency injection
❌ **DON'T:**
- Put business logic in components
- Mutate @Input() properties
- Forget to unsubscribe from observables
- Use function calls in templates
- Use nested subscriptions
---
## 🔧 Service Development
### Service Pattern
```typescript
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, catchError, retry, shareReplay, throwError } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class DataService {
private readonly http = inject(HttpClient);
private readonly cache$ = new Map<string, Observable<any>>();
getData(id: string): Observable<Data> {
// Implement caching
if (!this.cache$.has(id)) {
this.cache$.set(
id,
this.http.get<Data>(`/api/data/${id}`).pipe(
retry(2),
catchError(this.handleError),
shareReplay(1)
)
);
}
return this.cache$.get(id)!;
}
private handleError(error: HttpErrorResponse): Observable<never> {
console.error('Service error:', error);
// Log to monitoring service here
return throwError(() => new Error('Operation failed. Please try again.'));
}
}
```
### Service Best Practices
- Use `providedIn: 'root'` for singleton services
- Return Observables for async operations
- Implement proper error handling
- Use caching strategies when appropriate
- Keep services focused (Single Responsibility)
---
## 🌊 RxJS Patterns & Operators
### Operator Decision Matrix
| Operator | Use Case | Behavior |
|----------|----------|----------|
| **switchMap** | Search, navigation | Cancels previous, emits latest |
| **mergeMap** | Parallel operations | Runs all concurrently |
| **concatMap** | Sequential operations | Maintains order, waits for completion |
| **exhaustMap** | Form submission, clicks | Ignores new until current completes |
### Subscription Management
```typescript
export class ExampleComponent implements OnDestroy {
private readonly destroy$ = new Subject<void>();
ngOnInit(): void {
// Pattern 1: takeUntil
this.service.getData()
.pipe(takeUntil(this.destroy$))
.subscribe(data => this.handleData(data));
// Pattern 2: take(1) for single emission
this.service.getConfig()
.pipe(take(1))
.subscribe(config => this.config = config);
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
}
```
### Template Usage (Preferred)
```typescript
// Component
data$ = this.service.getData().pipe(
catchError(error => {
this.handleError(error);
return of([]);
})
);
// Template
<div *ngIf="data$ | async as data">
{{ data.name }}
</div>
```
---
## 🏗️ ABP Framework Integration
### 1. Localization System
```typescript
// Component
import { LocalizationService } from '@abp/ng.core';
export class MyComponent {
private readonly localization = inject(LocalizationService);
readonly texts = {
title: this.localization.instant('::PageTitle'),
save: this.localization.instant('::Save'),
cancel: this.localization.instant('::Cancel')
};
}
// Template
<h1>{{ '::PageTitle' | abpLocalization }}</h1>
<button>{{ '::Save' | abpLocalization }}</button>
```
### 2. Permission System
```typescript
// Template
<button
*abpPermission="'BookStore.Books.Create'"
(click)="createBook()">
{{ '::NewBook' | abpLocalization }}
</button>
// Component
import { ConfigStateService } from '@abp/ng.core';
export class BookListComponent {
private readonly config = inject(ConfigStateService);
canEdit$ = this.config.getGrantedPolicy$('BookStore.Books.Edit');
canDelete$ = this.config.getGrantedPolicy$('BookStore.Books.Delete');
checkPermission(): boolean {
return this.config.getGrantedPolicy('BookStore.Books.Create');
}
}
```
### 3. API Proxy Services
```typescript
// ✅ ALWAYS use generated proxy services
import { BookService } from '@proxy/books';
import { GetBooksInput } from '@proxy/books/models';
export class BookListComponent {
private readonly bookService = inject(BookService);
books$ = this.bookService.getList({
maxResultCount: 10,
skipCount: 0
});
createBook(input: CreateBookDto): void {
this.bookService.create(input).pipe(
take(1),
catchError(this.handleError)
).subscribe(() => this.refreshList());
}
}
// ❌ DON'T create manual HTTP calls for ABP APIs
```
### 4. State Management with NGXS
```typescript
// Actions
export class GetBooks {
static readonly type = '[Books] Get Books';
constructor(public payload: GetBooksInput) {}
}
export class CreateBook {
static readonly type = '[Books] Create Book';
constructor(public payload: CreateBookDto) {}
}
// State
export interface BooksStateModel {
books: BookDto[];
loading: boolean;
error: string | null;
totalCount: number;
}
@State<BooksStateModel>({
name: 'books',
defaults: {
books: [],
loading: false,
error: null,
totalCount: 0
}
})
@Injectable()
export class BooksState {
private readonly bookService = inject(BookService);
@Selector()
static books(state: BooksStateModel): BookDto[] {
return state.books;
}
@Selector()
static loading(state: BooksStateModel): boolean {
return state.loading;
}
@Selector()
static totalCount(state: BooksStateModel): number {
return state.totalCount;
}
@Action(GetBooks)
getBooks(ctx: StateContext<BooksStateModel>, action: GetBooks) {
ctx.patchState({ loading: true, error: null });
return this.bookService.getList(action.payload).pipe(
tap(response => {
ctx.patchState({
books: response.items,
totalCount: response.totalCount,
loading: false
});
}),
catchError(error => {
ctx.patchState({
loading: false,
error: error.message
});
return throwError(() => error);
})
);
}
@Action(CreateBook)
createBook(ctx: StateContext<BooksStateModel>, action: CreateBook) {
return this.bookService.create(action.payload).pipe(
tap(book => {
const state = ctx.getState();
ctx.patchState({
books: [...state.books, book],
totalCount: state.totalCount + 1
});
})
);
}
}
```
### 5. Multi-Tenancy Support
```typescript
import { ConfigStateService } from '@abp/ng.core';
export class TenantAwareComponent {
private readonly config = inject(ConfigStateService);
get currentTenant() {
return this.config.getOne('currentTenant');
}
get isTenantContext(): boolean {
return !!this.currentTenant?.id;
}
}
```
---
## 📝 Reactive Forms
### Form Implementation
```typescript
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { CustomValidators } from './validators';
export class BookFormComponent implements OnInit {
private readonly fb = inject(FormBuilder);
bookForm!: FormGroup;
ngOnInit(): void {
this.bookForm = this.fb.group({
name: ['', [
Validators.required,
Validators.minLength(3),
Validators.maxLength(128)
]],
type: ['', Validators.required],
publishDate: ['', [
Validators.required,
CustomValidators.notFutureDate
]],
price: [0, [
Validators.required,
Validators.min(0),
Validators.max(999999.99)
]],
description: ['', Validators.maxLength(1000)]
});
}
onSubmit(): void {
if (this.bookForm.valid) {
const formValue = this.bookForm.getRawValue();
this.submitForm(formValue);
} else {
this.markFormGroupTouched(this.bookForm);
}
}
private markFormGroupTouched(formGroup: FormGroup): void {
Object.keys(formGroup.controls).forEach(key => {
const control = formGroup.get(key);
control?.markAsTouched();
if (control instanceof FormGroup) {
this.markFormGroupTouched(control);
}
});
}
}
```
---
## 🎨 Template Best Practices
```html
<!-- ✅ Async pipe with null check -->
<div *ngIf="books$ | async as books; else loading">
<div
*ngFor="let book of books; trackBy: trackByBookId"
class="book-item">
<h3>{{ book.name }}</h3>
<p>{{ book.publishDate | date:'shortDate' }}</p>
<p>{{ book.price | currency }}</p>
</div>
</div>
<ng-template #loading>
<div class="spinner">Loading...</div>
</ng-template>
<!-- ✅ Accessibility -->
<button
type="button"
[attr.aria-label]="'::DeleteBook' | abpLocalization"
[attr.aria-disabled]="(canDelete$ | async) === false"
[disabled]="(canDelete$ | async) === false"
(click)="deleteBook(book)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
<!-- ✅ Permission check -->
<div *abpPermission="'BookStore.Books.Create'">
<button (click)="createBook()">
{{ '::NewBook' | abpLocalization }}
</button>
</div>
<!-- ✅ Localization -->
<h1>{{ '::BookManagement' | abpLocalization }}</h1>
<p>{{ '::BookDescription' | abpLocalization:{ name: book.name } }}</p>
```
--- ---
## 🧪 Testing Strategies ## ⚙️ 2. ABP / .NET Development Rules
### Component Testing ### Code Style and Structure
- Follow ABP’s standard folder structure:
```typescript - `*.Application`, `*.Domain`, `*.EntityFrameworkCore`, `*.HttpApi`
describe('BookListComponent', () => { - Write concise, idiomatic C# code using modern language features.
let component: BookListComponent; - Apply **modular and layered design** (Domain, Application, Infrastructure, UI).
let fixture: ComponentFixture<BookListComponent>; - Prefer **LINQ** and **lambda expressions** for collection operations.
let mockBookService: jasmine.SpyObj<BookService>; - Use **descriptive method and variable names** (`GetActiveUsers`, `CalculateTotalAmount`).
beforeEach(async () => { ### Naming Conventions
mockBookService = jasmine.createSpyObj('BookService', [ - **PascalCase** → Classes, Methods, Properties
'getList', - **camelCase** → Local variables and private fields
'create', - **UPPER_CASE** → Constants
'delete' - Prefix interfaces with **`I`** (e.g., `IUserRepository`).
]);
### C# and .NET Usage
await TestBed.configureTestingModule({ - Use **C# 10+ features** (records, pattern matching, null-coalescing assignment).
imports: [BookListComponent], - Utilize **ABP modules** (Permission Management, Setting Management, Audit Logging).
providers: [ - Integrate **Entity Framework Core** with ABP’s repository abstractions.
{ provide: BookService, useValue: mockBookService }
] ### Syntax and Formatting
}).compileComponents(); - Follow [Microsoft C# Coding Conventions](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions).
- Use `var` when the type is clear.
fixture = TestBed.createComponent(BookListComponent); - Use `string interpolation` and null-conditional operators.
component = fixture.componentInstance; - Keep code consistent and well-formatted.
});
### Error Handling and Validation
it('should create', () => { - Use exceptions only for exceptional cases.
expect(component).toBeTruthy(); - Log errors via ABP’s built-in logging or a compatible provider.
}); - Validate models with **DataAnnotations** or **FluentValidation**.
- Rely on ABP’s global exception middleware for unified responses.
it('should load books on init', () => { - Return consistent HTTP status codes and error DTOs.
const mockBooks = [
{ id: '1', name: 'Book 1', price: 10 }, ### API Design
{ id: '2', name: 'Book 2', price: 20 } - Build RESTful APIs via `HttpApi` layer and **ABP conventional controllers**.
]; - Use **attribute-based routing** and versioning when needed.
- Apply **action filters/middleware** for cross-cutting concerns (auditing, authorization).
mockBookService.getList.and.returnValue(of({
items: mockBooks, ### Performance Optimization
totalCount: 2 - Use `async/await` for I/O operations.
})); - Use `IDistributedCache` over `IMemoryCache`.
- Avoid N+1 queries — include relations explicitly.
component.ngOnInit(); - Implement pagination with `PagedResultDto`.
expect(mockBookService.getList).toHaveBeenCalled(); ### Key Conventions
}); - Use **Dependency Injection** via ABP’s DI system.
}); - Apply **repository pattern** or EF Core directly as needed.
``` - Use **AutoMapper** or ABP object mapping for DTOs.
- Implement **background jobs** with ABP’s job system or `IHostedService`.
- Follow **domain-driven design (DDD)** principles:
- Business rules in Domain layer.
- Use `AuditedAggregateRoot`, `FullAuditedEntity`, etc.
- Avoid unnecessary dependencies between layers.
### Testing
- Use **xUnit**, **Shouldly**, and **NSubstitute** for testing.
- Write **unit and integration tests** per module (`Application.Tests`, `Domain.Tests`).
- Mock dependencies properly and use ABP’s test base classes.
### Security
- Use **OpenIddict** for authentication & authorization.
- Implement permission checks through ABP’s infrastructure.
- Enforce **HTTPS** and properly configure **CORS**.
### API Documentation
- Use **Swagger / OpenAPI** (Swashbuckle or NSwag).
- Add XML comments to controllers and DTOs.
- Follow ABP’s documentation conventions for module APIs.
**Reference Best Practices:**
- [Domain Services](https://abp.io/docs/latest/framework/architecture/best-practices/domain-services)
- [Repositories](https://abp.io/docs/latest/framework/architecture/best-practices/repositories)
- [Entities](https://abp.io/docs/latest/framework/architecture/best-practices/entities)
- [Application Services](https://abp.io/docs/latest/framework/architecture/best-practices/application-services)
- [DTOs](https://abp.io/docs/latest/framework/architecture/best-practices/data-transfer-objects)
- [Entity Framework Integration](https://abp.io/docs/latest/framework/architecture/best-practices/entity-framework-core-integration)
--- ---
## 🚀 Performance Optimization ## 🌐 3. Angular / TypeScript Development Rules
### 1. Change Detection Strategy ### TypeScript Best Practices
```typescript - Enable **strict type checking** in `tsconfig.json`.
@Component({ - Use **type inference** when the type is obvious.
changeDetection: ChangeDetectionStrategy.OnPush - Avoid `any`; use `unknown` or generics instead.
}) - Use interfaces and types for clarity and structure.
```
### Angular Best Practices
### 2. TrackBy Functions - Prefer **standalone components** (no `NgModules`).
```typescript - Do **NOT** set `standalone: true` manually — it’s default.
trackByBookId(index: number, book: BookDto): string { - Use **signals** for state management.
return book.id; - Implement **lazy loading** for feature routes.
} - Avoid `@HostBinding` / `@HostListener`; use `host` object in decorators.
``` - Use **`NgOptimizedImage`** for static images (not base64).
### 3. Lazy Loading ### Components
```typescript - Keep components small, focused, and reusable.
const routes: Routes = [ - Use `input()` and `output()` functions instead of decorators.
{ - Use `computed()` for derived state.
path: 'books', - Always set `changeDetection: ChangeDetectionStrategy.OnPush`.
loadChildren: () => import('./books/books.routes') - Use **inline templates** for small components.
.then(m => m.BOOKS_ROUTES) - Prefer **Reactive Forms** over template-driven forms.
} - Avoid `ngClass` → use `[class]` bindings.
]; - Avoid `ngStyle` → use `[style]` bindings.
```
### State Management
### 4. Virtual Scrolling (for large lists) - Manage **local component state** with signals.
```typescript - Use **`computed()`** for derived data.
<cdk-virtual-scroll-viewport itemSize="50" class="list-viewport"> - Keep state transformations **pure and predictable**.
<div *cdkVirtualFor="let book of books; trackBy: trackByBookId"> - Avoid `mutate()` on signals — use `update()` or `set()`.
{{ book.name }}
</div> ### Templates
</cdk-virtual-scroll-viewport> - Use **native control flow** (`@if`, `@for`, `@switch`) instead of structural directives.
``` - Keep templates minimal and declarative.
- Use the **async pipe** for observable bindings.
---
### Services
## 📁 File Structure (Nx Workspace) - Design services for **single responsibility**.
- Provide services using `providedIn: 'root'`.
``` - Use the **`inject()` function** instead of constructor injection.
libs/
books/
feature/
src/
lib/
components/
book-list/
book-form/
book-detail/
services/
state/
guards/
books-feature.routes.ts
index.ts
data-access/
src/
lib/
services/
models/
index.ts
ui/
src/
lib/
components/
index.ts
```
---
## ✅ Quality Checklist
Before committing code, verify:
- [ ] TypeScript strict mode compliance
- [ ] No `any` types
- [ ] OnPush change detection
- [ ] Proper unsubscription
- [ ] Error handling implemented
- [ ] Unit tests written
- [ ] Localization keys used
- [ ] Permission checks added
- [ ] Accessibility attributes included
- [ ] Performance optimized (trackBy, lazy loading)
- [ ] Security validated
- [ ] Code formatted (Prettier)
- [ ] Linting passed
--- ---
## 🚫 Common Anti-Patterns ## 🔒 4. Combined Full-Stack Practices
- Ensure backend and frontend follow consistent **DTO contracts** and **naming conventions**.
| Anti-Pattern | Why It's Bad | Better Approach | - Maintain shared models (e.g., via a `contracts` package or OpenAPI generation).
|--------------|--------------|-----------------| - Version APIs carefully and handle changes in Angular clients.
| Using `any` | Loses type safety | Use proper types or `unknown` | - Use ABP’s **CORS**, **Swagger**, and **Identity** modules to simplify frontend integration.
| No unsubscribe | Memory leaks | Use takeUntil or async pipe | - Apply **global error handling** and consistent response wrappers in both layers.
| Logic in templates | Hard to test | Move to component/service | - Monitor performance with tools like **Application Insights**, **ABP auditing**, or **Angular profiler**.
| Nested subscriptions | Hard to maintain | Use RxJS operators |
| Direct state mutation | Breaks change detection | Use immutable patterns |
| Missing error handling | Poor UX | Always handle errors |
| Hardcoded strings | Not localizable | Use localization system |
---
## 📚 Resources
- [Angular Style Guide](https://angular.io/guide/styleguide)
- [ABP Framework Documentation](https://docs.abp.io)
- [RxJS Documentation](https://rxjs.dev)
- [Nx Documentation](https://nx.dev)
- [NGXS Documentation](https://www.ngxs.io)
--- ---
Follow these guidelines to build maintainable, performant, and secure Angular applications with ABP Framework. ## ✅ Summary
This document defines a unified standard for developing **ABP + Angular full-stack applications**, ensuring:
- Code is **modular**, **performant**, and **maintainable**.
- Teams follow **consistent conventions** across backend and frontend.
- Every layer (Domain, Application, UI) is **clean, testable, and scalable**.

Loading…
Cancel
Save