Skip to content

Generate per-call dispatchers for Dispatchable interfaces - #1

Merged
thomasrepnik merged 17 commits into
masterfrom
dispatcher-generation
Nov 4, 2026
Merged

thomasrepnik merged 17 commits into
masterfrom
dispatcher-generation

Conversation

@thomasrepnik

@thomasrepnik thomasrepnik commented Nov 4, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • New Dispatchable<TContext = void> marker (extends ImplScan, which stays memberless and unchanged for existing users).
  • For every Dispatchable interface the CLI generates a <Interface>Dispatcher class that implements the interface and forwards each member to the applicable implementation (isApplicableTo / highest getPriority()), resolved on every call. The context comes from a generated <INTERFACE>_CONTEXT token typed () => TContext; the plain target takes implementations and context function in the constructor.
  • No per-interface entry in app.config.ts:
    • a class implementing DispatchContextProvider<TContext> next to the interface is found by the scan, and provideImplscan() builds the context token from it;
    • extends Dispatchable without a type argument is context-free: isApplicableTo() takes no parameter, no token is generated, each implementation decides from what it injects;
    • the explicit token provider still works and overrides both (tests, component- or route-scoped contexts).
  • New src/dispatcher.ts module: signature copying, import type resolution through the type checker, unsupported shapes (overloads, optional members, destructured params, accessors, this types, index/call signatures, generic interfaces or bases, non-exported types, import-name collisions, import() types) get a warning while list and token are still generated.
  • Generated files are never scanned, so a dispatcher is never collected as an implementation.
  • Example: PaymentHandler dispatched by PaymentContext through a scanned PaymentContextProvider, context-free ReceiptFormatter (RECEIPT_FORMAT=md), Notifier stays a plain list. README, smoke test and CI updated; npm test added.

Test plan

  • npm test: 40 generator, CLI and runtime dispatcher tests
  • npm run typecheck, npm run build
  • npm start / npm run start:angular through real inject(); the Angular demo provides only its own settings token
  • npm run generate twice is byte-identical
  • npm run test:package against the packed tarball
  • ng build (AOT, Angular CLI 22.2, TypeScript 6.0) in a scratch app: build clean, app renders, dispatcher and context provider resolve through real DI, per-call switching verified in the browser

@thomasrepnik
thomasrepnik merged commit 02e709d into master Nov 4, 2026
3 checks passed
@thomasrepnik
thomasrepnik deleted the dispatcher-generation branch November 4, 2026 21:27
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.

1 participant