@contember/engine-content-api 1.3.0-alpha.1 → 1.3.0-alpha.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/dist/src/ExecutionContainer.d.ts +141 -0
- package/dist/src/ExecutionContainer.d.ts.map +1 -0
- package/dist/src/ExecutionContainer.js +84 -0
- package/dist/src/ExecutionContainer.js.map +1 -0
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +18 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/mapper/ColumnValue.d.ts +2 -2
- package/dist/src/mapper/ColumnValue.d.ts.map +1 -1
- package/dist/src/mapper/EventManager.d.ts +86 -0
- package/dist/src/mapper/EventManager.d.ts.map +1 -0
- package/dist/src/mapper/EventManager.js +118 -0
- package/dist/src/mapper/EventManager.js.map +1 -0
- package/dist/src/mapper/JunctionTableManager.d.ts +12 -11
- package/dist/src/mapper/JunctionTableManager.d.ts.map +1 -1
- package/dist/src/mapper/JunctionTableManager.js +20 -8
- package/dist/src/mapper/JunctionTableManager.js.map +1 -1
- package/dist/src/mapper/Mapper.d.ts +11 -6
- package/dist/src/mapper/Mapper.d.ts.map +1 -1
- package/dist/src/mapper/Mapper.js +34 -17
- package/dist/src/mapper/Mapper.js.map +1 -1
- package/dist/src/mapper/MapperFactory.d.ts +33 -0
- package/dist/src/mapper/MapperFactory.d.ts.map +1 -0
- package/dist/src/mapper/MapperFactory.js +40 -0
- package/dist/src/mapper/MapperFactory.js.map +1 -0
- package/dist/src/mapper/Result.d.ts +3 -2
- package/dist/src/mapper/Result.d.ts.map +1 -1
- package/dist/src/mapper/Result.js +2 -1
- package/dist/src/mapper/Result.js.map +1 -1
- package/dist/src/mapper/delete/DeleteExecutor.d.ts.map +1 -1
- package/dist/src/mapper/delete/DeleteExecutor.js +41 -1
- package/dist/src/mapper/delete/DeleteExecutor.js.map +1 -1
- package/dist/src/mapper/index.d.ts +3 -1
- package/dist/src/mapper/index.d.ts.map +1 -1
- package/dist/src/mapper/index.js +3 -1
- package/dist/src/mapper/index.js.map +1 -1
- package/dist/src/mapper/insert/InsertBuilder.d.ts +2 -2
- package/dist/src/mapper/insert/InsertBuilder.d.ts.map +1 -1
- package/dist/src/mapper/insert/InsertBuilder.js +8 -2
- package/dist/src/mapper/insert/InsertBuilder.js.map +1 -1
- package/dist/src/mapper/insert/Inserter.js +3 -3
- package/dist/src/mapper/insert/Inserter.js.map +1 -1
- package/dist/src/mapper/select/OrderByHelper.d.ts +1 -1
- package/dist/src/mapper/select/OrderByHelper.d.ts.map +1 -1
- package/dist/src/mapper/select/OrderByHelper.js +3 -1
- package/dist/src/mapper/select/OrderByHelper.js.map +1 -1
- package/dist/src/mapper/select/RelationFetcher.js +2 -2
- package/dist/src/mapper/select/RelationFetcher.js.map +1 -1
- package/dist/src/mapper/update/UpdateBuilder.d.ts +4 -4
- package/dist/src/mapper/update/UpdateBuilder.d.ts.map +1 -1
- package/dist/src/mapper/update/UpdateBuilder.js +26 -8
- package/dist/src/mapper/update/UpdateBuilder.js.map +1 -1
- package/dist/src/mapper/update/UpdateBuilderFactory.d.ts +1 -1
- package/dist/src/mapper/update/UpdateBuilderFactory.d.ts.map +1 -1
- package/dist/src/mapper/update/UpdateBuilderFactory.js +2 -2
- package/dist/src/mapper/update/UpdateBuilderFactory.js.map +1 -1
- package/dist/src/mapper/update/Updater.d.ts.map +1 -1
- package/dist/src/mapper/update/Updater.js +6 -10
- package/dist/src/mapper/update/Updater.js.map +1 -1
- package/dist/src/resolvers/GraphQlQueryAstFactory.d.ts +1 -3
- package/dist/src/resolvers/GraphQlQueryAstFactory.d.ts.map +1 -1
- package/dist/src/resolvers/GraphQlQueryAstFactory.js +1 -4
- package/dist/src/resolvers/GraphQlQueryAstFactory.js.map +1 -1
- package/dist/src/resolvers/MutationResolver.d.ts +1 -4
- package/dist/src/resolvers/MutationResolver.d.ts.map +1 -1
- package/dist/src/resolvers/MutationResolver.js +9 -11
- package/dist/src/resolvers/MutationResolver.js.map +1 -1
- package/dist/src/resolvers/ReadResolver.d.ts +1 -3
- package/dist/src/resolvers/ReadResolver.d.ts.map +1 -1
- package/dist/src/resolvers/ReadResolver.js +6 -10
- package/dist/src/resolvers/ReadResolver.js.map +1 -1
- package/dist/src/resolvers/ValidationResolver.d.ts +1 -3
- package/dist/src/resolvers/ValidationResolver.d.ts.map +1 -1
- package/dist/src/resolvers/ValidationResolver.js +3 -4
- package/dist/src/resolvers/ValidationResolver.js.map +1 -1
- package/dist/src/resolvers/index.d.ts +0 -1
- package/dist/src/resolvers/index.d.ts.map +1 -1
- package/dist/src/resolvers/index.js +0 -1
- package/dist/src/resolvers/index.js.map +1 -1
- package/dist/src/schema/CustomTypesProvider.d.ts.map +1 -1
- package/dist/src/schema/CustomTypesProvider.js +1 -23
- package/dist/src/schema/CustomTypesProvider.js.map +1 -1
- package/dist/src/schema/MutationProvider.js +4 -4
- package/dist/src/schema/MutationProvider.js.map +1 -1
- package/dist/src/schema/QueryProvider.js +3 -3
- package/dist/src/schema/QueryProvider.js.map +1 -1
- package/dist/src/tsconfig.tsbuildinfo +1 -1
- package/dist/src/types.d.ts +2 -3
- package/dist/src/types.d.ts.map +1 -1
- package/dist/tests/cases/bugs/bug-update-by-nested-unique.test.js +3 -5
- package/dist/tests/cases/bugs/bug-update-by-nested-unique.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlDb/insert/insertSequence.test.js +2 -2
- package/dist/tests/cases/integration/graphQlDb/insert/insertSequence.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlDb/update/bug-freeze-connect-missing-one.test.js +1 -1
- package/dist/tests/cases/integration/graphQlDb/update/bug-freeze-connect-missing-one.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlDb/update/deferedConstraints.test.js +45 -45
- package/dist/tests/cases/integration/graphQlDb/update/deferedConstraints.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlDb/update/failedDelete.test.js +5 -5
- package/dist/tests/cases/integration/graphQlDb/update/failedDelete.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlDb/update/invalidInput.test.js +2 -2
- package/dist/tests/cases/integration/graphQlDb/update/invalidInput.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlDb/update/nullChecksNotNull.test.js +7 -7
- package/dist/tests/cases/integration/graphQlDb/update/nullChecksNotNull.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlDb/update/nullChecksNullable.test.js +7 -7
- package/dist/tests/cases/integration/graphQlDb/update/nullChecksNullable.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlDb/update/uniqueConstraint.test.js +2 -2
- package/dist/tests/cases/integration/graphQlDb/update/uniqueConstraint.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/insert/oneHasMany/connect.test.js +3 -3
- package/dist/tests/cases/integration/graphQlRequests/insert/oneHasMany/connect.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/sorting/orderBy.test.d.ts +2 -0
- package/dist/tests/cases/integration/graphQlRequests/query/sorting/orderBy.test.d.ts.map +1 -0
- package/dist/tests/cases/integration/graphQlRequests/query/sorting/orderBy.test.js +67 -0
- package/dist/tests/cases/integration/graphQlRequests/query/sorting/orderBy.test.js.map +1 -0
- package/dist/tests/cases/integration/graphQlRequests/update/acl/aclUpdate.test.js +6 -18
- package/dist/tests/cases/integration/graphQlRequests/update/acl/aclUpdate.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/additionalFilter.test.js +3 -4
- package/dist/tests/cases/integration/graphQlRequests/update/additionalFilter.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/basic/columnUpdate.test.js +3 -8
- package/dist/tests/cases/integration/graphQlRequests/update/basic/columnUpdate.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyInverse/update.test.js +3 -9
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyInverse/update.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyInverse/upsert.test.js +3 -9
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyInverse/upsert.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyOwning/update.test.js +3 -9
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyOwning/update.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyOwning/upsert.test.js +3 -9
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyOwning/upsert.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/connect.test.js +3 -10
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/connect.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/create.test.js +3 -10
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/create.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/disconnect.test.js +3 -9
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/disconnect.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/update.test.js +3 -9
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/update.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/upsert.test.js +6 -18
- package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/upsert.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/connect.test.js +3 -11
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/connect.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/disconnect.test.js +3 -8
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/disconnect.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/update.test.js +3 -6
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/update.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/upsert.test.js +3 -6
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/upsert.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/connect.test.js +15 -50
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/connect.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/create.test.js +3 -10
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/create.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/disconnect.test.js +3 -10
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/disconnect.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/update.test.js +3 -6
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/update.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/upsert.test.js +3 -7
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/upsert.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/connect.test.js +12 -32
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/connect.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/connectOrCreate.test.js +3 -3
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/connectOrCreate.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/create.test.js +6 -20
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/create.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/disconnect.test.js +3 -10
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/disconnect.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/update.test.js +3 -9
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/update.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/upsert.test.js +6 -19
- package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/upsert.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/queryPortal.test.js +6 -8
- package/dist/tests/cases/integration/graphQlRequests/update/queryPortal.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/transaction.test.js +9 -24
- package/dist/tests/cases/integration/graphQlRequests/update/transaction.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/upsert/basicUpsert.test.js +3 -7
- package/dist/tests/cases/integration/graphQlRequests/upsert/basicUpsert.test.js.map +1 -1
- package/dist/tests/cases/unit/orderbyHelper.test.js +11 -0
- package/dist/tests/cases/unit/orderbyHelper.test.js.map +1 -1
- package/dist/tests/src/test.d.ts +1 -0
- package/dist/tests/src/test.d.ts.map +1 -1
- package/dist/tests/src/test.js +34 -6
- package/dist/tests/src/test.js.map +1 -1
- package/dist/tests/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -11
- package/src/ExecutionContainer.ts +204 -0
- package/src/index.ts +24 -1
- package/src/mapper/ColumnValue.ts +2 -2
- package/src/mapper/EventManager.ts +158 -0
- package/src/mapper/JunctionTableManager.ts +50 -32
- package/src/mapper/Mapper.ts +39 -21
- package/src/mapper/MapperFactory.ts +67 -0
- package/src/mapper/Result.ts +2 -1
- package/src/mapper/delete/DeleteExecutor.ts +42 -1
- package/src/mapper/index.ts +3 -1
- package/src/mapper/insert/InsertBuilder.ts +12 -2
- package/src/mapper/insert/Inserter.ts +3 -3
- package/src/mapper/select/OrderByHelper.ts +2 -1
- package/src/mapper/select/RelationFetcher.ts +2 -2
- package/src/mapper/update/UpdateBuilder.ts +30 -7
- package/src/mapper/update/UpdateBuilderFactory.ts +2 -2
- package/src/mapper/update/Updater.ts +6 -11
- package/src/resolvers/GraphQlQueryAstFactory.ts +1 -2
- package/src/resolvers/MutationResolver.ts +12 -13
- package/src/resolvers/ReadResolver.ts +5 -9
- package/src/resolvers/ValidationResolver.ts +2 -4
- package/src/resolvers/index.ts +0 -1
- package/src/schema/CustomTypesProvider.ts +2 -27
- package/src/schema/MutationProvider.ts +4 -4
- package/src/schema/QueryProvider.ts +3 -3
- package/src/tsconfig.json +7 -21
- package/src/types.ts +2 -3
- package/tests/cases/bugs/bug-update-by-nested-unique.test.ts +3 -5
- package/tests/cases/integration/graphQlDb/insert/insertSequence.test.ts +2 -2
- package/tests/cases/integration/graphQlDb/update/bug-freeze-connect-missing-one.test.ts +1 -1
- package/tests/cases/integration/graphQlDb/update/deferedConstraints.test.ts +9 -9
- package/tests/cases/integration/graphQlDb/update/failedDelete.test.ts +3 -3
- package/tests/cases/integration/graphQlDb/update/invalidInput.test.ts +2 -2
- package/tests/cases/integration/graphQlDb/update/nullChecksNotNull.test.ts +7 -7
- package/tests/cases/integration/graphQlDb/update/nullChecksNullable.test.ts +7 -7
- package/tests/cases/integration/graphQlDb/update/uniqueConstraint.test.ts +2 -2
- package/tests/cases/integration/graphQlRequests/insert/oneHasMany/connect.test.ts +3 -3
- package/tests/cases/integration/graphQlRequests/query/sorting/orderBy.test.ts +67 -0
- package/tests/cases/integration/graphQlRequests/update/acl/aclUpdate.test.ts +6 -18
- package/tests/cases/integration/graphQlRequests/update/additionalFilter.test.ts +3 -4
- package/tests/cases/integration/graphQlRequests/update/basic/columnUpdate.test.ts +3 -8
- package/tests/cases/integration/graphQlRequests/update/manyHasManyInverse/update.test.ts +3 -9
- package/tests/cases/integration/graphQlRequests/update/manyHasManyInverse/upsert.test.ts +3 -9
- package/tests/cases/integration/graphQlRequests/update/manyHasManyOwning/update.test.ts +3 -9
- package/tests/cases/integration/graphQlRequests/update/manyHasManyOwning/upsert.test.ts +3 -9
- package/tests/cases/integration/graphQlRequests/update/manyHasOne/connect.test.ts +3 -10
- package/tests/cases/integration/graphQlRequests/update/manyHasOne/create.test.ts +3 -10
- package/tests/cases/integration/graphQlRequests/update/manyHasOne/disconnect.test.ts +3 -9
- package/tests/cases/integration/graphQlRequests/update/manyHasOne/update.test.ts +3 -9
- package/tests/cases/integration/graphQlRequests/update/manyHasOne/upsert.test.ts +6 -18
- package/tests/cases/integration/graphQlRequests/update/oneHasMany/connect.test.ts +3 -11
- package/tests/cases/integration/graphQlRequests/update/oneHasMany/disconnect.test.ts +3 -8
- package/tests/cases/integration/graphQlRequests/update/oneHasMany/update.test.ts +3 -6
- package/tests/cases/integration/graphQlRequests/update/oneHasMany/upsert.test.ts +3 -6
- package/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/connect.test.ts +15 -50
- package/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/create.test.ts +3 -10
- package/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/disconnect.test.ts +3 -10
- package/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/update.test.ts +3 -6
- package/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/upsert.test.ts +3 -7
- package/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/connect.test.ts +12 -32
- package/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/connectOrCreate.test.ts +3 -3
- package/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/create.test.ts +6 -20
- package/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/disconnect.test.ts +3 -10
- package/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/update.test.ts +3 -9
- package/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/upsert.test.ts +6 -19
- package/tests/cases/integration/graphQlRequests/update/queryPortal.test.ts +6 -8
- package/tests/cases/integration/graphQlRequests/update/transaction.test.ts +9 -24
- package/tests/cases/integration/graphQlRequests/upsert/basicUpsert.test.ts +3 -7
- package/tests/cases/unit/orderbyHelper.test.ts +13 -0
- package/tests/src/test.ts +38 -15
- package/tests/tsconfig.json +3 -9
- package/dist/src/mapper/MapperContainer.d.ts +0 -18
- package/dist/src/mapper/MapperContainer.d.ts.map +0 -1
- package/dist/src/mapper/MapperContainer.js +0 -55
- package/dist/src/mapper/MapperContainer.js.map +0 -1
- package/dist/src/resolvers/ExecutionContainerFactory.d.ts +0 -24
- package/dist/src/resolvers/ExecutionContainerFactory.d.ts.map +0 -1
- package/dist/src/resolvers/ExecutionContainerFactory.js +0 -45
- package/dist/src/resolvers/ExecutionContainerFactory.js.map +0 -1
- package/src/mapper/MapperContainer.ts +0 -142
- package/src/resolvers/ExecutionContainerFactory.ts +0 -74
package/src/mapper/Mapper.ts
CHANGED
|
@@ -10,8 +10,7 @@ import {
|
|
|
10
10
|
SelectResultObject,
|
|
11
11
|
WhereBuilder,
|
|
12
12
|
} from './select'
|
|
13
|
-
import
|
|
14
|
-
import { Client, ConstraintHelper, SelectBuilder } from '@contember/database'
|
|
13
|
+
import { Client, Connection, ConstraintHelper, SelectBuilder } from '@contember/database'
|
|
15
14
|
import { PredicatesInjector } from '../acl'
|
|
16
15
|
import { JunctionTableManager } from './JunctionTableManager'
|
|
17
16
|
import { DeletedEntitiesStorage, DeleteExecutor } from './delete'
|
|
@@ -23,16 +22,22 @@ import { ObjectNode, UniqueWhereExpander } from '../inputProcessing'
|
|
|
23
22
|
import { Mutex } from '../utils'
|
|
24
23
|
import { CheckedPrimary } from './CheckedPrimary'
|
|
25
24
|
import { ImplementationException } from '../exception'
|
|
25
|
+
import { EventManager } from './EventManager'
|
|
26
26
|
|
|
27
|
-
export class Mapper {
|
|
27
|
+
export class Mapper<ConnectionType extends Connection.ConnectionLike = Connection.ConnectionLike> {
|
|
28
28
|
private primaryKeyCache: Record<string, Promise<string> | string> = {}
|
|
29
|
+
private systemVariablesSetupDone: Promise<void> | undefined
|
|
29
30
|
public readonly deletedEntities = new DeletedEntitiesStorage()
|
|
30
31
|
public readonly mutex = new Mutex()
|
|
31
32
|
public readonly constraintHelper: ConstraintHelper
|
|
32
33
|
|
|
34
|
+
public readonly eventManager: EventManager
|
|
35
|
+
|
|
33
36
|
constructor(
|
|
37
|
+
public readonly db: Client<ConnectionType>,
|
|
38
|
+
public readonly identityId: string,
|
|
39
|
+
public readonly transactionId: string,
|
|
34
40
|
private readonly schema: Model.Schema,
|
|
35
|
-
public readonly db: database.Client,
|
|
36
41
|
private readonly predicatesInjector: PredicatesInjector,
|
|
37
42
|
private readonly selectBuilderFactory: SelectBuilderFactory,
|
|
38
43
|
private readonly uniqueWhereExpander: UniqueWhereExpander,
|
|
@@ -44,6 +49,7 @@ export class Mapper {
|
|
|
44
49
|
private readonly pathFactory: PathFactory,
|
|
45
50
|
) {
|
|
46
51
|
this.constraintHelper = new ConstraintHelper(db)
|
|
52
|
+
this.eventManager = new EventManager(this)
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
public async selectField(entity: Model.Entity, where: Input.UniqueWhere | CheckedPrimary, fieldName: string) {
|
|
@@ -122,7 +128,7 @@ export class Mapper {
|
|
|
122
128
|
relationPath: Model.AnyRelationContext[],
|
|
123
129
|
groupBy?: string,
|
|
124
130
|
) {
|
|
125
|
-
const inputWithOrder = OrderByHelper.appendDefaultOrderBy(entity, input,
|
|
131
|
+
const inputWithOrder = OrderByHelper.appendDefaultOrderBy(entity, input, undefined)
|
|
126
132
|
const path = this.pathFactory.create([])
|
|
127
133
|
const augmentedBuilder = qb.from(entity.tableName, path.alias).meta('path', [...input.path, input.alias])
|
|
128
134
|
|
|
@@ -174,12 +180,9 @@ export class Mapper {
|
|
|
174
180
|
if (entity.view) {
|
|
175
181
|
throw new ImplementationException()
|
|
176
182
|
}
|
|
177
|
-
|
|
178
|
-
const where = { [entity.primary]: id }
|
|
179
|
-
this.primaryKeyCache[this.hashWhere(entity.name, where)] = id
|
|
180
|
-
}
|
|
183
|
+
await this.setupSystemVariables()
|
|
181
184
|
return tryMutation(this.schema, () =>
|
|
182
|
-
this.
|
|
185
|
+
this.insertInternal(entity, data, builderCb),
|
|
183
186
|
)
|
|
184
187
|
}
|
|
185
188
|
|
|
@@ -192,6 +195,7 @@ export class Mapper {
|
|
|
192
195
|
if (entity.view) {
|
|
193
196
|
throw new ImplementationException()
|
|
194
197
|
}
|
|
198
|
+
await this.setupSystemVariables()
|
|
195
199
|
return tryMutation(this.schema, async () => {
|
|
196
200
|
const primaryValue = await this.getPrimaryValue(entity, by)
|
|
197
201
|
if (primaryValue === undefined) {
|
|
@@ -209,6 +213,7 @@ export class Mapper {
|
|
|
209
213
|
if (entity.view) {
|
|
210
214
|
throw new ImplementationException()
|
|
211
215
|
}
|
|
216
|
+
await this.setupSystemVariables()
|
|
212
217
|
return tryMutation(this.schema, async () => {
|
|
213
218
|
const primaryValue = await this.getPrimaryValue(entity, by)
|
|
214
219
|
if (primaryValue === undefined) {
|
|
@@ -227,19 +232,23 @@ export class Mapper {
|
|
|
227
232
|
if (entity.view) {
|
|
228
233
|
throw new ImplementationException()
|
|
229
234
|
}
|
|
235
|
+
await this.setupSystemVariables()
|
|
230
236
|
return tryMutation(this.schema, async () => {
|
|
231
237
|
const primaryValue = await this.getPrimaryValue(entity, by)
|
|
232
238
|
if (primaryValue === undefined) {
|
|
233
|
-
|
|
234
|
-
const where = { [entity.primary]: id }
|
|
235
|
-
this.primaryKeyCache[this.hashWhere(entity.name, where)] = id
|
|
236
|
-
}
|
|
237
|
-
return await this.inserter.insert(this, entity, create, pushIdCallback, () => {})
|
|
239
|
+
return await this.insertInternal(entity, create)
|
|
238
240
|
}
|
|
239
241
|
return await this.updater.update(this, entity, primaryValue, update, filter)
|
|
240
242
|
})
|
|
241
243
|
}
|
|
242
244
|
|
|
245
|
+
private insertInternal(entity: Model.Entity, data: Input.CreateDataInput, builderCb: (builder: InsertBuilder) => void = () => {}) {
|
|
246
|
+
return this.inserter.insert(this, entity, data, id => {
|
|
247
|
+
const where = { [entity.primary]: id }
|
|
248
|
+
this.primaryKeyCache[this.hashWhere(entity.name, where)] = id
|
|
249
|
+
}, builderCb)
|
|
250
|
+
}
|
|
251
|
+
|
|
243
252
|
public async delete(
|
|
244
253
|
entity: Model.Entity,
|
|
245
254
|
by: Input.UniqueWhere | CheckedPrimary,
|
|
@@ -248,6 +257,7 @@ export class Mapper {
|
|
|
248
257
|
if (entity.view) {
|
|
249
258
|
throw new ImplementationException()
|
|
250
259
|
}
|
|
260
|
+
await this.setupSystemVariables()
|
|
251
261
|
return tryMutation(this.schema, () => this.deleteExecutor.execute(this, entity, by, filter))
|
|
252
262
|
}
|
|
253
263
|
|
|
@@ -257,15 +267,16 @@ export class Mapper {
|
|
|
257
267
|
thisPrimary: Input.PrimaryValue,
|
|
258
268
|
otherPrimary: Input.PrimaryValue,
|
|
259
269
|
): Promise<MutationResultList> {
|
|
270
|
+
await this.setupSystemVariables()
|
|
260
271
|
const err = () => {
|
|
261
272
|
throw new ImplementationException()
|
|
262
273
|
}
|
|
263
274
|
return await acceptFieldVisitor(this.schema, entity, relation, {
|
|
264
275
|
visitManyHasManyOwning: ({ entity, relation }) => {
|
|
265
|
-
return this.junctionTableManager.connectJunction(this
|
|
276
|
+
return this.junctionTableManager.connectJunction(this, entity, relation, thisPrimary, otherPrimary)
|
|
266
277
|
},
|
|
267
278
|
visitManyHasManyInverse: ({ targetEntity, targetRelation }) => {
|
|
268
|
-
return this.junctionTableManager.connectJunction(this
|
|
279
|
+
return this.junctionTableManager.connectJunction(this, targetEntity, targetRelation, otherPrimary, thisPrimary)
|
|
269
280
|
},
|
|
270
281
|
visitColumn: err,
|
|
271
282
|
visitOneHasMany: err,
|
|
@@ -281,15 +292,16 @@ export class Mapper {
|
|
|
281
292
|
thisPrimary: Input.PrimaryValue,
|
|
282
293
|
otherPrimary: Input.PrimaryValue,
|
|
283
294
|
): Promise<MutationResultList> {
|
|
295
|
+
await this.setupSystemVariables()
|
|
284
296
|
const err = () => {
|
|
285
297
|
throw new ImplementationException()
|
|
286
298
|
}
|
|
287
299
|
return await acceptFieldVisitor(this.schema, entity, relation, {
|
|
288
300
|
visitManyHasManyOwning: ({ entity, relation }) => {
|
|
289
|
-
return this.junctionTableManager.disconnectJunction(this
|
|
301
|
+
return this.junctionTableManager.disconnectJunction(this, entity, relation, thisPrimary, otherPrimary)
|
|
290
302
|
},
|
|
291
303
|
visitManyHasManyInverse: ({ targetEntity, targetRelation }) => {
|
|
292
|
-
return this.junctionTableManager.disconnectJunction(this
|
|
304
|
+
return this.junctionTableManager.disconnectJunction(this, targetEntity, targetRelation, otherPrimary, thisPrimary)
|
|
293
305
|
},
|
|
294
306
|
visitColumn: err,
|
|
295
307
|
visitOneHasMany: err,
|
|
@@ -323,6 +335,12 @@ export class Mapper {
|
|
|
323
335
|
private hashWhere(entityName: string, where: Input.UniqueWhere): string {
|
|
324
336
|
return JSON.stringify([entityName, where])
|
|
325
337
|
}
|
|
326
|
-
}
|
|
327
338
|
|
|
328
|
-
|
|
339
|
+
private async setupSystemVariables() {
|
|
340
|
+
this.systemVariablesSetupDone ??= (async () => {
|
|
341
|
+
await this.db.query('SELECT set_config(?, ?, false)', ['tenant.identity_id', this.identityId]) // todo rename to system.identity_id
|
|
342
|
+
await this.db.query('SELECT set_config(?, ?, false)', ['system.transaction_id', this.transactionId])
|
|
343
|
+
})()
|
|
344
|
+
await this.systemVariablesSetupDone
|
|
345
|
+
}
|
|
346
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { PredicatesInjector } from '../acl'
|
|
2
|
+
import { PathFactory, SelectBuilderFactory, WhereBuilder } from './select'
|
|
3
|
+
import { UniqueWhereExpander } from '../inputProcessing'
|
|
4
|
+
import { JunctionTableManager } from './JunctionTableManager'
|
|
5
|
+
import { DeleteExecutor } from './delete'
|
|
6
|
+
import { Updater } from './update'
|
|
7
|
+
import { Inserter } from './insert'
|
|
8
|
+
import { Model } from '@contember/schema'
|
|
9
|
+
import { Client, Connection } from '@contember/database'
|
|
10
|
+
import { Mapper } from './Mapper'
|
|
11
|
+
import { Providers } from '@contember/schema-utils'
|
|
12
|
+
|
|
13
|
+
export type MapperFactoryHook = (mapper: Mapper) => void
|
|
14
|
+
|
|
15
|
+
export class MapperFactory {
|
|
16
|
+
|
|
17
|
+
public readonly hooks: MapperFactoryHook[] = []
|
|
18
|
+
|
|
19
|
+
constructor(
|
|
20
|
+
private readonly db: Client,
|
|
21
|
+
private readonly identityId: string,
|
|
22
|
+
private readonly schema: Model.Schema,
|
|
23
|
+
private readonly predicatesInjector: PredicatesInjector,
|
|
24
|
+
private readonly selectBuilderFactory: SelectBuilderFactory,
|
|
25
|
+
private readonly uniqueWhereExpander: UniqueWhereExpander,
|
|
26
|
+
private readonly whereBuilder: WhereBuilder,
|
|
27
|
+
private readonly junctionTableManager: JunctionTableManager,
|
|
28
|
+
private readonly deleteExecutor: DeleteExecutor,
|
|
29
|
+
private readonly updater: Updater,
|
|
30
|
+
private readonly inserter: Inserter,
|
|
31
|
+
private readonly pathFactory: PathFactory,
|
|
32
|
+
private readonly providers: Providers,
|
|
33
|
+
) {
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public create() {
|
|
37
|
+
return this.createInternal(this.db)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public transaction<T>(cb: (mapper: Mapper<Connection.TransactionLike>) => Promise<T>): Promise<T> {
|
|
41
|
+
return this.db.transaction(async trx => {
|
|
42
|
+
await trx.connection.query(Connection.REPEATABLE_READ)
|
|
43
|
+
const mapper = this.createInternal(trx)
|
|
44
|
+
return await cb(mapper)
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private createInternal<T extends Connection.ConnectionLike>(db: Client<T>) {
|
|
49
|
+
const mapper = new Mapper<T>(
|
|
50
|
+
db,
|
|
51
|
+
this.identityId,
|
|
52
|
+
this.providers.uuid(),
|
|
53
|
+
this.schema,
|
|
54
|
+
this.predicatesInjector,
|
|
55
|
+
this.selectBuilderFactory,
|
|
56
|
+
this.uniqueWhereExpander,
|
|
57
|
+
this.whereBuilder,
|
|
58
|
+
this.junctionTableManager,
|
|
59
|
+
this.deleteExecutor,
|
|
60
|
+
this.updater,
|
|
61
|
+
this.inserter,
|
|
62
|
+
this.pathFactory,
|
|
63
|
+
)
|
|
64
|
+
this.hooks.forEach(it => it(mapper))
|
|
65
|
+
return mapper
|
|
66
|
+
}
|
|
67
|
+
}
|
package/src/mapper/Result.ts
CHANGED
|
@@ -50,7 +50,7 @@ interface MutationResultInterface {
|
|
|
50
50
|
hints: MutationResultHint[]
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
export type RowValues = { [fieldName: string]: Value.
|
|
53
|
+
export type RowValues = { [fieldName: string]: Value.FieldValue }
|
|
54
54
|
|
|
55
55
|
export class MutationUpdateOk implements MutationResultInterface {
|
|
56
56
|
result = MutationResultType.ok as const
|
|
@@ -63,6 +63,7 @@ export class MutationUpdateOk implements MutationResultInterface {
|
|
|
63
63
|
public readonly primary: Value.PrimaryValue,
|
|
64
64
|
public readonly input: Input.UpdateDataInput,
|
|
65
65
|
public readonly values: RowValues,
|
|
66
|
+
public readonly oldValues?: RowValues,
|
|
66
67
|
) {}
|
|
67
68
|
}
|
|
68
69
|
|
|
@@ -26,6 +26,8 @@ import {
|
|
|
26
26
|
OneHasOneOwningRelationTuple,
|
|
27
27
|
} from './helpers'
|
|
28
28
|
import { getEntity } from '@contember/schema-utils'
|
|
29
|
+
import { AfterUpdateEvent, BeforeDeleteEvent, BeforeUpdateEvent, EventManager } from '../EventManager'
|
|
30
|
+
import { ImplementationException } from '../../exception'
|
|
29
31
|
|
|
30
32
|
type DeleteQueue = [entity: Model.Entity, ids: Input.PrimaryValue[]][]
|
|
31
33
|
|
|
@@ -67,7 +69,46 @@ export class DeleteExecutor {
|
|
|
67
69
|
if (!state.isOk()) {
|
|
68
70
|
return state.getResult()
|
|
69
71
|
}
|
|
72
|
+
const result = state.getResult()
|
|
73
|
+
const entryToEventMap = new Map<MutationUpdateOk, BeforeUpdateEvent>()
|
|
74
|
+
for (const entry of result) {
|
|
75
|
+
if (entry instanceof MutationDeleteOk) {
|
|
76
|
+
await mapper.eventManager.fire(new BeforeDeleteEvent(entry.entity, entry.primary))
|
|
77
|
+
} else if (entry instanceof MutationUpdateOk) {
|
|
78
|
+
const beforeUpdateEvent = new BeforeUpdateEvent(entry.entity, [{
|
|
79
|
+
columnName: Object.keys(entry.values)[0],
|
|
80
|
+
fieldName: Object.keys(entry.input)[0],
|
|
81
|
+
columnType: 'text',
|
|
82
|
+
resolvedValue: null,
|
|
83
|
+
value: Promise.resolve(null),
|
|
84
|
+
}], entry.primary)
|
|
85
|
+
entryToEventMap.set(entry, beforeUpdateEvent)
|
|
86
|
+
await mapper.eventManager.fire(beforeUpdateEvent)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
70
90
|
await this.executeDeletes(deleteQueue, mapper.db)
|
|
91
|
+
|
|
92
|
+
for (const entry of result) {
|
|
93
|
+
if (entry instanceof MutationUpdateOk) {
|
|
94
|
+
const beforeEvent = entryToEventMap.get(entry)
|
|
95
|
+
if (!beforeEvent) {
|
|
96
|
+
throw new ImplementationException()
|
|
97
|
+
}
|
|
98
|
+
const data = [{
|
|
99
|
+
columnName: Object.keys(entry.values)[0],
|
|
100
|
+
fieldName: Object.keys(entry.input)[0],
|
|
101
|
+
columnType: 'text',
|
|
102
|
+
resolvedValue: null,
|
|
103
|
+
value: Promise.resolve(null),
|
|
104
|
+
old: Object.values(entry.oldValues ?? {})[0],
|
|
105
|
+
}]
|
|
106
|
+
const afterEvent = new AfterUpdateEvent(entry.entity, data, entry.primary)
|
|
107
|
+
beforeEvent.afterEvent = afterEvent
|
|
108
|
+
await mapper.eventManager.fire(afterEvent)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
71
112
|
state.confirmDeleted()
|
|
72
113
|
|
|
73
114
|
return state.getResult()
|
|
@@ -190,7 +231,7 @@ export class DeleteExecutor {
|
|
|
190
231
|
const input = { [relation.name]: { disconnect: true } }
|
|
191
232
|
const values = { [relation.joiningColumn.columnName]: null }
|
|
192
233
|
|
|
193
|
-
state.pushOkResult(result.map(it =>
|
|
234
|
+
state.pushOkResult(result.map(it => new MutationUpdateOk([], entity, it.id, input, values, { [relation.joiningColumn.columnName]: it.ref })))
|
|
194
235
|
return
|
|
195
236
|
}
|
|
196
237
|
|
package/src/mapper/index.ts
CHANGED
|
@@ -5,9 +5,11 @@ export * from './update'
|
|
|
5
5
|
export * from './ColumnValue'
|
|
6
6
|
export * from './Constraints'
|
|
7
7
|
export * from './ErrorUtils'
|
|
8
|
+
export * from './EventManager'
|
|
8
9
|
export * from './JunctionTableManager'
|
|
9
10
|
export * from './Mapper'
|
|
10
|
-
export * from '
|
|
11
|
+
export * from '../ExecutionContainer'
|
|
12
|
+
export * from './MapperFactory'
|
|
11
13
|
export * from './MutationProcessorHelper'
|
|
12
14
|
export * from './Result'
|
|
13
15
|
export * from './types'
|
|
@@ -6,6 +6,8 @@ import { ColumnValue, ResolvedColumnValue, resolveGenericValue, resolveRowData }
|
|
|
6
6
|
import { ImplementationException } from '../../exception'
|
|
7
7
|
import { PredicateFactory } from '../../acl'
|
|
8
8
|
import { AbortDataManipulation, DataManipulationBuilder } from '../DataManipulationBuilder'
|
|
9
|
+
import { AfterInsertEvent, BeforeInsertEvent, EventManager } from '../EventManager'
|
|
10
|
+
import { Mapper } from '../Mapper'
|
|
9
11
|
|
|
10
12
|
export interface InsertResult {
|
|
11
13
|
values: ResolvedColumnValue[]
|
|
@@ -55,7 +57,7 @@ export class InsertBuilder implements DataManipulationBuilder {
|
|
|
55
57
|
return resolveRowData([...this.rowData.values()])
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
public async execute(
|
|
60
|
+
public async execute(mapper: Mapper): Promise<InsertResult> {
|
|
59
61
|
try {
|
|
60
62
|
const resolvedData = await this.getResolvedData()
|
|
61
63
|
if (resolvedData.find(it => it.resolvedValue === AbortDataManipulation)) {
|
|
@@ -83,8 +85,16 @@ export class InsertBuilder implements DataManipulationBuilder {
|
|
|
83
85
|
})
|
|
84
86
|
.returning(this.entity.primaryColumn)
|
|
85
87
|
|
|
86
|
-
const
|
|
88
|
+
const beforeInsertEvent = new BeforeInsertEvent(this.entity, resolvedData as ResolvedColumnValue[])
|
|
89
|
+
await mapper.eventManager.fire(beforeInsertEvent)
|
|
90
|
+
|
|
91
|
+
const returning = (await qb.execute(mapper.db)).map(it => it[this.entity.primaryColumn])
|
|
87
92
|
const result = returning.length === 1 ? returning[0] : null
|
|
93
|
+
|
|
94
|
+
const afterInsertEvent = new AfterInsertEvent(this.entity, resolvedData as ResolvedColumnValue[], result)
|
|
95
|
+
beforeInsertEvent.afterEvent = afterInsertEvent
|
|
96
|
+
await mapper.eventManager.fire(afterInsertEvent)
|
|
97
|
+
|
|
88
98
|
this.resolver(result)
|
|
89
99
|
return { values: resolvedData as ResolvedColumnValue[], executed: true, primaryValue: result, aborted: false }
|
|
90
100
|
} catch (e) {
|
|
@@ -51,18 +51,18 @@ export class Inserter {
|
|
|
51
51
|
|
|
52
52
|
const okResultFactory = (primary: Value.PrimaryValue, values: RowValues) =>
|
|
53
53
|
new MutationCreateOk([], entity, primary, data, values)
|
|
54
|
-
const insertPromise = this.executeInsert(insertBuilder, mapper
|
|
54
|
+
const insertPromise = this.executeInsert(insertBuilder, mapper, okResultFactory)
|
|
55
55
|
|
|
56
56
|
return await collectResults(this.schema, insertPromise, Object.values(promises))
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
private async executeInsert(
|
|
60
60
|
insertBuilder: InsertBuilder,
|
|
61
|
-
|
|
61
|
+
mapper: Mapper,
|
|
62
62
|
okResultFactory: (primary: Value.PrimaryValue, values: RowValues) => MutationCreateOk,
|
|
63
63
|
): Promise<MutationResultList> {
|
|
64
64
|
return tryMutation(this.schema, async () => {
|
|
65
|
-
const result = await insertBuilder.execute(
|
|
65
|
+
const result = await insertBuilder.execute(mapper)
|
|
66
66
|
if (result.aborted) {
|
|
67
67
|
return [new MutationNothingToDo([], NothingToDoReason.aborted)]
|
|
68
68
|
}
|
|
@@ -5,10 +5,11 @@ export class OrderByHelper {
|
|
|
5
5
|
public static appendDefaultOrderBy(
|
|
6
6
|
entity: Model.Entity,
|
|
7
7
|
objectNode: ObjectNode<Input.ListQueryInput>,
|
|
8
|
-
|
|
8
|
+
relationOrderBy: readonly Model.OrderBy[] | undefined,
|
|
9
9
|
): ObjectNode<Input.ListQueryInput> {
|
|
10
10
|
const inputOrder = objectNode.args.orderBy || []
|
|
11
11
|
const hasOrderBy = inputOrder.length > 0
|
|
12
|
+
const defaultOrderBy = relationOrderBy ?? entity.orderBy ?? []
|
|
12
13
|
if (!hasOrderBy && defaultOrderBy.length > 0) {
|
|
13
14
|
const defaultOrderByWithPrimary = [...defaultOrderBy, ...this.getPrimaryOrderBy(inputOrder, entity)]
|
|
14
15
|
return objectNode.withArg('orderBy', this.buildOrderBy(defaultOrderByWithPrimary))
|
|
@@ -83,7 +83,7 @@ export class RelationFetcher {
|
|
|
83
83
|
const objectNodeWithOrder = OrderByHelper.appendDefaultOrderBy(
|
|
84
84
|
targetEntity,
|
|
85
85
|
objectNodeWithWhere,
|
|
86
|
-
relation.orderBy
|
|
86
|
+
relation.orderBy,
|
|
87
87
|
)
|
|
88
88
|
|
|
89
89
|
return mapper.selectGrouped(targetEntity, objectNodeWithOrder, targetRelation, [
|
|
@@ -144,7 +144,7 @@ export class RelationFetcher {
|
|
|
144
144
|
}: FetchManyHasManyGroupsArgs): Promise<SelectGroupedObjects> {
|
|
145
145
|
const owningRelation = relationContext.type === 'manyHasManyInverse' ? relationContext.targetRelation : relationContext.relation
|
|
146
146
|
const joiningColumns = this.resolveJoiningColumns({ relationType: relationContext.type, joiningTable: owningRelation.joiningTable })
|
|
147
|
-
const defaultOrderBy = relationContext.relation.orderBy
|
|
147
|
+
const defaultOrderBy = relationContext.relation.orderBy
|
|
148
148
|
const objectNode = OrderByHelper.appendDefaultOrderBy(relationContext.targetEntity, field, defaultOrderBy)
|
|
149
149
|
const { targetEntity } = relationContext
|
|
150
150
|
const junctionValues = await this.fetchJunction(
|
|
@@ -6,6 +6,8 @@ import { PathFactory, WhereBuilder } from '../select'
|
|
|
6
6
|
import { ColumnValue, ResolvedColumnValue, resolveGenericValue, resolveRowData } from '../ColumnValue'
|
|
7
7
|
import { PredicateFactory } from '../../acl'
|
|
8
8
|
import { AbortDataManipulation, DataManipulationBuilder } from '../DataManipulationBuilder'
|
|
9
|
+
import { AfterUpdateEvent, BeforeUpdateEvent, EventManager } from '../EventManager'
|
|
10
|
+
import { Mapper } from '../Mapper'
|
|
9
11
|
|
|
10
12
|
export interface UpdateResult {
|
|
11
13
|
values: ResolvedColumnValue[]
|
|
@@ -29,7 +31,7 @@ export class UpdateBuilder implements DataManipulationBuilder {
|
|
|
29
31
|
private readonly schema: Model.Schema,
|
|
30
32
|
private readonly entity: Model.Entity,
|
|
31
33
|
private readonly whereBuilder: WhereBuilder,
|
|
32
|
-
private readonly
|
|
34
|
+
private readonly primary: Input.PrimaryValue,
|
|
33
35
|
private readonly pathFactory: PathFactory,
|
|
34
36
|
private readonly predicateFactory: PredicateFactory,
|
|
35
37
|
) {}
|
|
@@ -59,7 +61,7 @@ export class UpdateBuilder implements DataManipulationBuilder {
|
|
|
59
61
|
this.addOldWhere(predicate)
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
public async execute(
|
|
64
|
+
public async execute(mapper: Mapper): Promise<UpdateResult> {
|
|
63
65
|
try {
|
|
64
66
|
const resolvedData = await resolveRowData<AbortDataManipulation>([...this.rowData.values()])
|
|
65
67
|
if (Object.keys(resolvedData).length === 0) {
|
|
@@ -70,12 +72,15 @@ export class UpdateBuilder implements DataManipulationBuilder {
|
|
|
70
72
|
this.resolver(null)
|
|
71
73
|
return { values: [], affectedRows: null, executed: false, aborted: true }
|
|
72
74
|
}
|
|
75
|
+
const oldColSuffix = '_old__'
|
|
73
76
|
|
|
74
77
|
const qb = DbUpdateBuilder.create()
|
|
75
78
|
.with('newData_', qb => {
|
|
76
79
|
qb = resolvedData.reduce(
|
|
77
80
|
(qb, value) =>
|
|
78
|
-
qb
|
|
81
|
+
qb
|
|
82
|
+
.select(expr => expr.selectValue(value.resolvedValue as DbValue, value.columnType), value.columnName)
|
|
83
|
+
.select(['root_', value.columnName], value.columnName + oldColSuffix),
|
|
79
84
|
qb,
|
|
80
85
|
)
|
|
81
86
|
const columns = new Set(resolvedData.map(it => it.columnName))
|
|
@@ -97,7 +102,9 @@ export class UpdateBuilder implements DataManipulationBuilder {
|
|
|
97
102
|
qb = remainingColumns.reduce((qb, columnName) => qb.select(['root_', columnName]), qb)
|
|
98
103
|
|
|
99
104
|
qb = this.whereBuilder.build(qb, this.entity, this.pathFactory.create([]), {
|
|
100
|
-
and: [
|
|
105
|
+
and: [{
|
|
106
|
+
[this.entity.primary]: { eq: this.primary },
|
|
107
|
+
}, this.oldWhere],
|
|
101
108
|
})
|
|
102
109
|
|
|
103
110
|
return qb
|
|
@@ -112,6 +119,7 @@ export class UpdateBuilder implements DataManipulationBuilder {
|
|
|
112
119
|
{},
|
|
113
120
|
),
|
|
114
121
|
)
|
|
122
|
+
.returning(...resolvedData.map(it => it.columnName + oldColSuffix))
|
|
115
123
|
.from(qb => {
|
|
116
124
|
qb = qb.from('newData_')
|
|
117
125
|
const col1 = tuple(this.entity.tableName, this.entity.primaryColumn)
|
|
@@ -121,9 +129,24 @@ export class UpdateBuilder implements DataManipulationBuilder {
|
|
|
121
129
|
return qb
|
|
122
130
|
})
|
|
123
131
|
|
|
124
|
-
|
|
125
|
-
this.
|
|
126
|
-
|
|
132
|
+
|
|
133
|
+
const beforeEvent = new BeforeUpdateEvent(this.entity, resolvedData as ResolvedColumnValue[], this.primary)
|
|
134
|
+
await mapper.eventManager.fire(beforeEvent)
|
|
135
|
+
|
|
136
|
+
const result = await qb.execute(mapper.db)
|
|
137
|
+
this.resolver(result.length)
|
|
138
|
+
|
|
139
|
+
if (result.length === 1) {
|
|
140
|
+
const eventData = (resolvedData as ResolvedColumnValue[]).map(it => ({
|
|
141
|
+
...it,
|
|
142
|
+
old: result[0][it.columnName + oldColSuffix],
|
|
143
|
+
}))
|
|
144
|
+
const afterUpdateEvent = new AfterUpdateEvent(this.entity, eventData, this.primary)
|
|
145
|
+
beforeEvent.afterEvent = afterUpdateEvent
|
|
146
|
+
await mapper.eventManager.fire(afterUpdateEvent)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return { values: resolvedData as ResolvedColumnValue[], affectedRows: result.length, executed: true, aborted: false }
|
|
127
150
|
} catch (e) {
|
|
128
151
|
this.resolver(null)
|
|
129
152
|
throw e
|
|
@@ -11,12 +11,12 @@ export class UpdateBuilderFactory {
|
|
|
11
11
|
private readonly predicateFactory: PredicateFactory,
|
|
12
12
|
) {}
|
|
13
13
|
|
|
14
|
-
public create(entity: Model.Entity,
|
|
14
|
+
public create(entity: Model.Entity, primary: Input.PrimaryValue): UpdateBuilder {
|
|
15
15
|
return new UpdateBuilder(
|
|
16
16
|
this.schema,
|
|
17
17
|
entity,
|
|
18
18
|
this.whereBuilder,
|
|
19
|
-
|
|
19
|
+
primary,
|
|
20
20
|
this.pathFactory,
|
|
21
21
|
this.predicateFactory,
|
|
22
22
|
)
|
|
@@ -5,7 +5,6 @@ import { PredicateFactory } from '../../acl'
|
|
|
5
5
|
import { UpdateBuilderFactory } from './UpdateBuilderFactory'
|
|
6
6
|
import { Mapper } from '../Mapper'
|
|
7
7
|
import { acceptEveryFieldVisitor } from '@contember/schema-utils'
|
|
8
|
-
import { Client } from '@contember/database'
|
|
9
8
|
import {
|
|
10
9
|
collectResults,
|
|
11
10
|
MutationNoResultError,
|
|
@@ -33,9 +32,7 @@ export class Updater {
|
|
|
33
32
|
data: Input.UpdateDataInput,
|
|
34
33
|
filter?: Input.OptionalWhere,
|
|
35
34
|
): Promise<MutationResultList> {
|
|
36
|
-
const updateBuilder = this.updateBuilderFactory.create(entity,
|
|
37
|
-
[entity.primary]: { eq: primaryValue },
|
|
38
|
-
})
|
|
35
|
+
const updateBuilder = this.updateBuilderFactory.create(entity, primaryValue)
|
|
39
36
|
|
|
40
37
|
const predicateFields = Object.keys(data)
|
|
41
38
|
updateBuilder.addPredicates(predicateFields)
|
|
@@ -48,7 +45,7 @@ export class Updater {
|
|
|
48
45
|
const promises = acceptEveryFieldVisitor<Promise<ResultListNotFlatten | undefined>>(this.schema, entity, visitor)
|
|
49
46
|
|
|
50
47
|
const okResultFactory = (values: RowValues) => new MutationUpdateOk([], entity, primaryValue, data, values)
|
|
51
|
-
const mutationResultPromise = Updater.executeUpdate(updateBuilder, mapper
|
|
48
|
+
const mutationResultPromise = Updater.executeUpdate(updateBuilder, mapper, okResultFactory)
|
|
52
49
|
const otherPromises = Object.values(promises)
|
|
53
50
|
if (otherPromises.length === 0) {
|
|
54
51
|
return await mutationResultPromise
|
|
@@ -63,22 +60,20 @@ export class Updater {
|
|
|
63
60
|
primaryValue: Input.PrimaryValue,
|
|
64
61
|
builderCb: (builder: UpdateBuilder) => void,
|
|
65
62
|
): Promise<MutationResultList> {
|
|
66
|
-
const updateBuilder = this.updateBuilderFactory.create(entity,
|
|
67
|
-
[entity.primary]: { eq: primaryValue },
|
|
68
|
-
})
|
|
63
|
+
const updateBuilder = this.updateBuilderFactory.create(entity, primaryValue)
|
|
69
64
|
|
|
70
65
|
const okResultFactory = (values: RowValues) => new MutationUpdateOk([], entity, primaryValue, {}, values)
|
|
71
66
|
builderCb(updateBuilder)
|
|
72
67
|
|
|
73
|
-
return Updater.executeUpdate(updateBuilder, mapper
|
|
68
|
+
return Updater.executeUpdate(updateBuilder, mapper, okResultFactory)
|
|
74
69
|
}
|
|
75
70
|
|
|
76
71
|
private static async executeUpdate(
|
|
77
72
|
updateBuilder: UpdateBuilder,
|
|
78
|
-
|
|
73
|
+
mapper: Mapper,
|
|
79
74
|
okResultFactory: (values: RowValues) => MutationUpdateOk,
|
|
80
75
|
): Promise<MutationResultList> {
|
|
81
|
-
const result = await updateBuilder.execute(
|
|
76
|
+
const result = await updateBuilder.execute(mapper)
|
|
82
77
|
if (result.aborted) {
|
|
83
78
|
return [new MutationNothingToDo([], NothingToDoReason.aborted)]
|
|
84
79
|
}
|
|
@@ -19,7 +19,6 @@ type NodeFilter = (node: GraphQlFieldNode, path: string[]) => boolean
|
|
|
19
19
|
type AnyNode = ObjectNode | FieldNode
|
|
20
20
|
|
|
21
21
|
export class GraphQlQueryAstFactory {
|
|
22
|
-
constructor(private readonly argumentValuesResolver: typeof getArgumentValues) {}
|
|
23
22
|
|
|
24
23
|
public create<Args = any>(info: GraphQLResolveInfo, filter?: NodeFilter): ObjectNode<Args> {
|
|
25
24
|
const node = ResolveInfoUtils.extractFieldNode(info)
|
|
@@ -53,7 +52,7 @@ export class GraphQlQueryAstFactory {
|
|
|
53
52
|
name,
|
|
54
53
|
alias,
|
|
55
54
|
fields,
|
|
56
|
-
|
|
55
|
+
getArgumentValues(field, node, info.variableValues),
|
|
57
56
|
field.extensions || {},
|
|
58
57
|
path,
|
|
59
58
|
)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Input, Model, Result, Value } from '@contember/schema'
|
|
2
2
|
import {
|
|
3
|
+
AfterCommitEvent,
|
|
4
|
+
BeforeCommitEvent,
|
|
3
5
|
ConstraintType,
|
|
4
6
|
getInsertPrimary,
|
|
5
7
|
InputErrorKind,
|
|
@@ -14,7 +16,7 @@ import { ValidationResolver } from './ValidationResolver'
|
|
|
14
16
|
import { GraphQLResolveInfo } from 'graphql'
|
|
15
17
|
import { GraphQlQueryAstFactory } from './GraphQlQueryAstFactory'
|
|
16
18
|
import { ImplementationException } from '../exception'
|
|
17
|
-
import {
|
|
19
|
+
import { retryTransaction } from '@contember/database'
|
|
18
20
|
import { Operation, readOperationMeta } from '../schema'
|
|
19
21
|
import { assertNever } from '../utils'
|
|
20
22
|
import { InputPreValidator } from '../input-validation'
|
|
@@ -29,9 +31,7 @@ type TransactionOptions = { deferForeignKeyConstraints?: boolean }
|
|
|
29
31
|
export class MutationResolver {
|
|
30
32
|
constructor(
|
|
31
33
|
private readonly schema: Model.Schema,
|
|
32
|
-
private readonly db: Client,
|
|
33
34
|
private readonly mapperFactory: MapperFactory,
|
|
34
|
-
private readonly systemVariablesSetup: (db: Client) => Promise<void>,
|
|
35
35
|
private readonly inputValidator: InputPreValidator,
|
|
36
36
|
private readonly graphqlQueryAstFactory: GraphQlQueryAstFactory,
|
|
37
37
|
) {}
|
|
@@ -60,7 +60,7 @@ export class MutationResolver {
|
|
|
60
60
|
: undefined,
|
|
61
61
|
}))
|
|
62
62
|
|
|
63
|
-
return this.transaction(async
|
|
63
|
+
return this.transaction(async mapper => {
|
|
64
64
|
if (options?.deferForeignKeyConstraints) {
|
|
65
65
|
logger.debug('MutationResolver: deferring foreign constraints')
|
|
66
66
|
await mapper.constraintHelper.setFkConstraintsDeferred()
|
|
@@ -468,25 +468,24 @@ export class MutationResolver {
|
|
|
468
468
|
}
|
|
469
469
|
|
|
470
470
|
private async transaction<R extends { ok: boolean }>(
|
|
471
|
-
cb: (mapper: Mapper
|
|
471
|
+
cb: (mapper: Mapper) => Promise<R>,
|
|
472
472
|
): Promise<R> {
|
|
473
473
|
return await retryTransaction(
|
|
474
474
|
async () => {
|
|
475
|
-
|
|
475
|
+
const [result, mapper] = await this.mapperFactory.transaction(async mapper => {
|
|
476
476
|
logger.debug('MutationResolver: Starting mutation transaction')
|
|
477
|
-
await
|
|
478
|
-
await this.systemVariablesSetup(trx)
|
|
479
|
-
const mapper = this.mapperFactory(trx)
|
|
480
|
-
|
|
481
|
-
const result = await cb(mapper, trx)
|
|
477
|
+
const result = await cb(mapper)
|
|
482
478
|
if (!result.ok) {
|
|
483
479
|
logger.debug('MutationResolver: Transaction failed, rolling back', { result })
|
|
484
|
-
await
|
|
480
|
+
await mapper.db.connection.rollback()
|
|
485
481
|
} else {
|
|
486
482
|
logger.debug('MutationResolver: Transaction ok, committing')
|
|
487
483
|
}
|
|
488
|
-
|
|
484
|
+
await mapper.eventManager.fire(new BeforeCommitEvent())
|
|
485
|
+
return [result, mapper]
|
|
489
486
|
})
|
|
487
|
+
await mapper.eventManager.fire(new AfterCommitEvent())
|
|
488
|
+
return result
|
|
490
489
|
},
|
|
491
490
|
message => logger.warn(message),
|
|
492
491
|
{
|