UNPKG

@furystack/repository

Version:

Repository implementation for FuryStack

65 lines 2.56 kB
import { defineService } from '@furystack/inject'; import { DataSet } from './data-set.js'; /** * Resolves a {@link StoreToken} to a {@link PhysicalStore} whose * `TWritableData` generic matches the owning data set. `StoreToken` defaults * `TWritableData` to `WithOptionalId`, while a {@link DataSet} may narrow it * (e.g. to strip system-owned fields). The write surface of `PhysicalStore` * is contravariant in `TWritableData` — a store that accepts * `WithOptionalId<T, TPK>` also accepts any narrower shape — but TypeScript * cannot express that with the default generic, so the cast is localized * here with this explanation rather than scattered at call sites. */ const resolvePhysicalStore = (ctx, store) => ctx.inject(store); /** * Defines a singleton {@link DataSet} token backed by a {@link StoreToken}. * The token mirrors the store's `model` and `primaryKey` so reflection * tools (entity sync, OpenAPI generators, test harnesses) can discover the * dataset's shape from the token alone. Disposal of the owning injector * tears down the dataset's event subscriptions. * * @example * ```ts * const UserStore = defineStore({ * name: 'my-app/UserStore', * model: User, * primaryKey: 'username', * factory: () => new InMemoryStore({ model: User, primaryKey: 'username' }), * }) * * export const UserDataSet = defineDataSet({ * name: 'my-app/UserDataSet', * store: UserStore, * settings: { * authorizeAdd: async ({ injector, entity }) => ({ isAllowed: true }), * }, * }) * * const ds = injector.get(UserDataSet) * await ds.add(injector, { username: 'alice', roles: [] }) * ``` */ export const defineDataSet = (options) => { const token = defineService({ name: options.name, lifetime: 'singleton', factory: (ctx) => { const physicalStore = resolvePhysicalStore(ctx, options.store); const dataSet = new DataSet({ ...options.settings, physicalStore, }); // Disposal is delegated to the injector via `onDispose`; the dataset // outlives this factory invocation and is torn down on scope teardown. // eslint-disable-next-line furystack/prefer-using-wrapper ctx.onDispose(() => dataSet[Symbol.dispose]()); return dataSet; }, }); const result = Object.assign(token, { model: options.store.model, primaryKey: options.store.primaryKey, }); return result; }; //# sourceMappingURL=define-data-set.js.map