@datorama/akita
Version:
A Reactive State Management Tailored-Made for JS Applications
203 lines • 6.4 kB
JavaScript
import { distinctUntilChanged, filter, map, of, switchMap } from 'rxjs';
import { distinctUntilArrayItemChanged } from './arrayFind';
import { coerceArray } from './coerceArray';
import { entitiesToArray } from './entitiesToArray';
import { entitiesToMap } from './entitiesToMap';
import { findEntityByPredicate, getEntity } from './getEntity';
import { isArray } from './isArray';
import { isDefined } from './isDefined';
import { isFunction } from './isFunction';
import { isNil } from './isNil';
import { mapSkipUndefined } from './mapSkipUndefined';
import { Query } from './query';
import { sortByOptions } from './sortByOptions';
import { toBoolean } from './toBoolean';
/**
*
* The Entity Query is similar to the general Query, with additional functionality tailored for EntityStores.
*
* class WidgetsQuery extends QueryEntity<WidgetsState> {
* constructor(protected store: WidgetsStore) {
* super(store);
* }
* }
*
*
*
*/
export class QueryEntity extends Query {
constructor(store, options = {}) {
super(store);
this.options = options;
this.__store__ = store;
}
selectAll(options = {
asObject: false,
}) {
return this.select((state) => state.entities).pipe(map(() => this.getAll(options)));
}
getAll(options = { asObject: false, filterBy: undefined, limitTo: undefined }) {
if (options.asObject) {
return entitiesToMap(this.getValue(), options);
}
sortByOptions(options, this.config || this.options);
return entitiesToArray(this.getValue(), options);
}
selectMany(ids, project) {
if (!ids || !ids.length)
return of([]);
return this.select((state) => state.entities).pipe(map((entities) => mapSkipUndefined(ids, (id) => getEntity(id, project)(entities))), distinctUntilArrayItemChanged());
}
selectEntity(idOrPredicate, project) {
let id = idOrPredicate;
if (isFunction(idOrPredicate)) {
// For performance reason we expect the entity to be in the store
id = findEntityByPredicate(idOrPredicate, this.getValue().entities);
}
return this.select((state) => state.entities).pipe(map(getEntity(id, project)), distinctUntilChanged());
}
/**
* Get an entity by id
*
* @example
*
* this.query.getEntity(1);
*/
getEntity(id) {
return this.getValue().entities[id];
}
/**
* Select the active entity's id
*
* @example
*
* this.query.selectActiveId()
*/
selectActiveId() {
return this.select((state) => state.active);
}
/**
* Get the active id
*
* @example
*
* this.query.getActiveId()
*/
getActiveId() {
return this.getValue().active;
}
selectActive(project) {
if (isArray(this.getActive())) {
return this.selectActiveId().pipe(switchMap((ids) => this.selectMany(ids, project)));
}
return this.selectActiveId().pipe(switchMap((ids) => this.selectEntity(ids, project)));
}
getActive() {
const activeId = this.getActiveId();
if (isArray(activeId)) {
return activeId.map((id) => this.getValue().entities[id]);
}
return toBoolean(activeId) ? this.getEntity(activeId) : undefined;
}
/**
* Select the store's entity collection length
*
* @example
*
* this.query.selectCount()
* this.query.selectCount(entity => entity.completed)
*/
selectCount(predicate) {
return this.select((state) => state.entities).pipe(map(() => this.getCount(predicate)));
}
/**
* Get the store's entity collection length
*
* @example
*
* this.query.getCount()
* this.query.getCount(entity => entity.completed)
*/
getCount(predicate) {
if (isFunction(predicate)) {
return this.getAll().filter(predicate).length;
}
return this.getValue().ids.length;
}
selectLast(project) {
return this.selectAt((ids) => ids[ids.length - 1], project);
}
selectFirst(project) {
return this.selectAt((ids) => ids[0], project);
}
selectEntityAction(actionOrActions) {
if (isNil(actionOrActions)) {
return this.store.selectEntityAction$;
}
const project = isArray(actionOrActions) ? (action) => action : ({ ids }) => ids;
const actions = coerceArray(actionOrActions);
return this.store.selectEntityAction$.pipe(filter(({ type }) => actions.includes(type)), map((action) => project(action)));
}
hasEntity(projectOrIds) {
if (isNil(projectOrIds)) {
return this.getValue().ids.length > 0;
}
if (isFunction(projectOrIds)) {
return this.getAll().some(projectOrIds);
}
if (isArray(projectOrIds)) {
return projectOrIds.every((id) => id in this.getValue().entities);
}
return projectOrIds in this.getValue().entities;
}
/**
* Returns whether entity store has an active entity
*
* @example
*
* this.query.hasActive()
* this.query.hasActive(3)
*
*/
hasActive(id) {
const active = this.getValue().active;
const isIdProvided = isDefined(id);
if (Array.isArray(active)) {
if (isIdProvided) {
return active.includes(id);
}
return active.length > 0;
}
return isIdProvided ? active === id : isDefined(active);
}
/**
*
* Create sub UI query for querying Entity's UI state
*
* @example
*
*
* export class ProductsQuery extends QueryEntity<ProductsState> {
* ui: EntityUIQuery<ProductsUIState>;
*
* constructor(protected store: ProductsStore) {
* super(store);
* this.createUIQuery();
* }
*
* }
*/
createUIQuery() {
this.ui = new EntityUIQuery(this.__store__.ui);
}
selectAt(mapFn, project) {
return this.select((state) => state.ids).pipe(map(mapFn), distinctUntilChanged(), switchMap((id) => this.selectEntity(id, project)));
}
}
// @internal
export class EntityUIQuery extends QueryEntity {
constructor(store) {
super(store);
}
}
//# sourceMappingURL=queryEntity.js.map