All files / core projection.ts

100% Statements 9/9
100% Branches 5/5
100% Functions 3/3
100% Lines 6/6

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28                            34x 34x 134x   34x 34x 34x              
import { createControllerHost } from './host';
import type { RuntimeController } from './types';
 
/** Internal snapshot projection used by derived controllers without duplicating subscriptions. */
export interface SnapshotProjection<TSnapshot extends object> extends RuntimeController<TSnapshot> {
  refresh(): void;
}
 
/** Creates a lifecycle-safe derived snapshot and optionally owns the source controller. */
export function createSnapshotProjection<TSource extends object, TSnapshot extends object>(
  source: RuntimeController<TSource>,
  project: (snapshot: Readonly<TSource>) => TSnapshot,
  destroySource = true,
): SnapshotProjection<TSnapshot> {
  const host = createControllerHost<TSnapshot, Record<never, never>>(project(source.getSnapshot()));
  const refresh = (): void => {
    if (host.alive()) host.update(project(source.getSnapshot()));
  };
  if (destroySource) host.resources.add(() => source.destroy());
  host.resources.add(source.subscribe(refresh));
  return {
    getSnapshot: host.getSnapshot,
    subscribe: host.subscribe,
    refresh,
    destroy: host.destroy,
  };
}