修正了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) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var noRelationDestEntities, rewriterPromises;
var rewriterPromises;
var _this = this;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
noRelationDestEntities = [];
this.reinforceSelectionInner(entity, selection, context, noRelationDestEntities);
this.reinforceSelectionInner(entity, selection, context);
rewriterPromises = this.selectionRewriters.map(function (ele) { return ele(_this.getSchema(), entity, selection, context); });
if (!(rewriterPromises.length > 0)) return [3 /*break*/, 2];
return [4 /*yield*/, Promise.all(rewriterPromises)];
@ -44,13 +43,16 @@ var CascadeStore = /** @class */ (function (_super) {
};
CascadeStore.prototype.reinforceSelectionSync = function (entity, selection, context, option) {
var _this = this;
this.reinforceSelectionInner(entity, selection, context, []);
var rewriterPromises = this.selectionRewriters.map(function (ele) { return ele(_this.getSchema(), entity, selection, context); });
this.reinforceSelectionInner(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 filter = selection.filter, data = selection.data, sorter = selection.sorter;
var checkNode = function (projectionNode, attrs) {
var assignNecessaryProjectionAttrs = function (projectionNode, attrs) {
attrs.forEach(function (attr) {
var _a;
if (!projectionNode.hasOwnProperty(attr)) {
@ -60,108 +62,108 @@ var CascadeStore = /** @class */ (function (_super) {
}
});
};
var relevantIds = [];
if (filter) {
var toBeAssignNode_1 = {}; // 用来记录在表达式中涉及到的结点
// filter当中所关联到的属性必须在projection中
var filterNodeDict_1 = {};
var checkFilterNode_1 = function (entity2, filterNode, projectionNode) {
var _a, e_1, _b, _c, _d, _e, _f;
var necessaryAttrs = ['id'];
for (var attr in filterNode) {
if (attr === '#id') {
(0, assert_1.default)(!filterNodeDict_1[filterNode[attr]], "projection\u4E2D\u7ED3\u70B9\u7684id\u6709\u91CD\u590D, ".concat(filterNode[attr]));
Object.assign(filterNodeDict_1, (_a = {},
_a[filterNode[attr]] = projectionNode,
_a));
if (toBeAssignNode_1[filterNode[attr]]) {
checkNode(projectionNode, toBeAssignNode_1[filterNode[attr]]);
var checkFilterNode = function (entity2, filterNode, projectionNode, toBeAssignNode, filterNodeDict) {
var _a, e_1, _b, _c, _d, _e, _f;
var necessaryAttrs = ['id'];
for (var attr in filterNode) {
if (attr === '#id') {
(0, assert_1.default)(!filterNodeDict[filterNode[attr]], "projection\u4E2D\u7ED3\u70B9\u7684id\u6709\u91CD\u590D, ".concat(filterNode[attr]));
Object.assign(filterNodeDict, (_a = {},
_a[filterNode[attr]] = projectionNode,
_a));
if (toBeAssignNode[filterNode[attr]]) {
assignNecessaryProjectionAttrs(projectionNode, toBeAssignNode[filterNode[attr]]);
}
}
else if (['$and', '$or'].includes(attr)) {
try {
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 {
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_1(entity2, node, projectionNode);
}
if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
finally { if (e_1) throw e_1.error; }
}
}
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 (attr === '$not') {
checkFilterNode_1(entity2, filterNode[attr], projectionNode);
}
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 if (filterNodeDict[nodeName]) {
assignNecessaryProjectionAttrs(filterNodeDict[nodeName], exprResult[nodeName]);
}
else {
if (toBeAssignNode[nodeName]) {
(_c = toBeAssignNode[nodeName]).push.apply(_c, tslib_1.__spreadArray([], tslib_1.__read(exprResult[nodeName]), false));
}
else {
if (toBeAssignNode_1[nodeName]) {
(_c = toBeAssignNode_1[nodeName]).push.apply(_c, tslib_1.__spreadArray([], tslib_1.__read(exprResult[nodeName]), false));
}
else {
Object.assign(toBeAssignNode_1, (_d = {},
_d[nodeName] = exprResult[nodeName],
_d));
}
Object.assign(toBeAssignNode, (_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) {
// 子查询,暂时不处理
}
}
}
};
checkFilterNode_1(entity, filter, data);
assignNecessaryProjectionAttrs(projectionNode, necessaryAttrs);
}
};
var relevantIds = [];
if (filter) {
var toBeAssignNode = {}; // 用来记录在表达式中涉及到的结点
// filter当中所关联到的属性必须在projection中
var filterNodeDict = {};
checkFilterNode(entity, filter, data, toBeAssignNode, filterNodeDict);
relevantIds = (0, filter_2.getRelevantIds)(filter);
}
// sorter感觉现在取不取影响不大前端的list直接获取返回的ids了先不管之
@ -179,7 +181,7 @@ var CascadeStore = /** @class */ (function (_super) {
_a[projectionNode[attr]] = projectionNode,
_a));
if (toBeAssignNode2[projectionNode[attr]]) {
checkNode(projectionNode, toBeAssignNode2[projectionNode[attr]]);
assignNecessaryProjectionAttrs(projectionNode, toBeAssignNode2[projectionNode[attr]]);
}
}
else {
@ -187,10 +189,10 @@ var CascadeStore = /** @class */ (function (_super) {
var exprResult = (0, types_1.getAttrRefInExpression)(projectionNode[attr]);
for (var nodeName in exprResult) {
if (nodeName === '#current') {
checkNode(projectionNode, exprResult[nodeName]);
assignNecessaryProjectionAttrs(projectionNode, exprResult[nodeName]);
}
else if (projectionNodeDict[nodeName]) {
checkNode(projectionNodeDict[nodeName], exprResult[nodeName]);
assignNecessaryProjectionAttrs(projectionNodeDict[nodeName], exprResult[nodeName]);
}
else {
if (toBeAssignNode2[nodeName]) {
@ -219,18 +221,18 @@ var CascadeStore = /** @class */ (function (_super) {
checkProjectionNode(rel, projectionNode[attr]);
}
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]) {
checkNode(data_1, [rel[1]]);
assignNecessaryProjectionAttrs(data_1, [rel[1]]);
}
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
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 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 {};

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 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) {
const noRelationDestEntities: string[] = [];
this.reinforceSelectionInner(entity, selection, context, noRelationDestEntities);
private async reinforceSelectionAsync<Cxt extends AsyncContext<ED>, OP extends SelectOption>(entity: keyof ED, selection: ED[keyof ED]['Selection'], context: Cxt, option: OP) {
this.reinforceSelectionInner(entity, selection, context);
const rewriterPromises = this.selectionRewriters.map(
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) {
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) {
this.reinforceSelectionInner(entity, selection, context, []);
this.reinforceSelectionInner(entity, selection, context);
const rewriterPromises = this.selectionRewriters.map(
ele => ele(this.getSchema(), entity, selection, context)
this.selectionRewriters.forEach(
ele => {
const result = ele(this.getSchema(), entity, selection, context);
assert(!(result instanceof Promise));
}
);
}
private reinforceSelectionInner<Cxt extends AsyncContext<ED> | SyncContext<ED>, OP extends SelectOption>(
entity: keyof ED,
selection: ED[keyof ED]['Selection'],
context: Cxt,
noRelationDestEntities: string[]) {
entity: keyof ED,
selection: ED[keyof ED]['Selection'],
context: Cxt
) {
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(
(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[] = [];
if (filter) {
const toBeAssignNode: Record<string, string[]> = {}; // 用来记录在表达式中涉及到的结点
// filter当中所关联到的属性必须在projection中
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(
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);
checkFilterNode(entity, filter, data, toBeAssignNode, filterNodeDict);
relevantIds = getRelevantIds(filter);
}
@ -208,7 +194,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
[projectionNode[attr]!]: projectionNode,
});
if (toBeAssignNode2[projectionNode[attr]!]) {
checkNode(projectionNode, toBeAssignNode2[projectionNode[attr]!]);
assignNecessaryProjectionAttrs(projectionNode, toBeAssignNode2[projectionNode[attr]!]);
}
}
else {
@ -216,10 +202,10 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
const exprResult = getAttrRefInExpression(projectionNode[attr]!);
for (const nodeName in exprResult) {
if (nodeName === '#current') {
checkNode(projectionNode, exprResult[nodeName]);
assignNecessaryProjectionAttrs(projectionNode, exprResult[nodeName]);
}
else if (projectionNodeDict[nodeName]) {
checkNode(projectionNodeDict[nodeName], exprResult[nodeName]);
assignNecessaryProjectionAttrs(projectionNodeDict[nodeName], exprResult[nodeName]);
}
else {
if (toBeAssignNode2[nodeName]) {
@ -248,18 +234,18 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
checkProjectionNode(rel, projectionNode[attr]);
}
else if (rel instanceof Array && !attr.endsWith('$$aggr')) {
const { data } = projectionNode[attr];
const { data, filter } = projectionNode[attr];
if (rel[1]) {
checkNode(data, [rel[1]]);
assignNecessaryProjectionAttrs(data, [rel[1]]);
}
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
@ -312,7 +298,6 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
} 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 { AsyncContext } from "../store/AsyncRowStore";
@ -12,4 +12,10 @@ export interface AspectWrapper<ED extends EntityDict, Cxt extends AsyncContext<E
opRecords?: OpRecord<ED>[];
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 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'],
};