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.
@@ -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) && !rebuild) {
871
- console.log(`[${initDevFile}]文件已经存在,无需构建启动文件`);
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
- else {
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
- console.log(`[${initProdFile}]文件已经存在,无需构建启动文件`);
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
- else {
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
- console.log(`[${initFeaturesFile}]文件已经存在,无需构建启动文件`);
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
- else {
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
- console.log(`[${runtimeCxtFile}]文件已经存在,无需构建启动文件`);
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
- else {
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
- console.log(`[${dependentExceptionsFile}]文件已经存在,无需构建启动文件`);
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
- else {
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
- console.log(`[${polyfillDtsFile}]文件已经存在,无需构建启动文件`);
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
- else {
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
- console.log(`[${featureIndexFile}]文件已经存在,无需构建启动文件`);
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
- console.log(`[${contextFile}]文件已经存在,无需构建启动文件`);
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
- else {
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
- console.log(`[${contextFile}]文件已经存在,无需构建启动文件`);
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
- else {
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
- /**这个用来处理级联的select和update,对不同能力的 */
18
- class CascadeStore extends RowStore_1.RowStore {
19
- constructor(storageSchema) {
20
- super(storageSchema);
21
- }
22
- selectionRewriters = [];
23
- operationRewriters = [];
24
- async reinforceSelectionAsync(entity, selection, context, option, isAggr) {
25
- if (!isAggr && !selection.distinct) {
26
- this.reinforceSelectionInner(entity, selection, context, option);
27
- }
28
- const rewriterPromises = this.selectionRewriters.map(ele => ele(this.getSchema(), entity, selection, context, option, isAggr));
29
- if (rewriterPromises.length > 0) {
30
- await Promise.all(rewriterPromises);
31
- }
32
- }
33
- reinforceSelectionSync(entity, selection, context, option, isAggr) {
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
- reinforceSelectionInner(entity, selection, context, option) {
43
- const { filter, data, sorter } = selection;
44
- const assignNecessaryProjectionAttrs = (projectionNode, attrs) => {
45
- attrs.forEach((attr) => {
46
- if (!projectionNode.hasOwnProperty(attr)) {
47
- Object.assign(projectionNode, {
48
- [attr]: 1,
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
- else if (attr === '$text') {
74
- // 全文检索首先要有fulltext索引,其次要把fulltext的相关属性加到projection里
75
- const { indexes } = this.getSchema()[entity2];
76
- const fulltextIndex = indexes.find(ele => ele.config && ele.config.type === 'fulltext');
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
- else {
81
- if (attr.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
82
- const exprResult = (0, types_1.getAttrRefInExpression)(filterNode[attr]);
83
- for (const nodeName in exprResult) {
84
- if (nodeName === '#current') {
85
- assignNecessaryProjectionAttrs(projectionNode, exprResult[nodeName]);
86
- }
87
- else if (filterNodeDict[nodeName]) {
88
- assignNecessaryProjectionAttrs(filterNodeDict[nodeName], exprResult[nodeName]);
89
- }
90
- else {
91
- if (toBeAssignNode[nodeName]) {
92
- toBeAssignNode[nodeName].push(...exprResult[nodeName]);
93
- }
94
- else {
95
- Object.assign(toBeAssignNode, {
96
- [nodeName]: exprResult[nodeName],
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
- else {
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 if (rel === 2) {
108
- // entity/entityId反指
109
- necessaryAttrs.push('entity', 'entityId');
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
- checkFilterNode(attr, filterNode[attr], projectionNode[attr], toBeAssignNode, filterNodeDict);
118
- }
119
- else if (typeof rel === 'string') {
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
- assignNecessaryProjectionAttrs(projectionNode, necessaryAttrs);
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 (typeof rel === 'string') {
147
- if (!projNode[attr]) {
148
- Object.assign(projNode, {
149
- [attr]: {},
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
- (0, assert_1.default)(typeof sortAttr[attr] === 'object');
153
- checkSortAttr(rel, sortAttr[attr], projNode[attr]);
100
+ checkFilterNode(attr, filterNode[attr], projectionNode[attr], toBeAssignNode, filterNodeDict);
154
101
  }
155
- else {
156
- (0, assert_1.default)(rel === 2);
157
- if (!projNode[attr]) {
158
- Object.assign(projNode, {
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
- (0, assert_1.default)(typeof sortAttr[attr] === 'object');
163
- checkSortAttr(attr, sortAttr[attr], projNode[attr]);
111
+ checkFilterNode(rel, filterNode[attr], projectionNode[attr], toBeAssignNode, filterNodeDict);
112
+ }
113
+ else if (rel instanceof Array) {
114
+ // 子查询,暂时不处理
164
115
  }
165
116
  }
166
- assignNecessaryProjectionAttrs(projNode, necessaryAttrs);
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
- const toBeAssignNode2 = {}; // 用来记录在表达式中涉及到的结点
186
- const projectionNodeDict = {};
187
- const checkProjectionNode = (entity2, projectionNode) => {
188
- const necessaryAttrs = ['id', '$$createAt$$', '$$updateAt$$']; // 有的页面依赖于其它页面取数据,有时两个页面的filter的差异会导致有一个加createAt,有一个不加,此时可能产生前台取数据不完整的异常。先统一加上
189
- for (const attr in projectionNode) {
190
- if (attr === '#id') {
191
- (0, assert_1.default)(!projectionNodeDict[projectionNode[attr]], `projection中结点的id有重复, ${projectionNode[attr]}`);
192
- Object.assign(projectionNodeDict, {
193
- [projectionNode[attr]]: projectionNode,
194
- });
195
- if (toBeAssignNode2[projectionNode[attr]]) {
196
- assignNecessaryProjectionAttrs(projectionNode, toBeAssignNode2[projectionNode[attr]]);
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
- if (attr.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
201
- const exprResult = (0, types_1.getAttrRefInExpression)(projectionNode[attr]);
202
- for (const nodeName in exprResult) {
203
- if (nodeName === '#current') {
204
- assignNecessaryProjectionAttrs(projectionNode, exprResult[nodeName]);
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
- else {
222
- const rel = (0, relation_1.judgeRelation)(this.getSchema(), entity2, attr);
223
- if (rel === 1) {
224
- necessaryAttrs.push(attr);
225
- }
226
- else if (rel === 2) {
227
- // entity/entityId反指
228
- necessaryAttrs.push('entity', 'entityId');
229
- checkProjectionNode(attr, projectionNode[attr]);
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 (typeof rel === 'string') {
232
- necessaryAttrs.push(`${attr}Id`);
233
- checkProjectionNode(rel, projectionNode[attr]);
189
+ else if (projectionNodeDict[nodeName]) {
190
+ assignNecessaryProjectionAttrs(projectionNodeDict[nodeName], exprResult[nodeName]);
234
191
  }
235
- else if (rel instanceof Array && !attr.endsWith('$$aggr')) {
236
- const { data, filter } = projectionNode[attr];
237
- if (rel[1]) {
238
- assignNecessaryProjectionAttrs(data, [rel[1]]);
192
+ else {
193
+ if (toBeAssignNode2[nodeName]) {
194
+ toBeAssignNode2[nodeName].push(...exprResult[nodeName]);
239
195
  }
240
196
  else {
241
- assignNecessaryProjectionAttrs(data, ['entity', 'entityId']);
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
- assignNecessaryProjectionAttrs(projectionNode, necessaryAttrs);
248
- }
249
- // 如果对象中指向一对多的Modi,此时加上指向Modi的projection
250
- // 此逻辑关闭,用户自己撰写去取modi by Xc 20241207
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
- // 如果对象上有relation关系,在此将本用户相关的relation和actionAuth全部取出
274
- // 还要将actionAuth上没有relation关系但destEntity为本对象的行也全部取出,这些是指向userId的可能路径
275
- // 放在这里有点怪异,暂先这样
276
- if (context instanceof AsyncRowStore_1.AsyncContext && !option.dontCollect) {
277
- const userId = context.getCurrentUserId(true);
278
- if (userId && !entities_1.SYSTEM_RESERVE_ENTITIES.includes(entity2)) {
279
- if (this.getSchema()[entity2].relation && !projectionNode.userRelation$entity) {
280
- Object.assign(projectionNode, {
281
- userRelation$entity: {
282
- $entity: 'userRelation',
283
- data: {
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
- entity: 1,
286
- entityId: 1,
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
- filter: {
300
- userId,
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, `${attrsIllegal.join(',')}不允许被${action}动作更新`);
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
  }
@@ -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], `${entity}: ${attr}'s value "${data[attr]}" is not a string`);
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], `${entity}: ${attr}'s value "${data[attr]}" is too long`);
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], `${entity}: ${attr}'s value "${data[attr]}" is not a number`);
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], `${entity}: ${attr}'s value "${data[attr]}" is too small`);
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], `${entity}: ${attr}'s value "${data[attr]}" is too big`);
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], `${entity}: ${attr}'s value "${data[attr]}" is not in enumeration`);
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']) => NonNullable<ED[T]['Filter']>);
21
+ filter?: (NonNullable<ED[T]['Filter']>) | ((action: ED[T]['Action']) => ED[T]['Filter'] | undefined);
22
22
  };
23
23
  };
24
24
  };
@@ -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;
@@ -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
  }
@@ -1,5 +1,5 @@
1
1
  import { SelectOption, CheckerType } from ".";
2
- import { GenericAction } from "../actions/action";
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'], GenericAction> | 'update' | Array<Exclude<ED[T]['Action'], GenericAction> | 'update'>;
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;
@@ -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;
@@ -4,4 +4,10 @@
4
4
  * @param reqVersion 比较版本
5
5
  * @returns
6
6
  */
7
- export declare const compareVersion: (curVersion: string, reqVersion: string) => number;
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;
@@ -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
- const compareVersion = (curVersion, reqVersion) => {
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oak-domain",
3
- "version": "5.1.18",
3
+ "version": "5.1.20",
4
4
  "author": {
5
5
  "name": "XuChang"
6
6
  },