

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1# ABP Framework – Cursor Rules2# Scope: ABP Framework repository (abpframework/abp) — for developing ABP itself, not ABP-based applications.3# Goal: Enforce ABP module architecture best practices (DDD, layering, DB/ORM independence),4# maintain backward compatibility, ensure extensibility, and align with ABP contribution guidelines.56## Global Defaults7- Follow existing patterns in this repository first. Before generating new code, search for similar implementations and mirror their structure, naming, and conventions.8- Prefer minimal, focused diffs. Avoid drive-by refactors and formatting churn.9- Preserve public APIs. Avoid breaking changes unless explicitly requested and justified.10- Keep layers clean. Do not introduce forbidden dependencies between packages.1112## Module / Package Architecture (Layering)13- Use a layered module structure with explicit dependencies:14 - *.Domain.Shared: constants, enums, shared types safe for all layers and 3rd-party clients. MUST NOT contain entities, repositories, domain services, or business objects.15 - *.Domain: entities/aggregate roots, repository interfaces, domain services.16 - *.Application.Contracts: application service interfaces and DTOs.17 - *.Application: application service implementations.18 - *.EntityFrameworkCore / *.MongoDb: ORM integration packages depend on *.Domain only. MUST NOT depend on other layers.19 - *.HttpApi: REST controllers. MUST depend ONLY on *.Application.Contracts (NOT *.Application).20 - *.HttpApi.Client: remote client proxies. MUST depend ONLY on *.Application.Contracts.21 - *.Web: UI. MUST depend ONLY on *.HttpApi.22- Enforce dependency direction:23 - Web -> HttpApi -> Application.Contracts24 - Application -> Domain + Application.Contracts25 - Domain -> Domain.Shared26 - ORM integration -> Domain27- Do not leak web concerns into application/domain.2829## Domain Layer – Entities & Aggregate Roots30- Define entities in the domain layer.31- Entities must be valid at creation:32 - Provide a primary constructor that enforces invariants.33 - Always include a protected parameterless constructor for ORMs.34 - Always initialize sub-collections in the primary constructor.35 - Do NOT generate Guid keys inside constructors; accept `id` and generate using `IGuidGenerator` from the calling code.36- Make members `virtual` where appropriate (ORM/proxy compatibility).37- Protect consistency:38 - Use non-public setters (private/protected/internal) when needed.39 - Provide meaningful domain methods for state transitions; prefer returning `this` from setters when applicable.40- Aggregate roots:41 - Always use a single `Id` property. Do NOT use composite keys.42 - Prefer `Guid` keys for aggregate roots.43 - Inherit from `AggregateRoot<TKey>` or audited base classes as required.44- Aggregate boundaries:45 - Keep aggregates small. Avoid large sub-collections unless necessary.46- References:47 - Reference other aggregate roots by Id only.48 - Do NOT add navigation properties to other aggregate roots.4950## Repositories51- Define repository interfaces in the domain layer.52- Create one dedicated repository interface per aggregate root (e.g., `IProductRepository`).53- Public repository interfaces exposed by modules:54 - SHOULD inherit from `IBasicRepository<TEntity, TKey>` (or `IReadOnlyRepository<...>` when suitable).55 - SHOULD NOT expose `IQueryable` in the public contract.56 - Internal implementations MAY use `IRepository<TEntity, TKey>` and `IQueryable` as needed.57- Do NOT define repositories for non-aggregate-root entities.58- Repository method conventions:59 - All methods async.60 - Include optional `CancellationToken cancellationToken = default` in every method.61 - For single-entity returning methods: include `bool includeDetails = true`.62 - For list returning methods: include `bool includeDetails = false`.63 - Do NOT return composite projection classes like `UserWithRoles`. Use `includeDetails` for eager-loading.64 - Avoid projection-only view models from repositories by default; only allow when performance is critical.6566## Domain Services67- Define domain services in the domain layer.68- Default: do NOT create interfaces for domain services unless necessary (mocking/multiple implementations).69- Naming: use `*Manager` suffix.70- Domain service methods:71 - Focus on operations that enforce domain invariants and business rules.72 - Query methods are acceptable when they encapsulate domain-specific lookup logic (e.g., normalized lookups, caching, complex resolution). Simple queries belong in repositories.73 - Define methods that mutate state and enforce domain rules.74 - Use specific, intention-revealing names (avoid generic `UpdateXAsync`).75 - Accept valid domain objects as parameters; do NOT accept/return DTOs.76 - On rule violations, throw `BusinessException` (or custom business exceptions).77 - Use unique, namespaced error codes suitable for localization (e.g., `IssueTracking:ConcurrentOpenIssueLimit`).78 - Do NOT depend on authenticated user logic; pass required values from application layer.7980## Application Services (Contracts + Implementation)81### Contracts82- Define one interface per application service in *.Application.Contracts.83- Interfaces must inherit from `IApplicationService`.84- Naming: `I*AppService`.85- Do NOT accept/return entities. Use DTOs and primitive parameters.8687### Method Naming & Shapes88- All service methods async and end with `Async`.89- Do not repeat entity names in method names (use `GetAsync`, not `GetProductAsync`).90- Standard CRUD:91 - `GetAsync(Guid id)` returns a detailed DTO.92 - `GetListAsync(QueryDto queryDto)` returns a list of detailed DTOs.93 - `CreateAsync(CreateDto dto)` returns detailed DTO.94 - `UpdateAsync(Guid id, UpdateDto dto)` returns detailed DTO (id MUST NOT be inside update DTO).95 - `DeleteAsync(Guid id)` returns void/Task.96- `GetListAsync` query DTO:97 - Filtering/sorting/paging fields optional with defaults.98 - Enforce a maximum page size for performance.99100### DTO Usage101- Inputs:102 - Do not include unused properties.103 - Do NOT share input DTOs between methods.104 - Do NOT use inheritance between input DTOs (except rare abstract base DTO cases; be very cautious).105106### Implementation107- Application layer must be independent of web.108- Implement interfaces in *.Application, name `ProductAppService` for `IProductAppService`.109- Inherit from `ApplicationService`.110- Make all public methods `virtual`.111- Avoid private helper methods; prefer `protected virtual` helpers for extensibility.112- Data access:113 - Use dedicated repositories (e.g., `IProductRepository`).114 - Do NOT use generic repositories.115 - Do NOT put LINQ/SQL queries inside application service methods; repositories perform queries.116- Entity mutation:117 - Load required entities from repositories.118 - Mutate using domain methods.119 - Call repository `UpdateAsync` after updates (do not assume change tracking).120- Extra properties:121 - Use `MapExtraPropertiesTo` or configure object mapper for `MapExtraProperties`.122- Files:123 - Do NOT use web types like `IFormFile` or `Stream` in application services.124 - Controllers handle upload; pass `byte[]` (or similar) to application services.125- Cross-application-service calls:126 - Do NOT call other application services within the same module.127 - For reuse, push logic into domain layer or extract shared helpers carefully.128 - You MAY call other modules’ application services only via their Application.Contracts.129130## DTO Conventions131- Define DTOs in *.Application.Contracts.132- Prefer ABP base DTO types (`EntityDto<TKey>`, audited DTOs).133- For aggregate roots, prefer extensible DTO base types so extra properties can map.134- DTO properties: public getters/setters.135- Input DTO validation:136 - Use data annotations.137 - Reuse constants from Domain.Shared wherever possible.138- Avoid logic in DTOs; only implement `IValidatableObject` when necessary.139- Do NOT use `[Serializable]` attribute (BinaryFormatter is obsolete); ABP uses JSON serialization.140- Output DTO strategy:141 - Prefer a Basic DTO and a Detailed DTO; avoid many variants.142 - Detailed DTOs: include reference details as nested basic DTOs; avoid duplicating raw FK ids unnecessarily.143144## EF Core Integration145- Define a separate DbContext interface + class per module.146- Do NOT rely on lazy loading; do NOT enable lazy loading.147- DbContext interface:148 - Inherit from `IEfCoreDbContext`.149 - Add `[ConnectionStringName("...")]`.150 - Expose `DbSet<TEntity>` ONLY for aggregate roots.151 - Do NOT include setters in the interface.152- DbContext class:153 - Inherit `AbpDbContext<TDbContext>`.154 - Add `[ConnectionStringName("...")]` and implement the interface.155- Table prefix/schema:156 - Provide static `TablePrefix` and `Schema` defaulted from constants.157 - Use short prefixes; `Abp` prefix reserved for ABP core modules.158 - Default schema should be `null`.159- Model mapping:160 - Do NOT configure entities directly inside `OnModelCreating`.161 - Create `ModelBuilder` extension method `ConfigureX()` and call it.162 - Call `b.ConfigureByConvention()` for each entity.163- Repository implementations:164 - Inherit from `EfCoreRepository<TDbContextInterface, TEntity, TKey>`.165 - Use DbContext interface as generic parameter.166 - Pass cancellation tokens using `GetCancellationToken(cancellationToken)`.167 - Implement `IncludeDetails(include)` extension per aggregate root with sub-collections.168 - Override `WithDetailsAsync()` where needed.169170## MongoDB Integration171- Define a separate MongoDbContext interface + class per module.172- MongoDbContext interface:173 - Inherit from `IAbpMongoDbContext`.174 - Add `[ConnectionStringName("...")]`.175 - Expose `IMongoCollection<TEntity>` ONLY for aggregate roots.176- MongoDbContext class:177 - Inherit `AbpMongoDbContext` and implement the interface.178- Collection prefix:179 - Provide static `CollectionPrefix` defaulted from constants.180 - Use short prefixes; `Abp` prefix reserved for ABP core modules.181- Mapping:182 - Do NOT configure directly inside `CreateModel`.183 - Create `IMongoModelBuilder` extension method `ConfigureX()` and call it.184- Repository implementations:185 - Inherit from `MongoDbRepository<TMongoDbContextInterface, TEntity, TKey>`.186 - Pass cancellation tokens using `GetCancellationToken(cancellationToken)`.187 - Ignore `includeDetails` for MongoDB in most cases (documents load sub-collections).188 - Prefer `GetQueryableAsync()` to ensure ABP data filters are applied.189190## ABP Module Classes191- Every package must have exactly one `AbpModule` class.192- Naming: `Abp[ModuleName][Layer]Module` (e.g., `AbpIdentityDomainModule`, `AbpIdentityApplicationModule`).193- Use `[DependsOn(typeof(...))]` to declare module dependencies explicitly.194- Override `ConfigureServices` for DI registration and configuration.195- Override `OnApplicationInitialization` sparingly; prefer `ConfigureServices` when possible.196- Each module must be usable standalone; avoid hidden cross-module coupling.197198## Framework Extensibility199- All public and protected members should be `virtual` for inheritance-based extensibility.200- Prefer `protected virtual` over `private` for helper methods to allow overriding.201- Use `[Dependency(ReplaceServices = true)]` patterns for services intended to be replaceable.202- Provide extension points via interfaces and virtual methods.203- Document extension points with XML comments explaining intended usage.204- Consider providing `*Options` classes for configuration-based extensibility.205206## Backward Compatibility207- Do NOT remove or rename public API members without a deprecation cycle.208- Use `[Obsolete("Message. Use X instead.")]` with clear migration guidance before removal.209- Maintain binary and source compatibility within major versions.210- Add new optional parameters with defaults; do not change existing method signatures.211- When adding new abstract members to base classes, provide default implementations if possible.212- Prefer adding new interfaces over modifying existing ones.213214## Localization Resources215- Define localization resources in Domain.Shared.216- Resource class naming: `[ModuleName]Resource` (e.g., `IdentityResource`, `PermissionManagementResource`).217- JSON files under `/Localization/[ModuleName]/` directory.218- Use `LocalizableString.Create<TResource>("Key")` for localizable exceptions and messages.219- All user-facing strings must be localized; no hardcoded English text in code.220- Error codes should be namespaced: `ModuleName:ErrorCode` (e.g., `Identity:UserNameAlreadyExists`).221222## Settings & Features223- Define settings in `*SettingDefinitionProvider` in Domain.Shared or Domain.224- Setting names must follow `Abp.[ModuleName].[SettingName]` convention.225- Define features in `*FeatureDefinitionProvider` in Domain.Shared.226- Feature names must follow `[ModuleName].[FeatureName]` convention.227- Use constants for setting/feature names; never hardcode strings.228229## Permissions230- Define permissions in `*PermissionDefinitionProvider` in Application.Contracts.231- Permission names must follow `[ModuleName].[Permission]` convention.232- Use constants for permission names (e.g., `IdentityPermissions.Users.Create`).233- Group related permissions logically.234235## Event Bus & Distributed Events236- Use `ILocalEventBus` for intra-module communication within the same process.237- Use `IDistributedEventBus` for cross-module or cross-service communication.238- Define Event Transfer Objects (ETOs) in Domain.Shared for distributed events.239- ETO naming: `[EntityName][Action]Eto` (e.g., `UserCreatedEto`, `OrderCompletedEto`).240- Event handlers belong in the Application layer.241- ETOs should be simple, serializable, and contain only primitive types or nested ETOs.242243## Testing244- Unit tests: `*.Tests` projects for isolated logic testing with mocked dependencies.245- Integration tests: `*.EntityFrameworkCore.Tests` / `*.MongoDB.Tests` for repository and DB tests.246- Use `AbpIntegratedTest<TModule>` or `AbpApplicationTestBase<TModule>` base classes.247- Test modules should use `[DependsOn]` on the module under test.248- Use `Shouldly` assertions (ABP convention).249- Test both EF Core and MongoDB implementations when the module supports both.250- Include tests for permission checks, validation, and edge cases.251- Name test methods: `MethodName_Scenario_ExpectedResult` or `Should_ExpectedBehavior_When_Condition`.252253## Contribution Discipline (PR / Issues / Tests)254- Before significant changes, align via GitHub issue/discussion.255- PRs:256 - Keep changes scoped and reviewable.257 - Add/update unit/integration tests relevant to the change.258 - Build and run tests for the impacted area when possible.259- Localization:260 - Prefer the `abp translate` workflow for adding missing translations (generate `abp-translation.json`, fill, apply, then PR).261262## Review Checklist263- Layer dependencies respected (no forbidden references).264- No `IQueryable` or generic repository usage leaking into application/domain.265- Entities maintain invariants; Guid id generation not inside constructors.266- Repositories follow async + CancellationToken + includeDetails conventions.267- No web types in application services.268- DTOs in contracts, serializable, validated, minimal, no logic.269- EF/Mongo integration follows context + mapping + repository patterns.270- Minimal diff; no unnecessary API surface expansion.271
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| abpframework/abpnpm/ng-packs/packages/schematics/src/commands/ai-config/files/claude/.claude/CLAUDE.md · 14k | CLAUDE.md | testlint-formatstylearch+8 | 76/100 | 13 days ago | |
| abpframework/abpnpm/ng-packs/packages/schematics/src/commands/ai-config/files/copilot/.github/copilot-instructions.md · 14k | Copilot instructions | testlint-formatstylearch+8 | 76/100 | 13 days ago | |
| abpframework/abpnpm/ng-packs/packages/schematics/src/commands/ai-config/files/cursor/.cursor/rules/cursor.mdc · 14k | Cursor rules | testlint-formatstylearch+8 | 76/100 | 13 days ago | |
| abpframework/abpnpm/ng-packs/packages/schematics/src/commands/ai-config/files/gemini/.gemini/GEMINI.md · 14k | GEMINI.md | testlint-formatstylearch+8 | 76/100 | 13 days ago | |
| abpframework/abpnpm/ng-packs/packages/schematics/src/commands/ai-config/files/windsurf/.windsurf/rules/guidelines.md · 14k | Windsurf rules | testlint-formatstylearch+8 | 76/100 | 13 days ago | |
| abpframework/abp.github/copilot-instructions.md · 14k | Copilot instructions | teststyletypesgit+4 | 61/100 | 13 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/abpframework-abp-cursorrules)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.
Directory