Files
2026-05-27 23:29:53 +01:00

2.1 KiB

loaders.ts

(no submodules)

Purpose

Defines the per-request loader bag the Yoga engine constructs at pipeline step 7 and disposes at step 11. Two concurrent requests therefore see independent DataLoader instances — caching that R1 establishes for a key cannot leak to R2 even when both resolvers call rctx.loaders.customer.load(id) for the same id within the same event loop tick.

The bag is the binding between the abstract LoaderFactory contract (owned by @suaveplan/api-graphql) and the concrete request-scoped loader handles resolvers see. Disposal is a hook for future async-resource loaders; today's in-memory factories make it a no-op.

Features

  • Constructs one loader handle per registered factory.
  • Idempotent dispose() so the engine can safely call it on both the happy path and the error path.
  • Returned handles map is frozen-by-convention — engine code never mutates after construction.

Usage: Basic

import { createGraphqlRegistry } from "@suaveplan/api-graphql";
import { buildRequestLoaders } from "@suaveplan/api-graphql-yoga";

const reg = createGraphqlRegistry();
reg.addLoader("customer", async (keys) => keys.map((k) => `customer:${String(k)}`));

const snap = (reg as unknown as { freeze: () => { loaders: ReadonlyMap<string, never> } }).freeze();
const bag = buildRequestLoaders(snap.loaders);
const customer = await bag.handles.customer.load("c1");
bag.dispose();

Usage: Advanced

import { buildRequestLoaders } from "@suaveplan/api-graphql-yoga";

function makeRctx(loaders: Awaited<ReturnType<typeof buildRequestLoaders>>) {
    return {
        loaders: loaders.handles,
        dispose: () => loaders.dispose(),
    };
}

API Reference

  • RequestLoaderBag — { handles, dispose() }.
  • buildRequestLoaders(factories) — constructs the bag.

Implementation Notes

The disposed boolean lets the engine call dispose() on both happy and error paths without worrying about double-free. When async-resource loaders land, the close branch will flip from no-op to a real close sequence; the public shape stays unchanged.