@thisisagile/easy
Version:
Straightforward library for building domain-driven microservice architectures
220 lines (168 loc) • 6.71 kB
text/typescript
import { isList, List, toList } from './List';
import { Construct, ofConstruct } from './Constructor';
import { isA } from './IsA';
import { PlainSort, Sort } from './Sort';
import { GetProperty } from './Get';
import { ArrayLike } from './Array';
import { Optional } from './Types';
import { isNumber } from './Is';
import { choose } from './Case';
import type { Id } from './Id';
export type FilterValue = { label?: string; value: any, count?: number };
export type Filter = { label?: string; field: string; shortField?: string; values: FilterValue[] };
export const toFilter = (field: string, value: any): Filter => toShortFilter(field, field, value);
export const toShortFilter = (field: string, shortField: string, value: any): Filter => ({
field,
shortField,
values: [{ value }],
});
export type PageOptions = { take?: number; skip?: number; sort?: Sort[]; sorts?: PlainSort; filters?: Filter[] };
export type PageListOptions = Exclude<PageOptions, 'sort'> & { total?: number };
export class PageList<T> extends List<T> {
private _options?: PageListOptions;
get options(): Optional<PageListOptions> {
return this._options;
}
get take(): number {
return this._options?.take ?? 250;
}
get skip(): number {
return this._options?.skip ?? 0;
}
get total(): Optional<number> {
return this._options?.total;
}
get sorts(): Optional<PlainSort> {
return this._options?.sorts;
}
get filters(): Optional<Filter[]> {
return this._options?.filters;
}
get meta(): PageListOptions {
return {
take: this.take,
skip: this.skip,
total: this.total,
sorts: this.sorts,
filters: this.filters,
};
}
get ids(): PageList<Id> {
return this.mapDefined(i => (i as any).id as Id);
}
asc(p: GetProperty<T, any>): PageList<T> {
return toPageList(super.asc(p), this);
}
desc(p: GetProperty<T, any>): PageList<T> {
return toPageList(super.desc(p), this);
}
diff(others: ArrayLike<T>): PageList<T> {
return toPageList(super.diff(others), this);
}
diffByKey<U = T>(others: ArrayLike<U>, key: keyof T & keyof U): PageList<T> {
return toPageList(super.diffByKey(others, key), this);
}
symmetricDiff(others: ArrayLike<T>): PageList<T> {
return toPageList(super.symmetricDiff(others), this);
}
symmetricDiffByKey(others: ArrayLike<T>, key: keyof T): PageList<T> {
return toPageList(super.symmetricDiffByKey(others, key), this);
}
intersect(others: ArrayLike<T>): PageList<T> {
return toPageList(super.intersect(others), this);
}
intersectByKey<U>(others: ArrayLike<U>, key: keyof T & keyof U): PageList<T> {
return toPageList(super.intersectByKey(others, key), this);
}
map<U>(f: (value: T, index: number, array: T[]) => U, params?: unknown): PageList<U> {
const items = super.map(f, params);
return toPageList(items, this);
}
flatMap<U, This = unknown>(f: (this: This, value: T, index: number, array: T[]) => ReadonlyArray<U> | U, params?: This): PageList<U> {
return toPageList(super.flatMap(f, params), this);
}
mapDefined<U>(f: (value: T, index: number, array: T[]) => U, params?: unknown): PageList<NonNullable<U>> {
return toPageList(super.mapDefined(f, params), this);
}
mapAsync(f: (i: T) => Promise<T>): Promise<PageList<T>> {
return super.mapAsync(f).then(r => toPageList(r, this));
}
areEqual(...items: ArrayLike<T> ): boolean {
return this.isSubSetOf(...items) && toList(...items).isSubSetOf(...this);
}
distinct(): PageList<T> {
return toPageList(super.distinct(), this);
}
distinctByKey(key: keyof T): PageList<T> {
return toPageList(super.distinctByKey(key), this);
}
distinctByValue(): PageList<T> {
return toPageList(super.distinctByValue(), this);
}
filter(p: (value: T, index: number, array: T[]) => unknown, params?: unknown): PageList<T> {
return toPageList(super.filter(p, params), this);
}
accumulate(...keys: (keyof T)[]): PageList<T> {
return toPageList(super.accumulate(...keys), this);
}
concat(...items: ConcatArray<T>[]): PageList<T>;
concat(...items: (T | ConcatArray<T>)[]): PageList<T>;
concat(...items: (T | ConcatArray<T>)[]): PageList<T> {
return toPageList(super.concat(...items), this);
}
reverse(): PageList<T> {
return toPageList(super.reverse(), this);
}
splice(start: number, deleteCount?: number): PageList<T>;
splice(start: number, deleteCount: number, ...items: T[]): PageList<T>;
splice(start: number, deleteCount: number, ...items: T[]): PageList<T> {
return toPageList(super.splice(start, deleteCount, ...items), this);
}
remove(item: T): PageList<T> {
return toPageList(super.remove(item), this);
}
replace(key: keyof T, item: T): PageList<T> {
return toPageList(super.replace(key, item), this);
}
switch(item: T): PageList<T> {
return toPageList(super.switch(item), this);
}
defined(): PageList<NonNullable<T>> {
return toPageList(super.defined(), this);
}
orElse(...alt: ArrayLike<T>): Optional<PageList<T>> {
return toPageList(super.orElse(...alt), this);
}
slice(start?: number, end?: number): PageList<T> {
return toPageList(super.slice(start, end), this);
}
//we needed to add U because of a Typescript issue with generics
update<U = T>(p: (value: T, index: number, array: T[]) => unknown, val: T | ((v: U) => T)): PageList<T> {
return toPageList(super.update(p, val), this);
}
updateFirst<U = T>(p: (value: T, index: number, array: T[]) => unknown, val: T | ((v: U) => T)): PageList<T> {
return toPageList(super.updateFirst(p, val), this);
}
updateFirstById<U = T>(id: Id, val: T | ((v: U) => T)): PageList<T> {
return toPageList(super.updateFirstById(id, val), this);
}
updateById<U = T>(id: Id, val: T | ((v: U) => T)): PageList<T> {
return toPageList(super.updateById(id, val), this);
}
private setPageOptions(options?: PageListOptions): this {
this._options = options;
return this;
}
}
export const isPageList = <T>(l?: unknown): l is PageList<T> => isList<T>(l) && isA(l, 'total');
export const toPageList = <T>(items: T[] = [], options?: Omit<PageOptions, 'sort'> & { total?: number }): PageList<T> =>
(
choose(items)
.case(
i => i.length === 1 && isNumber(i[0]),
i => new PageList<T>().add(...i)
)
.else(i => new PageList<T>(...i)) as any
).setPageOptions(options);
/* @deprecated No longer needed as the PageList is now a class that extends from List, use the map function */
export const asPageList = <T, U>(c: Construct<T>, items = toPageList<U>()): PageList<T> => items.map(i => ofConstruct(c, i));