Skip to content
mycl is in early development. The API may change before a stable release; it is not yet recommended for production use.

Registries & Layers

A registry is an immutable collection of capability bindings. registry() makes an empty one; .layer() and .augment() each return a new registry with the binding added: the original is never touched. You build registries up, then hand them to scope() or mycl().

.layer(capability, value) binds a single capability: one layer. Because every call returns a fresh registry, chaining .layer(...).layer(...) simply threads each new registry into the next call. Nothing mutates, so you can branch off a shared base and the branches stay independent.

A registry has two read-only methods for introspection, useful in tests, tooling, and debugging:

  • .has(capability) returns whether the registry binds that capability.
  • .bindings() returns a ReadonlyMap of every binding, keyed by capability.

Registries compose: pass several to mycl() or scope() and they fold into one resolved registry, the form a scope dispatches against. When two registries bind the same capability, the later one wins; augments accumulate across all of them. Don’t confuse composition with .layer(): .layer() adds one binding to one registry, while composition combines whole registries. (The primitive underneath, merge, lives on @mycl/core/factory for kernel authors; the everyday surface composes for you.)

Immutability makes a registry the natural test seam. Keep the code under test exactly as it ships and bind a test registry that swaps its I/O capabilities for in-memory stand-ins. No mock library, no module patching: the capability surface is the seam.

The example passes only because both swaps took: if the test registry missed sendEmail, the real default would throw. That is the seam doing its job.

  • Factories: bundle registries once and build instances with mycl().
  • Layer strategies: make multiple bindings for one capability combine instead of overwrite.
  • Scopes: how a resolved registry becomes active at call time.