boardgame-core/src/utils/entity.ts

47 lines
1.3 KiB
TypeScript

import {Signal, signal, SignalOptions} from "@preact/signals-core";
import {create} from 'mutative';
export class Entity<T> extends Signal<T> {
public constructor(public readonly id: string, t?: T, options?: SignalOptions<T>) {
super(t, options);
}
produce(fn: (draft: T) => void) {
this.value = create(this.value, fn);
}
}
export function entity<T = undefined>(id: string, t?: T, options?: SignalOptions<T>) {
return new Entity<T>(id, t, options);
}
export type EntityCollection<T> = {
collection: Signal<Record<string, Entity<T>>>;
remove(...ids: string[]): void;
add(...entities: (T & {id: string})[]): void;
get(id: string): Entity<T>;
}
export function createEntityCollection<T>(): EntityCollection<T> {
const collection = signal({} as Record<string, Entity<T>>);
const remove = (...ids: string[]) => {
collection.value = Object.fromEntries(
Object.entries(collection.value).filter(([id]) => !ids.includes(id)),
);
};
const add = (...entities: (T & {id: string})[]) => {
collection.value = {
...collection.value,
...Object.fromEntries(entities.map((e) => [e.id, entity(e.id, e)])),
};
};
const get = (id: string) => collection.value[id];
return {
collection,
remove,
add,
get
}
}