oak-domain 5.1.23 → 5.1.25

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.
@@ -33,7 +33,7 @@ export declare abstract class CascadeStore<ED extends EntityDict & BaseEntityDic
33
33
  protected abstract updateAbjointRowAsync<T extends keyof ED, OP extends OperateOption, Cxt extends AsyncContext<ED>>(entity: T, operation: ED[T]['Create'] | ED[T]['Update'] | ED[T]['Remove'], context: Cxt, option: OP): Promise<number>;
34
34
  protected abstract aggregateAbjointRowSync<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, aggregation: ED[T]['Aggregation'], context: Cxt, option: OP): AggregationResult<ED[T]['Schema']>;
35
35
  protected abstract aggregateAbjointRowAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, aggregation: ED[T]['Aggregation'], context: Cxt, option: OP): Promise<AggregationResult<ED[T]['Schema']>>;
36
- protected destructCascadeSelect<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED> | AsyncContext<ED>>(entity: T, projection2: ED[T]['Projection'], context: Cxt, cascadeSelectFn: <T2 extends keyof ED>(entity2: T2, selection: ED[T2]['Selection'], context: Cxt, op: OP) => Partial<ED[T2]['Schema']>[] | Promise<Partial<ED[T2]['Schema']>[]>, aggregateFn: <T2 extends keyof ED>(entity2: T2, aggregation: ED[T2]['Aggregation'], context: Cxt, op: OP) => AggregationResult<ED[T2]['Schema']> | Promise<AggregationResult<ED[T2]['Schema']>>, option: OP): {
36
+ protected destructCascadeSelect<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED> | AsyncContext<ED>>(entity: T, projection2: ED[T]['Projection'], context: Cxt, cascadeSelectFn: <T2 extends keyof ED>(entity2: T2, selection: ED[T2]['Selection'], context: Cxt, op: OP) => Partial<ED[T2]['Schema']>[] | Promise<Partial<ED[T2]['Schema']>[]>, aggregateFn: <T2 extends keyof ED>(entity2: T2, aggregation: ED[T2]['Aggregation'], context: Cxt, op: OP) => AggregationResult<ED[T2]['Schema']> | Promise<AggregationResult<ED[T2]['Schema']>>, option: OP, selectionId?: string): {
37
37
  projection: ED[T]["Projection"];
38
38
  cascadeSelectionFns: ((result: Partial<ED[T]['Schema']>[]) => Promise<void> | void)[];
39
39
  };
@@ -317,7 +317,7 @@ class CascadeStore extends RowStore_1.RowStore {
317
317
  registerSelectionRewriter(rewriter) {
318
318
  this.selectionRewriters.push(rewriter);
319
319
  }
320
- destructCascadeSelect(entity, projection2, context, cascadeSelectFn, aggregateFn, option) {
320
+ destructCascadeSelect(entity, projection2, context, cascadeSelectFn, aggregateFn, option, selectionId) {
321
321
  const cascadeSelectionFns = [];
322
322
  const supportMtoJoin = this.supportManyToOneJoin();
323
323
  const { toModi } = this.getSchema()[entity];
@@ -352,7 +352,7 @@ class CascadeStore extends RowStore_1.RowStore {
352
352
  });
353
353
  }
354
354
  });
355
- const { projection: subProjection, cascadeSelectionFns: subCascadeSelectionFns, } = this.destructCascadeSelect(attr, projection2[attr], context, cascadeSelectFn, aggregateFn, option);
355
+ const { projection: subProjection, cascadeSelectionFns: subCascadeSelectionFns, } = this.destructCascadeSelect(attr, projection2[attr], context, cascadeSelectFn, aggregateFn, option, selectionId);
356
356
  subCascadeSelectionFns.forEach(ele => cascadeSelectionFns.push((result) => {
357
357
  return ele(result.map(ele2 => ele2[attr]).filter(ele2 => !!ele2));
358
358
  }));
@@ -372,6 +372,7 @@ class CascadeStore extends RowStore_1.RowStore {
372
372
  throw new types_1.OakRowUnexistedException([{
373
373
  entity: attr,
374
374
  selection: {
375
+ id: selectionId,
375
376
  data: projection2[attr],
376
377
  filter: {
377
378
  id: {
@@ -400,6 +401,7 @@ class CascadeStore extends RowStore_1.RowStore {
400
401
  };
401
402
  if (entityIds.length > 0) {
402
403
  const subRows = cascadeSelectFn.call(this, attr, {
404
+ id: selectionId,
403
405
  data: projection2[attr],
404
406
  filter: {
405
407
  id: {
@@ -440,7 +442,7 @@ class CascadeStore extends RowStore_1.RowStore {
440
442
  }
441
443
  });
442
444
  }
443
- const { projection: subProjection, cascadeSelectionFns: subCascadeSelectionFns, } = this.destructCascadeSelect(relation, projection2[attr], context, cascadeSelectFn, aggregateFn, option);
445
+ const { projection: subProjection, cascadeSelectionFns: subCascadeSelectionFns, } = this.destructCascadeSelect(relation, projection2[attr], context, cascadeSelectFn, aggregateFn, option, selectionId);
444
446
  subCascadeSelectionFns.forEach(ele => cascadeSelectionFns.push((result) => {
445
447
  return ele(result.map(ele2 => ele2[attr]).filter(ele2 => !!ele2));
446
448
  }));
@@ -489,6 +491,7 @@ class CascadeStore extends RowStore_1.RowStore {
489
491
  };
490
492
  if (ids.length > 0) {
491
493
  const subRows = cascadeSelectFn.call(this, relation, {
494
+ id: selectionId,
492
495
  data: projection2[attr],
493
496
  filter: {
494
497
  id: {
@@ -506,7 +509,7 @@ class CascadeStore extends RowStore_1.RowStore {
506
509
  }
507
510
  else {
508
511
  (0, assert_1.default)(relation instanceof Array);
509
- const { data: subProjection, filter: subFilter, indexFrom, count, sorter: subSorter, total, randomRange } = projection2[attr];
512
+ const { data: subProjection, filter: subFilter, indexFrom, count, sorter: subSorter, total, randomRange, id: subSelectionId } = projection2[attr];
510
513
  const [entity2, foreignKey] = relation;
511
514
  const isAggr = attr.endsWith('$$aggr');
512
515
  const otmAggrFn = (result) => {
@@ -573,6 +576,7 @@ class CascadeStore extends RowStore_1.RowStore {
573
576
  },
574
577
  }, subFilter]);
575
578
  const subRows = cascadeSelectFn.call(this, entity2, {
579
+ id: subSelectionId || selectionId,
576
580
  data: subProjection,
577
581
  filter: filter2,
578
582
  sorter: subSorter,
@@ -600,6 +604,7 @@ class CascadeStore extends RowStore_1.RowStore {
600
604
  entityId: row.id,
601
605
  }, subFilter]);
602
606
  const subRows = cascadeSelectFn.call(this, entity2, {
607
+ id: subSelectionId || selectionId,
603
608
  data: subProjection,
604
609
  filter: filter2,
605
610
  sorter: subSorter,
@@ -1662,7 +1667,7 @@ class CascadeStore extends RowStore_1.RowStore {
1662
1667
  * @param rows
1663
1668
  * @param context
1664
1669
  */
1665
- addToResultSelections(entity, rows, context) {
1670
+ addToResultSelections(entity, rows, context, id) {
1666
1671
  if (this.supportManyToOneJoin()) {
1667
1672
  // 这里的外键连接有可能为空,需要使用所有的行的attr的并集来测试
1668
1673
  const attrs = (0, lodash_1.uniq)(rows.map(ele => Object.keys(ele)).flat());
@@ -1671,29 +1676,29 @@ class CascadeStore extends RowStore_1.RowStore {
1671
1676
  const data = {};
1672
1677
  const rel = this.judgeRelation(entity, attr);
1673
1678
  if (rel === 2) {
1674
- this.addToResultSelections(attr, rows.map(ele => ele[attr]).filter(ele => !!ele), context);
1679
+ this.addToResultSelections(attr, rows.map(ele => ele[attr]).filter(ele => !!ele), context, id);
1675
1680
  }
1676
1681
  else if (typeof rel === 'string') {
1677
- this.addToResultSelections(rel, rows.map(ele => ele[attr]).filter(ele => !!ele), context);
1682
+ this.addToResultSelections(rel, rows.map(ele => ele[attr]).filter(ele => !!ele), context, id);
1678
1683
  }
1679
1684
  else if (rel instanceof Array) {
1680
- this.addToResultSelections(rel[0], rows.map(ele => ele[attr]).reduce((prev, current) => prev.concat(current), []), context);
1685
+ this.addToResultSelections(rel[0], rows.map(ele => ele[attr]).reduce((prev, current) => prev.concat(current), []), context, id);
1681
1686
  }
1682
1687
  else {
1683
1688
  attrsToPick.push(attr);
1684
1689
  }
1685
1690
  }
1686
1691
  const originRows = rows.map(ele => (0, lodash_1.pick)(ele, attrsToPick));
1687
- this.addSingleRowToResultSelections(entity, originRows, context);
1692
+ this.addSingleRowToResultSelections(entity, originRows, context, id);
1688
1693
  }
1689
1694
  else {
1690
- this.addSingleRowToResultSelections(entity, rows, context);
1695
+ this.addSingleRowToResultSelections(entity, rows, context, id);
1691
1696
  }
1692
1697
  }
1693
- addSingleRowToResultSelections(entity, rows, context) {
1698
+ addSingleRowToResultSelections(entity, rows, context, id) {
1694
1699
  const { opRecords } = context;
1695
1700
  let lastOperation = opRecords[opRecords.length - 1];
1696
- if (lastOperation && lastOperation.a === 's') {
1701
+ if (lastOperation && lastOperation.a === 's' && id === lastOperation.id) {
1697
1702
  const entityBranch = lastOperation.d[entity];
1698
1703
  if (entityBranch) {
1699
1704
  rows.forEach((row) => {
@@ -1714,6 +1719,7 @@ class CascadeStore extends RowStore_1.RowStore {
1714
1719
  }
1715
1720
  else {
1716
1721
  lastOperation = {
1722
+ id,
1717
1723
  a: 's',
1718
1724
  d: {},
1719
1725
  };
@@ -1733,8 +1739,8 @@ class CascadeStore extends RowStore_1.RowStore {
1733
1739
  });
1734
1740
  }
1735
1741
  async cascadeSelectAsync(entity, selection, context, option) {
1736
- const { data, filter, indexFrom, count, sorter, total, randomRange, distinct } = selection;
1737
- const { projection, cascadeSelectionFns } = this.destructCascadeSelect(entity, data, context, this.cascadeSelectAsync, this.aggregateAsync, option);
1742
+ const { data, filter, indexFrom, count, sorter, total, randomRange, distinct, id: selectionId } = selection;
1743
+ const { projection, cascadeSelectionFns } = this.destructCascadeSelect(entity, data, context, this.cascadeSelectAsync, this.aggregateAsync, option, selectionId);
1738
1744
  const rows2 = await this.selectAbjointRowAsync(entity, {
1739
1745
  data: projection,
1740
1746
  filter,
@@ -1758,7 +1764,7 @@ class CascadeStore extends RowStore_1.RowStore {
1758
1764
  });
1759
1765
  }
1760
1766
  if (!option.dontCollect) {
1761
- this.addToResultSelections(entity, rows, context);
1767
+ this.addToResultSelections(entity, rows, context, selection.id);
1762
1768
  }
1763
1769
  if (cascadeSelectionFns.length > 0) {
1764
1770
  const ruException = [];
@@ -262,9 +262,19 @@ function createActionTransformerCheckers(actionDefDict) {
262
262
  * @param filters
263
263
  * @param context
264
264
  */
265
- function cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, restAttrs, context) {
265
+ function cascadelyCheckUpdateFilters(entity, schema, action, data, filter, matrix, restAttrs, context) {
266
266
  const successAttrs = (0, lodash_1.difference)(Object.keys(data), restAttrs);
267
267
  const successAttrFilter = (0, lodash_1.pick)(data, successAttrs);
268
+ const checkConditionalFilter = (cf) => {
269
+ // 此时看应用了success的attributes更新后,能否消除掉f中的部分条件
270
+ const result = (0, filter_1.analyzeFilterRelation)(entity, schema, successAttrFilter, cf, true);
271
+ if (typeof result === 'boolean') {
272
+ return result;
273
+ }
274
+ const { sureAttributes } = result;
275
+ const f2 = (0, lodash_1.omit)(cf, sureAttributes);
276
+ return (0, filter_1.checkFilterContains)(entity, context, f2, filter, true);
277
+ };
268
278
  /**
269
279
  * 先找到能直接更新成功的属性
270
280
  */
@@ -273,15 +283,14 @@ function cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, restA
273
283
  if (!f) {
274
284
  return true;
275
285
  }
276
- (0, assert_1.default)(typeof f !== 'function', '此处是原来写的时候的疏漏情况,跑出来再改。by Xc 20250214');
277
- // 此时看应用了success的attributes更新后,能否消除掉f中的部分条件
278
- const result = (0, filter_1.analyzeFilterRelation)(entity, schema, successAttrFilter, f, true);
279
- if (typeof result === 'boolean') {
280
- return result;
286
+ if (typeof f === 'function') {
287
+ const cf = f({ action, data, filter }, context);
288
+ if (cf instanceof Promise) {
289
+ return cf.then((cf2) => cf2 ? checkConditionalFilter(cf2) : true);
290
+ }
291
+ return cf ? checkConditionalFilter(cf) : true;
281
292
  }
282
- const { sureAttributes } = result;
283
- const f2 = (0, lodash_1.omit)(f, sureAttributes);
284
- return (0, filter_1.checkFilterContains)(entity, context, f2, filter, true);
293
+ return checkConditionalFilter(f);
285
294
  });
286
295
  const checkResult1 = (lar) => {
287
296
  const legalAttrs = [];
@@ -301,7 +310,7 @@ function cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, restA
301
310
  if (legalAttrs.length === 0) {
302
311
  throw new types_1.OakAttrCantUpdateException(entity, illegalAttrs, '更新的行当前属性不满足约束,请仔细检查数据');
303
312
  }
304
- return cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, illegalAttrs, context);
313
+ return cascadelyCheckUpdateFilters(entity, schema, action, data, filter, matrix, illegalAttrs, context);
305
314
  };
306
315
  if (legalAttrResult.find(ele => ele instanceof Promise)) {
307
316
  return Promise.all(legalAttrResult).then((lar) => checkResult1(lar));
@@ -341,30 +350,33 @@ function createAttrUpdateCheckers(schema, attrUpdateMatrix) {
341
350
  }
342
351
  const filters = condition.map(ele => {
343
352
  if (typeof ele?.filter === 'function') {
344
- return ele.filter(action || 'select');
353
+ return (ele.filter)({ action: action || 'select', data: data, filter }, context);
345
354
  }
346
355
  return ele?.filter;
347
- }).filter(ele => !!ele);
348
- const f = filters.length > 0 && (0, filter_1.combineFilters)(entity, schema, filters);
349
- if (f) {
350
- const result = (0, filter_1.checkFilterContains)(entity, context, f, filter, true);
351
- if (result instanceof Promise) {
352
- return result.then((v) => {
353
- if (!v) {
354
- if (attrs.length > 1) {
355
- return cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, attrs, context);
356
- }
357
- throw new types_1.OakAttrCantUpdateException(entity, attrs);
356
+ });
357
+ const checkFiltersInner = (filters2) => {
358
+ const filters3 = filters2.filter(ele => !!ele);
359
+ const f = filters3.length > 0 && (0, filter_1.combineFilters)(entity, schema, filters3);
360
+ const checkResultInner = (result2) => {
361
+ if (!result2) {
362
+ if (attrs.length > 1) {
363
+ return cascadelyCheckUpdateFilters(entity, schema, action || 'select', data, filter, matrix, attrs, context);
358
364
  }
359
- });
360
- }
361
- if (!result) {
362
- if (attrs.length > 1) {
363
- return cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, attrs, context);
365
+ throw new types_1.OakAttrCantUpdateException(entity, attrs);
364
366
  }
365
- throw new types_1.OakAttrCantUpdateException(entity, attrs, '更新的行当前属性不满足约束,请仔细检查数据');
367
+ };
368
+ if (f) {
369
+ const result = (0, filter_1.checkFilterContains)(entity, context, f, filter, true);
370
+ if (result instanceof Promise) {
371
+ return result.then((r) => checkResultInner(r));
372
+ }
373
+ return checkResultInner(result);
366
374
  }
375
+ };
376
+ if (filters.find(ele => ele instanceof Promise)) {
377
+ return Promise.all(filters).then((ff) => checkFiltersInner(ff));
367
378
  }
379
+ return checkFiltersInner(filters);
368
380
  }
369
381
  };
370
382
  checkers.push(updateChecker);
@@ -45,6 +45,12 @@ export type ServerConfiguration = {
45
45
  headers?: string[];
46
46
  methods?: string[];
47
47
  };
48
+ ui?: {
49
+ path?: string;
50
+ disable?: boolean;
51
+ username?: string;
52
+ password?: string;
53
+ };
48
54
  internalExceptionMask?: string;
49
55
  koaBody?: IKoaBodyOptions;
50
56
  socket?: (ctx: Koa.ParameterizedContext<any, KoaRouter.IRouterParamContext<any, {}>, any>) => {
@@ -182,6 +182,7 @@ export type CascadeRelationAuth<R extends string> = {
182
182
  [K in R]?: CascadeRelationItem | (CascadeRelationItem | CascadeRelationItem[])[];
183
183
  };
184
184
  export type SelectOpResult<ED extends EntityDict> = {
185
+ id?: string;
185
186
  a: 's';
186
187
  d: {
187
188
  [T in keyof ED]?: {
@@ -1,7 +1,11 @@
1
1
  import { LocaleDef } from './Locale';
2
2
  import { Index } from './Storage';
3
3
  import { EntityShape, Configuration, EntityDict } from './Entity';
4
+ import { EntityDict as BaseEntityDict } from '../base-app-domain';
4
5
  import { StyleDesc } from './Style';
6
+ import { AsyncContext } from '../store/AsyncRowStore';
7
+ import { SyncContext } from '../store/SyncRowStore';
8
+ import { SyncOrAsync } from './Polyfill';
5
9
  export type EntityDesc<Schema extends EntityShape, Action extends string = '', Relation extends string = '', V extends Record<string, string> = {
6
10
  ['##oak_illegal##']: '';
7
11
  }> = {
@@ -14,11 +18,15 @@ export type EntityDesc<Schema extends EntityShape, Action extends string = '', R
14
18
  }) : {
15
19
  style: StyleDesc<Action, V>;
16
20
  });
17
- export type AttrUpdateMatrix<ED extends EntityDict> = {
21
+ export type AttrUpdateMatrix<ED extends EntityDict & BaseEntityDict> = {
18
22
  [T in keyof ED]?: {
19
23
  [A in keyof ED[T]['Update']['data']]?: {
20
24
  actions?: ED[T]['Action'][];
21
- filter?: (NonNullable<ED[T]['Filter']>) | ((action: ED[T]['Action']) => ED[T]['Filter'] | undefined);
25
+ filter?: (NonNullable<ED[T]['Filter']>) | ((option: {
26
+ action: ED[T]['Action'];
27
+ data: ED[T]['Update']['data'];
28
+ filter?: ED[T]['Update']['filter'];
29
+ }, context: AsyncContext<ED> | SyncContext<ED>) => SyncOrAsync<ED[T]['Filter'] | undefined>);
22
30
  };
23
31
  };
24
32
  };
@@ -189,7 +189,7 @@ class SimpleConnector {
189
189
  };
190
190
  }
191
191
  async serializeResult(result, opRecords, headers, body, message) {
192
- if (result instanceof stream_1.Stream || result instanceof Buffer || result instanceof ReadableStream) {
192
+ if (result instanceof stream_1.Stream || result instanceof Buffer) {
193
193
  return {
194
194
  body: result,
195
195
  headers: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oak-domain",
3
- "version": "5.1.23",
3
+ "version": "5.1.25",
4
4
  "author": {
5
5
  "name": "XuChang"
6
6
  },