Merge branch 'release'
This commit is contained in:
commit
b3de5cb62c
|
|
@ -1,5 +1,5 @@
|
||||||
import { CascadeRelationItem, RelationHierarchy } from "../types/Entity";
|
import { CascadeRelationItem, RelationHierarchy, EntityDict } from "../types/Entity";
|
||||||
export declare type GenericRelation = 'owner';
|
export declare type GenericRelation = 'owner';
|
||||||
export declare function convertHierarchyToAuth<R extends string>(hierarchy: RelationHierarchy<R>): {
|
export declare function convertHierarchyToAuth<ED extends EntityDict, T extends keyof ED>(entity: T, hierarchy: RelationHierarchy<NonNullable<ED[T]['Relation']>>): {
|
||||||
[K in R]?: CascadeRelationItem;
|
[K in NonNullable<ED[T]['Relation']>]?: CascadeRelationItem;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.convertHierarchyToAuth = void 0;
|
exports.convertHierarchyToAuth = void 0;
|
||||||
var tslib_1 = require("tslib");
|
var tslib_1 = require("tslib");
|
||||||
function convertHierarchyToAuth(hierarchy) {
|
function convertHierarchyToAuth(entity, hierarchy) {
|
||||||
var e_1, _a;
|
var e_1, _a;
|
||||||
var _b;
|
var _b;
|
||||||
var reverseHierarchy = {};
|
var reverseHierarchy = {};
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ var modi_1 = require("../store/modi");
|
||||||
function createDynamicCheckers(schema, authDict) {
|
function createDynamicCheckers(schema, authDict) {
|
||||||
var checkers = [];
|
var checkers = [];
|
||||||
checkers.push.apply(checkers, tslib_1.__spreadArray([], tslib_1.__read((0, modi_1.createModiRelatedCheckers)(schema)), false));
|
checkers.push.apply(checkers, tslib_1.__spreadArray([], tslib_1.__read((0, modi_1.createModiRelatedCheckers)(schema)), false));
|
||||||
checkers.push.apply(checkers, tslib_1.__spreadArray([], tslib_1.__read((0, checker_1.createRemoveCheckers)(schema)), false));
|
checkers.push.apply(checkers, tslib_1.__spreadArray([], tslib_1.__read((0, checker_1.createRemoveCheckers)(schema, authDict)), false));
|
||||||
if (authDict) {
|
if (authDict) {
|
||||||
checkers.push.apply(checkers, tslib_1.__spreadArray([], tslib_1.__read((0, checker_1.createAuthCheckers)(schema, authDict)), false));
|
checkers.push.apply(checkers, tslib_1.__spreadArray([], tslib_1.__read((0, checker_1.createAuthCheckers)(schema, authDict)), false));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,20 +100,27 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var entityIds = (0, lodash_1.uniq)(result.filter(function (ele) { return ele.entity === attr; }).map(function (ele) { return ele.entityId; }));
|
var entityIds = (0, lodash_1.uniq)(result.filter(function (ele) { return ele.entity === attr; }).map(function (ele) {
|
||||||
var subRows = cascadeSelectFn.call(_this, attr, {
|
(0, assert_1.default)(ele.entityId !== null);
|
||||||
data: projection2[attr],
|
return ele.entityId;
|
||||||
filter: {
|
}));
|
||||||
id: {
|
if (entityIds.length > 0) {
|
||||||
$in: entityIds
|
var subRows = cascadeSelectFn.call(_this, attr, {
|
||||||
|
data: projection2[attr],
|
||||||
|
filter: {
|
||||||
|
id: {
|
||||||
|
$in: entityIds
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}, context, option);
|
||||||
}, context, option);
|
if (subRows instanceof Promise) {
|
||||||
if (subRows instanceof Promise) {
|
return subRows.then(function (subRowss) { return dealWithSubRows(subRowss); });
|
||||||
return subRows.then(function (subRowss) { return dealWithSubRows(subRowss); });
|
}
|
||||||
|
else {
|
||||||
|
dealWithSubRows(subRows);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dealWithSubRows(subRows);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -191,18 +198,20 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var ids = (0, lodash_1.uniq)(result.filter(function (ele) { return !!(ele["".concat(attr, "Id")]); }).map(function (ele) { return ele["".concat(attr, "Id")]; }));
|
var ids = (0, lodash_1.uniq)(result.filter(function (ele) { return !!(ele["".concat(attr, "Id")]); }).map(function (ele) { return ele["".concat(attr, "Id")]; }));
|
||||||
var subRows = cascadeSelectFn.call(_this, relation, {
|
if (ids.length > 0) {
|
||||||
data: projection2[attr],
|
var subRows = cascadeSelectFn.call(_this, relation, {
|
||||||
filter: {
|
data: projection2[attr],
|
||||||
id: {
|
filter: {
|
||||||
$in: ids
|
id: {
|
||||||
|
$in: ids
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}, context, option);
|
||||||
}, context, option);
|
if (subRows instanceof Promise) {
|
||||||
if (subRows instanceof Promise) {
|
return subRows.then(function (subRowss) { return dealWithSubRows(subRowss); });
|
||||||
return subRows.then(function (subRowss) { return dealWithSubRows(subRowss); });
|
}
|
||||||
|
dealWithSubRows(subRows);
|
||||||
}
|
}
|
||||||
dealWithSubRows(subRows);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -261,21 +270,23 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
_a));
|
_a));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var subRows = cascadeSelectFn.call(_this, entity2_1, {
|
if (ids.length > 0) {
|
||||||
data: subProjection_1,
|
var subRows = cascadeSelectFn.call(_this, entity2_1, {
|
||||||
filter: (0, filter_1.combineFilters)([(_a = {},
|
data: subProjection_1,
|
||||||
_a[foreignKey_1] = {
|
filter: (0, filter_1.combineFilters)([(_a = {},
|
||||||
$in: ids,
|
_a[foreignKey_1] = {
|
||||||
},
|
$in: ids,
|
||||||
_a), subFilter_1]),
|
},
|
||||||
sorter: subSorter_1,
|
_a), subFilter_1]),
|
||||||
indexFrom: indexFrom_1,
|
sorter: subSorter_1,
|
||||||
count: count_1
|
indexFrom: indexFrom_1,
|
||||||
}, context, option);
|
count: count_1
|
||||||
if (subRows instanceof Promise) {
|
}, context, option);
|
||||||
return subRows.then(function (subRowss) { return dealWithSubRows(subRowss); });
|
if (subRows instanceof Promise) {
|
||||||
|
return subRows.then(function (subRowss) { return dealWithSubRows(subRowss); });
|
||||||
|
}
|
||||||
|
dealWithSubRows(subRows);
|
||||||
}
|
}
|
||||||
dealWithSubRows(subRows);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -329,22 +340,24 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
_a));
|
_a));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var subRows = cascadeSelectFn.call(_this, entity2_1, {
|
if (ids.length > 0) {
|
||||||
data: subProjection_1,
|
var subRows = cascadeSelectFn.call(_this, entity2_1, {
|
||||||
filter: (0, filter_1.combineFilters)([{
|
data: subProjection_1,
|
||||||
entity: entity,
|
filter: (0, filter_1.combineFilters)([{
|
||||||
entityId: {
|
entity: entity,
|
||||||
$in: ids,
|
entityId: {
|
||||||
}
|
$in: ids,
|
||||||
}, subFilter_1]),
|
}
|
||||||
sorter: subSorter_1,
|
}, subFilter_1]),
|
||||||
indexFrom: indexFrom_1,
|
sorter: subSorter_1,
|
||||||
count: count_1
|
indexFrom: indexFrom_1,
|
||||||
}, context, option);
|
count: count_1
|
||||||
if (subRows instanceof Promise) {
|
}, context, option);
|
||||||
return subRows.then(function (subRowss) { return dealWithSubRows(subRowss); });
|
if (subRows instanceof Promise) {
|
||||||
|
return subRows.then(function (subRowss) { return dealWithSubRows(subRowss); });
|
||||||
|
}
|
||||||
|
dealWithSubRows(subRows);
|
||||||
}
|
}
|
||||||
dealWithSubRows(subRows);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -708,11 +721,11 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
*/
|
*/
|
||||||
CascadeStore.prototype.doUpdateSingleRowAsync = function (entity, operation, context, option) {
|
CascadeStore.prototype.doUpdateSingleRowAsync = function (entity, operation, context, option) {
|
||||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||||
var data, action, operId, filter, now, _a, modiCreate, result_1, createInner, multipleCreate, data_1, data_1_1, d, createSingleOper, e_2_1, operatorId, createOper, _b, ids_1, selection, rows, modiUpsert, upsertModis, _c, originData, originId, createOper, updateAttrCount, result;
|
var data, action, operId, filter, now, _a, modiCreate, result_1, createInner, multipleCreate, data_1, data_1_1, d, createSingleOper, e_2_1, operatorId, createOper, _b, ids_1, selection, rows, modiUpsert, upsertModis, _c, originData, originId, _d, createOper, updateAttrCount, result;
|
||||||
var e_2, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
var e_2, _e, _f, _g, _h, _j, _k, _l;
|
||||||
var _this = this;
|
var _this = this;
|
||||||
return tslib_1.__generator(this, function (_o) {
|
return tslib_1.__generator(this, function (_m) {
|
||||||
switch (_o.label) {
|
switch (_m.label) {
|
||||||
case 0:
|
case 0:
|
||||||
data = operation.data, action = operation.action, operId = operation.id, filter = operation.filter;
|
data = operation.data, action = operation.action, operId = operation.id, filter = operation.filter;
|
||||||
now = Date.now();
|
now = Date.now();
|
||||||
|
|
@ -746,7 +759,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
};
|
};
|
||||||
return [4 /*yield*/, this.cascadeUpdateAsync('modi', modiCreate, context, option)];
|
return [4 /*yield*/, this.cascadeUpdateAsync('modi', modiCreate, context, option)];
|
||||||
case 2:
|
case 2:
|
||||||
_o.sent();
|
_m.sent();
|
||||||
return [2 /*return*/, 1];
|
return [2 /*return*/, 1];
|
||||||
case 3:
|
case 3:
|
||||||
result_1 = 0;
|
result_1 = 0;
|
||||||
|
|
@ -836,12 +849,12 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
if (!multipleCreate) return [3 /*break*/, 5];
|
if (!multipleCreate) return [3 /*break*/, 5];
|
||||||
return [4 /*yield*/, createInner(operation)];
|
return [4 /*yield*/, createInner(operation)];
|
||||||
case 4:
|
case 4:
|
||||||
_o.sent();
|
_m.sent();
|
||||||
return [3 /*break*/, 12];
|
return [3 /*break*/, 12];
|
||||||
case 5:
|
case 5:
|
||||||
_o.trys.push([5, 10, 11, 12]);
|
_m.trys.push([5, 10, 11, 12]);
|
||||||
data_1 = tslib_1.__values(data), data_1_1 = data_1.next();
|
data_1 = tslib_1.__values(data), data_1_1 = data_1.next();
|
||||||
_o.label = 6;
|
_m.label = 6;
|
||||||
case 6:
|
case 6:
|
||||||
if (!!data_1_1.done) return [3 /*break*/, 9];
|
if (!!data_1_1.done) return [3 /*break*/, 9];
|
||||||
d = data_1_1.value;
|
d = data_1_1.value;
|
||||||
|
|
@ -852,27 +865,27 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
};
|
};
|
||||||
return [4 /*yield*/, createInner(createSingleOper)];
|
return [4 /*yield*/, createInner(createSingleOper)];
|
||||||
case 7:
|
case 7:
|
||||||
_o.sent();
|
_m.sent();
|
||||||
_o.label = 8;
|
_m.label = 8;
|
||||||
case 8:
|
case 8:
|
||||||
data_1_1 = data_1.next();
|
data_1_1 = data_1.next();
|
||||||
return [3 /*break*/, 6];
|
return [3 /*break*/, 6];
|
||||||
case 9: return [3 /*break*/, 12];
|
case 9: return [3 /*break*/, 12];
|
||||||
case 10:
|
case 10:
|
||||||
e_2_1 = _o.sent();
|
e_2_1 = _m.sent();
|
||||||
e_2 = { error: e_2_1 };
|
e_2 = { error: e_2_1 };
|
||||||
return [3 /*break*/, 12];
|
return [3 /*break*/, 12];
|
||||||
case 11:
|
case 11:
|
||||||
try {
|
try {
|
||||||
if (data_1_1 && !data_1_1.done && (_d = data_1.return)) _d.call(data_1);
|
if (data_1_1 && !data_1_1.done && (_e = data_1.return)) _e.call(data_1);
|
||||||
}
|
}
|
||||||
finally { if (e_2) throw e_2.error; }
|
finally { if (e_2) throw e_2.error; }
|
||||||
return [7 /*endfinally*/];
|
return [7 /*endfinally*/];
|
||||||
case 12: return [3 /*break*/, 15];
|
case 12: return [3 /*break*/, 15];
|
||||||
case 13: return [4 /*yield*/, createInner(operation)];
|
case 13: return [4 /*yield*/, createInner(operation)];
|
||||||
case 14:
|
case 14:
|
||||||
_o.sent();
|
_m.sent();
|
||||||
_o.label = 15;
|
_m.label = 15;
|
||||||
case 15:
|
case 15:
|
||||||
if (!option.dontCollect) {
|
if (!option.dontCollect) {
|
||||||
context.opRecords.push({
|
context.opRecords.push({
|
||||||
|
|
@ -886,20 +899,20 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
(0, assert_1.default)(operId);
|
(0, assert_1.default)(operId);
|
||||||
return [4 /*yield*/, context.getCurrentUserId(true)];
|
return [4 /*yield*/, context.getCurrentUserId(true)];
|
||||||
case 16:
|
case 16:
|
||||||
operatorId = _o.sent();
|
operatorId = _m.sent();
|
||||||
if (!operatorId) return [3 /*break*/, 22];
|
if (!operatorId) return [3 /*break*/, 22];
|
||||||
_e = {
|
_f = {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
action: 'create'
|
action: 'create'
|
||||||
};
|
};
|
||||||
_f = {
|
_g = {
|
||||||
id: operId,
|
id: operId,
|
||||||
action: action,
|
action: action,
|
||||||
data: data,
|
data: data,
|
||||||
operatorId: operatorId
|
operatorId: operatorId
|
||||||
};
|
};
|
||||||
if (!(data instanceof Array)) return [3 /*break*/, 18];
|
if (!(data instanceof Array)) return [3 /*break*/, 18];
|
||||||
_g = {
|
_h = {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
action: 'create'
|
action: 'create'
|
||||||
};
|
};
|
||||||
|
|
@ -918,34 +931,34 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
});
|
});
|
||||||
}); }))];
|
}); }))];
|
||||||
case 17:
|
case 17:
|
||||||
_b = (_g.data = _o.sent(),
|
_b = (_h.data = _m.sent(),
|
||||||
_g);
|
_h);
|
||||||
return [3 /*break*/, 20];
|
return [3 /*break*/, 20];
|
||||||
case 18:
|
case 18:
|
||||||
_h = {
|
_j = {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
action: 'create'
|
action: 'create'
|
||||||
};
|
};
|
||||||
_j = {};
|
_k = {};
|
||||||
return [4 /*yield*/, (0, uuid_1.generateNewIdAsync)()];
|
return [4 /*yield*/, (0, uuid_1.generateNewIdAsync)()];
|
||||||
case 19:
|
case 19:
|
||||||
_b = [(_h.data = (_j.id = _o.sent(),
|
_b = [(_j.data = (_k.id = _m.sent(),
|
||||||
_j.entity = entity,
|
_k.entity = entity,
|
||||||
_j.entityId = data.id,
|
_k.entityId = data.id,
|
||||||
_j),
|
_k),
|
||||||
_h)];
|
_j)];
|
||||||
_o.label = 20;
|
_m.label = 20;
|
||||||
case 20:
|
case 20:
|
||||||
createOper = (_e.data = (_f.operEntity$oper = _b,
|
createOper = (_f.data = (_g.operEntity$oper = _b,
|
||||||
_f),
|
_g),
|
||||||
_e);
|
_f);
|
||||||
return [4 /*yield*/, this.cascadeUpdateAsync('oper', createOper, context, {
|
return [4 /*yield*/, this.cascadeUpdateAsync('oper', createOper, context, {
|
||||||
dontCollect: true,
|
dontCollect: true,
|
||||||
dontCreateOper: true,
|
dontCreateOper: true,
|
||||||
})];
|
})];
|
||||||
case 21:
|
case 21:
|
||||||
_o.sent();
|
_m.sent();
|
||||||
_o.label = 22;
|
_m.label = 22;
|
||||||
case 22: return [2 /*return*/, result_1];
|
case 22: return [2 /*return*/, result_1];
|
||||||
case 23:
|
case 23:
|
||||||
ids_1 = (0, filter_2.getRelevantIds)(filter);
|
ids_1 = (0, filter_2.getRelevantIds)(filter);
|
||||||
|
|
@ -962,9 +975,9 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
dontCollect: true,
|
dontCollect: true,
|
||||||
})];
|
})];
|
||||||
case 24:
|
case 24:
|
||||||
rows = _o.sent();
|
rows = _m.sent();
|
||||||
ids_1.push.apply(ids_1, tslib_1.__spreadArray([], tslib_1.__read((rows.map(function (ele) { return ele.id; }))), false));
|
ids_1.push.apply(ids_1, tslib_1.__spreadArray([], tslib_1.__read((rows.map(function (ele) { return ele.id; }))), false));
|
||||||
_o.label = 25;
|
_m.label = 25;
|
||||||
case 25:
|
case 25:
|
||||||
if (data) {
|
if (data) {
|
||||||
this.preProcessDataUpdated(data);
|
this.preProcessDataUpdated(data);
|
||||||
|
|
@ -1003,7 +1016,7 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
count: 1,
|
count: 1,
|
||||||
}, context, option)];
|
}, context, option)];
|
||||||
case 26:
|
case 26:
|
||||||
upsertModis = _o.sent();
|
upsertModis = _m.sent();
|
||||||
if (upsertModis.length > 0) {
|
if (upsertModis.length > 0) {
|
||||||
_c = upsertModis[0], originData = _c.data, originId = _c.id;
|
_c = upsertModis[0], originData = _c.data, originId = _c.id;
|
||||||
modiUpsert = {
|
modiUpsert = {
|
||||||
|
|
@ -1017,24 +1030,26 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
_o.label = 27;
|
_m.label = 27;
|
||||||
case 27:
|
case 27:
|
||||||
if (!!modiUpsert) return [3 /*break*/, 29];
|
if (!!modiUpsert) return [3 /*break*/, 29];
|
||||||
_k = {
|
modiUpsert = {
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
action: 'create'
|
action: 'create',
|
||||||
|
data: {
|
||||||
|
id: operId,
|
||||||
|
targetEntity: entity,
|
||||||
|
entity: option.modiParentEntity,
|
||||||
|
entityId: option.modiParentId,
|
||||||
|
action: action,
|
||||||
|
data: data,
|
||||||
|
iState: 'active',
|
||||||
|
filter: filter,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
if (!(ids_1.length > 0)) return [3 /*break*/, 29];
|
||||||
|
_d = modiUpsert.data;
|
||||||
_l = {
|
_l = {
|
||||||
id: operId,
|
|
||||||
targetEntity: entity,
|
|
||||||
entity: option.modiParentEntity,
|
|
||||||
entityId: option.modiParentId,
|
|
||||||
action: action,
|
|
||||||
data: data,
|
|
||||||
iState: 'active',
|
|
||||||
filter: filter
|
|
||||||
};
|
|
||||||
_m = {
|
|
||||||
id: 'dummy',
|
id: 'dummy',
|
||||||
action: 'create'
|
action: 'create'
|
||||||
};
|
};
|
||||||
|
|
@ -1053,14 +1068,12 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
});
|
});
|
||||||
}); }))];
|
}); }))];
|
||||||
case 28:
|
case 28:
|
||||||
modiUpsert = (_k.data = (_l.modiEntity$modi = (_m.data = _o.sent(),
|
_d.modiEntity$modi = (_l.data = _m.sent(),
|
||||||
_m),
|
_l);
|
||||||
_l),
|
_m.label = 29;
|
||||||
_k);
|
|
||||||
_o.label = 29;
|
|
||||||
case 29: return [4 /*yield*/, this.cascadeUpdateAsync('modi', modiUpsert, context, option)];
|
case 29: return [4 /*yield*/, this.cascadeUpdateAsync('modi', modiUpsert, context, option)];
|
||||||
case 30:
|
case 30:
|
||||||
_o.sent();
|
_m.sent();
|
||||||
return [2 /*return*/, 1];
|
return [2 /*return*/, 1];
|
||||||
case 31:
|
case 31:
|
||||||
createOper = function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
createOper = function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
||||||
|
|
@ -1155,15 +1168,15 @@ var CascadeStore = /** @class */ (function (_super) {
|
||||||
return [4 /*yield*/, createOper()];
|
return [4 /*yield*/, createOper()];
|
||||||
case 34:
|
case 34:
|
||||||
// 如果不是update动作而是用户自定义的动作,这里还是要记录oper
|
// 如果不是update动作而是用户自定义的动作,这里还是要记录oper
|
||||||
_o.sent();
|
_m.sent();
|
||||||
return [2 /*return*/, 0];
|
return [2 /*return*/, 0];
|
||||||
case 35: return [2 /*return*/, 0];
|
case 35: return [2 /*return*/, 0];
|
||||||
case 36: return [4 /*yield*/, this.updateAbjointRowAsync(entity, operation, context, option)];
|
case 36: return [4 /*yield*/, this.updateAbjointRowAsync(entity, operation, context, option)];
|
||||||
case 37:
|
case 37:
|
||||||
result = _o.sent();
|
result = _m.sent();
|
||||||
return [4 /*yield*/, createOper()];
|
return [4 /*yield*/, createOper()];
|
||||||
case 38:
|
case 38:
|
||||||
_o.sent();
|
_m.sent();
|
||||||
return [2 /*return*/, result];
|
return [2 /*return*/, result];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -23,4 +23,4 @@ export declare function createAuthCheckers<ED extends EntityDict & BaseEntityDic
|
||||||
* @returns
|
* @returns
|
||||||
* 如果有的对象允许删除,需要使用trigger来处理其相关联的外键对象,这些trigger写作before,则会在checker之前执行,仍然可以删除成功
|
* 如果有的对象允许删除,需要使用trigger来处理其相关联的外键对象,这些trigger写作before,则会在checker之前执行,仍然可以删除成功
|
||||||
*/
|
*/
|
||||||
export declare function createRemoveCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>>(schema: StorageSchema<ED>): Checker<ED, keyof ED, Cxt>[];
|
export declare function createRemoveCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>>(schema: StorageSchema<ED>, authDict?: AuthDefDict<ED>): Checker<ED, keyof ED, Cxt>[];
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,12 @@ var tslib_1 = require("tslib");
|
||||||
var assert_1 = tslib_1.__importDefault(require("assert"));
|
var assert_1 = tslib_1.__importDefault(require("assert"));
|
||||||
var filter_1 = require("../store/filter");
|
var filter_1 = require("../store/filter");
|
||||||
var Exception_1 = require("../types/Exception");
|
var Exception_1 = require("../types/Exception");
|
||||||
|
var types_1 = require("../types");
|
||||||
var actionDef_1 = require("./actionDef");
|
var actionDef_1 = require("./actionDef");
|
||||||
var string_1 = require("../utils/string");
|
var string_1 = require("../utils/string");
|
||||||
var lodash_1 = require("../utils/lodash");
|
var lodash_1 = require("../utils/lodash");
|
||||||
var relation_1 = require("./relation");
|
var relation_1 = require("./relation");
|
||||||
|
var uuid_1 = require("../utils/uuid");
|
||||||
function translateCheckerInAsyncContext(checker) {
|
function translateCheckerInAsyncContext(checker) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
var entity = checker.entity, type = checker.type, action = checker.action;
|
var entity = checker.entity, type = checker.type, action = checker.action;
|
||||||
|
|
@ -406,12 +408,12 @@ function createAuthCheckers(schema, authDict) {
|
||||||
var _b = authDict[entity], relationAuth = _b.relationAuth, actionAuth = _b.actionAuth;
|
var _b = authDict[entity], relationAuth = _b.relationAuth, actionAuth = _b.actionAuth;
|
||||||
if (relationAuth) {
|
if (relationAuth) {
|
||||||
var raFilterMakerDict_1 = {};
|
var raFilterMakerDict_1 = {};
|
||||||
|
var userEntityName_1 = "user".concat((0, string_1.firstLetterUpperCase)(entity));
|
||||||
for (var r in relationAuth) {
|
for (var r in relationAuth) {
|
||||||
Object.assign(raFilterMakerDict_1, (_a = {},
|
Object.assign(raFilterMakerDict_1, (_a = {},
|
||||||
_a[r] = translateActionAuthFilterMaker(schema, relationAuth[r], entity),
|
_a[r] = translateActionAuthFilterMaker(schema, relationAuth[r], entity),
|
||||||
_a));
|
_a));
|
||||||
}
|
}
|
||||||
var userEntityName_1 = "user".concat((0, string_1.firstLetterUpperCase)(entity));
|
|
||||||
var entityIdAttr_1 = "".concat(entity, "Id");
|
var entityIdAttr_1 = "".concat(entity, "Id");
|
||||||
checkers.push({
|
checkers.push({
|
||||||
entity: userEntityName_1,
|
entity: userEntityName_1,
|
||||||
|
|
@ -508,7 +510,7 @@ exports.createAuthCheckers = createAuthCheckers;
|
||||||
* @returns
|
* @returns
|
||||||
* 如果有的对象允许删除,需要使用trigger来处理其相关联的外键对象,这些trigger写作before,则会在checker之前执行,仍然可以删除成功
|
* 如果有的对象允许删除,需要使用trigger来处理其相关联的外键对象,这些trigger写作before,则会在checker之前执行,仍然可以删除成功
|
||||||
*/
|
*/
|
||||||
function createRemoveCheckers(schema) {
|
function createRemoveCheckers(schema, authDict) {
|
||||||
var e_1, _a;
|
var e_1, _a;
|
||||||
var checkers = [];
|
var checkers = [];
|
||||||
// 先建立所有的一对多的关系
|
// 先建立所有的一对多的关系
|
||||||
|
|
@ -575,7 +577,7 @@ function createRemoveCheckers(schema) {
|
||||||
var e_3, _a, e_4, _b;
|
var e_3, _a, e_4, _b;
|
||||||
var promises = [];
|
var promises = [];
|
||||||
if (OneToManyMatrix[entity]) {
|
if (OneToManyMatrix[entity]) {
|
||||||
var _loop_4 = function (otm) {
|
var _loop_5 = function (otm) {
|
||||||
var _g, _h, _j, _k;
|
var _g, _h, _j, _k;
|
||||||
var _l = tslib_1.__read(otm, 2), e = _l[0], attr = _l[1];
|
var _l = tslib_1.__read(otm, 2), e = _l[0], attr = _l[1];
|
||||||
var proj = (_g = {
|
var proj = (_g = {
|
||||||
|
|
@ -627,7 +629,7 @@ function createRemoveCheckers(schema) {
|
||||||
try {
|
try {
|
||||||
for (var _c = (e_3 = void 0, tslib_1.__values(OneToManyMatrix[entity])), _d = _c.next(); !_d.done; _d = _c.next()) {
|
for (var _c = (e_3 = void 0, tslib_1.__values(OneToManyMatrix[entity])), _d = _c.next(); !_d.done; _d = _c.next()) {
|
||||||
var otm = _d.value;
|
var otm = _d.value;
|
||||||
_loop_4(otm);
|
_loop_5(otm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
||||||
|
|
@ -639,7 +641,7 @@ function createRemoveCheckers(schema) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (OneToManyOnEntityMatrix[entity]) {
|
if (OneToManyOnEntityMatrix[entity]) {
|
||||||
var _loop_5 = function (otm) {
|
var _loop_6 = function (otm) {
|
||||||
var _o, _p, _q;
|
var _o, _p, _q;
|
||||||
var proj = {
|
var proj = {
|
||||||
id: 1,
|
id: 1,
|
||||||
|
|
@ -690,7 +692,7 @@ function createRemoveCheckers(schema) {
|
||||||
try {
|
try {
|
||||||
for (var _e = (e_4 = void 0, tslib_1.__values(OneToManyOnEntityMatrix[entity])), _f = _e.next(); !_f.done; _f = _e.next()) {
|
for (var _e = (e_4 = void 0, tslib_1.__values(OneToManyOnEntityMatrix[entity])), _f = _e.next(); !_f.done; _f = _e.next()) {
|
||||||
var otm = _f.value;
|
var otm = _f.value;
|
||||||
_loop_5(otm);
|
_loop_6(otm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
||||||
|
|
@ -720,6 +722,146 @@ function createRemoveCheckers(schema) {
|
||||||
}
|
}
|
||||||
finally { if (e_1) throw e_1.error; }
|
finally { if (e_1) throw e_1.error; }
|
||||||
}
|
}
|
||||||
|
var _loop_4 = function (entity) {
|
||||||
|
var e_5, _b;
|
||||||
|
var cascadeRemove = authDict[entity].cascadeRemove;
|
||||||
|
if (cascadeRemove) {
|
||||||
|
var entitiesOnEntityAttr = [];
|
||||||
|
var hasAllEntity = false;
|
||||||
|
var _loop_7 = function (attr) {
|
||||||
|
if (attr === '@entity') {
|
||||||
|
hasAllEntity = true;
|
||||||
|
return "continue";
|
||||||
|
}
|
||||||
|
var rel = (0, relation_1.judgeRelation)(schema, entity, attr);
|
||||||
|
if (rel === 2) {
|
||||||
|
entitiesOnEntityAttr.push(attr);
|
||||||
|
checkers.push({
|
||||||
|
entity: attr,
|
||||||
|
action: 'remove',
|
||||||
|
type: 'logical',
|
||||||
|
priority: types_1.REMOVE_CASCADE_PRIORITY,
|
||||||
|
checker: function (operation, context) {
|
||||||
|
var _a, _b;
|
||||||
|
var filter = operation.filter;
|
||||||
|
if (cascadeRemove[attr] === 'remove') {
|
||||||
|
return context.operate(entity, {
|
||||||
|
id: (0, uuid_1.generateNewId)(),
|
||||||
|
action: 'remove',
|
||||||
|
data: {},
|
||||||
|
filter: filter ? (_a = {},
|
||||||
|
_a[attr] = filter,
|
||||||
|
_a) : undefined,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
}
|
||||||
|
return context.operate(entity, {
|
||||||
|
id: (0, uuid_1.generateNewId)(),
|
||||||
|
action: 'update',
|
||||||
|
data: {
|
||||||
|
entity: null,
|
||||||
|
entityId: null,
|
||||||
|
},
|
||||||
|
filter: filter ? (_b = {},
|
||||||
|
_b[attr] = filter,
|
||||||
|
_b) : undefined,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
(0, assert_1.default)(typeof rel === 'string');
|
||||||
|
checkers.push({
|
||||||
|
entity: rel,
|
||||||
|
action: 'remove',
|
||||||
|
type: 'logical',
|
||||||
|
priority: types_1.REMOVE_CASCADE_PRIORITY,
|
||||||
|
checker: function (operation, context) {
|
||||||
|
var _a, _b, _c;
|
||||||
|
var filter = operation.filter;
|
||||||
|
if (cascadeRemove[attr] === 'remove') {
|
||||||
|
return context.operate(entity, {
|
||||||
|
id: (0, uuid_1.generateNewId)(),
|
||||||
|
action: 'remove',
|
||||||
|
data: {},
|
||||||
|
filter: filter ? (_a = {},
|
||||||
|
_a[attr] = filter,
|
||||||
|
_a) : undefined,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
}
|
||||||
|
return context.operate(entity, {
|
||||||
|
id: (0, uuid_1.generateNewId)(),
|
||||||
|
action: 'update',
|
||||||
|
data: (_b = {},
|
||||||
|
_b["".concat(attr, "Id")] = null,
|
||||||
|
_b),
|
||||||
|
filter: filter ? (_c = {},
|
||||||
|
_c[attr] = filter,
|
||||||
|
_c) : undefined,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (var attr in cascadeRemove) {
|
||||||
|
_loop_7(attr);
|
||||||
|
}
|
||||||
|
if (hasAllEntity) {
|
||||||
|
var attributes = schema[entity].attributes;
|
||||||
|
var ref = attributes.entity.ref;
|
||||||
|
var restEntities = (0, lodash_1.difference)(ref, entitiesOnEntityAttr);
|
||||||
|
var _loop_8 = function (e) {
|
||||||
|
checkers.push({
|
||||||
|
entity: e,
|
||||||
|
action: 'remove',
|
||||||
|
type: 'logical',
|
||||||
|
priority: types_1.REMOVE_CASCADE_PRIORITY,
|
||||||
|
checker: function (operation, context) {
|
||||||
|
var _a, _b;
|
||||||
|
var filter = operation.filter;
|
||||||
|
if (cascadeRemove['@entity'] === 'remove') {
|
||||||
|
return context.operate(entity, {
|
||||||
|
id: (0, uuid_1.generateNewId)(),
|
||||||
|
action: 'remove',
|
||||||
|
data: {},
|
||||||
|
filter: filter ? (_a = {},
|
||||||
|
_a[e] = filter,
|
||||||
|
_a) : undefined,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
}
|
||||||
|
return context.operate(entity, {
|
||||||
|
id: (0, uuid_1.generateNewId)(),
|
||||||
|
action: 'update',
|
||||||
|
data: {
|
||||||
|
entity: null,
|
||||||
|
entityId: null,
|
||||||
|
},
|
||||||
|
filter: filter ? (_b = {},
|
||||||
|
_b[e] = filter,
|
||||||
|
_b) : undefined,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
for (var restEntities_1 = (e_5 = void 0, tslib_1.__values(restEntities)), restEntities_1_1 = restEntities_1.next(); !restEntities_1_1.done; restEntities_1_1 = restEntities_1.next()) {
|
||||||
|
var e = restEntities_1_1.value;
|
||||||
|
_loop_8(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
if (restEntities_1_1 && !restEntities_1_1.done && (_b = restEntities_1.return)) _b.call(restEntities_1);
|
||||||
|
}
|
||||||
|
finally { if (e_5) throw e_5.error; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 注入声明的cascade删除时的外键处理动作
|
||||||
|
for (var entity in authDict) {
|
||||||
|
_loop_4(entity);
|
||||||
|
}
|
||||||
return checkers;
|
return checkers;
|
||||||
}
|
}
|
||||||
exports.createRemoveCheckers = createRemoveCheckers;
|
exports.createRemoveCheckers = createRemoveCheckers;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ export declare type ActionDictOfEntityDict<E extends EntityDict> = {
|
||||||
[A in keyof E[T]['OpSchema']]?: ActionDef<string, string>;
|
[A in keyof E[T]['OpSchema']]?: ActionDef<string, string>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
export declare type CascadeActionItem = CascadeRelationItem;
|
||||||
export declare type CascadeActionAuth<A extends Action = ''> = {
|
export declare type CascadeActionAuth<A extends Action = ''> = {
|
||||||
[K in A | GenericAction]?: CascadeRelationItem | (CascadeRelationItem | CascadeRelationItem[])[];
|
[K in A | GenericAction]?: CascadeActionItem | (CascadeActionItem | CascadeActionItem[])[];
|
||||||
};
|
};
|
||||||
|
export declare type ActionOnRemove = 'setNull' | 'remove';
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { CascadeActionAuth, CascadeRelationAuth } from ".";
|
import { CascadeActionAuth, CascadeRelationAuth, ActionOnRemove } from ".";
|
||||||
import { AsyncContext } from "../store/AsyncRowStore";
|
import { AsyncContext } from "../store/AsyncRowStore";
|
||||||
import { SyncContext } from "../store/SyncRowStore";
|
import { SyncContext } from "../store/SyncRowStore";
|
||||||
import { EntityDict, OperateOption, SelectOption } from "../types/Entity";
|
import { EntityDict, OperateOption, SelectOption } from "../types/Entity";
|
||||||
|
|
@ -60,6 +60,9 @@ export declare type Checker<ED extends EntityDict, T extends keyof ED, Cxt exten
|
||||||
export declare type AuthDef<ED extends EntityDict, T extends keyof ED> = {
|
export declare type AuthDef<ED extends EntityDict, T extends keyof ED> = {
|
||||||
relationAuth?: CascadeRelationAuth<NonNullable<ED[T]['Relation']>>;
|
relationAuth?: CascadeRelationAuth<NonNullable<ED[T]['Relation']>>;
|
||||||
actionAuth?: CascadeActionAuth<ED[T]['Action']>;
|
actionAuth?: CascadeActionAuth<ED[T]['Action']>;
|
||||||
|
cascadeRemove?: {
|
||||||
|
[E in keyof ED[T]['OpSchema'] | '@entity']?: ActionOnRemove;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
export declare type AuthDefDict<ED extends EntityDict> = {
|
export declare type AuthDefDict<ED extends EntityDict> = {
|
||||||
[K in keyof ED]?: AuthDef<ED, K>;
|
[K in keyof ED]?: AuthDef<ED, K>;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "oak-domain",
|
"name": "oak-domain",
|
||||||
"version": "2.5.1",
|
"version": "2.5.2",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "XuChang"
|
"name": "XuChang"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,28 @@
|
||||||
import { CascadeRelationItem, RelationHierarchy } from "../types/Entity";
|
import { CascadeRelationItem, RelationHierarchy, EntityDict } from "../types/Entity";
|
||||||
|
|
||||||
export type GenericRelation = 'owner';
|
export type GenericRelation = 'owner';
|
||||||
|
|
||||||
export function convertHierarchyToAuth<R extends string>(hierarchy: RelationHierarchy<R>): {
|
export function convertHierarchyToAuth<ED extends EntityDict, T extends keyof ED>(entity: T, hierarchy: RelationHierarchy<NonNullable<ED[T]['Relation']>>): {
|
||||||
[K in R]?: CascadeRelationItem;
|
[K in NonNullable<ED[T]['Relation']>]?: CascadeRelationItem;
|
||||||
} {
|
} {
|
||||||
const reverseHierarchy: RelationHierarchy<R> = {};
|
const reverseHierarchy: RelationHierarchy<NonNullable<ED[T]['Relation']>> = {};
|
||||||
for (const r in hierarchy) {
|
for (const r in hierarchy) {
|
||||||
for (const r2 of hierarchy[r]!) {
|
for (const r2 of hierarchy[r as NonNullable<ED[T]['Relation']>]!) {
|
||||||
if (reverseHierarchy[r2]) {
|
if (reverseHierarchy[r2]) {
|
||||||
reverseHierarchy[r2]?.push(r);
|
reverseHierarchy[r2]?.push(r as NonNullable<ED[T]['Relation']>);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
reverseHierarchy[r2] = [r];
|
reverseHierarchy[r2] = [r as NonNullable<ED[T]['Relation']>];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const result: {
|
const result: {
|
||||||
[K in R]?: CascadeRelationItem;
|
[K in NonNullable<ED[T]['Relation']>]?: CascadeRelationItem;
|
||||||
} = {};
|
} = {};
|
||||||
for (const r in reverseHierarchy) {
|
for (const r in reverseHierarchy) {
|
||||||
result[r] = {
|
result[r as NonNullable<ED[T]['Relation']>] = {
|
||||||
cascadePath: '',
|
cascadePath: '',
|
||||||
relations: reverseHierarchy[r],
|
relations: reverseHierarchy[r as NonNullable<ED[T]['Relation']>],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { StorageSchema, EntityDict as BaseEntityDict, Checker, AuthDef, AuthDefD
|
||||||
export function createDynamicCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>>(schema: StorageSchema<ED>, authDict?: AuthDefDict<ED>){
|
export function createDynamicCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>>(schema: StorageSchema<ED>, authDict?: AuthDefDict<ED>){
|
||||||
const checkers: Checker<ED, keyof ED, Cxt>[] = [];
|
const checkers: Checker<ED, keyof ED, Cxt>[] = [];
|
||||||
checkers.push(...createModiRelatedCheckers<ED, Cxt>(schema));
|
checkers.push(...createModiRelatedCheckers<ED, Cxt>(schema));
|
||||||
checkers.push(...createRemoveCheckers<ED, Cxt>(schema));
|
checkers.push(...createRemoveCheckers<ED, Cxt>(schema, authDict));
|
||||||
if (authDict) {
|
if (authDict) {
|
||||||
checkers.push(...createAuthCheckers<ED, Cxt>(schema, authDict));
|
checkers.push(...createAuthCheckers<ED, Cxt>(schema, authDict));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,24 +169,32 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
const entityIds = uniq(result.filter(
|
const entityIds = uniq(result.filter(
|
||||||
ele => ele.entity === attr
|
ele => ele.entity === attr
|
||||||
).map(
|
).map(
|
||||||
ele => ele.entityId
|
ele => {
|
||||||
|
assert(ele.entityId !== null);
|
||||||
|
return ele.entityId;
|
||||||
|
}
|
||||||
) as string[]);
|
) as string[]);
|
||||||
|
|
||||||
const subRows = cascadeSelectFn.call(this, attr as any, {
|
if (entityIds.length > 0) {
|
||||||
data: projection2[attr],
|
const subRows = cascadeSelectFn.call(this, attr as any, {
|
||||||
filter: {
|
data: projection2[attr],
|
||||||
id: {
|
filter: {
|
||||||
$in: entityIds
|
id: {
|
||||||
},
|
$in: entityIds
|
||||||
} as any,
|
},
|
||||||
}, context, option);
|
} as any,
|
||||||
if (subRows instanceof Promise) {
|
}, context, option);
|
||||||
return subRows.then(
|
if (subRows instanceof Promise) {
|
||||||
(subRowss) => dealWithSubRows(subRowss)
|
return subRows.then(
|
||||||
)
|
(subRowss) => dealWithSubRows(subRowss)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dealWithSubRows(subRows as any);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dealWithSubRows(subRows as any);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
@ -286,20 +294,22 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
ele => ele[`${attr}Id`]
|
ele => ele[`${attr}Id`]
|
||||||
) as string[]);
|
) as string[]);
|
||||||
|
|
||||||
const subRows = cascadeSelectFn.call(this, relation, {
|
if (ids.length > 0) {
|
||||||
data: projection2[attr],
|
const subRows = cascadeSelectFn.call(this, relation, {
|
||||||
filter: {
|
data: projection2[attr],
|
||||||
id: {
|
filter: {
|
||||||
$in: ids
|
id: {
|
||||||
},
|
$in: ids
|
||||||
} as any,
|
},
|
||||||
}, context, option);
|
} as any,
|
||||||
if (subRows instanceof Promise) {
|
}, context, option);
|
||||||
return subRows.then(
|
if (subRows instanceof Promise) {
|
||||||
(subRowss) => dealWithSubRows(subRowss)
|
return subRows.then(
|
||||||
);
|
(subRowss) => dealWithSubRows(subRowss)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
dealWithSubRows(subRows as any);
|
||||||
}
|
}
|
||||||
dealWithSubRows(subRows as any);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -370,23 +380,25 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const subRows = cascadeSelectFn.call(this, entity2, {
|
if (ids.length > 0) {
|
||||||
data: subProjection,
|
const subRows = cascadeSelectFn.call(this, entity2, {
|
||||||
filter: combineFilters([{
|
data: subProjection,
|
||||||
[foreignKey]: {
|
filter: combineFilters([{
|
||||||
$in: ids,
|
[foreignKey]: {
|
||||||
}
|
$in: ids,
|
||||||
}, subFilter]),
|
}
|
||||||
sorter: subSorter,
|
}, subFilter]),
|
||||||
indexFrom,
|
sorter: subSorter,
|
||||||
count
|
indexFrom,
|
||||||
}, context, option);
|
count
|
||||||
if (subRows instanceof Promise) {
|
}, context, option);
|
||||||
return subRows.then(
|
if (subRows instanceof Promise) {
|
||||||
(subRowss) => dealWithSubRows(subRowss)
|
return subRows.then(
|
||||||
);
|
(subRowss) => dealWithSubRows(subRowss)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
dealWithSubRows(subRows as any);
|
||||||
}
|
}
|
||||||
dealWithSubRows(subRows as any);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -452,24 +464,26 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const subRows = cascadeSelectFn.call(this, entity2, {
|
if (ids.length > 0) {
|
||||||
data: subProjection,
|
const subRows = cascadeSelectFn.call(this, entity2, {
|
||||||
filter: combineFilters([{
|
data: subProjection,
|
||||||
entity,
|
filter: combineFilters([{
|
||||||
entityId: {
|
entity,
|
||||||
$in: ids,
|
entityId: {
|
||||||
}
|
$in: ids,
|
||||||
}, subFilter]),
|
}
|
||||||
sorter: subSorter,
|
}, subFilter]),
|
||||||
indexFrom,
|
sorter: subSorter,
|
||||||
count
|
indexFrom,
|
||||||
}, context, option);
|
count
|
||||||
if (subRows instanceof Promise) {
|
}, context, option);
|
||||||
return subRows.then(
|
if (subRows instanceof Promise) {
|
||||||
(subRowss) => dealWithSubRows(subRowss)
|
return subRows.then(
|
||||||
);
|
(subRowss) => dealWithSubRows(subRowss)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
dealWithSubRows(subRows as any);
|
||||||
}
|
}
|
||||||
dealWithSubRows(subRows as any);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1117,21 +1131,23 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
||||||
data,
|
data,
|
||||||
iState: 'active',
|
iState: 'active',
|
||||||
filter,
|
filter,
|
||||||
modiEntity$modi: {
|
|
||||||
id: 'dummy',
|
|
||||||
action: 'create',
|
|
||||||
data: await Promise.all(
|
|
||||||
ids.map(
|
|
||||||
async (id) => ({
|
|
||||||
id: await generateNewIdAsync(),
|
|
||||||
entity: entity as string,
|
|
||||||
entityId: id,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
if (ids.length > 0){
|
||||||
|
modiUpsert.data.modiEntity$modi = {
|
||||||
|
id: 'dummy',
|
||||||
|
action: 'create',
|
||||||
|
data: await Promise.all(
|
||||||
|
ids.map(
|
||||||
|
async (id) => ({
|
||||||
|
id: await generateNewIdAsync(),
|
||||||
|
entity: entity as string,
|
||||||
|
entityId: id,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await this.cascadeUpdateAsync('modi', modiUpsert!, context, option);
|
await this.cascadeUpdateAsync('modi', modiUpsert!, context, option);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { addFilterSegment, checkFilterContains, combineFilters } from "../store/
|
||||||
import { OakRowInconsistencyException, OakUserUnpermittedException } from '../types/Exception';
|
import { OakRowInconsistencyException, OakUserUnpermittedException } from '../types/Exception';
|
||||||
import {
|
import {
|
||||||
AuthDefDict, CascadeRelationItem, Checker, CreateTriggerInTxn,
|
AuthDefDict, CascadeRelationItem, Checker, CreateTriggerInTxn,
|
||||||
EntityDict, OperateOption, SelectOption, StorageSchema, Trigger, UpdateTriggerInTxn, RelationHierarchy, SelectOpResult
|
EntityDict, OperateOption, SelectOption, StorageSchema, Trigger, UpdateTriggerInTxn, RelationHierarchy, SelectOpResult, REMOVE_CASCADE_PRIORITY
|
||||||
} from "../types";
|
} from "../types";
|
||||||
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
||||||
import { AsyncContext } from "./AsyncRowStore";
|
import { AsyncContext } from "./AsyncRowStore";
|
||||||
|
|
@ -12,6 +12,7 @@ import { SyncContext } from './SyncRowStore';
|
||||||
import { firstLetterUpperCase } from '../utils/string';
|
import { firstLetterUpperCase } from '../utils/string';
|
||||||
import { union, uniq, difference } from '../utils/lodash';
|
import { union, uniq, difference } from '../utils/lodash';
|
||||||
import { judgeRelation } from './relation';
|
import { judgeRelation } from './relation';
|
||||||
|
import { generateNewId } from '../utils/uuid';
|
||||||
|
|
||||||
export function translateCheckerInAsyncContext<
|
export function translateCheckerInAsyncContext<
|
||||||
ED extends EntityDict & BaseEntityDict,
|
ED extends EntityDict & BaseEntityDict,
|
||||||
|
|
@ -387,12 +388,12 @@ export function createAuthCheckers<ED extends EntityDict & BaseEntityDict, Cxt e
|
||||||
const { relationAuth, actionAuth } = authDict[entity]!;
|
const { relationAuth, actionAuth } = authDict[entity]!;
|
||||||
if (relationAuth) {
|
if (relationAuth) {
|
||||||
const raFilterMakerDict = {} as Record<string, (userId: string) => ED[keyof ED]['Selection']['filter']>;
|
const raFilterMakerDict = {} as Record<string, (userId: string) => ED[keyof ED]['Selection']['filter']>;
|
||||||
|
const userEntityName = `user${firstLetterUpperCase(entity)}`;
|
||||||
for (const r in relationAuth) {
|
for (const r in relationAuth) {
|
||||||
Object.assign(raFilterMakerDict, {
|
Object.assign(raFilterMakerDict, {
|
||||||
[r]: translateActionAuthFilterMaker(schema, relationAuth[r as NonNullable<ED[keyof ED]['Relation']>]!, entity),
|
[r]: translateActionAuthFilterMaker(schema, relationAuth[r as NonNullable<ED[keyof ED]['Relation']>]!, entity),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const userEntityName = `user${firstLetterUpperCase(entity)}`;
|
|
||||||
const entityIdAttr = `${entity}Id`;
|
const entityIdAttr = `${entity}Id`;
|
||||||
checkers.push({
|
checkers.push({
|
||||||
entity: userEntityName as keyof ED,
|
entity: userEntityName as keyof ED,
|
||||||
|
|
@ -490,7 +491,7 @@ export function createAuthCheckers<ED extends EntityDict & BaseEntityDict, Cxt e
|
||||||
* @returns
|
* @returns
|
||||||
* 如果有的对象允许删除,需要使用trigger来处理其相关联的外键对象,这些trigger写作before,则会在checker之前执行,仍然可以删除成功
|
* 如果有的对象允许删除,需要使用trigger来处理其相关联的外键对象,这些trigger写作before,则会在checker之前执行,仍然可以删除成功
|
||||||
*/
|
*/
|
||||||
export function createRemoveCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>>(schema: StorageSchema<ED>) {
|
export function createRemoveCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>>(schema: StorageSchema<ED>, authDict?: AuthDefDict<ED>) {
|
||||||
const checkers: Checker<ED, keyof ED, Cxt>[] = [];
|
const checkers: Checker<ED, keyof ED, Cxt>[] = [];
|
||||||
|
|
||||||
// 先建立所有的一对多的关系
|
// 先建立所有的一对多的关系
|
||||||
|
|
@ -657,5 +658,125 @@ export function createRemoveCheckers<ED extends EntityDict & BaseEntityDict, Cxt
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 注入声明的cascade删除时的外键处理动作
|
||||||
|
for (const entity in authDict) {
|
||||||
|
const { cascadeRemove } = authDict[entity]!;
|
||||||
|
if (cascadeRemove) {
|
||||||
|
const entitiesOnEntityAttr = [] as Array<keyof ED>;
|
||||||
|
let hasAllEntity = false;
|
||||||
|
for (const attr in cascadeRemove) {
|
||||||
|
if (attr === '@entity') {
|
||||||
|
hasAllEntity = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const rel = judgeRelation(schema, entity, attr);
|
||||||
|
if (rel === 2) {
|
||||||
|
entitiesOnEntityAttr.push(attr);
|
||||||
|
checkers.push({
|
||||||
|
entity: attr,
|
||||||
|
action: 'remove',
|
||||||
|
type: 'logical',
|
||||||
|
priority: REMOVE_CASCADE_PRIORITY, // 这个checker必须在检查外键不为空的checker之前执行,否则无法完成
|
||||||
|
checker: (operation, context) => {
|
||||||
|
const { filter } = operation;
|
||||||
|
if (cascadeRemove[attr] === 'remove') {
|
||||||
|
return context.operate(entity, {
|
||||||
|
id: generateNewId(),
|
||||||
|
action: 'remove',
|
||||||
|
data: {},
|
||||||
|
filter: filter ? {
|
||||||
|
[attr]: filter,
|
||||||
|
}: undefined,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
}
|
||||||
|
return context.operate(entity, {
|
||||||
|
id: generateNewId(),
|
||||||
|
action: 'update',
|
||||||
|
data: {
|
||||||
|
entity: null,
|
||||||
|
entityId: null,
|
||||||
|
},
|
||||||
|
filter: filter ? {
|
||||||
|
[attr]: filter,
|
||||||
|
}: undefined,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(typeof rel === 'string');
|
||||||
|
checkers.push({
|
||||||
|
entity: rel,
|
||||||
|
action: 'remove',
|
||||||
|
type: 'logical',
|
||||||
|
priority: REMOVE_CASCADE_PRIORITY, // 这个checker必须在检查外键不为空的checker之前执行,否则无法完成
|
||||||
|
checker: (operation, context) => {
|
||||||
|
const { filter } = operation;
|
||||||
|
if (cascadeRemove[attr] === 'remove') {
|
||||||
|
return context.operate(entity, {
|
||||||
|
id: generateNewId(),
|
||||||
|
action: 'remove',
|
||||||
|
data: {},
|
||||||
|
filter: filter ? {
|
||||||
|
[attr]: filter,
|
||||||
|
}: undefined,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
}
|
||||||
|
return context.operate(entity, {
|
||||||
|
id: generateNewId(),
|
||||||
|
action: 'update',
|
||||||
|
data: {
|
||||||
|
[`${attr}Id`]: null,
|
||||||
|
},
|
||||||
|
filter: filter ? {
|
||||||
|
[attr]: filter,
|
||||||
|
}: undefined,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasAllEntity) {
|
||||||
|
const { attributes } = schema[entity];
|
||||||
|
const { ref } = attributes.entity;
|
||||||
|
const restEntities = difference(ref, entitiesOnEntityAttr);
|
||||||
|
for (const e of restEntities) {
|
||||||
|
checkers.push({
|
||||||
|
entity: e,
|
||||||
|
action: 'remove',
|
||||||
|
type: 'logical',
|
||||||
|
priority: REMOVE_CASCADE_PRIORITY, // 这个checker必须在检查外键不为空的checker之前执行,否则无法完成
|
||||||
|
checker: (operation, context) => {
|
||||||
|
const { filter } = operation;
|
||||||
|
if (cascadeRemove['@entity'] === 'remove') {
|
||||||
|
return context.operate(entity, {
|
||||||
|
id: generateNewId(),
|
||||||
|
action: 'remove',
|
||||||
|
data: {},
|
||||||
|
filter: filter ? {
|
||||||
|
[e]: filter,
|
||||||
|
}: undefined,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
}
|
||||||
|
return context.operate(entity, {
|
||||||
|
id: generateNewId(),
|
||||||
|
action: 'update',
|
||||||
|
data: {
|
||||||
|
entity: null,
|
||||||
|
entityId: null,
|
||||||
|
},
|
||||||
|
filter: filter ? {
|
||||||
|
[e]: filter,
|
||||||
|
}: undefined,
|
||||||
|
}, { dontCollect: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return checkers;
|
return checkers;
|
||||||
}
|
}
|
||||||
|
|
@ -17,7 +17,11 @@ export type ActionDictOfEntityDict<E extends EntityDict> = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CascadeActionItem = CascadeRelationItem;
|
||||||
|
|
||||||
// 即在cascadePath指向的对象上,有relation关系。若relation为空则不限定关系
|
// 即在cascadePath指向的对象上,有relation关系。若relation为空则不限定关系
|
||||||
export type CascadeActionAuth<A extends Action = ''> = {
|
export type CascadeActionAuth<A extends Action = ''> = {
|
||||||
[K in A | GenericAction]?: CascadeRelationItem | (CascadeRelationItem | CascadeRelationItem[])[];
|
[K in A | GenericAction]?: CascadeActionItem | (CascadeActionItem | CascadeActionItem[])[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ActionOnRemove = 'setNull' | 'remove'; // 当外键指向的对象被remove时,本对象所定义的cascade动作
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { CascadeActionAuth, RelationHierarchy, CascadeRelationAuth } from ".";
|
import { CascadeActionAuth, RelationHierarchy, CascadeRelationAuth, ActionOnRemove } from ".";
|
||||||
import { AsyncContext } from "../store/AsyncRowStore";
|
import { AsyncContext } from "../store/AsyncRowStore";
|
||||||
import { SyncContext } from "../store/SyncRowStore";
|
import { SyncContext } from "../store/SyncRowStore";
|
||||||
import { EntityDict, OperateOption, SelectOption } from "../types/Entity";
|
import { EntityDict, OperateOption, SelectOption } from "../types/Entity";
|
||||||
|
|
@ -88,6 +88,9 @@ export type Checker<ED extends EntityDict, T extends keyof ED, Cxt extends Async
|
||||||
export type AuthDef<ED extends EntityDict, T extends keyof ED> = {
|
export type AuthDef<ED extends EntityDict, T extends keyof ED> = {
|
||||||
relationAuth?: CascadeRelationAuth<NonNullable<ED[T]['Relation']>>;
|
relationAuth?: CascadeRelationAuth<NonNullable<ED[T]['Relation']>>;
|
||||||
actionAuth?: CascadeActionAuth<ED[T]['Action']>;
|
actionAuth?: CascadeActionAuth<ED[T]['Action']>;
|
||||||
|
cascadeRemove?: {
|
||||||
|
[E in keyof ED[T]['OpSchema'] | '@entity']?: ActionOnRemove;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AuthDefDict<ED extends EntityDict> = {
|
export type AuthDefDict<ED extends EntityDict> = {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue