# `loaders` — per-request DataLoader scope _(no submodules)_ ## Purpose `loaders` defines the per-request DataLoader scope the engine creates around every incoming GraphQL operation. Two concurrent requests receive distinct loader instances; the cache never leaks across request boundaries even though both requests draw from the same set of loader factories registered on the abstract `GraphqlRegistry`. The module is deliberately the thinnest possible wrapper around the `LoaderFactory.create()` surface owned by `@suaveplan/api-types/graphql`. The engine calls `createRequestLoaderScope()` once per request; resolvers that need a loader call `scope.get(name, factory)`; the engine disposes the scope at request end. ## Features - One scope per request — distinct cache per request guaranteed. - Loader lazily instantiated on first `get(name, factory)` call; subsequent calls reuse the instance. - `dispose()` blocks subsequent `get()` calls so a buggy late resolver cannot resurrect a freed cache. - Zero runtime dependencies — pure JS, fits in ~40 lines. ## Usage: Basic ```ts import { createRequestLoaderScope } from "@suaveplan/api-graphql-apollo/loaders"; const scope = createRequestLoaderScope(); const userLoader = scope.get("users", userLoaderFactory); const user = await userLoader.load("u_42"); scope.dispose(); ``` ## Usage: Advanced Wire the scope into a resolver context object so resolvers consume loaders by name through the request context: ```ts import { createRequestLoaderScope } from "@suaveplan/api-graphql-apollo/loaders"; function makeContext(): RequestContext { const scope = createRequestLoaderScope(); return { loaders: { users: () => scope.get("users", userLoaderFactory), orders: () => scope.get("orders", orderLoaderFactory), }, finalize: () => scope.dispose(), } as unknown as RequestContext; } ``` ## API Reference - `RequestLoaderScope`: - `get(name, factory): { load }` - `dispose(): void` - `size(): number` - `createRequestLoaderScope(): RequestLoaderScope`. ## Implementation Notes The scope is a closure over a `Map` plus a `disposed` boolean. Throwing on `get` after `dispose` surfaces the late-resolver bug at the call site instead of silently producing inconsistent reads. The size accessor is provided so OTel histograms can record loader-fanout per request.