93 lines
4.8 KiB
TypeScript
93 lines
4.8 KiB
TypeScript
import type { UncheckedIndexedAccess } from '../uncheckedindexed';
|
|
import type { Draft } from 'immer';
|
|
import type { PayloadAction } from '../createAction';
|
|
import type { GetSelectorsOptions } from './state_selectors';
|
|
import type { CastAny, Id as Compute } from '../tsHelpers';
|
|
/**
|
|
* @public
|
|
*/
|
|
export type EntityId = number | string;
|
|
/**
|
|
* @public
|
|
*/
|
|
export type Comparer<T> = (a: T, b: T) => number;
|
|
/**
|
|
* @public
|
|
*/
|
|
export type IdSelector<T, Id extends EntityId> = (model: T) => Id;
|
|
/**
|
|
* @public
|
|
*/
|
|
export type Update<T, Id extends EntityId> = {
|
|
id: Id;
|
|
changes: Partial<T>;
|
|
};
|
|
/**
|
|
* @public
|
|
*/
|
|
export interface EntityState<T, Id extends EntityId> {
|
|
ids: Id[];
|
|
entities: Record<Id, T>;
|
|
}
|
|
/**
|
|
* @public
|
|
*/
|
|
export interface EntityAdapterOptions<T, Id extends EntityId> {
|
|
selectId?: IdSelector<T, Id>;
|
|
sortComparer?: false | Comparer<T>;
|
|
}
|
|
export type PreventAny<S, T, Id extends EntityId> = CastAny<S, EntityState<T, Id>>;
|
|
export type DraftableEntityState<T, Id extends EntityId> = EntityState<T, Id> | Draft<EntityState<T, Id>>;
|
|
/**
|
|
* @public
|
|
*/
|
|
export interface EntityStateAdapter<T, Id extends EntityId> {
|
|
addOne<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, entity: T): S;
|
|
addOne<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, action: PayloadAction<T>): S;
|
|
addMany<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, entities: readonly T[] | Record<Id, T>): S;
|
|
addMany<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, entities: PayloadAction<readonly T[] | Record<Id, T>>): S;
|
|
setOne<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, entity: T): S;
|
|
setOne<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, action: PayloadAction<T>): S;
|
|
setMany<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, entities: readonly T[] | Record<Id, T>): S;
|
|
setMany<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, entities: PayloadAction<readonly T[] | Record<Id, T>>): S;
|
|
setAll<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, entities: readonly T[] | Record<Id, T>): S;
|
|
setAll<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, entities: PayloadAction<readonly T[] | Record<Id, T>>): S;
|
|
removeOne<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, key: Id): S;
|
|
removeOne<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, key: PayloadAction<Id>): S;
|
|
removeMany<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, keys: readonly Id[]): S;
|
|
removeMany<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, keys: PayloadAction<readonly Id[]>): S;
|
|
removeAll<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>): S;
|
|
updateOne<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, update: Update<T, Id>): S;
|
|
updateOne<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, update: PayloadAction<Update<T, Id>>): S;
|
|
updateMany<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, updates: ReadonlyArray<Update<T, Id>>): S;
|
|
updateMany<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, updates: PayloadAction<ReadonlyArray<Update<T, Id>>>): S;
|
|
upsertOne<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, entity: T): S;
|
|
upsertOne<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, entity: PayloadAction<T>): S;
|
|
upsertMany<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, entities: readonly T[] | Record<Id, T>): S;
|
|
upsertMany<S extends DraftableEntityState<T, Id>>(state: PreventAny<S, T, Id>, entities: PayloadAction<readonly T[] | Record<Id, T>>): S;
|
|
}
|
|
/**
|
|
* @public
|
|
*/
|
|
export interface EntitySelectors<T, V, Id extends EntityId> {
|
|
selectIds: (state: V) => Id[];
|
|
selectEntities: (state: V) => Record<Id, T>;
|
|
selectAll: (state: V) => T[];
|
|
selectTotal: (state: V) => number;
|
|
selectById: (state: V, id: Id) => Compute<UncheckedIndexedAccess<T>>;
|
|
}
|
|
/**
|
|
* @public
|
|
*/
|
|
export interface EntityStateFactory<T, Id extends EntityId> {
|
|
getInitialState(state?: undefined, entities?: Record<Id, T> | readonly T[]): EntityState<T, Id>;
|
|
getInitialState<S extends object>(state: S, entities?: Record<Id, T> | readonly T[]): EntityState<T, Id> & S;
|
|
}
|
|
/**
|
|
* @public
|
|
*/
|
|
export interface EntityAdapter<T, Id extends EntityId> extends EntityStateAdapter<T, Id>, EntityStateFactory<T, Id>, Required<EntityAdapterOptions<T, Id>> {
|
|
getSelectors(selectState?: undefined, options?: GetSelectorsOptions): EntitySelectors<T, EntityState<T, Id>, Id>;
|
|
getSelectors<V>(selectState: (state: V) => EntityState<T, Id>, options?: GetSelectorsOptions): EntitySelectors<T, V, Id>;
|
|
}
|