76 lines
2.5 KiB
TypeScript
76 lines
2.5 KiB
TypeScript
import assert from "assert";
|
|
import { EntityDict } from "../base-app-domain";
|
|
import { EXPRESSION_PREFIX } from "../types/Demand";
|
|
import { EntityDict as BaseEntityDict, initinctiveAttributes } from "../types/Entity";
|
|
import { StorageSchema } from "../types/Storage";
|
|
|
|
/**
|
|
* 判断对象和属性之间的关系
|
|
* @param schema
|
|
* @param entity
|
|
* @param attr
|
|
* @param row
|
|
* @returns
|
|
*/
|
|
export function judgeRelation<ED extends EntityDict & BaseEntityDict>(schema: StorageSchema<ED>, entity: keyof ED, attr: string, allowUnrecognized?: boolean) {
|
|
const { [entity]: { attributes } } = schema;
|
|
|
|
if (attr.startsWith(EXPRESSION_PREFIX) || attr.startsWith('#')) {
|
|
// 表达式属性或者metadata
|
|
return 0;
|
|
}
|
|
|
|
if (attributes.hasOwnProperty(attr) || initinctiveAttributes.includes(attr)) {
|
|
// 原生属性
|
|
return 1;
|
|
}
|
|
|
|
if (attr.includes('$')) {
|
|
const firstDelimiter = attr.indexOf('$');
|
|
const entity2 = attr.slice(0, firstDelimiter);
|
|
assert (schema.hasOwnProperty(entity2));
|
|
const secondDelimiter = attr.indexOf('$', firstDelimiter + 1);
|
|
const foreignKey = attr.slice(firstDelimiter + 1, secondDelimiter > 0 ? secondDelimiter : attr.length);
|
|
const { [entity2]: { attributes: attributes2 } } = schema;
|
|
|
|
if (foreignKey === 'entity') {
|
|
// 基于反指对象的反向关联
|
|
return [entity2];
|
|
}
|
|
else if (attributes2.hasOwnProperty(`${foreignKey}Id`)
|
|
&& attributes2[`${foreignKey}Id`].type === 'ref'
|
|
&& attributes2[`${foreignKey}Id`].ref === entity) {
|
|
// 基于外键的反向关联
|
|
return [entity2, `${foreignKey}Id`];
|
|
}
|
|
else {
|
|
// 这种情况应该不会跑到
|
|
assert(false);
|
|
}
|
|
}
|
|
else if ((attributes.hasOwnProperty(`${attr}Id`))){
|
|
const { type, ref } = attributes[`${attr}Id`];
|
|
if (type === 'ref') {
|
|
return ref!;
|
|
}
|
|
return 1;
|
|
}
|
|
else if (attributes.hasOwnProperty('entity')
|
|
&& attributes.hasOwnProperty('entityId')
|
|
&& schema.hasOwnProperty(attr)) {
|
|
assert(attributes.entity.ref!.includes(attr), '不应当出现的case');
|
|
// 反向指针的外键
|
|
return 2;
|
|
}
|
|
else {
|
|
if(initinctiveAttributes.includes(attr)) {
|
|
return 1;
|
|
}
|
|
else if (allowUnrecognized) {
|
|
return -1;
|
|
}
|
|
else {
|
|
throw new Error(`${entity as string}对象中的${attr}属性找不到`);
|
|
}
|
|
}
|
|
} |