Mango.Nop.Libraries/.github/copilot-instructions.md

6.4 KiB

Mango.Nop Libraries — Domain Rules

own-dep-repos: "name: path" — paths are relative to this repo root (.github/..)

@repo { name = "Mango.Nop Libraries" type = "framework" layer = 1 own-dep-repos = ["AyCode.Core: ../../../../../Aycode/Source/AyCode.Core"] }

This is the single source of truth for Mango.Nop library rules. Do not duplicate these elsewhere. For detailed docs see: README.mddocs/ For core framework rules see: .github/copilot-instructions.md (in AyCode.Core repo) External repos in own-dep-repos are fully accessible — read their source code, docs, and .github/copilot-instructions.md freely when you need type definitions, base classes, or context. Do not limit yourself to the current workspace.

nopCommerce Compatibility

  1. All three libraries target net9.0 — required by nopCommerce 4.80.9. Do NOT change TFM.
  2. NopDependencies folder in Mango.Nop.Core contains mirror copies of nopCommerce entity classes (BaseEntity, Customer, Order, Product, GenericAttribute, etc.) so that Mango.Nop.Core can be referenced without the full nopCommerce dependency chain.
  3. Do NOT modify files in NopDependencies/ unless the nopCommerce version changes.

Entity & DTO Patterns

  1. BaseEntity (NopDependencies) = root entity base with int Id and IBaseEntity interface. All nopCommerce entities inherit from this. Namespace: Nop.Core.
  2. MgEntityBase = custom entity base that inherits BaseEntity and implements IEntityInt (from AyCode.Interfaces). Used for domain-specific entities and complex DTOs.
  3. Two DTO base strategies exist:
    • ModelDtoBase<TMainEntity> — for simple DTOs (e.g. CustomerDto). Manual CopyEntityValuesToDto/CopyDtoValuesToEntity overrides. Uses Activator.CreateInstance<T>() in CreateMainEntity().
    • MgEntityBase + IModelDtoBase<T> — for complex DTOs with LinqToDB [Association] navigations (e.g. MgOrderDto, MgOrderItemDto). Uses PropertyHelper.CopyPublicValueTypeProperties() for automatic value-type copy.
  4. GenericAttribute = polymorphic key-value store. KeyGroup = owner type name, EntityId = owner ID, Key = attribute name, Value = string value. Use GenericAttributeExtensions.GetValueOrNull<T>()/GetValueOrDefault<T>()/TryGetValue<T>() — never parse raw strings manually.

Data Access Patterns

  1. MgDbTableBase<TEntity> = repository base wrapping nopCommerce EntityRepository<TEntity>. Adds GetAll() (IQueryable<T>), automatic timestamp handling (ITimeStampCreated/ITimeStampModified), virtual CRUD hooks (OnInsert/OnUpdate/OnDelete).
  2. MgDtoDbTableBase<TDtoEntity, TMainEntity> = DTO-aware repository. CRITICAL: All Delete methods throw — always use DeleteMainEntityById(int id). Event bridging: DTO insert/update events → main entity events.
  3. MgDbContextBase = DB context base (NOT EF Core DbContext — wraps INopDataProvider and IRepository<T> nopCommerce repos). Provides Transaction/TransactionSafe/TransactionAsync/TransactionSafeAsync. TransactionSafe variants use global SemaphoreSlim lock for serialized access.

Service Patterns

  1. MgBackgroundServiceBase — inherits Microsoft.Extensions.Hosting.BackgroundService. Loop: Task.Delay(interval)OnExecuteAsync(). Pause support. Per-iteration exception handling. Uses nopCommerce Nop.Services.Logging.ILogger (not Mango logger).
  2. MgEventConsumerBase — subscribes to EntityUpdatedEvent<Product>, EntityInsertedEvent<Product>, CustomerRegisteredEvent, OrderPlacedEvent, PageRenderingEvent, ProductSearchEvent. Override relevant handlers. Built-in: CheckAndUpdateProductManageInventoryMethodToManageStock().
  3. NopLogWriter — AyCode → nopCommerce log bridge. Log level mapping: Detail/Trace/Debug/InfoInformation; Suggest/WarningWarning; ErrorError. Uses TransactionScope(Suppress) to avoid nesting.

Conventions

  1. Mg prefix for all custom types: MgEntityBase, MgOrderDto, MgDbTableBase, etc.
  2. No redundant code — before writing new logic, check whether similar methods already exist in the current context. Reuse or extract shared logic.
  3. Keep all .md files in sync — when you modify code and you know which .md file documents it, update that .md file too. If you notice a contradiction between code and an .md file, automatically update the .md to match the code (code is the source of truth). When fixing a reference, check other .md files that may share the same broken reference. If the root cause is at a lower layer, fix it there first. During code review, if you find useful behavior or conventions not yet documented, briefly suggest what to document and where — but do not add new content without approval.
  4. All AyCode references are via DLL (not ProjectReference) — this is intentional. AyCode.Core solution (../../../../../Aycode/Source/AyCode.Core/) contains all core framework code: interfaces, serialization, binary protocol, SignalR base classes, data sources, logging. Types not defined in this library (e.g. IEntityInt, IId<T>, AcConst, ToonDescription) likely live in AyCode.Core.
  5. Do not re-read .md files already in your context window. They only change if you modify them yourself (new content is already in context) or if the developer tells you they changed — in that case re-read them once.
  6. Documentation layering — write .md documentation at the defining layer (where the code lives). Higher-layer .md files reference AyCode.Core base docs using the form ../../../../../Aycode/Source/AyCode.Core/{Project}/docs/FILENAME.md. Document only project-specific overrides or extensions. Never duplicate base-layer descriptions in consumer-level docs.
  7. LinqToDB associations — use [Association(ThisKey = nameof(FK), OtherKey = nameof(Target.Id), CanBeNull = true/false)] for navigation properties in DTOs.
  8. Timestamp auto-management — entities with ITimeStampCreated or ITimeStampModified get automatic UTC timestamps in MgDbTableBase CRUD hooks. Don't set these manually.

Reference Modes

  • Full stack (ProjectReference, all 3 libraries) — for nopCommerce plugins needing entity access, data layer, and services.
  • Types only (DLL reference, Mango.Nop.Core only) — for projects that only need DTOs, entities, and interfaces without the nopCommerce runtime dependency.