| 1 | import type { Draft } from 'immer'
|
|---|
| 2 | import { current, isDraft } from '../immerImports'
|
|---|
| 3 | import type {
|
|---|
| 4 | DraftableEntityState,
|
|---|
| 5 | EntityId,
|
|---|
| 6 | IdSelector,
|
|---|
| 7 | Update,
|
|---|
| 8 | } from './models'
|
|---|
| 9 |
|
|---|
| 10 | export function selectIdValue<T, Id extends EntityId>(
|
|---|
| 11 | entity: T,
|
|---|
| 12 | selectId: IdSelector<T, Id>,
|
|---|
| 13 | ) {
|
|---|
| 14 | const key = selectId(entity)
|
|---|
| 15 |
|
|---|
| 16 | if (process.env.NODE_ENV !== 'production' && key === undefined) {
|
|---|
| 17 | console.warn(
|
|---|
| 18 | 'The entity passed to the `selectId` implementation returned undefined.',
|
|---|
| 19 | 'You should probably provide your own `selectId` implementation.',
|
|---|
| 20 | 'The entity that was passed:',
|
|---|
| 21 | entity,
|
|---|
| 22 | 'The `selectId` implementation:',
|
|---|
| 23 | selectId.toString(),
|
|---|
| 24 | )
|
|---|
| 25 | }
|
|---|
| 26 |
|
|---|
| 27 | return key
|
|---|
| 28 | }
|
|---|
| 29 |
|
|---|
| 30 | export function ensureEntitiesArray<T, Id extends EntityId>(
|
|---|
| 31 | entities: readonly T[] | Record<Id, T>,
|
|---|
| 32 | ): readonly T[] {
|
|---|
| 33 | if (!Array.isArray(entities)) {
|
|---|
| 34 | entities = Object.values(entities)
|
|---|
| 35 | }
|
|---|
| 36 |
|
|---|
| 37 | return entities
|
|---|
| 38 | }
|
|---|
| 39 |
|
|---|
| 40 | export function getCurrent<T>(value: T | Draft<T>): T {
|
|---|
| 41 | return (isDraft(value) ? current(value) : value) as T
|
|---|
| 42 | }
|
|---|
| 43 |
|
|---|
| 44 | export function splitAddedUpdatedEntities<T, Id extends EntityId>(
|
|---|
| 45 | newEntities: readonly T[] | Record<Id, T>,
|
|---|
| 46 | selectId: IdSelector<T, Id>,
|
|---|
| 47 | state: DraftableEntityState<T, Id>,
|
|---|
| 48 | ): [T[], Update<T, Id>[], Id[]] {
|
|---|
| 49 | newEntities = ensureEntitiesArray(newEntities)
|
|---|
| 50 |
|
|---|
| 51 | const existingIdsArray = getCurrent(state.ids)
|
|---|
| 52 | const existingIds = new Set<Id>(existingIdsArray)
|
|---|
| 53 |
|
|---|
| 54 | const added: T[] = []
|
|---|
| 55 | const addedIds = new Set<Id>([])
|
|---|
| 56 | const updated: Update<T, Id>[] = []
|
|---|
| 57 |
|
|---|
| 58 | for (const entity of newEntities) {
|
|---|
| 59 | const id = selectIdValue(entity, selectId)
|
|---|
| 60 | if (existingIds.has(id) || addedIds.has(id)) {
|
|---|
| 61 | updated.push({ id, changes: entity })
|
|---|
| 62 | } else {
|
|---|
| 63 | addedIds.add(id)
|
|---|
| 64 | added.push(entity)
|
|---|
| 65 | }
|
|---|
| 66 | }
|
|---|
| 67 | return [added, updated, existingIdsArray]
|
|---|
| 68 | }
|
|---|