From 589a06c4a5f713dd14b9e1e66e23c739a5bc0dc5 Mon Sep 17 00:00:00 2001 From: griest024 Date: Mon, 13 May 2024 23:36:24 -0400 Subject: [PATCH] feat(core): make operation entity adapter extensible (#2795) also don't overwrite incoming `DaffState` --- .../src/operation/entity/adapter.spec.ts | 4 +- .../state/src/operation/entity/adapter.ts | 177 +++++++++++------- 2 files changed, 111 insertions(+), 70 deletions(-) diff --git a/libs/core/state/src/operation/entity/adapter.spec.ts b/libs/core/state/src/operation/entity/adapter.spec.ts index f618257613..67aed52770 100644 --- a/libs/core/state/src/operation/entity/adapter.spec.ts +++ b/libs/core/state/src/operation/entity/adapter.spec.ts @@ -190,8 +190,8 @@ describe('@daffodil/core/state | daffCreateOperationEntityStateAdapter', () => { result = adapter.operationFailed(entity.id, errors, adapter.list(entities, state)); }); - it('should reset the entity state', () => { - expect(result.entities[entity.id].daffState).toEqual(DaffState.Stable); + it('should indicate that the entity is in an error state', () => { + expect(result.entities[entity.id].daffState).toEqual(DaffState.Error); }); it('should should store the errors on the entity', () => { diff --git a/libs/core/state/src/operation/entity/adapter.ts b/libs/core/state/src/operation/entity/adapter.ts index f9f0f0a28a..ceca8d0831 100644 --- a/libs/core/state/src/operation/entity/adapter.ts +++ b/libs/core/state/src/operation/entity/adapter.ts @@ -17,7 +17,7 @@ import { DaffState } from '../../states/public_api'; /** * An entity state adapter that takes care of managing contextual operation and error state for entities. */ -export interface DaffOperationEntityStateAdapter { +export interface DaffOperationEntityStateAdapterInterface { /** * Stores a list of entities in state and resets them all to stable. */ @@ -72,85 +72,126 @@ export interface DaffOperationEntityStateAdapter(selectState: (state: TRootState) => DaffOperationEntityState): DaffOperationEntityStateSelectors; } -export function daffCreateOperationEntityStateAdapter(adapter: EntityAdapter> = createEntityAdapter>()): DaffOperationEntityStateAdapter { - return { - list: (entities, state) => adapter.setAll( +/** + * @inheritdoc + */ +export class DaffOperationEntityStateAdapter implements DaffOperationEntityStateAdapterInterface { + constructor( + protected adapter: EntityAdapter> = createEntityAdapter>(), + ) {} + + list = DaffOperationEntityState>(entities: T[], state: S): S { + return this.adapter.setAll( entities.map>(entity => ({ - ...entity, daffState: DaffState.Stable, + ...entity, daffErrors: [], daffTemp: false, })), state, - ), - preload: (key, state) => - adapter.upsertOne(>{ + ); + } + + preload = DaffOperationEntityState>(id: string, state: S): S { + return this.adapter.upsertOne(>{ // TODO: allow for non identifiable entities? - id: key, - daffState: DaffState.Resolving, + id, + daffState: DaffState.Resolving, + daffErrors: [], + daffTemp: !state.entities[id], + }, state); + } + + load = DaffOperationEntityState>(entity: T, state: S): S { + return this.adapter.upsertOne({ + daffState: DaffState.Stable, + ...entity, + daffErrors: [], + daffTemp: false, + }, state); + } + + preadd = DaffOperationEntityState>(entity: T, state: S, placeholderId?: string): S { + return placeholderId + ? this.adapter.upsertOne({ + ...entity, + // TODO: allow for non identifiable entities? + id: placeholderId, + daffState: DaffState.Adding, daffErrors: [], - daffTemp: !state.entities[key], - }, state), - load: (entity, state) => - adapter.upsertOne({ + daffTemp: true, + }, state) + : state; + } + + add = DaffOperationEntityState>(entity: T, state: S, placeholderId?: string): S { + return this.adapter.upsertOne( + { + daffState: DaffState.Added, ...entity, - daffState: DaffState.Stable, daffErrors: [], daffTemp: false, - }, state), - preadd: (entity, state, placeholderId) => - placeholderId - ? adapter.upsertOne({ - ...entity, - // TODO: allow for non identifiable entities? - id: placeholderId, - daffState: DaffState.Adding, - daffErrors: [], - daffTemp: true, - }, state) - : state, - add: (entity, state, placeholderId) => - adapter.upsertOne({ + }, + placeholderId ? this.adapter.removeOne(placeholderId, state) : state, + ); + } + + preupdate = DaffOperationEntityState>(entity: Partial & DaffIdentifiable, state: S): S { + return this.adapter.upsertOne({ + ...state.entities[entity.id], + daffState: DaffState.Mutating, + daffErrors: [], + }, state); + } + + update = DaffOperationEntityState>(entity: Partial & DaffIdentifiable, state: S): S { + return this.adapter.updateOne({ + id: entity.id, + changes: >>{ + daffState: DaffState.Mutated, ...entity, - daffState: DaffState.Added, daffErrors: [], daffTemp: false, - }, placeholderId ? adapter.removeOne(placeholderId, state) : state), - preupdate: (entity, state) => - adapter.upsertOne({ - ...state.entities[entity.id], - daffState: DaffState.Mutating, - daffErrors: [], - }, state), - update: (entity, state) => - adapter.updateOne({ - id: entity.id, - changes: >>{ - ...entity, - daffState: DaffState.Mutated, - daffErrors: [], - daffTemp: false, - }, - }, state), - preremove: (key, state) => - adapter.upsertOne({ - ...state.entities[key], - daffErrors: [], - daffState: DaffState.Deleting, - }, state), - remove: adapter.removeOne, - operationFailed: (key, errors, state) => - adapter.upsertOne({ - ...state.entities[key], - daffState: DaffState.Stable, - daffErrors: errors, - }, state), - resetState: (key, state) => - adapter.upsertOne({ - ...state.entities[key], - daffState: DaffState.Stable, - }, state), - getInitialState: adapter.getInitialState, - getSelectors: (selectState) => daffOperationEntityStateSelectorFactory(adapter.getSelectors(selectState)), - }; + }, + }, state); + } + + preremove = DaffOperationEntityState>(key: string, state: S): S { + return this.adapter.upsertOne({ + ...state.entities[key], + daffErrors: [], + daffState: DaffState.Deleting, + }, state); + } + + remove = DaffOperationEntityState>(key: string, state: S): S { + return this.adapter.removeOne(key, state); + } + + operationFailed = DaffOperationEntityState>(key: string, errors: DaffStateError[], state: S): S { + return this.adapter.upsertOne({ + ...state.entities[key], + daffState: DaffState.Error, + daffErrors: errors, + }, state); + } + + resetState = DaffOperationEntityState>(key: string, state: S): S { + return this.adapter.upsertOne({ + ...state.entities[key], + daffState: DaffState.Stable, + }, state); + } + + getInitialState = DaffOperationEntityState>(state?: S): S { + return this.adapter.getInitialState(state); + } + + getSelectors(selectState: (state: TRootState) => DaffOperationEntityState): DaffOperationEntityStateSelectors { + return daffOperationEntityStateSelectorFactory(this.adapter.getSelectors(selectState)); + } +} + +export function daffCreateOperationEntityStateAdapter(adapter: EntityAdapter> = createEntityAdapter>()): DaffOperationEntityStateAdapter { + return new DaffOperationEntityStateAdapter(adapter); }