Appearance
Carrot.Data.Scaffold.Compilers
net
Core compilation pipeline framework for Carrot's scaffold code generation system. Defines the module/renderer/sink/action abstractions and the orchestrator that drives the build pipeline.
Installation
xml
<ProjectReference Include="..\Carrot.Data.Scaffold.Compilers\Carrot.Data.Scaffold.Compilers.csproj" />Architecture
Pipeline Flow
ScaffoldCompiler.Build() executes a deterministic pipeline:
- StartBuild - fire actions
- BeforeModules - fire actions
- For each module:
- Write sink metadata (module-level)
- For each renderer in the module:
renderer.Render()producesIScaffoldCompilerRendererOutputitems- Write sink metadata (renderer-level, with output counts)
- Bundle outputs into the manifest
- AfterModules - fire actions (bundle is now complete)
- For each sink:
sink.Write(bundle)- sinks receive the full bundle of outputs
- Flush - analyse each manifest directory, detect orphaned files, and delete them
- EndBuild - fire actions
Key Abstractions
- Module (
IScaffoldCompilerModule<TGraphRoot>) - owns a graph root (the data model) and a list of renderers. Modules configure their renderers inConfigureRenderers(). - Renderer (
IScaffoldCompilerRenderer<TGraphRoot, TData>) - transforms graph data into file outputs (IScaffoldCompilerRendererOutput). Output types cover C#, TypeScript, JSON, raw text, Disclose markup, and StringBuilder. - Sink (
IScaffoldCompilerSink) - writes the bundled outputs somewhere (filesystem, log, etc.). Sinks implementingIScaffoldCompilerSinkMetaalso receive per-module/per-renderer metadata callbacks during the module loop. - Action (
IScaffoldCompilerAction) - cross-cutting logic attached to specificScaffoldCompilerPipelineEventpoints. Actions receive aScaffoldCompilerActionContextwith the current module, renderer, sink, bundle, etc. - Manifest (
ScaffoldCompilerManifest) - collects all generated files, groups them by directory, and after flush can report new/rewritten/orphaned files viaScaffoldCompilerManifestDirectory.Analyse().
Orphan Detection
During flush, each ScaffoldCompilerManifestDirectory compares existing files on disk with the bundle. Files present on disk but not in the bundle are orphaned and deleted (excluding .csproj, packages.lock.json, readme.md).
Scoped Graph Types
ScaffoldGraphEntityScoped, ScaffoldGraphEnumScoped, and ScaffoldGraphTraitScoped pair a graph element with its owning ScaffoldDatabaseGraphContext, enabling renderers to generate context-aware output.
Dependencies
| Dependency | Kind |
|---|---|
Carrot.Data.Scaffold | project (scaffold data model, graph) |
Carrot.IO | project (file path abstractions) |
Carrot.Text.Code.CSharp | project (C# code builder) |
Carrot.Text.Code.Typescript | project (TypeScript code builder) |
Carrot.Text.Markup.Json | project (JSON document builder) |
Build
bash
dotnet buildUsing Carrot.Data.Scaffold.Compilers
Core compilation pipeline framework - wire up modules, renderers, sinks, and actions to generate code from scaffold data.
Getting Started
csharp
using Carrot.Data.Scaffold.Compilers;
using Carrot.Data.Scaffold.Domain;
scaffold.Compiler(compiler =>
{
compiler
.AddModule<MyGraphRoot, MyModule>()
.SinkTo<MyFileSystemSink>()
.Build();
});Common Patterns
1. Define a module with renderers
csharp
public class MyModule : ScaffoldCompilerModule<ScaffoldDatabaseGraph>
{
public override string Name => "MyModule";
public override ScaffoldDatabaseGraph GraphRoot => this.Scaffold.ScaffoldDatabase.Graph;
protected override void ConfigureRenderers()
{
this.AddRenderer<MyEntityRenderer, ScaffoldGraphEntityScoped>(
new ScaffoldGraphEntityScoped(context, entity));
}
}2. Define a renderer
csharp
public class MyEntityRenderer : ScaffoldCompilerRenderer<ScaffoldDatabaseGraph, ScaffoldGraphEntityScoped>
{
public override string Name => "EntityRenderer";
public override IEnumerable<IScaffoldCompilerRendererOutput> Render()
{
CSharpFile file = new("MyEntity.cs");
// ... build file content from this.Data ...
yield return new ScaffoldCompilerRendererOutputCSharp(file, "src/Domain/Entities");
}
}3. Use renderer options
csharp
public class MyRendererOptions : IScaffoldCompilerRendererOptions
{
public bool IncludeComments { get; set; } = true;
}
public class MyRenderer : ScaffoldCompilerRenderer<MyGraph, MyData, MyRendererOptions>
{
public override string Name => "Renderer";
public override IEnumerable<IScaffoldCompilerRendererOutput> Render()
{
if (this.Options.IncludeComments) { /* ... */ }
// ...
}
}4. Register a pipeline action
csharp
compiler.AddAction<MyAction, MyActionOptions>(
ScaffoldCompilerPipelineEvent.AfterModules,
options =>
{
options.Enabled = true;
});5. Register a sink with options
csharp
compiler.SinkTo<MySink, MySinkOptions>(options =>
{
options.Enabled = true;
options.DryRun = false;
});6. Module with options
csharp
compiler.AddModule<MyGraph, MyModule, MyModuleOptions>(options =>
{
options.SomeFlag = true;
});7. Output types
csharp
// C#
yield return new ScaffoldCompilerRendererOutputCSharp(csharpFile, "src/Domain");
// TypeScript
yield return new ScaffoldCompilerRendererOutputTypescript(tsFile, "src/client");
// JSON
yield return new ScaffoldCompilerRendererOutputJson(jsonDoc, "config");
// Raw content
yield return new ScaffoldCompilerRendererOutputRaw(content, "schema", "graphql", "src/api");
// StringBuilder
yield return new ScaffoldCompilerRendererOutputStringBuilder(sb, "output", "txt", "docs");Tips / Gotchas
- Actions are sync-over-async -
Handle()wrapsHandleAsync()viaTask.Run().GetAwaiter().GetResult(). Long-running actions should implementHandleAsyncproperly. - Orphan detection ignores
.csproj,packages.lock.json, andreadme.md- these files are never deleted during flush even if they are not in the bundle. - Sinks must opt in - all sinks have
IScaffoldCompilerSinkOptions.Enabled. IfEnabledis false,IfEnabled()short-circuits andWrite/WriteMetaare never called. - Module ordering matters - modules execute in registration order, so renderers that depend on files from a previous module should be added after it.
- Manifest directories are rooted at git root -
ScaffoldCompilerManifestBundleItemresolves paths relative toFileSystem.ExecutingAssemblyDirectoryGitRoot.
Package Contents
Carrot.Data.Scaffold.Compilers.Modules.Api
Package: Carrot.Data.Scaffold.Compilers.Modules.Api
Compiler
ScaffoldCompilerApi - scaffold compiler module for the "Api" target; iterates the ScaffoldApi graph and registers renderers for each api, controller, enum, type, command, and model
ScaffoldCompilerApiOptions - options type (currently empty, reserved for future configuration)
Renderers
ScaffoldCompilerApiRendererReadme - generates the root-level readme for the entire API collection (controllers, models, commands, enums, types)
ScaffoldCompilerApiRendererApi - generates the static Api class and rate-limit installation code per API
ScaffoldCompilerApiRendererApiReadme - generates per-API readme files documenting controllers, models, commands, enums, types
ScaffoldCompilerApiRendererController - generates abstract controller base classes with action methods, authorization, search/sort/pagination support, logging, error handling, and security headers
ScaffoldCompilerApiRendererEnum - generates C# enum types from scaffold enum definitions
ScaffoldCompilerApiRendererType - generates C# type classes with constructors, property validation (Ensure* methods), and JSON serialization attributes
ScaffoldCompilerApiRendererCommand - generates C# record types for single-shape command payloads
ScaffoldCompilerApiRendererModel - generates CQRS model records (All, Get, Reference, Create, Update, Upsert, Patch) with primary key resolution, JSON:API resource IDs, and relationship filtering
ScaffoldCompilerApiRendererModelAdapters - generates read/write adapter interfaces and base classes for entity-to-API and API-to-entity CQRS mapping
Extensions
ScaffoldCompilerApiExtensions - IScaffoldCompiler.AddModuleApi() and AddModuleApi(options) extension methods
ScaffoldApiGraphApiExtensions - type resolution helpers: GetTypeName · ResolveActionRequestNameRaw · ResolveActionResponseActionName · ResolveActionResponseImplementationName · ResolveActionResponseNameRaw · ResolveTypeName
CqrsRoleFlagsCSharpExtensions - RenderCSharpExpression() for rendering CqrsRoleFlags as C# code
Exceptions
ScaffoldCompilerApiExceptionTypeNotSupported - thrown when a scaffold type cannot be resolved
ScaffoldCompilerApiExceptionTypeNotSupported<T> - generic variant for strongly-typed context
Carrot.Data.Scaffold.Compilers.Modules.ApiSchemas
Package: Carrot.Data.Scaffold.Compilers.Modules.ApiSchemas
Compiler
ScaffoldCompilerApiSchemas - scaffold compiler module for the "Api Schemas" target; iterates ScaffoldApi graph APIs and registers a Postman collection renderer per API
ScaffoldCompilerApiSchemasOptions - options type (currently empty, reserved for future configuration)
Renderers
ScaffoldCompilerApiSchemasRendererApi - generates a Postman Collection JSON file per API, containing folders per controller with request items for each action, including HTTP verb, URL, headers, and request body property definitions
Extensions
ScaffoldCompilerApiSchemaExtensions - IScaffoldCompiler.AddModuleApiSchemas() and AddModuleApiSchemas(options) extension methods
Carrot.Data.Scaffold.Compilers.Modules.Domain
Package: Carrot.Data.Scaffold.Compilers.Modules.Domain
Compiler
ScaffoldCompilerDomain - scaffold compiler module for the "Domain" target; uses a composite ScaffoldDomain graph root combining both ScaffoldApi and ScaffoldDatabase graphs
ScaffoldCompilerDomainOptions - options type (currently empty, reserved for future configuration)
Graph Root
ScaffoldDomain - composite graph root with Api (ScaffoldApi) and Database (ScaffoldDatabase) properties
Renderers
ScaffoldCompilerDomainRendererReadme - generates the root-level domain readme for the collection
ScaffoldCompilerDomainRendererApiReadme - generates per-API domain readme files
Extensions
ScaffoldCompilerDomainExtensions - IScaffoldCompiler.AddModuleDomain() and AddModuleApi(options) extension methods
Carrot.Data.Scaffold.Compilers.Modules.EntityFramework
Package: Carrot.Data.Scaffold.Compilers.Modules.EntityFramework
Compiler
ScaffoldCompilerEntityFramework - scaffold compiler module for the "EntityFramework" target; iterates the ScaffoldDatabase graph and registers renderers for contexts, entities, repositories, queries, traits, and enums
ScaffoldCompilerEntityFrameworkOptions - options type (currently empty, reserved for future configuration)
Renderers - DbContext
ScaffoldCompilerEntityFrameworkRendererDbContext - generates the DbContext class and its I{ContextName} interface with database/context name properties, entity name/type arrays, and a comparer factory
ScaffoldCompilerEntityFrameworkRendererDbContextDbSets - generates DbSet<T> property declarations
ScaffoldCompilerEntityFrameworkRendererDbContextModelBuilder - generates OnModelCreating with entity configurations, navigations, indexes, and primary keys
ScaffoldCompilerEntityFrameworkRendererDbContextOnConfiguring - generates OnConfiguring overrides
ScaffoldCompilerEntityFrameworkRendererDbContextRegister - generates DI service registration code
ScaffoldCompilerEntityFrameworkRendererDbContextConventions - generates EF model conventions
ScaffoldCompilerEntityFrameworkRendererDbContextConversions - generates EF value conversions for custom types
ScaffoldCompilerEntityFrameworkRendererDbContextReadme - generates per-context readme documentation
Renderers - Entities
ScaffoldCompilerEntityFrameworkRendererEntity - generates entity classes and interfaces with properties, modelling contracts, trait interfaces, and compound key types
ScaffoldCompilerEntityFrameworkRendererRepository - generates repository classes and interfaces with key services, CRUD lifecycle hooks (PrepareForInsert/Update/Delete), and support for CarrotId, compound, and custom key types
ScaffoldCompilerEntityFrameworkRendererQueries - generates query extension classes with Include/ThenInclude methods for navigations, With/For filter methods for foreign keys, and navigation shortcut properties
Renderers - Other
ScaffoldCompilerEntityFrameworkRendererTrait - generates trait interfaces with properties extending ITrait
ScaffoldCompilerEntityFrameworkRendererEnum - generates C# enum types from database enum definitions
ScaffoldCompilerEntityFrameworkRendererInstallation - generates DI installation/registration code per context
ScaffoldCompilerEntityFrameworkRendererReadme - generates the root-level readme
Extensions - EF Naming
ScaffoldGraphEntityExtensions - GetEfName() · GetEfVariable() for entity naming
ScaffoldGraphEntityPropertyExtensions - RenderEf() for property configuration (required, max length, value comparers) · GetTypeNameForContext() for context-aware type resolution
ScaffoldGraphPropertyExtensions - ShouldRender() filter for scalar, enum, and conversion-backed properties
ScaffoldGraphNavigationExtensions - RenderEf() for navigation configuration (HasOne/HasMany, WithOne/WithMany, HasForeignKey, HasConstraintName) · link table support
ScaffoldGraphNavigationShortcutExtensions - RenderEf() for navigation shortcuts (currently a placeholder)
ScaffoldGraphPrimaryKeyExtensions - RenderEf() for primary key and value generation configuration · GetMethodParameters() · RenderProperties()
ScaffoldGraphIndexExtensions - RenderEf() for index configuration (database name, method, operators, unique, clustered) · RenderProperties() · RenderOperators()
ScaffoldGraphTableSchemaExtensions - RenderEfTableSchema() for ToTable() with table name and schema
Extensions - Registration
ScaffoldCompilerEntityFrameworkExtensions - IScaffoldCompiler.AddModuleEntityFramework() and AddModuleEntityFramework(options) extension methods
Carrot.Data.Scaffold.Compilers.Modules.NetClient
Package: Carrot.Data.Scaffold.Compilers.Modules.NetClient
Status
This package is currently an empty placeholder. No public types have been implemented yet.
The project references Carrot.Data.Scaffold.Compilers and contains an empty Data/Scaffold/Graph/ folder, indicating the intended architecture will follow the same scaffold compiler module pattern as the other modules.
Carrot.Data.Scaffold.Compilers.Modules.TypescriptClient
Package: Carrot.Data.Scaffold.Compilers.Modules.TypescriptClient
Compiler
ScaffoldCompilerTypescriptClient - scaffold compiler module for the "TypescriptClient" target; creates directory structures and registers renderers for package root files, source index, endpoints, enums, types, models, and commands per API
ScaffoldCompilerTypescriptClientOptions - options type (currently empty, reserved for future configuration)
Renderers
ScaffoldCompilerTypescriptClientRendererRoot - generates package root files (package.json, tsconfig, etc.) for the generated npm package
ScaffoldCompilerTypescriptClientRendererSrc - generates the src/ directory structure and barrel exports
ScaffoldCompilerTypescriptClientRendererSrcIndex - generates src/index.ts barrel export file
ScaffoldCompilerTypescriptClientRendererSrcEndpoint - generates TypeScript endpoint classes per controller with typed methods for each action
ScaffoldCompilerTypescriptClientRendererSrcEnum - generates TypeScript enum types
ScaffoldCompilerTypescriptClientRendererSrcType - generates TypeScript type/class definitions
ScaffoldCompilerTypescriptClientRendererSrcModel - generates TypeScript model interfaces with CQRS role variants and serializers
ScaffoldCompilerTypescriptClientRendererSrcModel~Serializer - generates model serializer/deserializer functions
ScaffoldCompilerTypescriptClientRendererSrcCommand - generates TypeScript command types
Scoped Types
ScaffoldApiScoped - scoped context carrying FilePath root and ScaffoldApiGraphApi
ScaffoldApiControllerScoped - scoped context for controller rendering (root path, API, controller)
ScaffoldApiEnumScoped - scoped context for enum rendering
ScaffoldApiTypeScoped - scoped context for type rendering
ScaffoldApiModelScoped - scoped context for model rendering
ScaffoldApiCommandScoped - scoped context for command rendering
Graph Extensions
ScaffoldApiGraphApi (in Graph folder) - API graph extensions for TypeScript client generation
Type Extensions
TypescriptTypeExtensions - CLR-to-TypeScript type mapping helpers
Extensions
ScaffoldCompilerTypescriptClientExtensions - IScaffoldCompiler.AddModuleTypescriptClient() and AddModuleTypescriptClient(options) extension methods
Carrot.Data.Scaffold.Compilers.Modules.VueJsLibrary
Package: Carrot.Data.Scaffold.Compilers.Modules.VueJsLibrary
Compiler
ScaffoldCompilerVueJsLibrary - scaffold compiler module for the "VueJsLibrary" target; calculates an ActionMap linking models to Get/Reference controller actions, then registers renderers for package root, source files, and per-model stores
ScaffoldCompilerVueJsLibraryOptions - options type (currently empty, reserved for future configuration)
Renderers
ScaffoldCompilerVueJsLibraryRendererRoot - generates package root files (package.json, tsconfig, etc.)
ScaffoldCompilerVueJsLibraryRendererSrc - generates the src/ directory structure
ScaffoldCompilerVueJsLibraryRendererSrcIndex - generates src/index.ts barrel export
ScaffoldCompilerVueJsLibraryRendererSrcInstall - generates installation/registration entry point
ScaffoldCompilerVueJsLibraryRendererSrcProvide - generates Vue provide/inject setup
ScaffoldCompilerVueJsLibraryRendererSrcUse - generates Vue plugin use composable
ScaffoldCompilerVueJsLibraryRendererSrcStore - generates per-model ApiTypeStore classes with controller action bindings, identity resolvers, reference resolvers, and primary key resolution
ScaffoldCompilerVueJsLibraryRendererSrcStore~ActionBinding - generates action binding methods connecting store actions to API client endpoint calls
ScaffoldCompilerVueJsLibraryRendererSrcStore~Create - generates store factory/creation functions
ScaffoldCompilerVueJsLibraryRendererSrcStore~Install - generates per-store installation code
ScaffoldCompilerVueJsLibraryRendererSrcStore~Use - generates per-store use{Model}Store composable
Scoped Types
ScaffoldApiScoped - scoped context carrying FilePath root, ScaffoldApiGraphApi, and ActionMap
ScaffoldApiModelScoped - scoped context for model store rendering (root path, API, model, actions, controllers)
ScaffoldApiModelIdentityBinding - binding between a model identity and its parameter mappings
ScaffoldApiModelIdentityParameterBinding - maps an identity property name to a controller action parameter
ActionMap - Dictionary<ScaffoldApiGraphModel, IReadOnlyList<ScaffoldApiGraphControllerAction>> mapping models to their Get/Reference actions
Exceptions
ScaffoldApiGraphControllerActionIdentityAmbiguousMatchException - thrown when multiple controller actions ambiguously match a model identity
ScaffoldApiGraphControllerActionIdentityMatchNotFoundException - thrown when no controller action matches a model identity
ScaffoldApiGraphControllerActionMultipleIdentityMatchException - thrown when multiple identities match a single action
Type Extensions
TypescriptTypeExtensions - CLR-to-TypeScript type mapping helpers
Extensions
ScaffoldCompilerVueJsLibraryExtensions - IScaffoldCompiler.AddModuleVueJsLibrary() and AddModuleVueJsLibrary(options) extension methods
Carrot.Data.Scaffold.Compilers.Sinks.FileSystem
Package: Carrot.Data.Scaffold.Compilers.Sinks.FileSystem
Sink
ScaffoldCompilerSinkFileSystem - writes generated code files to disk; creates directories as needed, resolves paths from git root
ScaffoldCompilerSinkFileSystemOptions - options: Enabled (default true) · DryRun (default false)
Extensions
ScaffoldCompilerSinkFileSystemExtensions - IScaffoldCompiler.SinkToFileSystem() · IScaffoldCompiler.SinkToFileSystem(options)
Carrot.Data.Scaffold.Compilers.Sinks.Logging
Package: Carrot.Data.Scaffold.Compilers.Sinks.Logging
Sink
ScaffoldCompilerSinkLog - logging sink with metadata support; reports module execution, renderer completion with file counts, and optionally dumps full file content
ScaffoldCompilerSinkLogOptions - options: Enabled (default true) · ReportFileCreation (default false) · ReportFinalFiles (default false) · ReportZeroFiles (default true)
Extensions
ScaffoldCompilerSinkLogExtensions - IScaffoldCompiler.SinkToLog() · IScaffoldCompiler.SinkToLog(options)
Carrot.Data.Scaffold.Compilers.Actions.EnsureProjects
Package: Carrot.Data.Scaffold.Compilers.Actions.EnsureProjects
Action
ScaffoldCompilerActionEnsureProjects - pipeline action that ensures .NET project structure matches the scaffold graph: creates missing projects, sets root namespaces, adds to solution, manages references
ScaffoldCompilerActionEnsureProjectsOptions - options: Enabled · DryRun · UpdateSolution · FlushFiles · FlushReferences · LogStructure · CommonRoot
Structure
ProjectBuilder - orchestrates project creation, namespace setting, solution management, and reference wiring using a dependency graph
ProjectNode - represents a single project: ProjectName · ProjectFolder · SolutionFolder · Axis · Tier · Ownership · DependsOnProjects · AdditionalReferences · RootNamespace
ProjectNodePaths - resolved paths: Root · ProjectFolderRelative · ProjectFolderAbsolute · ProjectFileRelative · ProjectFileAbsolute
ProjectNodeExtensions - filtering: ByAxis · ByOwnership · ByTier
Enums
ProjectAxis - Domain · Abstraction · Database · Api · Contract · Application · Hosting
ProjectOwnership - Architect · Generated · Implementer — who owns the file contents; drives the build pass (Architect = wire only, Generated = create + wire, Implementer = excluded)
ProjectTier - Base · Collection · Context
Planning
ProjectPlanner - builds the full project graph from scaffold data across all axes: BuildDomain · BuildAbstractions · BuildApi · BuildDatabase · BuildContracts · BuildApplicationApi · BuildApplicationDatabase · BuildApplicationOperations · BuildApplication · BuildHosting
CLI Integration
DotNet - wraps dotnet CLI and Visual Studio tooling: CreateProjectFromTemplateAsync · AddProjectToSolutionAsync · SetProjectRootNamespace · AddReferenceAsync · AddReferencesAsync · RemoveReferencesAsync · GetProjectReferencesAsync · SolutionContainsProjectAsync
Extensions
ScaffoldCompilerActionEnsureProjectsExtensions - IScaffoldCompiler.AddActionEnsureProjects() · IScaffoldCompiler.AddActionEnsureProjects(options)