vona-module-a-orm 5.1.8 → 5.1.12

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.
Files changed (171) hide show
  1. package/LICENSE +1 -1
  2. package/cli/databaseDialect/boilerplate/{{sceneName}}.{{beanName}}.ts_ +2 -2
  3. package/dist/.metadata/index.d.ts +3 -2
  4. package/dist/.metadata/index.d.ts.map +1 -1
  5. package/dist/bean/bean.database.d.ts +2 -2
  6. package/dist/bean/bean.database.d.ts.map +1 -1
  7. package/dist/bean/bean.model.d.ts +1 -1
  8. package/dist/bean/bean.model.d.ts.map +1 -1
  9. package/dist/common/buildWhere.d.ts.map +1 -1
  10. package/dist/common/utils.d.ts +1 -1
  11. package/dist/common/utils.d.ts.map +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1396 -1394
  15. package/dist/index.js.map +1 -1
  16. package/dist/lib/bean.model/bean.model_cache.d.ts.map +1 -0
  17. package/dist/lib/bean.model/bean.model_crud.d.ts.map +1 -0
  18. package/dist/lib/bean.model/bean.model_crud_inner.d.ts.map +1 -0
  19. package/dist/lib/bean.model/bean.model_crud_table.d.ts.map +1 -0
  20. package/dist/lib/bean.model/bean.model_knex.d.ts.map +1 -0
  21. package/dist/{bean → lib}/bean.model/bean.model_meta.d.ts +2 -2
  22. package/dist/lib/bean.model/bean.model_meta.d.ts.map +1 -0
  23. package/dist/lib/bean.model/bean.model_utils.d.ts.map +1 -0
  24. package/dist/lib/bean.model/bean.model_view.d.ts.map +1 -0
  25. package/dist/lib/bean.modelBase.d.ts.map +1 -0
  26. package/dist/lib/dto/dtoAggregate.d.ts +1 -1
  27. package/dist/lib/dto/dtoAggregate.d.ts.map +1 -1
  28. package/dist/lib/dto/dtoCreate.d.ts +1 -1
  29. package/dist/lib/dto/dtoCreate.d.ts.map +1 -1
  30. package/dist/lib/dto/dtoGet.d.ts +1 -1
  31. package/dist/lib/dto/dtoGet.d.ts.map +1 -1
  32. package/dist/lib/dto/dtoGroup.d.ts +1 -1
  33. package/dist/lib/dto/dtoGroup.d.ts.map +1 -1
  34. package/dist/lib/dto/dtoMutate.d.ts +1 -1
  35. package/dist/lib/dto/dtoMutate.d.ts.map +1 -1
  36. package/dist/lib/dto/dtoSelectAndCount.d.ts +1 -1
  37. package/dist/lib/dto/dtoSelectAndCount.d.ts.map +1 -1
  38. package/dist/lib/dto/dtoUpdate.d.ts +1 -1
  39. package/dist/lib/dto/dtoUpdate.d.ts.map +1 -1
  40. package/dist/lib/index.d.ts +1 -0
  41. package/dist/lib/index.d.ts.map +1 -1
  42. package/dist/lib/modelCacheBase.d.ts +3 -3
  43. package/dist/lib/modelCacheBase.d.ts.map +1 -1
  44. package/dist/lib/relations.d.ts +1 -1
  45. package/dist/lib/relations.d.ts.map +1 -1
  46. package/dist/lib/relationsDynamic.d.ts +1 -1
  47. package/dist/lib/relationsDynamic.d.ts.map +1 -1
  48. package/dist/lib/relationsMutate.d.ts +1 -1
  49. package/dist/lib/relationsMutate.d.ts.map +1 -1
  50. package/dist/lib/relationsStatic.d.ts +1 -1
  51. package/dist/lib/relationsStatic.d.ts.map +1 -1
  52. package/dist/service/cacheEntity_.d.ts +1 -1
  53. package/dist/service/cacheEntity_.d.ts.map +1 -1
  54. package/dist/service/cacheQuery_.d.ts +1 -1
  55. package/dist/service/cacheQuery_.d.ts.map +1 -1
  56. package/dist/service/database.d.ts +2 -2
  57. package/dist/service/database.d.ts.map +1 -1
  58. package/dist/{bean/bean.databaseDialectBase.d.ts → service/databaseDialectBase_.d.ts} +2 -2
  59. package/dist/service/databaseDialectBase_.d.ts.map +1 -0
  60. package/dist/service/db_.d.ts +2 -2
  61. package/dist/service/db_.d.ts.map +1 -1
  62. package/dist/service/relations_.d.ts +1 -1
  63. package/dist/service/relations_.d.ts.map +1 -1
  64. package/dist/types/database.d.ts +0 -4
  65. package/dist/types/database.d.ts.map +1 -1
  66. package/dist/types/dto/dtoGet.d.ts +1 -1
  67. package/dist/types/dto/dtoGet.d.ts.map +1 -1
  68. package/dist/types/dto/dtoMutate.d.ts +1 -1
  69. package/dist/types/dto/dtoMutate.d.ts.map +1 -1
  70. package/dist/types/dto/dtoSelectAndCount.d.ts +1 -1
  71. package/dist/types/dto/dtoSelectAndCount.d.ts.map +1 -1
  72. package/dist/types/model.d.ts +1 -1
  73. package/dist/types/model.d.ts.map +1 -1
  74. package/dist/types/modelAggr.d.ts +1 -1
  75. package/dist/types/modelAggr.d.ts.map +1 -1
  76. package/dist/types/modelCount.d.ts +1 -1
  77. package/dist/types/modelCount.d.ts.map +1 -1
  78. package/dist/types/modelGeneral.d.ts +1 -1
  79. package/dist/types/modelGeneral.d.ts.map +1 -1
  80. package/dist/types/modelGroup.d.ts +1 -1
  81. package/dist/types/modelGroup.d.ts.map +1 -1
  82. package/dist/types/modelIncrement.d.ts +1 -1
  83. package/dist/types/modelIncrement.d.ts.map +1 -1
  84. package/dist/types/modelWhere.d.ts +3 -3
  85. package/dist/types/modelWhere.d.ts.map +1 -1
  86. package/dist/types/relations.d.ts +1 -1
  87. package/dist/types/relations.d.ts.map +1 -1
  88. package/dist/types/relationsColumns.d.ts +1 -1
  89. package/dist/types/relationsColumns.d.ts.map +1 -1
  90. package/dist/types/relationsDef.d.ts +1 -1
  91. package/dist/types/relationsDef.d.ts.map +1 -1
  92. package/dist/types/relationsDefDynamic.d.ts +1 -1
  93. package/dist/types/relationsDefDynamic.d.ts.map +1 -1
  94. package/dist/types/relationsDefMutate.d.ts +1 -1
  95. package/dist/types/relationsDefMutate.d.ts.map +1 -1
  96. package/dist/types/relationsMutate.d.ts +1 -1
  97. package/dist/types/relationsMutate.d.ts.map +1 -1
  98. package/dist/types/relationsTables.d.ts +1 -1
  99. package/dist/types/relationsTables.d.ts.map +1 -1
  100. package/package.json +11 -8
  101. package/src/.metadata/index.ts +4 -3
  102. package/src/bean/bean.database.ts +3 -3
  103. package/src/bean/bean.model.ts +1 -1
  104. package/src/bean/schedule.softDeletionPrune.ts +1 -1
  105. package/src/common/buildWhere.ts +8 -9
  106. package/src/common/utils.ts +1 -1
  107. package/src/index.ts +1 -1
  108. package/src/{bean → lib}/bean.model/bean.model_cache.ts +15 -9
  109. package/src/{bean → lib}/bean.model/bean.model_meta.ts +1 -1
  110. package/src/{bean → lib}/bean.modelBase.ts +0 -5
  111. package/src/lib/dto/dtoAggregate.ts +1 -1
  112. package/src/lib/dto/dtoCreate.ts +1 -1
  113. package/src/lib/dto/dtoGet.ts +1 -1
  114. package/src/lib/dto/dtoGroup.ts +1 -1
  115. package/src/lib/dto/dtoMutate.ts +1 -1
  116. package/src/lib/dto/dtoSelectAndCount.ts +1 -1
  117. package/src/lib/dto/dtoUpdate.ts +1 -1
  118. package/src/lib/index.ts +1 -0
  119. package/src/lib/modelCacheBase.ts +3 -3
  120. package/src/lib/relations.ts +1 -1
  121. package/src/lib/relationsDynamic.ts +1 -1
  122. package/src/lib/relationsMutate.ts +1 -1
  123. package/src/lib/relationsStatic.ts +1 -1
  124. package/src/service/cacheEntity_.ts +1 -1
  125. package/src/service/cacheQuery_.ts +1 -1
  126. package/src/service/database.ts +2 -2
  127. package/src/{bean/bean.databaseDialectBase.ts → service/databaseDialectBase_.ts} +38 -41
  128. package/src/service/db_.ts +2 -2
  129. package/src/service/relations_.ts +3 -3
  130. package/src/types/database.ts +0 -5
  131. package/src/types/dto/dtoGet.ts +1 -1
  132. package/src/types/dto/dtoMutate.ts +1 -1
  133. package/src/types/dto/dtoSelectAndCount.ts +1 -1
  134. package/src/types/model.ts +1 -1
  135. package/src/types/modelAggr.ts +1 -1
  136. package/src/types/modelCount.ts +1 -1
  137. package/src/types/modelGeneral.ts +1 -1
  138. package/src/types/modelGroup.ts +1 -1
  139. package/src/types/modelIncrement.ts +1 -1
  140. package/src/types/modelWhere.ts +2 -2
  141. package/src/types/relations.ts +1 -1
  142. package/src/types/relationsColumns.ts +1 -1
  143. package/src/types/relationsDef.ts +1 -1
  144. package/src/types/relationsDefDynamic.ts +1 -1
  145. package/src/types/relationsDefMutate.ts +1 -1
  146. package/src/types/relationsMutate.ts +1 -1
  147. package/src/types/relationsTables.ts +1 -1
  148. package/dist/bean/bean.databaseDialectBase.d.ts.map +0 -1
  149. package/dist/bean/bean.model/bean.model_cache.d.ts.map +0 -1
  150. package/dist/bean/bean.model/bean.model_crud.d.ts.map +0 -1
  151. package/dist/bean/bean.model/bean.model_crud_inner.d.ts.map +0 -1
  152. package/dist/bean/bean.model/bean.model_crud_table.d.ts.map +0 -1
  153. package/dist/bean/bean.model/bean.model_knex.d.ts.map +0 -1
  154. package/dist/bean/bean.model/bean.model_meta.d.ts.map +0 -1
  155. package/dist/bean/bean.model/bean.model_utils.d.ts.map +0 -1
  156. package/dist/bean/bean.model/bean.model_view.d.ts.map +0 -1
  157. package/dist/bean/bean.modelBase.d.ts.map +0 -1
  158. /package/dist/{bean → lib}/bean.model/bean.model_cache.d.ts +0 -0
  159. /package/dist/{bean → lib}/bean.model/bean.model_crud.d.ts +0 -0
  160. /package/dist/{bean → lib}/bean.model/bean.model_crud_inner.d.ts +0 -0
  161. /package/dist/{bean → lib}/bean.model/bean.model_crud_table.d.ts +0 -0
  162. /package/dist/{bean → lib}/bean.model/bean.model_knex.d.ts +0 -0
  163. /package/dist/{bean → lib}/bean.model/bean.model_utils.d.ts +0 -0
  164. /package/dist/{bean → lib}/bean.model/bean.model_view.d.ts +0 -0
  165. /package/dist/{bean → lib}/bean.modelBase.d.ts +0 -0
  166. /package/src/{bean → lib}/bean.model/bean.model_crud.ts +0 -0
  167. /package/src/{bean → lib}/bean.model/bean.model_crud_inner.ts +0 -0
  168. /package/src/{bean → lib}/bean.model/bean.model_crud_table.ts +0 -0
  169. /package/src/{bean → lib}/bean.model/bean.model_knex.ts +0 -0
  170. /package/src/{bean → lib}/bean.model/bean.model_utils.ts +0 -0
  171. /package/src/{bean → lib}/bean.model/bean.model_view.ts +0 -0
package/dist/index.js CHANGED
@@ -1,17 +1,16 @@
1
1
  import BigNumber from 'bignumber.js';
2
- import { BeanInfo, BeanAopMethodBase, BeanBase, deepExtend, appResource, beanFullNameFromOnionName, Virtual, cast, useApp, $makeLocaleMagic, disposeInstance, BeanSimple, combineConfigDefault, BeanScopeBase, createBeanDecorator, PickClassInner, $Class } from 'vona';
2
+ import { BeanInfo, BeanAopMethodBase, BeanBase, deepExtend, appResource, beanFullNameFromOnionName, cast, useApp, $makeLocaleMagic, Virtual, BeanSimple, combineConfigDefault, BeanScopeBase, createBeanDecorator, PickClassInner, $Class, disposeInstance } from 'vona';
3
3
  import { __decorate, __metadata } from 'tslib';
4
4
  import { AopMethod } from 'vona-module-a-aspect';
5
5
  import { Service, Bean, Scope } from 'vona-module-a-bean';
6
6
  import { AsyncLocalStorage, AsyncResource } from 'node:async_hooks';
7
- import { isNil, catchError, safeBoolean, ensureArray, hashkey } from '@cabloy/utils';
7
+ import { isNil, catchError, ensureArray, safeBoolean, hashkey } from '@cabloy/utils';
8
8
  import knex from 'knex';
9
9
  import { BeanMutateBase } from 'vona-module-a-beanmutate';
10
10
  import { swapDeps } from '@cabloy/deps';
11
11
  import { $tableNameFromEntity, $tableDefaults, $columnsAll } from 'vona-module-a-ormutils';
12
12
  import { prepareClassType, Api, v, schemaRenderVisible, getSchemaDynamic, SymbolSchemaDynamicRefId, addSchemaDynamic, mergeDtoFieldsOpenapiMetadata } from 'vona-module-a-openapiutils';
13
13
  import z from 'zod';
14
- import { parseFirstWord, toLowerCaseFirstChar } from '@cabloy/word-utils';
15
14
  import { Broadcast, BeanBroadcastBase } from 'vona-module-a-broadcast';
16
15
  import { Event, BeanEventBase } from 'vona-module-a-event';
17
16
  import { Hmr } from 'vona-module-a-hmrbase';
@@ -20,6 +19,7 @@ import { Schedule } from 'vona-module-a-schedule';
20
19
  import { configAll, configRedis } from 'vona-module-a-summer';
21
20
  import { ServiceDatabaseAsyncLocalStorage as ServiceDatabaseAsyncLocalStorage$1, ServiceTransactionConsistency‌ as ServiceTransactionConsistency_ } from 'vona-module-a-orm';
22
21
  import { mutate } from 'mutate-on-copy';
22
+ import { parseFirstWord, toLowerCaseFirstChar } from '@cabloy/word-utils';
23
23
 
24
24
  let AopMethodTransaction = class AopMethodTransaction extends BeanAopMethodBase {
25
25
  execute(options, _args, next, _receiver, _prop) {
@@ -769,131 +769,6 @@ BeanDatabase = __decorate([Bean(), BeanInfo({
769
769
  module: "a-orm"
770
770
  })], BeanDatabase);
771
771
 
772
- let BeanDatabaseDialectBase = class BeanDatabaseDialectBase extends BeanBase {
773
- constructor(...args) {
774
- super(...args);
775
- this._capabilities = void 0;
776
- this._configBase = void 0;
777
- }
778
- get capabilities() {
779
- if (!this._capabilities) throw new Error('Should provide dialect capabilities');
780
- return this._capabilities;
781
- }
782
- get configBase() {
783
- return this._configBase;
784
- }
785
- async fetchDatabases(_schemaBuilder, _databasePrefix) {
786
- throw new Error('Not Implemented');
787
- }
788
- async createDatabase(_schemaBuilder, _databaseName) {
789
- throw new Error('Not Implemented');
790
- }
791
- async dropDatabase(_schemaBuilder, _databaseName) {
792
- throw new Error('Not Implemented');
793
- }
794
- async fetchIndexes(_schemaBuilder, _tableName) {
795
- throw new Error('Not Implemented');
796
- }
797
- async insert(_builder, _datas) {
798
- throw new Error('Not Implemented');
799
- }
800
- async select(_builder, datas, _fn) {
801
- return datas;
802
- }
803
- query(_result) {
804
- throw new Error('Not Implemented');
805
- }
806
- async viewDependents(_builder, _viewName) {
807
- throw new Error('Not Implemented');
808
- }
809
- coerceColumn(column) {
810
- // result
811
- const result = {
812
- type: column.type
813
- };
814
- // coerce
815
- result.default = this._coerceColumnValue(column.type, column.defaultValue);
816
- // ok
817
- return result;
818
- }
819
- async selectAsSqlite3(_builder, datas, fn) {
820
- const columns = await fn();
821
- // data
822
- for (const data of datas) {
823
- for (const columnName in columns) {
824
- const column = columns[columnName];
825
- if (Object.prototype.hasOwnProperty.call(data, columnName)) {
826
- const value = data[columnName];
827
- if (column.type === 'json' && !isNil(value) && typeof value === 'string') {
828
- data[columnName] = JSON.parse(value);
829
- } else if (column.type === 'datetime' && !isNil(value)) {
830
- data[columnName] = new Date(value);
831
- }
832
- }
833
- }
834
- }
835
- return datas;
836
- }
837
- async insertAsMysql(builder, datas) {
838
- if (datas.length === 0) return [[], builder];
839
- if (isNil(datas[0].id)) {
840
- let builderFirst = undefined;
841
- const ids = [];
842
- for (const data of datas) {
843
- const builder2 = builder.clone();
844
- builder2.insert(data);
845
- const items = await builder2;
846
- ids.push(items[0]);
847
- if (!builderFirst) builderFirst = builder2;
848
- }
849
- return [ids, builderFirst ?? builder];
850
- } else {
851
- builder.insert(datas);
852
- await builder;
853
- return [datas.map(item => item.id), builder];
854
- }
855
- }
856
- async insertAsPg(builder, datas) {
857
- if (datas.length === 0) return [[], builder];
858
- if (isNil(datas[0].id)) {
859
- builder.insert(datas).returning('id');
860
- const items = await builder;
861
- return [items.map(item => item.id), builder];
862
- } else {
863
- builder.insert(datas);
864
- await builder;
865
- return [datas.map(item => item.id), builder];
866
- }
867
- }
868
- _coerceColumnValue(type, value) {
869
- // null
870
- if (isNil(value)) return undefined;
871
- // type
872
- if (['bit', 'bool', 'boolean'].includes(type)) return safeBoolean(value);
873
- if (['int'].includes(type)) return this._safeNumber(value);
874
- if (this._columnTypePrefixes(type, ['timestamp']) && value === 'CURRENT_TIMESTAMP') return undefined; // new Date();
875
- if (this._columnTypePrefixes(type, ['float', 'double'])) return this._safeNumber(value);
876
- if (this._columnTypePrefixes(type, ['tinyint', 'smallint', 'mediumint', 'bigint', 'numeric', 'integer'])) {
877
- return this._safeNumber(value);
878
- }
879
- // pg: NULL::character varying
880
- if (value.indexOf('NULL::') === 0) return undefined;
881
- // others
882
- return value;
883
- }
884
- // pg: nextval
885
- _safeNumber(value) {
886
- const num = Number(value);
887
- return Number.isNaN(num) ? undefined : num;
888
- }
889
- _columnTypePrefixes(type, prefixes) {
890
- return prefixes.some(prefix => type.includes(prefix));
891
- }
892
- };
893
- BeanDatabaseDialectBase = __decorate([Bean(), Virtual(), BeanInfo({
894
- module: "a-orm"
895
- })], BeanDatabaseDialectBase);
896
-
897
772
  const OpAggrs = ['count', 'sum', 'avg', 'max', 'min'];
898
773
  const OpJoint = {
899
774
  and: '_and_',
@@ -926,7 +801,7 @@ const OpNormal = {
926
801
  ref: '_ref_'
927
802
  };
928
803
  const Op = {
929
- skip: '_skip_',
804
+ omit: undefined,
930
805
  ...OpJoint,
931
806
  ...OpNormal
932
807
  };
@@ -994,8 +869,8 @@ function buildWhere(db, builder, wheres, having = false) {
994
869
  _buildWhereInner(having, db, builder, wheres);
995
870
  }
996
871
  function _buildWhereInner(having, db, builder, wheres, column) {
997
- // skip
998
- if (wheres === Op.skip) {
872
+ // omit
873
+ if (wheres === Op.omit) {
999
874
  return;
1000
875
  }
1001
876
  // raw
@@ -1024,8 +899,8 @@ function _buildWhereInner(having, db, builder, wheres, column) {
1024
899
  }
1025
900
  }
1026
901
  function _buildWhereOpJoint(having, db, builder, column, wheres, op) {
1027
- // skip
1028
- if (wheres === Op.skip) {
902
+ // omit
903
+ if (wheres === Op.omit) {
1029
904
  return;
1030
905
  }
1031
906
  // and/or
@@ -1072,8 +947,8 @@ function _buildWhereOpJoint(having, db, builder, column, wheres, op) {
1072
947
  }
1073
948
  }
1074
949
  function _buildWhereColumn(having, db, builder, column, value, op) {
1075
- // skip
1076
- if (value === Op.skip) {
950
+ // omit condition
951
+ if (value === Op.omit) {
1077
952
  return;
1078
953
  }
1079
954
  // raw
@@ -1081,8 +956,8 @@ function _buildWhereColumn(having, db, builder, column, value, op) {
1081
956
  _buildWhereColumnOpNormal(having, db, builder, column, value, op ?? Op.eq);
1082
957
  return;
1083
958
  }
1084
- // null/undefined
1085
- if (isNil(value)) {
959
+ // null
960
+ if (value === null) {
1086
961
  _buildWhereColumnOpNormal(having, db, builder, column, value, op ?? Op.is);
1087
962
  return;
1088
963
  }
@@ -2273,6 +2148,165 @@ ServiceCacheQuery = __decorate([Service(), BeanInfo({
2273
2148
  module: "a-orm"
2274
2149
  })], ServiceCacheQuery);
2275
2150
 
2151
+ const BOOLEAN_COLUMN_TYPES = ['bit', 'bool', 'boolean'];
2152
+ const NUMBER_COLUMN_TYPES = ['int'];
2153
+ const TIMESTAMP_COLUMN_TYPE_PREFIXES = ['timestamp'];
2154
+ const FLOAT_COLUMN_TYPE_PREFIXES = ['float', 'double'];
2155
+ const INTEGER_COLUMN_TYPE_PREFIXES = ['tinyint', 'smallint', 'mediumint', 'bigint', 'numeric', 'integer'];
2156
+ let ServiceDatabaseDialectBase = class ServiceDatabaseDialectBase extends BeanBase {
2157
+ constructor(...args) {
2158
+ super(...args);
2159
+ this._capabilities = void 0;
2160
+ this._configBase = void 0;
2161
+ }
2162
+ get capabilities() {
2163
+ if (!this._capabilities) throw new Error('Should provide dialect capabilities');
2164
+ return this._capabilities;
2165
+ }
2166
+ get configBase() {
2167
+ return this._configBase;
2168
+ }
2169
+ async fetchDatabases(_schemaBuilder, _databasePrefix) {
2170
+ throw new Error('Not Implemented');
2171
+ }
2172
+ async createDatabase(_schemaBuilder, _databaseName) {
2173
+ throw new Error('Not Implemented');
2174
+ }
2175
+ async dropDatabase(_schemaBuilder, _databaseName) {
2176
+ throw new Error('Not Implemented');
2177
+ }
2178
+ async fetchIndexes(_schemaBuilder, _tableName) {
2179
+ throw new Error('Not Implemented');
2180
+ }
2181
+ async insert(_builder, _datas) {
2182
+ throw new Error('Not Implemented');
2183
+ }
2184
+ async select(_builder, datas, _fn) {
2185
+ return datas;
2186
+ }
2187
+ query(_result) {
2188
+ throw new Error('Not Implemented');
2189
+ }
2190
+ async viewDependents(_builder, _viewName) {
2191
+ throw new Error('Not Implemented');
2192
+ }
2193
+ coerceColumn(column) {
2194
+ const result = {
2195
+ type: column.type
2196
+ };
2197
+ result.default = this._coerceColumnValue(column.type, column.defaultValue);
2198
+ return result;
2199
+ }
2200
+ async selectAsSqlite3(_builder, datas, fn) {
2201
+ const columns = await fn();
2202
+ // data
2203
+ for (const data of datas) {
2204
+ for (const columnName in columns) {
2205
+ const column = columns[columnName];
2206
+ if (Object.prototype.hasOwnProperty.call(data, columnName)) {
2207
+ const value = data[columnName];
2208
+ if (column.type === 'json' && !isNil(value) && typeof value === 'string') {
2209
+ data[columnName] = JSON.parse(value);
2210
+ } else if (column.type === 'datetime' && !isNil(value)) {
2211
+ data[columnName] = new Date(value);
2212
+ }
2213
+ }
2214
+ }
2215
+ }
2216
+ return datas;
2217
+ }
2218
+ async insertAsMysql(builder, datas) {
2219
+ if (datas.length === 0) return [[], builder];
2220
+ if (!isNil(datas[0].id)) {
2221
+ builder.insert(datas);
2222
+ await builder;
2223
+ return [datas.map(item => item.id), builder];
2224
+ }
2225
+ let builderFirst = undefined;
2226
+ const ids = [];
2227
+ for (const data of datas) {
2228
+ const builder2 = builder.clone();
2229
+ builder2.insert(data);
2230
+ const items = await builder2;
2231
+ ids.push(items[0]);
2232
+ if (!builderFirst) builderFirst = builder2;
2233
+ }
2234
+ return [ids, builderFirst ?? builder];
2235
+ }
2236
+ async insertAsPg(builder, datas) {
2237
+ if (datas.length === 0) return [[], builder];
2238
+ if (!isNil(datas[0].id)) {
2239
+ builder.insert(datas);
2240
+ await builder;
2241
+ return [datas.map(item => item.id), builder];
2242
+ }
2243
+ builder.insert(datas).returning('id');
2244
+ const items = await builder;
2245
+ return [items.map(item => item.id), builder];
2246
+ }
2247
+ _coerceColumnValue(type, value) {
2248
+ if (isNil(value)) return undefined;
2249
+ if (BOOLEAN_COLUMN_TYPES.includes(type)) return safeBoolean(value);
2250
+ if (NUMBER_COLUMN_TYPES.includes(type)) return this._safeNumber(value);
2251
+ if (this._columnTypePrefixes(type, TIMESTAMP_COLUMN_TYPE_PREFIXES) && value === 'CURRENT_TIMESTAMP') {
2252
+ return undefined; // new Date();
2253
+ }
2254
+ if (this._columnTypePrefixes(type, FLOAT_COLUMN_TYPE_PREFIXES)) return this._safeNumber(value);
2255
+ if (this._columnTypePrefixes(type, INTEGER_COLUMN_TYPE_PREFIXES)) return this._safeNumber(value);
2256
+ // pg: NULL::character varying
2257
+ if (value.indexOf('NULL::') === 0) return undefined;
2258
+ return value;
2259
+ }
2260
+ // pg: nextval
2261
+ _safeNumber(value) {
2262
+ const num = Number(value);
2263
+ return Number.isNaN(num) ? undefined : num;
2264
+ }
2265
+ _columnTypePrefixes(type, prefixes) {
2266
+ return prefixes.some(prefix => type.includes(prefix));
2267
+ }
2268
+ };
2269
+ ServiceDatabaseDialectBase = __decorate([Service(), Virtual(), BeanInfo({
2270
+ module: "a-orm"
2271
+ })], ServiceDatabaseDialectBase);
2272
+
2273
+ const SymbolModuleScope$1 = Symbol('SymbolModuleScope');
2274
+ let ServiceEntityResolver = class ServiceEntityResolver extends BeanBase {
2275
+ constructor(moduleScope) {
2276
+ super();
2277
+ this[SymbolModuleScope$1] = void 0;
2278
+ this.__instances = {};
2279
+ this[SymbolModuleScope$1] = moduleScope;
2280
+ }
2281
+ __get__(prop) {
2282
+ if (!this.__instances[prop]) {
2283
+ const beanFullName = `${this[SymbolModuleScope$1]}.entity.${prop}`;
2284
+ const beanOptions = appResource.getBean(beanFullName);
2285
+ this.__instances[prop] = $columnsAll(beanOptions.beanClass, true, true);
2286
+ }
2287
+ return this.__instances[prop];
2288
+ }
2289
+ };
2290
+ ServiceEntityResolver = __decorate([Service(), __metadata("design:paramtypes", [String]), BeanInfo({
2291
+ module: "a-orm"
2292
+ })], ServiceEntityResolver);
2293
+
2294
+ const SymbolModuleScope = Symbol('SymbolModuleScope');
2295
+ let ServiceModelResolver = class ServiceModelResolver extends BeanBase {
2296
+ constructor(moduleScope) {
2297
+ super();
2298
+ this[SymbolModuleScope] = void 0;
2299
+ this[SymbolModuleScope] = moduleScope;
2300
+ }
2301
+ __get__(prop) {
2302
+ const beanFullName = `${this[SymbolModuleScope]}.model.${prop}`;
2303
+ return this.bean._getBean(beanFullName);
2304
+ }
2305
+ };
2306
+ ServiceModelResolver = __decorate([Service(), __metadata("design:paramtypes", [String]), BeanInfo({
2307
+ module: "a-orm"
2308
+ })], ServiceModelResolver);
2309
+
2276
2310
  function handleRelationsCollection(relationsStatic, includeWrapper) {
2277
2311
  // collect
2278
2312
  const relations = [];
@@ -2856,1379 +2890,1347 @@ ServiceRelations = __decorate([Service(), BeanInfo({
2856
2890
  module: "a-orm"
2857
2891
  })], ServiceRelations);
2858
2892
 
2859
- class BeanModelCrud extends BeanModelCrudInner {
2860
- async mget(ids, options) {
2861
- return await this._mget(undefined, ids, options);
2862
- }
2863
- async select(params, options) {
2864
- return await this._select(undefined, params, options);
2865
- }
2866
- async get(where, options) {
2867
- return await this._get(undefined, where, options);
2868
- }
2869
- async count(params, options) {
2870
- return await this._count(undefined, params, options);
2871
- }
2872
- async insert(data, options) {
2873
- return await this._insertBulk(undefined, data, options);
2893
+ let BroadcastColumnsClear = class BroadcastColumnsClear extends BeanBroadcastBase {
2894
+ async execute(data, isEmitter) {
2895
+ const {
2896
+ clientName,
2897
+ tableName
2898
+ } = data;
2899
+ if (!isEmitter) {
2900
+ await cast(this.scope.service.database).columnsClearWorker(clientName, tableName);
2901
+ }
2874
2902
  }
2875
- async insertBulk(data, options) {
2876
- return await this._insertBulk(undefined, data, options);
2877
- }
2878
- async update(data, options) {
2879
- return await this._update(undefined, data, options);
2880
- }
2881
- async delete(where, options) {
2882
- return await this._delete(undefined, where, options);
2903
+ };
2904
+ BroadcastColumnsClear = __decorate([Broadcast(), BeanInfo({
2905
+ module: "a-orm"
2906
+ })], BroadcastColumnsClear);
2907
+
2908
+ let EventClientNameReal = class EventClientNameReal extends BeanEventBase {};
2909
+ EventClientNameReal = __decorate([Event(), BeanInfo({
2910
+ module: "a-orm"
2911
+ })], EventClientNameReal);
2912
+
2913
+ let EventColumnsClear = class EventColumnsClear extends BeanEventBase {};
2914
+ EventColumnsClear = __decorate([Event(), BeanInfo({
2915
+ module: "a-orm"
2916
+ })], EventColumnsClear);
2917
+
2918
+ let HmrEntity = class HmrEntity extends BeanBase {
2919
+ async reload(_beanOptions) {
2920
+ this.app.bean.worker.reload();
2883
2921
  }
2884
- }
2922
+ };
2923
+ HmrEntity = __decorate([Hmr(), BeanInfo({
2924
+ module: "a-orm"
2925
+ })], HmrEntity);
2885
2926
 
2886
- class BeanModelCache extends BeanModelCrud {
2887
- constructor(...args) {
2888
- super(...args);
2889
- this.cacheQuery = void 0;
2890
- this.cacheEntity = void 0;
2891
- this.relations = void 0;
2927
+ // import { clearAllCacheModelsClear, clearCacheModelCacheInstance } from '../lib/const.ts';
2928
+ let HmrModel = class HmrModel extends BeanBase {
2929
+ async reload(_beanOptions) {
2930
+ // more deps: dto/model
2931
+ this.app.bean.worker.reload();
2932
+ // clearAllCacheModelsClear(this.app);
2933
+ // await clearCacheModelCacheInstance(this.app, beanOptions.beanFullName);
2892
2934
  }
2893
- __init__(clientName, table) {
2894
- super.__init__(clientName, table);
2895
- this.cacheQuery = this.bean._newBean(ServiceCacheQuery, this);
2896
- this.cacheEntity = this.bean._newBean(ServiceCacheEntity, this);
2897
- this.relations = this.bean._newBean(ServiceRelations, this);
2935
+ };
2936
+ HmrModel = __decorate([Hmr(), BeanInfo({
2937
+ module: "a-orm"
2938
+ })], HmrModel);
2939
+
2940
+ let QueueDoubleDelete = class QueueDoubleDelete extends BeanQueueBase {
2941
+ async execute(data, _options) {
2942
+ const beanInstance = this.app.bean._newBean(data.beanFullName, data.clientName, data.table);
2943
+ await beanInstance[data.method](...data.args);
2898
2944
  }
2899
- async __dispose__() {
2900
- await disposeInstance(this.cacheQuery);
2901
- await disposeInstance(this.cacheEntity);
2945
+ };
2946
+ QueueDoubleDelete = __decorate([Queue({
2947
+ options: {
2948
+ job: {
2949
+ delay: 3 * 1000
2950
+ }
2902
2951
  }
2903
- async insert(data, options) {
2904
- if (!data) data = {};
2905
- const items = await this.insertBulk([data], options);
2906
- return items[0];
2952
+ }), BeanInfo({
2953
+ module: "a-orm"
2954
+ })], QueueDoubleDelete);
2955
+
2956
+ let ScheduleSoftDeletionPrune = class ScheduleSoftDeletionPrune extends BeanBase {
2957
+ async execute() {
2958
+ const onionSlices = this.bean.onion.model.getOnionsEnabledCached();
2959
+ for (const onionSlice of onionSlices) {
2960
+ if (onionSlice.beanOptions.options?.disableDeleted) continue;
2961
+ let softDeletionPrune = onionSlice.beanOptions.options?.softDeletionPrune ?? this.scope.config.softDeletionPrune.enable;
2962
+ if (!softDeletionPrune) continue;
2963
+ if (softDeletionPrune === true) softDeletionPrune = {};
2964
+ await this._modulePrune(onionSlice, softDeletionPrune);
2965
+ }
2907
2966
  }
2908
- async insertBulk(items, options) {
2909
- const itemsResult = await this.__insertBulk_raw(undefined, items, options);
2910
- const itemsNew = items.map((item, index) => {
2911
- return Object.assign({}, item, {
2912
- id: cast(itemsResult[index]).id
2967
+ async _modulePrune(onionSlice, softDeletionPrune) {
2968
+ const handler = softDeletionPrune.handler;
2969
+ const expired = softDeletionPrune.expired ?? this.scope.config.softDeletionPrune.expired;
2970
+ const modelTarget = this.bean._getBean(onionSlice.beanOptions.beanFullName);
2971
+ if (handler) {
2972
+ await handler(this.ctx, modelTarget, {
2973
+ expired
2913
2974
  });
2914
- });
2915
- return await this.relations.handleRelationsMutate(itemsResult, itemsNew, options, options);
2916
- }
2917
- async __insertBulk_raw(table, items, options) {
2918
- if (items.length === 0) return [];
2919
- // table
2920
- table = table || this.getTable(items[0]);
2921
- if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
2922
- // insert
2923
- const res = await this._insertBulk(table, items, options);
2924
- // delete cache
2925
- const ids = res.map(item => cast(item).id);
2926
- await this.cacheEntityDel(ids, table);
2927
- return res;
2928
- }
2929
- async mutate(data, options) {
2930
- if (!data) data = {};
2931
- const items = await this.mutateBulk([data], options);
2932
- return items[0];
2933
- }
2934
- async mutateBulk(items, options) {
2935
- return await this.__mutateBulk_raw(undefined, items, options);
2936
- }
2937
- async __mutateBulk_raw(table, items, options) {
2938
- // table
2939
- table = table || this.getTable(items[0]);
2940
- if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
2941
- // check
2942
- const indexesInsert = [];
2943
- const indexesUpdate = [];
2944
- const itemsInsert = [];
2945
- const itemsUpdate = [];
2946
- const itemsDelete = [];
2947
- for (let index = 0; index < items.length; index++) {
2948
- const item = items[index];
2949
- if (cast(item).deleted) {
2950
- if (!isNil(cast(item).id)) {
2951
- itemsDelete.push(item);
2975
+ } else {
2976
+ const expiredTime = new Date(Date.now() - expired);
2977
+ await modelTarget.delete({
2978
+ deleted: true,
2979
+ updatedAt: {
2980
+ _lt_: expiredTime
2952
2981
  }
2953
- } else if (!isNil(cast(item).id)) {
2954
- itemsUpdate.push(item);
2955
- indexesUpdate.push(index);
2956
- } else {
2957
- itemsInsert.push(item);
2958
- indexesInsert.push(index);
2959
- }
2960
- }
2961
- // insert/update
2962
- const itemsInsertNew = await this.__insertBulk_raw(table, itemsInsert, options);
2963
- await this.__updateBulk_raw(table, itemsUpdate, options);
2964
- const itemsMutate = itemsInsert.map((item, index) => {
2965
- return Object.assign({}, item, {
2966
- id: cast(itemsInsertNew[index]).id
2982
+ }, {
2983
+ disableDeleted: true
2967
2984
  });
2968
- }).concat(itemsUpdate);
2969
- let itemsMutateResult = itemsInsertNew.concat(itemsUpdate);
2970
- const indexesMutate = indexesInsert.concat(indexesUpdate);
2971
- itemsMutateResult = await this.relations.handleRelationsMutate(itemsMutateResult, itemsMutate, options, options);
2972
- let result = [];
2973
- for (let index = 0; index < indexesMutate.length; index++) {
2974
- result[indexesMutate[index]] = itemsMutateResult[index];
2975
2985
  }
2976
- result = result.filter(item => !!item); // fitler deleted items
2977
- // delete
2978
- const idsDelete = itemsDelete.map(item => cast(item).id);
2979
- await this.__deleteBulk_raw_with_relations(table, idsDelete, options);
2980
- // ok
2981
- return result;
2982
2986
  }
2983
- async mget(ids, options) {
2984
- if (ids.length === 0) return [];
2985
- const relations = this.relations.handleRelationsCollection(options);
2986
- const [options2, refKeys] = this.relations.prepareColumnsByRelations(relations, options);
2987
- let items = await this.__mget_raw(undefined, ids, options2);
2988
- if (items.length === 0) return items;
2989
- items = await this.relations.handleRelationsMany(relations, items, options, options);
2990
- if (refKeys) {
2991
- for (const item of items) {
2992
- for (const refKey of refKeys) {
2993
- delete item[refKey];
2987
+ };
2988
+ ScheduleSoftDeletionPrune = __decorate([Schedule({
2989
+ repeat: {
2990
+ every: 24 * 3600 * 1000
2991
+ }
2992
+ }), BeanInfo({
2993
+ module: "a-orm"
2994
+ })], ScheduleSoftDeletionPrune);
2995
+
2996
+ function config(_app) {
2997
+ return {
2998
+ sharding: {
2999
+ cache: {
3000
+ doubleDelete: true
3001
+ }
3002
+ },
3003
+ rest: {
3004
+ query: {
3005
+ pageSize: {
3006
+ default: 20,
3007
+ max: 100
3008
+ },
3009
+ orders: {
3010
+ default: 'createdAt,desc'
2994
3011
  }
2995
3012
  }
2996
- }
2997
- return items;
2998
- }
2999
- async __mget_raw(table, ids, options) {
3000
- // table
3001
- table = table || this.getTable(undefined);
3002
- if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3003
- // check if cache
3004
- if (this._checkDisableCacheEntityByOptions(options)) {
3005
- return await super._mget(table, ids, options);
3006
- }
3007
- // cache
3008
- const cache = this.cacheEntity.getInstance(table);
3009
- let items = await cache.mget(ids, {
3010
- mget: async ids => {
3011
- return await super._mget_original(table, ids, {
3012
- disableDeleted: true
3013
- });
3013
+ },
3014
+ table: {
3015
+ identityType: 'bigint'
3016
+ },
3017
+ model: {
3018
+ disableDeleted: false,
3019
+ disableInstance: false,
3020
+ disableCreateTime: false,
3021
+ disableUpdateTime: false
3022
+ },
3023
+ softDeletionPrune: {
3024
+ enable: true,
3025
+ expired: 14 * 24 * 3600 * 1000
3026
+ },
3027
+ dialects: {
3028
+ 'better-sqlite3': 'a-ormdialect:betterSqlite3',
3029
+ 'mysql': 'a-ormdialect:mysql',
3030
+ 'mysql2': 'a-ormdialect:mysql3',
3031
+ 'pg': 'a-ormdialect:pg'
3032
+ },
3033
+ summer: {
3034
+ enable: true,
3035
+ meta: {},
3036
+ presetDefault: 'redis',
3037
+ preset: {
3038
+ redis: configRedis,
3039
+ all: configAll
3014
3040
  },
3015
- db: this.db
3016
- });
3017
- // filter disableDeleted
3018
- items = items.filter(item => {
3019
- if (!item) return false;
3020
- if (!this._checkIfEntityValidByDeleted(item, options)) return false;
3021
- return true;
3022
- });
3023
- return this.__filterMGetColumns(items, options?.columns);
3024
- }
3025
- async count(params, options, _modelJoins) {
3026
- const column = params?.column ?? '*';
3027
- const params2 = Object.assign({}, params, {
3028
- aggrs: {
3029
- count: column
3030
- },
3031
- column: undefined
3032
- });
3033
- const item = await this.aggregate(params2, options);
3034
- return this.extractFirstValue(item);
3035
- }
3036
- async increment(params, options, _modelJoins) {
3037
- return await this.__increment_raw(undefined, params, options);
3038
- }
3039
- async decrement(params, options, _modelJoins) {
3040
- const columns = {};
3041
- for (const key in params.columns) {
3042
- columns[key] = -params.columns[key];
3041
+ redis: {
3042
+ client: 'model'
3043
+ }
3044
+ },
3045
+ logger: {
3046
+ maxLength: 256
3043
3047
  }
3044
- const params2 = Object.assign({}, params, {
3045
- columns
3048
+ };
3049
+ }
3050
+
3051
+ const errors = {
3052
+ ShouldSpecifyTable: 1001
3053
+ };
3054
+
3055
+ function ExtendSchemaBuilder(app) {
3056
+ ['fetchDatabases', 'createDatabase', 'dropDatabase', 'fetchIndexes'].forEach(method => {
3057
+ knex.SchemaBuilder.extend(method, async function (...args) {
3058
+ const client = cast(cast(this).client).config.client;
3059
+ const dialect = app.bean.database.getDialect(client);
3060
+ return await dialect[method](this, ...args);
3046
3061
  });
3047
- return await this.__increment_raw(undefined, params2, options);
3048
- }
3049
- async __increment_raw(table, params, options) {
3050
- // table
3051
- table = table || this.getTable(params?.where);
3052
- if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3053
- // check if cache
3054
- if (this._checkDisableCacheEntityByOptions(options)) {
3055
- return await super._increment(table, params, options);
3056
- }
3057
- const where = params?.where;
3058
- const items = await this.__select_raw(table, {
3059
- where,
3060
- columns: ['id']
3061
- }, options);
3062
- if (items.length === 0) {
3063
- // donothing
3064
- return 0;
3062
+ });
3063
+ }
3064
+
3065
+ const __ThisModule__ = 'a-orm';
3066
+
3067
+ function ExtendTableBuilder(app) {
3068
+ const scope = app.scope(__ThisModule__);
3069
+ function _basicFields(options, identityType) {
3070
+ options = options || {};
3071
+ if (options.id !== false) {
3072
+ const _identityType = identityType ?? scope.config.table.identityType;
3073
+ if (_identityType === 'bigint') {
3074
+ this.bigIncrements();
3075
+ } else if (_identityType === 'number') {
3076
+ this.increments();
3077
+ } else {
3078
+ throw new Error('Should create column id by yourself');
3079
+ }
3065
3080
  }
3066
- let id;
3067
- if (items.length === 1) {
3068
- id = cast(items[0]).id;
3081
+ if (options.timestamps !== false) this.timestamps(true, true, true);
3082
+ if (options.deleted !== false) this.boolean('deleted').defaultTo(false);
3083
+ if (options.iid !== false) this.integer('iid').defaultTo(0);
3084
+ return this;
3085
+ }
3086
+ knex.TableBuilder.extend('basicFields', function (options) {
3087
+ _basicFields.call(this, options, undefined);
3088
+ return this;
3089
+ });
3090
+ knex.TableBuilder.extend('basicFieldsSimple', function (options) {
3091
+ _basicFields.call(this, options, 'number');
3092
+ return this;
3093
+ });
3094
+ knex.TableBuilder.extend('tableIdentity', function (columnName) {
3095
+ const _identityType = scope.config.table.identityType;
3096
+ if (_identityType === 'bigint') {
3097
+ return this.bigInteger(columnName); // default value is null
3098
+ } else if (_identityType === 'number') {
3099
+ return this.integer(columnName); // default value is null
3069
3100
  } else {
3070
- id = items.map(item => cast(item).id);
3101
+ throw new Error(`Should create column ${columnName} by yourself`);
3071
3102
  }
3072
- // update by id/ids
3073
- params = Object.assign({}, params, {
3074
- where: {
3075
- id
3076
- }
3103
+ });
3104
+ knex.TableBuilder.extend('userId', function (columnName) {
3105
+ return this.tableIdentity(columnName ?? 'userId');
3106
+ });
3107
+ knex.TableBuilder.extend('int0', function (columnName) {
3108
+ return this.integer(columnName).defaultTo(0);
3109
+ });
3110
+ knex.TableBuilder.extend('int1', function (columnName) {
3111
+ return this.integer(columnName).defaultTo(1);
3112
+ });
3113
+ ['description'].forEach(method => {
3114
+ knex.TableBuilder.extend(method, function (length = 255) {
3115
+ return this.string(method, length);
3077
3116
  });
3078
- const res = await this._increment(table, params, options);
3079
- // delete cache
3080
- await this.cacheEntityDel(id, table);
3081
- return res;
3082
- }
3083
- async aggregate(params, options, _modelJoins) {
3084
- const items = await this.__aggregate_raw(undefined, params, options);
3085
- return items[0];
3086
- }
3087
- async __aggregate_raw(table, params, options) {
3088
- // table
3089
- table = table || this.getTable(params?.where);
3090
- if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3091
- const items = await this.__select_cache(table, params, options);
3092
- return items;
3093
- }
3094
- async group(params, options, _modelJoins) {
3095
- return await this.__group_raw(undefined, params, options);
3096
- }
3097
- async __group_raw(table, params, options) {
3098
- // table
3099
- table = table || this.getTable(params?.where);
3100
- if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3101
- const items = await this.__select_cache(table, params, options);
3102
- return items;
3103
- }
3104
- async selectAndCount(params, options, modelJoins) {
3105
- // pageNo/pageSize
3106
- const pageSize = params?.limit ?? this.scopeOrm.config.rest.query.pageSize.default;
3107
- const pageNo = Math.floor((params?.offset ?? 0) / pageSize) + 1;
3108
- // count
3109
- const paramsCount = Object.assign({}, params, {
3110
- columns: undefined,
3111
- orders: undefined,
3112
- limit: undefined,
3113
- offset: undefined
3117
+ });
3118
+ ['content'].forEach(method => {
3119
+ knex.TableBuilder.extend(method, function (useText) {
3120
+ return useText ? this.text(method) : this.json(method);
3114
3121
  });
3115
- let count = await this.count(paramsCount, options, modelJoins);
3116
- if (!count) count = '0';
3117
- // list
3118
- let list;
3119
- if (count === '0') {
3120
- list = [];
3121
- } else {
3122
- list = await this.select(params, options, modelJoins);
3123
- }
3124
- // pageNo/pageSize/pageCount
3125
- const pageCount = Math.ceil(BigNumber(count).div(pageSize).toNumber());
3126
- // ok
3127
- return {
3128
- list,
3129
- total: count,
3130
- pageCount,
3131
- pageSize,
3132
- pageNo
3133
- };
3122
+ });
3123
+ }
3124
+
3125
+ function ExtendKnex(app) {
3126
+ ExtendSchemaBuilder(app);
3127
+ ExtendTableBuilder(app);
3128
+ }
3129
+
3130
+ const SymbolTransactionConsistency = Symbol('SymbolTransactionConsistency');
3131
+ class Main extends BeanSimple {
3132
+ async moduleLoading() {
3133
+ // config
3134
+ const _configDefault = await combineConfigDefault(this.app, configDefault, configDev, configProd, configTest);
3135
+ this.app.config.database = deepExtend({}, _configDefault, this.app.config.database);
3134
3136
  }
3135
- async select(params, options, _modelJoins) {
3136
- const relations = this.relations.handleRelationsCollection(params);
3137
- const [params2, refKeys] = this.relations.prepareColumnsByRelations(relations, params);
3138
- let items = await this.__select_raw(undefined, params2, options);
3139
- if (items.length === 0) return items;
3140
- items = await this.relations.handleRelationsMany(relations, items, params, options);
3141
- if (refKeys) {
3142
- for (const item of items) {
3143
- for (const refKey of refKeys) {
3144
- delete item[refKey];
3145
- }
3137
+ async moduleLoaded() {
3138
+ // ExtendKnex
3139
+ ExtendKnex(this.app);
3140
+ // db
3141
+ Object.defineProperty(this.app.context, 'db', {
3142
+ enumerable: false,
3143
+ get() {
3144
+ return this.app.bean._getBean(ServiceDatabaseAsyncLocalStorage$1).current;
3146
3145
  }
3147
- }
3148
- return items;
3149
- }
3150
- async __select_raw(table, params, options) {
3151
- // table
3152
- table = table || this.getTable(params?.where);
3153
- if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3154
- // check if cache
3155
- if (this._checkDisableCacheEntityByOptions(options)) {
3156
- return await this.__select_cache(table, params, options);
3157
- }
3158
- // 1: select id
3159
- const columnId = `${table}.id`;
3160
- const params2 = Object.assign({}, params, {
3161
- columns: [columnId]
3162
3146
  });
3163
- const items = await this.__select_cache(table, params2, options);
3164
- if (items.length === 0) {
3165
- // donothing
3166
- return [];
3167
- }
3168
- // 1: special check
3169
- if (params?.columns) {
3170
- const columnsTarget = Array.isArray(params?.columns) ? params?.columns : [params?.columns];
3171
- if (this.__checkIfOnlyKey(columnsTarget, table)) {
3172
- // just return
3173
- return items;
3147
+ // transactionConsistency
3148
+ Object.defineProperty(this.app.context, 'transactionConsistency', {
3149
+ enumerable: false,
3150
+ get() {
3151
+ if (!this[SymbolTransactionConsistency]) {
3152
+ this[SymbolTransactionConsistency] = this.app.bean._newBean(ServiceTransactionConsistency_);
3153
+ }
3154
+ return this[SymbolTransactionConsistency];
3174
3155
  }
3175
- }
3176
- // 2: mget
3177
- const ids = items.map(item => cast(item).id);
3178
- const options3 = params?.columns ? Object.assign({}, options, {
3179
- columns: params?.columns
3180
- }) : options;
3181
- return await this.__mget_raw(table, ids, options3);
3182
- }
3183
- async __select_cache(table, params, options) {
3184
- // check if cache
3185
- if (this._checkDisableCacheQueryByOptions(options)) {
3186
- return await super._select(table, params, options);
3187
- }
3188
- // builder
3189
- const builder = this._select_buildParams(table, params, options);
3190
- const sql = builder.toQuery();
3191
- const key = {
3192
- sql
3193
- };
3194
- // cache
3195
- const cache = this.cacheQuery.getInstance(table);
3196
- const items = await cache.get(key, {
3197
- ...options?.cache,
3198
- get: async () => {
3199
- return await super._select(table, params, options, builder);
3200
- },
3201
- db: this.db
3202
3156
  });
3203
- return items;
3204
- }
3205
- async get(where, options) {
3206
- const relations = this.relations.handleRelationsCollection(options);
3207
- const [options2, refKeys] = this.relations.prepareColumnsByRelations(relations, options);
3208
- let item = await this.__get_raw(undefined, where, options2);
3209
- if (!item) return item;
3210
- item = await this.relations.handleRelationsOne(relations, item, options, options);
3211
- if (refKeys) {
3212
- for (const refKey of refKeys) {
3213
- delete item[refKey];
3214
- }
3215
- }
3216
- return item;
3217
- }
3218
- async __get_raw(table, where, options) {
3219
- // table
3220
- table = table || this.getTable(where);
3221
- if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3222
- // check if cache
3223
- if (this._checkDisableCacheEntityByOptions(options)) {
3224
- return await super._get(table, where, options);
3225
- }
3226
- const id = this.__checkCacheKeyValid(where, table);
3227
- if (isNil(id)) {
3228
- // not key
3229
- if (this._checkDisableCacheQueryByOptions(options)) {
3230
- return await super._get(table, where, options);
3157
+ // commit
3158
+ Object.defineProperty(this.app.context, 'commit', {
3159
+ enumerable: false,
3160
+ get() {
3161
+ return function (cb) {
3162
+ if (this.ctxCaller) {
3163
+ this.ctxCaller.commit(cb);
3164
+ } else {
3165
+ cast(this).transactionConsistency.commit(cb);
3166
+ }
3167
+ };
3231
3168
  }
3232
- // by cache query
3233
- // params
3234
- const params = {
3235
- where
3236
- };
3237
- if (options?.columns) {
3238
- params.columns = options?.columns;
3169
+ });
3170
+ Object.defineProperty(this.app.context, 'commitsDone', {
3171
+ enumerable: false,
3172
+ get() {
3173
+ return function () {
3174
+ return cast(this).transactionConsistency.commitsDone();
3175
+ };
3239
3176
  }
3240
- // select
3241
- const options2 = deepExtend({}, options, {
3242
- columns: undefined
3243
- });
3244
- const items = await this.__select_raw(table, params, options2);
3245
- return items[0];
3177
+ });
3178
+ }
3179
+ async configLoaded(_config) {}
3180
+ }
3181
+ async function configDefault(_app) {
3182
+ return {};
3183
+ }
3184
+ async function configDev(_app) {
3185
+ return {};
3186
+ }
3187
+ async function configProd(_app) {
3188
+ return {};
3189
+ }
3190
+ async function configTest(_app) {
3191
+ return {};
3192
+ }
3193
+
3194
+ let ScopeModuleAOrm = class ScopeModuleAOrm extends BeanScopeBase {};
3195
+ ScopeModuleAOrm = __decorate([Scope(), BeanInfo({
3196
+ module: "a-orm"
3197
+ })], ScopeModuleAOrm);
3198
+ /** scope: end */
3199
+
3200
+ function DatabaseDialect(options) {
3201
+ return createBeanDecorator('databaseDialect', options);
3202
+ }
3203
+
3204
+ function DtoAggregate(modelLike, aggrs) {
3205
+ return _DtoAggregate_raw(modelLike, aggrs);
3206
+ }
3207
+ function _DtoAggregate_raw(modelLike, aggrs) {
3208
+ class TargetClass {}
3209
+ return _DtoAggregate_inner(TargetClass, modelLike, aggrs);
3210
+ }
3211
+ function _DtoAggregate_inner(classTarget, _modelLike, aggrs) {
3212
+ for (const key in aggrs) {
3213
+ const columns = ensureArray(aggrs[key]);
3214
+ if (!columns) continue;
3215
+ for (const column of columns) {
3216
+ const column2 = `${key}_${column === '*' ? 'all' : column}`;
3217
+ Api.field(v.optional(), z.string())(classTarget.prototype, column2);
3246
3218
  }
3247
- // key
3248
- return this.__filterGetColumns(await this.__get_key(id, table, where, options), options?.columns);
3249
3219
  }
3250
- async update(data, options) {
3251
- const ids = await this.__update_raw(undefined, data, options);
3252
- if (!ids || ids.length !== 1) return data;
3253
- // only support =1
3254
- const dataNew = [Object.assign({}, data, {
3255
- id: ids[0]
3256
- })];
3257
- const items = await this.relations.handleRelationsMutate(dataNew, dataNew, options, options);
3258
- return items[0];
3220
+ return classTarget;
3221
+ }
3222
+
3223
+ function DtoGroup(modelLike, groups, aggrs, columns) {
3224
+ return _DtoGroup_raw(modelLike, groups, aggrs, columns);
3225
+ }
3226
+ function _DtoGroup_raw(modelLike, groups, aggrs, columns) {
3227
+ class TargetClass {}
3228
+ // model
3229
+ const modelClass = prepareClassModel(modelLike);
3230
+ // entity
3231
+ const entityClass = getClassEntityFromClassModel(modelClass);
3232
+ // columns/groups
3233
+ const displays = ensureArray(columns ?? groups);
3234
+ if (displays) {
3235
+ PickClassInner(TargetClass, entityClass, displays);
3259
3236
  }
3260
- async updateBulk(items, options) {
3261
- await this.__updateBulk_raw(undefined, items, options);
3262
- return await this.relations.handleRelationsMutate(items, items, options, options);
3237
+ // aggrs
3238
+ if (aggrs) {
3239
+ _DtoAggregate_inner(TargetClass, modelLike, aggrs);
3263
3240
  }
3264
- async __updateBulk_raw(table, items, options) {
3265
- if (items.length === 0) return;
3266
- for (const item of items) {
3267
- await this.__update_raw(table, item, options);
3268
- }
3241
+ // ok
3242
+ return TargetClass;
3243
+ }
3244
+
3245
+ function DtoGet(modelLike, params) {
3246
+ return _DtoGet_raw(modelLike, params);
3247
+ }
3248
+ function _DtoGet_raw(modelLike, params) {
3249
+ // model
3250
+ const modelClass = prepareClassModel(modelLike);
3251
+ // entity
3252
+ let entityClass = getClassEntityFromClassModel(modelClass);
3253
+ // columns
3254
+ const columns = prepareColumns(params?.columns);
3255
+ // always create a new class, no matter if columns empty
3256
+ entityClass = $Class.pick(entityClass, columns);
3257
+ // relations
3258
+ _DtoGet_relations(modelClass, entityClass, params);
3259
+ return entityClass;
3260
+ }
3261
+ function _DtoGet_relations(modelClass, entityClass, includeWrapper, mutateTypeTopLevel) {
3262
+ // relations
3263
+ const relations = _DtoGet_relations_collection(modelClass, includeWrapper);
3264
+ if (!relations) return;
3265
+ for (const relation of relations) {
3266
+ _DtoGet_relation_handle(entityClass, relation, mutateTypeTopLevel);
3269
3267
  }
3270
- async __update_raw(table, data, options) {
3271
- // table
3272
- table = table || this.getTable(data);
3273
- if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3274
- // check if cache
3275
- if (this._checkDisableCacheEntityByOptions(options)) {
3276
- await super._update(table, data, options);
3268
+ }
3269
+ function _DtoGet_relation_handle(entityClass, relation, mutateTypeTopLevel) {
3270
+ const [relationName, relationReal, includeReal, withReal, autoload] = relation;
3271
+ const {
3272
+ type,
3273
+ model,
3274
+ options
3275
+ } = relationReal;
3276
+ const modelTarget = prepareClassModel(model);
3277
+ const optionsReal = Object.assign({}, options, {
3278
+ include: includeReal,
3279
+ with: withReal
3280
+ });
3281
+ if (mutateTypeTopLevel) {
3282
+ if (type === 'belongsTo') {
3283
+ // donot mutate
3277
3284
  return;
3278
3285
  }
3279
- // check where and get id
3280
- let id = this.__checkCacheKeyValid(data, table, true);
3281
- if (!options?.where) {
3282
- if (isNil(id)) {
3283
- throw new Error('id should be specified for update method');
3284
- }
3285
- if (Array.isArray(id) && id.length === 0) return;
3286
- const id2 = this.__checkCacheKeyValid(data, table, false);
3287
- if (!isNil(id2)) {
3288
- // donothing
3289
- return;
3290
- }
3286
+ let schema;
3287
+ if (type === 'belongsToMany') {
3288
+ schema = v.array(z.object({
3289
+ id: v.tableIdentity()(),
3290
+ deleted: z.boolean().optional()
3291
+ }));
3292
+ } else if (type === 'hasOne') {
3293
+ const schemaLazy = _DtoGet_relation_handle_schemaLazy(modelTarget, optionsReal, autoload, mutateTypeTopLevel, relation);
3294
+ schema = v.lazy(schemaRenderVisible(false), schemaLazy);
3295
+ // optional = true;
3291
3296
  } else {
3292
- const id2 = this.__checkCacheKeyValid(options?.where, table, false);
3293
- if (id2) {
3294
- id = id2;
3297
+ // hasMany
3298
+ const schemaLazy = _DtoGet_relation_handle_schemaLazy(modelTarget, optionsReal, autoload, mutateTypeTopLevel, relation);
3299
+ schema = v.array(v.lazy(schemaLazy));
3300
+ }
3301
+ Api.field(v.optional(), schema)(entityClass.prototype, relationName);
3302
+ } else {
3303
+ const schemaLazy = _DtoGet_relation_handle_schemaLazy(modelTarget, optionsReal, autoload, mutateTypeTopLevel, relation);
3304
+ let schema;
3305
+ let optional = false;
3306
+ if (type === 'hasOne' || type === 'belongsTo') {
3307
+ schema = v.lazy(schemaRenderVisible(false), schemaLazy);
3308
+ optional = true;
3309
+ } else {
3310
+ if (optionsReal.groups) {
3311
+ schema = v.array(v.lazy(schemaLazy));
3312
+ } else if (optionsReal.aggrs) {
3313
+ schema = v.lazy(schemaLazy);
3314
+ optional = true;
3295
3315
  } else {
3296
- const where = !isNil(id) ? Object.assign({}, options?.where, {
3297
- id
3298
- }) : options?.where;
3299
- const options2 = deepExtend({}, options, {
3300
- where: undefined
3301
- });
3302
- const items = await this.__select_raw(table, {
3303
- where,
3304
- columns: ['id']
3305
- }, options2);
3306
- if (items.length === 0) {
3307
- // donothing
3308
- return;
3309
- }
3310
- if (items.length === 1) {
3311
- id = cast(items[0]).id;
3312
- } else {
3313
- id = items.map(item => cast(item).id);
3314
- }
3315
- // update by id/ids
3316
- options = Object.assign({}, options, {
3317
- where: {
3318
- id
3319
- }
3320
- });
3316
+ schema = v.array(v.lazy(schemaLazy));
3321
3317
  }
3322
3318
  }
3323
- await super._update(table, data, options);
3324
- // delete cache
3325
- await this.cacheEntityDel(id, table);
3326
- // id
3327
- return Array.isArray(id) ? id : [id];
3328
- }
3329
- async delete(where, options) {
3330
- const ids = await this.__delete_raw(undefined, where, options);
3331
- if (!isNil(ids)) {
3332
- await this.relations.handleRelationsDelete(ids, options, options);
3319
+ if (optional) {
3320
+ Api.field(v.optional(), schema)(entityClass.prototype, relationName);
3321
+ } else {
3322
+ Api.field(schema)(entityClass.prototype, relationName);
3333
3323
  }
3334
3324
  }
3335
- async deleteBulk(ids, options) {
3336
- return await this.__deleteBulk_raw_with_relations(undefined, ids, options);
3337
- }
3338
- async __deleteBulk_raw_with_relations(table, ids, options) {
3339
- if (ids.length === 0) return;
3340
- await this.__delete_raw(table, {
3341
- id: ids
3342
- }, options);
3343
- await this.relations.handleRelationsDelete(ids, options, options);
3344
- }
3345
- async __delete_raw(table, where, options) {
3346
- // table
3347
- table = table || this.getTable(where);
3348
- if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3349
- // check if cache
3350
- if (this._checkDisableCacheEntityByOptions(options)) {
3351
- return await super._delete(table, where, options);
3325
+ }
3326
+ function _DtoGet_relation_handle_schemaLazy(modelTarget, optionsReal, autoload, mutateTypeTopLevel, relation) {
3327
+ return () => {
3328
+ if (!autoload) {
3329
+ return _DtoGet_relation_handle_schemaLazy_raw(modelTarget, optionsReal, mutateTypeTopLevel, relation);
3352
3330
  }
3353
- // id
3354
- let id = this.__checkCacheKeyValid(where, table);
3355
- if (isNil(id)) {
3356
- // check where and get id
3357
- const items = await this.__select_raw(table, {
3358
- where,
3359
- columns: ['id']
3360
- }, options);
3361
- if (items.length === 0) {
3362
- // donothing
3363
- return;
3364
- }
3365
- if (items.length === 1) {
3366
- id = cast(items[0]).id;
3331
+ // dynamic
3332
+ const entityClass = getClassEntityFromClassModel(modelTarget);
3333
+ const beanFullName = appResource.getBeanFullName(entityClass);
3334
+ const _hashkey = _DtoGet_relation_handle_schemaLazy_hashkey(optionsReal, mutateTypeTopLevel);
3335
+ const dynamicName = `${beanFullName}_${_hashkey}`;
3336
+ let entityTarget = getSchemaDynamic(dynamicName);
3337
+ if (!entityTarget) {
3338
+ entityTarget = _DtoGet_relation_handle_schemaLazy_raw(modelTarget, optionsReal, mutateTypeTopLevel, relation);
3339
+ entityTarget[SymbolSchemaDynamicRefId] = dynamicName;
3340
+ addSchemaDynamic(dynamicName, entityTarget);
3341
+ }
3342
+ return entityTarget;
3343
+ };
3344
+ }
3345
+ function _DtoGet_relation_handle_schemaLazy_raw(modelTarget, optionsReal, mutateTypeTopLevel, relation) {
3346
+ if (mutateTypeTopLevel) {
3347
+ return _DtoMutate_raw(modelTarget, optionsReal, mutateTypeTopLevel, undefined, false, relation); // columnsOmitDefault: undefined
3348
+ } else {
3349
+ if (optionsReal.groups) {
3350
+ return DtoGroup(modelTarget, optionsReal.groups, optionsReal.aggrs, optionsReal.columns);
3351
+ } else if (optionsReal.aggrs) {
3352
+ return DtoAggregate(modelTarget, optionsReal.aggrs);
3353
+ } else {
3354
+ return _DtoGet_raw(modelTarget, optionsReal);
3355
+ }
3356
+ }
3357
+ }
3358
+ function _DtoGet_relation_handle_schemaLazy_hashkey(optionsReal, mutateTypeTopLevel) {
3359
+ const columns = prepareColumns(optionsReal.columns);
3360
+ const aggrs = ensureArray(optionsReal.aggrs);
3361
+ const groups = ensureArray(optionsReal.groups);
3362
+ return columns || aggrs || groups || mutateTypeTopLevel ? hashkey({
3363
+ columns,
3364
+ aggrs,
3365
+ groups,
3366
+ mutate: mutateTypeTopLevel
3367
+ }) : 'none';
3368
+ }
3369
+ function _DtoGet_relations_collection(modelClass, includeWrapper) {
3370
+ const beanOptions = appResource.getBean(modelClass);
3371
+ const options = beanOptions?.options;
3372
+ return handleRelationsCollection(options?.relations, includeWrapper);
3373
+ }
3374
+
3375
+ function _DtoMutate_raw(modelLike, params, mutateTypeTopLevel, columnsOmitDefault, topLevel, relation) {
3376
+ // model
3377
+ const modelClass = prepareClassModel(modelLike);
3378
+ // entity
3379
+ let entityClass = getClassEntityFromClassModel(modelClass);
3380
+ // columns
3381
+ let columns = prepareColumns(params?.columns);
3382
+ if (columns) {
3383
+ if (!topLevel) {
3384
+ if (mutateTypeTopLevel === 'create') {
3385
+ for (const key of ['deleted', 'id']) {
3386
+ const index = columns.indexOf(key);
3387
+ if (index > -1) {
3388
+ columns = mutate(columns, copyState => {
3389
+ copyState.splice(index, 1);
3390
+ });
3391
+ }
3392
+ }
3367
3393
  } else {
3368
- id = items.map(item => cast(item).id);
3394
+ for (const key of ['deleted', 'id']) {
3395
+ if (!columns.includes(key)) {
3396
+ columns = mutate(columns, copyState => {
3397
+ copyState.unshift(key);
3398
+ });
3399
+ }
3400
+ }
3369
3401
  }
3370
3402
  }
3371
- if (Array.isArray(id) && id.length === 0) return;
3372
- // delete by id/ids
3373
- await super._delete(table, {
3374
- id
3375
- }, options);
3376
- // delete cache
3377
- await this.cacheEntityDel(id, table);
3378
- // id
3379
- return Array.isArray(id) ? id : [id];
3380
- }
3381
- async __get_key(id, table, where, options) {
3382
- // cache
3383
- const cache = this.cacheEntity.getInstance(table);
3384
- const item = await cache.get(id, {
3385
- get: async () => {
3386
- // where: maybe contain aux key
3387
- return await super._get(table, where, {
3388
- disableDeleted: true
3389
- });
3390
- },
3391
- db: this.db
3392
- });
3393
- if (!item || !this._checkIfEntityValidByDeleted(item, options)) return undefined;
3394
- return item;
3403
+ entityClass = $Class.pick(entityClass, columns);
3404
+ } else {
3405
+ const columns = columnsOmitDefault ?? (mutateTypeTopLevel === 'create' ? ['id', 'iid', 'deleted', 'createdAt', 'updatedAt'] : ['iid', 'createdAt', 'updatedAt']);
3406
+ entityClass = $Class.omit(entityClass, prepareColumns(columns));
3395
3407
  }
3396
- __filterMGetColumns(items, columns) {
3397
- if (items.length === 0 || !columns) return items;
3398
- return items.map(item => {
3399
- return this.__filterGetColumns(item, columns);
3400
- });
3408
+ if (!topLevel && mutateTypeTopLevel !== 'create') {
3409
+ entityClass = $Class.partial(entityClass, ['id', 'deleted']);
3401
3410
  }
3402
- __filterGetColumns(data, columns) {
3403
- if (!data || !columns) return data;
3404
- if (!Array.isArray(columns)) columns = cast(columns).split(',');
3405
- const data2 = {};
3406
- for (let column of cast(columns)) {
3407
- column = getTargetColumnName(column);
3408
- if (column === '*') return data;
3409
- if (data[column] !== undefined) {
3410
- data2[column] = data[column];
3411
- }
3411
+ if (!topLevel && relation) {
3412
+ const [_relationName, relationReal] = relation;
3413
+ const {
3414
+ type,
3415
+ key
3416
+ } = relationReal;
3417
+ if (type === 'hasOne' || type === 'hasMany') {
3418
+ entityClass = $Class.omit(entityClass, key);
3412
3419
  }
3413
- return data2;
3414
3420
  }
3415
- async cacheEntityDel(id, table) {
3416
- await this.cacheEntityDelInner(id, table);
3417
- this.db.commit(async () => {
3418
- await this.cacheEntityDelInner(id, table);
3419
- }, {
3420
- ignoreIfNotInTransaction: true
3421
+ // relations
3422
+ _DtoGet_relations(modelClass, entityClass, params, mutateTypeTopLevel);
3423
+ return entityClass;
3424
+ }
3425
+
3426
+ function DtoCreate(modelLike, params) {
3427
+ return _DtoMutate_raw(modelLike, params, 'create', ['id', 'iid', 'deleted', 'createdAt', 'updatedAt'], true, undefined);
3428
+ }
3429
+
3430
+ function DtoListAndCount(classRef) {
3431
+ class TargetClass {}
3432
+ Api.field(v.array(classRef))(TargetClass.prototype, 'list');
3433
+ Api.field(z.string())(TargetClass.prototype, 'total');
3434
+ Api.field(z.number())(TargetClass.prototype, 'pageCount');
3435
+ Api.field(z.number())(TargetClass.prototype, 'pageSize');
3436
+ Api.field(z.number())(TargetClass.prototype, 'pageNo');
3437
+ return TargetClass;
3438
+ }
3439
+
3440
+ function DtoQuery(classRef, keys) {
3441
+ return $Class.mixin(DtoQueryBase, $Class.partial($Class.pick(classRef, keys)));
3442
+ }
3443
+
3444
+ function DtoQueryPage(classRef, keys) {
3445
+ return $Class.mixin(DtoQueryPageBase, $Class.partial($Class.pick(classRef, keys)));
3446
+ }
3447
+
3448
+ function DtoSelectAndCount(modelLike, params) {
3449
+ const DtoGetResult = DtoGet(modelLike, params);
3450
+ return DtoListAndCount(DtoGetResult);
3451
+ }
3452
+
3453
+ function DtoUpdate(modelLike, params) {
3454
+ return _DtoMutate_raw(modelLike, params, 'update', ['id', 'iid', 'deleted', 'createdAt', 'updatedAt'], true, undefined);
3455
+ }
3456
+ // not use Partial/$Class.partial, for form render at frontend
3457
+
3458
+ const $Dto = {
3459
+ create: DtoCreate,
3460
+ update: DtoUpdate,
3461
+ get: DtoGet,
3462
+ aggregate: DtoAggregate,
3463
+ group: DtoGroup,
3464
+ query: DtoQuery,
3465
+ queryPage: DtoQueryPage,
3466
+ selectAndCount: DtoSelectAndCount,
3467
+ listAndCount: DtoListAndCount
3468
+ };
3469
+
3470
+ function Entity(table, options) {
3471
+ if (typeof table === 'string') {
3472
+ options = Object.assign({}, options, {
3473
+ table
3421
3474
  });
3422
- this._shardingCacheDoubleDelete({
3423
- beanFullName: this.$beanFullName,
3424
- clientName: this.db.clientName,
3425
- table,
3426
- method: 'cacheEntityDelInner',
3427
- args: [id, table]
3428
- });
3429
- }
3430
- async cacheEntityDelInner(id, table) {
3431
- await this.cacheEntity.del(id, table);
3432
- await this.cacheQueryClearInner(table);
3475
+ } else {
3476
+ options = table || {};
3433
3477
  }
3434
- async cacheEntityClear(table) {
3435
- await this.cacheEntityClearInner(table);
3436
- this.db.commit(async () => {
3437
- await this.cacheEntityClearInner(table);
3438
- }, {
3439
- ignoreIfNotInTransaction: true
3440
- });
3441
- this._shardingCacheDoubleDelete({
3442
- beanFullName: this.$beanFullName,
3443
- clientName: this.db.clientName,
3444
- table,
3445
- method: 'cacheEntityClearInner',
3446
- args: [table]
3447
- });
3478
+ // // tableName
3479
+ // const tableName = options.table;
3480
+ // if (__tableNames.has(tableName)) {
3481
+ // throw new Error(`entity table exists: ${tableName}`);
3482
+ // }
3483
+ // __tableNames.add(tableName);
3484
+ return createBeanDecorator('entity', options, false, target => {
3485
+ mergeDtoFieldsOpenapiMetadata(target);
3486
+ });
3487
+ }
3488
+
3489
+ function Model(options) {
3490
+ return createBeanDecorator('model', options);
3491
+ }
3492
+
3493
+ class BeanModelCrud extends BeanModelCrudInner {
3494
+ async mget(ids, options) {
3495
+ return await this._mget(undefined, ids, options);
3448
3496
  }
3449
- async cacheEntityClearInner(table) {
3450
- await this.cacheEntity.clear(table);
3451
- await this.cacheQueryClearInner(table);
3497
+ async select(params, options) {
3498
+ return await this._select(undefined, params, options);
3452
3499
  }
3453
- async cacheQueryClear(table) {
3454
- await this.cacheQueryClearInner(table);
3455
- this.db.commit(async () => {
3456
- await this.cacheQueryClearInner(table);
3457
- }, {
3458
- ignoreIfNotInTransaction: true
3459
- });
3460
- this._shardingCacheDoubleDelete({
3461
- beanFullName: this.$beanFullName,
3462
- clientName: this.db.clientName,
3463
- table,
3464
- method: 'cacheQueryClearInner',
3465
- args: [table]
3466
- });
3500
+ async get(where, options) {
3501
+ return await this._get(undefined, where, options);
3467
3502
  }
3468
- async cacheQueryClearInner(table) {
3469
- await this.cacheQuery.clear(table);
3470
- await this._cacheQueryClearModelsClear();
3503
+ async count(params, options) {
3504
+ return await this._count(undefined, params, options);
3471
3505
  }
3472
- _shardingCacheDoubleDelete(jobData) {
3473
- const doubleDelete = this.scopeOrm.config.sharding.cache.doubleDelete;
3474
- if (!doubleDelete) return;
3475
- this.db.commit(() => {
3476
- this.scopeOrm.queue.doubleDelete.push(jobData);
3477
- });
3506
+ async insert(data, options) {
3507
+ return await this._insertBulk(undefined, data, options);
3478
3508
  }
3479
- async _cacheQueryClearModelsClear() {
3480
- const modelsClear = this._getModelsClear();
3481
- if (!modelsClear || modelsClear.length === 0) return;
3482
- for (const modelClear of modelsClear) {
3483
- const modelTarget = this.newInstanceTarget(modelClear);
3484
- const modelsClearedByFn = modelTarget.options.cache?.modelsClearedByFn;
3485
- if (modelsClearedByFn) {
3486
- await modelsClearedByFn(this.ctx, modelTarget, this);
3487
- } else {
3488
- await modelTarget.cacheQueryClearInner();
3489
- }
3490
- }
3509
+ async insertBulk(data, options) {
3510
+ return await this._insertBulk(undefined, data, options);
3491
3511
  }
3492
- _getModelsClear(modelName) {
3493
- const modelsClearAll = getCacheModelsClear(this.app);
3494
- return modelsClearAll[modelName ?? this.$onionName];
3512
+ async update(data, options) {
3513
+ return await this._update(undefined, data, options);
3495
3514
  }
3496
- _checkDisableCacheQueryByOptions(options) {
3497
- if (options?.disableCacheQuery === true || options?.disableCacheQuery === false) {
3498
- return options?.disableCacheQuery;
3499
- }
3500
- return !(options?.cache?.enable ?? this.cacheQuery.enabled);
3515
+ async delete(where, options) {
3516
+ return await this._delete(undefined, where, options);
3501
3517
  }
3502
- _checkDisableCacheEntityByOptions(options) {
3503
- if (options?.disableCacheEntity === true || options?.disableCacheEntity === false) {
3504
- return options?.disableCacheEntity;
3505
- }
3506
- return !(options?.cache?.enable ?? this.cacheEntity.enabled);
3518
+ }
3519
+
3520
+ class BeanModelCache extends BeanModelCrud {
3521
+ constructor(...args) {
3522
+ super(...args);
3523
+ this.cacheQuery = void 0;
3524
+ this.cacheEntity = void 0;
3525
+ this.relations = void 0;
3507
3526
  }
3508
- __checkIfOnlyKey(keys, table, noCheckLength) {
3509
- const columnId = `${table}.id`;
3510
- if (!noCheckLength) {
3511
- const keysAux = this.cacheEntity.keysAux;
3512
- if (keysAux) {
3513
- const keysAux2 = Array.isArray(keysAux) ? keysAux : [keysAux];
3514
- keys = keys.filter(item => !keysAux2.includes(String(item)));
3515
- }
3516
- if (keys.length !== 1) return false;
3517
- if (keys[0] === 'id') return 'id';
3518
- if (keys[0] === columnId) return columnId;
3519
- return false;
3520
- } else {
3521
- if (keys.includes('id')) return 'id';
3522
- if (keys.includes(columnId)) return columnId;
3523
- return false;
3524
- }
3527
+ __init__(clientName, table) {
3528
+ super.__init__(clientName, table);
3529
+ this.cacheQuery = this.bean._newBean(ServiceCacheQuery, this);
3530
+ this.cacheEntity = this.bean._newBean(ServiceCacheEntity, this);
3531
+ this.relations = this.bean._newBean(ServiceRelations, this);
3525
3532
  }
3526
- __checkCacheKeyValid(where, table, noCheckLength) {
3527
- if (!where) return undefined;
3528
- const columnId = this.__checkIfOnlyKey(Object.keys(where), table, noCheckLength);
3529
- if (!columnId) return undefined;
3530
- return ['number', 'string', 'bigint', 'array'].includes(typeof where[columnId]) ? where[columnId] : undefined;
3533
+ async __dispose__() {
3534
+ await disposeInstance(this.cacheQuery);
3535
+ await disposeInstance(this.cacheEntity);
3531
3536
  }
3532
- __get__(prop) {
3533
- if (prop.startsWith('getBy')) {
3534
- const [fieldName, op] = __parseMagicField(prop.substring('getBy'.length));
3535
- if (!fieldName) throw new Error(`invalid magic method: ${prop}`);
3536
- return (fieldValue, options) => {
3537
- const where = __combineMagicWhere(fieldName, op, fieldValue);
3538
- return this.get(where, options);
3539
- };
3540
- } else if (prop.startsWith('selectBy')) {
3541
- const [fieldName, op] = __parseMagicField(prop.substring('selectBy'.length));
3542
- if (!fieldName) throw new Error(`invalid magic method: ${prop}`);
3543
- return (fieldValue, params, options, modelJoins) => {
3544
- const where = __combineMagicWhere(fieldName, op, fieldValue);
3545
- const params2 = params ? deepExtend({}, params, {
3546
- where
3547
- }) : {
3548
- where
3549
- };
3550
- return this.select(params2, options, modelJoins);
3551
- };
3552
- } else if (prop.startsWith('updateBy')) {
3553
- const [fieldName, op] = __parseMagicField(prop.substring('updateBy'.length));
3554
- if (!fieldName) throw new Error(`invalid magic method: ${prop}`);
3555
- return (fieldValue, data, options) => {
3556
- const where = __combineMagicWhere(fieldName, op, fieldValue);
3557
- if (fieldName === 'id') {
3558
- data = Object.assign({}, data, where);
3559
- } else {
3560
- options = deepExtend({}, options, {
3561
- where
3562
- });
3563
- }
3564
- return this.update(data, options);
3565
- };
3566
- } else if (prop.startsWith('deleteBy')) {
3567
- const [fieldName, op] = __parseMagicField(prop.substring('deleteBy'.length));
3568
- if (!fieldName) throw new Error(`invalid magic method: ${prop}`);
3569
- return (fieldValue, options) => {
3570
- const where = __combineMagicWhere(fieldName, op, fieldValue);
3571
- return this.delete(where, options);
3572
- };
3573
- }
3537
+ async insert(data, options) {
3538
+ if (!data) data = {};
3539
+ const items = await this.insertBulk([data], options);
3540
+ return items[0];
3574
3541
  }
3575
- }
3576
- function __combineMagicWhere(fieldName, op, fieldValue) {
3577
- return {
3578
- [fieldName]: fieldValue === undefined ? undefined : op === 'eq' ? fieldValue : {
3579
- [`_${op}_`]: fieldValue
3580
- }
3581
- };
3582
- }
3583
- function __parseMagicField(str) {
3584
- const fieldName = parseFirstWord(str, true);
3585
- if (!fieldName) return [fieldName, undefined];
3586
- const op = toLowerCaseFirstChar(str.substring(fieldName.length)) || 'eq';
3587
- return [fieldName, op];
3588
- }
3589
-
3590
- let BeanModelBase = class BeanModelBase extends BeanModelCache {};
3591
- BeanModelBase = __decorate([Bean(), Virtual(), BeanInfo({
3592
- module: "a-orm"
3593
- })], BeanModelBase);
3594
-
3595
- const SymbolModuleScope$1 = Symbol('SymbolModuleScope');
3596
- let ServiceEntityResolver = class ServiceEntityResolver extends BeanBase {
3597
- constructor(moduleScope) {
3598
- super();
3599
- this[SymbolModuleScope$1] = void 0;
3600
- this.__instances = {};
3601
- this[SymbolModuleScope$1] = moduleScope;
3542
+ async insertBulk(items, options) {
3543
+ const itemsResult = await this.__insertBulk_raw(undefined, items, options);
3544
+ const itemsNew = items.map((item, index) => {
3545
+ return Object.assign({}, item, {
3546
+ id: cast(itemsResult[index]).id
3547
+ });
3548
+ });
3549
+ return await this.relations.handleRelationsMutate(itemsResult, itemsNew, options, options);
3602
3550
  }
3603
- __get__(prop) {
3604
- if (!this.__instances[prop]) {
3605
- const beanFullName = `${this[SymbolModuleScope$1]}.entity.${prop}`;
3606
- const beanOptions = appResource.getBean(beanFullName);
3607
- this.__instances[prop] = $columnsAll(beanOptions.beanClass, true, true);
3608
- }
3609
- return this.__instances[prop];
3551
+ async __insertBulk_raw(table, items, options) {
3552
+ if (items.length === 0) return [];
3553
+ // table
3554
+ table = table || this.getTable(items[0]);
3555
+ if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3556
+ // insert
3557
+ const res = await this._insertBulk(table, items, options);
3558
+ // delete cache
3559
+ const ids = res.map(item => cast(item).id);
3560
+ await this.cacheEntityDel(ids, table);
3561
+ return res;
3610
3562
  }
3611
- };
3612
- ServiceEntityResolver = __decorate([Service(), __metadata("design:paramtypes", [String]), BeanInfo({
3613
- module: "a-orm"
3614
- })], ServiceEntityResolver);
3615
-
3616
- const SymbolModuleScope = Symbol('SymbolModuleScope');
3617
- let ServiceModelResolver = class ServiceModelResolver extends BeanBase {
3618
- constructor(moduleScope) {
3619
- super();
3620
- this[SymbolModuleScope] = void 0;
3621
- this[SymbolModuleScope] = moduleScope;
3563
+ async mutate(data, options) {
3564
+ if (!data) data = {};
3565
+ const items = await this.mutateBulk([data], options);
3566
+ return items[0];
3622
3567
  }
3623
- __get__(prop) {
3624
- const beanFullName = `${this[SymbolModuleScope]}.model.${prop}`;
3625
- return this.bean._getBean(beanFullName);
3568
+ async mutateBulk(items, options) {
3569
+ return await this.__mutateBulk_raw(undefined, items, options);
3626
3570
  }
3627
- };
3628
- ServiceModelResolver = __decorate([Service(), __metadata("design:paramtypes", [String]), BeanInfo({
3629
- module: "a-orm"
3630
- })], ServiceModelResolver);
3631
-
3632
- let BroadcastColumnsClear = class BroadcastColumnsClear extends BeanBroadcastBase {
3633
- async execute(data, isEmitter) {
3634
- const {
3635
- clientName,
3636
- tableName
3637
- } = data;
3638
- if (!isEmitter) {
3639
- await cast(this.scope.service.database).columnsClearWorker(clientName, tableName);
3571
+ async __mutateBulk_raw(table, items, options) {
3572
+ // table
3573
+ table = table || this.getTable(items[0]);
3574
+ if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3575
+ // check
3576
+ const indexesInsert = [];
3577
+ const indexesUpdate = [];
3578
+ const itemsInsert = [];
3579
+ const itemsUpdate = [];
3580
+ const itemsDelete = [];
3581
+ for (let index = 0; index < items.length; index++) {
3582
+ const item = items[index];
3583
+ if (cast(item).deleted) {
3584
+ if (!isNil(cast(item).id)) {
3585
+ itemsDelete.push(item);
3586
+ }
3587
+ } else if (!isNil(cast(item).id)) {
3588
+ itemsUpdate.push(item);
3589
+ indexesUpdate.push(index);
3590
+ } else {
3591
+ itemsInsert.push(item);
3592
+ indexesInsert.push(index);
3593
+ }
3594
+ }
3595
+ // insert/update
3596
+ const itemsInsertNew = await this.__insertBulk_raw(table, itemsInsert, options);
3597
+ await this.__updateBulk_raw(table, itemsUpdate, options);
3598
+ const itemsMutate = itemsInsert.map((item, index) => {
3599
+ return Object.assign({}, item, {
3600
+ id: cast(itemsInsertNew[index]).id
3601
+ });
3602
+ }).concat(itemsUpdate);
3603
+ let itemsMutateResult = itemsInsertNew.concat(itemsUpdate);
3604
+ const indexesMutate = indexesInsert.concat(indexesUpdate);
3605
+ itemsMutateResult = await this.relations.handleRelationsMutate(itemsMutateResult, itemsMutate, options, options);
3606
+ let result = [];
3607
+ for (let index = 0; index < indexesMutate.length; index++) {
3608
+ result[indexesMutate[index]] = itemsMutateResult[index];
3640
3609
  }
3610
+ result = result.filter(item => !!item); // fitler deleted items
3611
+ // delete
3612
+ const idsDelete = itemsDelete.map(item => cast(item).id);
3613
+ await this.__deleteBulk_raw_with_relations(table, idsDelete, options);
3614
+ // ok
3615
+ return result;
3641
3616
  }
3642
- };
3643
- BroadcastColumnsClear = __decorate([Broadcast(), BeanInfo({
3644
- module: "a-orm"
3645
- })], BroadcastColumnsClear);
3646
-
3647
- let EventClientNameReal = class EventClientNameReal extends BeanEventBase {};
3648
- EventClientNameReal = __decorate([Event(), BeanInfo({
3649
- module: "a-orm"
3650
- })], EventClientNameReal);
3651
-
3652
- let EventColumnsClear = class EventColumnsClear extends BeanEventBase {};
3653
- EventColumnsClear = __decorate([Event(), BeanInfo({
3654
- module: "a-orm"
3655
- })], EventColumnsClear);
3656
-
3657
- let HmrEntity = class HmrEntity extends BeanBase {
3658
- async reload(_beanOptions) {
3659
- this.app.bean.worker.reload();
3617
+ async mget(ids, options) {
3618
+ if (ids.length === 0) return [];
3619
+ const relations = this.relations.handleRelationsCollection(options);
3620
+ const [options2, refKeys] = this.relations.prepareColumnsByRelations(relations, options);
3621
+ let items = await this.__mget_raw(undefined, ids, options2);
3622
+ if (items.length === 0) return items;
3623
+ items = await this.relations.handleRelationsMany(relations, items, options, options);
3624
+ if (refKeys) {
3625
+ for (const item of items) {
3626
+ for (const refKey of refKeys) {
3627
+ delete item[refKey];
3628
+ }
3629
+ }
3630
+ }
3631
+ return items;
3660
3632
  }
3661
- };
3662
- HmrEntity = __decorate([Hmr(), BeanInfo({
3663
- module: "a-orm"
3664
- })], HmrEntity);
3665
-
3666
- // import { clearAllCacheModelsClear, clearCacheModelCacheInstance } from '../lib/const.ts';
3667
- let HmrModel = class HmrModel extends BeanBase {
3668
- async reload(_beanOptions) {
3669
- // more deps: dto/model
3670
- this.app.bean.worker.reload();
3671
- // clearAllCacheModelsClear(this.app);
3672
- // await clearCacheModelCacheInstance(this.app, beanOptions.beanFullName);
3633
+ async __mget_raw(table, ids, options) {
3634
+ // table
3635
+ table = table || this.getTable(undefined);
3636
+ if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3637
+ // check if cache
3638
+ if (this._checkDisableCacheEntityByOptions(options)) {
3639
+ return await super._mget(table, ids, options);
3640
+ }
3641
+ // cache
3642
+ const cache = this.cacheEntity.getInstance(table);
3643
+ let items = await cache.mget(ids, {
3644
+ mget: async ids => {
3645
+ return await super._mget_original(table, ids, {
3646
+ disableDeleted: true
3647
+ });
3648
+ },
3649
+ db: this.db
3650
+ });
3651
+ // filter disableDeleted
3652
+ items = items.filter(item => {
3653
+ if (!item) return false;
3654
+ if (!this._checkIfEntityValidByDeleted(item, options)) return false;
3655
+ return true;
3656
+ });
3657
+ return this.__filterMGetColumns(items, options?.columns);
3673
3658
  }
3674
- };
3675
- HmrModel = __decorate([Hmr(), BeanInfo({
3676
- module: "a-orm"
3677
- })], HmrModel);
3678
-
3679
- let QueueDoubleDelete = class QueueDoubleDelete extends BeanQueueBase {
3680
- async execute(data, _options) {
3681
- const beanInstance = this.app.bean._newBean(data.beanFullName, data.clientName, data.table);
3682
- await beanInstance[data.method](...data.args);
3659
+ async count(params, options, _modelJoins) {
3660
+ const column = params?.column ?? '*';
3661
+ const params2 = Object.assign({}, params, {
3662
+ aggrs: {
3663
+ count: column
3664
+ },
3665
+ column: undefined
3666
+ });
3667
+ const item = await this.aggregate(params2, options);
3668
+ return this.extractFirstValue(item);
3683
3669
  }
3684
- };
3685
- QueueDoubleDelete = __decorate([Queue({
3686
- options: {
3687
- job: {
3688
- delay: 3 * 1000
3689
- }
3670
+ async increment(params, options, _modelJoins) {
3671
+ return await this.__increment_raw(undefined, params, options);
3690
3672
  }
3691
- }), BeanInfo({
3692
- module: "a-orm"
3693
- })], QueueDoubleDelete);
3694
-
3695
- let ScheduleSoftDeletionPrune = class ScheduleSoftDeletionPrune extends BeanBase {
3696
- async execute() {
3697
- const onionSlices = this.bean.onion.model.getOnionsEnabledCached();
3698
- for (const onionSlice of onionSlices) {
3699
- if (onionSlice.beanOptions.options?.disableDeleted) continue;
3700
- let softDeletionPrune = onionSlice.beanOptions.options?.softDeletionPrune ?? this.scope.config.softDeletionPrune.enable;
3701
- if (!softDeletionPrune) continue;
3702
- if (softDeletionPrune === true) softDeletionPrune = {};
3703
- await this._modulePrune(onionSlice, softDeletionPrune);
3673
+ async decrement(params, options, _modelJoins) {
3674
+ const columns = {};
3675
+ for (const key in params.columns) {
3676
+ columns[key] = -params.columns[key];
3704
3677
  }
3678
+ const params2 = Object.assign({}, params, {
3679
+ columns
3680
+ });
3681
+ return await this.__increment_raw(undefined, params2, options);
3705
3682
  }
3706
- async _modulePrune(onionSlice, softDeletionPrune) {
3707
- const handler = softDeletionPrune.handler;
3708
- const expired = softDeletionPrune.expired ?? this.scope.config.softDeletionPrune.expired;
3709
- const modelTarget = this.bean._getBean(onionSlice.beanOptions.beanFullName);
3710
- if (handler) {
3711
- await handler(this.ctx, modelTarget, {
3712
- expired
3713
- });
3683
+ async __increment_raw(table, params, options) {
3684
+ // table
3685
+ table = table || this.getTable(params?.where);
3686
+ if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3687
+ // check if cache
3688
+ if (this._checkDisableCacheEntityByOptions(options)) {
3689
+ return await super._increment(table, params, options);
3690
+ }
3691
+ const where = params?.where;
3692
+ const items = await this.__select_raw(table, {
3693
+ where,
3694
+ columns: ['id']
3695
+ }, options);
3696
+ if (items.length === 0) {
3697
+ // donothing
3698
+ return 0;
3699
+ }
3700
+ let id;
3701
+ if (items.length === 1) {
3702
+ id = cast(items[0]).id;
3714
3703
  } else {
3715
- const expiredTime = new Date(Date.now() - expired);
3716
- await modelTarget.delete({
3717
- deleted: true,
3718
- updatedAt: {
3719
- _lt_: expiredTime
3720
- }
3721
- }, {
3722
- disableDeleted: true
3723
- });
3704
+ id = items.map(item => cast(item).id);
3724
3705
  }
3706
+ // update by id/ids
3707
+ params = Object.assign({}, params, {
3708
+ where: {
3709
+ id
3710
+ }
3711
+ });
3712
+ const res = await this._increment(table, params, options);
3713
+ // delete cache
3714
+ await this.cacheEntityDel(id, table);
3715
+ return res;
3725
3716
  }
3726
- };
3727
- ScheduleSoftDeletionPrune = __decorate([Schedule({
3728
- repeat: {
3729
- every: 24 * 3600 * 1000
3717
+ async aggregate(params, options, _modelJoins) {
3718
+ const items = await this.__aggregate_raw(undefined, params, options);
3719
+ return items[0];
3730
3720
  }
3731
- }), BeanInfo({
3732
- module: "a-orm"
3733
- })], ScheduleSoftDeletionPrune);
3734
-
3735
- function config(_app) {
3736
- return {
3737
- sharding: {
3738
- cache: {
3739
- doubleDelete: true
3740
- }
3741
- },
3742
- rest: {
3743
- query: {
3744
- pageSize: {
3745
- default: 20,
3746
- max: 100
3747
- },
3748
- orders: {
3749
- default: 'createdAt,desc'
3750
- }
3751
- }
3752
- },
3753
- table: {
3754
- identityType: 'bigint'
3755
- },
3756
- model: {
3757
- disableDeleted: false,
3758
- disableInstance: false,
3759
- disableCreateTime: false,
3760
- disableUpdateTime: false
3761
- },
3762
- softDeletionPrune: {
3763
- enable: true,
3764
- expired: 14 * 24 * 3600 * 1000
3765
- },
3766
- dialects: {
3767
- 'better-sqlite3': 'a-ormdialect:betterSqlite3',
3768
- 'mysql': 'a-ormdialect:mysql',
3769
- 'mysql2': 'a-ormdialect:mysql3',
3770
- 'pg': 'a-ormdialect:pg'
3771
- },
3772
- summer: {
3773
- enable: true,
3774
- meta: {},
3775
- presetDefault: 'redis',
3776
- preset: {
3777
- redis: configRedis,
3778
- all: configAll
3779
- },
3780
- redis: {
3781
- client: 'model'
3721
+ async __aggregate_raw(table, params, options) {
3722
+ // table
3723
+ table = table || this.getTable(params?.where);
3724
+ if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3725
+ const items = await this.__select_cache(table, params, options);
3726
+ return items;
3727
+ }
3728
+ async group(params, options, _modelJoins) {
3729
+ return await this.__group_raw(undefined, params, options);
3730
+ }
3731
+ async __group_raw(table, params, options) {
3732
+ // table
3733
+ table = table || this.getTable(params?.where);
3734
+ if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3735
+ const items = await this.__select_cache(table, params, options);
3736
+ return items;
3737
+ }
3738
+ async selectAndCount(params, options, modelJoins) {
3739
+ // pageNo/pageSize
3740
+ const pageSize = params?.limit ?? this.scopeOrm.config.rest.query.pageSize.default;
3741
+ const pageNo = Math.floor((params?.offset ?? 0) / pageSize) + 1;
3742
+ // count
3743
+ const paramsCount = Object.assign({}, params, {
3744
+ columns: undefined,
3745
+ orders: undefined,
3746
+ limit: undefined,
3747
+ offset: undefined
3748
+ });
3749
+ let count = await this.count(paramsCount, options, modelJoins);
3750
+ if (!count) count = '0';
3751
+ // list
3752
+ let list;
3753
+ if (count === '0') {
3754
+ list = [];
3755
+ } else {
3756
+ list = await this.select(params, options, modelJoins);
3757
+ }
3758
+ // pageNo/pageSize/pageCount
3759
+ const pageCount = Math.ceil(BigNumber(count).div(pageSize).toNumber());
3760
+ // ok
3761
+ return {
3762
+ list,
3763
+ total: count,
3764
+ pageCount,
3765
+ pageSize,
3766
+ pageNo
3767
+ };
3768
+ }
3769
+ async select(params, options, _modelJoins) {
3770
+ const relations = this.relations.handleRelationsCollection(params);
3771
+ const [params2, refKeys] = this.relations.prepareColumnsByRelations(relations, params);
3772
+ let items = await this.__select_raw(undefined, params2, options);
3773
+ if (items.length === 0) return items;
3774
+ items = await this.relations.handleRelationsMany(relations, items, params, options);
3775
+ if (refKeys) {
3776
+ for (const item of items) {
3777
+ for (const refKey of refKeys) {
3778
+ delete item[refKey];
3779
+ }
3782
3780
  }
3783
- },
3784
- logger: {
3785
- maxLength: 256
3786
3781
  }
3787
- };
3788
- }
3789
-
3790
- const errors = {
3791
- ShouldSpecifyTable: 1001
3792
- };
3793
-
3794
- function ExtendSchemaBuilder(app) {
3795
- ['fetchDatabases', 'createDatabase', 'dropDatabase', 'fetchIndexes'].forEach(method => {
3796
- knex.SchemaBuilder.extend(method, async function (...args) {
3797
- const client = cast(cast(this).client).config.client;
3798
- const dialect = app.bean.database.getDialect(client);
3799
- return await dialect[method](this, ...args);
3782
+ return items;
3783
+ }
3784
+ async __select_raw(table, params, options) {
3785
+ // table
3786
+ table = table || this.getTable(params?.where);
3787
+ if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3788
+ // check if cache
3789
+ if (this._checkDisableCacheEntityByOptions(options)) {
3790
+ return await this.__select_cache(table, params, options);
3791
+ }
3792
+ // 1: select id
3793
+ const columnId = `${table}.id`;
3794
+ const params2 = Object.assign({}, params, {
3795
+ columns: [columnId]
3800
3796
  });
3801
- });
3802
- }
3803
-
3804
- const __ThisModule__ = 'a-orm';
3805
-
3806
- function ExtendTableBuilder(app) {
3807
- const scope = app.scope(__ThisModule__);
3808
- function _basicFields(options, identityType) {
3809
- options = options || {};
3810
- if (options.id !== false) {
3811
- const _identityType = identityType ?? scope.config.table.identityType;
3812
- if (_identityType === 'bigint') {
3813
- this.bigIncrements();
3814
- } else if (_identityType === 'number') {
3815
- this.increments();
3816
- } else {
3817
- throw new Error('Should create column id by yourself');
3797
+ const items = await this.__select_cache(table, params2, options);
3798
+ if (items.length === 0) {
3799
+ // donothing
3800
+ return [];
3801
+ }
3802
+ // 1: special check
3803
+ if (params?.columns) {
3804
+ const columnsTarget = Array.isArray(params?.columns) ? params?.columns : [params?.columns];
3805
+ if (this.__checkIfOnlyKey(columnsTarget, table)) {
3806
+ // just return
3807
+ return items;
3818
3808
  }
3819
3809
  }
3820
- if (options.timestamps !== false) this.timestamps(true, true, true);
3821
- if (options.deleted !== false) this.boolean('deleted').defaultTo(false);
3822
- if (options.iid !== false) this.integer('iid').defaultTo(0);
3823
- return this;
3810
+ // 2: mget
3811
+ const ids = items.map(item => cast(item).id);
3812
+ const options3 = params?.columns ? Object.assign({}, options, {
3813
+ columns: params?.columns
3814
+ }) : options;
3815
+ return await this.__mget_raw(table, ids, options3);
3824
3816
  }
3825
- knex.TableBuilder.extend('basicFields', function (options) {
3826
- _basicFields.call(this, options, undefined);
3827
- return this;
3828
- });
3829
- knex.TableBuilder.extend('basicFieldsSimple', function (options) {
3830
- _basicFields.call(this, options, 'number');
3831
- return this;
3832
- });
3833
- knex.TableBuilder.extend('tableIdentity', function (columnName) {
3834
- const _identityType = scope.config.table.identityType;
3835
- if (_identityType === 'bigint') {
3836
- return this.bigInteger(columnName); // default value is null
3837
- } else if (_identityType === 'number') {
3838
- return this.integer(columnName); // default value is null
3839
- } else {
3840
- throw new Error(`Should create column ${columnName} by yourself`);
3817
+ async __select_cache(table, params, options) {
3818
+ // check if cache
3819
+ if (this._checkDisableCacheQueryByOptions(options)) {
3820
+ return await super._select(table, params, options);
3841
3821
  }
3842
- });
3843
- knex.TableBuilder.extend('userId', function (columnName) {
3844
- return this.tableIdentity(columnName ?? 'userId');
3845
- });
3846
- knex.TableBuilder.extend('int0', function (columnName) {
3847
- return this.integer(columnName).defaultTo(0);
3848
- });
3849
- knex.TableBuilder.extend('int1', function (columnName) {
3850
- return this.integer(columnName).defaultTo(1);
3851
- });
3852
- ['description'].forEach(method => {
3853
- knex.TableBuilder.extend(method, function (length = 255) {
3854
- return this.string(method, length);
3855
- });
3856
- });
3857
- ['content'].forEach(method => {
3858
- knex.TableBuilder.extend(method, function (useText) {
3859
- return useText ? this.text(method) : this.json(method);
3822
+ // builder
3823
+ const builder = this._select_buildParams(table, params, options);
3824
+ const sql = builder.toQuery();
3825
+ const key = {
3826
+ sql
3827
+ };
3828
+ // cache
3829
+ const cache = this.cacheQuery.getInstance(table);
3830
+ const items = await cache.get(key, {
3831
+ ...options?.cache,
3832
+ get: async () => {
3833
+ return await super._select(table, params, options, builder);
3834
+ },
3835
+ db: this.db
3860
3836
  });
3861
- });
3862
- }
3863
-
3864
- function ExtendKnex(app) {
3865
- ExtendSchemaBuilder(app);
3866
- ExtendTableBuilder(app);
3867
- }
3868
-
3869
- const SymbolTransactionConsistency = Symbol('SymbolTransactionConsistency');
3870
- class Main extends BeanSimple {
3871
- async moduleLoading() {
3872
- // config
3873
- const _configDefault = await combineConfigDefault(this.app, configDefault, configDev, configProd, configTest);
3874
- this.app.config.database = deepExtend({}, _configDefault, this.app.config.database);
3837
+ return items;
3838
+ }
3839
+ async get(where, options) {
3840
+ const relations = this.relations.handleRelationsCollection(options);
3841
+ const [options2, refKeys] = this.relations.prepareColumnsByRelations(relations, options);
3842
+ let item = await this.__get_raw(undefined, where, options2);
3843
+ if (!item) return item;
3844
+ item = await this.relations.handleRelationsOne(relations, item, options, options);
3845
+ if (refKeys) {
3846
+ for (const refKey of refKeys) {
3847
+ delete item[refKey];
3848
+ }
3849
+ }
3850
+ return item;
3851
+ }
3852
+ async __get_raw(table, where, options) {
3853
+ // table
3854
+ table = table || this.getTable(where);
3855
+ if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3856
+ // check if cache
3857
+ if (this._checkDisableCacheEntityByOptions(options)) {
3858
+ return await super._get(table, where, options);
3859
+ }
3860
+ const id = this.__checkCacheKeyValid(where, table);
3861
+ if (isNil(id)) {
3862
+ // not key
3863
+ if (this._checkDisableCacheQueryByOptions(options)) {
3864
+ return await super._get(table, where, options);
3865
+ }
3866
+ // by cache query
3867
+ // params
3868
+ const params = {
3869
+ where
3870
+ };
3871
+ if (options?.columns) {
3872
+ params.columns = options?.columns;
3873
+ }
3874
+ // select
3875
+ const options2 = deepExtend({}, options, {
3876
+ columns: undefined
3877
+ });
3878
+ const items = await this.__select_raw(table, params, options2);
3879
+ return items[0];
3880
+ }
3881
+ // key
3882
+ return this.__filterGetColumns(await this.__get_key(id, table, where, options), options?.columns);
3883
+ }
3884
+ async update(data, options) {
3885
+ const ids = await this.__update_raw(undefined, data, options);
3886
+ if (!ids || ids.length !== 1) return data;
3887
+ // only support =1
3888
+ const dataNew = [Object.assign({}, data, {
3889
+ id: ids[0]
3890
+ })];
3891
+ const items = await this.relations.handleRelationsMutate(dataNew, dataNew, options, options);
3892
+ return items[0];
3893
+ }
3894
+ async updateBulk(items, options) {
3895
+ await this.__updateBulk_raw(undefined, items, options);
3896
+ return await this.relations.handleRelationsMutate(items, items, options, options);
3897
+ }
3898
+ async __updateBulk_raw(table, items, options) {
3899
+ if (items.length === 0) return;
3900
+ for (const item of items) {
3901
+ await this.__update_raw(table, item, options);
3902
+ }
3903
+ }
3904
+ async __update_raw(table, data, options) {
3905
+ // table
3906
+ table = table || this.getTable(data);
3907
+ if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3908
+ // check if cache
3909
+ if (this._checkDisableCacheEntityByOptions(options)) {
3910
+ await super._update(table, data, options);
3911
+ return;
3912
+ }
3913
+ // check where and get id
3914
+ let id = this.__checkCacheKeyValid(data, table, true);
3915
+ if (!options?.where) {
3916
+ if (isNil(id)) {
3917
+ throw new Error('id should be specified for update method');
3918
+ }
3919
+ if (Array.isArray(id) && id.length === 0) return;
3920
+ const id2 = this.__checkCacheKeyValid(data, table, false);
3921
+ if (!isNil(id2)) {
3922
+ // donothing
3923
+ return;
3924
+ }
3925
+ } else {
3926
+ const id2 = this.__checkCacheKeyValid(options?.where, table, false);
3927
+ if (id2) {
3928
+ id = id2;
3929
+ } else {
3930
+ const where = !isNil(id) ? Object.assign({}, options?.where, {
3931
+ id
3932
+ }) : options?.where;
3933
+ const options2 = deepExtend({}, options, {
3934
+ where: undefined
3935
+ });
3936
+ const items = await this.__select_raw(table, {
3937
+ where,
3938
+ columns: ['id']
3939
+ }, options2);
3940
+ if (items.length === 0) {
3941
+ // donothing
3942
+ return;
3943
+ }
3944
+ if (items.length === 1) {
3945
+ id = cast(items[0]).id;
3946
+ } else {
3947
+ id = items.map(item => cast(item).id);
3948
+ }
3949
+ // update by id/ids
3950
+ options = Object.assign({}, options, {
3951
+ where: {
3952
+ id
3953
+ }
3954
+ });
3955
+ }
3956
+ }
3957
+ await super._update(table, data, options);
3958
+ // delete cache
3959
+ await this.cacheEntityDel(id, table);
3960
+ // id
3961
+ return Array.isArray(id) ? id : [id];
3962
+ }
3963
+ async delete(where, options) {
3964
+ const ids = await this.__delete_raw(undefined, where, options);
3965
+ if (!isNil(ids)) {
3966
+ await this.relations.handleRelationsDelete(ids, options, options);
3967
+ }
3968
+ }
3969
+ async deleteBulk(ids, options) {
3970
+ return await this.__deleteBulk_raw_with_relations(undefined, ids, options);
3971
+ }
3972
+ async __deleteBulk_raw_with_relations(table, ids, options) {
3973
+ if (ids.length === 0) return;
3974
+ await this.__delete_raw(table, {
3975
+ id: ids
3976
+ }, options);
3977
+ await this.relations.handleRelationsDelete(ids, options, options);
3978
+ }
3979
+ async __delete_raw(table, where, options) {
3980
+ // table
3981
+ table = table || this.getTable(where);
3982
+ if (!table) return this.scopeOrm.error.ShouldSpecifyTable.throw();
3983
+ // check if cache
3984
+ if (this._checkDisableCacheEntityByOptions(options)) {
3985
+ return await super._delete(table, where, options);
3986
+ }
3987
+ // id
3988
+ let id = this.__checkCacheKeyValid(where, table);
3989
+ if (isNil(id)) {
3990
+ // check where and get id
3991
+ const items = await this.__select_raw(table, {
3992
+ where,
3993
+ columns: ['id']
3994
+ }, options);
3995
+ if (items.length === 0) {
3996
+ // donothing
3997
+ return;
3998
+ }
3999
+ if (items.length === 1) {
4000
+ id = cast(items[0]).id;
4001
+ } else {
4002
+ id = items.map(item => cast(item).id);
4003
+ }
4004
+ }
4005
+ if (Array.isArray(id) && id.length === 0) return;
4006
+ // delete by id/ids
4007
+ await super._delete(table, {
4008
+ id
4009
+ }, options);
4010
+ // delete cache
4011
+ await this.cacheEntityDel(id, table);
4012
+ // id
4013
+ return Array.isArray(id) ? id : [id];
3875
4014
  }
3876
- async moduleLoaded() {
3877
- // ExtendKnex
3878
- ExtendKnex(this.app);
3879
- // db
3880
- Object.defineProperty(this.app.context, 'db', {
3881
- enumerable: false,
3882
- get() {
3883
- return this.app.bean._getBean(ServiceDatabaseAsyncLocalStorage$1).current;
3884
- }
4015
+ async __get_key(id, table, where, options) {
4016
+ // cache
4017
+ const cache = this.cacheEntity.getInstance(table);
4018
+ const item = await cache.get(id, {
4019
+ get: async () => {
4020
+ // where: maybe contain aux key
4021
+ return await super._get(table, where, {
4022
+ disableDeleted: true
4023
+ });
4024
+ },
4025
+ db: this.db
3885
4026
  });
3886
- // transactionConsistency
3887
- Object.defineProperty(this.app.context, 'transactionConsistency', {
3888
- enumerable: false,
3889
- get() {
3890
- if (!this[SymbolTransactionConsistency]) {
3891
- this[SymbolTransactionConsistency] = this.app.bean._newBean(ServiceTransactionConsistency_);
3892
- }
3893
- return this[SymbolTransactionConsistency];
3894
- }
4027
+ if (!item || !this._checkIfEntityValidByDeleted(item, options)) return undefined;
4028
+ return item;
4029
+ }
4030
+ __filterMGetColumns(items, columns) {
4031
+ if (items.length === 0 || !columns) return items;
4032
+ return items.map(item => {
4033
+ return this.__filterGetColumns(item, columns);
3895
4034
  });
3896
- // commit
3897
- Object.defineProperty(this.app.context, 'commit', {
3898
- enumerable: false,
3899
- get() {
3900
- return function (cb) {
3901
- if (this.ctxCaller) {
3902
- this.ctxCaller.commit(cb);
3903
- } else {
3904
- cast(this).transactionConsistency.commit(cb);
3905
- }
3906
- };
4035
+ }
4036
+ __filterGetColumns(data, columns) {
4037
+ if (!data || !columns) return data;
4038
+ if (!Array.isArray(columns)) columns = cast(columns).split(',');
4039
+ const data2 = {};
4040
+ for (let column of cast(columns)) {
4041
+ column = getTargetColumnName(column);
4042
+ if (column === '*') return data;
4043
+ if (data[column] !== undefined) {
4044
+ data2[column] = data[column];
3907
4045
  }
4046
+ }
4047
+ return data2;
4048
+ }
4049
+ async cacheEntityDel(id, table) {
4050
+ await this.cacheEntityDelInner(id, table);
4051
+ this.db.commit(async () => {
4052
+ await this.cacheEntityDelInner(id, table);
4053
+ }, {
4054
+ ignoreIfNotInTransaction: true
3908
4055
  });
3909
- Object.defineProperty(this.app.context, 'commitsDone', {
3910
- enumerable: false,
3911
- get() {
3912
- return function () {
3913
- return cast(this).transactionConsistency.commitsDone();
3914
- };
3915
- }
4056
+ this._shardingCacheDoubleDelete({
4057
+ beanFullName: this.$beanFullName,
4058
+ clientName: this.db.clientName,
4059
+ table,
4060
+ method: 'cacheEntityDelInner',
4061
+ args: [id, table]
3916
4062
  });
3917
4063
  }
3918
- async configLoaded(_config) {}
3919
- }
3920
- async function configDefault(_app) {
3921
- return {};
3922
- }
3923
- async function configDev(_app) {
3924
- return {};
3925
- }
3926
- async function configProd(_app) {
3927
- return {};
3928
- }
3929
- async function configTest(_app) {
3930
- return {};
3931
- }
3932
-
3933
- let ScopeModuleAOrm = class ScopeModuleAOrm extends BeanScopeBase {};
3934
- ScopeModuleAOrm = __decorate([Scope(), BeanInfo({
3935
- module: "a-orm"
3936
- })], ScopeModuleAOrm);
3937
- /** scope: end */
3938
-
3939
- function DatabaseDialect(options) {
3940
- return createBeanDecorator('databaseDialect', options);
3941
- }
3942
-
3943
- function DtoAggregate(modelLike, aggrs) {
3944
- return _DtoAggregate_raw(modelLike, aggrs);
3945
- }
3946
- function _DtoAggregate_raw(modelLike, aggrs) {
3947
- class TargetClass {}
3948
- return _DtoAggregate_inner(TargetClass, modelLike, aggrs);
3949
- }
3950
- function _DtoAggregate_inner(classTarget, _modelLike, aggrs) {
3951
- for (const key in aggrs) {
3952
- const columns = ensureArray(aggrs[key]);
3953
- if (!columns) continue;
3954
- for (const column of columns) {
3955
- const column2 = `${key}_${column === '*' ? 'all' : column}`;
3956
- Api.field(v.optional(), z.string())(classTarget.prototype, column2);
3957
- }
4064
+ async cacheEntityDelInner(id, table) {
4065
+ await this.cacheEntity.del(id, table);
4066
+ await this.cacheQueryClearInner(table);
3958
4067
  }
3959
- return classTarget;
3960
- }
3961
-
3962
- function DtoGroup(modelLike, groups, aggrs, columns) {
3963
- return _DtoGroup_raw(modelLike, groups, aggrs, columns);
3964
- }
3965
- function _DtoGroup_raw(modelLike, groups, aggrs, columns) {
3966
- class TargetClass {}
3967
- // model
3968
- const modelClass = prepareClassModel(modelLike);
3969
- // entity
3970
- const entityClass = getClassEntityFromClassModel(modelClass);
3971
- // columns/groups
3972
- const displays = ensureArray(columns ?? groups);
3973
- if (displays) {
3974
- PickClassInner(TargetClass, entityClass, displays);
4068
+ async cacheEntityClear(table) {
4069
+ await this.cacheEntityClearInner(table);
4070
+ this.db.commit(async () => {
4071
+ await this.cacheEntityClearInner(table);
4072
+ }, {
4073
+ ignoreIfNotInTransaction: true
4074
+ });
4075
+ this._shardingCacheDoubleDelete({
4076
+ beanFullName: this.$beanFullName,
4077
+ clientName: this.db.clientName,
4078
+ table,
4079
+ method: 'cacheEntityClearInner',
4080
+ args: [table]
4081
+ });
3975
4082
  }
3976
- // aggrs
3977
- if (aggrs) {
3978
- _DtoAggregate_inner(TargetClass, modelLike, aggrs);
4083
+ async cacheEntityClearInner(table) {
4084
+ await this.cacheEntity.clear(table);
4085
+ await this.cacheQueryClearInner(table);
3979
4086
  }
3980
- // ok
3981
- return TargetClass;
3982
- }
3983
-
3984
- function DtoGet(modelLike, params) {
3985
- return _DtoGet_raw(modelLike, params);
3986
- }
3987
- function _DtoGet_raw(modelLike, params) {
3988
- // model
3989
- const modelClass = prepareClassModel(modelLike);
3990
- // entity
3991
- let entityClass = getClassEntityFromClassModel(modelClass);
3992
- // columns
3993
- const columns = prepareColumns(params?.columns);
3994
- // always create a new class, no matter if columns empty
3995
- entityClass = $Class.pick(entityClass, columns);
3996
- // relations
3997
- _DtoGet_relations(modelClass, entityClass, params);
3998
- return entityClass;
3999
- }
4000
- function _DtoGet_relations(modelClass, entityClass, includeWrapper, mutateTypeTopLevel) {
4001
- // relations
4002
- const relations = _DtoGet_relations_collection(modelClass, includeWrapper);
4003
- if (!relations) return;
4004
- for (const relation of relations) {
4005
- _DtoGet_relation_handle(entityClass, relation, mutateTypeTopLevel);
4087
+ async cacheQueryClear(table) {
4088
+ await this.cacheQueryClearInner(table);
4089
+ this.db.commit(async () => {
4090
+ await this.cacheQueryClearInner(table);
4091
+ }, {
4092
+ ignoreIfNotInTransaction: true
4093
+ });
4094
+ this._shardingCacheDoubleDelete({
4095
+ beanFullName: this.$beanFullName,
4096
+ clientName: this.db.clientName,
4097
+ table,
4098
+ method: 'cacheQueryClearInner',
4099
+ args: [table]
4100
+ });
4006
4101
  }
4007
- }
4008
- function _DtoGet_relation_handle(entityClass, relation, mutateTypeTopLevel) {
4009
- const [relationName, relationReal, includeReal, withReal, autoload] = relation;
4010
- const {
4011
- type,
4012
- model,
4013
- options
4014
- } = relationReal;
4015
- const modelTarget = prepareClassModel(model);
4016
- const optionsReal = Object.assign({}, options, {
4017
- include: includeReal,
4018
- with: withReal
4019
- });
4020
- if (mutateTypeTopLevel) {
4021
- if (type === 'belongsTo') {
4022
- // donot mutate
4023
- return;
4024
- }
4025
- let schema;
4026
- if (type === 'belongsToMany') {
4027
- schema = v.array(z.object({
4028
- id: v.tableIdentity()(),
4029
- deleted: z.boolean().optional()
4030
- }));
4031
- } else if (type === 'hasOne') {
4032
- const schemaLazy = _DtoGet_relation_handle_schemaLazy(modelTarget, optionsReal, autoload, mutateTypeTopLevel, relation);
4033
- schema = v.lazy(schemaRenderVisible(false), schemaLazy);
4034
- // optional = true;
4035
- } else {
4036
- // hasMany
4037
- const schemaLazy = _DtoGet_relation_handle_schemaLazy(modelTarget, optionsReal, autoload, mutateTypeTopLevel, relation);
4038
- schema = v.array(v.lazy(schemaLazy));
4039
- }
4040
- Api.field(v.optional(), schema)(entityClass.prototype, relationName);
4041
- } else {
4042
- const schemaLazy = _DtoGet_relation_handle_schemaLazy(modelTarget, optionsReal, autoload, mutateTypeTopLevel, relation);
4043
- let schema;
4044
- let optional = false;
4045
- if (type === 'hasOne' || type === 'belongsTo') {
4046
- schema = v.lazy(schemaRenderVisible(false), schemaLazy);
4047
- optional = true;
4048
- } else {
4049
- if (optionsReal.groups) {
4050
- schema = v.array(v.lazy(schemaLazy));
4051
- } else if (optionsReal.aggrs) {
4052
- schema = v.lazy(schemaLazy);
4053
- optional = true;
4102
+ async cacheQueryClearInner(table) {
4103
+ await this.cacheQuery.clear(table);
4104
+ await this._cacheQueryClearModelsClear();
4105
+ }
4106
+ _shardingCacheDoubleDelete(jobData) {
4107
+ const doubleDelete = this.scopeOrm.config.sharding.cache.doubleDelete;
4108
+ if (!doubleDelete) return;
4109
+ this.db.commit(() => {
4110
+ this.scopeOrm.queue.doubleDelete.push(jobData);
4111
+ });
4112
+ }
4113
+ async _cacheQueryClearModelsClear() {
4114
+ const modelsClear = this._getModelsClear();
4115
+ if (!modelsClear || modelsClear.length === 0) return;
4116
+ for (const modelClear of modelsClear) {
4117
+ const modelTarget = this.newInstanceTarget(modelClear);
4118
+ const modelsClearedByFn = modelTarget.options.cache?.modelsClearedByFn;
4119
+ if (modelsClearedByFn) {
4120
+ await modelsClearedByFn(this.ctx, modelTarget, this);
4054
4121
  } else {
4055
- schema = v.array(v.lazy(schemaLazy));
4122
+ await modelTarget.cacheQueryClearInner();
4056
4123
  }
4057
4124
  }
4058
- if (optional) {
4059
- Api.field(v.optional(), schema)(entityClass.prototype, relationName);
4060
- } else {
4061
- Api.field(schema)(entityClass.prototype, relationName);
4062
- }
4063
4125
  }
4064
- }
4065
- function _DtoGet_relation_handle_schemaLazy(modelTarget, optionsReal, autoload, mutateTypeTopLevel, relation) {
4066
- return () => {
4067
- if (!autoload) {
4068
- return _DtoGet_relation_handle_schemaLazy_raw(modelTarget, optionsReal, mutateTypeTopLevel, relation);
4069
- }
4070
- // dynamic
4071
- const entityClass = getClassEntityFromClassModel(modelTarget);
4072
- const beanFullName = appResource.getBeanFullName(entityClass);
4073
- const _hashkey = _DtoGet_relation_handle_schemaLazy_hashkey(optionsReal, mutateTypeTopLevel);
4074
- const dynamicName = `${beanFullName}_${_hashkey}`;
4075
- let entityTarget = getSchemaDynamic(dynamicName);
4076
- if (!entityTarget) {
4077
- entityTarget = _DtoGet_relation_handle_schemaLazy_raw(modelTarget, optionsReal, mutateTypeTopLevel, relation);
4078
- entityTarget[SymbolSchemaDynamicRefId] = dynamicName;
4079
- addSchemaDynamic(dynamicName, entityTarget);
4126
+ _getModelsClear(modelName) {
4127
+ const modelsClearAll = getCacheModelsClear(this.app);
4128
+ return modelsClearAll[modelName ?? this.$onionName];
4129
+ }
4130
+ _checkDisableCacheQueryByOptions(options) {
4131
+ if (options?.disableCacheQuery === true || options?.disableCacheQuery === false) {
4132
+ return options?.disableCacheQuery;
4080
4133
  }
4081
- return entityTarget;
4082
- };
4083
- }
4084
- function _DtoGet_relation_handle_schemaLazy_raw(modelTarget, optionsReal, mutateTypeTopLevel, relation) {
4085
- if (mutateTypeTopLevel) {
4086
- return _DtoMutate_raw(modelTarget, optionsReal, mutateTypeTopLevel, undefined, false, relation); // columnsOmitDefault: undefined
4087
- } else {
4088
- if (optionsReal.groups) {
4089
- return DtoGroup(modelTarget, optionsReal.groups, optionsReal.aggrs, optionsReal.columns);
4090
- } else if (optionsReal.aggrs) {
4091
- return DtoAggregate(modelTarget, optionsReal.aggrs);
4092
- } else {
4093
- return _DtoGet_raw(modelTarget, optionsReal);
4134
+ return !(options?.cache?.enable ?? this.cacheQuery.enabled);
4135
+ }
4136
+ _checkDisableCacheEntityByOptions(options) {
4137
+ if (options?.disableCacheEntity === true || options?.disableCacheEntity === false) {
4138
+ return options?.disableCacheEntity;
4094
4139
  }
4140
+ return !(options?.cache?.enable ?? this.cacheEntity.enabled);
4095
4141
  }
4096
- }
4097
- function _DtoGet_relation_handle_schemaLazy_hashkey(optionsReal, mutateTypeTopLevel) {
4098
- const columns = prepareColumns(optionsReal.columns);
4099
- const aggrs = ensureArray(optionsReal.aggrs);
4100
- const groups = ensureArray(optionsReal.groups);
4101
- return columns || aggrs || groups || mutateTypeTopLevel ? hashkey({
4102
- columns,
4103
- aggrs,
4104
- groups,
4105
- mutate: mutateTypeTopLevel
4106
- }) : 'none';
4107
- }
4108
- function _DtoGet_relations_collection(modelClass, includeWrapper) {
4109
- const beanOptions = appResource.getBean(modelClass);
4110
- const options = beanOptions?.options;
4111
- return handleRelationsCollection(options?.relations, includeWrapper);
4112
- }
4113
-
4114
- function _DtoMutate_raw(modelLike, params, mutateTypeTopLevel, columnsOmitDefault, topLevel, relation) {
4115
- // model
4116
- const modelClass = prepareClassModel(modelLike);
4117
- // entity
4118
- let entityClass = getClassEntityFromClassModel(modelClass);
4119
- // columns
4120
- let columns = prepareColumns(params?.columns);
4121
- if (columns) {
4122
- if (!topLevel) {
4123
- if (mutateTypeTopLevel === 'create') {
4124
- for (const key of ['deleted', 'id']) {
4125
- const index = columns.indexOf(key);
4126
- if (index > -1) {
4127
- columns = mutate(columns, copyState => {
4128
- copyState.splice(index, 1);
4129
- });
4130
- }
4131
- }
4132
- } else {
4133
- for (const key of ['deleted', 'id']) {
4134
- if (!columns.includes(key)) {
4135
- columns = mutate(columns, copyState => {
4136
- copyState.unshift(key);
4137
- });
4138
- }
4139
- }
4142
+ __checkIfOnlyKey(keys, table, noCheckLength) {
4143
+ const columnId = `${table}.id`;
4144
+ if (!noCheckLength) {
4145
+ const keysAux = this.cacheEntity.keysAux;
4146
+ if (keysAux) {
4147
+ const keysAux2 = Array.isArray(keysAux) ? keysAux : [keysAux];
4148
+ keys = keys.filter(item => !keysAux2.includes(String(item)));
4140
4149
  }
4150
+ if (keys.length !== 1) return false;
4151
+ if (keys[0] === 'id') return 'id';
4152
+ if (keys[0] === columnId) return columnId;
4153
+ return false;
4154
+ } else {
4155
+ if (keys.includes('id')) return 'id';
4156
+ if (keys.includes(columnId)) return columnId;
4157
+ return false;
4141
4158
  }
4142
- entityClass = $Class.pick(entityClass, columns);
4143
- } else {
4144
- const columns = columnsOmitDefault ?? (mutateTypeTopLevel === 'create' ? ['id', 'iid', 'deleted', 'createdAt', 'updatedAt'] : ['iid', 'createdAt', 'updatedAt']);
4145
- entityClass = $Class.omit(entityClass, prepareColumns(columns));
4146
4159
  }
4147
- if (!topLevel && mutateTypeTopLevel !== 'create') {
4148
- entityClass = $Class.partial(entityClass, ['id', 'deleted']);
4160
+ __checkCacheKeyValid(where, table, noCheckLength) {
4161
+ if (!where) return undefined;
4162
+ const columnId = this.__checkIfOnlyKey(Object.keys(where), table, noCheckLength);
4163
+ if (!columnId) return undefined;
4164
+ return ['number', 'string', 'bigint', 'array'].includes(typeof where[columnId]) ? where[columnId] : undefined;
4149
4165
  }
4150
- if (!topLevel && relation) {
4151
- const [_relationName, relationReal] = relation;
4152
- const {
4153
- type,
4154
- key
4155
- } = relationReal;
4156
- if (type === 'hasOne' || type === 'hasMany') {
4157
- entityClass = $Class.omit(entityClass, key);
4166
+ __get__(prop) {
4167
+ if (prop.startsWith('getBy')) {
4168
+ const [fieldName, op] = __parseMagicField(prop.substring('getBy'.length));
4169
+ if (!fieldName) throw new Error(`invalid magic method: ${prop}`);
4170
+ return (fieldValue, options) => {
4171
+ const where = __combineMagicWhere(fieldName, op, fieldValue);
4172
+ return this.get(where, options);
4173
+ };
4174
+ } else if (prop.startsWith('selectBy')) {
4175
+ const [fieldName, op] = __parseMagicField(prop.substring('selectBy'.length));
4176
+ if (!fieldName) throw new Error(`invalid magic method: ${prop}`);
4177
+ return (fieldValue, params, options, modelJoins) => {
4178
+ const where = __combineMagicWhere(fieldName, op, fieldValue);
4179
+ const params2 = params ? deepExtend({}, params, {
4180
+ where
4181
+ }) : {
4182
+ where
4183
+ };
4184
+ return this.select(params2, options, modelJoins);
4185
+ };
4186
+ } else if (prop.startsWith('updateBy')) {
4187
+ const [fieldName, op] = __parseMagicField(prop.substring('updateBy'.length));
4188
+ if (!fieldName) throw new Error(`invalid magic method: ${prop}`);
4189
+ return (fieldValue, data, options) => {
4190
+ const where = __combineMagicWhere(fieldName, op, fieldValue);
4191
+ if (fieldName === 'id' && where.id !== null) {
4192
+ data = Object.assign({}, data, where);
4193
+ } else {
4194
+ options = deepExtend({}, options, {
4195
+ where
4196
+ });
4197
+ }
4198
+ return this.update(data, options);
4199
+ };
4200
+ } else if (prop.startsWith('deleteBy')) {
4201
+ const [fieldName, op] = __parseMagicField(prop.substring('deleteBy'.length));
4202
+ if (!fieldName) throw new Error(`invalid magic method: ${prop}`);
4203
+ return (fieldValue, options) => {
4204
+ const where = __combineMagicWhere(fieldName, op, fieldValue);
4205
+ return this.delete(where, options);
4206
+ };
4158
4207
  }
4159
4208
  }
4160
- // relations
4161
- _DtoGet_relations(modelClass, entityClass, params, mutateTypeTopLevel);
4162
- return entityClass;
4163
- }
4164
-
4165
- function DtoCreate(modelLike, params) {
4166
- return _DtoMutate_raw(modelLike, params, 'create', ['id', 'iid', 'deleted', 'createdAt', 'updatedAt'], true, undefined);
4167
- }
4168
-
4169
- function DtoListAndCount(classRef) {
4170
- class TargetClass {}
4171
- Api.field(v.array(classRef))(TargetClass.prototype, 'list');
4172
- Api.field(z.string())(TargetClass.prototype, 'total');
4173
- Api.field(z.number())(TargetClass.prototype, 'pageCount');
4174
- Api.field(z.number())(TargetClass.prototype, 'pageSize');
4175
- Api.field(z.number())(TargetClass.prototype, 'pageNo');
4176
- return TargetClass;
4177
- }
4178
-
4179
- function DtoQuery(classRef, keys) {
4180
- return $Class.mixin(DtoQueryBase, $Class.partial($Class.pick(classRef, keys)));
4181
- }
4182
-
4183
- function DtoQueryPage(classRef, keys) {
4184
- return $Class.mixin(DtoQueryPageBase, $Class.partial($Class.pick(classRef, keys)));
4185
- }
4186
-
4187
- function DtoSelectAndCount(modelLike, params) {
4188
- const DtoGetResult = DtoGet(modelLike, params);
4189
- return DtoListAndCount(DtoGetResult);
4190
- }
4191
-
4192
- function DtoUpdate(modelLike, params) {
4193
- return _DtoMutate_raw(modelLike, params, 'update', ['id', 'iid', 'deleted', 'createdAt', 'updatedAt'], true, undefined);
4194
4209
  }
4195
- // not use Partial/$Class.partial, for form render at frontend
4196
-
4197
- const $Dto = {
4198
- create: DtoCreate,
4199
- update: DtoUpdate,
4200
- get: DtoGet,
4201
- aggregate: DtoAggregate,
4202
- group: DtoGroup,
4203
- query: DtoQuery,
4204
- queryPage: DtoQueryPage,
4205
- selectAndCount: DtoSelectAndCount,
4206
- listAndCount: DtoListAndCount
4207
- };
4208
-
4209
- function Entity(table, options) {
4210
- if (typeof table === 'string') {
4211
- options = Object.assign({}, options, {
4212
- table
4213
- });
4214
- } else {
4215
- options = table || {};
4210
+ function __combineMagicWhere(fieldName, op, fieldValue) {
4211
+ if (fieldValue === undefined) {
4212
+ if (op === 'eq') {
4213
+ return {
4214
+ [fieldName]: null
4215
+ };
4216
+ }
4217
+ throw new Error(`should specify the value for magic method: ${fieldName}/${op}`);
4216
4218
  }
4217
- // // tableName
4218
- // const tableName = options.table;
4219
- // if (__tableNames.has(tableName)) {
4220
- // throw new Error(`entity table exists: ${tableName}`);
4221
- // }
4222
- // __tableNames.add(tableName);
4223
- return createBeanDecorator('entity', options, false, target => {
4224
- mergeDtoFieldsOpenapiMetadata(target);
4225
- });
4219
+ return {
4220
+ [fieldName]: op === 'eq' ? fieldValue : {
4221
+ [`_${op}_`]: fieldValue
4222
+ }
4223
+ };
4226
4224
  }
4227
-
4228
- function Model(options) {
4229
- return createBeanDecorator('model', options);
4225
+ function __parseMagicField(str) {
4226
+ const fieldName = parseFirstWord(str, true);
4227
+ if (!fieldName) return [fieldName, undefined];
4228
+ const op = toLowerCaseFirstChar(str.substring(fieldName.length)) || 'eq';
4229
+ return [fieldName, op];
4230
4230
  }
4231
4231
 
4232
+ class BeanModelBase extends BeanModelCache {}
4233
+
4232
4234
  function hasOne$2(classModel, key, options) {
4233
4235
  // : IModelRelationHasOne<MODEL, AUTOLOAD, COLUMNS> {
4234
4236
  return {
@@ -4407,5 +4409,5 @@ const $relationMutate = {
4407
4409
  belongsToMany
4408
4410
  };
4409
4411
 
4410
- export { $Dto, $locale, $relation, $relationDynamic, $relationMutate, AopMethodTransaction, BeanDatabase, BeanDatabaseDialectBase, BeanModel, BeanModelBase, BeanModelMeta, BroadcastColumnsClear, DatabaseDialect, DtoQueryBase, DtoQueryPageBase, Entity, EntityBase, EntityBaseEmpty, EntityBaseInner, EntityBaseSimple, EventClientNameReal, EventColumnsClear, ExtendKnex, ExtendSchemaBuilder, ExtendTableBuilder, HmrEntity, HmrModel, Main, Model, Op, OpAggrs, OpJoint, OpJointValues, OpNormal, OpNormalValues, OpValues, QueueDoubleDelete, ScheduleSoftDeletionPrune, ScopeModuleAOrm, ServiceCacheEntity, ServiceCacheQuery, ServiceColumns, ServiceColumnsCache, ServiceDatabase, ServiceDatabaseAsyncLocalStorage, ServiceDatabaseClient, ServiceDb, ServiceEntityResolver, ServiceModelResolver, ServiceRelations, ServiceTransaction, ServiceTransactionAsyncLocalStorage, ServiceTransactionConsistency‌, ServiceTransactionFiber, ServiceTransactionState, SymbolCacheModelCacheInstances, SymbolCacheModelsClear, SymbolKeyEntity, SymbolKeyEntityMeta, SymbolKeyFieldsMore, SymbolKeyModelOptions, TransactionIsolationLevelsMap, buildWhere, clearAllCacheModelsClear, clearCacheModelCacheInstance, config, configDefault, errors, getCacheModelCacheInstances, getCacheModelsClear, getClassEntityFromClassModel, getTableOrTableAlias, getTargetColumnName, isRaw, isRef, locales, prepareClassModel, prepareColumns };
4412
+ export { $Dto, $locale, $relation, $relationDynamic, $relationMutate, AopMethodTransaction, BeanDatabase, BeanModel, BeanModelBase, BeanModelMeta, BroadcastColumnsClear, DatabaseDialect, DtoQueryBase, DtoQueryPageBase, Entity, EntityBase, EntityBaseEmpty, EntityBaseInner, EntityBaseSimple, EventClientNameReal, EventColumnsClear, ExtendKnex, ExtendSchemaBuilder, ExtendTableBuilder, HmrEntity, HmrModel, Main, Model, Op, OpAggrs, OpJoint, OpJointValues, OpNormal, OpNormalValues, OpValues, QueueDoubleDelete, ScheduleSoftDeletionPrune, ScopeModuleAOrm, ServiceCacheEntity, ServiceCacheQuery, ServiceColumns, ServiceColumnsCache, ServiceDatabase, ServiceDatabaseAsyncLocalStorage, ServiceDatabaseClient, ServiceDatabaseDialectBase, ServiceDb, ServiceEntityResolver, ServiceModelResolver, ServiceRelations, ServiceTransaction, ServiceTransactionAsyncLocalStorage, ServiceTransactionConsistency‌, ServiceTransactionFiber, ServiceTransactionState, SymbolCacheModelCacheInstances, SymbolCacheModelsClear, SymbolKeyEntity, SymbolKeyEntityMeta, SymbolKeyFieldsMore, SymbolKeyModelOptions, TransactionIsolationLevelsMap, buildWhere, clearAllCacheModelsClear, clearCacheModelCacheInstance, config, configDefault, errors, getCacheModelCacheInstances, getCacheModelsClear, getClassEntityFromClassModel, getTableOrTableAlias, getTargetColumnName, isRaw, isRef, locales, prepareClassModel, prepareColumns };
4411
4413
  //# sourceMappingURL=index.js.map