oak-domain 5.1.32 → 5.1.33

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.
@@ -76,7 +76,7 @@ export declare abstract class CascadeStore<ED extends EntityDict & BaseEntityDic
76
76
  };
77
77
  protected preProcessDataCreated<T extends keyof ED>(entity: T, data: ED[T]['Create']['data']): void;
78
78
  protected preProcessDataUpdated(action: string, data: Record<string, any>, async?: true): void;
79
- judgeRelation(entity: keyof ED, attr: string): string | 1 | 2 | string[] | 0 | -1;
79
+ judgeRelation(entity: keyof ED, attr: string): string | 2 | 1 | string[] | 0 | -1;
80
80
  private tryMergeModi;
81
81
  /**
82
82
  * 和具体的update过程无关的例程放在这里,包括对later动作的处理、对oper的记录以及对record的收集等
@@ -1311,6 +1311,7 @@ class CascadeStore extends RowStore_1.RowStore {
1311
1311
  operatorId,
1312
1312
  targetEntity: entity,
1313
1313
  bornAt,
1314
+ iState: 'normal',
1314
1315
  operEntity$oper: data instanceof Array ? [{
1315
1316
  id: 'dummy',
1316
1317
  action: 'create',
@@ -1450,6 +1451,7 @@ class CascadeStore extends RowStore_1.RowStore {
1450
1451
  targetEntity: entity,
1451
1452
  bornAt,
1452
1453
  operatorId,
1454
+ iState: 'normal',
1453
1455
  operEntity$oper: [{
1454
1456
  id: 'dummy',
1455
1457
  action: 'create',
@@ -1496,7 +1498,7 @@ class CascadeStore extends RowStore_1.RowStore {
1496
1498
  }
1497
1499
  else {
1498
1500
  // 如果没有更新到行,说明这些数据还在modi当中
1499
- (0, assert_1.default)(count === 0, 'update成功的行数只能为id所在行数或者0');
1501
+ (0, assert_1.default)(count === 0, `update成功的行数只能为id所在行数或者0,得到: ${count}, ids: ${ids.join(',')}`);
1500
1502
  return await createModi();
1501
1503
  }
1502
1504
  }
@@ -286,7 +286,9 @@ function cascadelyCheckUpdateFilters(entity, schema, action, data, filter, matri
286
286
  if (typeof f === 'function') {
287
287
  const cf = f({ action, data, filter }, context);
288
288
  if (cf instanceof Promise) {
289
- return cf.then((cf2) => cf2 ? checkConditionalFilter(cf2) : true);
289
+ return cf.then(
290
+ // @oak-ignore
291
+ (cf2) => cf2 ? checkConditionalFilter(cf2) : true);
290
292
  }
291
293
  return cf ? checkConditionalFilter(cf) : true;
292
294
  }
@@ -31,6 +31,7 @@ class RelationAuth {
31
31
  if (context.isRoot()) {
32
32
  return;
33
33
  }
34
+ // @oak-ignore 这里只有纯前台会跑到,一定是同步的
34
35
  this.checkActions2(entity, operation, context);
35
36
  }
36
37
  // 后台检查filter是否满足relation约束
@@ -58,6 +59,7 @@ class RelationAuth {
58
59
  /**
59
60
  * 找到能创建此relation的所有父级relation,只要user和其中一个有关联即可以通过
60
61
  */
62
+ // @oak-ignore
61
63
  const relationAuths = context.select('relationAuth', {
62
64
  data: {
63
65
  id: 1,
@@ -108,7 +110,9 @@ class RelationAuth {
108
110
  return ele > 0;
109
111
  }));
110
112
  }
111
- const result = relationAuths.map(ra => checkRelationAuth(ra));
113
+ const result = relationAuths.map(
114
+ // @oak-ignore
115
+ ra => checkRelationAuth(ra));
112
116
  return !!result.find(ele => ele > 0);
113
117
  };
114
118
  /**
@@ -127,6 +131,7 @@ class RelationAuth {
127
131
  if (relevantIds.length > 0) {
128
132
  return relevantIds;
129
133
  }
134
+ // @oak-ignore
130
135
  const relations = context.select('relation', {
131
136
  data: {
132
137
  id: 1,
@@ -170,6 +175,7 @@ class RelationAuth {
170
175
  // 如果没有relationId(前端cache中),直接返回false
171
176
  return false;
172
177
  }
178
+ // @oak-ignore
173
179
  const value = relationIds.map(ele => checkOnRelationId(entity2, ele, entityFilter));
174
180
  if (intersection) {
175
181
  return !(value.includes(false));
@@ -340,6 +346,7 @@ class RelationAuth {
340
346
  * 这种情况一般发生在entity1 -> entity2上,此时entity2应该是一个固定id查询的filter
341
347
  * 在这里先假设如果碰到了list类型的filter,直接不使用deduce路径上的对象来推导
342
348
  */
349
+ // @oak-ignore
343
350
  const rows2 = context.select(entity, {
344
351
  data: {
345
352
  id: 1,
@@ -363,6 +370,7 @@ class RelationAuth {
363
370
  // 说明没有找到行,这时候有一种可能是modi。这时候只能假设是指定id更新了,其它情况很难处理。by Xc
364
371
  if (filter.id) {
365
372
  // 用modi对应的entity/entityId来判定
373
+ // @oak-ignore
366
374
  const modies = context.select('modi', {
367
375
  data: {
368
376
  id: 1,
@@ -820,7 +828,9 @@ class RelationAuth {
820
828
  (0, assert_1.default)(context instanceof AsyncRowStore_1.AsyncContext);
821
829
  return actionAuths.then((aas) => Promise.all(dlSelections.map((ele) => Promise.all(ele.map((ele2) => this.checkActionAuthInGroup(ele2.entity, ele2.filter, aas, context))))).then((result) => checkResult(result)));
822
830
  }
823
- return checkResult(dlSelections.map(ele => ele.map(ele2 => this.checkActionAuthInGroup(ele2.entity, ele2.filter, actionAuths, context))));
831
+ return checkResult(dlSelections.map(ele => ele.map(
832
+ // @oak-ignore
833
+ ele2 => this.checkActionAuthInGroup(ele2.entity, ele2.filter, actionAuths, context))));
824
834
  };
825
835
  if (deducedLeafSelections[0] instanceof Promise) {
826
836
  return Promise.all(deducedLeafSelections)
@@ -859,11 +869,14 @@ class RelationAuth {
859
869
  const result = [];
860
870
  if (specialEntities.length > 0) {
861
871
  // 对于deduce出来的special对象,直接判定create应该问题不大,否则写起来太烦琐(具体情况遇到了再调试)
862
- result.push(...specialEntities.map(ele => this.checkOperateSpecialEntities2(ele.entity, ele.entity === entity ? node.action : 'create', ele.filter, context)));
872
+ result.push(...specialEntities.map(
873
+ // @oak-ignore
874
+ ele => this.checkOperateSpecialEntities2(ele.entity, ele.entity === entity ? node.action : 'create', ele.filter, context)));
863
875
  }
864
876
  if (unspecicalEntities.length > 0) {
865
877
  const allEntities = unspecicalEntities.map(ele => ele.entity);
866
878
  const allActions = (0, lodash_1.uniq)(unspecicalEntities.map(ele => ele.actions).flat());
879
+ // @oak-ignore
867
880
  const actionAuths2 = context.select('actionAuth', {
868
881
  data: {
869
882
  id: 1,
@@ -937,10 +950,14 @@ class RelationAuth {
937
950
  return result.includes(true);
938
951
  };
939
952
  if (actionAuths2 instanceof Promise) {
940
- result.push(actionAuths2.then((ars2) => checkActionAuths(ars2)));
953
+ result.push(actionAuths2.then(
954
+ // @oak-ignore
955
+ (ars2) => checkActionAuths(ars2)));
941
956
  }
942
957
  else {
943
- result.push(checkActionAuths(actionAuths2));
958
+ result.push(
959
+ // @oak-ignore
960
+ checkActionAuths(actionAuths2));
944
961
  }
945
962
  }
946
963
  if (result.find(ele => ele instanceof Promise)) {
@@ -987,6 +1004,7 @@ class RelationAuth {
987
1004
  const childLegalAuths = legalPaths.map((ele) => {
988
1005
  const { path: { value: pv }, relationId } = ele;
989
1006
  const pv2 = pv ? `${pathToParent}.${pv}` : pathToParent;
1007
+ // @oak-ignore
990
1008
  return context.select('actionAuth', {
991
1009
  data: {
992
1010
  id: 1,
@@ -1006,13 +1024,18 @@ class RelationAuth {
1006
1024
  }, { dontCollect: true });
1007
1025
  });
1008
1026
  if (childLegalAuths[0] instanceof Promise) {
1009
- return Promise.all(childLegalAuths).then((clas) => child.map((c) => checkNode(c, clas.flat())));
1027
+ return Promise.all(childLegalAuths).then((clas) => child.map(
1028
+ // @oak-ignore
1029
+ (c) => checkNode(c, clas.flat())));
1010
1030
  }
1011
- return child.map((c) => checkNode(c, childLegalAuths.flat()));
1031
+ return child.map(
1032
+ // @oak-ignore
1033
+ (c) => checkNode(c, childLegalAuths.flat()));
1012
1034
  }
1013
1035
  const childLegalAuths = legalPaths.map((ele) => {
1014
1036
  const { path: { value: pv }, relationId } = ele;
1015
1037
  const pv2 = pv ? `${pathToParent}.${pv}` : pathToParent;
1038
+ // @oak-ignore
1016
1039
  return context.select('actionAuth', {
1017
1040
  data: {
1018
1041
  id: 1,
@@ -1032,8 +1055,11 @@ class RelationAuth {
1032
1055
  }, { dontCollect: true });
1033
1056
  }).flat();
1034
1057
  if (childLegalAuths[0] instanceof Promise) {
1035
- return Promise.all(childLegalAuths).then((clas) => checkNode(child, clas.flat()));
1058
+ return Promise.all(childLegalAuths).then(
1059
+ // @oak-ignore
1060
+ (clas) => checkNode(child, clas.flat()));
1036
1061
  }
1062
+ // @oak-ignore
1037
1063
  return checkNode(child, childLegalAuths);
1038
1064
  }).flat();
1039
1065
  if (childResult[0] instanceof Promise) {
@@ -104,6 +104,17 @@ class TriggerExecutor {
104
104
  || trigger.action instanceof Array && !trigger.action.includes('create'), `trigger【${trigger.name}】是create类型但却带有filter`);
105
105
  (0, assert_1.default)(trigger.when === 'before' || trigger.when === 'commit', `定义了filter的trigger【${trigger.name}】的when只能是before或者commit`);
106
106
  }
107
+ if (Array.isArray(trigger.action)) {
108
+ const actions = trigger.action;
109
+ const seen = new Set();
110
+ const duplicate = actions.find(item => {
111
+ if (seen.has(item))
112
+ return true;
113
+ seen.add(item);
114
+ return false;
115
+ });
116
+ (0, assert_1.default)(!duplicate, `注册 trigger 「${trigger.name}」 时发现定义中出现了重复定义的action: 「${duplicate}」`);
117
+ }
107
118
  Object.assign(this.triggerNameMap, {
108
119
  [trigger.name]: trigger,
109
120
  });
@@ -293,6 +304,7 @@ class TriggerExecutor {
293
304
  const { filter } = trigger;
294
305
  const filterr = typeof filter === 'function' ? filter(operation, context, option) : filter;
295
306
  (0, assert_1.default)(!(filterr instanceof Promise));
307
+ // @oak-ignore
296
308
  const filterRepelled = (0, filter_1.checkFilterRepel)(entity, context, filterr, operation.filter);
297
309
  if (filterRepelled) {
298
310
  continue;
@@ -365,6 +377,7 @@ class TriggerExecutor {
365
377
  await this.preCommitTrigger(entity, operation, trigger, context, option);
366
378
  return execCommitTrigger(idx + 1);
367
379
  };
380
+ // @oak-ignore
368
381
  return execPreTrigger(0)
369
382
  .then(() => execCommitTrigger(0));
370
383
  }
@@ -161,6 +161,7 @@ function translateCheckerInSyncContext(checker, schema) {
161
161
  }
162
162
  (0, assert_1.default)(!(filter2 instanceof Promise));
163
163
  (0, assert_1.default)(operationFilter2, '定义了row类型的checker但却进行了无filter操作');
164
+ // @oak-ignore
164
165
  if ((0, filter_1.checkFilterContains)(entity, context, filter2, operationFilter2, true)) {
165
166
  return;
166
167
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -9,4 +9,4 @@ import { StorageSchema } from "../types/Storage";
9
9
  * @param row
10
10
  * @returns
11
11
  */
12
- export declare function judgeRelation<ED extends EntityDict & BaseEntityDict>(schema: StorageSchema<ED>, entity: keyof ED, attr: string, allowUnrecognized?: boolean): string | 1 | 2 | string[] | 0 | -1;
12
+ export declare function judgeRelation<ED extends EntityDict & BaseEntityDict>(schema: StorageSchema<ED>, entity: keyof ED, attr: string, allowUnrecognized?: boolean): string | 2 | 1 | string[] | 0 | -1;
@@ -18,7 +18,7 @@ export type RedisConfiguration = {
18
18
  * 后台配置
19
19
  */
20
20
  export type ServerConfiguration = {
21
- database: {
21
+ database?: {
22
22
  type: 'mysql';
23
23
  host: string;
24
24
  database: string;
@@ -3,6 +3,7 @@ import { SyncContext } from "../store/SyncRowStore";
3
3
  import { EntityDict, OpRecord } from "./Entity";
4
4
  import { EntityDict as BaseEntityDict } from '../base-app-domain';
5
5
  import { OakException } from "./Exception";
6
+ type Promisable<T> = T | Promise<T>;
6
7
  export interface Connector<ED extends EntityDict & BaseEntityDict, FrontCxt extends SyncContext<ED>> {
7
8
  callAspect: (name: string, params: any, context?: FrontCxt) => Promise<{
8
9
  result: any;
@@ -10,11 +11,11 @@ export interface Connector<ED extends EntityDict & BaseEntityDict, FrontCxt exte
10
11
  message?: string | null;
11
12
  }>;
12
13
  getRouter: () => string;
13
- parseRequest: (headers: IncomingHttpHeaders, body?: any, files?: any) => {
14
+ parseRequest: (headers: IncomingHttpHeaders, body?: any, files?: any) => Promisable<{
14
15
  contextString?: string;
15
16
  aspectName: string;
16
17
  data?: any;
17
- };
18
+ }>;
18
19
  serializeResult: (result: any, opRecords: OpRecord<ED>[], headers: IncomingHttpHeaders, body: any, message?: string) => Promise<{
19
20
  body: any;
20
21
  headers?: Record<string, any>;
@@ -43,4 +44,18 @@ export interface Connector<ED extends EntityDict & BaseEntityDict, FrontCxt exte
43
44
  [T in keyof ED]?: ED[T]['OpSchema'][];
44
45
  }>;
45
46
  getCorsHeader: () => string[];
47
+ getCorsExposeHeaders?: () => string[];
48
+ registerCustomAspect?: () => {
49
+ name: string;
50
+ handler: (params: {
51
+ headers?: IncomingHttpHeaders;
52
+ contextString?: string;
53
+ params?: any;
54
+ }) => Promise<{
55
+ result: any;
56
+ opRecords?: OpRecord<ED>[];
57
+ message?: string;
58
+ }>;
59
+ }[];
46
60
  }
61
+ export {};
@@ -54,6 +54,7 @@ export type Q_State<S> = S | {
54
54
  export type Q_FullTextValue = {
55
55
  $search: string;
56
56
  $language?: 'zh_CN' | 'en_US';
57
+ $ts?: string;
57
58
  };
58
59
  export type Q_FullTextKey = '$text';
59
60
  export type FulltextFilter = {
@@ -1,10 +1,27 @@
1
1
  import { StorageSchema } from ".";
2
2
  import { EntityDict, OpRecord } from "./Entity";
3
3
  import { EntityDict as BaseEntityDict } from '../base-app-domain';
4
+ declare const OAK_EXCEPTION_SYMBOL: unique symbol;
5
+ /**
6
+ * 判断一个对象是否为 OakException 实例,作用和 `instanceof` 类似,但更安全可靠。
7
+ * 如OakUserException继承自OakException,使用时可传入OakUserException以进一步确认类型。
8
+ * @param obj 需要判断的对象
9
+ * @param exceptionName 可选参数,指定异常类名以进一步确认
10
+ *
11
+ * ```ts
12
+ * if (isOakException(e, OakUserException)) {
13
+ * // 这里的 e 已被类型缩小为 OakUserException
14
+ * }
15
+ * ```
16
+ *
17
+ * @returns 如果对象是 OakException 实例则返回 true,否则返回 false
18
+ */
19
+ export declare function isOakException<T extends OakException<any>>(obj: any, errType?: new () => T): obj is T;
4
20
  export declare class OakException<ED extends EntityDict & BaseEntityDict> extends Error {
5
21
  opRecords: OpRecord<ED>[];
6
22
  _module?: string;
7
23
  params?: Record<string, any>;
24
+ [OAK_EXCEPTION_SYMBOL]: boolean;
8
25
  constructor(message?: string, _module?: string, params?: Record<string, any>);
9
26
  addData<T extends keyof ED>(entity: T, rows: Partial<ED[T]['Schema']>[], schema: StorageSchema<ED>): void;
10
27
  setOpRecords(opRecords: OpRecord<ED>[]): void;
@@ -81,6 +98,8 @@ export declare class OakServerProxyException<ED extends EntityDict & BaseEntityD
81
98
  }
82
99
  export declare class OakClockDriftException<ED extends EntityDict & BaseEntityDict> extends OakException<ED> {
83
100
  }
101
+ export declare class OakInsecureRequestException<ED extends EntityDict & BaseEntityDict> extends OakException<ED> {
102
+ }
84
103
  export declare class OakSignatureVerificationException<ED extends EntityDict & BaseEntityDict> extends OakException<ED> {
85
104
  constructor(message?: string, _module?: string, params?: Record<string, any>);
86
105
  }
@@ -200,3 +219,4 @@ export declare function makeException<ED extends EntityDict & BaseEntityDict>(da
200
219
  opRecords: OpRecord<ED>[];
201
220
  [A: string]: any;
202
221
  }): OakException<ED> | undefined;
222
+ export {};
@@ -1,13 +1,64 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- 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;
3
+ 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.OakInsecureRequestException = 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
+ exports.isOakException = isOakException;
4
5
  exports.makeException = makeException;
5
6
  const relation_1 = require("../store/relation");
6
7
  const lodash_1 = require("../utils/lodash");
8
+ const OAK_EXCEPTION_SYMBOL = Symbol.for('oak-domain:exception');
9
+ /**
10
+ * 判断一个对象是否为 OakException 实例,作用和 `instanceof` 类似,但更安全可靠。
11
+ * 如OakUserException继承自OakException,使用时可传入OakUserException以进一步确认类型。
12
+ * @param obj 需要判断的对象
13
+ * @param exceptionName 可选参数,指定异常类名以进一步确认
14
+ *
15
+ * ```ts
16
+ * if (isOakException(e, OakUserException)) {
17
+ * // 这里的 e 已被类型缩小为 OakUserException
18
+ * }
19
+ * ```
20
+ *
21
+ * @returns 如果对象是 OakException 实例则返回 true,否则返回 false
22
+ */
23
+ function isOakException(obj, errType) {
24
+ if (!obj) {
25
+ return false;
26
+ }
27
+ const isOakException = !!obj[OAK_EXCEPTION_SYMBOL];
28
+ if (isOakException) {
29
+ if (!errType) {
30
+ return true;
31
+ }
32
+ }
33
+ else {
34
+ return false;
35
+ }
36
+ try {
37
+ let proto = Object.getPrototypeOf(obj);
38
+ const expectedName = errType.name;
39
+ let depth = 0;
40
+ const maxDepth = 10; // 防止无限循环
41
+ while (proto && depth < maxDepth) {
42
+ const constructorName = proto.constructor?.name;
43
+ if (constructorName === expectedName) {
44
+ return true;
45
+ }
46
+ proto = Object.getPrototypeOf(proto);
47
+ depth++;
48
+ }
49
+ return false;
50
+ }
51
+ catch (e) {
52
+ console.warn(e);
53
+ // 如果检查过程出错,安全返回 false
54
+ return false;
55
+ }
56
+ }
7
57
  class OakException extends Error {
8
58
  opRecords;
9
59
  _module;
10
60
  params;
61
+ [OAK_EXCEPTION_SYMBOL] = true;
11
62
  constructor(message, _module, params) {
12
63
  super(message);
13
64
  this._module = _module;
@@ -200,6 +251,10 @@ exports.OakServerProxyException = OakServerProxyException;
200
251
  class OakClockDriftException extends OakException {
201
252
  }
202
253
  exports.OakClockDriftException = OakClockDriftException;
254
+ // 非安全的请求(未加密)
255
+ class OakInsecureRequestException extends OakException {
256
+ }
257
+ exports.OakInsecureRequestException = OakInsecureRequestException;
203
258
  // 验签失败
204
259
  class OakSignatureVerificationException extends OakException {
205
260
  constructor(message, _module, params) {
@@ -528,6 +583,10 @@ function makeException(data) {
528
583
  e = new OakClockDriftException(message, _module, params);
529
584
  break;
530
585
  }
586
+ case 'OakInsecureRequestException': {
587
+ e = new OakInsecureRequestException(message, _module, params);
588
+ break;
589
+ }
531
590
  case 'OakServerProxyException': {
532
591
  e = new OakServerProxyException(message, _module, params);
533
592
  break;
@@ -11,6 +11,7 @@ export interface IndexConfig {
11
11
  unique?: boolean;
12
12
  type?: 'fulltext' | 'btree' | 'hash' | 'spatial';
13
13
  parser?: 'ngram';
14
+ tsConfig?: string | string[];
14
15
  }
15
16
  export interface Index<SH extends EntityShape> {
16
17
  name: string;