@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.
Files changed (263) hide show
  1. package/dist/src/ExecutionContainer.d.ts +141 -0
  2. package/dist/src/ExecutionContainer.d.ts.map +1 -0
  3. package/dist/src/ExecutionContainer.js +84 -0
  4. package/dist/src/ExecutionContainer.js.map +1 -0
  5. package/dist/src/index.d.ts +2 -1
  6. package/dist/src/index.d.ts.map +1 -1
  7. package/dist/src/index.js +18 -2
  8. package/dist/src/index.js.map +1 -1
  9. package/dist/src/mapper/ColumnValue.d.ts +2 -2
  10. package/dist/src/mapper/ColumnValue.d.ts.map +1 -1
  11. package/dist/src/mapper/EventManager.d.ts +86 -0
  12. package/dist/src/mapper/EventManager.d.ts.map +1 -0
  13. package/dist/src/mapper/EventManager.js +118 -0
  14. package/dist/src/mapper/EventManager.js.map +1 -0
  15. package/dist/src/mapper/JunctionTableManager.d.ts +12 -11
  16. package/dist/src/mapper/JunctionTableManager.d.ts.map +1 -1
  17. package/dist/src/mapper/JunctionTableManager.js +20 -8
  18. package/dist/src/mapper/JunctionTableManager.js.map +1 -1
  19. package/dist/src/mapper/Mapper.d.ts +11 -6
  20. package/dist/src/mapper/Mapper.d.ts.map +1 -1
  21. package/dist/src/mapper/Mapper.js +34 -17
  22. package/dist/src/mapper/Mapper.js.map +1 -1
  23. package/dist/src/mapper/MapperFactory.d.ts +33 -0
  24. package/dist/src/mapper/MapperFactory.d.ts.map +1 -0
  25. package/dist/src/mapper/MapperFactory.js +40 -0
  26. package/dist/src/mapper/MapperFactory.js.map +1 -0
  27. package/dist/src/mapper/Result.d.ts +3 -2
  28. package/dist/src/mapper/Result.d.ts.map +1 -1
  29. package/dist/src/mapper/Result.js +2 -1
  30. package/dist/src/mapper/Result.js.map +1 -1
  31. package/dist/src/mapper/delete/DeleteExecutor.d.ts.map +1 -1
  32. package/dist/src/mapper/delete/DeleteExecutor.js +41 -1
  33. package/dist/src/mapper/delete/DeleteExecutor.js.map +1 -1
  34. package/dist/src/mapper/index.d.ts +3 -1
  35. package/dist/src/mapper/index.d.ts.map +1 -1
  36. package/dist/src/mapper/index.js +3 -1
  37. package/dist/src/mapper/index.js.map +1 -1
  38. package/dist/src/mapper/insert/InsertBuilder.d.ts +2 -2
  39. package/dist/src/mapper/insert/InsertBuilder.d.ts.map +1 -1
  40. package/dist/src/mapper/insert/InsertBuilder.js +8 -2
  41. package/dist/src/mapper/insert/InsertBuilder.js.map +1 -1
  42. package/dist/src/mapper/insert/Inserter.js +3 -3
  43. package/dist/src/mapper/insert/Inserter.js.map +1 -1
  44. package/dist/src/mapper/select/OrderByHelper.d.ts +1 -1
  45. package/dist/src/mapper/select/OrderByHelper.d.ts.map +1 -1
  46. package/dist/src/mapper/select/OrderByHelper.js +3 -1
  47. package/dist/src/mapper/select/OrderByHelper.js.map +1 -1
  48. package/dist/src/mapper/select/RelationFetcher.js +2 -2
  49. package/dist/src/mapper/select/RelationFetcher.js.map +1 -1
  50. package/dist/src/mapper/update/UpdateBuilder.d.ts +4 -4
  51. package/dist/src/mapper/update/UpdateBuilder.d.ts.map +1 -1
  52. package/dist/src/mapper/update/UpdateBuilder.js +26 -8
  53. package/dist/src/mapper/update/UpdateBuilder.js.map +1 -1
  54. package/dist/src/mapper/update/UpdateBuilderFactory.d.ts +1 -1
  55. package/dist/src/mapper/update/UpdateBuilderFactory.d.ts.map +1 -1
  56. package/dist/src/mapper/update/UpdateBuilderFactory.js +2 -2
  57. package/dist/src/mapper/update/UpdateBuilderFactory.js.map +1 -1
  58. package/dist/src/mapper/update/Updater.d.ts.map +1 -1
  59. package/dist/src/mapper/update/Updater.js +6 -10
  60. package/dist/src/mapper/update/Updater.js.map +1 -1
  61. package/dist/src/resolvers/GraphQlQueryAstFactory.d.ts +1 -3
  62. package/dist/src/resolvers/GraphQlQueryAstFactory.d.ts.map +1 -1
  63. package/dist/src/resolvers/GraphQlQueryAstFactory.js +1 -4
  64. package/dist/src/resolvers/GraphQlQueryAstFactory.js.map +1 -1
  65. package/dist/src/resolvers/MutationResolver.d.ts +1 -4
  66. package/dist/src/resolvers/MutationResolver.d.ts.map +1 -1
  67. package/dist/src/resolvers/MutationResolver.js +9 -11
  68. package/dist/src/resolvers/MutationResolver.js.map +1 -1
  69. package/dist/src/resolvers/ReadResolver.d.ts +1 -3
  70. package/dist/src/resolvers/ReadResolver.d.ts.map +1 -1
  71. package/dist/src/resolvers/ReadResolver.js +6 -10
  72. package/dist/src/resolvers/ReadResolver.js.map +1 -1
  73. package/dist/src/resolvers/ValidationResolver.d.ts +1 -3
  74. package/dist/src/resolvers/ValidationResolver.d.ts.map +1 -1
  75. package/dist/src/resolvers/ValidationResolver.js +3 -4
  76. package/dist/src/resolvers/ValidationResolver.js.map +1 -1
  77. package/dist/src/resolvers/index.d.ts +0 -1
  78. package/dist/src/resolvers/index.d.ts.map +1 -1
  79. package/dist/src/resolvers/index.js +0 -1
  80. package/dist/src/resolvers/index.js.map +1 -1
  81. package/dist/src/schema/CustomTypesProvider.d.ts.map +1 -1
  82. package/dist/src/schema/CustomTypesProvider.js +1 -23
  83. package/dist/src/schema/CustomTypesProvider.js.map +1 -1
  84. package/dist/src/schema/MutationProvider.js +4 -4
  85. package/dist/src/schema/MutationProvider.js.map +1 -1
  86. package/dist/src/schema/QueryProvider.js +3 -3
  87. package/dist/src/schema/QueryProvider.js.map +1 -1
  88. package/dist/src/tsconfig.tsbuildinfo +1 -1
  89. package/dist/src/types.d.ts +2 -3
  90. package/dist/src/types.d.ts.map +1 -1
  91. package/dist/tests/cases/bugs/bug-update-by-nested-unique.test.js +3 -5
  92. package/dist/tests/cases/bugs/bug-update-by-nested-unique.test.js.map +1 -1
  93. package/dist/tests/cases/integration/graphQlDb/insert/insertSequence.test.js +2 -2
  94. package/dist/tests/cases/integration/graphQlDb/insert/insertSequence.test.js.map +1 -1
  95. package/dist/tests/cases/integration/graphQlDb/update/bug-freeze-connect-missing-one.test.js +1 -1
  96. package/dist/tests/cases/integration/graphQlDb/update/bug-freeze-connect-missing-one.test.js.map +1 -1
  97. package/dist/tests/cases/integration/graphQlDb/update/deferedConstraints.test.js +45 -45
  98. package/dist/tests/cases/integration/graphQlDb/update/deferedConstraints.test.js.map +1 -1
  99. package/dist/tests/cases/integration/graphQlDb/update/failedDelete.test.js +5 -5
  100. package/dist/tests/cases/integration/graphQlDb/update/failedDelete.test.js.map +1 -1
  101. package/dist/tests/cases/integration/graphQlDb/update/invalidInput.test.js +2 -2
  102. package/dist/tests/cases/integration/graphQlDb/update/invalidInput.test.js.map +1 -1
  103. package/dist/tests/cases/integration/graphQlDb/update/nullChecksNotNull.test.js +7 -7
  104. package/dist/tests/cases/integration/graphQlDb/update/nullChecksNotNull.test.js.map +1 -1
  105. package/dist/tests/cases/integration/graphQlDb/update/nullChecksNullable.test.js +7 -7
  106. package/dist/tests/cases/integration/graphQlDb/update/nullChecksNullable.test.js.map +1 -1
  107. package/dist/tests/cases/integration/graphQlDb/update/uniqueConstraint.test.js +2 -2
  108. package/dist/tests/cases/integration/graphQlDb/update/uniqueConstraint.test.js.map +1 -1
  109. package/dist/tests/cases/integration/graphQlRequests/insert/oneHasMany/connect.test.js +3 -3
  110. package/dist/tests/cases/integration/graphQlRequests/insert/oneHasMany/connect.test.js.map +1 -1
  111. package/dist/tests/cases/integration/graphQlRequests/query/sorting/orderBy.test.d.ts +2 -0
  112. package/dist/tests/cases/integration/graphQlRequests/query/sorting/orderBy.test.d.ts.map +1 -0
  113. package/dist/tests/cases/integration/graphQlRequests/query/sorting/orderBy.test.js +67 -0
  114. package/dist/tests/cases/integration/graphQlRequests/query/sorting/orderBy.test.js.map +1 -0
  115. package/dist/tests/cases/integration/graphQlRequests/update/acl/aclUpdate.test.js +6 -18
  116. package/dist/tests/cases/integration/graphQlRequests/update/acl/aclUpdate.test.js.map +1 -1
  117. package/dist/tests/cases/integration/graphQlRequests/update/additionalFilter.test.js +3 -4
  118. package/dist/tests/cases/integration/graphQlRequests/update/additionalFilter.test.js.map +1 -1
  119. package/dist/tests/cases/integration/graphQlRequests/update/basic/columnUpdate.test.js +3 -8
  120. package/dist/tests/cases/integration/graphQlRequests/update/basic/columnUpdate.test.js.map +1 -1
  121. package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyInverse/update.test.js +3 -9
  122. package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyInverse/update.test.js.map +1 -1
  123. package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyInverse/upsert.test.js +3 -9
  124. package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyInverse/upsert.test.js.map +1 -1
  125. package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyOwning/update.test.js +3 -9
  126. package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyOwning/update.test.js.map +1 -1
  127. package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyOwning/upsert.test.js +3 -9
  128. package/dist/tests/cases/integration/graphQlRequests/update/manyHasManyOwning/upsert.test.js.map +1 -1
  129. package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/connect.test.js +3 -10
  130. package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/connect.test.js.map +1 -1
  131. package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/create.test.js +3 -10
  132. package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/create.test.js.map +1 -1
  133. package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/disconnect.test.js +3 -9
  134. package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/disconnect.test.js.map +1 -1
  135. package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/update.test.js +3 -9
  136. package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/update.test.js.map +1 -1
  137. package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/upsert.test.js +6 -18
  138. package/dist/tests/cases/integration/graphQlRequests/update/manyHasOne/upsert.test.js.map +1 -1
  139. package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/connect.test.js +3 -11
  140. package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/connect.test.js.map +1 -1
  141. package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/disconnect.test.js +3 -8
  142. package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/disconnect.test.js.map +1 -1
  143. package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/update.test.js +3 -6
  144. package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/update.test.js.map +1 -1
  145. package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/upsert.test.js +3 -6
  146. package/dist/tests/cases/integration/graphQlRequests/update/oneHasMany/upsert.test.js.map +1 -1
  147. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/connect.test.js +15 -50
  148. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/connect.test.js.map +1 -1
  149. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/create.test.js +3 -10
  150. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/create.test.js.map +1 -1
  151. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/disconnect.test.js +3 -10
  152. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/disconnect.test.js.map +1 -1
  153. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/update.test.js +3 -6
  154. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/update.test.js.map +1 -1
  155. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/upsert.test.js +3 -7
  156. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/upsert.test.js.map +1 -1
  157. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/connect.test.js +12 -32
  158. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/connect.test.js.map +1 -1
  159. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/connectOrCreate.test.js +3 -3
  160. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/connectOrCreate.test.js.map +1 -1
  161. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/create.test.js +6 -20
  162. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/create.test.js.map +1 -1
  163. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/disconnect.test.js +3 -10
  164. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/disconnect.test.js.map +1 -1
  165. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/update.test.js +3 -9
  166. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/update.test.js.map +1 -1
  167. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/upsert.test.js +6 -19
  168. package/dist/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/upsert.test.js.map +1 -1
  169. package/dist/tests/cases/integration/graphQlRequests/update/queryPortal.test.js +6 -8
  170. package/dist/tests/cases/integration/graphQlRequests/update/queryPortal.test.js.map +1 -1
  171. package/dist/tests/cases/integration/graphQlRequests/update/transaction.test.js +9 -24
  172. package/dist/tests/cases/integration/graphQlRequests/update/transaction.test.js.map +1 -1
  173. package/dist/tests/cases/integration/graphQlRequests/upsert/basicUpsert.test.js +3 -7
  174. package/dist/tests/cases/integration/graphQlRequests/upsert/basicUpsert.test.js.map +1 -1
  175. package/dist/tests/cases/unit/orderbyHelper.test.js +11 -0
  176. package/dist/tests/cases/unit/orderbyHelper.test.js.map +1 -1
  177. package/dist/tests/src/test.d.ts +1 -0
  178. package/dist/tests/src/test.d.ts.map +1 -1
  179. package/dist/tests/src/test.js +34 -6
  180. package/dist/tests/src/test.js.map +1 -1
  181. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  182. package/package.json +11 -11
  183. package/src/ExecutionContainer.ts +204 -0
  184. package/src/index.ts +24 -1
  185. package/src/mapper/ColumnValue.ts +2 -2
  186. package/src/mapper/EventManager.ts +158 -0
  187. package/src/mapper/JunctionTableManager.ts +50 -32
  188. package/src/mapper/Mapper.ts +39 -21
  189. package/src/mapper/MapperFactory.ts +67 -0
  190. package/src/mapper/Result.ts +2 -1
  191. package/src/mapper/delete/DeleteExecutor.ts +42 -1
  192. package/src/mapper/index.ts +3 -1
  193. package/src/mapper/insert/InsertBuilder.ts +12 -2
  194. package/src/mapper/insert/Inserter.ts +3 -3
  195. package/src/mapper/select/OrderByHelper.ts +2 -1
  196. package/src/mapper/select/RelationFetcher.ts +2 -2
  197. package/src/mapper/update/UpdateBuilder.ts +30 -7
  198. package/src/mapper/update/UpdateBuilderFactory.ts +2 -2
  199. package/src/mapper/update/Updater.ts +6 -11
  200. package/src/resolvers/GraphQlQueryAstFactory.ts +1 -2
  201. package/src/resolvers/MutationResolver.ts +12 -13
  202. package/src/resolvers/ReadResolver.ts +5 -9
  203. package/src/resolvers/ValidationResolver.ts +2 -4
  204. package/src/resolvers/index.ts +0 -1
  205. package/src/schema/CustomTypesProvider.ts +2 -27
  206. package/src/schema/MutationProvider.ts +4 -4
  207. package/src/schema/QueryProvider.ts +3 -3
  208. package/src/tsconfig.json +7 -21
  209. package/src/types.ts +2 -3
  210. package/tests/cases/bugs/bug-update-by-nested-unique.test.ts +3 -5
  211. package/tests/cases/integration/graphQlDb/insert/insertSequence.test.ts +2 -2
  212. package/tests/cases/integration/graphQlDb/update/bug-freeze-connect-missing-one.test.ts +1 -1
  213. package/tests/cases/integration/graphQlDb/update/deferedConstraints.test.ts +9 -9
  214. package/tests/cases/integration/graphQlDb/update/failedDelete.test.ts +3 -3
  215. package/tests/cases/integration/graphQlDb/update/invalidInput.test.ts +2 -2
  216. package/tests/cases/integration/graphQlDb/update/nullChecksNotNull.test.ts +7 -7
  217. package/tests/cases/integration/graphQlDb/update/nullChecksNullable.test.ts +7 -7
  218. package/tests/cases/integration/graphQlDb/update/uniqueConstraint.test.ts +2 -2
  219. package/tests/cases/integration/graphQlRequests/insert/oneHasMany/connect.test.ts +3 -3
  220. package/tests/cases/integration/graphQlRequests/query/sorting/orderBy.test.ts +67 -0
  221. package/tests/cases/integration/graphQlRequests/update/acl/aclUpdate.test.ts +6 -18
  222. package/tests/cases/integration/graphQlRequests/update/additionalFilter.test.ts +3 -4
  223. package/tests/cases/integration/graphQlRequests/update/basic/columnUpdate.test.ts +3 -8
  224. package/tests/cases/integration/graphQlRequests/update/manyHasManyInverse/update.test.ts +3 -9
  225. package/tests/cases/integration/graphQlRequests/update/manyHasManyInverse/upsert.test.ts +3 -9
  226. package/tests/cases/integration/graphQlRequests/update/manyHasManyOwning/update.test.ts +3 -9
  227. package/tests/cases/integration/graphQlRequests/update/manyHasManyOwning/upsert.test.ts +3 -9
  228. package/tests/cases/integration/graphQlRequests/update/manyHasOne/connect.test.ts +3 -10
  229. package/tests/cases/integration/graphQlRequests/update/manyHasOne/create.test.ts +3 -10
  230. package/tests/cases/integration/graphQlRequests/update/manyHasOne/disconnect.test.ts +3 -9
  231. package/tests/cases/integration/graphQlRequests/update/manyHasOne/update.test.ts +3 -9
  232. package/tests/cases/integration/graphQlRequests/update/manyHasOne/upsert.test.ts +6 -18
  233. package/tests/cases/integration/graphQlRequests/update/oneHasMany/connect.test.ts +3 -11
  234. package/tests/cases/integration/graphQlRequests/update/oneHasMany/disconnect.test.ts +3 -8
  235. package/tests/cases/integration/graphQlRequests/update/oneHasMany/update.test.ts +3 -6
  236. package/tests/cases/integration/graphQlRequests/update/oneHasMany/upsert.test.ts +3 -6
  237. package/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/connect.test.ts +15 -50
  238. package/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/create.test.ts +3 -10
  239. package/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/disconnect.test.ts +3 -10
  240. package/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/update.test.ts +3 -6
  241. package/tests/cases/integration/graphQlRequests/update/oneHasOneInverse/upsert.test.ts +3 -7
  242. package/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/connect.test.ts +12 -32
  243. package/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/connectOrCreate.test.ts +3 -3
  244. package/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/create.test.ts +6 -20
  245. package/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/disconnect.test.ts +3 -10
  246. package/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/update.test.ts +3 -9
  247. package/tests/cases/integration/graphQlRequests/update/oneHasOneOwning/upsert.test.ts +6 -19
  248. package/tests/cases/integration/graphQlRequests/update/queryPortal.test.ts +6 -8
  249. package/tests/cases/integration/graphQlRequests/update/transaction.test.ts +9 -24
  250. package/tests/cases/integration/graphQlRequests/upsert/basicUpsert.test.ts +3 -7
  251. package/tests/cases/unit/orderbyHelper.test.ts +13 -0
  252. package/tests/src/test.ts +38 -15
  253. package/tests/tsconfig.json +3 -9
  254. package/dist/src/mapper/MapperContainer.d.ts +0 -18
  255. package/dist/src/mapper/MapperContainer.d.ts.map +0 -1
  256. package/dist/src/mapper/MapperContainer.js +0 -55
  257. package/dist/src/mapper/MapperContainer.js.map +0 -1
  258. package/dist/src/resolvers/ExecutionContainerFactory.d.ts +0 -24
  259. package/dist/src/resolvers/ExecutionContainerFactory.d.ts.map +0 -1
  260. package/dist/src/resolvers/ExecutionContainerFactory.js +0 -45
  261. package/dist/src/resolvers/ExecutionContainerFactory.js.map +0 -1
  262. package/src/mapper/MapperContainer.ts +0 -142
  263. package/src/resolvers/ExecutionContainerFactory.ts +0 -74
@@ -10,8 +10,7 @@ import {
10
10
  SelectResultObject,
11
11
  WhereBuilder,
12
12
  } from './select'
13
- import * as database from '@contember/database'
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
- const pushId = (id: string) => {
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.inserter.insert(this, entity, data, pushId, builderCb),
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
- const pushIdCallback = (id: string) => {
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.db, entity, relation, thisPrimary, otherPrimary)
276
+ return this.junctionTableManager.connectJunction(this, entity, relation, thisPrimary, otherPrimary)
266
277
  },
267
278
  visitManyHasManyInverse: ({ targetEntity, targetRelation }) => {
268
- return this.junctionTableManager.connectJunction(this.db, targetEntity, targetRelation, otherPrimary, thisPrimary)
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.db, entity, relation, thisPrimary, otherPrimary)
301
+ return this.junctionTableManager.disconnectJunction(this, entity, relation, thisPrimary, otherPrimary)
290
302
  },
291
303
  visitManyHasManyInverse: ({ targetEntity, targetRelation }) => {
292
- return this.junctionTableManager.disconnectJunction(this.db, targetEntity, targetRelation, otherPrimary, thisPrimary)
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
- export type MapperFactory = (db: Client) => Mapper
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
+ }
@@ -50,7 +50,7 @@ interface MutationResultInterface {
50
50
  hints: MutationResultHint[]
51
51
  }
52
52
 
53
- export type RowValues = { [fieldName: string]: Value.AtomicValue }
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 => it.id).map(id => new MutationUpdateOk([], entity, id, input, values)))
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
 
@@ -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 './MapperContainer'
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(db: Client): Promise<InsertResult> {
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 returning = (await qb.execute(db)).map(it => it[this.entity.primaryColumn])
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.db, okResultFactory)
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
- db: Client,
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(db)
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
- defaultOrderBy: readonly Model.OrderBy[],
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 uniqueWhere: Input.Where,
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(db: Client): Promise<UpdateResult> {
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.select(expr => expr.selectValue(value.resolvedValue as DbValue, value.columnType), value.columnName),
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: [this.uniqueWhere, this.oldWhere],
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
- const result = await qb.execute(db)
125
- this.resolver(result)
126
- return { values: resolvedData as ResolvedColumnValue[], affectedRows: result, executed: true, aborted: false }
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, uniqueWhere: Input.Where): UpdateBuilder {
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
- uniqueWhere,
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.db, okResultFactory)
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.db, okResultFactory)
68
+ return Updater.executeUpdate(updateBuilder, mapper, okResultFactory)
74
69
  }
75
70
 
76
71
  private static async executeUpdate(
77
72
  updateBuilder: UpdateBuilder,
78
- db: Client,
73
+ mapper: Mapper,
79
74
  okResultFactory: (values: RowValues) => MutationUpdateOk,
80
75
  ): Promise<MutationResultList> {
81
- const result = await updateBuilder.execute(db)
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
- this.argumentValuesResolver(field, node, info.variableValues),
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 { Client, Connection, retryTransaction } from '@contember/database'
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 (mapper, trx) => {
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, db: Client<Connection.TransactionLike>) => Promise<R>,
471
+ cb: (mapper: Mapper) => Promise<R>,
472
472
  ): Promise<R> {
473
473
  return await retryTransaction(
474
474
  async () => {
475
- return await this.db.transaction(async trx => {
475
+ const [result, mapper] = await this.mapperFactory.transaction(async mapper => {
476
476
  logger.debug('MutationResolver: Starting mutation transaction')
477
- await trx.connection.query(Connection.REPEATABLE_READ)
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 trx.connection.rollback()
480
+ await mapper.db.connection.rollback()
485
481
  } else {
486
482
  logger.debug('MutationResolver: Transaction ok, committing')
487
483
  }
488
- return result
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
  {