@fireflysemantics/slice
Version:

473 lines (469 loc) • 13.8 kB
TypeScript
import { AbstractStore } from './AbstractStore';
import { StoreConfig } from './models/StoreConfig';
import { Predicate, Delta } from './models/';
import { Observable } from 'rxjs';
import { Slice } from './Slice';
/**
* This `todoFactory` code will be used to illustrate the API examples. The following
* utilities are used in the tests and the API Typedoc examples contained here.
* @example Utilities for API Examples
* ```
* export const enum TodoSliceEnum {
* COMPLETE = "Complete",
* INCOMPLETE = "Incomplete"
* }
* export class Todo {
* constructor(
* public complete: boolean,
* public title: string,
* public gid?:string,
* public id?:string) {}
* }
*
* export let todos = [new Todo(false, "You complete me!"), new Todo(true, "You completed me!")];
*
* export function todosFactory():Todo[] {
* return [new Todo(false, "You complete me!"), new Todo(true, "You completed me!")];
* }
* ```
*/
export declare class EStore<E> extends AbstractStore<E> {
/**
* Store constructor (Initialization with element is optional)
*
* perform initial notification to all observers,
* such that functions like {@link combineLatest}{}
* will execute at least once.
*
* @param entities The entities to initialize the store with.
* @param config The optional configuration instance.
*
* @example EStore<Todo> Creation
* ```
* // Initialize the Store
* let store: EStore<Todo> = new EStore<Todo>(todosFactory());
* ```
*/
constructor(entities?: E[], config?: StoreConfig);
/**
* Calls complete on all EStore {@link ReplaySubject} instances.
*
* Call destroy when disposing of the store.
*/
destroy(): void;
/**
* Toggles the entity:
*
* If the store contains the entity
* it will be deleted. If the store
* does not contains the entity,
* it is added.
* @param e The entity to toggle
* @example Toggle the Todo instance
* ```
* estore.post(todo);
* // Remove todo
* estore.toggle(todo);
* // Add it back
* estore.toggle(todo);
* ```
*/
toggle(e: E): void;
/**
* Notifies observers when the store is empty.
*/
private notifyActive;
/**
* `Map` of active entties. The instance is public and can be used
* directly to add and remove active entities, however we recommend
* using the {@link addActive} and {@link deleteActive} methods.
*/
active: Map<string, E>;
/**
* Add multiple entity entities to active.
*
* If the entity is not contained in the store it is added
* to the store before it is added to `active`.
*
* Also we clone the map prior to broadcasting it with
* `notifyActive` to make sure we will trigger Angular
* change detection in the event that it maintains
* a reference to the `active` state `Map` instance.
*
* @example Add todo1 and todo2 as active
* ```
* addActive(todo1);
* addActive(todo2);
* ```
*/
addActive(e: E): void;
/**
* Delete an active entity.
*
* Also we clone the map prior to broadcasting it with
* `notifyActive` to make sure we will trigger Angular
* change detection in the event that it maintains
* a reference to the `active` state `Map` instance.
*
* @example Remove todo1 and todo2 as active entities
* ```
* deleteActive(todo1);
* deleteActive(todo2);
* ```
*/
deleteActive(e: E): void;
/**
* Clear / reset the active entity map.
*
* Also we clone the map prior to broadcasting it with
* `notifyActive` to make sure we will trigger Angular
* change detection in the event that it maintains
* a reference to the `active` state `Map` instance.
*
* @example Clear active todo instances
* ```
* store.clearActive();
* ```
*/
clearActive(): void;
/**
* Observe the active entities.
*
* @example
* ```
* let active$ = store.observeActive();
* ```
*/
observeActive(): Observable<Map<string, E>>;
/**
* Observe the active entity.
* @example
<pre>
let active$ = source.activeSnapshot();
</pre>
*/
activeSnapshot(): E[];
/**
* Observable of errors occurred during a load request.
*
* The error Observable should be created by the
* client.
*/
loadingError: Observable<any>;
/**
* Notifies observers when the store is loading.
*
* This is a common pattern found when implementing
* `Observable` data sources.
*/
private notifyLoading;
/**
* The current loading state. Use loading when fetching new
* data for the store. The default loading state is `true`.
*
* This is such that if data is fetched asynchronously
* in a service, components can wait on loading notification
* before attempting to retrieve data from the service.
*
* Loading could be based on a composite response. For example
* when the stock and mutual funds have loaded, set loading to `false`.
*/
private _loading;
/**
* Sets the current loading state and notifies observers.
*/
set loading(loading: boolean);
/**
* @return A snapshot of the loading state.
* @example Create a reference to the loading state
* ```
* const loading:boolean = todoStore.loading;
* ```
*/
get loading(): boolean;
/**
* Observe loading.
*
* Note that this obverable piped through
* `takeWhile(v->v, true), such that it will
* complete after each emission.
*
* See:
* https://fireflysemantics.medium.com/waiting-on-estore-to-load-8dcbe161613c
*
* For more details.
* Also note that v=>v is the same as v=>v!=false
*
* @example
* ```
* const observeLoadingHandler: Observer<boolean> = {
* complete: () => {
* console.log(`Data Loaded and Observable Marked as Complete`);
* }, // completeHandler
* error: () => {
* console.log(`Any Errors?`);
* }, // errorHandler
* next: (l) => {
* console.log(`Data loaded and loading is ${l}`);
* },
* };
*
* const observeLoadingResubscribeHandler: Observer<boolean> = {
* complete: () => {
* console.log(`Data Loaded and Resubscribe Observable Marked as Complete`);
* }, // completeHandler
* error: () => {
* console.log(`Any Resubscribe Errors?`);
* }, // errorHandler
* next: (l) => {
* console.log(`Data loaded and resusbscribe loading value is ${l}`);
* },
* };
*
* const todoStore: EStore<Todo> = new EStore();
* //============================================
* // Loading is true by default
* //============================================
* console.log(`The initial value of loading is ${todoStore.loading}`);
* //============================================
* // Observe Loading
* //============================================
* let loading$: Observable<boolean> = todoStore.observeLoading();
* loading$.subscribe((l) => console.log(`The value of loading is ${l}`));
*
* todoStore.loading = false;
* loading$.subscribe(observeLoadingHandler);
* //============================================
* // The subscription no longer fires
* //============================================
* todoStore.loading = true;
* todoStore.loading = false;
*
* //============================================
* // The subscription no longer fires,
* // so if we want to observe loading again
* // resusbscribe.
* //============================================
* todoStore.loading = true;
* loading$ = todoStore.observeLoading();
* loading$.subscribe(observeLoadingResubscribeHandler);
* todoStore.loading = false;
* ```
*/
observeLoading(): Observable<boolean>;
/**
* Notfiies when loading has completed.
*/
observeLoadingComplete(): Observable<boolean>;
/**
* Observable of errors occurred during a search request.
*
* The error Observable should be created by the
* client.
*/
searchError: Observable<any>;
/**
* Notifies observers that a search is in progress.
*
* This is a common pattern found when implementing
* `Observable` data sources.
*/
private notifySearching;
/**
* The current `searching` state. Use `searching`
* for example to display a spinnner
* when performing a search.
* The default `searching` state is `false`.
*/
private _searching;
/**
* Sets the current searching state and notifies observers.
*/
set searching(searching: boolean);
/**
* @return A snapshot of the searching state.
*/
get searching(): boolean;
/**
* Observe searching.
* @example
<pre>
let searching$ = source.observeSearching();
</pre>
Note that this obverable piped through
`takeWhile(v->v, true), such that it will
complete after each emission.
See:
https://medium.com/@ole.ersoy/waiting-on-estore-to-load-8dcbe161613c
For more details.
*/
observeSearching(): Observable<boolean>;
/**
* Notfiies when searching has completed.
*/
observeSearchingComplete(): Observable<boolean>;
/**
* Store slices
*/
private slices;
/**
* Adds a slice to the store and keys it by the slices label.
*
* @param p
* @param label
*
* @example Setup a Todo Slice for COMPLETE Todos
```
source.addSlice(todo => todo.complete, TodoSlices.COMPLETE);
```
*/
addSlice(p: Predicate<E>, label: string): void;
/**
* Remove a slice
* @param label The label identifying the slice
*
* @example Remove the TodoSlices.COMPLETE Slice
```
source.removeSlice(TodoSlices.COMPLETE);
```
*/
removeSlice(label: string): void;
/**
* Get a slice
* @param label The label identifying the slice
* @return The Slice instance or undefined
*
* @example Get the TodoSlices.COMPLETE slice
```
source.getSlice(TodoSlices.COMPLETE);
```
*/
getSlice(label: string): Slice<E> | undefined;
/**
* Post (Add a new) element(s) to the store.
* @param e An indiidual entity or an array of entities
* @example Post a Todo instance.
*
*```
* store.post(todo);
*```
*/
post(e: E | E[]): void;
/**
* Post N entities to the store.
* @param ...e
* @example Post two Todo instances.
* ```
* store.post(todo1, todo2);
* ```
*/
postN(...e: E[]): void;
/**
* Post (Add) an array of elements to the store.
* @param e
* @example Post a Todo array.
*
* ```
* store.post([todo1, todo2]);
* ```
*/
postA(e: E[]): void;
/**
* Put (Update) an entity.
* @param e
* @example Put a Todo instance.
* ```
* store.put(todo1);
* ```
*/
put(e: E | E[]): void;
/**
* Put (Update) an element or add an element that was read from a persistence source
* and thus already has an assigned global id`.
* @param e The enetity instances to update.
* @example Put N Todo instances.
*
* ```
* store.put(todo1, todo2);
* ```
*/
putN(...e: E[]): void;
/**
* Put (Update) the array of enntities.
* @param e The array of enntities to update
* @example Put an array of Todo instances.
* ```
* store.put([todo1, todo2]);
* ```
*/
putA(e: E[]): void;
/**
* Delete (Update) the array of elements.
* @param e
* @example Delete todo1.
* ```
* store.delete(todo1]);
* ```
*/
delete(e: E | E[]): void;
/**
* Delete N elements.
* @param ...e
* @example Delete N Todo instance argument.
* ```
* store.deleteN(todo1, todo2);
* ```
*/
deleteN(...e: E[]): void;
/**
* Delete an array of elements.
* @param e The array of instances to be deleted
* @example Delete the array of Todo instances.
* ```
* store.deleteA([todo1, todo2]);
* ```
*/
deleteA(e: E[]): void;
/**
* Delete elements by {@link Predicate}.
* @param p The predicate.
* @example Delete the Todo instances.
* ```
* store.delete(todo1, todo2);
* ```
*/
deleteP(p: Predicate<E>): void;
/**
* If the entity has the `id` key initialized with a value,
* then also add the entity to the `idEntries`.
*
* @param e The element to be added to the `idEntries`.
*/
private updateIDEntry;
/**
* If the entity has the `id` key initialized with a value,
* then also delete the entity to the `idEntries`.
*
* @param e The element to be added to the `idEntries`.
*/
private deleteIDEntry;
/**
* Resets the store and all contained slice instances to empty.
* Also perform delta notification that sends all current store entries.
* The ActionType.RESET code is sent with the delta notification. Slices
* send their own delta notification.
*
* @example Reset the store.
* ```
* store.reset();
* ```
*/
reset(): void;
/**
* Call all the notifiers at once.
*
* @param v
* @param delta
*/
protected notifyAll(v: E[], delta: Delta<E>): void;
}