oak-domain 5.1.18 → 5.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/compiler/dependencyBuilder.js +99 -18
- package/lib/data/i18n.js +6 -0
- package/lib/store/AsyncRowStore.d.ts +2 -1
- package/lib/store/CascadeStore.d.ts +9 -1
- package/lib/store/CascadeStore.js +252 -267
- package/lib/store/IntrinsicCheckers.js +4 -3
- package/lib/store/checker.js +21 -6
- package/lib/types/EntityDesc.d.ts +1 -1
- package/lib/types/Exception.d.ts +3 -0
- package/lib/types/Exception.js +14 -2
- package/lib/types/Trigger.d.ts +2 -2
- package/lib/utils/validator.js +2 -2
- package/lib/utils/version.d.ts +7 -1
- package/lib/utils/version.js +13 -3
- package/package.json +1 -1
|
@@ -865,69 +865,150 @@ function buildDependency(rebuild) {
|
|
|
865
865
|
];
|
|
866
866
|
const program = ts.createProgram(templateFileList, {});
|
|
867
867
|
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
|
868
|
+
let output = true;
|
|
868
869
|
if (!isModule) {
|
|
869
870
|
const initDevFile = join(cwd, 'src', 'initialize.frontend.ts');
|
|
870
|
-
if ((0, fs_1.existsSync)(initDevFile)
|
|
871
|
-
|
|
871
|
+
if ((0, fs_1.existsSync)(initDevFile)) {
|
|
872
|
+
let tips = `[${initDevFile}]文件已经存在`;
|
|
873
|
+
if (!rebuild) {
|
|
874
|
+
tips += ',忽略构建。';
|
|
875
|
+
output = false;
|
|
876
|
+
}
|
|
877
|
+
else {
|
|
878
|
+
tips += ',将重新构建';
|
|
879
|
+
}
|
|
880
|
+
console.log(tips);
|
|
872
881
|
}
|
|
873
|
-
|
|
882
|
+
if (output) {
|
|
874
883
|
outputIntializeDev(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[0]), printer, initDevFile);
|
|
875
884
|
}
|
|
885
|
+
output = true;
|
|
876
886
|
const initProdFile = join(cwd, 'src', 'initialize.server.ts');
|
|
877
887
|
if ((0, fs_1.existsSync)(initProdFile) && !rebuild) {
|
|
878
|
-
|
|
888
|
+
let tips = `[${initProdFile}]文件已经存在`;
|
|
889
|
+
if (!rebuild) {
|
|
890
|
+
tips += ',忽略构建。';
|
|
891
|
+
output = false;
|
|
892
|
+
}
|
|
893
|
+
else {
|
|
894
|
+
tips += ',将重新构建';
|
|
895
|
+
}
|
|
896
|
+
console.log(tips);
|
|
879
897
|
}
|
|
880
|
-
|
|
898
|
+
if (output) {
|
|
881
899
|
outputIntializeProd(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[1]), printer, initProdFile);
|
|
882
900
|
}
|
|
901
|
+
output = true;
|
|
883
902
|
const initFeaturesFile = join(cwd, 'src', 'initializeFeatures.ts');
|
|
884
903
|
if ((0, fs_1.existsSync)(initFeaturesFile) && !rebuild) {
|
|
885
|
-
|
|
904
|
+
let tips = `[${initFeaturesFile}]文件已经存在`;
|
|
905
|
+
if (!rebuild) {
|
|
906
|
+
tips += ',忽略构建。';
|
|
907
|
+
output = false;
|
|
908
|
+
}
|
|
909
|
+
else {
|
|
910
|
+
tips += ',将重新构建,注意如果自定义过初始化过程,需要重新输入';
|
|
911
|
+
}
|
|
912
|
+
console.log(tips);
|
|
886
913
|
}
|
|
887
|
-
|
|
914
|
+
if (output) {
|
|
888
915
|
outputIntializeFeatures(cwd, dependencies, briefNames, program.getSourceFile(templateFileList[2]), printer, initFeaturesFile);
|
|
889
916
|
}
|
|
890
917
|
}
|
|
918
|
+
output = true;
|
|
891
919
|
const runtimeCxtFile = join(cwd, 'src', 'types', 'RuntimeCxt.ts');
|
|
892
920
|
if ((0, fs_1.existsSync)(runtimeCxtFile) && !rebuild) {
|
|
893
|
-
|
|
921
|
+
let tips = `[${runtimeCxtFile}]文件已经存在`;
|
|
922
|
+
if (!rebuild) {
|
|
923
|
+
tips += ',忽略构建。';
|
|
924
|
+
output = false;
|
|
925
|
+
}
|
|
926
|
+
else {
|
|
927
|
+
tips += ',将重新构建';
|
|
928
|
+
}
|
|
929
|
+
console.log(tips);
|
|
894
930
|
}
|
|
895
|
-
|
|
931
|
+
if (output) {
|
|
896
932
|
outputRuntimeCxt(dependencies, briefNames, program.getSourceFile(templateFileList[3]), printer, runtimeCxtFile);
|
|
897
933
|
}
|
|
934
|
+
output = true;
|
|
898
935
|
const dependentExceptionsFile = join(cwd, 'src', 'types', 'DependentExceptions.ts');
|
|
899
936
|
if ((0, fs_1.existsSync)(dependentExceptionsFile) && !rebuild) {
|
|
900
|
-
|
|
937
|
+
let tips = `[${dependentExceptionsFile}]文件已经存在`;
|
|
938
|
+
if (!rebuild) {
|
|
939
|
+
tips += ',忽略构建。';
|
|
940
|
+
output = false;
|
|
941
|
+
}
|
|
942
|
+
else {
|
|
943
|
+
tips += ',将重新构建';
|
|
944
|
+
}
|
|
945
|
+
console.log(tips);
|
|
901
946
|
}
|
|
902
|
-
|
|
947
|
+
if (output) {
|
|
903
948
|
outputDependentExceptions(dependencies, briefNames, program.getSourceFile(templateFileList[4]), printer, dependentExceptionsFile);
|
|
904
949
|
}
|
|
950
|
+
output = true;
|
|
905
951
|
const polyfillDtsFile = join(cwd, 'typings', 'polyfill.d.ts');
|
|
906
952
|
if ((0, fs_1.existsSync)(polyfillDtsFile) && !rebuild) {
|
|
907
|
-
|
|
953
|
+
let tips = `[${polyfillDtsFile}]文件已经存在`;
|
|
954
|
+
if (!rebuild) {
|
|
955
|
+
tips += ',忽略构建。';
|
|
956
|
+
output = false;
|
|
957
|
+
}
|
|
958
|
+
else {
|
|
959
|
+
tips += ',将重新构建';
|
|
960
|
+
}
|
|
961
|
+
console.log(tips);
|
|
908
962
|
}
|
|
909
|
-
|
|
963
|
+
if (output) {
|
|
910
964
|
outputPolyfillDts(dependencies, briefNames, program.getSourceFile(templateFileList[5]), printer, polyfillDtsFile);
|
|
911
965
|
}
|
|
966
|
+
output = true;
|
|
912
967
|
const featureIndexFile = join(cwd, 'src', 'features', 'index.ts');
|
|
913
968
|
if ((0, fs_1.existsSync)(featureIndexFile) && !rebuild) {
|
|
914
|
-
|
|
969
|
+
let tips = `[${featureIndexFile}]文件已经存在`;
|
|
970
|
+
if (!rebuild) {
|
|
971
|
+
tips += ',忽略构建。';
|
|
972
|
+
output = false;
|
|
973
|
+
}
|
|
974
|
+
else {
|
|
975
|
+
tips += ',将重新构建';
|
|
976
|
+
}
|
|
977
|
+
console.log(tips);
|
|
915
978
|
}
|
|
916
979
|
else {
|
|
917
980
|
outputFeatureIndex(dependencies, briefNames, program.getSourceFile(templateFileList[6]), printer, featureIndexFile, isModule);
|
|
918
981
|
}
|
|
982
|
+
output = true;
|
|
919
983
|
let contextFile = join(cwd, 'src', 'context', 'BackendRuntimeContext.ts');
|
|
920
984
|
if ((0, fs_1.existsSync)(contextFile) && !rebuild) {
|
|
921
|
-
|
|
985
|
+
let tips = `[${contextFile}]文件已经存在`;
|
|
986
|
+
if (!rebuild) {
|
|
987
|
+
tips += ',忽略构建。';
|
|
988
|
+
output = false;
|
|
989
|
+
}
|
|
990
|
+
else {
|
|
991
|
+
tips += ',将重新构建,注意如果自定义过上下文的其它方法或属性,需要重新输入';
|
|
992
|
+
}
|
|
993
|
+
console.log(tips);
|
|
922
994
|
}
|
|
923
|
-
|
|
995
|
+
if (output) {
|
|
924
996
|
outputContext(depGraph, program.getSourceFile(templateFileList[7]), printer, contextFile);
|
|
925
997
|
}
|
|
998
|
+
output = true;
|
|
926
999
|
contextFile = join(cwd, 'src', 'context', 'FrontendRuntimeContext.ts');
|
|
927
1000
|
if ((0, fs_1.existsSync)(contextFile) && !rebuild) {
|
|
928
|
-
|
|
1001
|
+
let tips = `[${contextFile}]文件已经存在`;
|
|
1002
|
+
if (!rebuild) {
|
|
1003
|
+
tips += ',忽略构建。';
|
|
1004
|
+
output = false;
|
|
1005
|
+
}
|
|
1006
|
+
else {
|
|
1007
|
+
tips += ',将重新构建,注意如果自定义过上下文的其它方法或属性,需要重新输入';
|
|
1008
|
+
}
|
|
1009
|
+
console.log(tips);
|
|
929
1010
|
}
|
|
930
|
-
|
|
1011
|
+
if (output) {
|
|
931
1012
|
outputContext(depGraph, program.getSourceFile(templateFileList[8]), printer, contextFile);
|
|
932
1013
|
}
|
|
933
1014
|
// 把各个依赖项目的一些初始化的文件拷贝过去
|
package/lib/data/i18n.js
CHANGED
|
@@ -16,6 +16,11 @@ const i18ns = [
|
|
|
16
16
|
"signatureFailed": "验签失败",
|
|
17
17
|
"attributesNull": "属性[%{attributes}]不允许为空",
|
|
18
18
|
"attributesCantUpdate": "属性[%{attributes}]不能更新",
|
|
19
|
+
"attributesFormatError": "属性[%{attributes}]格式不对,应当是[%{format}]",
|
|
20
|
+
"attributesTooLong": "属性[%{attributes}]长度过长,最长长度是[%{length}]",
|
|
21
|
+
"attributesOverMax": "属性[%{attributes}]超过最大值[%{threshold}]",
|
|
22
|
+
"attributesUnderMin": "属性[%{attributes}]低于最小值[%{threshold}]",
|
|
23
|
+
"attributesNotInEnumeration": "属性[%{attributes}]不在有效的枚举值当中",
|
|
19
24
|
"operationUnpermitted": "用户操作权限不足",
|
|
20
25
|
"dataInvisible": "用户查询权限不足",
|
|
21
26
|
"unLoggedIn": "用户未登录",
|
|
@@ -25,6 +30,7 @@ const i18ns = [
|
|
|
25
30
|
"preconditionUnset": "前置条件未满足",
|
|
26
31
|
"externalException": "外部接口调用异常",
|
|
27
32
|
"socketConnectException": "连接出现问题,请尝试刷新页面",
|
|
33
|
+
"applicationHasToUpgrade": "应用需要升级",
|
|
28
34
|
"importedDataParseError": "import的数据存在异常"
|
|
29
35
|
}
|
|
30
36
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, Context, TxnOption, OpRecord, AggregationResult, ClusterInfo } from "../types";
|
|
2
|
+
import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, Context, TxnOption, OpRecord, AggregationResult, ClusterInfo, OakException } from "../types";
|
|
3
3
|
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
|
4
4
|
import { IncomingHttpHeaders } from "http";
|
|
5
5
|
/**
|
|
@@ -61,6 +61,7 @@ export declare abstract class AsyncContext<ED extends EntityDict & BaseEntityDic
|
|
|
61
61
|
abstract initialize(data?: any, later?: boolean): Promise<void>;
|
|
62
62
|
abstract allowUserUpdate(): boolean;
|
|
63
63
|
abstract openRootMode(): () => void;
|
|
64
|
+
abstract tryDeduceException(err: Error): Promise<OakException<any> | void>;
|
|
64
65
|
}
|
|
65
66
|
export interface AsyncRowStore<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> extends RowStore<ED> {
|
|
66
67
|
operate<T extends keyof ED, OP extends OperateOption>(entity: T, operation: ED[T]['Operation'], context: Cxt, option: OP): Promise<OperationResult<ED>>;
|
|
@@ -4,6 +4,15 @@ import { OperationRewriter, RowStore, SelectionRewriter } from '../types/RowStor
|
|
|
4
4
|
import { StorageSchema } from '../types/Storage';
|
|
5
5
|
import { SyncContext } from "./SyncRowStore";
|
|
6
6
|
import { AsyncContext } from "./AsyncRowStore";
|
|
7
|
+
/**
|
|
8
|
+
* 补全一个不完整的Selection,会将需要的各种连接、过滤和排序的属性加到相应的projection上
|
|
9
|
+
* @param schema
|
|
10
|
+
* @param entity
|
|
11
|
+
* @param selection
|
|
12
|
+
* @param context
|
|
13
|
+
* @param option
|
|
14
|
+
*/
|
|
15
|
+
export declare function polishSelection<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>, Op extends SelectOption>(schema: StorageSchema<ED>, entity: keyof ED, selection: ED[keyof ED]['Selection'] | ED[keyof ED]['Aggregation'], context?: Cxt, option?: Op): void;
|
|
7
16
|
/**这个用来处理级联的select和update,对不同能力的 */
|
|
8
17
|
export declare abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> extends RowStore<ED> {
|
|
9
18
|
constructor(storageSchema: StorageSchema<ED>);
|
|
@@ -13,7 +22,6 @@ export declare abstract class CascadeStore<ED extends EntityDict & BaseEntityDic
|
|
|
13
22
|
private operationRewriters;
|
|
14
23
|
private reinforceSelectionAsync;
|
|
15
24
|
private reinforceSelectionSync;
|
|
16
|
-
private reinforceSelectionInner;
|
|
17
25
|
private reinforceOperation;
|
|
18
26
|
registerOperationRewriter(rewriter: OperationRewriter<ED, AsyncContext<ED> | SyncContext<ED>, OperateOption>): void;
|
|
19
27
|
registerSelectionRewriter(rewriter: SelectionRewriter<ED, AsyncContext<ED> | SyncContext<ED>, SelectOption>): void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CascadeStore = void 0;
|
|
3
|
+
exports.CascadeStore = exports.polishSelection = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const assert_1 = tslib_1.__importDefault(require("assert"));
|
|
6
6
|
const Entity_1 = require("../types/Entity");
|
|
@@ -14,314 +14,299 @@ const filter_2 = require("./filter");
|
|
|
14
14
|
const uuid_1 = require("../utils/uuid");
|
|
15
15
|
const entities_1 = require("../compiler/entities");
|
|
16
16
|
const projection_1 = require("../utils/projection");
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (!isAggr && !selection.distinct) {
|
|
35
|
-
this.reinforceSelectionInner(entity, selection, context, option);
|
|
36
|
-
}
|
|
37
|
-
this.selectionRewriters.forEach(ele => {
|
|
38
|
-
const result = ele(this.getSchema(), entity, selection, context, option, isAggr);
|
|
39
|
-
(0, assert_1.default)(!(result instanceof Promise));
|
|
17
|
+
/**
|
|
18
|
+
* 补全一个不完整的Selection,会将需要的各种连接、过滤和排序的属性加到相应的projection上
|
|
19
|
+
* @param schema
|
|
20
|
+
* @param entity
|
|
21
|
+
* @param selection
|
|
22
|
+
* @param context
|
|
23
|
+
* @param option
|
|
24
|
+
*/
|
|
25
|
+
function polishSelection(schema, entity, selection, context, option) {
|
|
26
|
+
const { filter, data, sorter } = selection;
|
|
27
|
+
const assignNecessaryProjectionAttrs = (projectionNode, attrs) => {
|
|
28
|
+
attrs.forEach((attr) => {
|
|
29
|
+
if (!projectionNode.hasOwnProperty(attr)) {
|
|
30
|
+
Object.assign(projectionNode, {
|
|
31
|
+
[attr]: 1,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
40
34
|
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
};
|
|
53
|
-
const checkFilterNode = (entity2, filterNode, projectionNode, toBeAssignNode, filterNodeDict) => {
|
|
54
|
-
const necessaryAttrs = ['id'];
|
|
55
|
-
for (const attr in filterNode) {
|
|
56
|
-
if (attr === '#id') {
|
|
57
|
-
(0, assert_1.default)(!filterNodeDict[filterNode[attr]], `projection中结点的id有重复, ${filterNode[attr]}`);
|
|
58
|
-
Object.assign(filterNodeDict, {
|
|
59
|
-
[filterNode[attr]]: projectionNode,
|
|
60
|
-
});
|
|
61
|
-
if (toBeAssignNode[filterNode[attr]]) {
|
|
62
|
-
assignNecessaryProjectionAttrs(projectionNode, toBeAssignNode[filterNode[attr]]);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
else if (['$and', '$or'].includes(attr)) {
|
|
66
|
-
for (const node of filterNode[attr]) {
|
|
67
|
-
checkFilterNode(entity2, node, projectionNode, toBeAssignNode, filterNodeDict);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
else if (attr === '$not') {
|
|
71
|
-
checkFilterNode(entity2, filterNode[attr], projectionNode, toBeAssignNode, filterNodeDict);
|
|
35
|
+
};
|
|
36
|
+
const checkFilterNode = (entity2, filterNode, projectionNode, toBeAssignNode, filterNodeDict) => {
|
|
37
|
+
const necessaryAttrs = ['id'];
|
|
38
|
+
for (const attr in filterNode) {
|
|
39
|
+
if (attr === '#id') {
|
|
40
|
+
(0, assert_1.default)(!filterNodeDict[filterNode[attr]], `projection中结点的id有重复, ${filterNode[attr]}`);
|
|
41
|
+
Object.assign(filterNodeDict, {
|
|
42
|
+
[filterNode[attr]]: projectionNode,
|
|
43
|
+
});
|
|
44
|
+
if (toBeAssignNode[filterNode[attr]]) {
|
|
45
|
+
assignNecessaryProjectionAttrs(projectionNode, toBeAssignNode[filterNode[attr]]);
|
|
72
46
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const { attributes } = fulltextIndex;
|
|
78
|
-
necessaryAttrs.push(...(attributes.map(ele => ele.name)));
|
|
47
|
+
}
|
|
48
|
+
else if (['$and', '$or'].includes(attr)) {
|
|
49
|
+
for (const node of filterNode[attr]) {
|
|
50
|
+
checkFilterNode(entity2, node, projectionNode, toBeAssignNode, filterNodeDict);
|
|
79
51
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
}
|
|
52
|
+
}
|
|
53
|
+
else if (attr === '$not') {
|
|
54
|
+
checkFilterNode(entity2, filterNode[attr], projectionNode, toBeAssignNode, filterNodeDict);
|
|
55
|
+
}
|
|
56
|
+
else if (attr === '$text') {
|
|
57
|
+
// 全文检索首先要有fulltext索引,其次要把fulltext的相关属性加到projection里
|
|
58
|
+
const { indexes } = schema[entity2];
|
|
59
|
+
const fulltextIndex = indexes.find(ele => ele.config && ele.config.type === 'fulltext');
|
|
60
|
+
const { attributes } = fulltextIndex;
|
|
61
|
+
necessaryAttrs.push(...(attributes.map(ele => ele.name)));
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
if (attr.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
|
|
65
|
+
const exprResult = (0, types_1.getAttrRefInExpression)(filterNode[attr]);
|
|
66
|
+
for (const nodeName in exprResult) {
|
|
67
|
+
if (nodeName === '#current') {
|
|
68
|
+
assignNecessaryProjectionAttrs(projectionNode, exprResult[nodeName]);
|
|
100
69
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const rel = this.judgeRelation(entity2, attr);
|
|
104
|
-
if (rel === 1) {
|
|
105
|
-
necessaryAttrs.push(attr);
|
|
70
|
+
else if (filterNodeDict[nodeName]) {
|
|
71
|
+
assignNecessaryProjectionAttrs(filterNodeDict[nodeName], exprResult[nodeName]);
|
|
106
72
|
}
|
|
107
|
-
else
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (!projectionNode[attr]) {
|
|
111
|
-
Object.assign(projectionNode, {
|
|
112
|
-
[attr]: {
|
|
113
|
-
id: 1,
|
|
114
|
-
}
|
|
115
|
-
});
|
|
73
|
+
else {
|
|
74
|
+
if (toBeAssignNode[nodeName]) {
|
|
75
|
+
toBeAssignNode[nodeName].push(...exprResult[nodeName]);
|
|
116
76
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
necessaryAttrs.push(`${attr}Id`);
|
|
121
|
-
if (!projectionNode[attr]) {
|
|
122
|
-
Object.assign(projectionNode, {
|
|
123
|
-
[attr]: {
|
|
124
|
-
id: 1,
|
|
125
|
-
}
|
|
77
|
+
else {
|
|
78
|
+
Object.assign(toBeAssignNode, {
|
|
79
|
+
[nodeName]: exprResult[nodeName],
|
|
126
80
|
});
|
|
127
81
|
}
|
|
128
|
-
checkFilterNode(rel, filterNode[attr], projectionNode[attr], toBeAssignNode, filterNodeDict);
|
|
129
|
-
}
|
|
130
|
-
else if (rel instanceof Array) {
|
|
131
|
-
// 子查询,暂时不处理
|
|
132
82
|
}
|
|
133
83
|
}
|
|
134
84
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const checkSorterNode = (entity2, sorterNode, projectionNode) => {
|
|
139
|
-
const checkSortAttr = (e2, sortAttr, projNode) => {
|
|
140
|
-
const necessaryAttrs = [];
|
|
141
|
-
for (const attr in sortAttr) {
|
|
142
|
-
const rel = this.judgeRelation(e2, attr);
|
|
143
|
-
if (typeof rel === 'number' && [0, 1].includes(rel)) {
|
|
85
|
+
else {
|
|
86
|
+
const rel = (0, relation_1.judgeRelation)(schema, entity2, attr);
|
|
87
|
+
if (rel === 1) {
|
|
144
88
|
necessaryAttrs.push(attr);
|
|
145
89
|
}
|
|
146
|
-
else if (
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
90
|
+
else if (rel === 2) {
|
|
91
|
+
// entity/entityId反指
|
|
92
|
+
necessaryAttrs.push('entity', 'entityId');
|
|
93
|
+
if (!projectionNode[attr]) {
|
|
94
|
+
Object.assign(projectionNode, {
|
|
95
|
+
[attr]: {
|
|
96
|
+
id: 1,
|
|
97
|
+
}
|
|
150
98
|
});
|
|
151
99
|
}
|
|
152
|
-
(
|
|
153
|
-
checkSortAttr(rel, sortAttr[attr], projNode[attr]);
|
|
100
|
+
checkFilterNode(attr, filterNode[attr], projectionNode[attr], toBeAssignNode, filterNodeDict);
|
|
154
101
|
}
|
|
155
|
-
else {
|
|
156
|
-
|
|
157
|
-
if (!
|
|
158
|
-
Object.assign(
|
|
159
|
-
[attr]: {
|
|
102
|
+
else if (typeof rel === 'string') {
|
|
103
|
+
necessaryAttrs.push(`${attr}Id`);
|
|
104
|
+
if (!projectionNode[attr]) {
|
|
105
|
+
Object.assign(projectionNode, {
|
|
106
|
+
[attr]: {
|
|
107
|
+
id: 1,
|
|
108
|
+
}
|
|
160
109
|
});
|
|
161
110
|
}
|
|
162
|
-
(
|
|
163
|
-
|
|
111
|
+
checkFilterNode(rel, filterNode[attr], projectionNode[attr], toBeAssignNode, filterNodeDict);
|
|
112
|
+
}
|
|
113
|
+
else if (rel instanceof Array) {
|
|
114
|
+
// 子查询,暂时不处理
|
|
164
115
|
}
|
|
165
116
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
sorterNode.forEach((node) => {
|
|
169
|
-
const { $attr } = node;
|
|
170
|
-
checkSortAttr(entity2, $attr, projectionNode);
|
|
171
|
-
});
|
|
172
|
-
};
|
|
173
|
-
let relevantIds = [];
|
|
174
|
-
if (filter) {
|
|
175
|
-
const toBeAssignNode = {}; // 用来记录在表达式中涉及到的结点
|
|
176
|
-
// filter当中所关联到的属性必须在projection中
|
|
177
|
-
const filterNodeDict = {};
|
|
178
|
-
checkFilterNode(entity, filter, data, toBeAssignNode, filterNodeDict);
|
|
179
|
-
relevantIds = (0, filter_2.getRelevantIds)(filter);
|
|
180
|
-
}
|
|
181
|
-
// sorter也得取了,前端需要处理排序
|
|
182
|
-
if (sorter) {
|
|
183
|
-
checkSorterNode(entity, sorter, data);
|
|
117
|
+
}
|
|
118
|
+
assignNecessaryProjectionAttrs(projectionNode, necessaryAttrs);
|
|
184
119
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
const necessaryAttrs = [
|
|
189
|
-
for (const attr in
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (
|
|
196
|
-
|
|
120
|
+
};
|
|
121
|
+
const checkSorterNode = (entity2, sorterNode, projectionNode) => {
|
|
122
|
+
const checkSortAttr = (e2, sortAttr, projNode) => {
|
|
123
|
+
const necessaryAttrs = [];
|
|
124
|
+
for (const attr in sortAttr) {
|
|
125
|
+
const rel = (0, relation_1.judgeRelation)(schema, e2, attr);
|
|
126
|
+
if (typeof rel === 'number' && [0, 1].includes(rel)) {
|
|
127
|
+
necessaryAttrs.push(attr);
|
|
128
|
+
}
|
|
129
|
+
else if (typeof rel === 'string') {
|
|
130
|
+
if (!projNode[attr]) {
|
|
131
|
+
Object.assign(projNode, {
|
|
132
|
+
[attr]: {},
|
|
133
|
+
});
|
|
197
134
|
}
|
|
135
|
+
(0, assert_1.default)(typeof sortAttr[attr] === 'object');
|
|
136
|
+
checkSortAttr(rel, sortAttr[attr], projNode[attr]);
|
|
198
137
|
}
|
|
199
138
|
else {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
else if (projectionNodeDict[nodeName]) {
|
|
207
|
-
assignNecessaryProjectionAttrs(projectionNodeDict[nodeName], exprResult[nodeName]);
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
if (toBeAssignNode2[nodeName]) {
|
|
211
|
-
toBeAssignNode2[nodeName].push(...exprResult[nodeName]);
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
Object.assign(toBeAssignNode2, {
|
|
215
|
-
[nodeName]: exprResult[nodeName],
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
139
|
+
(0, assert_1.default)(rel === 2);
|
|
140
|
+
if (!projNode[attr]) {
|
|
141
|
+
Object.assign(projNode, {
|
|
142
|
+
[attr]: {},
|
|
143
|
+
});
|
|
220
144
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
145
|
+
(0, assert_1.default)(typeof sortAttr[attr] === 'object');
|
|
146
|
+
checkSortAttr(attr, sortAttr[attr], projNode[attr]);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
assignNecessaryProjectionAttrs(projNode, necessaryAttrs);
|
|
150
|
+
};
|
|
151
|
+
sorterNode.forEach((node) => {
|
|
152
|
+
const { $attr } = node;
|
|
153
|
+
checkSortAttr(entity2, $attr, projectionNode);
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
let relevantIds = [];
|
|
157
|
+
if (filter) {
|
|
158
|
+
const toBeAssignNode = {}; // 用来记录在表达式中涉及到的结点
|
|
159
|
+
// filter当中所关联到的属性必须在projection中
|
|
160
|
+
const filterNodeDict = {};
|
|
161
|
+
checkFilterNode(entity, filter, data, toBeAssignNode, filterNodeDict);
|
|
162
|
+
relevantIds = (0, filter_2.getRelevantIds)(filter);
|
|
163
|
+
}
|
|
164
|
+
// sorter也得取了,前端需要处理排序
|
|
165
|
+
if (sorter) {
|
|
166
|
+
checkSorterNode(entity, sorter, data);
|
|
167
|
+
}
|
|
168
|
+
const toBeAssignNode2 = {}; // 用来记录在表达式中涉及到的结点
|
|
169
|
+
const projectionNodeDict = {};
|
|
170
|
+
const checkProjectionNode = (entity2, projectionNode) => {
|
|
171
|
+
const necessaryAttrs = ['id', '$$createAt$$', '$$updateAt$$']; // 有的页面依赖于其它页面取数据,有时两个页面的filter的差异会导致有一个加createAt,有一个不加,此时可能产生前台取数据不完整的异常。先统一加上
|
|
172
|
+
for (const attr in projectionNode) {
|
|
173
|
+
if (attr === '#id') {
|
|
174
|
+
(0, assert_1.default)(!projectionNodeDict[projectionNode[attr]], `projection中结点的id有重复, ${projectionNode[attr]}`);
|
|
175
|
+
Object.assign(projectionNodeDict, {
|
|
176
|
+
[projectionNode[attr]]: projectionNode,
|
|
177
|
+
});
|
|
178
|
+
if (toBeAssignNode2[projectionNode[attr]]) {
|
|
179
|
+
assignNecessaryProjectionAttrs(projectionNode, toBeAssignNode2[projectionNode[attr]]);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
if (attr.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
|
|
184
|
+
const exprResult = (0, types_1.getAttrRefInExpression)(projectionNode[attr]);
|
|
185
|
+
for (const nodeName in exprResult) {
|
|
186
|
+
if (nodeName === '#current') {
|
|
187
|
+
assignNecessaryProjectionAttrs(projectionNode, exprResult[nodeName]);
|
|
230
188
|
}
|
|
231
|
-
else if (
|
|
232
|
-
|
|
233
|
-
checkProjectionNode(rel, projectionNode[attr]);
|
|
189
|
+
else if (projectionNodeDict[nodeName]) {
|
|
190
|
+
assignNecessaryProjectionAttrs(projectionNodeDict[nodeName], exprResult[nodeName]);
|
|
234
191
|
}
|
|
235
|
-
else
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
assignNecessaryProjectionAttrs(data, [rel[1]]);
|
|
192
|
+
else {
|
|
193
|
+
if (toBeAssignNode2[nodeName]) {
|
|
194
|
+
toBeAssignNode2[nodeName].push(...exprResult[nodeName]);
|
|
239
195
|
}
|
|
240
196
|
else {
|
|
241
|
-
|
|
197
|
+
Object.assign(toBeAssignNode2, {
|
|
198
|
+
[nodeName]: exprResult[nodeName],
|
|
199
|
+
});
|
|
242
200
|
}
|
|
243
|
-
this.reinforceSelectionInner(rel[0], projectionNode[attr], context, option);
|
|
244
201
|
}
|
|
245
202
|
}
|
|
246
203
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
/* if (this.getSchema()[entity2].toModi) {
|
|
252
|
-
Object.assign(projectionNode, {
|
|
253
|
-
modi$entity: {
|
|
254
|
-
$entity: 'modi',
|
|
255
|
-
data: {
|
|
256
|
-
id: 1,
|
|
257
|
-
targetEntity: 1,
|
|
258
|
-
entity: 1,
|
|
259
|
-
entityId: 1,
|
|
260
|
-
action: 1,
|
|
261
|
-
iState: 1,
|
|
262
|
-
data: 1,
|
|
263
|
-
filter: 1,
|
|
264
|
-
$$createAt$$: 1,
|
|
265
|
-
$$updateAt$$: 1,
|
|
266
|
-
},
|
|
267
|
-
filter: {
|
|
268
|
-
iState: 'active',
|
|
269
|
-
},
|
|
204
|
+
else {
|
|
205
|
+
const rel = (0, relation_1.judgeRelation)(schema, entity2, attr);
|
|
206
|
+
if (rel === 1) {
|
|
207
|
+
necessaryAttrs.push(attr);
|
|
270
208
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
209
|
+
else if (rel === 2) {
|
|
210
|
+
// entity/entityId反指
|
|
211
|
+
necessaryAttrs.push('entity', 'entityId');
|
|
212
|
+
checkProjectionNode(attr, projectionNode[attr]);
|
|
213
|
+
}
|
|
214
|
+
else if (typeof rel === 'string') {
|
|
215
|
+
necessaryAttrs.push(`${attr}Id`);
|
|
216
|
+
checkProjectionNode(rel, projectionNode[attr]);
|
|
217
|
+
}
|
|
218
|
+
else if (rel instanceof Array && !attr.endsWith('$$aggr')) {
|
|
219
|
+
const { data, filter } = projectionNode[attr];
|
|
220
|
+
if (rel[1]) {
|
|
221
|
+
assignNecessaryProjectionAttrs(data, [rel[1]]);
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
assignNecessaryProjectionAttrs(data, ['entity', 'entityId']);
|
|
225
|
+
}
|
|
226
|
+
polishSelection(schema, rel[0], projectionNode[attr], context, option);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
assignNecessaryProjectionAttrs(projectionNode, necessaryAttrs);
|
|
231
|
+
}
|
|
232
|
+
// 如果对象上有relation关系,在此将本用户相关的relation和actionAuth全部取出
|
|
233
|
+
// 还要将actionAuth上没有relation关系但destEntity为本对象的行也全部取出,这些是指向userId的可能路径
|
|
234
|
+
// 放在这里有点怪异,暂先这样
|
|
235
|
+
if (context && !option?.dontCollect) {
|
|
236
|
+
const userId = context.getCurrentUserId(true);
|
|
237
|
+
if (userId && !entities_1.SYSTEM_RESERVE_ENTITIES.includes(entity2)) {
|
|
238
|
+
if (schema[entity2].relation && !projectionNode.userRelation$entity) {
|
|
239
|
+
Object.assign(projectionNode, {
|
|
240
|
+
userRelation$entity: {
|
|
241
|
+
$entity: 'userRelation',
|
|
242
|
+
data: {
|
|
243
|
+
id: 1,
|
|
244
|
+
entity: 1,
|
|
245
|
+
entityId: 1,
|
|
246
|
+
userId: 1,
|
|
247
|
+
relationId: 1,
|
|
248
|
+
relation: {
|
|
284
249
|
id: 1,
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
userId: 1,
|
|
288
|
-
relationId: 1,
|
|
289
|
-
relation: {
|
|
290
|
-
id: 1,
|
|
291
|
-
name: 1,
|
|
292
|
-
display: 1,
|
|
293
|
-
[Entity_1.CreateAtAttribute]: 1,
|
|
294
|
-
[Entity_1.UpdateAtAttribute]: 1,
|
|
295
|
-
},
|
|
250
|
+
name: 1,
|
|
251
|
+
display: 1,
|
|
296
252
|
[Entity_1.CreateAtAttribute]: 1,
|
|
297
253
|
[Entity_1.UpdateAtAttribute]: 1,
|
|
298
254
|
},
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
},
|
|
255
|
+
[Entity_1.CreateAtAttribute]: 1,
|
|
256
|
+
[Entity_1.UpdateAtAttribute]: 1,
|
|
302
257
|
},
|
|
303
|
-
|
|
304
|
-
|
|
258
|
+
filter: {
|
|
259
|
+
userId,
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
});
|
|
305
263
|
}
|
|
306
264
|
}
|
|
307
|
-
};
|
|
308
|
-
checkProjectionNode(entity, data);
|
|
309
|
-
if (!sorter && relevantIds.length === 0) {
|
|
310
|
-
// 如果没有sorter,就给予一个按createAt逆序的sorter
|
|
311
|
-
Object.assign(selection, {
|
|
312
|
-
sorter: [
|
|
313
|
-
{
|
|
314
|
-
$attr: {
|
|
315
|
-
$$createAt$$: 1,
|
|
316
|
-
},
|
|
317
|
-
$direction: 'desc',
|
|
318
|
-
}
|
|
319
|
-
]
|
|
320
|
-
});
|
|
321
|
-
Object.assign(data, {
|
|
322
|
-
$$createAt$$: 1,
|
|
323
|
-
});
|
|
324
265
|
}
|
|
266
|
+
};
|
|
267
|
+
checkProjectionNode(entity, data);
|
|
268
|
+
if (!sorter && relevantIds.length === 0) {
|
|
269
|
+
// 如果没有sorter,就给予一个按createAt逆序的sorter
|
|
270
|
+
Object.assign(selection, {
|
|
271
|
+
sorter: [
|
|
272
|
+
{
|
|
273
|
+
$attr: {
|
|
274
|
+
$$createAt$$: 1,
|
|
275
|
+
},
|
|
276
|
+
$direction: 'desc',
|
|
277
|
+
}
|
|
278
|
+
]
|
|
279
|
+
});
|
|
280
|
+
Object.assign(data, {
|
|
281
|
+
$$createAt$$: 1,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
exports.polishSelection = polishSelection;
|
|
286
|
+
/**这个用来处理级联的select和update,对不同能力的 */
|
|
287
|
+
class CascadeStore extends RowStore_1.RowStore {
|
|
288
|
+
constructor(storageSchema) {
|
|
289
|
+
super(storageSchema);
|
|
290
|
+
}
|
|
291
|
+
selectionRewriters = [];
|
|
292
|
+
operationRewriters = [];
|
|
293
|
+
async reinforceSelectionAsync(entity, selection, context, option, isAggr) {
|
|
294
|
+
if (!isAggr && !selection.distinct) {
|
|
295
|
+
polishSelection(this.getSchema(), entity, selection, context, option);
|
|
296
|
+
}
|
|
297
|
+
const rewriterPromises = this.selectionRewriters.map(ele => ele(this.getSchema(), entity, selection, context, option, isAggr));
|
|
298
|
+
if (rewriterPromises.length > 0) {
|
|
299
|
+
await Promise.all(rewriterPromises);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
reinforceSelectionSync(entity, selection, context, option, isAggr) {
|
|
303
|
+
if (!isAggr && !selection.distinct) {
|
|
304
|
+
polishSelection(this.getSchema(), entity, selection);
|
|
305
|
+
}
|
|
306
|
+
this.selectionRewriters.forEach(ele => {
|
|
307
|
+
const result = ele(this.getSchema(), entity, selection, context, option, isAggr);
|
|
308
|
+
(0, assert_1.default)(!(result instanceof Promise));
|
|
309
|
+
});
|
|
325
310
|
}
|
|
326
311
|
async reinforceOperation(entity, operation, context, option) {
|
|
327
312
|
await Promise.all(this.operationRewriters.map(ele => ele(this.getSchema(), entity, operation, context, option)));
|
|
@@ -273,6 +273,7 @@ function cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, restA
|
|
|
273
273
|
if (!f) {
|
|
274
274
|
return true;
|
|
275
275
|
}
|
|
276
|
+
(0, assert_1.default)(typeof f !== 'function', '此处是原来写的时候的疏漏情况,跑出来再改。by Xc 20250214');
|
|
276
277
|
// 此时看应用了success的attributes更新后,能否消除掉f中的部分条件
|
|
277
278
|
const result = (0, filter_1.analyzeFilterRelation)(entity, schema, successAttrFilter, f, true);
|
|
278
279
|
if (typeof result === 'boolean') {
|
|
@@ -325,7 +326,7 @@ function createAttrUpdateCheckers(schema, attrUpdateMatrix) {
|
|
|
325
326
|
const attrs = Object.keys(data);
|
|
326
327
|
const extras = (0, lodash_1.difference)(attrs, updateAttrs);
|
|
327
328
|
if (extras.length > 0) {
|
|
328
|
-
throw new types_1.OakAttrCantUpdateException(entity, extras
|
|
329
|
+
throw new types_1.OakAttrCantUpdateException(entity, extras);
|
|
329
330
|
}
|
|
330
331
|
const condition = attrs.map(ele => matrix[ele]);
|
|
331
332
|
const actions = condition.map(ele => ele?.actions).filter(ele => !!ele);
|
|
@@ -335,7 +336,7 @@ function createAttrUpdateCheckers(schema, attrUpdateMatrix) {
|
|
|
335
336
|
if (!a.includes(action)) {
|
|
336
337
|
// 找到不满足的那个attr
|
|
337
338
|
const attrsIllegal = attrs.filter((attr) => matrix[attr]?.actions && !matrix[attr]?.actions?.includes(action));
|
|
338
|
-
throw new types_1.OakAttrCantUpdateException(entity, attrsIllegal
|
|
339
|
+
throw new types_1.OakAttrCantUpdateException(entity, attrsIllegal);
|
|
339
340
|
}
|
|
340
341
|
}
|
|
341
342
|
const filters = condition.map(ele => {
|
|
@@ -353,7 +354,7 @@ function createAttrUpdateCheckers(schema, attrUpdateMatrix) {
|
|
|
353
354
|
if (attrs.length > 1) {
|
|
354
355
|
return cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, attrs, context);
|
|
355
356
|
}
|
|
356
|
-
throw new types_1.OakAttrCantUpdateException(entity, attrs
|
|
357
|
+
throw new types_1.OakAttrCantUpdateException(entity, attrs);
|
|
357
358
|
}
|
|
358
359
|
});
|
|
359
360
|
}
|
package/lib/store/checker.js
CHANGED
|
@@ -352,11 +352,17 @@ function checkAttributeLegal(schema, entity, data) {
|
|
|
352
352
|
case 'char':
|
|
353
353
|
case 'varchar': {
|
|
354
354
|
if (typeof data[attr] !== 'string') {
|
|
355
|
-
throw new Exception_1.OakInputIllegalException(entity, [attr],
|
|
355
|
+
throw new Exception_1.OakInputIllegalException(entity, [attr], 'error::attributesFormatError', 'oak-domain', {
|
|
356
|
+
attribtues: attr,
|
|
357
|
+
format: 'string',
|
|
358
|
+
});
|
|
356
359
|
}
|
|
357
360
|
const { length } = params;
|
|
358
361
|
if (length && data[attr].length > length) {
|
|
359
|
-
throw new Exception_1.OakInputIllegalException(entity, [attr],
|
|
362
|
+
throw new Exception_1.OakInputIllegalException(entity, [attr], 'error::attributesTooLong', 'oak-domain', {
|
|
363
|
+
attributes: attr,
|
|
364
|
+
length,
|
|
365
|
+
});
|
|
360
366
|
}
|
|
361
367
|
break;
|
|
362
368
|
}
|
|
@@ -367,21 +373,30 @@ function checkAttributeLegal(schema, entity, data) {
|
|
|
367
373
|
case 'decimal':
|
|
368
374
|
case 'money': {
|
|
369
375
|
if (typeof data[attr] !== 'number') {
|
|
370
|
-
throw new Exception_1.OakInputIllegalException(entity, [attr],
|
|
376
|
+
throw new Exception_1.OakInputIllegalException(entity, [attr], 'error::attributesFormatError', 'oak-domain', {
|
|
377
|
+
attribtues: attr,
|
|
378
|
+
format: 'number',
|
|
379
|
+
});
|
|
371
380
|
}
|
|
372
381
|
const { min, max } = params || {};
|
|
373
382
|
if (typeof min === 'number' && data[attr] < min) {
|
|
374
|
-
throw new Exception_1.OakInputIllegalException(entity, [attr],
|
|
383
|
+
throw new Exception_1.OakInputIllegalException(entity, [attr], 'error::attributesUnderMin', 'oak-domain', {
|
|
384
|
+
attributes: attr,
|
|
385
|
+
threshold: `${min}`,
|
|
386
|
+
});
|
|
375
387
|
}
|
|
376
388
|
if (typeof max === 'number' && data[attr] > max) {
|
|
377
|
-
throw new Exception_1.OakInputIllegalException(entity, [attr],
|
|
389
|
+
throw new Exception_1.OakInputIllegalException(entity, [attr], 'error::attributesOverMax', 'oak-domain', {
|
|
390
|
+
attributes: attr,
|
|
391
|
+
threshold: `${max}`,
|
|
392
|
+
});
|
|
378
393
|
}
|
|
379
394
|
break;
|
|
380
395
|
}
|
|
381
396
|
case 'enum': {
|
|
382
397
|
(0, assert_1.default)(enumeration);
|
|
383
398
|
if (!enumeration.includes(data[attr])) {
|
|
384
|
-
throw new Exception_1.OakInputIllegalException(entity, [attr],
|
|
399
|
+
throw new Exception_1.OakInputIllegalException(entity, [attr], 'error::attributesNotInEnumeration');
|
|
385
400
|
}
|
|
386
401
|
break;
|
|
387
402
|
}
|
|
@@ -18,7 +18,7 @@ export type AttrUpdateMatrix<ED extends EntityDict> = {
|
|
|
18
18
|
[T in keyof ED]?: {
|
|
19
19
|
[A in keyof ED[T]['Update']['data']]?: {
|
|
20
20
|
actions?: ED[T]['Action'][];
|
|
21
|
-
filter?: (NonNullable<ED[T]['Filter']>) | ((action: ED[T]['Action']) =>
|
|
21
|
+
filter?: (NonNullable<ED[T]['Filter']>) | ((action: ED[T]['Action']) => ED[T]['Filter'] | undefined);
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
24
|
};
|
package/lib/types/Exception.d.ts
CHANGED
|
@@ -186,6 +186,9 @@ export declare class OakExternalException<ED extends EntityDict & BaseEntityDict
|
|
|
186
186
|
export declare class OakSocketConnectException<ED extends EntityDict & BaseEntityDict> extends OakUserException<ED> {
|
|
187
187
|
constructor(message?: string, _module?: string, params?: Record<string, any>);
|
|
188
188
|
}
|
|
189
|
+
export declare class OakApplicationHasToUpgrade<ED extends EntityDict & BaseEntityDict> extends OakUserException<ED> {
|
|
190
|
+
constructor(message?: string, _module?: string, params?: Record<string, any>);
|
|
191
|
+
}
|
|
189
192
|
export declare function makeException<ED extends EntityDict & BaseEntityDict>(data: {
|
|
190
193
|
name: string;
|
|
191
194
|
message?: string;
|
package/lib/types/Exception.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.makeException = exports.OakSocketConnectException = exports.OakExternalException = exports.OakPreConditionUnsetException = exports.OakDeadlock = exports.OakCongruentRowExists = exports.OakRowLockedException = exports.OakUnloggedInException = exports.OakDataInvisibleException = exports.OakOperationUnpermittedException = exports.OakAttrCantUpdateException = exports.OakAttrNotNullException = exports.OakInputIllegalException = exports.OakRowInconsistencyException = exports.OakSignatureVerificationException = exports.OakClockDriftException = exports.OakServerProxyException = exports.OakNetworkException = exports.OakImportDataParseException = exports.OakUniqueViolationException = exports.OakUserException = exports.OakRowUnexistedException = exports.OakOperExistedException = exports.OakNoRelationDefException = exports.OakDataException = exports.OakPartialSuccess = exports.OakMakeSureByMySelfException = exports.OakRequestTimeoutException = exports.OakException = void 0;
|
|
3
|
+
exports.makeException = exports.OakApplicationHasToUpgrade = exports.OakSocketConnectException = exports.OakExternalException = exports.OakPreConditionUnsetException = exports.OakDeadlock = exports.OakCongruentRowExists = exports.OakRowLockedException = exports.OakUnloggedInException = exports.OakDataInvisibleException = exports.OakOperationUnpermittedException = exports.OakAttrCantUpdateException = exports.OakAttrNotNullException = exports.OakInputIllegalException = exports.OakRowInconsistencyException = exports.OakSignatureVerificationException = exports.OakClockDriftException = exports.OakServerProxyException = exports.OakNetworkException = exports.OakImportDataParseException = exports.OakUniqueViolationException = exports.OakUserException = exports.OakRowUnexistedException = exports.OakOperExistedException = exports.OakNoRelationDefException = exports.OakDataException = exports.OakPartialSuccess = exports.OakMakeSureByMySelfException = exports.OakRequestTimeoutException = exports.OakException = void 0;
|
|
4
4
|
const relation_1 = require("../store/relation");
|
|
5
5
|
const lodash_1 = require("../utils/lodash");
|
|
6
6
|
class OakException extends Error {
|
|
@@ -225,7 +225,9 @@ class OakInputIllegalException extends OakUserException {
|
|
|
225
225
|
attributes;
|
|
226
226
|
entity;
|
|
227
227
|
constructor(entity, attributes, message, _module, params) {
|
|
228
|
-
super(message, _module, params
|
|
228
|
+
super(message, _module, params || {
|
|
229
|
+
attributes: attributes.join(','),
|
|
230
|
+
});
|
|
229
231
|
this.entity = entity;
|
|
230
232
|
this.attributes = attributes;
|
|
231
233
|
}
|
|
@@ -423,6 +425,12 @@ class OakSocketConnectException extends OakUserException {
|
|
|
423
425
|
}
|
|
424
426
|
exports.OakSocketConnectException = OakSocketConnectException;
|
|
425
427
|
;
|
|
428
|
+
class OakApplicationHasToUpgrade extends OakUserException {
|
|
429
|
+
constructor(message, _module, params) {
|
|
430
|
+
super(message || 'error::applicationHasToUpgrade', _module || 'oak-domain', params);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
exports.OakApplicationHasToUpgrade = OakApplicationHasToUpgrade;
|
|
426
434
|
function makeException(data) {
|
|
427
435
|
const { name, message, _module, params } = data;
|
|
428
436
|
let e = undefined;
|
|
@@ -531,6 +539,10 @@ function makeException(data) {
|
|
|
531
539
|
e = new OakSignatureVerificationException(message, _module, params);
|
|
532
540
|
break;
|
|
533
541
|
}
|
|
542
|
+
case 'OakApplicationHasToUpgrade': {
|
|
543
|
+
e = new OakApplicationHasToUpgrade(message, _module, params);
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
534
546
|
default:
|
|
535
547
|
return;
|
|
536
548
|
}
|
package/lib/types/Trigger.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SelectOption, CheckerType } from ".";
|
|
2
|
-
import {
|
|
2
|
+
import { ExcludeUpdateAction } from "../actions/action";
|
|
3
3
|
import { AsyncContext } from "../store/AsyncRowStore";
|
|
4
4
|
import { SyncContext } from "../store/SyncRowStore";
|
|
5
5
|
import { EntityDict, OperateOption } from "../types/Entity";
|
|
@@ -56,7 +56,7 @@ export type CreateTrigger<ED extends EntityDict & BaseEntityDict, T extends keyo
|
|
|
56
56
|
* 只要有,就会触发trigger。要注意的是这个条件是exists而不是all
|
|
57
57
|
*/
|
|
58
58
|
export interface UpdateTriggerBase<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> extends TriggerBase<ED, T> {
|
|
59
|
-
action: Exclude<ED[T]['Action'],
|
|
59
|
+
action: Exclude<ED[T]['Action'], ExcludeUpdateAction> | Array<Exclude<ED[T]['Action'], ExcludeUpdateAction>>;
|
|
60
60
|
attributes?: keyof ED[T]['OpSchema'] | Array<keyof ED[T]['OpSchema']>;
|
|
61
61
|
mt?: ModiTurn;
|
|
62
62
|
check?: (operation: ED[T]['Update']) => boolean;
|
package/lib/utils/validator.js
CHANGED
|
@@ -119,7 +119,7 @@ function checkAttributesNotNull(entity, data, attributes, allowEmpty) {
|
|
|
119
119
|
}
|
|
120
120
|
});
|
|
121
121
|
if (attrs.length > 0) {
|
|
122
|
-
throw new types_1.OakAttrNotNullException(entity, attrs, '
|
|
122
|
+
throw new types_1.OakAttrNotNullException(entity, attrs, 'error::attributesNull');
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
exports.checkAttributesNotNull = checkAttributesNotNull;
|
|
@@ -127,7 +127,7 @@ exports.checkAttributesNotNull = checkAttributesNotNull;
|
|
|
127
127
|
function checkAttributesScope(entity, data, attributes) {
|
|
128
128
|
const attrs = attributes.filter(attr => !data.hasOwnProperty(attr));
|
|
129
129
|
if (attrs.length > 0) {
|
|
130
|
-
throw new types_1.OakInputIllegalException(entity, attrs, '
|
|
130
|
+
throw new types_1.OakInputIllegalException(entity, attrs, 'error::attributesCantUpdate');
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
exports.checkAttributesScope = checkAttributesScope;
|
package/lib/utils/version.d.ts
CHANGED
|
@@ -4,4 +4,10 @@
|
|
|
4
4
|
* @param reqVersion 比较版本
|
|
5
5
|
* @returns
|
|
6
6
|
*/
|
|
7
|
-
export declare
|
|
7
|
+
export declare function compareVersion(curVersion: string, reqVersion: string): number;
|
|
8
|
+
/**
|
|
9
|
+
* 是不是一个有效的版本号
|
|
10
|
+
* @param version
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
export declare function isVersion(version: string): boolean;
|
package/lib/utils/version.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.compareVersion = void 0;
|
|
3
|
+
exports.isVersion = exports.compareVersion = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* 版本比较
|
|
6
6
|
* @param curVersion 当前版本
|
|
7
7
|
* @param reqVersion 比较版本
|
|
8
8
|
* @returns
|
|
9
9
|
*/
|
|
10
|
-
|
|
10
|
+
function compareVersion(curVersion, reqVersion) {
|
|
11
11
|
const v1 = curVersion.split('.');
|
|
12
12
|
const v2 = reqVersion.split('.');
|
|
13
13
|
for (let i = 0; i < Math.max(v1.length, v2.length); i++) {
|
|
@@ -17,5 +17,15 @@ const compareVersion = (curVersion, reqVersion) => {
|
|
|
17
17
|
return num1 - num2;
|
|
18
18
|
}
|
|
19
19
|
return 0;
|
|
20
|
-
}
|
|
20
|
+
}
|
|
21
21
|
exports.compareVersion = compareVersion;
|
|
22
|
+
;
|
|
23
|
+
/**
|
|
24
|
+
* 是不是一个有效的版本号
|
|
25
|
+
* @param version
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
function isVersion(version) {
|
|
29
|
+
return /([1-9][0-9]*|[0-9])\.([1-9][0-9]*|[0-9])*\.([1-9][0-9]*|[0-9])*(\-[0-9A-Za-z-](\.[0-9A-Za-z-])*)*/g.test(version);
|
|
30
|
+
}
|
|
31
|
+
exports.isVersion = isVersion;
|