391 lines
18 KiB
TypeScript
391 lines
18 KiB
TypeScript
import { EntityDict, StorageSchema, OpRecord } from "oak-domain/lib/types";
|
||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||
import { AspectDict as CommonAspectDict } from 'oak-common-aspect';
|
||
import { NamedFilterItem, NamedSorterItem } from "../types/NamedCondition";
|
||
import { Cache } from './cache';
|
||
import { Pagination } from '../types/Pagination';
|
||
import { Feature } from '../types/Feature';
|
||
export declare const MODI_NEXT_PATH_SUFFIX = ":next";
|
||
type LegalOperation<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = ED[T]['CreateSingle'] | ED[T]['Update'] | ED[T]['Remove'];
|
||
/**
|
||
* 树结点上的更新日志管理
|
||
*/
|
||
declare class UpdateLogManager<ED extends EntityDict & BaseEntityDict, T extends keyof ED> {
|
||
private logs;
|
||
private schema;
|
||
private entity;
|
||
maxLsn: number;
|
||
constructor(schema: StorageSchema<ED>, entity: T, maxLsn?: number);
|
||
/**
|
||
* 合并两个filter完全一致的更新
|
||
* @param oper1
|
||
* @param oper2
|
||
*/
|
||
private mergeOperation;
|
||
/**
|
||
* 增加一条更新日志记录
|
||
* @param lsn
|
||
* @param action
|
||
* @param data
|
||
* @param filter
|
||
*/
|
||
push(lsn: number, oper2: Omit<LegalOperation<ED, T>, "id">): void;
|
||
undo(filter: ED[T]['Update']['filter']): void;
|
||
/**
|
||
* 将lsn大于传入lsn的日志全部回滚
|
||
* @param lsn
|
||
*/
|
||
rollback(lsn: number): void;
|
||
makeOperations(): LegalOperation<ED, T>[];
|
||
isEmpty(): boolean;
|
||
}
|
||
declare abstract class Node<ED extends EntityDict & BaseEntityDict> extends Feature {
|
||
private zombie;
|
||
protected abstract children: Record<string, Node<ED>>;
|
||
protected stale?: boolean;
|
||
protected fullPath: string;
|
||
/**
|
||
* 当前有几个组件正在使用这个结点
|
||
*/
|
||
private count;
|
||
protected executing: boolean;
|
||
protected dirty?: boolean;
|
||
private extraData;
|
||
private refreshing;
|
||
private refreshCallbacks;
|
||
constructor(fullPath: string);
|
||
protected isInModiNextBranch(): boolean;
|
||
increaseCount(): number;
|
||
decreaseCount(): number;
|
||
getCount(): number;
|
||
setZombie(zombie: boolean): void;
|
||
isZombie(): boolean;
|
||
abstract getModiOperations(): Array<{
|
||
entity: keyof ED;
|
||
operation: ED[keyof ED]['Operation'];
|
||
}> | undefined;
|
||
abstract setDirty(): void;
|
||
isDirty(): boolean;
|
||
isLoading(): boolean;
|
||
isExecuting(): boolean;
|
||
setExecuting(executing: boolean): void;
|
||
protected startRefreshing(num: number): number | Promise<void>;
|
||
protected endRefreshing(num: number, error?: any): void;
|
||
saveExtraData(key: string, data: any): void;
|
||
loadExtraData(key: string): any;
|
||
isStale(): boolean;
|
||
abstract getParent(): Node<ED> | undefined;
|
||
}
|
||
declare abstract class EntityNode<ED extends EntityDict & BaseEntityDict, T extends keyof ED> extends Node<ED> {
|
||
protected entity: T;
|
||
protected schema: StorageSchema<ED>;
|
||
protected projection?: ED[T]['Projection'] | (() => ED[T]['Projection']);
|
||
protected parent?: SingleNode<ED, keyof ED> | ListNode<ED, keyof ED> | VirtualNode<ED>;
|
||
protected cache: Cache<ED>;
|
||
protected ulManager: UpdateLogManager<ED, T>;
|
||
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED>, fullPath: string, projection?: ED[T]['Projection'] | (() => Promise<ED[T]['Projection']>), parent?: SingleNode<ED, keyof ED> | ListNode<ED, keyof ED> | VirtualNode<ED>);
|
||
getEntity(): T;
|
||
getSchema(): StorageSchema<ED>;
|
||
abstract checkIfClean(child: Node<ED>): boolean;
|
||
setDirty(): void;
|
||
getParent(): SingleNode<ED, keyof ED> | ListNode<ED, keyof ED> | VirtualNode<ED> | undefined;
|
||
protected getProjection(): ED[T]['Projection'] | undefined;
|
||
setProjection(projection: ED[T]['Projection']): void;
|
||
protected judgeRelation(attr: string): string | 0 | 1 | string[] | 2 | -1;
|
||
}
|
||
declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof ED> extends EntityNode<ED, T> {
|
||
protected children: Record<string, SingleNode<ED, T>>;
|
||
private filters;
|
||
private sorters;
|
||
private getTotal?;
|
||
private pagination;
|
||
private sr;
|
||
private loadingMore;
|
||
private syncHandler;
|
||
setFiltersAndSortedApplied(): void;
|
||
private startLoading;
|
||
checkIfClean(child: Node<ED>): boolean;
|
||
getModiOperations(): Array<{
|
||
entity: keyof ED;
|
||
operation: ED[keyof ED]['Operation'];
|
||
}> | undefined;
|
||
onCacheSync(records: OpRecord<ED>[]): void;
|
||
destroy(): void;
|
||
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED>, fullPath: string, projection?: ED[T]['Projection'] | (() => Promise<ED[T]['Projection']>), parent?: SingleNode<ED, keyof ED> | VirtualNode<ED>, path?: string, filters?: NamedFilterItem<ED, T>[], sorters?: NamedSorterItem<ED, T>[], getTotal?: number, pagination?: Pick<Pagination, 'currentPage' | 'pageSize' | 'randomRange'>, stale?: boolean);
|
||
getPagination(): Pagination;
|
||
setPagination(pagination: Pick<Pagination, 'currentPage' | 'pageSize' | 'randomRange'>, dontRefresh?: true): void;
|
||
isLoadingMore(): boolean;
|
||
addChild(path: string, node: SingleNode<ED, T>): void;
|
||
removeChild(path: string): void;
|
||
getChild(path: string): SingleNode<ED, T>;
|
||
getNamedFilters(): (NamedFilterItem<ED, T> & {
|
||
applied?: boolean | undefined;
|
||
})[];
|
||
getNamedFilterByName(name: string): (NamedFilterItem<ED, T> & {
|
||
applied?: boolean | undefined;
|
||
}) | undefined;
|
||
setNamedFilters(filters: NamedFilterItem<ED, T>[], refresh?: boolean): void;
|
||
addNamedFilter(filter: NamedFilterItem<ED, T>, refresh?: boolean): void;
|
||
removeNamedFilter(filter: NamedFilterItem<ED, T>, refresh?: boolean): void;
|
||
removeNamedFilterByName(name: string, refresh?: boolean): void;
|
||
getNamedSorters(): (NamedSorterItem<ED, T> & {
|
||
applied?: boolean | undefined;
|
||
})[];
|
||
getNamedSorterByName(name: string): (NamedSorterItem<ED, T> & {
|
||
applied?: boolean | undefined;
|
||
}) | undefined;
|
||
setNamedSorters(sorters: NamedSorterItem<ED, T>[], refresh?: boolean): void;
|
||
addNamedSorter(sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||
removeNamedSorter(sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||
removeNamedSorterByName(name: string, refresh: boolean): void;
|
||
getFreshValue(): Array<Partial<ED[T]['Schema']>>;
|
||
private addItemInner;
|
||
addItem(lsn: number, item: Omit<ED[T]['CreateSingle']['data'], 'id'> & {
|
||
id?: string;
|
||
}): string;
|
||
addItems(lsn: number, items: Array<Omit<ED[T]['CreateSingle']['data'], 'id'> & {
|
||
id?: string;
|
||
}>): string[];
|
||
private removeItemInner;
|
||
removeItem(lsn: number, id: string): void;
|
||
removeItems(lsn: number, ids: string[]): void;
|
||
private recoverItemInner;
|
||
recoverItem(id: string): void;
|
||
recoverItems(ids: string[]): void;
|
||
resetItem(id: string): void;
|
||
private preProcessUpdateData;
|
||
private updateItemInner;
|
||
/**
|
||
* 目前只支持根据itemId进行更新
|
||
* @param data
|
||
* @param id
|
||
* @param beforeExecute
|
||
* @param afterExecute
|
||
*/
|
||
updateItem(lsn: number, data: ED[T]['Update']['data'], id: string, action?: ED[T]['Action']): void;
|
||
updateItems(lsn: number, data: Record<string, ED[T]['Update']['data']>, ids: string[], action?: ED[T]['Action']): void;
|
||
composeOperations(paths?: string[]): Array<{
|
||
entity: keyof ED;
|
||
operation: ED[keyof ED]['Operation'];
|
||
}> | undefined;
|
||
getProjection(): ED[T]["Projection"] | undefined;
|
||
private constructFilters;
|
||
constructSelection(withParent?: true, ignoreNewParent?: boolean, ignoreUnapplied?: true): {
|
||
data: ED[T]["Projection"] | undefined;
|
||
filter: ED[T]["Filter"] | undefined;
|
||
sorter: ED[T]["Sorter"];
|
||
total: number | undefined;
|
||
indexFrom: number;
|
||
count: number;
|
||
};
|
||
/**
|
||
* 存留查询结果
|
||
*/
|
||
saveRefreshResult(sr: Awaited<ReturnType<CommonAspectDict<ED>['select']>>, append?: boolean, currentPage?: number): void;
|
||
refresh(pageNumber?: number, append?: boolean, resetTotal?: boolean): Promise<void>;
|
||
loadMore(): Promise<void>;
|
||
setCurrentPage(currentPage: number): void;
|
||
clean(lsn?: number, dontPublish?: true): void;
|
||
getIntrinsticFilters(): ED[T]["Filter"] | undefined;
|
||
}
|
||
declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof ED> extends EntityNode<ED, T> {
|
||
private id?;
|
||
private sr;
|
||
protected children: {
|
||
[K: string]: SingleNode<ED, keyof ED> | ListNode<ED, keyof ED>;
|
||
};
|
||
private filters?;
|
||
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED>, fullPath: string, path: string, projection?: ED[T]['Projection'] | (() => Promise<ED[T]['Projection']>), parent?: SingleNode<ED, keyof ED> | VirtualNode<ED> | ListNode<ED, T>, id?: string, filters?: NamedFilterItem<ED, T>[], stale?: boolean);
|
||
getModiOperations(): Array<{
|
||
entity: keyof ED;
|
||
operation: ED[keyof ED]['Operation'];
|
||
}> | undefined;
|
||
setFiltersAndSortedApplied(): void;
|
||
startLoading(): number | Promise<void>;
|
||
checkIfClean(node: Node<ED>): boolean;
|
||
destroy(): void;
|
||
getChild(path: string): SingleNode<ED, keyof ED> | ListNode<ED, keyof ED>;
|
||
setId(id: string): void;
|
||
unsetId(): void;
|
||
getId(): string | undefined;
|
||
getChildren(): {
|
||
[K: string]: SingleNode<ED, keyof ED> | ListNode<ED, keyof ED>;
|
||
};
|
||
addChild(path: string, node: SingleNode<ED, keyof ED> | ListNode<ED, keyof ED>): void;
|
||
removeChild(path: string): void;
|
||
getFreshValue(): Partial<ED[T]['Schema']> | undefined;
|
||
private refreshListChildren;
|
||
create(lsn: number, data: Partial<Omit<ED[T]['CreateSingle']['data'], 'id'>>): void;
|
||
update(lsn: number, data: ED[T]['Update']['data'], action?: ED[T]['Action']): void;
|
||
remove(lsn: number): void;
|
||
setDirty(): void;
|
||
/**
|
||
*
|
||
* @param path 如果指定了某条路径,则只处理这条路径上的operation(区分modi的前后项)
|
||
* @returns
|
||
*/
|
||
composeOperations(paths?: string[]): Array<{
|
||
entity: keyof ED;
|
||
operation: ED[keyof ED]['Operation'];
|
||
}> | undefined;
|
||
getProjection(withDecendants?: boolean): ED[T]["Projection"] | undefined;
|
||
private passRsToChild;
|
||
saveRefreshResult(data: Record<string, any>): void;
|
||
refresh(): Promise<void>;
|
||
clean(lsn?: number, dontPublish?: true): void;
|
||
private getFilter;
|
||
getIntrinsticFilters(): ED[T]["Filter"] | undefined;
|
||
/**
|
||
* getParentFilter不能假设一定已经有数据,只能根据当前filter的条件去构造
|
||
* @param childNode
|
||
* @param disableOperation
|
||
* @returns
|
||
*/
|
||
getParentFilter<T2 extends keyof ED>(childNode: ListNode<ED, keyof ED>, ignoreNewParent?: boolean): ED[T2]['Filter'] | undefined;
|
||
}
|
||
declare class VirtualNode<ED extends EntityDict & BaseEntityDict> extends Node<ED> {
|
||
protected parent?: VirtualNode<ED>;
|
||
private refreshing2;
|
||
protected children: Record<string, SingleNode<ED, keyof ED> | ListNode<ED, keyof ED> | VirtualNode<ED>>;
|
||
constructor(fullPath: string, path?: string, parent?: VirtualNode<ED>, stale?: boolean);
|
||
getModiOperations(): Array<{
|
||
entity: keyof ED;
|
||
operation: ED[keyof ED]['Operation'];
|
||
}> | undefined;
|
||
setDirty(): void;
|
||
setFiltersAndSortedApplied(): void;
|
||
addChild(path: string, child: SingleNode<ED, keyof ED> | ListNode<ED, keyof ED> | VirtualNode<ED>): void;
|
||
removeChild(path: string): void;
|
||
getChild(path: string): VirtualNode<ED> | SingleNode<ED, keyof ED> | ListNode<ED, keyof ED>;
|
||
getParent(): VirtualNode<ED> | undefined;
|
||
destroy(): void;
|
||
getFreshValue(): undefined;
|
||
isLoading(): boolean;
|
||
refresh(): Promise<void>;
|
||
composeOperations(paths?: string[]): Array<{
|
||
entity: keyof ED;
|
||
operation: ED[keyof ED]['Operation'];
|
||
}> | undefined;
|
||
setExecuting(executing: boolean): void;
|
||
clean(lsn?: number, dontPublish?: true): void;
|
||
checkIfClean(node: Node<ED>): boolean;
|
||
}
|
||
export type CreateNodeOptions<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
|
||
path: string;
|
||
entity?: T;
|
||
isList?: boolean;
|
||
getTotal?: number;
|
||
projection?: ED[T]['Projection'] | (() => ED[T]['Projection']);
|
||
pagination?: Pick<Pagination, 'currentPage' | 'pageSize' | 'randomRange'>;
|
||
filters?: NamedFilterItem<ED, T>[];
|
||
sorters?: NamedSorterItem<ED, T>[];
|
||
beforeExecute?: (operations: ED[T]['Operation'][]) => Promise<void>;
|
||
afterExecute?: (operations: ED[T]['Operation'][]) => Promise<void>;
|
||
id?: string;
|
||
zombie: boolean;
|
||
stale?: boolean;
|
||
};
|
||
export declare class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature {
|
||
private logSerailNumber;
|
||
private cache;
|
||
private schema;
|
||
private root;
|
||
constructor(cache: Cache<ED>, schema: StorageSchema<ED>);
|
||
createNode<T extends keyof ED>(options: CreateNodeOptions<ED, T>, isPage: boolean): ListNode<ED, T> | SingleNode<ED, T> | VirtualNode<ED>;
|
||
private findNode;
|
||
destroyNode(path: string, isPage: boolean): void;
|
||
begin(): () => void;
|
||
getFreshValue(path: string): Partial<ED[keyof ED]["Schema"]> | Partial<ED[keyof ED]["Schema"]>[] | undefined;
|
||
isDirty(path: string): boolean;
|
||
addItem<T extends keyof ED>(path: string, data: Omit<ED[T]['CreateSingle']['data'], 'id'> & {
|
||
id?: string;
|
||
}): string;
|
||
addItems<T extends keyof ED>(path: string, data: Array<Omit<ED[T]['CreateSingle']['data'], 'id'> & {
|
||
id?: string;
|
||
}>): string[];
|
||
removeItem(path: string, id: string): void;
|
||
removeItems(path: string, ids: string[]): void;
|
||
updateItem<T extends keyof ED>(path: string, data: ED[T]['Update']['data'], id: string, action?: ED[T]['Action']): void;
|
||
updateItems<T extends keyof ED>(path: string, data: ED[T]['Update']['data'], ids: string[], action?: ED[T]['Action']): void;
|
||
recoverItem(path: string, id: string): void;
|
||
recoverItems(path: string, ids: string[]): void;
|
||
resetItem(path: string, id: string): void;
|
||
create<T extends keyof ED>(path: string, data: Omit<ED[T]['CreateSingle']['data'], 'id'>): void;
|
||
update<T extends keyof ED>(path: string, data: ED[T]['Update']['data'], action?: ED[T]['Action']): void;
|
||
remove(path: string): void;
|
||
isLoading(path: string): boolean | undefined;
|
||
isLoadingMore(path: string): boolean | undefined;
|
||
isExecuting(path: string): boolean;
|
||
isListChildOrStale(path: string): boolean;
|
||
private isInModiNextBranch;
|
||
refresh(path: string, pageNumber?: number, resetTotal?: boolean): Promise<void>;
|
||
loadMore(path: string): Promise<void>;
|
||
getPagination(path: string): Pagination;
|
||
setId(path: string, id: string): void;
|
||
unsetId(path: string): void;
|
||
getId(path: string): string | undefined;
|
||
getEntity(path: string): keyof ED;
|
||
setPageSize<T extends keyof ED>(path: string, pageSize: number): void;
|
||
setCurrentPage<T extends keyof ED>(path: string, currentPage: number): void;
|
||
getNamedFilters<T extends keyof ED>(path: string): (NamedFilterItem<ED, keyof ED> & {
|
||
applied?: boolean | undefined;
|
||
})[];
|
||
getNamedFilterByName<T extends keyof ED>(path: string, name: string): (NamedFilterItem<ED, keyof ED> & {
|
||
applied?: boolean | undefined;
|
||
}) | undefined;
|
||
setNamedFilters<T extends keyof ED>(path: string, filters: NamedFilterItem<ED, T>[], refresh?: boolean): void;
|
||
addNamedFilter<T extends keyof ED>(path: string, filter: NamedFilterItem<ED, T>, refresh?: boolean): void;
|
||
removeNamedFilter<T extends keyof ED>(path: string, filter: NamedFilterItem<ED, T>, refresh?: boolean): void;
|
||
removeNamedFilterByName<T extends keyof ED>(path: string, name: string, refresh?: boolean): void;
|
||
getNamedSorters<T extends keyof ED>(path: string): (NamedSorterItem<ED, keyof ED> & {
|
||
applied?: boolean | undefined;
|
||
})[];
|
||
getNamedSorterByName<T extends keyof ED>(path: string, name: string): (NamedSorterItem<ED, keyof ED> & {
|
||
applied?: boolean | undefined;
|
||
}) | undefined;
|
||
setNamedSorters<T extends keyof ED>(path: string, sorters: NamedSorterItem<ED, T>[], refresh?: boolean): void;
|
||
addNamedSorter<T extends keyof ED>(path: string, sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||
removeNamedSorter<T extends keyof ED>(path: string, sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||
removeNamedSorterByName(path: string, name: string, refresh?: boolean): void;
|
||
getIntrinsticFilters(path: string): ED[keyof ED]["Filter"] | undefined;
|
||
getOperations(path: string): {
|
||
entity: keyof ED;
|
||
operation: ED[keyof ED]["Operation"];
|
||
}[] | undefined;
|
||
private cachedOperations;
|
||
private cachedModis;
|
||
private invalidateCachedOperations;
|
||
private invalidateCachedModis;
|
||
/**
|
||
* 这个函数在reRender时可能会反复调用,composeOperations很消耗性能,在这里要做个缓存
|
||
* @param path
|
||
*/
|
||
redoBranchOperations(path: string): void;
|
||
/**
|
||
* 这个函数在reRender时可能会反复调用,getModiOperations很消耗性能,在这里要做个缓存
|
||
* @param path
|
||
*/
|
||
redoBranchModis(path: string): void;
|
||
execute<T extends keyof ED>(path?: string, action?: ED[T]['Action'], opers?: Array<{
|
||
entity: keyof ED;
|
||
operation: ED[keyof ED]['Operation'];
|
||
}>): Promise<{
|
||
result: import("oak-domain/lib/types").OperationResult<ED>[] | Awaited<import("oak-domain/lib/types").OperationResult<ED>>;
|
||
message: string | null | undefined;
|
||
} | {
|
||
message: string;
|
||
}>;
|
||
savePoint(): number;
|
||
/**
|
||
* 将path上的更新清除
|
||
* @param path
|
||
* @param lsn 要清除到某个指定的savepoint,不设则完全清空
|
||
* @param dontPublish
|
||
*/
|
||
clean(path: string, lsn?: number, dontPublish?: true): void;
|
||
getRoot(): Record<string, SingleNode<ED, keyof ED> | ListNode<ED, keyof ED> | VirtualNode<ED>>;
|
||
saveExtraData(path: string, key: string, data: any): void;
|
||
loadExtraData(path: string, key: string): any;
|
||
}
|
||
export {};
|