Sign in

    moonbitstack/moonapi/di does not have a README file

    Container

    pub(all) struct Container[V] {
    providers : Map[String, Provider[V]]
    overrides : Map[String, Provider[V]]
    }

    The provider registry: key -> Provider, plus a separate overrides map that shadows it. Overrides are FastAPI's app.dependency_overrides — a test swaps a real dependency (a live DB session) for a fake without touching the routes. A registered override always wins over the base provider.

    Container::clear_override

    fn[V] Container::clear_override(self : Container[V], key : String) -> Unit

    Drop the override for key (no-op if none), restoring the base provider.

    Container::clear_overrides

    fn[V] Container::clear_overrides(self : Container[V]) -> Unit

    Drop every override — the usual test teardown that returns the container to its production wiring.

    Container::erase

    fn[V] Container::erase(self : Container[V]) -> Deps

    This container with its value type erased, ready for App::depends. The providers, the per-request cache, the sub-dependency resolution and the LIFO teardown are all the container's own; erasure hides only the value.

    Container::new

    fn[V] Container::new() -> Container[V]

    An empty container.

    Container::open_scope

    fn[V] Container::open_scope(self : Container[V]) -> Scope[V]

    Open a fresh request scope over this container.

    Container::override_

    fn[V] Container::override_(self : Container[V], key : String, factory : () -> V, teardown? : (V, Error?) -> Unit) -> Container[V]

    Register a dependency override for key — FastAPI's app.dependency_overrides[dep] = fake. Takes precedence over the base provider until cleared.

    Container::provide

    fn[V] Container::provide(self : Container[V], key : String, factory : () -> V, teardown? : (V, Error?) -> Unit) -> Container[V]

    Register a base provider under key (last registration wins), returning the container so registrations can chain.

    Container::provide_using

    fn[V] Container::provide_using(self : Container[V], key : String, factory : (Scope[V]) -> V, teardown? : (V, Error?) -> Unit) -> Container[V]

    Register a base provider whose factory resolves sub-dependencies through the request scope it is handed (FastAPI's nested Depends). Otherwise like provide.

    Container::run

    Run handler inside a fresh request scope, then tear the scope down — the setup/teardown pair wrapped around a handler, exactly as a FastAPI yield dependency brackets the request. The handler resolves whatever it needs through the scope; every dependency built during the call is released (LIFO) once it returns, then the response is handed back.

    A handler that raises is released the same way, and the error reaches the teardowns before it is re-raised for the app's exception handlers to map: cleanup that only ran on the happy path would leak exactly when it matters.

    Deps

    pub struct Deps {
    open : () -> DepsScope
    }

    A container with its dependency value type erased (Container::erase builds one), so a non-generic App can hold one. Resolving through it runs a provider's factory and records its teardown exactly as Scope::get does; what it cannot do is hand the value back — which is precisely what a route-level dependency does not need, since FastAPI's dependencies=[...] discards the values it builds and keeps only their effects.

    DepsScope

    pub struct DepsScope {
    resolve : (String) -> Bool
    close : (Error?) -> Unit
    }

    One request's resolution scope over an erased container: resolve a key (false when nothing provides it), then close, handing any failure to the teardowns.

    Provider

    pub(all) struct Provider[V] {
    factory : (Scope[V]) -> V
    teardown : (V, Error?) -> Unit
    }

    A provider: a keyed factory that builds a request-scoped dependency value, with an optional teardown run after the handler (FastAPI's yield dependencies, whose post-yield body is cleanup). The factory runs at most once per request scope; the teardown receives the produced value and the error that ended the request, None when it succeeded — the exception a FastAPI yield dependency sees when it wraps its yield in a try. The factory is handed the Scope so it can resolve sub-dependencies through it — FastAPI's Depends(a) where a itself declares Depends(b).

    Provider::new

    fn[V] Provider::new(factory : () -> V, teardown? : (V, Error?) -> Unit) -> Provider[V]

    Build a leaf provider whose factory needs nothing else. teardown defaults to a no-op — the common "plain value, nothing to release" case.

    Provider::scoped

    fn[V] Provider::scoped(factory : (Scope[V]) -> V, teardown? : (V, Error?) -> Unit) -> Provider[V]

    Build a provider whose factory resolves other dependencies through the request Scope it is handed — the sub-dependency case (FastAPI's nested Depends).

    Scope

    pub struct Scope[V] {
    container : Container[V]
    cache : Map[String, V]
    building : Map[String, Bool]
    teardowns : Array[(Error?) -> Unit]
    }

    A request-scoped resolution scope. Each dependency is built at most once and its value cached for the life of the scope (FastAPI's per-request dependency cache), and each built value's teardown is recorded to run — in reverse registration order (LIFO) — when the scope closes. Open one per request, resolve dependencies through it, then close it (or use Container::run).

    Scope::close

    fn[V] Scope::close(self : Scope[V], failure? : Error) -> Unit

    Run every recorded teardown in LIFO order and clear them, so a closed scope is inert. Mirrors FastAPI unwinding yield dependencies in reverse — the last opened is torn down first. failure is the error that ended the request and is handed to every teardown, so cleanup can tell a failed request from a successful one and roll back rather than commit.

    Scope::get

    fn[V] Scope::get(self : Scope[V], key : String) -> V?

    Resolve key within this scope: return the already-built instance if the dependency was resolved earlier in the same request; otherwise run its factory once, cache the value, register its teardown, and return it. None when no provider (or override) is registered for key.

    Source Files