Scoped dependencies
Scoped dependencies cache one value for each context key. Compdi provides an accessor form and a contextual proxy form.
| Form | Context selection | Best fit |
|---|---|---|
defineScoped | Passed explicitly to the accessor | Request handlers and code where ownership should be visible. |
createScoped | Read from a context() callback | Framework integrations with an existing ambient context. |
Keyed accessor
defineScoped returns a callable accessor. Supply the context key when resolving a value:
const useRequestService = defineScoped<RequestService, Request>({
target: RequestService,
deps: [database],
onRelease: service => service.close(),
});
const service = useRequestService(request);
useRequestService.has(request); // true
useRequestService.peek(request); // existing value, without creating one
await useRequestService.release(request);
The lifecycle methods never create a value:
has(context)reports whether an entry exists.peek(context)returns an existing entry orundefined.release(context)removes the entry and runsonRelease, when configured.
Contextual proxy
createScoped returns a stable proxy and a controller. The proxy asks context() for the active key when one of its properties is used:
const [database, databaseScope] = createScoped({
factory: request => createRequestDatabase(request),
context: useRequest,
onRelease: instance => instance.close(),
});
database.query("SELECT 1");
await databaseScope.release(request);
Use the proxy form when an ambient context is already available. Use the accessor form when passing the context explicitly makes ownership clearer.
createScoped proxies objects. For primitive scoped values, use defineScoped.Release each finished context. Otherwise its cached value remains reachable for the lifetime of the module.