Skip to content

Commit

Permalink
Merge pull request #3669 from Olesj-Bilous/feature/EntityAdapter-Draf…
Browse files Browse the repository at this point in the history
…tableEntityState
  • Loading branch information
markerikson committed Oct 1, 2023
2 parents 39930eb + c8e899d commit b1c2381
Show file tree
Hide file tree
Showing 7 changed files with 435 additions and 375 deletions.
361 changes: 182 additions & 179 deletions packages/toolkit/src/entities/models.ts
@@ -1,179 +1,182 @@
import type { UncheckedIndexedAccess } from '../uncheckedindexed'
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 EntityDefinition<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>
>

/**
* @public
*/
export interface EntityStateAdapter<T, Id extends EntityId> {
addOne<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
entity: T
): S
addOne<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
action: PayloadAction<T>
): S

addMany<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
entities: readonly T[] | Record<Id, T>
): S
addMany<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
entities: PayloadAction<readonly T[] | Record<Id, T>>
): S

setOne<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
entity: T
): S
setOne<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
action: PayloadAction<T>
): S
setMany<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
entities: readonly T[] | Record<Id, T>
): S
setMany<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
entities: PayloadAction<readonly T[] | Record<Id, T>>
): S
setAll<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
entities: readonly T[] | Record<Id, T>
): S
setAll<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
entities: PayloadAction<readonly T[] | Record<Id, T>>
): S

removeOne<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
key: Id
): S
removeOne<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
key: PayloadAction<Id>
): S

removeMany<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
keys: readonly Id[]
): S
removeMany<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
keys: PayloadAction<readonly Id[]>
): S

removeAll<S extends EntityState<T, Id>>(state: PreventAny<S, T, Id>): S

updateOne<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
update: Update<T, Id>
): S
updateOne<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
update: PayloadAction<Update<T, Id>>
): S

updateMany<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
updates: ReadonlyArray<Update<T, Id>>
): S
updateMany<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
updates: PayloadAction<ReadonlyArray<Update<T, Id>>>
): S

upsertOne<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
entity: T
): S
upsertOne<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
entity: PayloadAction<T>
): S

upsertMany<S extends EntityState<T, Id>>(
state: PreventAny<S, T, Id>,
entities: readonly T[] | Record<Id, T>
): S
upsertMany<S extends EntityState<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 EntityAdapter<T, Id extends EntityId>
extends EntityStateAdapter<T, Id> {
selectId: IdSelector<T, Id>
sortComparer: false | Comparer<T>
getInitialState(): EntityState<T, Id>
getInitialState<S extends object>(state: S): EntityState<T, Id> & S
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>
}
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 EntityDefinition<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 EntityAdapter<T, Id extends EntityId>
extends EntityStateAdapter<T, Id> {
selectId: IdSelector<T, Id>
sortComparer: false | Comparer<T>
getInitialState(): EntityState<T, Id>
getInitialState<S extends object>(state: S): EntityState<T, Id> & S
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>
}

0 comments on commit b1c2381

Please sign in to comment.