Skip to content

Add module options pattern with IModuleOptions interface - #23

Merged
antosubash merged 5 commits into
mainfrom
claude/improve-module-extendability-SFKKL
Mar 28, 2026
Merged

antosubash merged 5 commits into
mainfrom
claude/improve-module-extendability-SFKKL

Conversation

@antosubash

@antosubash antosubash commented Mar 28, 2026 •

Copy link
Copy Markdown
Owner

Summary

Implements a configurable module options pattern that allows host applications to override module behavior at startup. Modules define options classes implementing IModuleOptions, which are auto-discovered by the source generator and exposed as typed Configure{Module}() extension methods on SimpleModuleOptions.

Key Changes

  • New IModuleOptions marker interface (SimpleModule.Core) — Base interface for module options classes
  • Module options discovery — Enhanced SymbolDiscovery to scan module and contracts assemblies for IModuleOptions implementations
  • ModuleOptionsEmitter — New code generator that:
    • Generates typed Configure{Module}() extension methods on SimpleModuleOptions
    • Generates RegisterModuleOptionsDefaults() to register IOptions<T> for all discovered options
  • SimpleModuleOptions enhancements — Added ConfigureModule() and ApplyModuleOptions() methods to support the configuration pipeline
  • Diagnostic SM0044 — Warns when a module has multiple IModuleOptions implementations (at most one per module)
  • Module options classes — Added to all existing modules:
    • ProductsModuleOptions (DefaultPageSize, MaxPageSize)
    • OrdersModuleOptions (DefaultPageSize, MaxPageSize)
    • UsersModuleOptions (password and lockout policies)
    • AuditLogsModuleOptions (batch size, flush interval, retention)
    • AdminModuleOptions (UsersPageSize)
    • FileStorageModuleOptions (MaxFileSizeMb, AllowedExtensions)
    • PageBuilderModuleOptions (MaxTitleLength, MaxSlugLength)
    • SettingsModuleOptions (CacheDuration)
  • ApplyUsersModuleOptions — Post-configuration hook that bridges UsersModuleOptions into ASP.NET Identity's IdentityOptions
  • Module integration — Updated modules to inject and use IOptions<T> instead of hardcoded values
  • Comprehensive tests — Added ModuleOptionsEmitterTests (generator behavior) and ModuleOptionsTests (runtime resolution and overrides)
  • Documentation — Updated CONSTITUTION.md with module options rules and usage examples

Implementation Details

  • Options classes may live in either the module assembly or its Contracts assembly
  • The source generator deduplicates by assembly when discovering options (each module assembly yields one options class)
  • Host applications configure options via fluent API: builder.AddSimpleModule(o => o.ConfigureProducts(p => p.MaxPageSize = 50))
  • Module code reads configured values via standard IOptions<T> dependency injection
  • All options have sensible defaults defined in their property initializers

Modules can now expose configurable options via the IModuleOptions marker
interface. The source generator auto-discovers these classes and generates
typed Configure{Module}() extension methods on SimpleModuleOptions, enabling
host apps to customize module behavior without modifying module code.

- Add IModuleOptions marker interface to SimpleModule.Core
- Generator discovers IModuleOptions in module and contracts assemblies
- Generate ConfigureProducts() (etc.) extension methods per module
- Register IOptions<T> defaults and apply user overrides at startup
- Add SM0044 (multiple options per module) and SM0045 (orphan options) diagnostics
- Add ProductsModuleOptions as reference implementation
- Wire IOptions<ProductsModuleOptions> into Products BrowseEndpoint
Auto-generated types.ts files updated by source generator during build.
Add IModuleOptions implementations for 8 modules with meaningful,
production-relevant configurable values:

- AuditLogs: batch size, flush interval, retention days, check interval
- Admin: users page size
- FileStorage: max file size (MB), allowed extensions
- Orders: default/max page size
- PageBuilder: max title/slug lengths
- Users: password policy (min length, digit/case requirements), lockout
- Settings: cache duration for settings and public menu
- Products: default/max page size (from prior commit)

Wire options into module code replacing hardcoded constants:
- AuditWriterService reads batch size and flush interval from options
- AuditRetentionService reads retention days and check interval
- Admin UsersEndpoint reads page size from options
- Users module bridges UsersModuleOptions into Identity options
- SettingsService and PublicMenuService read cache duration from options

Add comprehensive tests:
- 7 generator tests: discovery, extension method generation, defaults
  registration, multi-module, empty case, SM0044 diagnostic, hosting wiring
- 9 integration tests: verify all module options resolve with correct
  defaults via IOptions<T> from the real DI container
- 1 override test: verify all 8 module options can be overridden via
  services.Configure<T>() (simulating host app customization)
Address code review findings:

- Extract FindConcreteClassesImplementing() shared namespace walker to
  eliminate duplication between FindModuleOptionsClasses and similar
  recursive discovery methods
- Extract ModuleOptionsRecord.GroupByModule() to deduplicate identical
  dictionary-building logic in DiagnosticEmitter and ModuleOptionsEmitter
- Remove ModuleOptionsInfo mutable class — build ModuleOptionsRecord
  directly during discovery (no mutable accumulation needed)
- Remove unreachable SM0045 diagnostic — discovery only scans known
  module assemblies, so orphan options classes cannot occur
- Use ScanModuleAssemblies helper for module options discovery to get
  assembly-level deduplication (consistent with interceptor discovery)
- Align IModuleOptions pragma comment style with IModulePermissions
@antosubash
antosubash force-pushed the claude/improve-module-extendability-SFKKL branch from 9c82566 to 14acb60 Compare March 28, 2026 19:25
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying simplemodule-website with  Cloudflare Pages  Cloudflare Pages

Latest commit: e17fd59
Status: ✅  Deploy successful!
Preview URL: https://f9266e44.simplemodule-website.pages.dev
Branch Preview URL: https://claude-improve-module-extend.simplemodule-website.pages.dev

View logs

@antosubash
antosubash merged commit f0accad into main Mar 28, 2026
3 checks passed
@antosubash
antosubash deleted the claude/improve-module-extendability-SFKKL branch April 1, 2026 15:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants