-
Notifications
You must be signed in to change notification settings - Fork 2
Entity
This is the main class that you will use to manipulate and store entity's instances. It has next members:
actionCreators: EntityActionCreators<T>
- this is all redux action creators that entity uses. It will help you in cases when you need to perform actions manually and explicit. In 99.99% cases you won't need it.
- Get methods
- Dispatch methods
- Mixed methods (Get + Dispatch methods combinations)
getLoadingState$(): Observable<LoadingState | undefined>
It returns observable that will listen to the full entity loading state. LoadingState for entity is changed for every action that runs remote action.
getLoadingStateById$(
id: Id,
isAsap?: boolean,
): Observable<LoadingState | undefined>;
It returns observable that will listen to the entity by id loading state. LoadingState by id is changed for related to the id actions that runs remote action. isAsap
flag will set scheduler for this observable to asapScheduler.
getLoadingStateByIds$(
ids: Id[],
isAsap?: boolean,
): Observable<LoadingState | undefined>;
It returns observable that will listen to the entity by ids loading state. isAsap
flag will set scheduler for this observable to asapScheduler.
It will combine loading states by ids into LoadingState follow the next rule:
-
if any LoadingState.isLoading -> result LoadingState.isLoading will be true
-
if any LoadingState.error -> result LoadingState.error will be the first error
More explicit algorithm here
getPage$(
config: unknown,
isAsap?: boolean,
): Observable<Page | undefined>;
It returns observable that will listen to Entity page stored under key equal hash of config. isAsap
flag will set scheduler for this observable to asapScheduler.
getPageLoadingState$(
config: unknown,
isAsap?: boolean,
): Observable<LoadingState | undefined>;
It returns observable that will listen to Entity page loading state stored under key equal hash of config. isAsap
flag will set scheduler for this observable to asapScheduler.
getAll$(): Observable<T[] | undefined>;
It returns observable that will listen to all entity's instances.
getPages$(): Observable<Page[]>;
It returns observable that will listen to all entity pages stored by any config's hashes.
add(
data: T,
config?: unknown,
options?: EntityAddOptions,
): EntityActions;
This method will dispatch an action that will store data
object as entity instance. If config
passed, it will assotiate this instance with config's hash page. It also accepts options
:
data: T
- [required] this item preprocessed by Entity.schema.id
function if it exists will be stored under config
's hash.
config: unknown
- [optional] [default: undefined] this config (even if it equals undefined) will be hashed by Entity.schema.hashFn
and this hash will be used as page key where will be stored data
.
options: EntityAddOptions
- [optional]:
-
pasteIndex: number
- [optional] [default: undefined] the index where new instance will be stored. By default it will be stored at last -
merge: boolean
- [optional] [default: true] whether to merge entity isntance if there is instance with the same id. Merge is perfromed by merge util.
addWithId(
data: T,
tempId: string,
config?: unknown,
options?: EntityAddOptions,
): EntityActions;
The same as add
but you can use tempId for create an entity instance (or update existing) via apply patch (read more in optimistic change section).
addList(
data: T[],
config?: unknown,
isReplace?: boolean,
hasMore?: boolean,
options?: EntityAddListOptions,
): EntityActions;
This method the same as add
but it works with an array of entity's instances.
data: T[]
- [required] this items preprocessed by Entity.schema.id
function if it exists will be stored under config
's hash.
config: unknown
- [optional] [default: undefined] this config (even if it equals undefined) will be hashed by Entity.schema.hashFn
and this hash will be used as page key where will be stored data
.
isReplace: boolean
- [optional] [default: false] whether to replace instances previouslyloaded and stored under config
's hash.
hasMore: boolean
- [optional] [default: false] whether to set hasMore flag and do not load entities using get$ with the same config
.
options: EntityAddListOptions
- [optional]:
-
pasteIndex: number
- [optional] [default: undefined] an index from where new instance will be stored. By default it will be stored from the last -
merge: boolean
- [optional] [default: true] whether to merge entity isntances if there is instances with the same id. Merge is perfromed by merge util.
change(
id: Id,
patch: PatchRequest<T>,
options?: ChangeOptions,
): EntityActions;
This method will dispatch an action that will change entity's instance by id
using patch
.
id: Id
- [required] an id of changing entity's instance.
patch: PatchRequest<T>
- [required] a patch to apply. It can be either deep partial object of T
, or a function that will accept previous value from store and return a deep partial object of T.
options: ChangeOptions
- [optional]:
-
merge: boolean
- [optional] [default: true] whether to merge patch with exist entity or to replace it with patch. Merge is perfromed by merge util. -
ifNotExist: boolean
- [optional] [default: false] to create an entity if no entity with givenid
exists
changeList(
patches: IdPatchRequest<T>[],
options?: ChangeOptions,
): EntityActions;
This method the same as change
but it works with an array of patches.
patches: IdPatchRequest<T>[]
- [required] this is array of object with id and patch from change
method description.
options: ChangeOptions
- [optional]:
-
merge: boolean
- [optional] [default: true] whether to merge patch with exist entity or to replace it with the patch. Merge is performed by merge util. -
ifNotExist: boolean
- [optional] [default: false] to create an entity if no entity with givenid
exists
remove(
id: Id,
options?: EntityRemoveOptions,
): EntityActions;
This method will dispatch an action that will be remove entity's instance with given id
.
options: EntityRemoveOptions
- [optional]
-
safe: boolean
- [optional] [default: false] whether to permamenty remove entity's instance. Iftrue
is passed, it will just mark entity's instance asremoved
and it won't be visible by select observables (listened above) until it will be restored by restoreRemoved.
restoreRemoved(
id: Id,
): EntityActions;
This method will dispatch an action that will be restore entity's instance with given id
that was marked as removed
using either removeRemote$ or removeListRemote$ or remove or removeList methods with options.safe = true
.
removeList(
ids: Id[],
options?: EntityRemoveListOptions,
): EntityActions;
This method will dispatch an action that will be remove entities' instances with given ids
.
options: EntityRemoveListOptions
- [optional]
-
safe: boolean
- [optional] [default: false] whether to permamenty remove entity's instance. Iftrue
is passed, it will just mark entity's instance asremoved
and it won't be visible by select observables (listened above) until it will be restored by restoreRemovedList.
restoreRemovedList(
ids: Id[],
): EntityActions;
This method will dispatch an action that will be restore entities' instances with given ids
that was marked as removed
using either removeRemote$ or removeListRemote$ or remove or removeList methods with options.safe = true
.
setLoadingState(
state: LoadingState,
config?: unknown,
options?: EntitySetLoadingStateOptions,
): EntityActions;
This will dispatch an action and store new loading state
.
state: LoadingState
- [required] loading state to store
config: unknown
- [optional] config that will be hashed and used to set loading state for related page
options: EntitySetLoadingStateOptions
- [optional] - no options is now available
clear(config: unknown): EntityActions;
This will dispatch an action that will be clear page's instances
config: unknown
- [required] the config that will be hashed and used to clear the related page.
clearAll(): EntityActions;
This will dispatch an action that will be clear all pages with theirs instances.
setLoadingStateById(
id: Id,
state: LoadingState,
options?: EntitySetLoadingStateOptions,
): EntityActions;
This will dispatch an action and store new loading state
for the id
.
id: Id
- [required] the id to state
associated with.
state: LoadingState
- [required] loading state to store
options: EntitySetLoadingStateOptions
- [optional] - no options is now available
setLoadingStateByIds(
ids: Id[],
state: LoadingState,
options?: EntitySetLoadingStateOptions,
): EntityActions;
This will dispatch an action and store the same loading state
for each id in ids
.
ids: Id[]
- [required] the ids to state
associated with.
state: LoadingState
- [required] loading state to store
options: EntitySetLoadingStateOptions
- [optional] - no options is now available
setLoadingStateForKey(
id: Id,
key: string,
state: LoadingState,
options?: EntitySetLoadingStateOptions,
): EntityActions;
This will dispatch an action and store new loading state
for the id
for the key
.
id: Id
- [required] the id to state
associated with.
key: string
- [required] the key to state
associated with.
state: LoadingState
- [required] loading state to store
options: EntitySetLoadingStateOptions
- [optional] - no options is now available
setLoadingStateBus(
state: LoadingState,
id?: Id,
config?: unknown,
key?: string,
): EntityActions;
This will call either setLoadingStateById or setLoadingStateByIds or setLoadingStateForKey based on arguments
batch(
actions: EntityActions[],
): EntityActions;
This method allows you to dispatch several actions manually and explicit.
affectLoadingState(
config?: unknown,
key?: string,
rethrow?: boolean,
): AffectLoadingStateFactory;
It returns AffectLoadingStateFactory
for page loading state based on config
and key
. More detailed here.
affectLoadingStateById(
id?: Id,
key?: string,
rethrow?: boolean,
): AffectLoadingStateFactory;
It returns AffectLoadingStateFactory
for entity's instance loading state based on id
and key
. More detailed here.
affectLoadingStateByConfigOrId(
config?: unknown,
id?: Id,
key?: string,
rethrow?: boolean,
): AffectLoadingStateFactory;
It returns AffectLoadingStateFactory
and uses setLoadingStateBus under hood to determine loading state setter.
loadList$(
config: unknown,
dataSource: Observable<ResponseArray<T>> | Response$Factory<T>,
options?: EntityLoadListOptions,
paginatorSubj?: BehaviorSubject<boolean>,
): Observable<PaginatedResponse<T>>;
This method will subscribe to dataSource
and store the result using addList method. It will also affect loading state using setLoadingStateBus. This method returns cold observable.
config: unknown
- [required] the config that will be hashed and used as key for getting related page and check its hasMore
param to decide wheter to run dataSource
. It also set loading state for this page. It also store result to this page.
dataSource: Observable<ResponseArray<T>> | Response$Factory<T>
- [required] the main source of data. It can be either Observable with entity's instances or a factory to be used with paginatorSubj
options?: EntityLoadListOptions
- [optional]
-
pasteIndex: number
- [optional] [default: undefined] the index where new instances will be stored. By default it will be stored at last
-
merge: boolean
- [optional] [default: true] whether to merge entity isntance if there is instance with the same id. Merge is perfromed by merge util. -
single: boolean
- [optional] [default: false] if passedtrue
it will never subscribe todataSource
if underconfig
's hash page there are entity instances already -
rethrow: boolean
- [optional] [default: false] whether to rethrowdataSource
Observable
error. Caution iftrue
is passed it will be tear downSubscription
in case of error -
pageSize: number
- [optional] [default: Entity.schema.pageSize] the page size that will be used indataSource
if it is factory
paginatorSubj: BehaviorSubject<boolean>
- [optional] [default: new BehaviorSubject(false)
] pagination subject that allows you to either request next page, or refresh (clear all and request first page).
loadById$(
id: Id,
dataSource$: Observable<T>,
options?: EntityLoadOptions,
): Observable<T>;
This method will subscribe to dataSource
and store the result using add method. It will also affect loading state using setLoadingStateBus. This method returns cold observable.
id: Id
- [required] an id of entity instance to store by
dataSource: Observable<T>
- [required] the main source of data.
options?: EntityLoadOptions
- [optional]
-
rethrow: boolean
- [optional] [default: false] whether to rethrowdataSource
Observable
error. Caution iftrue
is passed it will be tear downSubscription
in case of error
get$(
config: unknown,
dataSource?: Observable<ResponseArray<T>> | Response$Factory<T>,
options?: EntityGetListOptions,
paginatorSubj?: BehaviorSubject<boolean>,
): Observable<T[] | undefined>;
This method is the most complex method of the library. It follows next steps:
- It reserves place in store and places with key equals
config
's hash using Entity.schema.hashFn - It creates selector for reserved place in store
- It immediately return an
Observable
that listen to reserved place using selector. It means you will get:- undefined in case of new
config
's hash - previously stored array of entities associated with given
config
- updated array of entities, which will be resolving from next steps (TL;DR: entities will be resolved from
dataSource
)
- undefined in case of new
- It sets loadingState (will be described later) to
{ isLoading: true, error: null }
- It subscribes to given
dataSource
- When given
dataSource
emits value,Entity
will store this result at reserved place. - It sets loadingState to
{ isLoading: false, error: null }
- In case of error from given
dataSource
Entity
will set loadingState to{ isLoading: false, error: <error from dataSource.error> }
- It will emit updated array
- From this point, returned
Observable
will emit actual entity array if it is changed from other places even if some entity is changed by its id using change
The algorithm you can always see in Redux DevTools panel. Also the method is the most used method.
config: unknown
- [required] the config that will be hashed and used as key for getting related page and check its hasMore
param to decide wheter to run dataSource
. It also set loading state for this page. It also store result to this page.
dataSource: Observable<ResponseArray<T>> | Response$Factory<T>
- [required] the main source of data. It can be either Observable
with entity's instances or a factory to be used with paginatorSubj
options?: EntityGetListOptions
- [optional]
-
pasteIndex: number
- [optional] [default: undefined] the index where new instances will be stored. By default it will be stored at last
-
merge: boolean
- [optional] [default: true] whether to merge entity isntance if there is instance with the same id. Merge is perfromed by merge util. -
single: boolean
- [optional] [default: false] if passedtrue
it will never subscribe todataSource
if underconfig
's hash page there are entity instances already -
rethrow: boolean
- [optional] [default: false] whether to rethrowdataSource
Observable
error. Caution iftrue
is passed it will be tear downSubscription
in case of error -
pageSize: number
- [optional] [default: Entity.schema.pageSize] the page size that will be used indataSource
if it is factory
paginatorSubj: BehaviorSubject<boolean>
- [optional] [default: new BehaviorSubject(false)
] pagination subject that allows you to either request next page, or refresh (clear all and request first page).
getDictionary$(
config: unknown,
dataSource?: Observable<ResponseArray<T>> | Response$Factory<T>,
options?: EntityGetListOptions,
paginatorSubj?: BehaviorSubject<boolean>,
): Observable<Dictionary<T>>;
This method is the same as get$ but it returns a dictionary of page instances (9 point in get$ algorithm).
getById$(
id: Id,
dataSource$?: Observable<T>,
options?: EntityGetOptions,
): Observable<T | undefined>;
This method is the same as get$ but it works with only one entity instance by id
addRemote$(
entity: T,
config: unknown,
dataSource$: Observable<T>,
options?: EntityAddOptions,
): Observable<T>;
This method will subscribe to dataSource$
and store the result using add method. It will also affect loading state using setLoadingStateBus. This method returns cold observable.
entity: T
- [required] an instance to store if options.optimistic
equals true
. In basic cases you have to pass undefined
and the instance will be recieved from dataSource$
config: unknown
- [optional] [default: undefined] this config (even if it equals undefined) will be hashed by Entity.schema.hashFn
and this hash will be used as page key where will be stored entity's instance.
dataSource$: Observable<T>
- [required] the main source of entity's instance.
options?: EntityAddOptions
- [optional]
-
pasteIndex: number
- [optional] [default: undefined] the index where new instances will be stored. By default it will be stored at last
-
merge: boolean
- [optional] [default: true] whether to merge entity isntance if there is instance with the same id. Merge is perfromed by merge util. -
single: boolean
- [optional] [default: false] if passedtrue
it will never subscribe todataSource
if underconfig
's hash page there are entity instances already -
rethrow: boolean
- [optional] [default: false] whether to rethrowdataSource
Observable
error. Caution iftrue
is passed it will be tear downSubscription
in case of error -
optimistic: boolean
- [optional] [default: false] whether to use optimistic strategy. More detailed here
changeRemote$(
id: Id,
patch: PatchRequest<T>,
dataSource$: Observable<DeepPartial<T> | undefined>,
options?: ChangeOptions,
): Observable<DeepPartial<T> | undefined>;
This method will subscribe to dataSource$
and apply patch using change method. It will also affect loading state using setLoadingStateBus. This method returns cold observable.
patch: PatchRequest<T>
- [required] the patch to apply. It can be either deep partial object of T
, or a function that will accept previous value from store and return a deep partial object of T.
This patch will be used if options.optimistic
equals true
. In basic cases you have to pass undefined
and the patch will be recieved from dataSource$
dataSource$: Observable<T>
- [required] the source of patch.
options: ChangeOptions
- [optional]:
-
merge: boolean
- [optional] [default: true] whether to merge patch with exist entity or to replace it with patch. whether to merge entity isntances if there is instances with the same id. Merge is perfromed by merge util. -
ifNotExist: boolean
- [optional] [default: false] to create an entity if no entity with givenid
exists -
optimistic: boolean
- [optional] [default: false] whether to use optimistic strategy. More detailed here
changeListRemote$(
patches: IdPatchRequest<T>[],
dataSource$: Observable<IdPatch<T>[] | undefined>,
options?: ChangeOptions,
): Observable<IdPatch<T>[] | undefined>;
This method will subscribe to dataSource$
and apply patches using changeList method. It will also affect loading state using setLoadingStateBus. This method returns cold observable.
patches: IdPatchRequest<T>[]
- [required] this is array of object with id and patch from change
method description.
This patch will be used if options.optimistic
equals true
. In basic cases you have to pass undefined
and the patch will be recieved from dataSource$
dataSource$: Observable<T>
- [required] the source of patch.
options: ChangeOptions
- [optional]:
-
merge: boolean
- [optional] [default: true] whether to merge patch with exist entity or to replace it with patch. whether to merge entity isntances if there is instances with the same id. Merge is perfromed by merge util. -
ifNotExist: boolean
- [optional] [default: false] to create an entity if no entity with givenid
exists -
optimistic: boolean
- [optional] [default: false] whether to use optimistic strategy. More detailed here
removeRemote$<R>(
id: Id,
observable$: Observable<R>,
options?: EntityRemoveOptions,
): Observable<R>;
This method will subscribe to observable$
and remove entity's instance using remove method. It will also affect loading state using setLoadingStateBus. This method returns cold observable.
observable$: Observable<R>
- [required] observable to subscribe and remove on next
options: EntityRemoveOptions
- [optional]
-
safe: boolean
- [optional] [default: false] whether to permamenty remove entity's instance. Iftrue
is passed, it will just mark entity's instance asremoved
and it won't be visible by select observables (listened above) until it will be restored by restoreRemoved. -
optimistic: boolean
- [optional] [default: false] whether to use optimistic strategy. More detailed here
removeListRemote$<R>(
ids: Id[],
observable$: Observable<R>,
options?: EntityRemoveListOptions,
): Observable<R>;
This method will subscribe to observable$
and remove entities' instances using removeList method. It will also affect loading state using setLoadingStateBus. This method returns cold observable.
observable$: Observable<R>
- [required] observable to subscribe and remove on next
options: EntityRemoveListOptions
- [optional]
-
safe: boolean
- [optional] [default: false] whether to permamenty remove entity's instance. Iftrue
is passed, it will just mark entity's instance asremoved
and it won't be visible by select observables (listened above) until it will be restored by restoreRemovedList. -
optimistic: boolean
- [optional] [default: false] whether to use optimistic strategy. More detailed here