##// END OF EJS Templates
Added tag v1.8.0 for changeset 66546e709732
Added tag v1.8.0 for changeset 66546e709732

File last commit:

r129:66546e709732 v1.8.0 default
r130:5811271fa858 default
Show More
store.ts
61 lines | 2.1 KiB | video/mp2t | TypeScriptLexer
import { PromiseOrValue } from "@implab/core-amd/interfaces";
import { isPromise } from "@implab/core-amd/safe";
import { observe, Observable } from "./observable";
export interface OrderedUpdate<T> {
/** The item is being updated */
readonly item: T;
/** The previous index of the item, -1 in case it is inserted */
readonly prevIndex: number;
/** The new index of the item, -1 in case it is deleted */
readonly newIndex: number;
}
export type QueryResults<T> = Observable<OrderedUpdate<T>>;
interface DjObservableResults<T> {
/**
* Allows observation of results
*/
observe(listener: (object: T, previousIndex: number, newIndex: number) => void, includeUpdates?: boolean): {
remove(): void;
};
}
interface Queryable<T, Q, O> {
query(query?: Q, options?: O): PromiseOrValue<T[]>;
}
export const isDjObservableResults = <T>(v: object): v is DjObservableResults<T> =>
v && (typeof (v as { observe?: unknown; }).observe === "function");
export const query = <T, Q, O>(store: Queryable<T, Q, O>, includeUpdates = true) =>
(query?: Q, options?: O & { observe?: boolean }) => {
return observe<OrderedUpdate<T>>(({ next, complete, error, isClosed }) => {
const processResults = (items: T[]) =>
items.forEach((item, newIndex) => next({ item, newIndex, prevIndex: -1 }));
try {
const results = store.query(query, options);
if (isPromise(results)) {
results.then(processResults).then(undefined, error);
} else {
processResults(results);
}
if (!isClosed() && (options?.observe !== false) && isDjObservableResults<T>(results)) {
const h = results.observe((item, prevIndex, newIndex) => next({ item, prevIndex, newIndex }), includeUpdates);
return () => h.remove();
} else {
complete();
}
} catch (err) {
error(err);
}
});
};