cache开启和关闭事务机制的再整理
This commit is contained in:
parent
e7ba378388
commit
7715cccca6
|
|
@ -119,7 +119,7 @@ export declare class Cache<ED extends EntityDict & BaseEntityDict, Cxt extends A
|
||||||
unbindOnSync(callback: (opRecords: OpRecord<ED>[]) => void): void;
|
unbindOnSync(callback: (opRecords: OpRecord<ED>[]) => void): void;
|
||||||
getCachedData(): { [T in keyof ED]?: ED[T]["OpSchema"][] | undefined; };
|
getCachedData(): { [T in keyof ED]?: ED[T]["OpSchema"][] | undefined; };
|
||||||
getFullData(): any;
|
getFullData(): any;
|
||||||
begin(): FrontCxt;
|
begin(allowExists?: boolean): FrontCxt | undefined;
|
||||||
commit(): void;
|
commit(): void;
|
||||||
rollback(): void;
|
rollback(): void;
|
||||||
getContext(): FrontCxt;
|
getContext(): FrontCxt;
|
||||||
|
|
|
||||||
|
|
@ -486,8 +486,13 @@ export class Cache extends Feature {
|
||||||
getFullData() {
|
getFullData() {
|
||||||
return this.getFullDataFn();
|
return this.getFullDataFn();
|
||||||
}
|
}
|
||||||
begin() {
|
begin(allowExists) {
|
||||||
assert(!this.context);
|
if (this.context) {
|
||||||
|
if (allowExists) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
this.context = this.contextBuilder();
|
this.context = this.contextBuilder();
|
||||||
this.context.begin();
|
this.context.begin();
|
||||||
return this.context;
|
return this.context;
|
||||||
|
|
|
||||||
|
|
@ -74,68 +74,74 @@ export class ContextMenuFactory extends Feature {
|
||||||
}
|
}
|
||||||
getMenusByContext(entity, entityId) {
|
getMenusByContext(entity, entityId) {
|
||||||
assert(this.menus, '应当先调用setMenus才能动态判定菜单');
|
assert(this.menus, '应当先调用setMenus才能动态判定菜单');
|
||||||
this.cache.begin();
|
const needRollback = !!this.cache.begin(true);
|
||||||
const menus = this.menus
|
try {
|
||||||
.filter((menu) => {
|
const menus = this.menus
|
||||||
const { entity: destEntity, paths, action } = menu;
|
.filter((menu) => {
|
||||||
// 如果没有关联在entity上,则默认显示,由页面自己处理用户权限
|
const { entity: destEntity, paths, action } = menu;
|
||||||
if (!destEntity || !paths) {
|
// 如果没有关联在entity上,则默认显示,由页面自己处理用户权限
|
||||||
return true;
|
if (!destEntity || !paths) {
|
||||||
}
|
|
||||||
assert(action);
|
|
||||||
const filters = paths && paths.length > 0
|
|
||||||
? this.makeMenuFilters(destEntity, paths, entity, entityId)
|
|
||||||
: [{}]; // 如果没有path,视为无法推断操作的filter,直接返回无任何限制
|
|
||||||
if (filters.length > 0) {
|
|
||||||
// 这里应该是or关系,paths表达的路径中只要有一条满足就可能满足
|
|
||||||
const allows = filters.map((filter) => {
|
|
||||||
if (filter === true) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// relationAuth和其它的checker现在分开判断
|
|
||||||
let result = false;
|
|
||||||
if (action instanceof Array) {
|
|
||||||
for (let i = 0; i < action.length; i++) {
|
|
||||||
// action有一个满足就行了
|
|
||||||
const checkResult = this.relationAuth.checkRelation(destEntity, {
|
|
||||||
action: action[i],
|
|
||||||
filter,
|
|
||||||
}) &&
|
|
||||||
this.cache.checkOperation(destEntity, {
|
|
||||||
action: action[i],
|
|
||||||
filter: filter,
|
|
||||||
}, [
|
|
||||||
'logical',
|
|
||||||
'row',
|
|
||||||
]);
|
|
||||||
if (checkResult) {
|
|
||||||
result = checkResult === true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return (this.relationAuth.checkRelation(destEntity, {
|
|
||||||
action,
|
|
||||||
filter,
|
|
||||||
}) &&
|
|
||||||
this.cache.checkOperation(destEntity, {
|
|
||||||
action,
|
|
||||||
filter: filter,
|
|
||||||
}, [
|
|
||||||
'logical',
|
|
||||||
'row',
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
if (allows.indexOf(true) >= 0) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
assert(action);
|
||||||
|
const filters = paths && paths.length > 0
|
||||||
|
? this.makeMenuFilters(destEntity, paths, entity, entityId)
|
||||||
|
: [{}]; // 如果没有path,视为无法推断操作的filter,直接返回无任何限制
|
||||||
|
if (filters.length > 0) {
|
||||||
|
// 这里应该是or关系,paths表达的路径中只要有一条满足就可能满足
|
||||||
|
const allows = filters.map((filter) => {
|
||||||
|
if (filter === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// relationAuth和其它的checker现在分开判断
|
||||||
|
let result = false;
|
||||||
|
if (action instanceof Array) {
|
||||||
|
for (let i = 0; i < action.length; i++) {
|
||||||
|
// action有一个满足就行了
|
||||||
|
const checkResult = this.relationAuth.checkRelation(destEntity, {
|
||||||
|
action: action[i],
|
||||||
|
filter,
|
||||||
|
}) &&
|
||||||
|
this.cache.checkOperation(destEntity, {
|
||||||
|
action: action[i],
|
||||||
|
filter: filter,
|
||||||
|
}, [
|
||||||
|
'logical',
|
||||||
|
'row',
|
||||||
|
]);
|
||||||
|
if (checkResult) {
|
||||||
|
result = checkResult === true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return (this.relationAuth.checkRelation(destEntity, {
|
||||||
|
action,
|
||||||
|
filter,
|
||||||
|
}) &&
|
||||||
|
this.cache.checkOperation(destEntity, {
|
||||||
|
action,
|
||||||
|
filter: filter,
|
||||||
|
}, [
|
||||||
|
'logical',
|
||||||
|
'row',
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
if (allows.indexOf(true) >= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
})
|
||||||
return false;
|
.map((wrapper) => omit(wrapper, ['filtersMaker']));
|
||||||
})
|
needRollback && this.cache.rollback();
|
||||||
.map((wrapper) => omit(wrapper, ['filtersMaker']));
|
return menus;
|
||||||
this.cache.rollback();
|
}
|
||||||
return menus;
|
catch (err) {
|
||||||
|
needRollback && this.cache.rollback();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -249,8 +249,7 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict, Cxt ext
|
||||||
checkIsModiNode(path: string): boolean;
|
checkIsModiNode(path: string): boolean;
|
||||||
private findNode;
|
private findNode;
|
||||||
destroyNode(path: string): void;
|
destroyNode(path: string): void;
|
||||||
redoBranchOperations(path: string): void;
|
redoBranchOperations(path: string): () => void;
|
||||||
rollbackRedoBranchOperations(): void;
|
|
||||||
getFreshValue(path: string): Partial<ED[keyof ED]["Schema"]> | Partial<ED[keyof ED]["Schema"]>[] | undefined;
|
getFreshValue(path: string): Partial<ED[keyof ED]["Schema"]> | Partial<ED[keyof ED]["Schema"]>[] | undefined;
|
||||||
isDirty(path: string): boolean;
|
isDirty(path: string): boolean;
|
||||||
addItem<T extends keyof ED>(path: string, data: Omit<ED[T]['CreateSingle']['data'], 'id'> & {
|
addItem<T extends keyof ED>(path: string, data: Omit<ED[T]['CreateSingle']['data'], 'id'> & {
|
||||||
|
|
|
||||||
|
|
@ -1656,18 +1656,19 @@ export class RunningTree extends Feature {
|
||||||
const paths = path.split('.');
|
const paths = path.split('.');
|
||||||
const root = this.root[paths[0]];
|
const root = this.root[paths[0]];
|
||||||
const opers = root.composeOperations();
|
const opers = root.composeOperations();
|
||||||
this.cache.begin();
|
const cxt = this.cache.begin();
|
||||||
if (opers) {
|
if (cxt) {
|
||||||
this.cache.redoOperation(opers);
|
if (opers) {
|
||||||
|
this.cache.redoOperation(opers);
|
||||||
|
}
|
||||||
|
const includeModi = path.includes(MODI_NEXT_PATH_SUFFIX);
|
||||||
|
if (includeModi) {
|
||||||
|
const modiOperations = (root instanceof SingleNode || root instanceof VirtualNode) && root.getModiOperations();
|
||||||
|
modiOperations && this.cache.redoOperation(modiOperations);
|
||||||
|
}
|
||||||
|
return () => this.cache.rollback();
|
||||||
}
|
}
|
||||||
const includeModi = path.includes(MODI_NEXT_PATH_SUFFIX);
|
return () => undefined;
|
||||||
if (includeModi) {
|
|
||||||
const modiOperations = (root instanceof SingleNode || root instanceof VirtualNode) && root.getModiOperations();
|
|
||||||
modiOperations && this.cache.redoOperation(modiOperations);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rollbackRedoBranchOperations() {
|
|
||||||
this.cache.rollback();
|
|
||||||
}
|
}
|
||||||
getFreshValue(path) {
|
getFreshValue(path) {
|
||||||
const node = this.findNode(path);
|
const node = this.findNode(path);
|
||||||
|
|
|
||||||
|
|
@ -405,7 +405,7 @@ export function reRender(option, extra) {
|
||||||
const localeState = features.locales.getState();
|
const localeState = features.locales.getState();
|
||||||
if (this.state.oakEntity && this.state.oakFullpath) {
|
if (this.state.oakEntity && this.state.oakFullpath) {
|
||||||
// 现在取数据需要把runningTree上的更新应用了再取,判定actions也一样
|
// 现在取数据需要把runningTree上的更新应用了再取,判定actions也一样
|
||||||
this.features.runningTree.redoBranchOperations(this.state.oakFullpath);
|
const cleanFn = this.features.runningTree.redoBranchOperations(this.state.oakFullpath);
|
||||||
try {
|
try {
|
||||||
const rows = this.features.runningTree.getFreshValue(this.state.oakFullpath);
|
const rows = this.features.runningTree.getFreshValue(this.state.oakFullpath);
|
||||||
const oakLegalActions = rows && checkActionsAndCascadeEntities.call(this, rows, option);
|
const oakLegalActions = rows && checkActionsAndCascadeEntities.call(this, rows, option);
|
||||||
|
|
@ -459,10 +459,10 @@ export function reRender(option, extra) {
|
||||||
Object.assign(data, extra);
|
Object.assign(data, extra);
|
||||||
}
|
}
|
||||||
this.setState(data);
|
this.setState(data);
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
cleanFn();
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
cleanFn();
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -188,10 +188,16 @@ const oakBehavior = Behavior({
|
||||||
const path2 = path
|
const path2 = path
|
||||||
? `${this.state.oakFullpath}.${path}`
|
? `${this.state.oakFullpath}.${path}`
|
||||||
: this.state.oakFullpath;
|
: this.state.oakFullpath;
|
||||||
this.features.runningTree.redoBranchOperations(path2);
|
const cleanFn = this.features.runningTree.redoBranchOperations(path2);
|
||||||
const value = this.features.runningTree.getFreshValue(path2);
|
try {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
const value = this.features.runningTree.getFreshValue(path2);
|
||||||
return value;
|
cleanFn();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cleanFn();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
checkOperation(entity, { action, data, filter }, checkerTypes) {
|
checkOperation(entity, { action, data, filter }, checkerTypes) {
|
||||||
if (checkerTypes?.includes('relation')) {
|
if (checkerTypes?.includes('relation')) {
|
||||||
|
|
@ -459,11 +465,17 @@ const oakBehavior = Behavior({
|
||||||
const path2 = path
|
const path2 = path
|
||||||
? `${this.state.oakFullpath}.${path}`
|
? `${this.state.oakFullpath}.${path}`
|
||||||
: this.state.oakFullpath;
|
: this.state.oakFullpath;
|
||||||
this.features.runningTree.redoBranchOperations(path2);
|
const cleanFn = this.features.runningTree.redoBranchOperations(path2);
|
||||||
const value = this.features.runningTree.getFreshValue(path2);
|
try {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
const value = this.features.runningTree.getFreshValue(path2);
|
||||||
assert(!(value instanceof Array));
|
assert(!(value instanceof Array));
|
||||||
return value?.$$createAt$$ === 1;
|
cleanFn();
|
||||||
|
return value?.$$createAt$$ === 1;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cleanFn();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async aggregate(aggregation) {
|
async aggregate(aggregation) {
|
||||||
return await this.features.cache.aggregate(this.state.oakEntity, aggregation);
|
return await this.features.cache.aggregate(this.state.oakEntity, aggregation);
|
||||||
|
|
|
||||||
|
|
@ -151,11 +151,17 @@ class OakComponentBase extends React.PureComponent {
|
||||||
const path2 = path
|
const path2 = path
|
||||||
? `${this.state.oakFullpath}.${path}`
|
? `${this.state.oakFullpath}.${path}`
|
||||||
: this.state.oakFullpath;
|
: this.state.oakFullpath;
|
||||||
this.features.runningTree.redoBranchOperations(path2);
|
const cleanFn = this.features.runningTree.redoBranchOperations(path2);
|
||||||
const value = this.features.runningTree.getFreshValue(path2);
|
try {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
const value = this.features.runningTree.getFreshValue(path2);
|
||||||
assert(!(value instanceof Array));
|
assert(!(value instanceof Array));
|
||||||
return value?.$$createAt$$ === 1;
|
cleanFn();
|
||||||
|
return value?.$$createAt$$ === 1;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cleanFn();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
clean(path) {
|
clean(path) {
|
||||||
const path2 = path
|
const path2 = path
|
||||||
|
|
@ -176,10 +182,16 @@ class OakComponentBase extends React.PureComponent {
|
||||||
const path2 = path
|
const path2 = path
|
||||||
? `${this.state.oakFullpath}.${path}`
|
? `${this.state.oakFullpath}.${path}`
|
||||||
: this.state.oakFullpath;
|
: this.state.oakFullpath;
|
||||||
this.features.runningTree.redoBranchOperations(path2);
|
const cleanFn = this.features.runningTree.redoBranchOperations(path2);
|
||||||
const value = this.features.runningTree.getFreshValue(path2);
|
try {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
const value = this.features.runningTree.getFreshValue(path2);
|
||||||
return value;
|
cleanFn();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cleanFn();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
checkOperation(entity, operation, checkerTypes) {
|
checkOperation(entity, operation, checkerTypes) {
|
||||||
if (checkerTypes?.includes('relation')) {
|
if (checkerTypes?.includes('relation')) {
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ export declare class Cache<ED extends EntityDict & BaseEntityDict, Cxt extends A
|
||||||
unbindOnSync(callback: (opRecords: OpRecord<ED>[]) => void): void;
|
unbindOnSync(callback: (opRecords: OpRecord<ED>[]) => void): void;
|
||||||
getCachedData(): { [T in keyof ED]?: ED[T]["OpSchema"][] | undefined; };
|
getCachedData(): { [T in keyof ED]?: ED[T]["OpSchema"][] | undefined; };
|
||||||
getFullData(): any;
|
getFullData(): any;
|
||||||
begin(): FrontCxt;
|
begin(allowExists?: boolean): FrontCxt | undefined;
|
||||||
commit(): void;
|
commit(): void;
|
||||||
rollback(): void;
|
rollback(): void;
|
||||||
getContext(): FrontCxt;
|
getContext(): FrontCxt;
|
||||||
|
|
|
||||||
|
|
@ -489,8 +489,13 @@ class Cache extends Feature_1.Feature {
|
||||||
getFullData() {
|
getFullData() {
|
||||||
return this.getFullDataFn();
|
return this.getFullDataFn();
|
||||||
}
|
}
|
||||||
begin() {
|
begin(allowExists) {
|
||||||
(0, assert_1.assert)(!this.context);
|
if (this.context) {
|
||||||
|
if (allowExists) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(0, assert_1.assert)(false);
|
||||||
|
}
|
||||||
this.context = this.contextBuilder();
|
this.context = this.contextBuilder();
|
||||||
this.context.begin();
|
this.context.begin();
|
||||||
return this.context;
|
return this.context;
|
||||||
|
|
|
||||||
|
|
@ -77,69 +77,75 @@ class ContextMenuFactory extends Feature_1.Feature {
|
||||||
}
|
}
|
||||||
getMenusByContext(entity, entityId) {
|
getMenusByContext(entity, entityId) {
|
||||||
(0, assert_1.assert)(this.menus, '应当先调用setMenus才能动态判定菜单');
|
(0, assert_1.assert)(this.menus, '应当先调用setMenus才能动态判定菜单');
|
||||||
this.cache.begin();
|
const needRollback = !!this.cache.begin(true);
|
||||||
const menus = this.menus
|
try {
|
||||||
.filter((menu) => {
|
const menus = this.menus
|
||||||
const { entity: destEntity, paths, action } = menu;
|
.filter((menu) => {
|
||||||
// 如果没有关联在entity上,则默认显示,由页面自己处理用户权限
|
const { entity: destEntity, paths, action } = menu;
|
||||||
if (!destEntity || !paths) {
|
// 如果没有关联在entity上,则默认显示,由页面自己处理用户权限
|
||||||
return true;
|
if (!destEntity || !paths) {
|
||||||
}
|
|
||||||
(0, assert_1.assert)(action);
|
|
||||||
const filters = paths && paths.length > 0
|
|
||||||
? this.makeMenuFilters(destEntity, paths, entity, entityId)
|
|
||||||
: [{}]; // 如果没有path,视为无法推断操作的filter,直接返回无任何限制
|
|
||||||
if (filters.length > 0) {
|
|
||||||
// 这里应该是or关系,paths表达的路径中只要有一条满足就可能满足
|
|
||||||
const allows = filters.map((filter) => {
|
|
||||||
if (filter === true) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// relationAuth和其它的checker现在分开判断
|
|
||||||
let result = false;
|
|
||||||
if (action instanceof Array) {
|
|
||||||
for (let i = 0; i < action.length; i++) {
|
|
||||||
// action有一个满足就行了
|
|
||||||
const checkResult = this.relationAuth.checkRelation(destEntity, {
|
|
||||||
action: action[i],
|
|
||||||
filter,
|
|
||||||
}) &&
|
|
||||||
this.cache.checkOperation(destEntity, {
|
|
||||||
action: action[i],
|
|
||||||
filter: filter,
|
|
||||||
}, [
|
|
||||||
'logical',
|
|
||||||
'row',
|
|
||||||
]);
|
|
||||||
if (checkResult) {
|
|
||||||
result = checkResult === true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return (this.relationAuth.checkRelation(destEntity, {
|
|
||||||
action,
|
|
||||||
filter,
|
|
||||||
}) &&
|
|
||||||
this.cache.checkOperation(destEntity, {
|
|
||||||
action,
|
|
||||||
filter: filter,
|
|
||||||
}, [
|
|
||||||
'logical',
|
|
||||||
'row',
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
if (allows.indexOf(true) >= 0) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
(0, assert_1.assert)(action);
|
||||||
|
const filters = paths && paths.length > 0
|
||||||
|
? this.makeMenuFilters(destEntity, paths, entity, entityId)
|
||||||
|
: [{}]; // 如果没有path,视为无法推断操作的filter,直接返回无任何限制
|
||||||
|
if (filters.length > 0) {
|
||||||
|
// 这里应该是or关系,paths表达的路径中只要有一条满足就可能满足
|
||||||
|
const allows = filters.map((filter) => {
|
||||||
|
if (filter === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// relationAuth和其它的checker现在分开判断
|
||||||
|
let result = false;
|
||||||
|
if (action instanceof Array) {
|
||||||
|
for (let i = 0; i < action.length; i++) {
|
||||||
|
// action有一个满足就行了
|
||||||
|
const checkResult = this.relationAuth.checkRelation(destEntity, {
|
||||||
|
action: action[i],
|
||||||
|
filter,
|
||||||
|
}) &&
|
||||||
|
this.cache.checkOperation(destEntity, {
|
||||||
|
action: action[i],
|
||||||
|
filter: filter,
|
||||||
|
}, [
|
||||||
|
'logical',
|
||||||
|
'row',
|
||||||
|
]);
|
||||||
|
if (checkResult) {
|
||||||
|
result = checkResult === true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return (this.relationAuth.checkRelation(destEntity, {
|
||||||
|
action,
|
||||||
|
filter,
|
||||||
|
}) &&
|
||||||
|
this.cache.checkOperation(destEntity, {
|
||||||
|
action,
|
||||||
|
filter: filter,
|
||||||
|
}, [
|
||||||
|
'logical',
|
||||||
|
'row',
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
if (allows.indexOf(true) >= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
})
|
||||||
return false;
|
.map((wrapper) => (0, lodash_1.omit)(wrapper, ['filtersMaker']));
|
||||||
})
|
needRollback && this.cache.rollback();
|
||||||
.map((wrapper) => (0, lodash_1.omit)(wrapper, ['filtersMaker']));
|
return menus;
|
||||||
this.cache.rollback();
|
}
|
||||||
return menus;
|
catch (err) {
|
||||||
|
needRollback && this.cache.rollback();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.ContextMenuFactory = ContextMenuFactory;
|
exports.ContextMenuFactory = ContextMenuFactory;
|
||||||
|
|
|
||||||
|
|
@ -249,8 +249,7 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict, Cxt ext
|
||||||
checkIsModiNode(path: string): boolean;
|
checkIsModiNode(path: string): boolean;
|
||||||
private findNode;
|
private findNode;
|
||||||
destroyNode(path: string): void;
|
destroyNode(path: string): void;
|
||||||
redoBranchOperations(path: string): void;
|
redoBranchOperations(path: string): () => void;
|
||||||
rollbackRedoBranchOperations(): void;
|
|
||||||
getFreshValue(path: string): Partial<ED[keyof ED]["Schema"]> | Partial<ED[keyof ED]["Schema"]>[] | undefined;
|
getFreshValue(path: string): Partial<ED[keyof ED]["Schema"]> | Partial<ED[keyof ED]["Schema"]>[] | undefined;
|
||||||
isDirty(path: string): boolean;
|
isDirty(path: string): boolean;
|
||||||
addItem<T extends keyof ED>(path: string, data: Omit<ED[T]['CreateSingle']['data'], 'id'> & {
|
addItem<T extends keyof ED>(path: string, data: Omit<ED[T]['CreateSingle']['data'], 'id'> & {
|
||||||
|
|
|
||||||
|
|
@ -1659,18 +1659,19 @@ class RunningTree extends Feature_1.Feature {
|
||||||
const paths = path.split('.');
|
const paths = path.split('.');
|
||||||
const root = this.root[paths[0]];
|
const root = this.root[paths[0]];
|
||||||
const opers = root.composeOperations();
|
const opers = root.composeOperations();
|
||||||
this.cache.begin();
|
const cxt = this.cache.begin();
|
||||||
if (opers) {
|
if (cxt) {
|
||||||
this.cache.redoOperation(opers);
|
if (opers) {
|
||||||
|
this.cache.redoOperation(opers);
|
||||||
|
}
|
||||||
|
const includeModi = path.includes(exports.MODI_NEXT_PATH_SUFFIX);
|
||||||
|
if (includeModi) {
|
||||||
|
const modiOperations = (root instanceof SingleNode || root instanceof VirtualNode) && root.getModiOperations();
|
||||||
|
modiOperations && this.cache.redoOperation(modiOperations);
|
||||||
|
}
|
||||||
|
return () => this.cache.rollback();
|
||||||
}
|
}
|
||||||
const includeModi = path.includes(exports.MODI_NEXT_PATH_SUFFIX);
|
return () => undefined;
|
||||||
if (includeModi) {
|
|
||||||
const modiOperations = (root instanceof SingleNode || root instanceof VirtualNode) && root.getModiOperations();
|
|
||||||
modiOperations && this.cache.redoOperation(modiOperations);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rollbackRedoBranchOperations() {
|
|
||||||
this.cache.rollback();
|
|
||||||
}
|
}
|
||||||
getFreshValue(path) {
|
getFreshValue(path) {
|
||||||
const node = this.findNode(path);
|
const node = this.findNode(path);
|
||||||
|
|
|
||||||
|
|
@ -409,7 +409,7 @@ function reRender(option, extra) {
|
||||||
const localeState = features.locales.getState();
|
const localeState = features.locales.getState();
|
||||||
if (this.state.oakEntity && this.state.oakFullpath) {
|
if (this.state.oakEntity && this.state.oakFullpath) {
|
||||||
// 现在取数据需要把runningTree上的更新应用了再取,判定actions也一样
|
// 现在取数据需要把runningTree上的更新应用了再取,判定actions也一样
|
||||||
this.features.runningTree.redoBranchOperations(this.state.oakFullpath);
|
const cleanFn = this.features.runningTree.redoBranchOperations(this.state.oakFullpath);
|
||||||
try {
|
try {
|
||||||
const rows = this.features.runningTree.getFreshValue(this.state.oakFullpath);
|
const rows = this.features.runningTree.getFreshValue(this.state.oakFullpath);
|
||||||
const oakLegalActions = rows && checkActionsAndCascadeEntities.call(this, rows, option);
|
const oakLegalActions = rows && checkActionsAndCascadeEntities.call(this, rows, option);
|
||||||
|
|
@ -463,10 +463,10 @@ function reRender(option, extra) {
|
||||||
Object.assign(data, extra);
|
Object.assign(data, extra);
|
||||||
}
|
}
|
||||||
this.setState(data);
|
this.setState(data);
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
cleanFn();
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
cleanFn();
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -191,10 +191,16 @@ const oakBehavior = Behavior({
|
||||||
const path2 = path
|
const path2 = path
|
||||||
? `${this.state.oakFullpath}.${path}`
|
? `${this.state.oakFullpath}.${path}`
|
||||||
: this.state.oakFullpath;
|
: this.state.oakFullpath;
|
||||||
this.features.runningTree.redoBranchOperations(path2);
|
const cleanFn = this.features.runningTree.redoBranchOperations(path2);
|
||||||
const value = this.features.runningTree.getFreshValue(path2);
|
try {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
const value = this.features.runningTree.getFreshValue(path2);
|
||||||
return value;
|
cleanFn();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cleanFn();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
checkOperation(entity, { action, data, filter }, checkerTypes) {
|
checkOperation(entity, { action, data, filter }, checkerTypes) {
|
||||||
if (checkerTypes?.includes('relation')) {
|
if (checkerTypes?.includes('relation')) {
|
||||||
|
|
@ -462,11 +468,17 @@ const oakBehavior = Behavior({
|
||||||
const path2 = path
|
const path2 = path
|
||||||
? `${this.state.oakFullpath}.${path}`
|
? `${this.state.oakFullpath}.${path}`
|
||||||
: this.state.oakFullpath;
|
: this.state.oakFullpath;
|
||||||
this.features.runningTree.redoBranchOperations(path2);
|
const cleanFn = this.features.runningTree.redoBranchOperations(path2);
|
||||||
const value = this.features.runningTree.getFreshValue(path2);
|
try {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
const value = this.features.runningTree.getFreshValue(path2);
|
||||||
(0, assert_1.assert)(!(value instanceof Array));
|
(0, assert_1.assert)(!(value instanceof Array));
|
||||||
return value?.$$createAt$$ === 1;
|
cleanFn();
|
||||||
|
return value?.$$createAt$$ === 1;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cleanFn();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async aggregate(aggregation) {
|
async aggregate(aggregation) {
|
||||||
return await this.features.cache.aggregate(this.state.oakEntity, aggregation);
|
return await this.features.cache.aggregate(this.state.oakEntity, aggregation);
|
||||||
|
|
|
||||||
|
|
@ -156,11 +156,17 @@ class OakComponentBase extends react_1.default.PureComponent {
|
||||||
const path2 = path
|
const path2 = path
|
||||||
? `${this.state.oakFullpath}.${path}`
|
? `${this.state.oakFullpath}.${path}`
|
||||||
: this.state.oakFullpath;
|
: this.state.oakFullpath;
|
||||||
this.features.runningTree.redoBranchOperations(path2);
|
const cleanFn = this.features.runningTree.redoBranchOperations(path2);
|
||||||
const value = this.features.runningTree.getFreshValue(path2);
|
try {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
const value = this.features.runningTree.getFreshValue(path2);
|
||||||
(0, assert_1.assert)(!(value instanceof Array));
|
(0, assert_1.assert)(!(value instanceof Array));
|
||||||
return value?.$$createAt$$ === 1;
|
cleanFn();
|
||||||
|
return value?.$$createAt$$ === 1;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cleanFn();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
clean(path) {
|
clean(path) {
|
||||||
const path2 = path
|
const path2 = path
|
||||||
|
|
@ -181,10 +187,16 @@ class OakComponentBase extends react_1.default.PureComponent {
|
||||||
const path2 = path
|
const path2 = path
|
||||||
? `${this.state.oakFullpath}.${path}`
|
? `${this.state.oakFullpath}.${path}`
|
||||||
: this.state.oakFullpath;
|
: this.state.oakFullpath;
|
||||||
this.features.runningTree.redoBranchOperations(path2);
|
const cleanFn = this.features.runningTree.redoBranchOperations(path2);
|
||||||
const value = this.features.runningTree.getFreshValue(path2);
|
try {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
const value = this.features.runningTree.getFreshValue(path2);
|
||||||
return value;
|
cleanFn();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cleanFn();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
checkOperation(entity, operation, checkerTypes) {
|
checkOperation(entity, operation, checkerTypes) {
|
||||||
if (checkerTypes?.includes('relation')) {
|
if (checkerTypes?.includes('relation')) {
|
||||||
|
|
|
||||||
|
|
@ -655,8 +655,13 @@ export class Cache<
|
||||||
return this.getFullDataFn();
|
return this.getFullDataFn();
|
||||||
}
|
}
|
||||||
|
|
||||||
begin() {
|
begin(allowExists?: boolean) {
|
||||||
assert(!this.context);
|
if (this.context) {
|
||||||
|
if (allowExists) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
this.context = this.contextBuilder!();
|
this.context = this.contextBuilder!();
|
||||||
this.context.begin();
|
this.context.begin();
|
||||||
return this.context;
|
return this.context;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ export class ContextMenuFactory<
|
||||||
Cxt extends AsyncContext<ED>,
|
Cxt extends AsyncContext<ED>,
|
||||||
FrontCxt extends SyncContext<ED>,
|
FrontCxt extends SyncContext<ED>,
|
||||||
AD extends CommonAspectDict<ED, Cxt> & Record<string, Aspect<ED, Cxt>>
|
AD extends CommonAspectDict<ED, Cxt> & Record<string, Aspect<ED, Cxt>>
|
||||||
> extends Feature {
|
> extends Feature {
|
||||||
cache: Cache<ED, Cxt, FrontCxt, AD>;
|
cache: Cache<ED, Cxt, FrontCxt, AD>;
|
||||||
menus?: IMenu<ED, keyof ED>[];
|
menus?: IMenu<ED, keyof ED>[];
|
||||||
relationAuth: RelationAuth<ED, Cxt, FrontCxt, AD>;
|
relationAuth: RelationAuth<ED, Cxt, FrontCxt, AD>;
|
||||||
|
|
@ -122,93 +122,99 @@ export class ContextMenuFactory<
|
||||||
entityId: string
|
entityId: string
|
||||||
) {
|
) {
|
||||||
assert(this.menus, '应当先调用setMenus才能动态判定菜单');
|
assert(this.menus, '应当先调用setMenus才能动态判定菜单');
|
||||||
this.cache.begin();
|
const needRollback = !!this.cache.begin(true);
|
||||||
const menus = this.menus
|
try {
|
||||||
.filter((menu) => {
|
const menus = this.menus
|
||||||
const { entity: destEntity, paths, action } = menu;
|
.filter((menu) => {
|
||||||
// 如果没有关联在entity上,则默认显示,由页面自己处理用户权限
|
const { entity: destEntity, paths, action } = menu;
|
||||||
if (!destEntity || !paths) {
|
// 如果没有关联在entity上,则默认显示,由页面自己处理用户权限
|
||||||
return true;
|
if (!destEntity || !paths) {
|
||||||
}
|
|
||||||
assert(action);
|
|
||||||
const filters =
|
|
||||||
paths && paths.length > 0
|
|
||||||
? this.makeMenuFilters(
|
|
||||||
destEntity!,
|
|
||||||
paths!,
|
|
||||||
entity,
|
|
||||||
entityId
|
|
||||||
)
|
|
||||||
: [{}]; // 如果没有path,视为无法推断操作的filter,直接返回无任何限制
|
|
||||||
if (filters.length > 0) {
|
|
||||||
// 这里应该是or关系,paths表达的路径中只要有一条满足就可能满足
|
|
||||||
const allows = filters.map((filter) => {
|
|
||||||
if (filter === true) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// relationAuth和其它的checker现在分开判断
|
|
||||||
let result = false;
|
|
||||||
if (action instanceof Array) {
|
|
||||||
for (let i = 0; i < action.length; i++) {
|
|
||||||
// action有一个满足就行了
|
|
||||||
const checkResult =
|
|
||||||
this.relationAuth.checkRelation(
|
|
||||||
destEntity,
|
|
||||||
{
|
|
||||||
action: action[i],
|
|
||||||
filter,
|
|
||||||
} as Omit<
|
|
||||||
ED[keyof ED]['Operation'],
|
|
||||||
'id'
|
|
||||||
>
|
|
||||||
) &&
|
|
||||||
this.cache.checkOperation(
|
|
||||||
destEntity,
|
|
||||||
{
|
|
||||||
action: action[i],
|
|
||||||
filter: filter,
|
|
||||||
} as Omit<ED[keyof ED]['Operation'], 'id'>,
|
|
||||||
[
|
|
||||||
'logical',
|
|
||||||
'row',
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (checkResult) {
|
|
||||||
result = checkResult === true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
this.relationAuth.checkRelation(destEntity, {
|
|
||||||
action,
|
|
||||||
filter,
|
|
||||||
} as Omit<ED[keyof ED]['Operation'], 'id'>) &&
|
|
||||||
this.cache.checkOperation(
|
|
||||||
destEntity,
|
|
||||||
{
|
|
||||||
action,
|
|
||||||
filter: filter,
|
|
||||||
} as Omit<ED[keyof ED]['Operation'], 'id'>,
|
|
||||||
[
|
|
||||||
'logical',
|
|
||||||
'row',
|
|
||||||
]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
if (allows.indexOf(true) >= 0) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
assert(action);
|
||||||
}
|
const filters =
|
||||||
return false;
|
paths && paths.length > 0
|
||||||
})
|
? this.makeMenuFilters(
|
||||||
.map((wrapper) => omit(wrapper, ['filtersMaker'])) as OMenu[];
|
destEntity!,
|
||||||
this.cache.rollback();
|
paths!,
|
||||||
|
entity,
|
||||||
|
entityId
|
||||||
|
)
|
||||||
|
: [{}]; // 如果没有path,视为无法推断操作的filter,直接返回无任何限制
|
||||||
|
if (filters.length > 0) {
|
||||||
|
// 这里应该是or关系,paths表达的路径中只要有一条满足就可能满足
|
||||||
|
const allows = filters.map((filter) => {
|
||||||
|
if (filter === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// relationAuth和其它的checker现在分开判断
|
||||||
|
let result = false;
|
||||||
|
if (action instanceof Array) {
|
||||||
|
for (let i = 0; i < action.length; i++) {
|
||||||
|
// action有一个满足就行了
|
||||||
|
const checkResult =
|
||||||
|
this.relationAuth.checkRelation(
|
||||||
|
destEntity,
|
||||||
|
{
|
||||||
|
action: action[i],
|
||||||
|
filter,
|
||||||
|
} as Omit<
|
||||||
|
ED[keyof ED]['Operation'],
|
||||||
|
'id'
|
||||||
|
>
|
||||||
|
) &&
|
||||||
|
this.cache.checkOperation(
|
||||||
|
destEntity,
|
||||||
|
{
|
||||||
|
action: action[i],
|
||||||
|
filter: filter,
|
||||||
|
} as Omit<ED[keyof ED]['Operation'], 'id'>,
|
||||||
|
[
|
||||||
|
'logical',
|
||||||
|
'row',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
return menus;
|
if (checkResult) {
|
||||||
|
result = checkResult === true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
this.relationAuth.checkRelation(destEntity, {
|
||||||
|
action,
|
||||||
|
filter,
|
||||||
|
} as Omit<ED[keyof ED]['Operation'], 'id'>) &&
|
||||||
|
this.cache.checkOperation(
|
||||||
|
destEntity,
|
||||||
|
{
|
||||||
|
action,
|
||||||
|
filter: filter,
|
||||||
|
} as Omit<ED[keyof ED]['Operation'], 'id'>,
|
||||||
|
[
|
||||||
|
'logical',
|
||||||
|
'row',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
if (allows.indexOf(true) >= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
.map((wrapper) => omit(wrapper, ['filtersMaker'])) as OMenu[];
|
||||||
|
needRollback && this.cache.rollback();
|
||||||
|
|
||||||
|
return menus;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
needRollback && this.cache.rollback();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ class ListNode<
|
||||||
case 'c': {
|
case 'c': {
|
||||||
const { e, d } = record as CreateOpResult<ED, T>;
|
const { e, d } = record as CreateOpResult<ED, T>;
|
||||||
if (e === this.entity) {
|
if (e === this.entity) {
|
||||||
const context = this.cache.begin();
|
const context = this.cache.begin()!;
|
||||||
const { filter } = this.constructSelection();
|
const { filter } = this.constructSelection();
|
||||||
if (d instanceof Array) {
|
if (d instanceof Array) {
|
||||||
d.forEach(
|
d.forEach(
|
||||||
|
|
@ -276,7 +276,7 @@ class ListNode<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const context = this.cache.begin();
|
const context = this.cache.begin()!;
|
||||||
for (const id in this.sr) {
|
for (const id in this.sr) {
|
||||||
if (!f || checkFilterContains<ED, T, FrontCxt>(e, context, f, { id }, true)) {
|
if (!f || checkFilterContains<ED, T, FrontCxt>(e, context, f, { id }, true)) {
|
||||||
unset(this.sr, id);
|
unset(this.sr, id);
|
||||||
|
|
@ -625,7 +625,7 @@ class ListNode<
|
||||||
private removeItemInner(id: string) {
|
private removeItemInner(id: string) {
|
||||||
if (this.updates[id] && this.updates[id].action === 'create') {
|
if (this.updates[id] && this.updates[id].action === 'create') {
|
||||||
// 如果是新增项,在这里抵消
|
// 如果是新增项,在这里抵消
|
||||||
unset(this.updates, id);
|
unset(this.updates, id);
|
||||||
} else {
|
} else {
|
||||||
this.updates[id] = {
|
this.updates[id] = {
|
||||||
id: generateNewId(),
|
id: generateNewId(),
|
||||||
|
|
@ -1012,7 +1012,7 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getModiOperations(): Array<{
|
getModiOperations(): Array<{
|
||||||
entity: keyof ED;
|
entity: keyof ED;
|
||||||
operation: ED[keyof ED]['Operation'];
|
operation: ED[keyof ED]['Operation'];
|
||||||
|
|
@ -2023,20 +2023,21 @@ export class RunningTree<
|
||||||
const root = this.root[paths[0]];
|
const root = this.root[paths[0]];
|
||||||
const opers = root.composeOperations();
|
const opers = root.composeOperations();
|
||||||
|
|
||||||
this.cache.begin();
|
const cxt = this.cache.begin();
|
||||||
if (opers) {
|
if (cxt) {
|
||||||
this.cache.redoOperation(opers);
|
if (opers) {
|
||||||
}
|
this.cache.redoOperation(opers);
|
||||||
|
}
|
||||||
const includeModi = path.includes(MODI_NEXT_PATH_SUFFIX);
|
|
||||||
if (includeModi) {
|
|
||||||
const modiOperations = (root instanceof SingleNode || root instanceof VirtualNode) && root.getModiOperations();
|
|
||||||
modiOperations && this.cache.redoOperation(modiOperations);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rollbackRedoBranchOperations() {
|
const includeModi = path.includes(MODI_NEXT_PATH_SUFFIX);
|
||||||
this.cache.rollback();
|
if (includeModi) {
|
||||||
|
const modiOperations = (root instanceof SingleNode || root instanceof VirtualNode) && root.getModiOperations();
|
||||||
|
modiOperations && this.cache.redoOperation(modiOperations);
|
||||||
|
}
|
||||||
|
return () => this.cache.rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFreshValue(path: string) {
|
getFreshValue(path: string) {
|
||||||
|
|
|
||||||
|
|
@ -505,7 +505,7 @@ export function reRender<
|
||||||
const localeState = features.locales.getState();
|
const localeState = features.locales.getState();
|
||||||
if (this.state.oakEntity && this.state.oakFullpath) {
|
if (this.state.oakEntity && this.state.oakFullpath) {
|
||||||
// 现在取数据需要把runningTree上的更新应用了再取,判定actions也一样
|
// 现在取数据需要把runningTree上的更新应用了再取,判定actions也一样
|
||||||
this.features.runningTree.redoBranchOperations(this.state.oakFullpath);
|
const cleanFn = this.features.runningTree.redoBranchOperations(this.state.oakFullpath);
|
||||||
try {
|
try {
|
||||||
const rows = this.features.runningTree.getFreshValue(this.state.oakFullpath);
|
const rows = this.features.runningTree.getFreshValue(this.state.oakFullpath);
|
||||||
const oakLegalActions = rows && checkActionsAndCascadeEntities.call(
|
const oakLegalActions = rows && checkActionsAndCascadeEntities.call(
|
||||||
|
|
@ -570,10 +570,10 @@ export function reRender<
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState(data);
|
this.setState(data);
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
cleanFn();
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
cleanFn();
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -322,10 +322,16 @@ const oakBehavior = Behavior<
|
||||||
const path2 = path
|
const path2 = path
|
||||||
? `${this.state.oakFullpath}.${path}`
|
? `${this.state.oakFullpath}.${path}`
|
||||||
: this.state.oakFullpath;
|
: this.state.oakFullpath;
|
||||||
this.features.runningTree.redoBranchOperations(path2);
|
const cleanFn = this.features.runningTree.redoBranchOperations(path2);
|
||||||
const value = this.features.runningTree.getFreshValue(path2);
|
try {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
const value = this.features.runningTree.getFreshValue(path2);
|
||||||
return value;
|
cleanFn();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cleanFn();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
checkOperation(entity, { action, data, filter }, checkerTypes) {
|
checkOperation(entity, { action, data, filter }, checkerTypes) {
|
||||||
|
|
@ -675,11 +681,17 @@ const oakBehavior = Behavior<
|
||||||
const path2 = path
|
const path2 = path
|
||||||
? `${this.state.oakFullpath}.${path}`
|
? `${this.state.oakFullpath}.${path}`
|
||||||
: this.state.oakFullpath;
|
: this.state.oakFullpath;
|
||||||
this.features.runningTree.redoBranchOperations(path2);
|
const cleanFn = this.features.runningTree.redoBranchOperations(path2);
|
||||||
const value = this.features.runningTree.getFreshValue(path2);
|
try {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
const value = this.features.runningTree.getFreshValue(path2);
|
||||||
assert(!(value instanceof Array));
|
assert(!(value instanceof Array));
|
||||||
return value?.$$createAt$$ === 1;
|
cleanFn();
|
||||||
|
return value?.$$createAt$$ === 1;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cleanFn();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async aggregate(aggregation) {
|
async aggregate(aggregation) {
|
||||||
|
|
|
||||||
|
|
@ -304,11 +304,17 @@ abstract class OakComponentBase<
|
||||||
const path2 = path
|
const path2 = path
|
||||||
? `${this.state.oakFullpath}.${path}`
|
? `${this.state.oakFullpath}.${path}`
|
||||||
: this.state.oakFullpath;
|
: this.state.oakFullpath;
|
||||||
this.features.runningTree.redoBranchOperations(path2);
|
const cleanFn = this.features.runningTree.redoBranchOperations(path2);
|
||||||
const value = this.features.runningTree.getFreshValue(path2);
|
try {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
const value = this.features.runningTree.getFreshValue(path2);
|
||||||
assert(!(value instanceof Array));
|
assert(!(value instanceof Array));
|
||||||
return value?.$$createAt$$ === 1;
|
cleanFn();
|
||||||
|
return value?.$$createAt$$ === 1;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cleanFn();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clean(path?: string) {
|
clean(path?: string) {
|
||||||
|
|
@ -338,10 +344,16 @@ abstract class OakComponentBase<
|
||||||
? `${this.state.oakFullpath}.${path}`
|
? `${this.state.oakFullpath}.${path}`
|
||||||
: this.state.oakFullpath;
|
: this.state.oakFullpath;
|
||||||
|
|
||||||
this.features.runningTree.redoBranchOperations(path2);
|
const cleanFn = this.features.runningTree.redoBranchOperations(path2);
|
||||||
const value = this.features.runningTree.getFreshValue(path2);
|
try {
|
||||||
this.features.runningTree.rollbackRedoBranchOperations();
|
const value = this.features.runningTree.getFreshValue(path2);
|
||||||
return value;
|
cleanFn();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
cleanFn();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkOperation<T2 extends keyof ED>(
|
checkOperation<T2 extends keyof ED>(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue