The more the community invests in a bridge, the more powerful the tool becomes“DomainCraft” is a working title
DomainCraft

Concepts

The Generation Gap pattern · Docs — DomainCraft

How bridges protect developer-written code across regenerations with overwrite:false and partial classes.

Code generators have a classic problem: what happens to hand-written business logic when you regenerate? DomainCraft answers it with the Generation Gap pattern — split generated code (always overwritten) from developer code (scaffolded once and owned).

The two halves

Bridges mark a template overwrite: false to scaffold a file once; the renderer skips it afterwards and records it in the file manifest as Custom: true, Written: false. The migration engine uses this manifest to protect developer-owned files when an entity is deleted, renamed or its types change.

The reference C# bridge implements the pattern with C# partial classes. Per entity it generates:

  • src/Application/Generated/<Entity>Service.g.csalways overwritten partial class with CRUD and the full hook surface: async before/after hooks (OnBeforeCreateAsync, OnAfterUpdateAsync, …) and full-flow override hooks (On*OverrideAsync). All of them return HookResultSuccess() to continue, Handled() to take over persistence (e.g. route to a queue instead of the DB), or Fail("reason") to abort cleanly (mapped to HTTP 400).
  • src/Application/Services/<Entity>Service.csoverwrite: false partial where the developer overrides the async hooks.
  • I<Entity>Service interface and DI registration I<Entity>Service → <Entity>Service (the merged partial class).
Generated/<Entity>Service.g.cs   (rewritten every generate)
        │  partial class <Entity>Service : I<Entity>Service

Services/<Entity>Service.cs      (created once, developer-owned partial)
        │  override Task<HookResult> OnBeforeCreateAsync(...) { /* your logic */ }

DI:  I<Entity>Service → <Entity>Service    (merged partial)

Why it works

Adding a field and regenerating rewrites only the .g.cs part; custom hook code survives. The migration engine renames or deletes the custom partial alongside the entity. The rule for bridge authors: split Core (always regenerated) and Custom (overwrite: false) code — put generated logic behind interfaces and scaffold the developer-owned implementation only once, using language-appropriate mechanisms (partial classes in C#, base classes elsewhere).

Edit this page on GitHub