Files
vercel__eve/packages/eve/src/client/eve-agent-projection.ts
T
2026-09-18 09:38:26 -07:00

52 lines
1.5 KiB
TypeScript

import type { EveAgentReducer, EveAgentReducerEvent } from "#client/reducer.js";
/** Owns reducer replay when optimistic events are replaced by server events. */
export class EveAgentProjection<TData> {
readonly #reducer: EveAgentReducer<TData>;
#events: readonly EveAgentReducerEvent[];
#data: TData;
constructor(reducer: EveAgentReducer<TData>, events: readonly EveAgentReducerEvent[]) {
this.#reducer = reducer;
this.#events = events;
this.#data = this.#reduce();
}
get data(): TData {
return this.#data;
}
reset(): void {
this.#events = [];
this.#data = this.#reducer.initial();
}
append(event: EveAgentReducerEvent): void {
this.#events = [...this.#events, event];
this.#data = this.#reducer.reduce(this.#data, event);
}
remove(predicate: (event: EveAgentReducerEvent) => boolean): void {
this.#events = this.#events.filter((event) => !predicate(event));
this.#data = this.#reduce();
}
replace(
predicate: (event: EveAgentReducerEvent) => boolean,
replacement: EveAgentReducerEvent,
): void {
const index = this.#events.findIndex(predicate);
this.#events =
index === -1
? [...this.#events, replacement]
: this.#events.map((event, i) => (i === index ? replacement : event));
this.#data = this.#reduce();
}
#reduce(): TData {
let data = this.#reducer.initial();
for (const event of this.#events) data = this.#reducer.reduce(data, event);
return data;
}
}