vona-module-a-orm 5.0.96 → 5.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +0 -0
- package/cli/entity/metadata/generate.ts +2 -1
- package/cli/model/metadata/generate.ts +6 -2
- package/cli/model/metadata/magic.ts +15 -6
- package/dist/.metadata/index.d.ts +1 -0
- package/dist/.metadata/index.d.ts.map +1 -0
- package/dist/.metadata/locales.d.ts +1 -0
- package/dist/.metadata/locales.d.ts.map +1 -0
- package/dist/.metadata/this.d.ts +1 -0
- package/dist/.metadata/this.d.ts.map +1 -0
- package/dist/bean/aopMethod.transaction.d.ts +2 -1
- package/dist/bean/aopMethod.transaction.d.ts.map +1 -0
- package/dist/bean/bean.database.d.ts +2 -1
- package/dist/bean/bean.database.d.ts.map +1 -0
- package/dist/bean/bean.databaseDialectBase.d.ts +2 -1
- package/dist/bean/bean.databaseDialectBase.d.ts.map +1 -0
- package/dist/bean/bean.model/bean.model_cache.d.ts +5 -1
- package/dist/bean/bean.model/bean.model_cache.d.ts.map +1 -0
- package/dist/bean/bean.model/bean.model_crud.d.ts +1 -0
- package/dist/bean/bean.model/bean.model_crud.d.ts.map +1 -0
- package/dist/bean/bean.model/bean.model_crud_inner.d.ts +3 -1
- package/dist/bean/bean.model/bean.model_crud_inner.d.ts.map +1 -0
- package/dist/bean/bean.model/bean.model_crud_table.d.ts +1 -0
- package/dist/bean/bean.model/bean.model_crud_table.d.ts.map +1 -0
- package/dist/bean/bean.model/bean.model_knex.d.ts +1 -0
- package/dist/bean/bean.model/bean.model_knex.d.ts.map +1 -0
- package/dist/bean/bean.model/bean.model_meta.d.ts +3 -2
- package/dist/bean/bean.model/bean.model_meta.d.ts.map +1 -0
- package/dist/bean/bean.model/bean.model_utils.d.ts +5 -3
- package/dist/bean/bean.model/bean.model_utils.d.ts.map +1 -0
- package/dist/bean/bean.model/bean.model_view.d.ts +1 -0
- package/dist/bean/bean.model/bean.model_view.d.ts.map +1 -0
- package/dist/bean/bean.model.d.ts +1 -0
- package/dist/bean/bean.model.d.ts.map +1 -0
- package/dist/bean/bean.modelBase.d.ts +1 -0
- package/dist/bean/bean.modelBase.d.ts.map +1 -0
- package/dist/bean/broadcast.columnsClear.d.ts +2 -1
- package/dist/bean/broadcast.columnsClear.d.ts.map +1 -0
- package/dist/bean/event.clientNameReal.d.ts +2 -1
- package/dist/bean/event.clientNameReal.d.ts.map +1 -0
- package/dist/bean/event.columnsClear.d.ts +2 -1
- package/dist/bean/event.columnsClear.d.ts.map +1 -0
- package/dist/bean/hmr.entity.d.ts +1 -0
- package/dist/bean/hmr.entity.d.ts.map +1 -0
- package/dist/bean/hmr.model.d.ts +1 -0
- package/dist/bean/hmr.model.d.ts.map +1 -0
- package/dist/bean/queue.doubleDelete.d.ts +2 -1
- package/dist/bean/queue.doubleDelete.d.ts.map +1 -0
- package/dist/bean/schedule.softDeletionPrune.d.ts +1 -0
- package/dist/bean/schedule.softDeletionPrune.d.ts.map +1 -0
- package/dist/common/buildWhere.d.ts +1 -0
- package/dist/common/buildWhere.d.ts.map +1 -0
- package/dist/common/checkWhere.d.ts +1 -0
- package/dist/common/checkWhere.d.ts.map +1 -0
- package/dist/common/index.d.ts +1 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/utils.d.ts +2 -1
- package/dist/common/utils.d.ts.map +1 -0
- package/dist/config/config.d.ts +1 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/errors.d.ts +1 -0
- package/dist/config/errors.d.ts.map +1 -0
- package/dist/config/locale/en-us.d.ts +1 -0
- package/dist/config/locale/en-us.d.ts.map +1 -0
- package/dist/config/locale/zh-cn.d.ts +1 -0
- package/dist/config/locale/zh-cn.d.ts.map +1 -0
- package/dist/extend/index.d.ts +1 -0
- package/dist/extend/index.d.ts.map +1 -0
- package/dist/extend/schemaBuilder.d.ts +1 -0
- package/dist/extend/schemaBuilder.d.ts.map +1 -0
- package/dist/extend/tableBuilder.d.ts +1 -0
- package/dist/extend/tableBuilder.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +94 -15
- package/dist/index.js.map +1 -0
- package/dist/lib/const.d.ts +1 -0
- package/dist/lib/const.d.ts.map +1 -0
- package/dist/lib/databaseDialect.d.ts +1 -0
- package/dist/lib/databaseDialect.d.ts.map +1 -0
- package/dist/lib/dto/dto.d.ts +3 -0
- package/dist/lib/dto/dto.d.ts.map +1 -0
- package/dist/lib/dto/dtoAggregate.d.ts +3 -2
- package/dist/lib/dto/dtoAggregate.d.ts.map +1 -0
- package/dist/lib/dto/dtoCreate.d.ts +2 -1
- package/dist/lib/dto/dtoCreate.d.ts.map +1 -0
- package/dist/lib/dto/dtoGet.d.ts +2 -1
- package/dist/lib/dto/dtoGet.d.ts.map +1 -0
- package/dist/lib/dto/dtoGroup.d.ts +2 -1
- package/dist/lib/dto/dtoGroup.d.ts.map +1 -0
- package/dist/lib/dto/dtoListAndCount.d.ts +4 -0
- package/dist/lib/dto/dtoListAndCount.d.ts.map +1 -0
- package/dist/lib/dto/dtoMutate.d.ts +3 -2
- package/dist/lib/dto/dtoMutate.d.ts.map +1 -0
- package/dist/lib/dto/dtoQuery.d.ts +1 -0
- package/dist/lib/dto/dtoQuery.d.ts.map +1 -0
- package/dist/lib/dto/dtoQueryPage.d.ts +1 -0
- package/dist/lib/dto/dtoQueryPage.d.ts.map +1 -0
- package/dist/lib/dto/dtoSelectAndCount.d.ts +2 -1
- package/dist/lib/dto/dtoSelectAndCount.d.ts.map +1 -0
- package/dist/lib/dto/dtoUpdate.d.ts +2 -1
- package/dist/lib/dto/dtoUpdate.d.ts.map +1 -0
- package/dist/lib/dto/index.d.ts +1 -0
- package/dist/lib/dto/index.d.ts.map +1 -0
- package/dist/lib/entity.d.ts +1 -0
- package/dist/lib/entity.d.ts.map +1 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/model.d.ts +1 -0
- package/dist/lib/model.d.ts.map +1 -0
- package/dist/lib/modelCacheBase.d.ts +2 -1
- package/dist/lib/modelCacheBase.d.ts.map +1 -0
- package/dist/lib/relations.d.ts +5 -4
- package/dist/lib/relations.d.ts.map +1 -0
- package/dist/lib/relationsDynamic.d.ts +5 -4
- package/dist/lib/relationsDynamic.d.ts.map +1 -0
- package/dist/lib/relationsMutate.d.ts +4 -3
- package/dist/lib/relationsMutate.d.ts.map +1 -0
- package/dist/lib/relationsStatic.d.ts +1 -0
- package/dist/lib/relationsStatic.d.ts.map +1 -0
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/main.d.ts +2 -1
- package/dist/main.d.ts.map +1 -0
- package/dist/service/cacheEntity_.d.ts +1 -0
- package/dist/service/cacheEntity_.d.ts.map +1 -0
- package/dist/service/cacheQuery_.d.ts +1 -0
- package/dist/service/cacheQuery_.d.ts.map +1 -0
- package/dist/service/columnsCache_.d.ts +2 -1
- package/dist/service/columnsCache_.d.ts.map +1 -0
- package/dist/service/columns_.d.ts +2 -1
- package/dist/service/columns_.d.ts.map +1 -0
- package/dist/service/database.d.ts +2 -1
- package/dist/service/database.d.ts.map +1 -0
- package/dist/service/databaseAsyncLocalStorage_.d.ts +1 -0
- package/dist/service/databaseAsyncLocalStorage_.d.ts.map +1 -0
- package/dist/service/databaseClient_.d.ts +2 -1
- package/dist/service/databaseClient_.d.ts.map +1 -0
- package/dist/service/db_.d.ts +2 -1
- package/dist/service/db_.d.ts.map +1 -0
- package/dist/service/entityResolver_.d.ts +1 -0
- package/dist/service/entityResolver_.d.ts.map +1 -0
- package/dist/service/modelResolver_.d.ts +1 -0
- package/dist/service/modelResolver_.d.ts.map +1 -0
- package/dist/service/relations_.d.ts +2 -1
- package/dist/service/relations_.d.ts.map +1 -0
- package/dist/service/transactionAsyncLocalStorage_.d.ts +1 -0
- package/dist/service/transactionAsyncLocalStorage_.d.ts.map +1 -0
- package/dist/service/transactionConsistency/342/200/214_.d.ts +1 -0
- package/dist/service/transactionConsistency/342/200/214_.d.ts.map +1 -0
- package/dist/service/transactionFiber_.d.ts +1 -0
- package/dist/service/transactionFiber_.d.ts.map +1 -0
- package/dist/service/transactionState_.d.ts +2 -1
- package/dist/service/transactionState_.d.ts.map +1 -0
- package/dist/service/transaction_.d.ts +2 -1
- package/dist/service/transaction_.d.ts.map +1 -0
- package/dist/types/columns.d.ts +1 -0
- package/dist/types/columns.d.ts.map +1 -0
- package/dist/types/config.d.ts +1 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/database.d.ts +1 -0
- package/dist/types/database.d.ts.map +1 -0
- package/dist/types/depth.d.ts +1 -0
- package/dist/types/depth.d.ts.map +1 -0
- package/dist/types/dialect.d.ts +1 -0
- package/dist/types/dialect.d.ts.map +1 -0
- package/dist/types/dto/dtoAggregate.d.ts +1 -0
- package/dist/types/dto/dtoAggregate.d.ts.map +1 -0
- package/dist/types/dto/dtoGet.d.ts +3 -2
- package/dist/types/dto/dtoGet.d.ts.map +1 -0
- package/dist/types/dto/dtoGroup.d.ts +1 -0
- package/dist/types/dto/dtoGroup.d.ts.map +1 -0
- package/dist/types/dto/dtoListAndCount.d.ts +8 -0
- package/dist/types/dto/dtoListAndCount.d.ts.map +1 -0
- package/dist/types/dto/dtoMutate.d.ts +8 -9
- package/dist/types/dto/dtoMutate.d.ts.map +1 -0
- package/dist/types/dto/dtoQueryBase.d.ts +1 -0
- package/dist/types/dto/dtoQueryBase.d.ts.map +1 -0
- package/dist/types/dto/dtoQueryPageBase.d.ts +1 -0
- package/dist/types/dto/dtoQueryPageBase.d.ts.map +1 -0
- package/dist/types/dto/dtoSelectAndCount.d.ts +2 -1
- package/dist/types/dto/dtoSelectAndCount.d.ts.map +1 -0
- package/dist/types/dto/index.d.ts +2 -0
- package/dist/types/dto/index.d.ts.map +1 -0
- package/dist/types/entity.d.ts +1 -0
- package/dist/types/entity.d.ts.map +1 -0
- package/dist/types/entityBase.d.ts +1 -0
- package/dist/types/entityBase.d.ts.map +1 -0
- package/dist/types/entityBaseEmpty.d.ts +1 -0
- package/dist/types/entityBaseEmpty.d.ts.map +1 -0
- package/dist/types/entityBaseInner.d.ts +1 -0
- package/dist/types/entityBaseInner.d.ts.map +1 -0
- package/dist/types/entityBaseSimple.d.ts +1 -0
- package/dist/types/entityBaseSimple.d.ts.map +1 -0
- package/dist/types/extra.d.ts +1 -0
- package/dist/types/extra.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/logger.d.ts +1 -0
- package/dist/types/logger.d.ts.map +1 -0
- package/dist/types/model.d.ts +3 -2
- package/dist/types/model.d.ts.map +1 -0
- package/dist/types/modelAggr.d.ts +2 -1
- package/dist/types/modelAggr.d.ts.map +1 -0
- package/dist/types/modelCount.d.ts +2 -1
- package/dist/types/modelCount.d.ts.map +1 -0
- package/dist/types/modelGeneral.d.ts +4 -3
- package/dist/types/modelGeneral.d.ts.map +1 -0
- package/dist/types/modelGroup.d.ts +2 -1
- package/dist/types/modelGroup.d.ts.map +1 -0
- package/dist/types/modelIncrement.d.ts +19 -0
- package/dist/types/modelIncrement.d.ts.map +1 -0
- package/dist/types/modelWhere.d.ts +2 -1
- package/dist/types/modelWhere.d.ts.map +1 -0
- package/dist/types/onion/databaseDialect.d.ts +1 -0
- package/dist/types/onion/databaseDialect.d.ts.map +1 -0
- package/dist/types/onion/entity.d.ts +1 -0
- package/dist/types/onion/entity.d.ts.map +1 -0
- package/dist/types/onion/index.d.ts +1 -0
- package/dist/types/onion/index.d.ts.map +1 -0
- package/dist/types/onion/model.d.ts +1 -0
- package/dist/types/onion/model.d.ts.map +1 -0
- package/dist/types/onion/table.d.ts +1 -0
- package/dist/types/onion/table.d.ts.map +1 -0
- package/dist/types/relations.d.ts +10 -11
- package/dist/types/relations.d.ts.map +1 -0
- package/dist/types/relationsAggr.d.ts +2 -1
- package/dist/types/relationsAggr.d.ts.map +1 -0
- package/dist/types/relationsColumns.d.ts +5 -4
- package/dist/types/relationsColumns.d.ts.map +1 -0
- package/dist/types/relationsDef.d.ts +5 -4
- package/dist/types/relationsDef.d.ts.map +1 -0
- package/dist/types/relationsDefDynamic.d.ts +6 -5
- package/dist/types/relationsDefDynamic.d.ts.map +1 -0
- package/dist/types/relationsDefMutate.d.ts +1 -0
- package/dist/types/relationsDefMutate.d.ts.map +1 -0
- package/dist/types/relationsGroup.d.ts +1 -0
- package/dist/types/relationsGroup.d.ts.map +1 -0
- package/dist/types/relationsMutate.d.ts +4 -3
- package/dist/types/relationsMutate.d.ts.map +1 -0
- package/dist/types/relationsTables.d.ts +1 -0
- package/dist/types/relationsTables.d.ts.map +1 -0
- package/dist/types/transaction.d.ts +1 -0
- package/dist/types/transaction.d.ts.map +1 -0
- package/dist-cli/entity/metadata/generate.js +1 -1
- package/dist-cli/model/metadata/generate.js +4 -2
- package/dist-cli/model/metadata/magic.js +2 -2
- package/package.json +40 -36
- package/src/.metadata/index.ts +348 -0
- package/src/.metadata/locales.ts +13 -0
- package/src/.metadata/this.ts +2 -0
- package/src/bean/aopMethod.transaction.ts +18 -0
- package/src/bean/bean.database.ts +57 -0
- package/src/bean/bean.databaseDialectBase.ts +149 -0
- package/src/bean/bean.model/bean.model_cache.ts +815 -0
- package/src/bean/bean.model/bean.model_crud.ts +46 -0
- package/src/bean/bean.model/bean.model_crud_inner.ts +281 -0
- package/src/bean/bean.model/bean.model_crud_table.ts +59 -0
- package/src/bean/bean.model/bean.model_knex.ts +60 -0
- package/src/bean/bean.model/bean.model_meta.ts +204 -0
- package/src/bean/bean.model/bean.model_utils.ts +275 -0
- package/src/bean/bean.model/bean.model_view.ts +129 -0
- package/src/bean/bean.model.ts +8 -0
- package/src/bean/bean.modelBase.ts +8 -0
- package/src/bean/broadcast.columnsClear.ts +24 -0
- package/src/bean/event.clientNameReal.ts +10 -0
- package/src/bean/event.columnsClear.ts +13 -0
- package/src/bean/hmr.entity.ts +12 -0
- package/src/bean/hmr.model.ts +16 -0
- package/src/bean/queue.doubleDelete.ts +29 -0
- package/src/bean/schedule.softDeletionPrune.ts +45 -0
- package/src/common/buildWhere.ts +238 -0
- package/src/common/checkWhere.ts +128 -0
- package/src/common/index.ts +3 -0
- package/src/common/utils.ts +74 -0
- package/src/config/config.ts +60 -0
- package/src/config/errors.ts +3 -0
- package/src/config/locale/en-us.ts +8 -0
- package/src/config/locale/zh-cn.ts +8 -0
- package/src/extend/index.ts +12 -0
- package/src/extend/schemaBuilder.ts +29 -0
- package/src/extend/tableBuilder.ts +87 -0
- package/src/index.ts +10 -0
- package/src/lib/const.ts +58 -0
- package/src/lib/databaseDialect.ts +7 -0
- package/src/lib/dto/dto.ts +21 -0
- package/src/lib/dto/dtoAggregate.ts +51 -0
- package/src/lib/dto/dtoCreate.ts +14 -0
- package/src/lib/dto/dtoGet.ts +159 -0
- package/src/lib/dto/dtoGroup.ts +57 -0
- package/src/lib/dto/dtoListAndCount.ts +16 -0
- package/src/lib/dto/dtoMutate.ts +82 -0
- package/src/lib/dto/dtoQuery.ts +9 -0
- package/src/lib/dto/dtoQueryPage.ts +9 -0
- package/src/lib/dto/dtoSelectAndCount.ts +20 -0
- package/src/lib/dto/dtoUpdate.ts +16 -0
- package/src/lib/dto/index.ts +1 -0
- package/src/lib/entity.ts +25 -0
- package/src/lib/index.ts +9 -0
- package/src/lib/model.ts +7 -0
- package/src/lib/modelCacheBase.ts +98 -0
- package/src/lib/relations.ts +118 -0
- package/src/lib/relationsDynamic.ts +75 -0
- package/src/lib/relationsMutate.ts +60 -0
- package/src/lib/relationsStatic.ts +18 -0
- package/src/lib/utils.ts +45 -0
- package/src/main.ts +79 -0
- package/src/service/cacheEntity_.ts +37 -0
- package/src/service/cacheQuery_.ts +20 -0
- package/src/service/columnsCache_.ts +69 -0
- package/src/service/columns_.ts +64 -0
- package/src/service/database.ts +126 -0
- package/src/service/databaseAsyncLocalStorage_.ts +29 -0
- package/src/service/databaseClient_.ts +124 -0
- package/src/service/db_.ts +77 -0
- package/src/service/entityResolver_.ts +25 -0
- package/src/service/modelResolver_.ts +19 -0
- package/src/service/relations_.ts +444 -0
- package/src/service/transactionAsyncLocalStorage_.ts +31 -0
- package/src/service/transactionConsistency/342/200/214_.ts +37 -0
- package/src/service/transactionFiber_.ts +42 -0
- package/src/service/transactionState_.ts +35 -0
- package/src/service/transaction_.ts +147 -0
- package/src/types/columns.ts +8 -0
- package/src/types/config.ts +23 -0
- package/src/types/database.ts +64 -0
- package/src/types/depth.ts +55 -0
- package/src/types/dialect.ts +17 -0
- package/src/types/dto/dtoAggregate.ts +3 -0
- package/src/types/dto/dtoGet.ts +23 -0
- package/src/types/dto/dtoGroup.ts +3 -0
- package/src/types/dto/dtoListAndCount.ts +7 -0
- package/src/types/dto/dtoMutate.ts +231 -0
- package/src/types/dto/dtoQueryBase.ts +18 -0
- package/src/types/dto/dtoQueryPageBase.ts +18 -0
- package/src/types/dto/dtoSelectAndCount.ts +11 -0
- package/src/types/dto/index.ts +8 -0
- package/src/types/entity.ts +15 -0
- package/src/types/entityBase.ts +11 -0
- package/src/types/entityBaseEmpty.ts +1 -0
- package/src/types/entityBaseInner.ts +18 -0
- package/src/types/entityBaseSimple.ts +9 -0
- package/src/types/extra.ts +23 -0
- package/src/types/index.ts +30 -0
- package/src/types/logger.ts +6 -0
- package/src/types/model.ts +152 -0
- package/src/types/modelAggr.ts +69 -0
- package/src/types/modelCount.ts +40 -0
- package/src/types/modelGeneral.ts +61 -0
- package/src/types/modelGroup.ts +48 -0
- package/src/types/modelIncrement.ts +50 -0
- package/src/types/modelWhere.ts +85 -0
- package/src/types/onion/databaseDialect.ts +22 -0
- package/src/types/onion/entity.ts +33 -0
- package/src/types/onion/index.ts +4 -0
- package/src/types/onion/model.ts +68 -0
- package/src/types/onion/table.ts +1 -0
- package/src/types/relations.ts +243 -0
- package/src/types/relationsAggr.ts +31 -0
- package/src/types/relationsColumns.ts +116 -0
- package/src/types/relationsDef.ts +152 -0
- package/src/types/relationsDefDynamic.ts +128 -0
- package/src/types/relationsDefMutate.ts +11 -0
- package/src/types/relationsGroup.ts +58 -0
- package/src/types/relationsMutate.ts +118 -0
- package/src/types/relationsTables.ts +38 -0
- package/src/types/transaction.ts +23 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import type { TableIdentity } from 'table-identity';
|
|
2
|
+
|
|
3
|
+
import { isNil } from '@cabloy/utils';
|
|
4
|
+
import { BeanBase, cast, deepExtend } from 'vona';
|
|
5
|
+
import { Service } from 'vona-module-a-bean';
|
|
6
|
+
|
|
7
|
+
import type { BeanModelCache } from '../bean/bean.model/bean.model_cache.ts';
|
|
8
|
+
import type { BeanModelCrud } from '../bean/bean.model/bean.model_crud.ts';
|
|
9
|
+
import type { BeanModelMeta } from '../bean/bean.model/bean.model_meta.ts';
|
|
10
|
+
import type { IModelMethodOptions, IModelRelationIncludeWrapper } from '../types/model.ts';
|
|
11
|
+
import type { IModelClassRecord } from '../types/onion/model.ts';
|
|
12
|
+
import type { TypeModelClassLike } from '../types/relations.ts';
|
|
13
|
+
import type { IModelRelationOptionsMetaBasic, IRelationItem } from '../types/relationsDef.ts';
|
|
14
|
+
|
|
15
|
+
import { handleRelationsCollection } from '../lib/utils.ts';
|
|
16
|
+
|
|
17
|
+
@Service()
|
|
18
|
+
export class ServiceRelations extends BeanBase {
|
|
19
|
+
protected _model: BeanModelCache;
|
|
20
|
+
|
|
21
|
+
protected __init__(model: BeanModelCache) {
|
|
22
|
+
this._model = model;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public async handleRelationsOne<TRecord extends {}>(
|
|
26
|
+
relations: IRelationItem[] | undefined,
|
|
27
|
+
entity: TRecord | undefined,
|
|
28
|
+
includeWrapper?: IModelRelationIncludeWrapper,
|
|
29
|
+
methodOptions?: IModelMethodOptions,
|
|
30
|
+
) {
|
|
31
|
+
if (!entity) return entity;
|
|
32
|
+
// relations
|
|
33
|
+
if (!relations) {
|
|
34
|
+
relations = this.handleRelationsCollection(includeWrapper);
|
|
35
|
+
}
|
|
36
|
+
if (relations.length === 0) return entity;
|
|
37
|
+
for (const relation of relations) {
|
|
38
|
+
await this.__handleRelationOne(entity, relation, methodOptions);
|
|
39
|
+
}
|
|
40
|
+
return entity;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public async handleRelationsMany<TRecord extends {}>(
|
|
44
|
+
relations: IRelationItem[] | undefined,
|
|
45
|
+
entities: TRecord[],
|
|
46
|
+
includeWrapper?: IModelRelationIncludeWrapper,
|
|
47
|
+
methodOptions?: IModelMethodOptions,
|
|
48
|
+
) {
|
|
49
|
+
if (entities.length === 0) return entities;
|
|
50
|
+
// relations
|
|
51
|
+
if (!relations) {
|
|
52
|
+
relations = this.handleRelationsCollection(includeWrapper);
|
|
53
|
+
}
|
|
54
|
+
if (relations.length === 0) return entities;
|
|
55
|
+
for (const relation of relations) {
|
|
56
|
+
await this.__handleRelationMany(entities, relation, methodOptions);
|
|
57
|
+
}
|
|
58
|
+
return entities;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public async handleRelationsMutate<TRecord extends {}>(
|
|
62
|
+
entitiesResult: TRecord[],
|
|
63
|
+
entities: TRecord[],
|
|
64
|
+
includeWrapper: IModelRelationIncludeWrapper | undefined,
|
|
65
|
+
methodOptions: IModelMethodOptions | undefined,
|
|
66
|
+
) {
|
|
67
|
+
if (entitiesResult.length === 0) return entitiesResult;
|
|
68
|
+
// relations
|
|
69
|
+
const relations = this.handleRelationsCollection(includeWrapper);
|
|
70
|
+
if (!relations) return entitiesResult;
|
|
71
|
+
for (const relation of relations) {
|
|
72
|
+
entitiesResult = await this.__handleRelationMutate(entitiesResult, entities, relation, methodOptions);
|
|
73
|
+
}
|
|
74
|
+
return entitiesResult;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public async handleRelationsDelete(ids: TableIdentity[], includeWrapper?: IModelRelationIncludeWrapper, methodOptions?: IModelMethodOptions) {
|
|
78
|
+
if (ids.length === 0) return;
|
|
79
|
+
// relations
|
|
80
|
+
const relations = this.handleRelationsCollection(includeWrapper);
|
|
81
|
+
if (!relations) return;
|
|
82
|
+
for (const relation of relations) {
|
|
83
|
+
await this.__handleRelationDelete(ids, relation, methodOptions);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private async __handleRelationOne<TRecord extends {}>(entity: TRecord, relation: IRelationItem, methodOptions?: IModelMethodOptions) {
|
|
88
|
+
const [relationName, relationReal, includeReal, withReal] = relation;
|
|
89
|
+
const { type, modelMiddle, model, keyFrom, keyTo, key, options } = relationReal;
|
|
90
|
+
const modelTarget = this.__getModelTarget(model, options?.meta) as BeanModelCache;
|
|
91
|
+
const optionsReal = Object.assign({}, options, { include: includeReal, with: withReal });
|
|
92
|
+
const methodOptionsReal = Object.assign({}, methodOptions, { columns: undefined });
|
|
93
|
+
if (type === 'hasOne') {
|
|
94
|
+
const idFrom = cast(entity).id;
|
|
95
|
+
if (isNil(idFrom)) {
|
|
96
|
+
entity[relationName] = undefined;
|
|
97
|
+
} else {
|
|
98
|
+
const where = { [key]: idFrom };
|
|
99
|
+
const options2 = deepExtend({}, methodOptionsReal, optionsReal);
|
|
100
|
+
entity[relationName] = await modelTarget.get(where, options2);
|
|
101
|
+
}
|
|
102
|
+
} else if (type === 'belongsTo') {
|
|
103
|
+
const idTo = cast(entity)[key];
|
|
104
|
+
if (isNil(idTo)) {
|
|
105
|
+
entity[relationName] = undefined;
|
|
106
|
+
} else {
|
|
107
|
+
const where = { id: idTo };
|
|
108
|
+
const options2 = deepExtend({}, methodOptionsReal, optionsReal);
|
|
109
|
+
entity[relationName] = await modelTarget.get(where, options2);
|
|
110
|
+
}
|
|
111
|
+
} else if (type === 'hasMany') {
|
|
112
|
+
const idFrom = cast(entity).id;
|
|
113
|
+
if (isNil(idFrom)) {
|
|
114
|
+
entity[relationName] = optionsReal.groups ? [] : optionsReal.aggrs ? undefined : [];
|
|
115
|
+
} else {
|
|
116
|
+
if (optionsReal.groups) {
|
|
117
|
+
const options2 = deepExtend({}, optionsReal, { where: { [key]: idFrom } });
|
|
118
|
+
entity[relationName] = await modelTarget.group(options2, methodOptionsReal);
|
|
119
|
+
} else if (optionsReal.aggrs) {
|
|
120
|
+
const options2 = deepExtend({}, optionsReal, { where: { [key]: idFrom } });
|
|
121
|
+
entity[relationName] = await modelTarget.aggregate(options2, methodOptionsReal);
|
|
122
|
+
} else {
|
|
123
|
+
const options2 = deepExtend({}, optionsReal, { where: { [key]: idFrom } });
|
|
124
|
+
entity[relationName] = await modelTarget.select(options2, methodOptionsReal);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
} else if (type === 'belongsToMany') {
|
|
128
|
+
const modelTargetMiddle = this.__getModelTarget(modelMiddle, options?.meta?.middle) as BeanModelCrud;
|
|
129
|
+
const idFrom = cast(entity).id;
|
|
130
|
+
if (isNil(idFrom)) {
|
|
131
|
+
entity[relationName] = optionsReal.groups ? [] : optionsReal.aggrs ? undefined : [];
|
|
132
|
+
} else {
|
|
133
|
+
const itemsMiddle = await modelTargetMiddle.select({ where: { [keyFrom]: idFrom } }, methodOptionsReal);
|
|
134
|
+
const idsTo = itemsMiddle.map(item => item[keyTo]);
|
|
135
|
+
if (optionsReal.groups) {
|
|
136
|
+
const options2 = deepExtend({}, optionsReal, { where: { id: idsTo } });
|
|
137
|
+
entity[relationName] = await modelTarget.group(options2, methodOptionsReal);
|
|
138
|
+
} else if (optionsReal.aggrs) {
|
|
139
|
+
const options2 = deepExtend({}, optionsReal, { where: { id: idsTo } });
|
|
140
|
+
entity[relationName] = await modelTarget.aggregate(options2, methodOptionsReal);
|
|
141
|
+
} else {
|
|
142
|
+
const options2 = deepExtend({}, methodOptionsReal, optionsReal);
|
|
143
|
+
entity[relationName] = await modelTarget.mget(idsTo, options2);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private async __handleRelationMany<TRecord extends {}>(entities: TRecord[], relation: IRelationItem, methodOptions?: IModelMethodOptions) {
|
|
150
|
+
const [relationName, relationReal, includeReal, withReal] = relation;
|
|
151
|
+
const { type, modelMiddle, model, keyFrom, keyTo, key, options } = relationReal;
|
|
152
|
+
const modelTarget = this.__getModelTarget(model, options?.meta) as BeanModelCache;
|
|
153
|
+
const optionsReal = Object.assign({}, options, { include: includeReal, with: withReal });
|
|
154
|
+
const methodOptionsReal = Object.assign({}, methodOptions, { columns: undefined });
|
|
155
|
+
if (type === 'hasOne') {
|
|
156
|
+
const idsFrom = entities.map(item => cast(item).id).filter(id => !isNil(id));
|
|
157
|
+
const [columns, withKey] = this.__prepareColumnsAndKey(optionsReal.columns, key);
|
|
158
|
+
const options2 = deepExtend({}, optionsReal, { columns, where: { [key]: idsFrom } });
|
|
159
|
+
let items;
|
|
160
|
+
if (idsFrom.length === 0) {
|
|
161
|
+
items = [];
|
|
162
|
+
} else {
|
|
163
|
+
items = await modelTarget.select(options2, methodOptionsReal);
|
|
164
|
+
}
|
|
165
|
+
for (const entity of entities) {
|
|
166
|
+
entity[relationName] = items.find(item => {
|
|
167
|
+
if (item[key] === cast(entity).id) {
|
|
168
|
+
if (!withKey) delete item[key];
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
return false;
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
} else if (type === 'belongsTo') {
|
|
175
|
+
const idsTo = entities.map(item => cast(item)[key]).filter(id => !isNil(id));
|
|
176
|
+
const options2 = deepExtend({}, methodOptionsReal, optionsReal);
|
|
177
|
+
const items = await modelTarget.mget(idsTo, options2);
|
|
178
|
+
for (const entity of entities) {
|
|
179
|
+
entity[relationName] = items.find(item => cast(item).id === cast(entity)[key]);
|
|
180
|
+
}
|
|
181
|
+
} else if (type === 'hasMany') {
|
|
182
|
+
const idsFrom = entities.map(item => cast(item).id).filter(id => !isNil(id));
|
|
183
|
+
if (optionsReal.groups) {
|
|
184
|
+
const groups = [key].concat(optionsReal.groups);
|
|
185
|
+
const options2 = deepExtend({}, optionsReal, { groups, where: { [key]: idsFrom } });
|
|
186
|
+
const items = await modelTarget.group(options2, methodOptionsReal);
|
|
187
|
+
for (const entity of entities) {
|
|
188
|
+
entity[relationName] = [];
|
|
189
|
+
for (const item of items) {
|
|
190
|
+
if (item[key] === cast(entity).id) {
|
|
191
|
+
delete item[key];
|
|
192
|
+
entity[relationName].push(item);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
} else if (optionsReal.aggrs) {
|
|
197
|
+
const options2 = deepExtend({}, optionsReal, { groups: key, where: { [key]: idsFrom } });
|
|
198
|
+
const items = await modelTarget.group(options2, methodOptionsReal);
|
|
199
|
+
for (const entity of entities) {
|
|
200
|
+
const item = items.find(item => item[key] === cast(entity).id);
|
|
201
|
+
if (item) {
|
|
202
|
+
delete item[key];
|
|
203
|
+
}
|
|
204
|
+
entity[relationName] = item;
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
const [columns, withKey] = this.__prepareColumnsAndKey(optionsReal.columns, key);
|
|
208
|
+
const options2 = deepExtend({}, optionsReal, { columns, where: { [key]: idsFrom } });
|
|
209
|
+
const items = await modelTarget.select(options2, methodOptionsReal);
|
|
210
|
+
for (const entity of entities) {
|
|
211
|
+
entity[relationName] = [];
|
|
212
|
+
for (const item of items) {
|
|
213
|
+
if (item[key] === cast(entity).id) {
|
|
214
|
+
if (!withKey) delete item[key];
|
|
215
|
+
entity[relationName].push(item);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
} else if (type === 'belongsToMany') {
|
|
221
|
+
const modelTargetMiddle = this.__getModelTarget(modelMiddle, options?.meta?.middle) as BeanModelCrud;
|
|
222
|
+
const idsFrom = entities.map(item => cast(item).id).filter(id => !isNil(id));
|
|
223
|
+
let itemsMiddle;
|
|
224
|
+
if (idsFrom.length === 0) {
|
|
225
|
+
itemsMiddle = [];
|
|
226
|
+
} else {
|
|
227
|
+
itemsMiddle = await modelTargetMiddle.select({ where: { [keyFrom]: idsFrom } }, methodOptionsReal);
|
|
228
|
+
}
|
|
229
|
+
if (optionsReal.groups) {
|
|
230
|
+
for (const entity of entities) {
|
|
231
|
+
const idsTo = itemsMiddle.filter(item => item[keyFrom] === cast(entity).id).map(item => item[keyTo]);
|
|
232
|
+
const options2 = deepExtend({}, optionsReal, { groups: optionsReal.groups, where: { id: idsTo } });
|
|
233
|
+
entity[relationName] = await modelTarget.group(options2, methodOptionsReal);
|
|
234
|
+
}
|
|
235
|
+
} else if (optionsReal.aggrs) {
|
|
236
|
+
for (const entity of entities) {
|
|
237
|
+
const idsTo = itemsMiddle.filter(item => item[keyFrom] === cast(entity).id).map(item => item[keyTo]);
|
|
238
|
+
const options2 = deepExtend({}, optionsReal, { where: { id: idsTo } });
|
|
239
|
+
entity[relationName] = await modelTarget.aggregate(options2, methodOptionsReal);
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
const idsTo = itemsMiddle.map(item => item[keyTo]);
|
|
243
|
+
const options2 = deepExtend({}, methodOptionsReal, optionsReal);
|
|
244
|
+
const items = await modelTarget.mget(idsTo, options2);
|
|
245
|
+
for (const entity of entities) {
|
|
246
|
+
entity[relationName] = [];
|
|
247
|
+
for (const itemMiddle of itemsMiddle) {
|
|
248
|
+
if (itemMiddle[keyFrom] === cast(entity).id) {
|
|
249
|
+
entity[relationName].push(items.find(item => cast(item).id === cast(itemMiddle)[keyTo]));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private async __handleRelationMutate<TRecord extends {}>(
|
|
258
|
+
entitiesResult: TRecord[],
|
|
259
|
+
entities: TRecord[],
|
|
260
|
+
relation: IRelationItem,
|
|
261
|
+
methodOptions?: IModelMethodOptions,
|
|
262
|
+
) {
|
|
263
|
+
const [relationName, relationReal, includeReal, withReal] = relation;
|
|
264
|
+
const { type, modelMiddle, model, keyFrom, keyTo, key, options } = relationReal;
|
|
265
|
+
const modelTarget = this.__getModelTarget(model, options?.meta) as BeanModelCache;
|
|
266
|
+
const methodOptionsReal = Object.assign({}, methodOptions, { include: includeReal, with: withReal });
|
|
267
|
+
if (type === 'hasOne') {
|
|
268
|
+
let children: any[] = [];
|
|
269
|
+
for (let index = 0; index < entities.length; index++) {
|
|
270
|
+
const entity = entities[index];
|
|
271
|
+
if (entity[relationName]) {
|
|
272
|
+
// donot check if has id of entity[relationName], for safety
|
|
273
|
+
const item: any = await modelTarget.get({ [key]: cast(entity).id });
|
|
274
|
+
if (!isNil(item?.id) && !isNil(entity[relationName].id) && String(item?.id) !== String(entity[relationName].id)) {
|
|
275
|
+
throw new Error(`invalid id: ${entity[relationName].id}`);
|
|
276
|
+
}
|
|
277
|
+
const dataNew: any = { [key]: cast(entity).id };
|
|
278
|
+
if (!isNil(item?.id)) {
|
|
279
|
+
dataNew.id = item.id;
|
|
280
|
+
}
|
|
281
|
+
children.push(Object.assign({}, entity[relationName], dataNew));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
children = await modelTarget.mutateBulk(children, methodOptionsReal);
|
|
285
|
+
const result: TRecord[] = entitiesResult.concat();
|
|
286
|
+
for (let index = 0; index < entities.length; index++) {
|
|
287
|
+
const entityResult = result[index];
|
|
288
|
+
const entity = entities[index];
|
|
289
|
+
if (entity[relationName]) {
|
|
290
|
+
entityResult[relationName] = children.find(item => String(item[key]) === String(cast(entity).id));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return result;
|
|
294
|
+
} else if (type === 'belongsTo') {
|
|
295
|
+
// do nothing
|
|
296
|
+
return entitiesResult;
|
|
297
|
+
} else if (type === 'hasMany') {
|
|
298
|
+
let children: any[] = [];
|
|
299
|
+
for (let index = 0; index < entities.length; index++) {
|
|
300
|
+
const entity = entities[index];
|
|
301
|
+
if (entity[relationName] && entity[relationName].length > 0) {
|
|
302
|
+
const entityId = cast(entity).id;
|
|
303
|
+
const idsTo = entity[relationName].map(item => item.id).filter(id => !isNil(id));
|
|
304
|
+
let idsTarget;
|
|
305
|
+
if (idsTo.length === 0) {
|
|
306
|
+
idsTarget = [];
|
|
307
|
+
} else {
|
|
308
|
+
const itemsTarget = await cast(modelTarget).__select_raw(undefined, { where: { [key]: entityId, id: idsTo } }, methodOptionsReal);
|
|
309
|
+
idsTarget = itemsTarget.map(item => item.id);
|
|
310
|
+
}
|
|
311
|
+
for (const child of entity[relationName]) {
|
|
312
|
+
if (!isNil(child.id) && !idsTarget.includes(child.id)) {
|
|
313
|
+
throw new Error(`invalid id: ${child.id}`);
|
|
314
|
+
}
|
|
315
|
+
children.push(Object.assign({}, child, { [key]: entityId }));
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
children = await modelTarget.mutateBulk(children, methodOptionsReal);
|
|
320
|
+
const result: TRecord[] = entitiesResult.concat();
|
|
321
|
+
for (let index = 0; index < entities.length; index++) {
|
|
322
|
+
const entityResult = result[index];
|
|
323
|
+
const entity = entities[index];
|
|
324
|
+
if (entity[relationName]) {
|
|
325
|
+
entityResult[relationName] = [];
|
|
326
|
+
for (const child of children) {
|
|
327
|
+
if (child[key] === cast(entity).id) {
|
|
328
|
+
entityResult[relationName].push(child);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return result;
|
|
334
|
+
} else if (type === 'belongsToMany') {
|
|
335
|
+
const modelTargetMiddle = this.__getModelTarget(modelMiddle, options?.meta?.middle) as BeanModelCache;
|
|
336
|
+
let children: any[] = [];
|
|
337
|
+
for (let index = 0; index < entities.length; index++) {
|
|
338
|
+
const entity = entities[index];
|
|
339
|
+
if (entity[relationName] && entity[relationName].length > 0) {
|
|
340
|
+
const idsTo = entity[relationName].map(item => item.id);
|
|
341
|
+
let itemsMiddle;
|
|
342
|
+
if (idsTo.length === 0) {
|
|
343
|
+
itemsMiddle = [];
|
|
344
|
+
} else {
|
|
345
|
+
itemsMiddle = await cast(modelTargetMiddle).__select_raw(
|
|
346
|
+
undefined,
|
|
347
|
+
{ where: { [keyFrom]: cast(entity).id, [keyTo]: idsTo } },
|
|
348
|
+
methodOptionsReal,
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
for (const child of entity[relationName]) {
|
|
352
|
+
const itemMiddle = itemsMiddle.find(item => item[keyTo] === child.id);
|
|
353
|
+
if (!itemMiddle) {
|
|
354
|
+
if (!child.deleted) {
|
|
355
|
+
// add
|
|
356
|
+
children.push({ [keyFrom]: cast(entity).id, [keyTo]: child.id });
|
|
357
|
+
}
|
|
358
|
+
} else {
|
|
359
|
+
if (child.deleted) {
|
|
360
|
+
// delete
|
|
361
|
+
children.push({ id: itemMiddle.id, deleted: child.deleted });
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
children = await modelTargetMiddle.mutateBulk(children, methodOptionsReal);
|
|
368
|
+
const result: TRecord[] = entitiesResult.concat();
|
|
369
|
+
for (let index = 0; index < entities.length; index++) {
|
|
370
|
+
const entityResult = result[index];
|
|
371
|
+
const entity = entities[index];
|
|
372
|
+
if (entity[relationName]) {
|
|
373
|
+
entityResult[relationName] = [];
|
|
374
|
+
for (const child of children) {
|
|
375
|
+
if (child[keyFrom] === cast(entity).id) {
|
|
376
|
+
entityResult[relationName].push({ id: child[keyTo] });
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return result;
|
|
382
|
+
}
|
|
383
|
+
// do nothing
|
|
384
|
+
return entitiesResult;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
private async __handleRelationDelete(ids: TableIdentity[], relation: IRelationItem, methodOptions?: IModelMethodOptions) {
|
|
388
|
+
const [_relationName, relationReal, includeReal, withReal] = relation;
|
|
389
|
+
const { type, modelMiddle, model, keyFrom, key, options } = relationReal;
|
|
390
|
+
const modelTarget = this.__getModelTarget(model, options?.meta) as BeanModelCache;
|
|
391
|
+
const methodOptionsReal = Object.assign({}, methodOptions, { include: includeReal, with: withReal });
|
|
392
|
+
if (type === 'hasOne' || type === 'hasMany') {
|
|
393
|
+
const children = await cast(modelTarget).__select_raw(undefined, { columns: 'id', where: { [key]: ids } }, methodOptionsReal);
|
|
394
|
+
const idsTo = children.map(item => item.id);
|
|
395
|
+
await modelTarget.deleteBulk(idsTo, methodOptionsReal);
|
|
396
|
+
} else if (type === 'belongsTo') {
|
|
397
|
+
// do nothing
|
|
398
|
+
} else if (type === 'belongsToMany') {
|
|
399
|
+
const modelTargetMiddle = this.__getModelTarget(modelMiddle, options?.meta?.middle) as BeanModelCache;
|
|
400
|
+
const itemsMiddle = await cast(modelTargetMiddle).__select_raw(undefined, { columns: 'id', where: { [keyFrom]: ids } }, methodOptionsReal);
|
|
401
|
+
const idsMiddle = itemsMiddle.map(item => item.id);
|
|
402
|
+
await modelTargetMiddle.deleteBulk(idsMiddle, methodOptionsReal);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
private __prepareColumnsAndKey(columns: string | string[] | undefined, key: string) {
|
|
407
|
+
if (!columns) return [columns, true];
|
|
408
|
+
columns = Array.isArray(columns) ? columns : [columns];
|
|
409
|
+
if (columns.includes('*') || columns.includes(key)) return [columns, true];
|
|
410
|
+
columns = columns.concat(key);
|
|
411
|
+
return [columns, false];
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
public prepareColumnsByRelations<T extends { columns?: any }>(relations: IRelationItem[], options?: T): [T | undefined, string[] | undefined] {
|
|
415
|
+
if (!options || !options.columns) return [options, undefined];
|
|
416
|
+
const columns = Array.isArray(options.columns) ? options.columns : [options.columns];
|
|
417
|
+
if (columns.includes('*')) return [options, undefined];
|
|
418
|
+
// refKeys
|
|
419
|
+
const refKeys: string[] = [];
|
|
420
|
+
for (const relation of relations) {
|
|
421
|
+
const [_relationName, relationReal] = relation;
|
|
422
|
+
const { type, key } = relationReal;
|
|
423
|
+
if (type === 'belongsTo') {
|
|
424
|
+
if (!columns.includes(key)) {
|
|
425
|
+
columns.push(key);
|
|
426
|
+
refKeys.push(key);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
options = refKeys.length === 0 ? options : { ...options, columns };
|
|
431
|
+
return [options, refKeys];
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
private __getModelTarget<MODEL extends BeanModelMeta | keyof IModelClassRecord>(
|
|
435
|
+
modelClassTarget: TypeModelClassLike<MODEL>,
|
|
436
|
+
meta: IModelRelationOptionsMetaBasic | undefined,
|
|
437
|
+
): BeanModelMeta {
|
|
438
|
+
return this._model.newInstanceTarget(modelClassTarget, meta?.client, meta?.table);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
public handleRelationsCollection(includeWrapper?: IModelRelationIncludeWrapper): IRelationItem[] {
|
|
442
|
+
return handleRelationsCollection(this._model.options.relations, includeWrapper);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { FunctionAsync } from 'vona';
|
|
2
|
+
|
|
3
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
4
|
+
import { BeanBase } from 'vona';
|
|
5
|
+
import { Service } from 'vona-module-a-bean';
|
|
6
|
+
|
|
7
|
+
import { ServiceTransactionState } from './transactionState_.ts';
|
|
8
|
+
|
|
9
|
+
@Service()
|
|
10
|
+
export class ServiceTransactionAsyncLocalStorage extends BeanBase {
|
|
11
|
+
transactionStorage: AsyncLocalStorage<ServiceTransactionState>;
|
|
12
|
+
|
|
13
|
+
protected __init__() {
|
|
14
|
+
this.transactionStorage = new AsyncLocalStorage();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get transactionState(): ServiceTransactionState {
|
|
18
|
+
return this.transactionStorage.getStore()!;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async run<RESULT>(fn: FunctionAsync<RESULT>): Promise<RESULT> {
|
|
22
|
+
// only once
|
|
23
|
+
if (this.transactionState) {
|
|
24
|
+
return fn();
|
|
25
|
+
}
|
|
26
|
+
const transactionState = this.bean._newBean(ServiceTransactionState);
|
|
27
|
+
return this.transactionStorage.run(transactionState, () => {
|
|
28
|
+
return fn();
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { FunctionAny } from 'vona';
|
|
2
|
+
|
|
3
|
+
import { AsyncResource } from 'node:async_hooks';
|
|
4
|
+
import { BeanBase } from 'vona';
|
|
5
|
+
import { Service } from 'vona-module-a-bean';
|
|
6
|
+
|
|
7
|
+
@Service()
|
|
8
|
+
export class ServiceTransactionConsistency extends BeanBase {
|
|
9
|
+
private _commitCallbacks: FunctionAny[] = [];
|
|
10
|
+
private _compensateCallbacks: FunctionAny[] = [];
|
|
11
|
+
|
|
12
|
+
commit(cb: FunctionAny) {
|
|
13
|
+
this._commitCallbacks.push(AsyncResource.bind(cb));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
compensate(cb: FunctionAny) {
|
|
17
|
+
this._compensateCallbacks.unshift(AsyncResource.bind(cb));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async commitsDone() {
|
|
21
|
+
while (true) {
|
|
22
|
+
const cb = this._commitCallbacks.shift();
|
|
23
|
+
if (!cb) break;
|
|
24
|
+
await cb();
|
|
25
|
+
}
|
|
26
|
+
this._compensateCallbacks = [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async compensatesDone() {
|
|
30
|
+
while (true) {
|
|
31
|
+
const cb = this._compensateCallbacks.shift();
|
|
32
|
+
if (!cb) break;
|
|
33
|
+
await cb();
|
|
34
|
+
}
|
|
35
|
+
this._commitCallbacks = [];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type knex from 'knex';
|
|
2
|
+
import type { FunctionAny } from 'vona';
|
|
3
|
+
|
|
4
|
+
import { BeanBase } from 'vona';
|
|
5
|
+
import { Service } from 'vona-module-a-bean';
|
|
6
|
+
|
|
7
|
+
import { ServiceTransactionConsistency } from './transactionConsistency_.ts';
|
|
8
|
+
|
|
9
|
+
@Service()
|
|
10
|
+
export class ServiceTransactionFiber extends BeanBase {
|
|
11
|
+
private _connection: knex.Knex.Transaction;
|
|
12
|
+
private _transactionConsistency: ServiceTransactionConsistency;
|
|
13
|
+
|
|
14
|
+
protected __init__(connection: knex.Knex.Transaction) {
|
|
15
|
+
this._connection = connection;
|
|
16
|
+
this._transactionConsistency = this.app.bean._newBean(ServiceTransactionConsistency);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public get connection() {
|
|
20
|
+
return this._connection;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
commit(cb: FunctionAny) {
|
|
24
|
+
this._transactionConsistency.commit(cb);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
compensate(cb: FunctionAny) {
|
|
28
|
+
this._transactionConsistency.compensate(cb);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async doCommit() {
|
|
32
|
+
await this._connection.commit();
|
|
33
|
+
await this._transactionConsistency.commitsDone();
|
|
34
|
+
this._connection = undefined as any;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async doRollback() {
|
|
38
|
+
await this._connection.rollback();
|
|
39
|
+
await this._transactionConsistency.compensatesDone();
|
|
40
|
+
this._connection = undefined as any;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type knex from 'knex';
|
|
2
|
+
|
|
3
|
+
import { BeanBase } from 'vona';
|
|
4
|
+
import { Service } from 'vona-module-a-bean';
|
|
5
|
+
|
|
6
|
+
import type { ServiceDb } from './db_.ts';
|
|
7
|
+
|
|
8
|
+
import { ServiceDatabase } from './database.ts';
|
|
9
|
+
import { ServiceTransactionFiber } from './transactionFiber_.ts';
|
|
10
|
+
|
|
11
|
+
@Service()
|
|
12
|
+
export class ServiceTransactionState extends BeanBase {
|
|
13
|
+
private _fibers: Record<string, ServiceTransactionFiber> = {};
|
|
14
|
+
|
|
15
|
+
private get serviceDatabase() {
|
|
16
|
+
return this.bean._getBean(ServiceDatabase);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public get(db: ServiceDb): ServiceTransactionFiber | undefined {
|
|
20
|
+
const selector = this.serviceDatabase.prepareClientNameSelector(db.info, db.dialect);
|
|
21
|
+
return this._fibers[selector];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public add(db: ServiceDb, connection: knex.Knex.Transaction) {
|
|
25
|
+
const selector = this.serviceDatabase.prepareClientNameSelector(db.info, db.dialect);
|
|
26
|
+
const fiber = this.bean._newBean(ServiceTransactionFiber, connection);
|
|
27
|
+
this._fibers[selector] = fiber;
|
|
28
|
+
return fiber;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public remove(db: ServiceDb) {
|
|
32
|
+
const selector = this.serviceDatabase.prepareClientNameSelector(db.info, db.dialect);
|
|
33
|
+
delete this._fibers[selector];
|
|
34
|
+
}
|
|
35
|
+
}
|