修正了reinforceSelection中的部分无用代码,增加了几个未来用于subscribe的结构定义

This commit is contained in:
Xu Chang 2023-08-29 13:45:19 +08:00
parent a506f2acc2
commit 060c208804
6 changed files with 246 additions and 242 deletions

View File

@ -24,13 +24,12 @@ var CascadeStore = /** @class */ (function (_super) {
} }
CascadeStore.prototype.reinforceSelectionAsync = function (entity, selection, context, option) { CascadeStore.prototype.reinforceSelectionAsync = function (entity, selection, context, option) {
return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__awaiter(this, void 0, void 0, function () {
var noRelationDestEntities, rewriterPromises; var rewriterPromises;
var _this = this; var _this = this;
return tslib_1.__generator(this, function (_a) { return tslib_1.__generator(this, function (_a) {
switch (_a.label) { switch (_a.label) {
case 0: case 0:
noRelationDestEntities = []; this.reinforceSelectionInner(entity, selection, context);
this.reinforceSelectionInner(entity, selection, context, noRelationDestEntities);
rewriterPromises = this.selectionRewriters.map(function (ele) { return ele(_this.getSchema(), entity, selection, context); }); rewriterPromises = this.selectionRewriters.map(function (ele) { return ele(_this.getSchema(), entity, selection, context); });
if (!(rewriterPromises.length > 0)) return [3 /*break*/, 2]; if (!(rewriterPromises.length > 0)) return [3 /*break*/, 2];
return [4 /*yield*/, Promise.all(rewriterPromises)]; return [4 /*yield*/, Promise.all(rewriterPromises)];
@ -44,13 +43,16 @@ var CascadeStore = /** @class */ (function (_super) {
}; };
CascadeStore.prototype.reinforceSelectionSync = function (entity, selection, context, option) { CascadeStore.prototype.reinforceSelectionSync = function (entity, selection, context, option) {
var _this = this; var _this = this;
this.reinforceSelectionInner(entity, selection, context, []); this.reinforceSelectionInner(entity, selection, context);
var rewriterPromises = this.selectionRewriters.map(function (ele) { return ele(_this.getSchema(), entity, selection, context); }); this.selectionRewriters.forEach(function (ele) {
var result = ele(_this.getSchema(), entity, selection, context);
(0, assert_1.default)(!(result instanceof Promise));
});
}; };
CascadeStore.prototype.reinforceSelectionInner = function (entity, selection, context, noRelationDestEntities) { CascadeStore.prototype.reinforceSelectionInner = function (entity, selection, context) {
var _this = this; var _this = this;
var filter = selection.filter, data = selection.data, sorter = selection.sorter; var filter = selection.filter, data = selection.data, sorter = selection.sorter;
var checkNode = function (projectionNode, attrs) { var assignNecessaryProjectionAttrs = function (projectionNode, attrs) {
attrs.forEach(function (attr) { attrs.forEach(function (attr) {
var _a; var _a;
if (!projectionNode.hasOwnProperty(attr)) { if (!projectionNode.hasOwnProperty(attr)) {
@ -60,108 +62,108 @@ var CascadeStore = /** @class */ (function (_super) {
} }
}); });
}; };
var relevantIds = []; var checkFilterNode = function (entity2, filterNode, projectionNode, toBeAssignNode, filterNodeDict) {
if (filter) { var _a, e_1, _b, _c, _d, _e, _f;
var toBeAssignNode_1 = {}; // 用来记录在表达式中涉及到的结点 var necessaryAttrs = ['id'];
// filter当中所关联到的属性必须在projection中 for (var attr in filterNode) {
var filterNodeDict_1 = {}; if (attr === '#id') {
var checkFilterNode_1 = function (entity2, filterNode, projectionNode) { (0, assert_1.default)(!filterNodeDict[filterNode[attr]], "projection\u4E2D\u7ED3\u70B9\u7684id\u6709\u91CD\u590D, ".concat(filterNode[attr]));
var _a, e_1, _b, _c, _d, _e, _f; Object.assign(filterNodeDict, (_a = {},
var necessaryAttrs = ['id']; _a[filterNode[attr]] = projectionNode,
for (var attr in filterNode) { _a));
if (attr === '#id') { if (toBeAssignNode[filterNode[attr]]) {
(0, assert_1.default)(!filterNodeDict_1[filterNode[attr]], "projection\u4E2D\u7ED3\u70B9\u7684id\u6709\u91CD\u590D, ".concat(filterNode[attr])); assignNecessaryProjectionAttrs(projectionNode, toBeAssignNode[filterNode[attr]]);
Object.assign(filterNodeDict_1, (_a = {}, }
_a[filterNode[attr]] = projectionNode, }
_a)); else if (['$and', '$or'].includes(attr)) {
if (toBeAssignNode_1[filterNode[attr]]) { try {
checkNode(projectionNode, toBeAssignNode_1[filterNode[attr]]); for (var _g = (e_1 = void 0, tslib_1.__values(filterNode[attr])), _h = _g.next(); !_h.done; _h = _g.next()) {
var node = _h.value;
checkFilterNode(entity2, node, projectionNode, toBeAssignNode, filterNodeDict);
} }
} }
else if (['$and', '$or'].includes(attr)) { catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try { try {
for (var _g = (e_1 = void 0, tslib_1.__values(filterNode[attr])), _h = _g.next(); !_h.done; _h = _g.next()) { if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
var node = _h.value;
checkFilterNode_1(entity2, node, projectionNode);
}
} }
catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { if (e_1) throw e_1.error; }
finally { }
try { }
if (_h && !_h.done && (_b = _g.return)) _b.call(_g); else if (attr === '$not') {
checkFilterNode(entity2, filterNode[attr], projectionNode, toBeAssignNode, filterNodeDict);
}
else if (attr === '$text') {
// 全文检索首先要有fulltext索引其次要把fulltext的相关属性加到projection里
var indexes = _this.getSchema()[entity2].indexes;
var fulltextIndex = indexes.find(function (ele) { return ele.config && ele.config.type === 'fulltext'; });
var attributes = fulltextIndex.attributes;
necessaryAttrs.push.apply(necessaryAttrs, tslib_1.__spreadArray([], tslib_1.__read((attributes.map(function (ele) { return ele.name; }))), false));
}
else {
if (attr.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
var exprResult = (0, types_1.getAttrRefInExpression)(filterNode[attr]);
for (var nodeName in exprResult) {
if (nodeName === '#current') {
assignNecessaryProjectionAttrs(projectionNode, exprResult[nodeName]);
} }
finally { if (e_1) throw e_1.error; } else if (filterNodeDict[nodeName]) {
} assignNecessaryProjectionAttrs(filterNodeDict[nodeName], exprResult[nodeName]);
} }
else if (attr === '$not') { else {
checkFilterNode_1(entity2, filterNode[attr], projectionNode); if (toBeAssignNode[nodeName]) {
} (_c = toBeAssignNode[nodeName]).push.apply(_c, tslib_1.__spreadArray([], tslib_1.__read(exprResult[nodeName]), false));
else if (attr === '$text') {
// 全文检索首先要有fulltext索引其次要把fulltext的相关属性加到projection里
var indexes = _this.getSchema()[entity2].indexes;
var fulltextIndex = indexes.find(function (ele) { return ele.config && ele.config.type === 'fulltext'; });
var attributes = fulltextIndex.attributes;
necessaryAttrs.push.apply(necessaryAttrs, tslib_1.__spreadArray([], tslib_1.__read((attributes.map(function (ele) { return ele.name; }))), false));
}
else {
if (attr.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
var exprResult = (0, types_1.getAttrRefInExpression)(filterNode[attr]);
for (var nodeName in exprResult) {
if (nodeName === '#current') {
checkNode(projectionNode, exprResult[nodeName]);
}
else if (filterNodeDict_1[nodeName]) {
checkNode(filterNodeDict_1[nodeName], exprResult[nodeName]);
} }
else { else {
if (toBeAssignNode_1[nodeName]) { Object.assign(toBeAssignNode, (_d = {},
(_c = toBeAssignNode_1[nodeName]).push.apply(_c, tslib_1.__spreadArray([], tslib_1.__read(exprResult[nodeName]), false)); _d[nodeName] = exprResult[nodeName],
} _d));
else {
Object.assign(toBeAssignNode_1, (_d = {},
_d[nodeName] = exprResult[nodeName],
_d));
}
} }
} }
} }
else {
var rel = _this.judgeRelation(entity2, attr);
if (rel === 1) {
necessaryAttrs.push(attr);
}
else if (rel === 2) {
// entity/entityId反指
necessaryAttrs.push('entity', 'entityId');
if (!projectionNode[attr]) {
Object.assign(projectionNode, (_e = {},
_e[attr] = {
id: 1,
},
_e));
}
checkFilterNode_1(attr, filterNode[attr], projectionNode[attr]);
}
else if (typeof rel === 'string') {
necessaryAttrs.push("".concat(attr, "Id"));
if (!projectionNode[attr]) {
Object.assign(projectionNode, (_f = {},
_f[attr] = {
id: 1,
},
_f));
}
checkFilterNode_1(rel, filterNode[attr], projectionNode[attr]);
}
else if (rel instanceof Array) {
// 现在filter中还不支持一对多的语义先放着吧
}
}
} }
checkNode(projectionNode, necessaryAttrs); else {
var rel = _this.judgeRelation(entity2, attr);
if (rel === 1) {
necessaryAttrs.push(attr);
}
else if (rel === 2) {
// entity/entityId反指
necessaryAttrs.push('entity', 'entityId');
if (!projectionNode[attr]) {
Object.assign(projectionNode, (_e = {},
_e[attr] = {
id: 1,
},
_e));
}
checkFilterNode(attr, filterNode[attr], projectionNode[attr], toBeAssignNode, filterNodeDict);
}
else if (typeof rel === 'string') {
necessaryAttrs.push("".concat(attr, "Id"));
if (!projectionNode[attr]) {
Object.assign(projectionNode, (_f = {},
_f[attr] = {
id: 1,
},
_f));
}
checkFilterNode(rel, filterNode[attr], projectionNode[attr], toBeAssignNode, filterNodeDict);
}
else if (rel instanceof Array) {
// 子查询,暂时不处理
}
}
} }
}; assignNecessaryProjectionAttrs(projectionNode, necessaryAttrs);
checkFilterNode_1(entity, filter, data); }
};
var relevantIds = [];
if (filter) {
var toBeAssignNode = {}; // 用来记录在表达式中涉及到的结点
// filter当中所关联到的属性必须在projection中
var filterNodeDict = {};
checkFilterNode(entity, filter, data, toBeAssignNode, filterNodeDict);
relevantIds = (0, filter_2.getRelevantIds)(filter); relevantIds = (0, filter_2.getRelevantIds)(filter);
} }
// sorter感觉现在取不取影响不大前端的list直接获取返回的ids了先不管之 // sorter感觉现在取不取影响不大前端的list直接获取返回的ids了先不管之
@ -179,7 +181,7 @@ var CascadeStore = /** @class */ (function (_super) {
_a[projectionNode[attr]] = projectionNode, _a[projectionNode[attr]] = projectionNode,
_a)); _a));
if (toBeAssignNode2[projectionNode[attr]]) { if (toBeAssignNode2[projectionNode[attr]]) {
checkNode(projectionNode, toBeAssignNode2[projectionNode[attr]]); assignNecessaryProjectionAttrs(projectionNode, toBeAssignNode2[projectionNode[attr]]);
} }
} }
else { else {
@ -187,10 +189,10 @@ var CascadeStore = /** @class */ (function (_super) {
var exprResult = (0, types_1.getAttrRefInExpression)(projectionNode[attr]); var exprResult = (0, types_1.getAttrRefInExpression)(projectionNode[attr]);
for (var nodeName in exprResult) { for (var nodeName in exprResult) {
if (nodeName === '#current') { if (nodeName === '#current') {
checkNode(projectionNode, exprResult[nodeName]); assignNecessaryProjectionAttrs(projectionNode, exprResult[nodeName]);
} }
else if (projectionNodeDict[nodeName]) { else if (projectionNodeDict[nodeName]) {
checkNode(projectionNodeDict[nodeName], exprResult[nodeName]); assignNecessaryProjectionAttrs(projectionNodeDict[nodeName], exprResult[nodeName]);
} }
else { else {
if (toBeAssignNode2[nodeName]) { if (toBeAssignNode2[nodeName]) {
@ -219,18 +221,18 @@ var CascadeStore = /** @class */ (function (_super) {
checkProjectionNode(rel, projectionNode[attr]); checkProjectionNode(rel, projectionNode[attr]);
} }
else if (rel instanceof Array && !attr.endsWith('$$aggr')) { else if (rel instanceof Array && !attr.endsWith('$$aggr')) {
var data_1 = projectionNode[attr].data; var _d = projectionNode[attr], data_1 = _d.data, filter_3 = _d.filter;
if (rel[1]) { if (rel[1]) {
checkNode(data_1, [rel[1]]); assignNecessaryProjectionAttrs(data_1, [rel[1]]);
} }
else { else {
checkNode(data_1, ['entity', 'entityId']); assignNecessaryProjectionAttrs(data_1, ['entity', 'entityId']);
} }
_this.reinforceSelectionInner(rel[0], projectionNode[attr], context, noRelationDestEntities); _this.reinforceSelectionInner(rel[0], projectionNode[attr], context);
} }
} }
} }
checkNode(projectionNode, necessaryAttrs); assignNecessaryProjectionAttrs(projectionNode, necessaryAttrs);
} }
// 如果对象中指向一对多的Modi此时加上指向Modi的projection // 如果对象中指向一对多的Modi此时加上指向Modi的projection
if (_this.getSchema()[entity2].toModi) { if (_this.getSchema()[entity2].toModi) {
@ -281,7 +283,6 @@ var CascadeStore = /** @class */ (function (_super) {
}, },
}); });
} }
noRelationDestEntities.push(entity2);
} }
} }
}; };

View File

@ -190,4 +190,9 @@ export declare type AuthDeduceRelationMap<ED extends EntityDict> = {
}; };
export declare type SelectFreeEntities<ED extends EntityDict> = (keyof ED)[]; export declare type SelectFreeEntities<ED extends EntityDict> = (keyof ED)[];
export declare type OtmKey<K extends string> = K | `${K}$${number}`; export declare type OtmKey<K extends string> = K | `${K}$${number}`;
export interface SubDataDef<ED extends EntityDict, T extends keyof ED> {
id: string;
entity: T;
filter: ED[T]['Selection']['filter'];
}
export {}; export {};

View File

@ -12,3 +12,4 @@ exports.initinctiveAttributes = [exports.PrimaryKeyAttribute, exports.TriggerDat
; ;
; ;
; ;
;

View File

@ -29,38 +29,14 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
private selectionRewriters: SelectionRewriter<ED, AsyncContext<ED> | SyncContext<ED>>[] = []; private selectionRewriters: SelectionRewriter<ED, AsyncContext<ED> | SyncContext<ED>>[] = [];
private operationRewriters: OperationRewriter<ED, AsyncContext<ED> | SyncContext<ED>>[] = []; private operationRewriters: OperationRewriter<ED, AsyncContext<ED> | SyncContext<ED>>[] = [];
private async reinforceSelectionAsync<Cxt extends AsyncContext<ED>, OP extends SelectOption>(entity: keyof ED, selection: ED[keyof ED]['Selection'], context: Cxt, option: OP) { private async reinforceSelectionAsync<Cxt extends AsyncContext<ED>, OP extends SelectOption>(entity: keyof ED, selection: ED[keyof ED]['Selection'], context: Cxt, option: OP) {
const noRelationDestEntities: string[] = [];
this.reinforceSelectionInner(entity, selection, context, noRelationDestEntities); this.reinforceSelectionInner(entity, selection, context);
const rewriterPromises = this.selectionRewriters.map( const rewriterPromises = this.selectionRewriters.map(
ele => ele(this.getSchema(), entity, selection, context) ele => ele(this.getSchema(), entity, selection, context)
); );
// 这个设计每次都要取actionAuth的数据感觉不是很优雅。by Xc 20230722
// 这个设计废除了前台页面自己来取需要的actionAUth通过cache的缓存和KeepFresh机制来减少对后台数据的访问
/* if (noRelationDestEntities.length > 0 && !option.dontCollect) {
rewriterPromises.push(
context.select('actionAuth', {
data: {
id: 1,
deActions: 1,
destEntity: 1,
paths: 1,
relationId: 1,
},
filter: {
relationId: {
$exists: false,
},
destEntity: {
$in: noRelationDestEntities,
},
},
}, {}) as any
);
} */
if (rewriterPromises.length > 0) { if (rewriterPromises.length > 0) {
await Promise.all(rewriterPromises); await Promise.all(rewriterPromises);
@ -68,21 +44,24 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
} }
private reinforceSelectionSync<Cxt extends SyncContext<ED>, OP extends SelectOption>(entity: keyof ED, selection: ED[keyof ED]['Selection'], context: Cxt, option: OP) { private reinforceSelectionSync<Cxt extends SyncContext<ED>, OP extends SelectOption>(entity: keyof ED, selection: ED[keyof ED]['Selection'], context: Cxt, option: OP) {
this.reinforceSelectionInner(entity, selection, context, []); this.reinforceSelectionInner(entity, selection, context);
const rewriterPromises = this.selectionRewriters.map( this.selectionRewriters.forEach(
ele => ele(this.getSchema(), entity, selection, context) ele => {
const result = ele(this.getSchema(), entity, selection, context);
assert(!(result instanceof Promise));
}
); );
} }
private reinforceSelectionInner<Cxt extends AsyncContext<ED> | SyncContext<ED>, OP extends SelectOption>( private reinforceSelectionInner<Cxt extends AsyncContext<ED> | SyncContext<ED>, OP extends SelectOption>(
entity: keyof ED, entity: keyof ED,
selection: ED[keyof ED]['Selection'], selection: ED[keyof ED]['Selection'],
context: Cxt, context: Cxt
noRelationDestEntities: string[]) { ) {
const { filter, data, sorter } = selection; const { filter, data, sorter } = selection;
const checkNode = (projectionNode: ED[keyof ED]['Selection']['data'], attrs: string[]) => { const assignNecessaryProjectionAttrs = (projectionNode: ED[keyof ED]['Selection']['data'], attrs: string[]) => {
attrs.forEach( attrs.forEach(
(attr) => { (attr) => {
if (!projectionNode.hasOwnProperty(attr)) { if (!projectionNode.hasOwnProperty(attr)) {
@ -94,102 +73,109 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
); );
}; };
const checkFilterNode = (
entity2: keyof ED,
filterNode: ED[keyof ED]['Selection']['filter'],
projectionNode: ED[keyof ED]['Selection']['data'],
toBeAssignNode: Record<string, string[]>,
filterNodeDict: Record<string, ED[keyof ED]['Selection']['data']>) => {
const necessaryAttrs: string[] = ['id'];
for (const attr in filterNode) {
if (attr === '#id') {
assert(!filterNodeDict[filterNode[attr]!], `projection中结点的id有重复, ${filterNode[attr]}`);
Object.assign(filterNodeDict, {
[filterNode[attr]!]: projectionNode,
});
if (toBeAssignNode[filterNode[attr]!]) {
assignNecessaryProjectionAttrs(projectionNode, toBeAssignNode[filterNode[attr]!]);
}
}
else if (['$and', '$or'].includes(attr)) {
for (const node of filterNode[attr]!) {
checkFilterNode(entity2, node, projectionNode, toBeAssignNode, filterNodeDict);
}
}
else if (attr === '$not') {
checkFilterNode(entity2, filterNode[attr]!, projectionNode, toBeAssignNode, filterNodeDict);
}
else if (attr === '$text') {
// 全文检索首先要有fulltext索引其次要把fulltext的相关属性加到projection里
const { indexes } = this.getSchema()[entity2];
const fulltextIndex = indexes!.find(
ele => ele.config && ele.config.type === 'fulltext'
);
const { attributes } = fulltextIndex!;
necessaryAttrs.push(...(attributes.map(ele => ele.name as string)));
}
else {
if (attr.toLowerCase().startsWith(EXPRESSION_PREFIX)) {
const exprResult = getAttrRefInExpression(filterNode[attr]!);
for (const nodeName in exprResult) {
if (nodeName === '#current') {
assignNecessaryProjectionAttrs(projectionNode, exprResult[nodeName]);
}
else if (filterNodeDict[nodeName]) {
assignNecessaryProjectionAttrs(filterNodeDict[nodeName], exprResult[nodeName]);
}
else {
if (toBeAssignNode[nodeName]) {
toBeAssignNode[nodeName].push(...exprResult[nodeName]);
}
else {
Object.assign(toBeAssignNode, {
[nodeName]: exprResult[nodeName],
});
}
}
}
}
else {
const rel = this.judgeRelation(entity2, attr);
if (rel === 1) {
necessaryAttrs.push(attr);
}
else if (rel === 2) {
// entity/entityId反指
necessaryAttrs.push('entity', 'entityId');
if (!projectionNode[attr]) {
Object.assign(projectionNode, {
[attr]: {
id: 1,
}
});
}
checkFilterNode(attr, filterNode[attr]!, projectionNode[attr], toBeAssignNode, filterNodeDict);
}
else if (typeof rel === 'string') {
necessaryAttrs.push(`${attr}Id`);
if (!projectionNode[attr]) {
Object.assign(projectionNode, {
[attr]: {
id: 1,
}
});
}
checkFilterNode(rel, filterNode[attr]!, projectionNode[attr], toBeAssignNode, filterNodeDict);
}
else if (rel instanceof Array) {
// 子查询,暂时不处理
}
}
}
assignNecessaryProjectionAttrs(projectionNode, necessaryAttrs);
}
};
let relevantIds: string[] = []; let relevantIds: string[] = [];
if (filter) { if (filter) {
const toBeAssignNode: Record<string, string[]> = {}; // 用来记录在表达式中涉及到的结点 const toBeAssignNode: Record<string, string[]> = {}; // 用来记录在表达式中涉及到的结点
// filter当中所关联到的属性必须在projection中 // filter当中所关联到的属性必须在projection中
const filterNodeDict: Record<string, ED[keyof ED]['Selection']['data']> = {}; const filterNodeDict: Record<string, ED[keyof ED]['Selection']['data']> = {};
const checkFilterNode = (entity2: keyof ED, filterNode: ED[keyof ED]['Selection']['filter'], projectionNode: ED[keyof ED]['Selection']['data']) => {
const necessaryAttrs: string[] = ['id'];
for (const attr in filterNode) {
if (attr === '#id') {
assert(!filterNodeDict[filterNode[attr]!], `projection中结点的id有重复, ${filterNode[attr]}`);
Object.assign(filterNodeDict, {
[filterNode[attr]!]: projectionNode,
});
if (toBeAssignNode[filterNode[attr]!]) {
checkNode(projectionNode, toBeAssignNode[filterNode[attr]!]);
}
}
else if (['$and', '$or'].includes(attr)) {
for (const node of filterNode[attr]!) {
checkFilterNode(entity2, node, projectionNode);
}
}
else if (attr === '$not') {
checkFilterNode(entity2, filterNode[attr]!, projectionNode);
}
else if (attr === '$text') {
// 全文检索首先要有fulltext索引其次要把fulltext的相关属性加到projection里
const { indexes } = this.getSchema()[entity2];
const fulltextIndex = indexes!.find( checkFilterNode(entity, filter, data, toBeAssignNode, filterNodeDict);
ele => ele.config && ele.config.type === 'fulltext'
);
const { attributes } = fulltextIndex!;
necessaryAttrs.push(...(attributes.map(ele => ele.name as string)));
}
else {
if (attr.toLowerCase().startsWith(EXPRESSION_PREFIX)) {
const exprResult = getAttrRefInExpression(filterNode[attr]!);
for (const nodeName in exprResult) {
if (nodeName === '#current') {
checkNode(projectionNode, exprResult[nodeName]);
}
else if (filterNodeDict[nodeName]) {
checkNode(filterNodeDict[nodeName], exprResult[nodeName]);
}
else {
if (toBeAssignNode[nodeName]) {
toBeAssignNode[nodeName].push(...exprResult[nodeName]);
}
else {
Object.assign(toBeAssignNode, {
[nodeName]: exprResult[nodeName],
});
}
}
}
}
else {
const rel = this.judgeRelation(entity2, attr);
if (rel === 1) {
necessaryAttrs.push(attr);
}
else if (rel === 2) {
// entity/entityId反指
necessaryAttrs.push('entity', 'entityId');
if (!projectionNode[attr]) {
Object.assign(projectionNode, {
[attr]: {
id: 1,
}
});
}
checkFilterNode(attr, filterNode[attr]!, projectionNode[attr]);
}
else if (typeof rel === 'string') {
necessaryAttrs.push(`${attr}Id`);
if (!projectionNode[attr]) {
Object.assign(projectionNode, {
[attr]: {
id: 1,
}
});
}
checkFilterNode(rel, filterNode[attr]!, projectionNode[attr]);
}
else if (rel instanceof Array) {
// 现在filter中还不支持一对多的语义先放着吧
}
}
}
checkNode(projectionNode, necessaryAttrs);
}
};
checkFilterNode(entity, filter, data);
relevantIds = getRelevantIds(filter); relevantIds = getRelevantIds(filter);
} }
@ -208,7 +194,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
[projectionNode[attr]!]: projectionNode, [projectionNode[attr]!]: projectionNode,
}); });
if (toBeAssignNode2[projectionNode[attr]!]) { if (toBeAssignNode2[projectionNode[attr]!]) {
checkNode(projectionNode, toBeAssignNode2[projectionNode[attr]!]); assignNecessaryProjectionAttrs(projectionNode, toBeAssignNode2[projectionNode[attr]!]);
} }
} }
else { else {
@ -216,10 +202,10 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
const exprResult = getAttrRefInExpression(projectionNode[attr]!); const exprResult = getAttrRefInExpression(projectionNode[attr]!);
for (const nodeName in exprResult) { for (const nodeName in exprResult) {
if (nodeName === '#current') { if (nodeName === '#current') {
checkNode(projectionNode, exprResult[nodeName]); assignNecessaryProjectionAttrs(projectionNode, exprResult[nodeName]);
} }
else if (projectionNodeDict[nodeName]) { else if (projectionNodeDict[nodeName]) {
checkNode(projectionNodeDict[nodeName], exprResult[nodeName]); assignNecessaryProjectionAttrs(projectionNodeDict[nodeName], exprResult[nodeName]);
} }
else { else {
if (toBeAssignNode2[nodeName]) { if (toBeAssignNode2[nodeName]) {
@ -248,18 +234,18 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
checkProjectionNode(rel, projectionNode[attr]); checkProjectionNode(rel, projectionNode[attr]);
} }
else if (rel instanceof Array && !attr.endsWith('$$aggr')) { else if (rel instanceof Array && !attr.endsWith('$$aggr')) {
const { data } = projectionNode[attr]; const { data, filter } = projectionNode[attr];
if (rel[1]) { if (rel[1]) {
checkNode(data, [rel[1]]); assignNecessaryProjectionAttrs(data, [rel[1]]);
} }
else { else {
checkNode(data, ['entity', 'entityId']); assignNecessaryProjectionAttrs(data, ['entity', 'entityId']);
} }
this.reinforceSelectionInner(rel[0], projectionNode[attr], context, noRelationDestEntities); this.reinforceSelectionInner(rel[0], projectionNode[attr], context);
} }
} }
} }
checkNode(projectionNode, necessaryAttrs); assignNecessaryProjectionAttrs(projectionNode, necessaryAttrs);
} }
// 如果对象中指向一对多的Modi此时加上指向Modi的projection // 如果对象中指向一对多的Modi此时加上指向Modi的projection
@ -312,7 +298,6 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
} as ED['userRelation']['Selection'], } as ED['userRelation']['Selection'],
}); });
} }
noRelationDestEntities.push(entity2 as string);
} }
} }
}; };

View File

@ -1,4 +1,4 @@
import { EntityDict } from "./Entity"; import { EntityDict, SubDataDef } from "./Entity";
import { OpRecord } from "./Entity"; import { OpRecord } from "./Entity";
import { AsyncContext } from "../store/AsyncRowStore"; import { AsyncContext } from "../store/AsyncRowStore";
@ -12,4 +12,10 @@ export interface AspectWrapper<ED extends EntityDict, Cxt extends AsyncContext<E
opRecords?: OpRecord<ED>[]; opRecords?: OpRecord<ED>[];
message?: string | null; message?: string | null;
}>; }>;
/* sub: (data: Array<SubDataDef<ED, keyof ED>>) => Promise<void>;
unsub: (ids: string[]) => Promise<void>;
registerSubCallback: (callback: (records: OpRecord<ED>[]) => void) => Promise<void>; */
}; };

View File

@ -268,3 +268,9 @@ export type AuthDeduceRelationMap<ED extends EntityDict> = {
export type SelectFreeEntities<ED extends EntityDict> = (keyof ED)[]; export type SelectFreeEntities<ED extends EntityDict> = (keyof ED)[];
// 一对多的键值的扩展 // 一对多的键值的扩展
export type OtmKey<K extends string> = K | `${K}$${number}`; export type OtmKey<K extends string> = K | `${K}$${number}`;
export interface SubDataDef<ED extends EntityDict, T extends keyof ED> {
id: string;
entity: T,
filter: ED[T]['Selection']['filter'],
};