@expo/entity 0.34.0 → 0.36.0

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 (333) hide show
  1. package/build/AuthorizationResultBasedEntityLoader.d.ts +128 -0
  2. package/build/AuthorizationResultBasedEntityLoader.js +196 -0
  3. package/build/AuthorizationResultBasedEntityLoader.js.map +1 -0
  4. package/build/ComposedEntityCacheAdapter.js +1 -0
  5. package/build/ComposedEntityCacheAdapter.js.map +1 -1
  6. package/build/ComposedSecondaryEntityCache.js +1 -0
  7. package/build/ComposedSecondaryEntityCache.js.map +1 -1
  8. package/build/EnforcingEntityLoader.d.ts +5 -4
  9. package/build/EnforcingEntityLoader.js +4 -2
  10. package/build/EnforcingEntityLoader.js.map +1 -1
  11. package/build/Entity.d.ts +4 -31
  12. package/build/Entity.js +19 -46
  13. package/build/Entity.js.map +1 -1
  14. package/build/EntityAssociationLoader.d.ts +9 -9
  15. package/build/EntityAssociationLoader.js +37 -12
  16. package/build/EntityAssociationLoader.js.map +1 -1
  17. package/build/EntityCompanion.js +9 -1
  18. package/build/EntityCompanion.js.map +1 -1
  19. package/build/EntityCompanionProvider.d.ts +3 -1
  20. package/build/EntityCompanionProvider.js +10 -4
  21. package/build/EntityCompanionProvider.js.map +1 -1
  22. package/build/EntityConfiguration.d.ts +2 -1
  23. package/build/EntityConfiguration.js +19 -1
  24. package/build/EntityConfiguration.js.map +1 -1
  25. package/build/EntityDatabaseAdapter.d.ts +2 -2
  26. package/build/EntityDatabaseAdapter.js +5 -3
  27. package/build/EntityDatabaseAdapter.js.map +1 -1
  28. package/build/EntityFieldDefinition.d.ts +21 -10
  29. package/build/EntityFieldDefinition.js +8 -9
  30. package/build/EntityFieldDefinition.js.map +1 -1
  31. package/build/EntityFields.d.ts +10 -0
  32. package/build/EntityFields.js +15 -1
  33. package/build/EntityFields.js.map +1 -1
  34. package/build/EntityLoader.d.ts +12 -125
  35. package/build/EntityLoader.js +24 -239
  36. package/build/EntityLoader.js.map +1 -1
  37. package/build/EntityLoaderFactory.d.ts +1 -1
  38. package/build/EntityLoaderFactory.js +3 -0
  39. package/build/EntityLoaderFactory.js.map +1 -1
  40. package/build/EntityLoaderUtils.d.ts +58 -0
  41. package/build/EntityLoaderUtils.js +109 -0
  42. package/build/EntityLoaderUtils.js.map +1 -0
  43. package/build/EntityMutator.d.ts +1 -0
  44. package/build/EntityMutator.js +71 -56
  45. package/build/EntityMutator.js.map +1 -1
  46. package/build/EntityMutatorFactory.js +9 -0
  47. package/build/EntityMutatorFactory.js.map +1 -1
  48. package/build/EntityPrivacyPolicy.d.ts +11 -5
  49. package/build/EntityPrivacyPolicy.js +5 -7
  50. package/build/EntityPrivacyPolicy.js.map +1 -1
  51. package/build/EntityQueryContext.d.ts +2 -1
  52. package/build/EntityQueryContext.js +11 -6
  53. package/build/EntityQueryContext.js.map +1 -1
  54. package/build/EntityQueryContextProvider.d.ts +1 -1
  55. package/build/EntityQueryContextProvider.js +1 -1
  56. package/build/EntityQueryContextProvider.js.map +1 -1
  57. package/build/EntitySecondaryCacheLoader.js +5 -1
  58. package/build/EntitySecondaryCacheLoader.js.map +1 -1
  59. package/build/GenericEntityCacheAdapter.js +1 -0
  60. package/build/GenericEntityCacheAdapter.js.map +1 -1
  61. package/build/GenericSecondaryEntityCache.js +2 -0
  62. package/build/GenericSecondaryEntityCache.js.map +1 -1
  63. package/build/IEntityCacheAdapterProvider.d.ts +1 -1
  64. package/build/IEntityDatabaseAdapterProvider.d.ts +1 -1
  65. package/build/ReadonlyEntity.d.ts +1 -1
  66. package/build/ReadonlyEntity.js +9 -2
  67. package/build/ReadonlyEntity.js.map +1 -1
  68. package/build/ViewerContext.d.ts +2 -2
  69. package/build/ViewerContext.js +5 -3
  70. package/build/ViewerContext.js.map +1 -1
  71. package/build/ViewerScopedEntityCompanion.js +2 -0
  72. package/build/ViewerScopedEntityCompanion.js.map +1 -1
  73. package/build/ViewerScopedEntityCompanionProvider.d.ts +0 -1
  74. package/build/ViewerScopedEntityCompanionProvider.js +2 -1
  75. package/build/ViewerScopedEntityCompanionProvider.js.map +1 -1
  76. package/build/ViewerScopedEntityLoaderFactory.d.ts +1 -1
  77. package/build/ViewerScopedEntityLoaderFactory.js +2 -0
  78. package/build/ViewerScopedEntityLoaderFactory.js.map +1 -1
  79. package/build/ViewerScopedEntityMutatorFactory.js +2 -0
  80. package/build/ViewerScopedEntityMutatorFactory.js.map +1 -1
  81. package/build/__tests__/ComposedCacheAdapter-test.js +2 -0
  82. package/build/__tests__/ComposedCacheAdapter-test.js.map +1 -1
  83. package/build/__tests__/ComposedSecondaryEntityCache-test.js +1 -0
  84. package/build/__tests__/ComposedSecondaryEntityCache-test.js.map +1 -1
  85. package/build/__tests__/EnforcingEntityLoader-test.js +101 -113
  86. package/build/__tests__/EnforcingEntityLoader-test.js.map +1 -1
  87. package/build/__tests__/Entity-test.js +5 -137
  88. package/build/__tests__/Entity-test.js.map +1 -1
  89. package/build/__tests__/EntityAssociationLoader-test.js +37 -65
  90. package/build/__tests__/EntityAssociationLoader-test.js.map +1 -1
  91. package/build/__tests__/EntityCommonUseCases-test.js +31 -37
  92. package/build/__tests__/EntityCommonUseCases-test.js.map +1 -1
  93. package/build/__tests__/EntityCompanion-test.js +26 -3
  94. package/build/__tests__/EntityCompanion-test.js.map +1 -1
  95. package/build/__tests__/EntityConfiguration-test.js +103 -0
  96. package/build/__tests__/EntityConfiguration-test.js.map +1 -0
  97. package/build/__tests__/EntityDatabaseAdapter-test.js +6 -0
  98. package/build/__tests__/EntityDatabaseAdapter-test.js.map +1 -1
  99. package/build/__tests__/EntityEdges-test.js +89 -80
  100. package/build/__tests__/EntityEdges-test.js.map +1 -1
  101. package/build/__tests__/EntityFields-test.js +6 -0
  102. package/build/__tests__/EntityFields-test.js.map +1 -1
  103. package/build/__tests__/EntityLoader-constructor-test.js +17 -18
  104. package/build/__tests__/EntityLoader-constructor-test.js.map +1 -1
  105. package/build/__tests__/EntityLoader-test.js +93 -41
  106. package/build/__tests__/EntityLoader-test.js.map +1 -1
  107. package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js +18 -21
  108. package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js.map +1 -1
  109. package/build/__tests__/EntityMutator-test.js +74 -29
  110. package/build/__tests__/EntityMutator-test.js.map +1 -1
  111. package/build/__tests__/EntityPrivacyPolicy-test.js +77 -59
  112. package/build/__tests__/EntityPrivacyPolicy-test.js.map +1 -1
  113. package/build/__tests__/EntityQueryContext-test.js +9 -0
  114. package/build/__tests__/EntityQueryContext-test.js.map +1 -1
  115. package/build/__tests__/EntitySecondaryCacheLoader-test.js +10 -10
  116. package/build/__tests__/EntitySecondaryCacheLoader-test.js.map +1 -1
  117. package/build/__tests__/EntitySelfReferentialEdges-test.js +59 -74
  118. package/build/__tests__/EntitySelfReferentialEdges-test.js.map +1 -1
  119. package/build/__tests__/ReadonlyEntity-test.js +13 -13
  120. package/build/__tests__/ReadonlyEntity-test.js.map +1 -1
  121. package/build/__tests__/ViewerContext-test.js +2 -2
  122. package/build/__tests__/ViewerContext-test.js.map +1 -1
  123. package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js.map +1 -1
  124. package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js +26 -28
  125. package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js.map +1 -1
  126. package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js +25 -30
  127. package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js.map +1 -1
  128. package/build/entityUtils.d.ts +1 -1
  129. package/build/entityUtils.js.map +1 -1
  130. package/build/errors/EntityCacheAdapterError.js +2 -5
  131. package/build/errors/EntityCacheAdapterError.js.map +1 -1
  132. package/build/errors/EntityDatabaseAdapterError.js +14 -35
  133. package/build/errors/EntityDatabaseAdapterError.js.map +1 -1
  134. package/build/errors/EntityError.js +1 -0
  135. package/build/errors/EntityError.js.map +1 -1
  136. package/build/errors/EntityInvalidFieldValueError.js +2 -2
  137. package/build/errors/EntityInvalidFieldValueError.js.map +1 -1
  138. package/build/errors/EntityNotAuthorizedError.js +3 -2
  139. package/build/errors/EntityNotAuthorizedError.js.map +1 -1
  140. package/build/errors/EntityNotFoundError.js +2 -2
  141. package/build/errors/EntityNotFoundError.js.map +1 -1
  142. package/build/index.d.ts +1 -0
  143. package/build/index.js +1 -0
  144. package/build/index.js.map +1 -1
  145. package/build/internal/EntityDataManager.d.ts +1 -1
  146. package/build/internal/EntityDataManager.js +7 -2
  147. package/build/internal/EntityDataManager.js.map +1 -1
  148. package/build/internal/EntityFieldTransformationUtils.d.ts +5 -5
  149. package/build/internal/EntityFieldTransformationUtils.js +5 -8
  150. package/build/internal/EntityFieldTransformationUtils.js.map +1 -1
  151. package/build/internal/EntityTableDataCoordinator.d.ts +1 -1
  152. package/build/internal/EntityTableDataCoordinator.js +5 -0
  153. package/build/internal/EntityTableDataCoordinator.js.map +1 -1
  154. package/build/internal/ReadThroughEntityCache.d.ts +1 -1
  155. package/build/internal/ReadThroughEntityCache.js +2 -0
  156. package/build/internal/ReadThroughEntityCache.js.map +1 -1
  157. package/build/internal/__tests__/EntityDataManager-test.js +11 -11
  158. package/build/internal/__tests__/EntityDataManager-test.js.map +1 -1
  159. package/build/internal/__tests__/EntityFieldTransformationUtils-test.js +6 -2
  160. package/build/internal/__tests__/EntityFieldTransformationUtils-test.js.map +1 -1
  161. package/build/internal/__tests__/ReadThroughEntityCache-test.js +33 -0
  162. package/build/internal/__tests__/ReadThroughEntityCache-test.js.map +1 -1
  163. package/build/metrics/IEntityMetricsAdapter.d.ts +1 -1
  164. package/build/rules/AlwaysAllowPrivacyPolicyRule.d.ts +1 -1
  165. package/build/rules/AlwaysAllowPrivacyPolicyRule.js.map +1 -1
  166. package/build/rules/AlwaysDenyPrivacyPolicyRule.d.ts +1 -1
  167. package/build/rules/AlwaysDenyPrivacyPolicyRule.js.map +1 -1
  168. package/build/rules/AlwaysSkipPrivacyPolicyRule.d.ts +1 -1
  169. package/build/rules/AlwaysSkipPrivacyPolicyRule.js.map +1 -1
  170. package/build/rules/PrivacyPolicyRule.d.ts +1 -1
  171. package/build/rules/PrivacyPolicyRule.js.map +1 -1
  172. package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js.map +1 -1
  173. package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js.map +1 -1
  174. package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js.map +1 -1
  175. package/build/testfixtures/DateIDTestEntity.js +12 -15
  176. package/build/testfixtures/DateIDTestEntity.js.map +1 -1
  177. package/build/testfixtures/SimpleTestEntity.d.ts +8 -8
  178. package/build/testfixtures/SimpleTestEntity.js +12 -15
  179. package/build/testfixtures/SimpleTestEntity.js.map +1 -1
  180. package/build/testfixtures/TestEntity.d.ts +12 -12
  181. package/build/testfixtures/TestEntity.js +12 -15
  182. package/build/testfixtures/TestEntity.js.map +1 -1
  183. package/build/testfixtures/TestEntity2.d.ts +8 -8
  184. package/build/testfixtures/TestEntity2.js +12 -15
  185. package/build/testfixtures/TestEntity2.js.map +1 -1
  186. package/build/testfixtures/TestEntityNumberKey.js +12 -15
  187. package/build/testfixtures/TestEntityNumberKey.js.map +1 -1
  188. package/build/testfixtures/TestEntityWithMutationTriggers.d.ts +36 -0
  189. package/build/testfixtures/TestEntityWithMutationTriggers.js +82 -0
  190. package/build/testfixtures/TestEntityWithMutationTriggers.js.map +1 -0
  191. package/build/testfixtures/TestViewerContext.d.ts +0 -3
  192. package/build/testfixtures/TestViewerContext.js +0 -6
  193. package/build/testfixtures/TestViewerContext.js.map +1 -1
  194. package/build/utils/EntityPrivacyUtils.d.ts +34 -0
  195. package/build/utils/EntityPrivacyUtils.js +160 -0
  196. package/build/utils/EntityPrivacyUtils.js.map +1 -0
  197. package/build/utils/__tests__/EntityPrivacyUtils-test.d.ts +1 -0
  198. package/build/utils/__tests__/EntityPrivacyUtils-test.js +395 -0
  199. package/build/utils/__tests__/EntityPrivacyUtils-test.js.map +1 -0
  200. package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.d.ts +1 -0
  201. package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.js +26 -0
  202. package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.js.map +1 -0
  203. package/build/utils/collections/maps.js.map +1 -1
  204. package/build/utils/mergeEntityMutationTriggerConfigurations.d.ts +4 -0
  205. package/build/utils/mergeEntityMutationTriggerConfigurations.js +28 -0
  206. package/build/utils/mergeEntityMutationTriggerConfigurations.js.map +1 -0
  207. package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +1 -1
  208. package/build/utils/testing/PrivacyPolicyRuleTestUtils.js.map +1 -1
  209. package/build/utils/testing/StubCacheAdapter.d.ts +3 -3
  210. package/build/utils/testing/StubCacheAdapter.js +3 -3
  211. package/build/utils/testing/StubCacheAdapter.js.map +1 -1
  212. package/build/utils/testing/StubDatabaseAdapter.d.ts +2 -2
  213. package/build/utils/testing/StubDatabaseAdapter.js +4 -2
  214. package/build/utils/testing/StubDatabaseAdapter.js.map +1 -1
  215. package/build/utils/testing/StubDatabaseAdapterProvider.d.ts +1 -1
  216. package/build/utils/testing/StubDatabaseAdapterProvider.js +1 -3
  217. package/build/utils/testing/StubDatabaseAdapterProvider.js.map +1 -1
  218. package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.d.ts +1 -0
  219. package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.js +42 -0
  220. package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.js.map +1 -0
  221. package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js +53 -0
  222. package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js.map +1 -1
  223. package/build/utils/testing/describeFieldTestCase.js.map +1 -1
  224. package/package.json +4 -3
  225. package/src/AuthorizationResultBasedEntityLoader.ts +297 -0
  226. package/src/ComposedEntityCacheAdapter.ts +6 -6
  227. package/src/ComposedSecondaryEntityCache.ts +8 -8
  228. package/src/EnforcingEntityLoader.ts +20 -19
  229. package/src/Entity.ts +26 -118
  230. package/src/EntityAssociationLoader.ts +56 -41
  231. package/src/EntityCompanion.ts +8 -4
  232. package/src/EntityCompanionProvider.ts +24 -16
  233. package/src/EntityConfiguration.ts +18 -7
  234. package/src/EntityDatabaseAdapter.ts +41 -41
  235. package/src/EntityFieldDefinition.ts +28 -18
  236. package/src/EntityFields.ts +15 -0
  237. package/src/EntityLoader.ts +63 -357
  238. package/src/EntityLoaderFactory.ts +10 -4
  239. package/src/EntityLoaderUtils.ts +149 -0
  240. package/src/EntityMutationInfo.ts +2 -2
  241. package/src/EntityMutationTriggerConfiguration.ts +5 -5
  242. package/src/EntityMutationValidator.ts +2 -2
  243. package/src/EntityMutator.ts +146 -144
  244. package/src/EntityMutatorFactory.ts +8 -8
  245. package/src/EntityPrivacyPolicy.ts +78 -28
  246. package/src/EntityQueryContext.ts +14 -13
  247. package/src/EntityQueryContextProvider.ts +6 -6
  248. package/src/EntitySecondaryCacheLoader.ts +13 -11
  249. package/src/GenericEntityCacheAdapter.ts +10 -10
  250. package/src/GenericSecondaryEntityCache.ts +6 -6
  251. package/src/IEntityCacheAdapter.ts +4 -4
  252. package/src/IEntityCacheAdapterProvider.ts +2 -2
  253. package/src/IEntityDatabaseAdapterProvider.ts +2 -2
  254. package/src/ReadonlyEntity.ts +8 -5
  255. package/src/ViewerContext.ts +10 -10
  256. package/src/ViewerScopedEntityCompanion.ts +4 -4
  257. package/src/ViewerScopedEntityCompanionProvider.ts +4 -5
  258. package/src/ViewerScopedEntityLoaderFactory.ts +10 -4
  259. package/src/ViewerScopedEntityMutatorFactory.ts +5 -5
  260. package/src/__tests__/ComposedCacheAdapter-test.ts +12 -10
  261. package/src/__tests__/ComposedSecondaryEntityCache-test.ts +8 -8
  262. package/src/__tests__/EnforcingEntityLoader-test.ts +236 -159
  263. package/src/__tests__/Entity-test.ts +5 -223
  264. package/src/__tests__/EntityAssociationLoader-test.ts +91 -169
  265. package/src/__tests__/EntityCommonUseCases-test.ts +36 -38
  266. package/src/__tests__/EntityCompanion-test.ts +57 -5
  267. package/src/__tests__/EntityConfiguration-test.ts +118 -0
  268. package/src/__tests__/EntityDatabaseAdapter-test.ts +11 -11
  269. package/src/__tests__/EntityEdges-test.ts +128 -118
  270. package/src/__tests__/EntityFields-test.ts +14 -2
  271. package/src/__tests__/EntityLoader-constructor-test.ts +21 -8
  272. package/src/__tests__/EntityLoader-test.ts +233 -105
  273. package/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts +17 -20
  274. package/src/__tests__/EntityMutator-test.ts +342 -163
  275. package/src/__tests__/EntityPrivacyPolicy-test.ts +166 -53
  276. package/src/__tests__/EntityQueryContext-test.ts +30 -12
  277. package/src/__tests__/EntitySecondaryCacheLoader-test.ts +17 -26
  278. package/src/__tests__/EntitySelfReferentialEdges-test.ts +67 -115
  279. package/src/__tests__/GenericEntityCacheAdapter-test.ts +2 -2
  280. package/src/__tests__/ReadonlyEntity-test.ts +13 -15
  281. package/src/__tests__/ViewerContext-test.ts +3 -4
  282. package/src/__tests__/ViewerScopedEntityCompanion-test.ts +2 -2
  283. package/src/__tests__/ViewerScopedEntityCompanionProvider-test.ts +2 -2
  284. package/src/__tests__/ViewerScopedEntityLoaderFactory-test.ts +2 -1
  285. package/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts +34 -45
  286. package/src/__tests__/cases/TwoEntitySameTableOverlappingRows-test.ts +22 -30
  287. package/src/__tests__/entityUtils-test.ts +2 -2
  288. package/src/entityUtils.ts +4 -4
  289. package/src/errors/EntityError.ts +4 -1
  290. package/src/errors/EntityInvalidFieldValueError.ts +2 -2
  291. package/src/errors/EntityNotAuthorizedError.ts +3 -3
  292. package/src/errors/EntityNotFoundError.ts +2 -2
  293. package/src/index.ts +1 -0
  294. package/src/internal/EntityDataManager.ts +25 -25
  295. package/src/internal/EntityFieldTransformationUtils.ts +39 -32
  296. package/src/internal/EntityTableDataCoordinator.ts +3 -3
  297. package/src/internal/ReadThroughEntityCache.ts +9 -9
  298. package/src/internal/__tests__/EntityDataManager-test.ts +62 -62
  299. package/src/internal/__tests__/EntityFieldTransformationUtils-test.ts +14 -10
  300. package/src/internal/__tests__/ReadThroughEntityCache-test.ts +74 -18
  301. package/src/metrics/EntityMetricsUtils.ts +4 -4
  302. package/src/metrics/IEntityMetricsAdapter.ts +1 -1
  303. package/src/rules/AlwaysAllowPrivacyPolicyRule.ts +9 -3
  304. package/src/rules/AlwaysDenyPrivacyPolicyRule.ts +9 -3
  305. package/src/rules/AlwaysSkipPrivacyPolicyRule.ts +9 -3
  306. package/src/rules/PrivacyPolicyRule.ts +9 -3
  307. package/src/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.ts +2 -1
  308. package/src/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.ts +2 -1
  309. package/src/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.ts +2 -1
  310. package/src/testfixtures/SimpleTestEntity.ts +8 -8
  311. package/src/testfixtures/TestEntity.ts +13 -16
  312. package/src/testfixtures/TestEntity2.ts +8 -8
  313. package/src/testfixtures/TestEntityWithMutationTriggers.ts +156 -0
  314. package/src/testfixtures/TestViewerContext.ts +1 -12
  315. package/src/utils/EntityPrivacyUtils.ts +325 -0
  316. package/src/utils/__tests__/EntityPrivacyUtils-test.ts +570 -0
  317. package/src/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.ts +29 -0
  318. package/src/utils/collections/__tests__/maps-test.ts +2 -2
  319. package/src/utils/collections/maps.ts +11 -11
  320. package/src/utils/mergeEntityMutationTriggerConfigurations.ts +44 -0
  321. package/src/utils/testing/PrivacyPolicyRuleTestUtils.ts +25 -22
  322. package/src/utils/testing/StubCacheAdapter.ts +17 -15
  323. package/src/utils/testing/StubDatabaseAdapter.ts +35 -30
  324. package/src/utils/testing/StubDatabaseAdapterProvider.ts +2 -2
  325. package/src/utils/testing/StubQueryContextProvider.ts +2 -2
  326. package/src/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.ts +42 -0
  327. package/src/utils/testing/__tests__/StubDatabaseAdapter-test.ts +111 -29
  328. package/src/utils/testing/createUnitTestEntityCompanionProvider.ts +2 -2
  329. package/src/utils/testing/describeFieldTestCase.ts +1 -1
  330. package/build/__tests__/EntityDataConfiguration-test.js +0 -68
  331. package/build/__tests__/EntityDataConfiguration-test.js.map +0 -1
  332. package/src/__tests__/EntityDataConfiguration-test.ts +0 -77
  333. /package/build/__tests__/{EntityDataConfiguration-test.d.ts → EntityConfiguration-test.d.ts} +0 -0
@@ -0,0 +1,297 @@
1
+ import { Result, result } from '@expo/results';
2
+ import invariant from 'invariant';
3
+ import nullthrows from 'nullthrows';
4
+
5
+ import { IEntityClass } from './Entity';
6
+ import EntityConfiguration from './EntityConfiguration';
7
+ import {
8
+ FieldEqualityCondition,
9
+ QuerySelectionModifiers,
10
+ isSingleValueFieldEqualityCondition,
11
+ QuerySelectionModifiersWithOrderByRaw,
12
+ } from './EntityDatabaseAdapter';
13
+ import EntityLoaderUtils from './EntityLoaderUtils';
14
+ import EntityPrivacyPolicy from './EntityPrivacyPolicy';
15
+ import { EntityQueryContext } from './EntityQueryContext';
16
+ import ReadonlyEntity from './ReadonlyEntity';
17
+ import ViewerContext from './ViewerContext';
18
+ import EntityInvalidFieldValueError from './errors/EntityInvalidFieldValueError';
19
+ import EntityNotFoundError from './errors/EntityNotFoundError';
20
+ import EntityDataManager from './internal/EntityDataManager';
21
+ import IEntityMetricsAdapter from './metrics/IEntityMetricsAdapter';
22
+ import { mapMap } from './utils/collections/maps';
23
+
24
+ /**
25
+ * Authorization-result-based entity loader. All normal loads are batched,
26
+ * cached, and authorized against the entity's EntityPrivacyPolicy. All loads through this
27
+ * loader are are results (or null for some loader methods), where an unsuccessful result
28
+ * means an authorization error or entity construction error occurred. Other errors are thrown.
29
+ */
30
+ export default class AuthorizationResultBasedEntityLoader<
31
+ TFields extends object,
32
+ TID extends NonNullable<TFields[TSelectedFields]>,
33
+ TViewerContext extends ViewerContext,
34
+ TEntity extends ReadonlyEntity<TFields, TID, TViewerContext, TSelectedFields>,
35
+ TPrivacyPolicy extends EntityPrivacyPolicy<
36
+ TFields,
37
+ TID,
38
+ TViewerContext,
39
+ TEntity,
40
+ TSelectedFields
41
+ >,
42
+ TSelectedFields extends keyof TFields,
43
+ > {
44
+ constructor(
45
+ private readonly queryContext: EntityQueryContext,
46
+ private readonly entityConfiguration: EntityConfiguration<TFields>,
47
+ private readonly entityClass: IEntityClass<
48
+ TFields,
49
+ TID,
50
+ TViewerContext,
51
+ TEntity,
52
+ TPrivacyPolicy,
53
+ TSelectedFields
54
+ >,
55
+ private readonly dataManager: EntityDataManager<TFields>,
56
+ protected readonly metricsAdapter: IEntityMetricsAdapter,
57
+ private readonly utils: EntityLoaderUtils<
58
+ TFields,
59
+ TID,
60
+ TViewerContext,
61
+ TEntity,
62
+ TPrivacyPolicy,
63
+ TSelectedFields
64
+ >,
65
+ ) {}
66
+
67
+ /**
68
+ * Load many entities where fieldName is one of fieldValues.
69
+ * @param fieldName - entity field being queried
70
+ * @param fieldValues - fieldName field values being queried
71
+ * @returns map from fieldValue to entity results that match the query for that fieldValue,
72
+ * where result errors can be UnauthorizedError
73
+ */
74
+ async loadManyByFieldEqualingManyAsync<N extends keyof Pick<TFields, TSelectedFields>>(
75
+ fieldName: N,
76
+ fieldValues: readonly NonNullable<TFields[N]>[],
77
+ ): Promise<ReadonlyMap<NonNullable<TFields[N]>, readonly Result<TEntity>[]>> {
78
+ this.validateFieldValues(fieldName, fieldValues);
79
+
80
+ const fieldValuesToFieldObjects = await this.dataManager.loadManyByFieldEqualingAsync(
81
+ this.queryContext,
82
+ fieldName,
83
+ fieldValues,
84
+ );
85
+
86
+ return await this.utils.constructAndAuthorizeEntitiesAsync(fieldValuesToFieldObjects);
87
+ }
88
+
89
+ /**
90
+ * Load many entities where fieldName equals fieldValue.
91
+ * @param fieldName - entity field being queried
92
+ * @param fieldValue - fieldName field value being queried
93
+ * @returns array of entity results that match the query for fieldValue, where result error can be UnauthorizedError
94
+ */
95
+ async loadManyByFieldEqualingAsync<N extends keyof Pick<TFields, TSelectedFields>>(
96
+ fieldName: N,
97
+ fieldValue: NonNullable<TFields[N]>,
98
+ ): Promise<readonly Result<TEntity>[]> {
99
+ const entityResults = await this.loadManyByFieldEqualingManyAsync(fieldName, [fieldValue]);
100
+ const entityResultsForFieldValue = entityResults.get(fieldValue);
101
+ invariant(
102
+ entityResultsForFieldValue !== undefined,
103
+ `${fieldValue} should be guaranteed to be present in returned map of entities`,
104
+ );
105
+ return entityResultsForFieldValue!;
106
+ }
107
+
108
+ /**
109
+ * Load an entity where fieldName equals fieldValue, or null if no entity exists.
110
+ * @param uniqueFieldName - entity field being queried
111
+ * @param fieldValue - uniqueFieldName field value being queried
112
+ * @returns entity result where uniqueFieldName equals fieldValue, or null if no entity matches the condition.
113
+ * @throws when multiple entities match the condition
114
+ */
115
+ async loadByFieldEqualingAsync<N extends keyof Pick<TFields, TSelectedFields>>(
116
+ uniqueFieldName: N,
117
+ fieldValue: NonNullable<TFields[N]>,
118
+ ): Promise<Result<TEntity> | null> {
119
+ const entityResults = await this.loadManyByFieldEqualingAsync(uniqueFieldName, fieldValue);
120
+ invariant(
121
+ entityResults.length <= 1,
122
+ `loadByFieldEqualing: Multiple entities of type ${this.entityClass.name} found for ${String(
123
+ uniqueFieldName,
124
+ )}=${fieldValue}`,
125
+ );
126
+ return entityResults[0] ?? null;
127
+ }
128
+
129
+ /**
130
+ * Loads an entity by a specified ID.
131
+ * @param id - ID of the entity
132
+ * @returns entity result for matching ID, where result error can be UnauthorizedError or EntityNotFoundError.
133
+ */
134
+ async loadByIDAsync(id: TID): Promise<Result<TEntity>> {
135
+ const entityResults = await this.loadManyByIDsAsync([id]);
136
+ // loadManyByIDsAsync is always populated for each id supplied
137
+ return nullthrows(entityResults.get(id));
138
+ }
139
+
140
+ /**
141
+ * Load an entity by a specified ID, or return null if non-existent.
142
+ * @param id - ID of the entity
143
+ * @returns entity result for matching ID, or null if no entity exists for ID.
144
+ */
145
+ async loadByIDNullableAsync(id: TID): Promise<Result<TEntity> | null> {
146
+ return await this.loadByFieldEqualingAsync(
147
+ this.entityConfiguration.idField as TSelectedFields,
148
+ id,
149
+ );
150
+ }
151
+
152
+ /**
153
+ * Loads many entities for a list of IDs.
154
+ * @param ids - IDs of the entities to load
155
+ * @returns map from ID to corresponding entity result, where result error can be UnauthorizedError or EntityNotFoundError.
156
+ */
157
+ async loadManyByIDsAsync(ids: readonly TID[]): Promise<ReadonlyMap<TID, Result<TEntity>>> {
158
+ const entityResults = (await this.loadManyByFieldEqualingManyAsync(
159
+ this.entityConfiguration.idField as TSelectedFields,
160
+ ids,
161
+ )) as ReadonlyMap<TID, readonly Result<TEntity>[]>;
162
+ return mapMap(entityResults, (entityResultsForId, id) => {
163
+ const entityResult = entityResultsForId[0];
164
+ return (
165
+ entityResult ??
166
+ result(new EntityNotFoundError(this.entityClass, this.entityConfiguration.idField, id))
167
+ );
168
+ });
169
+ }
170
+
171
+ /**
172
+ * Loads many entities for a list of IDs, returning null for any IDs that are non-existent.
173
+ * @param ids - IDs of the entities to load
174
+ * @returns map from ID to nullable corresponding entity result, where result error can be UnauthorizedError or EntityNotFoundError.
175
+ */
176
+ async loadManyByIDsNullableAsync(
177
+ ids: readonly TID[],
178
+ ): Promise<ReadonlyMap<TID, Result<TEntity> | null>> {
179
+ const entityResults = (await this.loadManyByFieldEqualingManyAsync(
180
+ this.entityConfiguration.idField as TSelectedFields,
181
+ ids,
182
+ )) as ReadonlyMap<TID, readonly Result<TEntity>[]>;
183
+ return mapMap(entityResults, (entityResultsForId) => {
184
+ return entityResultsForId[0] ?? null;
185
+ });
186
+ }
187
+
188
+ /**
189
+ * Loads the first entity matching the selection constructed from the conjunction of specified
190
+ * operands, or null if no matching entity exists. Entities loaded using this method are not
191
+ * batched or cached.
192
+ *
193
+ * This is a convenience method for {@link loadManyByFieldEqualityConjunctionAsync}. However, the
194
+ * `orderBy` option must be specified to define what "first" means. If ordering doesn't matter,
195
+ * explicitly pass in an empty array.
196
+ *
197
+ * @param fieldEqualityOperands - list of field equality selection operand specifications
198
+ * @param querySelectionModifiers - orderBy and optional offset for the query
199
+ * @returns the first entity results that matches the query, where result error can be
200
+ * UnauthorizedError
201
+ */
202
+ async loadFirstByFieldEqualityConjunctionAsync<N extends keyof Pick<TFields, TSelectedFields>>(
203
+ fieldEqualityOperands: FieldEqualityCondition<TFields, N>[],
204
+ querySelectionModifiers: Omit<QuerySelectionModifiers<TFields>, 'limit'> &
205
+ Required<Pick<QuerySelectionModifiers<TFields>, 'orderBy'>>,
206
+ ): Promise<Result<TEntity> | null> {
207
+ const results = await this.loadManyByFieldEqualityConjunctionAsync(fieldEqualityOperands, {
208
+ ...querySelectionModifiers,
209
+ limit: 1,
210
+ });
211
+ return results[0] ?? null;
212
+ }
213
+
214
+ /**
215
+ * Loads many entities matching the selection constructed from the conjunction of specified operands.
216
+ * Entities loaded using this method are not batched or cached.
217
+ *
218
+ * @example
219
+ * fieldEqualityOperands:
220
+ * `[{fieldName: 'hello', fieldValue: 1}, {fieldName: 'world', fieldValues: [2, 3]}]`
221
+ * Entities returned with a SQL EntityDatabaseAdapter:
222
+ * `WHERE hello = 1 AND world = ANY({2, 3})`
223
+ *
224
+ * @param fieldEqualityOperands - list of field equality selection operand specifications
225
+ * @param querySelectionModifiers - limit, offset, and orderBy for the query
226
+ * @returns array of entity results that match the query, where result error can be UnauthorizedError
227
+ */
228
+ async loadManyByFieldEqualityConjunctionAsync<N extends keyof Pick<TFields, TSelectedFields>>(
229
+ fieldEqualityOperands: FieldEqualityCondition<TFields, N>[],
230
+ querySelectionModifiers: QuerySelectionModifiers<TFields> = {},
231
+ ): Promise<readonly Result<TEntity>[]> {
232
+ for (const fieldEqualityOperand of fieldEqualityOperands) {
233
+ const fieldValues = isSingleValueFieldEqualityCondition(fieldEqualityOperand)
234
+ ? [fieldEqualityOperand.fieldValue]
235
+ : fieldEqualityOperand.fieldValues;
236
+ this.validateFieldValues(fieldEqualityOperand.fieldName, fieldValues);
237
+ }
238
+
239
+ const fieldObjects = await this.dataManager.loadManyByFieldEqualityConjunctionAsync(
240
+ this.queryContext,
241
+ fieldEqualityOperands,
242
+ querySelectionModifiers,
243
+ );
244
+ return await this.utils.constructAndAuthorizeEntitiesArrayAsync(fieldObjects);
245
+ }
246
+
247
+ /**
248
+ * Loads many entities matching the raw WHERE clause. Corresponds to the knex `whereRaw` argument format.
249
+ *
250
+ * @remarks
251
+ * Important notes:
252
+ * - Fields in clause are database column names instead of transformed entity field names.
253
+ * - Entities loaded using this method are not batched or cached.
254
+ * - Not all database adapters implement the ability to execute this method of fetching entities.
255
+ *
256
+ * @example
257
+ * rawWhereClause: `id = ?`
258
+ * bindings: `[1]`
259
+ * Entites returned `WHERE id = 1`
260
+ *
261
+ * http://knexjs.org/#Builder-whereRaw
262
+ * http://knexjs.org/#Raw-Bindings
263
+ *
264
+ * @param rawWhereClause - parameterized SQL WHERE clause with positional binding placeholders or named binding placeholders
265
+ * @param bindings - array of positional bindings or object of named bindings
266
+ * @param querySelectionModifiers - limit, offset, orderBy, and orderByRaw for the query
267
+ * @returns array of entity results that match the query, where result error can be UnauthorizedError
268
+ * @throws Error when rawWhereClause or bindings are invalid
269
+ */
270
+ async loadManyByRawWhereClauseAsync(
271
+ rawWhereClause: string,
272
+ bindings: any[] | object,
273
+ querySelectionModifiers: QuerySelectionModifiersWithOrderByRaw<TFields> = {},
274
+ ): Promise<readonly Result<TEntity>[]> {
275
+ const fieldObjects = await this.dataManager.loadManyByRawWhereClauseAsync(
276
+ this.queryContext,
277
+ rawWhereClause,
278
+ bindings,
279
+ querySelectionModifiers,
280
+ );
281
+ return await this.utils.constructAndAuthorizeEntitiesArrayAsync(fieldObjects);
282
+ }
283
+
284
+ private validateFieldValues<N extends keyof Pick<TFields, TSelectedFields>>(
285
+ fieldName: N,
286
+ fieldValues: readonly TFields[N][],
287
+ ): void {
288
+ const fieldDefinition = this.entityConfiguration.schema.get(fieldName);
289
+ invariant(fieldDefinition, `must have field definition for field = ${String(fieldName)}`);
290
+ for (const fieldValue of fieldValues) {
291
+ const isInputValid = fieldDefinition.validateInputValue(fieldValue);
292
+ if (!isInputValid) {
293
+ throw new EntityInvalidFieldValueError(this.entityClass, fieldName, fieldValue);
294
+ }
295
+ }
296
+ }
297
+ }
@@ -17,12 +17,12 @@ export default class ComposedEntityCacheAdapter<TFields> implements IEntityCache
17
17
 
18
18
  public async loadManyAsync<N extends keyof TFields>(
19
19
  fieldName: N,
20
- fieldValues: readonly NonNullable<TFields[N]>[]
20
+ fieldValues: readonly NonNullable<TFields[N]>[],
21
21
  ): Promise<ReadonlyMap<NonNullable<TFields[N]>, CacheLoadResult<TFields>>> {
22
22
  const retMap = new Map<NonNullable<TFields[N]>, CacheLoadResult<TFields>>();
23
23
  const fulfilledFieldValuesByCacheIndex: NonNullable<TFields[N]>[][] = Array.from(
24
24
  { length: this.cacheAdapters.length },
25
- () => []
25
+ () => [],
26
26
  );
27
27
 
28
28
  let unfulfilledFieldValues = fieldValues;
@@ -30,7 +30,7 @@ export default class ComposedEntityCacheAdapter<TFields> implements IEntityCache
30
30
  const cacheAdapter = nullthrows(this.cacheAdapters[i]);
31
31
  const cacheResultsFromAdapter = await cacheAdapter.loadManyAsync(
32
32
  fieldName,
33
- unfulfilledFieldValues
33
+ unfulfilledFieldValues,
34
34
  );
35
35
 
36
36
  const newUnfulfilledFieldValues = [];
@@ -87,7 +87,7 @@ export default class ComposedEntityCacheAdapter<TFields> implements IEntityCache
87
87
 
88
88
  public async cacheManyAsync<N extends keyof TFields>(
89
89
  fieldName: N,
90
- objectMap: ReadonlyMap<NonNullable<TFields[N]>, Readonly<TFields>>
90
+ objectMap: ReadonlyMap<NonNullable<TFields[N]>, Readonly<TFields>>,
91
91
  ): Promise<void> {
92
92
  // write to lower layers first
93
93
  for (let i = this.cacheAdapters.length - 1; i >= 0; i--) {
@@ -98,7 +98,7 @@ export default class ComposedEntityCacheAdapter<TFields> implements IEntityCache
98
98
 
99
99
  public async cacheDBMissesAsync<N extends keyof TFields>(
100
100
  fieldName: N,
101
- fieldValues: readonly NonNullable<TFields[N]>[]
101
+ fieldValues: readonly NonNullable<TFields[N]>[],
102
102
  ): Promise<void> {
103
103
  // write to lower layers first
104
104
  for (let i = this.cacheAdapters.length - 1; i >= 0; i--) {
@@ -109,7 +109,7 @@ export default class ComposedEntityCacheAdapter<TFields> implements IEntityCache
109
109
 
110
110
  public async invalidateManyAsync<N extends keyof TFields>(
111
111
  fieldName: N,
112
- fieldValues: readonly NonNullable<TFields[N]>[]
112
+ fieldValues: readonly NonNullable<TFields[N]>[],
113
113
  ): Promise<void> {
114
114
  // delete from lower layers first
115
115
  for (let i = this.cacheAdapters.length - 1; i >= 0; i--) {
@@ -14,19 +14,19 @@ export default class ComposedSecondaryEntityCache<TLoadParams, TFields>
14
14
  * Typically, caches closer to the application should be ordered before caches closer to the database.
15
15
  */
16
16
  constructor(
17
- private readonly secondaryEntityCaches: ISecondaryEntityCache<TFields, TLoadParams>[]
17
+ private readonly secondaryEntityCaches: ISecondaryEntityCache<TFields, TLoadParams>[],
18
18
  ) {}
19
19
 
20
20
  async loadManyThroughAsync(
21
21
  loadParamsArray: readonly Readonly<TLoadParams>[],
22
22
  fetcher: (
23
- fetcherLoadParamsArray: readonly Readonly<TLoadParams>[]
24
- ) => Promise<ReadonlyMap<Readonly<TLoadParams>, Readonly<TFields> | null>>
23
+ fetcherLoadParamsArray: readonly Readonly<TLoadParams>[],
24
+ ) => Promise<ReadonlyMap<Readonly<TLoadParams>, Readonly<TFields> | null>>,
25
25
  ): Promise<ReadonlyMap<Readonly<TLoadParams>, Readonly<TFields> | null>> {
26
26
  return await ComposedSecondaryEntityCache.loadManyThroughRecursivelyAsync(
27
27
  this.secondaryEntityCaches,
28
28
  loadParamsArray,
29
- fetcher
29
+ fetcher,
30
30
  );
31
31
  }
32
32
 
@@ -34,8 +34,8 @@ export default class ComposedSecondaryEntityCache<TLoadParams, TFields>
34
34
  secondaryEntityCaches: ISecondaryEntityCache<TFields, TLoadParams>[],
35
35
  loadParamsArray: readonly Readonly<TLoadParams>[],
36
36
  fetcher: (
37
- fetcherLoadParamsArray: readonly Readonly<TLoadParams>[]
38
- ) => Promise<ReadonlyMap<Readonly<TLoadParams>, Readonly<TFields> | null>>
37
+ fetcherLoadParamsArray: readonly Readonly<TLoadParams>[],
38
+ ) => Promise<ReadonlyMap<Readonly<TLoadParams>, Readonly<TFields> | null>>,
39
39
  ): Promise<ReadonlyMap<Readonly<TLoadParams>, Readonly<TFields> | null>> {
40
40
  if (secondaryEntityCaches.length === 0) {
41
41
  return await fetcher(loadParamsArray);
@@ -49,8 +49,8 @@ export default class ComposedSecondaryEntityCache<TLoadParams, TFields>
49
49
  ComposedSecondaryEntityCache.loadManyThroughRecursivelyAsync(
50
50
  restCaches,
51
51
  fetcherLoadParamsArray,
52
- fetcher
53
- )
52
+ fetcher,
53
+ ),
54
54
  );
55
55
  }
56
56
 
@@ -1,17 +1,18 @@
1
+ import AuthorizationResultBasedEntityLoader from './AuthorizationResultBasedEntityLoader';
1
2
  import {
2
3
  FieldEqualityCondition,
3
4
  QuerySelectionModifiers,
4
5
  QuerySelectionModifiersWithOrderByRaw,
5
6
  } from './EntityDatabaseAdapter';
6
- import EntityLoader from './EntityLoader';
7
7
  import EntityPrivacyPolicy from './EntityPrivacyPolicy';
8
8
  import ReadonlyEntity from './ReadonlyEntity';
9
9
  import ViewerContext from './ViewerContext';
10
10
  import { mapMap } from './utils/collections/maps';
11
11
 
12
12
  /**
13
- * Enforcing view on an entity loader. All loads through this loader will throw
14
- * if the loads are not successful.
13
+ * Enforcing entity loader. All normal loads are batched,
14
+ * cached, and authorized against the entity's EntityPrivacyPolicy. All loads
15
+ * through this loader will throw if the load is not successful.
15
16
  */
16
17
  export default class EnforcingEntityLoader<
17
18
  TFields extends object,
@@ -25,17 +26,17 @@ export default class EnforcingEntityLoader<
25
26
  TEntity,
26
27
  TSelectedFields
27
28
  >,
28
- TSelectedFields extends keyof TFields
29
+ TSelectedFields extends keyof TFields,
29
30
  > {
30
31
  constructor(
31
- private readonly entityLoader: EntityLoader<
32
+ private readonly entityLoader: AuthorizationResultBasedEntityLoader<
32
33
  TFields,
33
34
  TID,
34
35
  TViewerContext,
35
36
  TEntity,
36
37
  TPrivacyPolicy,
37
38
  TSelectedFields
38
- >
39
+ >,
39
40
  ) {}
40
41
 
41
42
  /**
@@ -44,14 +45,14 @@ export default class EnforcingEntityLoader<
44
45
  */
45
46
  async loadManyByFieldEqualingManyAsync<N extends keyof Pick<TFields, TSelectedFields>>(
46
47
  fieldName: N,
47
- fieldValues: readonly NonNullable<TFields[N]>[]
48
+ fieldValues: readonly NonNullable<TFields[N]>[],
48
49
  ): Promise<ReadonlyMap<NonNullable<TFields[N]>, readonly TEntity[]>> {
49
50
  const fieldValuesToResults = await this.entityLoader.loadManyByFieldEqualingManyAsync(
50
51
  fieldName,
51
- fieldValues
52
+ fieldValues,
52
53
  );
53
54
  return mapMap(fieldValuesToResults, (results) =>
54
- results.map((result) => result.enforceValue())
55
+ results.map((result) => result.enforceValue()),
55
56
  );
56
57
  }
57
58
 
@@ -61,11 +62,11 @@ export default class EnforcingEntityLoader<
61
62
  */
62
63
  async loadManyByFieldEqualingAsync<N extends keyof Pick<TFields, TSelectedFields>>(
63
64
  fieldName: N,
64
- fieldValue: NonNullable<TFields[N]>
65
+ fieldValue: NonNullable<TFields[N]>,
65
66
  ): Promise<readonly TEntity[]> {
66
67
  const entityResults = await this.entityLoader.loadManyByFieldEqualingAsync(
67
68
  fieldName,
68
- fieldValue
69
+ fieldValue,
69
70
  );
70
71
  return entityResults.map((result) => result.enforceValue());
71
72
  }
@@ -77,11 +78,11 @@ export default class EnforcingEntityLoader<
77
78
  */
78
79
  async loadByFieldEqualingAsync<N extends keyof Pick<TFields, TSelectedFields>>(
79
80
  uniqueFieldName: N,
80
- fieldValue: NonNullable<TFields[N]>
81
+ fieldValue: NonNullable<TFields[N]>,
81
82
  ): Promise<TEntity | null> {
82
83
  const entityResult = await this.entityLoader.loadByFieldEqualingAsync(
83
84
  uniqueFieldName,
84
- fieldValue
85
+ fieldValue,
85
86
  );
86
87
  return entityResult ? entityResult.enforceValue() : null;
87
88
  }
@@ -130,11 +131,11 @@ export default class EnforcingEntityLoader<
130
131
  async loadFirstByFieldEqualityConjunctionAsync<N extends keyof Pick<TFields, TSelectedFields>>(
131
132
  fieldEqualityOperands: FieldEqualityCondition<TFields, N>[],
132
133
  querySelectionModifiers: Omit<QuerySelectionModifiers<TFields>, 'limit'> &
133
- Required<Pick<QuerySelectionModifiers<TFields>, 'orderBy'>>
134
+ Required<Pick<QuerySelectionModifiers<TFields>, 'orderBy'>>,
134
135
  ): Promise<TEntity | null> {
135
136
  const entityResult = await this.entityLoader.loadFirstByFieldEqualityConjunctionAsync(
136
137
  fieldEqualityOperands,
137
- querySelectionModifiers
138
+ querySelectionModifiers,
138
139
  );
139
140
  return entityResult ? entityResult.enforceValue() : null;
140
141
  }
@@ -145,11 +146,11 @@ export default class EnforcingEntityLoader<
145
146
  */
146
147
  async loadManyByFieldEqualityConjunctionAsync<N extends keyof Pick<TFields, TSelectedFields>>(
147
148
  fieldEqualityOperands: FieldEqualityCondition<TFields, N>[],
148
- querySelectionModifiers: QuerySelectionModifiers<TFields> = {}
149
+ querySelectionModifiers: QuerySelectionModifiers<TFields> = {},
149
150
  ): Promise<readonly TEntity[]> {
150
151
  const entityResults = await this.entityLoader.loadManyByFieldEqualityConjunctionAsync(
151
152
  fieldEqualityOperands,
152
- querySelectionModifiers
153
+ querySelectionModifiers,
153
154
  );
154
155
  return entityResults.map((result) => result.enforceValue());
155
156
  }
@@ -161,12 +162,12 @@ export default class EnforcingEntityLoader<
161
162
  async loadManyByRawWhereClauseAsync(
162
163
  rawWhereClause: string,
163
164
  bindings: any[] | object,
164
- querySelectionModifiers: QuerySelectionModifiersWithOrderByRaw<TFields> = {}
165
+ querySelectionModifiers: QuerySelectionModifiersWithOrderByRaw<TFields> = {},
165
166
  ): Promise<readonly TEntity[]> {
166
167
  const entityResults = await this.entityLoader.loadManyByRawWhereClauseAsync(
167
168
  rawWhereClause,
168
169
  bindings,
169
- querySelectionModifiers
170
+ querySelectionModifiers,
170
171
  );
171
172
  return entityResults.map((result) => result.enforceValue());
172
173
  }