@expo/entity 0.41.0 → 0.43.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 (430) hide show
  1. package/build/AuthorizationResultBasedEntityAssociationLoader.d.ts +16 -16
  2. package/build/AuthorizationResultBasedEntityAssociationLoader.js.map +1 -1
  3. package/build/AuthorizationResultBasedEntityLoader.d.ts +39 -67
  4. package/build/AuthorizationResultBasedEntityLoader.js +85 -62
  5. package/build/AuthorizationResultBasedEntityLoader.js.map +1 -1
  6. package/build/AuthorizationResultBasedEntityMutator.d.ts +16 -16
  7. package/build/AuthorizationResultBasedEntityMutator.js.map +1 -1
  8. package/build/ComposedEntityCacheAdapter.d.ts +7 -6
  9. package/build/ComposedEntityCacheAdapter.js +28 -28
  10. package/build/ComposedEntityCacheAdapter.js.map +1 -1
  11. package/build/ComposedSecondaryEntityCache.d.ts +1 -1
  12. package/build/ComposedSecondaryEntityCache.js.map +1 -1
  13. package/build/EnforcingEntityAssociationLoader.d.ts +15 -15
  14. package/build/EnforcingEntityAssociationLoader.js.map +1 -1
  15. package/build/EnforcingEntityCreator.d.ts +2 -2
  16. package/build/EnforcingEntityDeleter.d.ts +2 -2
  17. package/build/EnforcingEntityLoader.d.ts +104 -18
  18. package/build/EnforcingEntityLoader.js +113 -12
  19. package/build/EnforcingEntityLoader.js.map +1 -1
  20. package/build/EnforcingEntityUpdater.d.ts +2 -2
  21. package/build/Entity.d.ts +10 -10
  22. package/build/Entity.js.map +1 -1
  23. package/build/EntityAssociationLoader.d.ts +3 -3
  24. package/build/EntityCompanion.d.ts +5 -5
  25. package/build/EntityCompanion.js.map +1 -1
  26. package/build/EntityCompanionProvider.d.ts +6 -6
  27. package/build/EntityCompanionProvider.js.map +1 -1
  28. package/build/EntityConfiguration.d.ts +46 -5
  29. package/build/EntityConfiguration.js +39 -1
  30. package/build/EntityConfiguration.js.map +1 -1
  31. package/build/EntityCreator.d.ts +4 -4
  32. package/build/EntityDatabaseAdapter.d.ts +15 -14
  33. package/build/EntityDatabaseAdapter.js +20 -12
  34. package/build/EntityDatabaseAdapter.js.map +1 -1
  35. package/build/EntityDeleter.d.ts +4 -4
  36. package/build/EntityFieldDefinition.d.ts +20 -10
  37. package/build/EntityFieldDefinition.js +3 -1
  38. package/build/EntityFieldDefinition.js.map +1 -1
  39. package/build/EntityFields.d.ts +14 -12
  40. package/build/EntityFields.js.map +1 -1
  41. package/build/EntityLoader.d.ts +5 -5
  42. package/build/EntityLoaderFactory.d.ts +3 -3
  43. package/build/EntityLoaderFactory.js.map +1 -1
  44. package/build/EntityLoaderUtils.d.ts +2 -2
  45. package/build/EntityLoaderUtils.js +27 -1
  46. package/build/EntityLoaderUtils.js.map +1 -1
  47. package/build/EntityMutationInfo.d.ts +2 -2
  48. package/build/EntityMutationTriggerConfiguration.d.ts +14 -14
  49. package/build/EntityMutationTriggerConfiguration.js.map +1 -1
  50. package/build/EntityMutationValidator.d.ts +2 -2
  51. package/build/EntityMutatorFactory.d.ts +5 -5
  52. package/build/EntityMutatorFactory.js.map +1 -1
  53. package/build/EntityPrivacyPolicy.d.ts +14 -14
  54. package/build/EntityPrivacyPolicy.js.map +1 -1
  55. package/build/EntitySecondaryCacheLoader.d.ts +4 -4
  56. package/build/EntityUpdater.d.ts +4 -4
  57. package/build/GenericEntityCacheAdapter.d.ts +7 -6
  58. package/build/GenericEntityCacheAdapter.js +13 -14
  59. package/build/GenericEntityCacheAdapter.js.map +1 -1
  60. package/build/GenericSecondaryEntityCache.d.ts +3 -3
  61. package/build/GenericSecondaryEntityCache.js.map +1 -1
  62. package/build/IEntityCacheAdapter.d.ts +17 -16
  63. package/build/IEntityCacheAdapterProvider.d.ts +1 -1
  64. package/build/IEntityDatabaseAdapterProvider.d.ts +1 -1
  65. package/build/IEntityGenericCacher.d.ts +15 -5
  66. package/build/ReadonlyEntity.d.ts +8 -8
  67. package/build/ReadonlyEntity.js.map +1 -1
  68. package/build/ViewerContext.d.ts +1 -1
  69. package/build/ViewerScopedEntityCompanion.d.ts +5 -5
  70. package/build/ViewerScopedEntityCompanionProvider.d.ts +1 -1
  71. package/build/ViewerScopedEntityLoaderFactory.d.ts +3 -3
  72. package/build/ViewerScopedEntityMutatorFactory.d.ts +5 -5
  73. package/build/entityUtils.d.ts +1 -1
  74. package/build/entityUtils.js.map +1 -1
  75. package/build/errors/EntityInvalidFieldValueError.d.ts +2 -2
  76. package/build/errors/EntityNotAuthorizedError.d.ts +1 -1
  77. package/build/errors/EntityNotFoundError.d.ts +2 -2
  78. package/build/index.d.ts +7 -7
  79. package/build/index.js +8 -13
  80. package/build/index.js.map +1 -1
  81. package/build/internal/CompositeFieldHolder.d.ts +48 -0
  82. package/build/internal/CompositeFieldHolder.js +116 -0
  83. package/build/internal/CompositeFieldHolder.js.map +1 -0
  84. package/build/internal/CompositeFieldValueMap.d.ts +15 -0
  85. package/build/internal/CompositeFieldValueMap.js +51 -0
  86. package/build/internal/CompositeFieldValueMap.js.map +1 -0
  87. package/build/internal/EntityDataManager.d.ts +16 -16
  88. package/build/internal/EntityDataManager.js +42 -45
  89. package/build/internal/EntityDataManager.js.map +1 -1
  90. package/build/internal/EntityFieldTransformationUtils.d.ts +5 -5
  91. package/build/internal/EntityFieldTransformationUtils.js.map +1 -1
  92. package/build/internal/EntityLoadInterfaces.d.ts +104 -0
  93. package/build/internal/EntityLoadInterfaces.js +25 -0
  94. package/build/internal/EntityLoadInterfaces.js.map +1 -0
  95. package/build/internal/EntityTableDataCoordinator.d.ts +6 -6
  96. package/build/internal/EntityTableDataCoordinator.js.map +1 -1
  97. package/build/internal/ReadThroughEntityCache.d.ts +17 -16
  98. package/build/internal/ReadThroughEntityCache.js +36 -36
  99. package/build/internal/ReadThroughEntityCache.js.map +1 -1
  100. package/build/internal/SingleFieldHolder.d.ts +34 -0
  101. package/build/internal/SingleFieldHolder.js +90 -0
  102. package/build/internal/SingleFieldHolder.js.map +1 -0
  103. package/build/metrics/EntityMetricsUtils.d.ts +2 -1
  104. package/build/metrics/EntityMetricsUtils.js.map +1 -1
  105. package/build/metrics/IEntityMetricsAdapter.d.ts +5 -0
  106. package/build/metrics/IEntityMetricsAdapter.js.map +1 -1
  107. package/build/rules/AlwaysAllowPrivacyPolicyRule.d.ts +2 -2
  108. package/build/rules/AlwaysAllowPrivacyPolicyRule.js.map +1 -1
  109. package/build/rules/AlwaysDenyPrivacyPolicyRule.d.ts +2 -2
  110. package/build/rules/AlwaysDenyPrivacyPolicyRule.js.map +1 -1
  111. package/build/rules/AlwaysSkipPrivacyPolicyRule.d.ts +2 -2
  112. package/build/rules/AlwaysSkipPrivacyPolicyRule.js.map +1 -1
  113. package/build/rules/PrivacyPolicyRule.d.ts +2 -2
  114. package/build/tsconfig.build.tsbuildinfo +1 -0
  115. package/build/utils/EntityPrivacyUtils.d.ts +4 -4
  116. package/build/utils/EntityPrivacyUtils.js.map +1 -1
  117. package/build/utils/collections/SerializableKeyMap.d.ts +27 -0
  118. package/build/utils/collections/SerializableKeyMap.js +60 -0
  119. package/build/utils/collections/SerializableKeyMap.js.map +1 -0
  120. package/build/utils/collections/maps.js +1 -2
  121. package/build/utils/collections/maps.js.map +1 -1
  122. package/build/utils/collections/sets.d.ts +1 -0
  123. package/build/utils/collections/sets.js +7 -0
  124. package/build/utils/collections/sets.js.map +1 -0
  125. package/build/utils/mergeEntityMutationTriggerConfigurations.d.ts +1 -1
  126. package/package.json +8 -5
  127. package/src/AuthorizationResultBasedEntityAssociationLoader.ts +56 -49
  128. package/src/AuthorizationResultBasedEntityLoader.ts +194 -81
  129. package/src/AuthorizationResultBasedEntityMutator.ts +71 -45
  130. package/src/ComposedEntityCacheAdapter.ts +55 -46
  131. package/src/ComposedSecondaryEntityCache.ts +5 -2
  132. package/src/EnforcingEntityAssociationLoader.ts +52 -44
  133. package/src/EnforcingEntityCreator.ts +5 -5
  134. package/src/EnforcingEntityDeleter.ts +5 -5
  135. package/src/EnforcingEntityLoader.ts +158 -21
  136. package/src/EnforcingEntityUpdater.ts +5 -5
  137. package/src/Entity.ts +39 -39
  138. package/src/EntityAssociationLoader.ts +6 -6
  139. package/src/EntityCompanion.ts +11 -11
  140. package/src/EntityCompanionProvider.ts +21 -18
  141. package/src/EntityConfiguration.ts +123 -9
  142. package/src/EntityCreator.ts +7 -7
  143. package/src/EntityDatabaseAdapter.ts +51 -28
  144. package/src/EntityDeleter.ts +7 -7
  145. package/src/EntityFieldDefinition.ts +32 -12
  146. package/src/EntityFields.ts +49 -12
  147. package/src/EntityLoader.ts +8 -8
  148. package/src/EntityLoaderFactory.ts +8 -8
  149. package/src/EntityLoaderUtils.ts +39 -10
  150. package/src/EntityMutationInfo.ts +6 -6
  151. package/src/EntityMutationTriggerConfiguration.ts +68 -20
  152. package/src/EntityMutationValidator.ts +4 -4
  153. package/src/EntityMutatorFactory.ts +13 -13
  154. package/src/EntityPrivacyPolicy.ts +50 -26
  155. package/src/EntitySecondaryCacheLoader.ts +6 -6
  156. package/src/EntityUpdater.ts +7 -7
  157. package/src/GenericEntityCacheAdapter.ts +39 -28
  158. package/src/GenericSecondaryEntityCache.ts +6 -3
  159. package/src/IEntityCacheAdapter.ts +45 -25
  160. package/src/IEntityCacheAdapterProvider.ts +3 -3
  161. package/src/IEntityDatabaseAdapterProvider.ts +3 -3
  162. package/src/IEntityGenericCacher.ts +33 -5
  163. package/src/ReadonlyEntity.ts +24 -24
  164. package/src/ViewerContext.ts +5 -5
  165. package/src/ViewerScopedEntityCompanion.ts +7 -7
  166. package/src/ViewerScopedEntityCompanionProvider.ts +6 -6
  167. package/src/ViewerScopedEntityLoaderFactory.ts +7 -7
  168. package/src/ViewerScopedEntityMutatorFactory.ts +8 -8
  169. package/src/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.ts +4 -4
  170. package/src/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.ts +14 -13
  171. package/src/__tests__/AuthorizationResultBasedEntityLoader-test.ts +367 -69
  172. package/src/__tests__/ComposedCacheAdapter-test.ts +235 -117
  173. package/src/__tests__/EnforcingEntityLoader-test.ts +135 -1
  174. package/src/__tests__/Entity-test.ts +2 -2
  175. package/src/__tests__/EntityAssociationLoader-test.ts +2 -2
  176. package/src/__tests__/EntityCommonUseCases-test.ts +11 -11
  177. package/src/__tests__/EntityCompanion-test.ts +4 -4
  178. package/src/__tests__/EntityCompanionProvider-test.ts +9 -8
  179. package/src/__tests__/EntityConfiguration-test.ts +85 -6
  180. package/src/__tests__/EntityDatabaseAdapter-test.ts +113 -17
  181. package/src/__tests__/EntityEdges-test.ts +97 -72
  182. package/src/__tests__/EntityFields-test.ts +2 -2
  183. package/src/__tests__/EntityLoader-test.ts +2 -2
  184. package/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts +11 -11
  185. package/src/__tests__/EntityMutator-SingleCompositeFieldCacheConsistency-test.ts +73 -0
  186. package/src/__tests__/EntityMutator-test.ts +74 -46
  187. package/src/__tests__/EntityPrivacyPolicy-test.ts +51 -74
  188. package/src/__tests__/EntityQueryContext-test.ts +1 -1
  189. package/src/__tests__/EntitySecondaryCacheLoader-test.ts +3 -3
  190. package/src/__tests__/EntitySelfReferentialEdges-test.ts +64 -39
  191. package/src/__tests__/GenericEntityCacheAdapter-test.ts +83 -28
  192. package/src/__tests__/ReadonlyEntity-test.ts +3 -3
  193. package/src/__tests__/ViewerContext-test.ts +1 -1
  194. package/src/__tests__/ViewerScopedEntityCompanion-test.ts +5 -2
  195. package/src/__tests__/ViewerScopedEntityCompanionProvider-test.ts +1 -1
  196. package/src/__tests__/ViewerScopedEntityMutatorFactory-test.ts +12 -3
  197. package/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts +12 -12
  198. package/src/__tests__/cases/TwoEntitySameTableOverlappingRows-test.ts +12 -12
  199. package/src/entityUtils.ts +4 -1
  200. package/src/errors/EntityInvalidFieldValueError.ts +5 -5
  201. package/src/errors/EntityNotAuthorizedError.ts +3 -3
  202. package/src/errors/EntityNotFoundError.ts +5 -5
  203. package/src/index.ts +7 -7
  204. package/src/internal/CompositeFieldHolder.ts +218 -0
  205. package/src/internal/CompositeFieldValueMap.ts +78 -0
  206. package/src/internal/EntityDataManager.ts +107 -96
  207. package/src/internal/EntityFieldTransformationUtils.ts +33 -14
  208. package/src/internal/EntityLoadInterfaces.ts +143 -0
  209. package/src/internal/EntityTableDataCoordinator.ts +8 -5
  210. package/src/internal/ReadThroughEntityCache.ts +63 -50
  211. package/src/internal/SingleFieldHolder.ts +131 -0
  212. package/src/internal/__tests__/CompositeFieldHolder-test.ts +25 -0
  213. package/src/internal/__tests__/CompositeFieldValueMap-test.ts +43 -0
  214. package/src/internal/__tests__/EntityDataManager-test.ts +308 -91
  215. package/src/internal/__tests__/EntityFieldTransformationUtils-test.ts +3 -2
  216. package/src/internal/__tests__/ReadThroughEntityCache-test.ts +315 -107
  217. package/src/metrics/EntityMetricsUtils.ts +7 -2
  218. package/src/metrics/IEntityMetricsAdapter.ts +6 -0
  219. package/src/rules/AlwaysAllowPrivacyPolicyRule.ts +5 -5
  220. package/src/rules/AlwaysDenyPrivacyPolicyRule.ts +5 -5
  221. package/src/rules/AlwaysSkipPrivacyPolicyRule.ts +5 -5
  222. package/src/rules/PrivacyPolicyRule.ts +4 -4
  223. package/src/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.ts +1 -1
  224. package/src/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.ts +1 -1
  225. package/src/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.ts +1 -1
  226. package/src/utils/EntityPrivacyUtils.ts +72 -30
  227. package/src/utils/{testing → __testfixtures__}/PrivacyPolicyRuleTestUtils.ts +26 -26
  228. package/src/{testfixtures → utils/__testfixtures__}/SimpleTestEntity.ts +16 -15
  229. package/src/utils/__testfixtures__/StubCacheAdapter.ts +164 -0
  230. package/src/utils/{testing → __testfixtures__}/StubDatabaseAdapter.ts +19 -12
  231. package/src/utils/{testing → __testfixtures__}/StubDatabaseAdapterProvider.ts +4 -4
  232. package/src/utils/__testfixtures__/TSMockitoExtensions.ts +69 -0
  233. package/src/{testfixtures → utils/__testfixtures__}/TestEntity.ts +21 -15
  234. package/src/{testfixtures → utils/__testfixtures__}/TestEntity2.ts +16 -15
  235. package/src/{testfixtures → utils/__testfixtures__}/TestEntityWithMutationTriggers.ts +23 -22
  236. package/src/{testfixtures → utils/__testfixtures__}/TestViewerContext.ts +1 -1
  237. package/src/utils/{testing → __testfixtures__}/describeFieldTestCase.ts +1 -1
  238. package/src/utils/__tests__/EntityPrivacyUtils-test.ts +62 -66
  239. package/src/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.ts +29 -25
  240. package/src/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.ts +1 -1
  241. package/src/utils/collections/SerializableKeyMap.ts +84 -0
  242. package/src/utils/collections/__tests__/SerializableKeyMap-test.ts +119 -0
  243. package/src/utils/collections/__tests__/sets-test.ts +17 -0
  244. package/src/utils/collections/maps.ts +7 -8
  245. package/src/utils/collections/sets.ts +3 -0
  246. package/src/utils/mergeEntityMutationTriggerConfigurations.ts +5 -5
  247. package/build/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.d.ts +0 -1
  248. package/build/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.js +0 -242
  249. package/build/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.js.map +0 -1
  250. package/build/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.d.ts +0 -26
  251. package/build/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.js +0 -110
  252. package/build/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.js.map +0 -1
  253. package/build/__tests__/AuthorizationResultBasedEntityLoader-test.d.ts +0 -1
  254. package/build/__tests__/AuthorizationResultBasedEntityLoader-test.js +0 -401
  255. package/build/__tests__/AuthorizationResultBasedEntityLoader-test.js.map +0 -1
  256. package/build/__tests__/ComposedCacheAdapter-test.d.ts +0 -1
  257. package/build/__tests__/ComposedCacheAdapter-test.js +0 -229
  258. package/build/__tests__/ComposedCacheAdapter-test.js.map +0 -1
  259. package/build/__tests__/ComposedSecondaryEntityCache-test.d.ts +0 -1
  260. package/build/__tests__/ComposedSecondaryEntityCache-test.js +0 -66
  261. package/build/__tests__/ComposedSecondaryEntityCache-test.js.map +0 -1
  262. package/build/__tests__/EnforcingEntityAssociationLoader-test.d.ts +0 -1
  263. package/build/__tests__/EnforcingEntityAssociationLoader-test.js +0 -115
  264. package/build/__tests__/EnforcingEntityAssociationLoader-test.js.map +0 -1
  265. package/build/__tests__/EnforcingEntityLoader-test.d.ts +0 -1
  266. package/build/__tests__/EnforcingEntityLoader-test.js +0 -253
  267. package/build/__tests__/EnforcingEntityLoader-test.js.map +0 -1
  268. package/build/__tests__/Entity-test.d.ts +0 -1
  269. package/build/__tests__/Entity-test.js +0 -94
  270. package/build/__tests__/Entity-test.js.map +0 -1
  271. package/build/__tests__/EntityAssociationLoader-test.d.ts +0 -1
  272. package/build/__tests__/EntityAssociationLoader-test.js +0 -30
  273. package/build/__tests__/EntityAssociationLoader-test.js.map +0 -1
  274. package/build/__tests__/EntityCommonUseCases-test.d.ts +0 -1
  275. package/build/__tests__/EntityCommonUseCases-test.js +0 -146
  276. package/build/__tests__/EntityCommonUseCases-test.js.map +0 -1
  277. package/build/__tests__/EntityCompanion-test.d.ts +0 -1
  278. package/build/__tests__/EntityCompanion-test.js +0 -77
  279. package/build/__tests__/EntityCompanion-test.js.map +0 -1
  280. package/build/__tests__/EntityCompanionProvider-test.d.ts +0 -1
  281. package/build/__tests__/EntityCompanionProvider-test.js +0 -54
  282. package/build/__tests__/EntityCompanionProvider-test.js.map +0 -1
  283. package/build/__tests__/EntityConfiguration-test.d.ts +0 -1
  284. package/build/__tests__/EntityConfiguration-test.js +0 -103
  285. package/build/__tests__/EntityConfiguration-test.js.map +0 -1
  286. package/build/__tests__/EntityDatabaseAdapter-test.d.ts +0 -1
  287. package/build/__tests__/EntityDatabaseAdapter-test.js +0 -146
  288. package/build/__tests__/EntityDatabaseAdapter-test.js.map +0 -1
  289. package/build/__tests__/EntityEdges-test.d.ts +0 -1
  290. package/build/__tests__/EntityEdges-test.js +0 -723
  291. package/build/__tests__/EntityEdges-test.js.map +0 -1
  292. package/build/__tests__/EntityFields-test.d.ts +0 -1
  293. package/build/__tests__/EntityFields-test.js +0 -63
  294. package/build/__tests__/EntityFields-test.js.map +0 -1
  295. package/build/__tests__/EntityLoader-test.d.ts +0 -1
  296. package/build/__tests__/EntityLoader-test.js +0 -36
  297. package/build/__tests__/EntityLoader-test.js.map +0 -1
  298. package/build/__tests__/EntityMutator-MutationCacheConsistency-test.d.ts +0 -1
  299. package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js +0 -73
  300. package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js.map +0 -1
  301. package/build/__tests__/EntityMutator-test.d.ts +0 -1
  302. package/build/__tests__/EntityMutator-test.js +0 -741
  303. package/build/__tests__/EntityMutator-test.js.map +0 -1
  304. package/build/__tests__/EntityPrivacyPolicy-test.d.ts +0 -1
  305. package/build/__tests__/EntityPrivacyPolicy-test.js +0 -463
  306. package/build/__tests__/EntityPrivacyPolicy-test.js.map +0 -1
  307. package/build/__tests__/EntityQueryContext-test.d.ts +0 -1
  308. package/build/__tests__/EntityQueryContext-test.js +0 -116
  309. package/build/__tests__/EntityQueryContext-test.js.map +0 -1
  310. package/build/__tests__/EntitySecondaryCacheLoader-test.d.ts +0 -1
  311. package/build/__tests__/EntitySecondaryCacheLoader-test.js +0 -60
  312. package/build/__tests__/EntitySecondaryCacheLoader-test.js.map +0 -1
  313. package/build/__tests__/EntitySelfReferentialEdges-test.d.ts +0 -1
  314. package/build/__tests__/EntitySelfReferentialEdges-test.js +0 -201
  315. package/build/__tests__/EntitySelfReferentialEdges-test.js.map +0 -1
  316. package/build/__tests__/GenericEntityCacheAdapter-test.d.ts +0 -1
  317. package/build/__tests__/GenericEntityCacheAdapter-test.js +0 -80
  318. package/build/__tests__/GenericEntityCacheAdapter-test.js.map +0 -1
  319. package/build/__tests__/ReadonlyEntity-test.d.ts +0 -1
  320. package/build/__tests__/ReadonlyEntity-test.js +0 -211
  321. package/build/__tests__/ReadonlyEntity-test.js.map +0 -1
  322. package/build/__tests__/ViewerContext-test.d.ts +0 -1
  323. package/build/__tests__/ViewerContext-test.js +0 -30
  324. package/build/__tests__/ViewerContext-test.js.map +0 -1
  325. package/build/__tests__/ViewerScopedEntityCompanion-test.d.ts +0 -1
  326. package/build/__tests__/ViewerScopedEntityCompanion-test.js +0 -20
  327. package/build/__tests__/ViewerScopedEntityCompanion-test.js.map +0 -1
  328. package/build/__tests__/ViewerScopedEntityCompanionProvider-test.d.ts +0 -1
  329. package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js +0 -20
  330. package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js.map +0 -1
  331. package/build/__tests__/ViewerScopedEntityLoaderFactory-test.d.ts +0 -1
  332. package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js +0 -23
  333. package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js.map +0 -1
  334. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.d.ts +0 -1
  335. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js +0 -22
  336. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js.map +0 -1
  337. package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.d.ts +0 -1
  338. package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js +0 -123
  339. package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js.map +0 -1
  340. package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.d.ts +0 -1
  341. package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js +0 -121
  342. package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js.map +0 -1
  343. package/build/__tests__/entityUtils-test.d.ts +0 -1
  344. package/build/__tests__/entityUtils-test.js +0 -87
  345. package/build/__tests__/entityUtils-test.js.map +0 -1
  346. package/build/internal/__tests__/EntityDataManager-test.d.ts +0 -1
  347. package/build/internal/__tests__/EntityDataManager-test.js +0 -373
  348. package/build/internal/__tests__/EntityDataManager-test.js.map +0 -1
  349. package/build/internal/__tests__/EntityFieldTransformationUtils-test.d.ts +0 -1
  350. package/build/internal/__tests__/EntityFieldTransformationUtils-test.js +0 -136
  351. package/build/internal/__tests__/EntityFieldTransformationUtils-test.js.map +0 -1
  352. package/build/internal/__tests__/ReadThroughEntityCache-test.d.ts +0 -1
  353. package/build/internal/__tests__/ReadThroughEntityCache-test.js +0 -206
  354. package/build/internal/__tests__/ReadThroughEntityCache-test.js.map +0 -1
  355. package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.d.ts +0 -1
  356. package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js +0 -21
  357. package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js.map +0 -1
  358. package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.d.ts +0 -1
  359. package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js +0 -21
  360. package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js.map +0 -1
  361. package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.d.ts +0 -1
  362. package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js +0 -21
  363. package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js.map +0 -1
  364. package/build/testfixtures/DateIDTestEntity.d.ts +0 -19
  365. package/build/testfixtures/DateIDTestEntity.js +0 -48
  366. package/build/testfixtures/DateIDTestEntity.js.map +0 -1
  367. package/build/testfixtures/SimpleTestEntity.d.ts +0 -20
  368. package/build/testfixtures/SimpleTestEntity.js +0 -48
  369. package/build/testfixtures/SimpleTestEntity.js.map +0 -1
  370. package/build/testfixtures/TestEntity.d.ts +0 -30
  371. package/build/testfixtures/TestEntity.js +0 -93
  372. package/build/testfixtures/TestEntity.js.map +0 -1
  373. package/build/testfixtures/TestEntity2.d.ts +0 -20
  374. package/build/testfixtures/TestEntity2.js +0 -51
  375. package/build/testfixtures/TestEntity2.js.map +0 -1
  376. package/build/testfixtures/TestEntityNumberKey.d.ts +0 -19
  377. package/build/testfixtures/TestEntityNumberKey.js +0 -48
  378. package/build/testfixtures/TestEntityNumberKey.js.map +0 -1
  379. package/build/testfixtures/TestEntityWithMutationTriggers.d.ts +0 -36
  380. package/build/testfixtures/TestEntityWithMutationTriggers.js +0 -82
  381. package/build/testfixtures/TestEntityWithMutationTriggers.js.map +0 -1
  382. package/build/testfixtures/TestViewerContext.d.ts +0 -3
  383. package/build/testfixtures/TestViewerContext.js +0 -10
  384. package/build/testfixtures/TestViewerContext.js.map +0 -1
  385. package/build/utils/__tests__/EntityPrivacyUtils-test.d.ts +0 -1
  386. package/build/utils/__tests__/EntityPrivacyUtils-test.js +0 -486
  387. package/build/utils/__tests__/EntityPrivacyUtils-test.js.map +0 -1
  388. package/build/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.d.ts +0 -1
  389. package/build/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.js +0 -178
  390. package/build/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.js.map +0 -1
  391. package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.d.ts +0 -1
  392. package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.js +0 -26
  393. package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.js.map +0 -1
  394. package/build/utils/collections/__tests__/maps-test.d.ts +0 -1
  395. package/build/utils/collections/__tests__/maps-test.js +0 -120
  396. package/build/utils/collections/__tests__/maps-test.js.map +0 -1
  397. package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +0 -28
  398. package/build/utils/testing/PrivacyPolicyRuleTestUtils.js +0 -52
  399. package/build/utils/testing/PrivacyPolicyRuleTestUtils.js.map +0 -1
  400. package/build/utils/testing/StubCacheAdapter.d.ts +0 -27
  401. package/build/utils/testing/StubCacheAdapter.js +0 -86
  402. package/build/utils/testing/StubCacheAdapter.js.map +0 -1
  403. package/build/utils/testing/StubDatabaseAdapter.d.ts +0 -25
  404. package/build/utils/testing/StubDatabaseAdapter.js +0 -191
  405. package/build/utils/testing/StubDatabaseAdapter.js.map +0 -1
  406. package/build/utils/testing/StubDatabaseAdapterProvider.d.ts +0 -7
  407. package/build/utils/testing/StubDatabaseAdapterProvider.js +0 -14
  408. package/build/utils/testing/StubDatabaseAdapterProvider.js.map +0 -1
  409. package/build/utils/testing/StubQueryContextProvider.d.ts +0 -7
  410. package/build/utils/testing/StubQueryContextProvider.js +0 -19
  411. package/build/utils/testing/StubQueryContextProvider.js.map +0 -1
  412. package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.d.ts +0 -1
  413. package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.js +0 -42
  414. package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.js.map +0 -1
  415. package/build/utils/testing/__tests__/StubDatabaseAdapter-test.d.ts +0 -1
  416. package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js +0 -402
  417. package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js.map +0 -1
  418. package/build/utils/testing/createUnitTestEntityCompanionProvider.d.ts +0 -7
  419. package/build/utils/testing/createUnitTestEntityCompanionProvider.js +0 -36
  420. package/build/utils/testing/createUnitTestEntityCompanionProvider.js.map +0 -1
  421. package/build/utils/testing/describeFieldTestCase.d.ts +0 -2
  422. package/build/utils/testing/describeFieldTestCase.js +0 -18
  423. package/build/utils/testing/describeFieldTestCase.js.map +0 -1
  424. package/src/testfixtures/DateIDTestEntity.ts +0 -59
  425. package/src/testfixtures/TestEntityNumberKey.ts +0 -59
  426. package/src/utils/testing/StubCacheAdapter.ts +0 -122
  427. package/src/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.ts +0 -42
  428. package/src/utils/testing/__tests__/StubDatabaseAdapter-test.ts +0 -548
  429. /package/src/utils/{testing → __testfixtures__}/StubQueryContextProvider.ts +0 -0
  430. /package/src/utils/{testing → __testfixtures__}/createUnitTestEntityCompanionProvider.ts +0 -0
@@ -0,0 +1,218 @@
1
+ import invariant from 'invariant';
2
+
3
+ import EntityConfiguration, {
4
+ EntityCompositeField,
5
+ EntityCompositeFieldValue,
6
+ } from '../EntityConfiguration';
7
+ import { pick } from '../entityUtils';
8
+ import { getDatabaseFieldForEntityField } from './EntityFieldTransformationUtils';
9
+ import {
10
+ EntityLoadMethodType,
11
+ IEntityLoadKey,
12
+ IEntityLoadValue,
13
+ LoadValueMap,
14
+ } from '../internal/EntityLoadInterfaces';
15
+
16
+ declare const CompositeFieldHolderSerializedBrand: unique symbol;
17
+ export type SerializedCompositeFieldHolder = string & {
18
+ readonly [CompositeFieldHolderSerializedBrand]: true;
19
+ };
20
+
21
+ /**
22
+ * A load key that represents a composite field (set of fieldName) on an entity.
23
+ * Must be defined in the entity configuration composite field definition.
24
+ */
25
+ export class CompositeFieldHolder<
26
+ TFields extends Record<string, any>,
27
+ TIDField extends keyof TFields,
28
+ > implements
29
+ IEntityLoadKey<
30
+ TFields,
31
+ TIDField,
32
+ SerializedCompositeFieldValueHolder,
33
+ CompositeFieldValueHolder<TFields, EntityCompositeField<TFields>>
34
+ >
35
+ {
36
+ public readonly compositeField: EntityCompositeField<TFields>;
37
+
38
+ constructor(compositeFieldInput: EntityCompositeField<TFields>) {
39
+ this.compositeField = [...compositeFieldInput].sort();
40
+ }
41
+
42
+ toString(): string {
43
+ return `CompositeField(${this.compositeField.join(',')})`;
44
+ }
45
+
46
+ public getFieldSet(): ReadonlySet<keyof TFields> {
47
+ return new Set(this.compositeField);
48
+ }
49
+
50
+ public extractCompositeFieldValueHolderFromObjectFields(
51
+ objectFields: TFields,
52
+ ): CompositeFieldValueHolder<TFields, EntityCompositeField<TFields>> | null {
53
+ const selection = pick(objectFields, this.compositeField);
54
+ if (Object.values(selection).some((value) => value === undefined || value === null)) {
55
+ return null;
56
+ }
57
+ return new CompositeFieldValueHolder(selection);
58
+ }
59
+
60
+ public serialize(): SerializedCompositeFieldHolder {
61
+ return JSON.stringify(this.compositeField) as SerializedCompositeFieldHolder;
62
+ }
63
+
64
+ isCacheable(entityConfiguration: EntityConfiguration<TFields, TIDField>): boolean {
65
+ return entityConfiguration.compositeFieldInfo.canCacheCompositeField(this.compositeField);
66
+ }
67
+
68
+ getDatabaseColumns(
69
+ entityConfiguration: EntityConfiguration<TFields, TIDField>,
70
+ ): readonly string[] {
71
+ return this.compositeField.map((fieldName) =>
72
+ getDatabaseFieldForEntityField(entityConfiguration, fieldName),
73
+ );
74
+ }
75
+
76
+ getDatabaseValues(
77
+ value: CompositeFieldValueHolder<TFields, EntityCompositeField<TFields>>,
78
+ ): readonly any[] {
79
+ return this.compositeField.map((fieldName) => value.compositeFieldValue[fieldName]);
80
+ }
81
+
82
+ getLoadValueForObject(
83
+ object: Readonly<TFields>,
84
+ ): CompositeFieldValueHolder<TFields, EntityCompositeField<TFields>> | null {
85
+ return this.extractCompositeFieldValueHolderFromObjectFields(object);
86
+ }
87
+
88
+ createCacheKeyPartsForLoadValue(
89
+ entityConfiguration: EntityConfiguration<TFields, TIDField>,
90
+ value: CompositeFieldValueHolder<TFields, EntityCompositeField<TFields>>,
91
+ ): readonly string[] {
92
+ const columnNames = this.compositeField.map((fieldName) => {
93
+ const columnName = entityConfiguration.entityToDBFieldsKeyMapping.get(fieldName);
94
+ invariant(columnName, `database field mapping missing for ${String(fieldName)}`);
95
+ return columnName;
96
+ });
97
+ const compositeFieldValues = this.compositeField.map(
98
+ (fieldName) => value.compositeFieldValue[fieldName],
99
+ );
100
+ return [...columnNames, ...compositeFieldValues.map((value) => String(value))];
101
+ }
102
+
103
+ getLoadMethodType(): EntityLoadMethodType {
104
+ return EntityLoadMethodType.COMPOSITE;
105
+ }
106
+
107
+ getDataManagerDataLoaderKey(): string {
108
+ return this.serialize();
109
+ }
110
+
111
+ serializeLoadValue(
112
+ value: CompositeFieldValueHolder<TFields, EntityCompositeField<TFields>>,
113
+ ): SerializedCompositeFieldValueHolder {
114
+ return value.serialize();
115
+ }
116
+
117
+ deserializeLoadValue(
118
+ value: SerializedCompositeFieldValueHolder,
119
+ ): CompositeFieldValueHolder<TFields, EntityCompositeField<TFields>> {
120
+ return CompositeFieldValueHolder.deserialize(value);
121
+ }
122
+
123
+ validateRuntimeLoadValuesForDataManagerDataLoader(
124
+ values: readonly CompositeFieldValueHolder<TFields, EntityCompositeField<TFields>>[],
125
+ entityClassName: string,
126
+ ): void {
127
+ const isInvalidRuntimeCompositeFieldValue = (
128
+ value: CompositeFieldValueHolder<TFields, EntityCompositeField<TFields>>,
129
+ ): boolean =>
130
+ Object.values(value.compositeFieldValue).some(
131
+ (fieldValue) => fieldValue === undefined || fieldValue === null,
132
+ );
133
+
134
+ const invalidValueIndex = values.findIndex(isInvalidRuntimeCompositeFieldValue);
135
+ if (invalidValueIndex >= 0) {
136
+ throw new Error(
137
+ `Invalid load: ${entityClassName} (${String(this.compositeField)} = ${
138
+ values[invalidValueIndex]
139
+ })`,
140
+ );
141
+ }
142
+ }
143
+
144
+ vendNewLoadValueMap<V>(): LoadValueMap<
145
+ SerializedCompositeFieldValueHolder,
146
+ CompositeFieldValueHolder<TFields, EntityCompositeField<TFields>>,
147
+ V
148
+ > {
149
+ return new CompositeFieldValueHolderMap();
150
+ }
151
+ }
152
+
153
+ declare const CompositeFieldValueHolderSerializedBrand: unique symbol;
154
+ export type SerializedCompositeFieldValueHolder = string & {
155
+ readonly [CompositeFieldValueHolderSerializedBrand]: true;
156
+ };
157
+
158
+ /**
159
+ * A load value for a CompositeFieldHolder.
160
+ */
161
+ export class CompositeFieldValueHolder<
162
+ TFields extends Record<string, any>,
163
+ TCompositeField extends EntityCompositeField<TFields>,
164
+ > implements IEntityLoadValue<SerializedCompositeFieldValueHolder>
165
+ {
166
+ constructor(
167
+ public readonly compositeFieldValue: EntityCompositeFieldValue<TFields, TCompositeField>,
168
+ ) {}
169
+
170
+ toString(): string {
171
+ return `CompositeFieldValue(${Object.entries(this.compositeFieldValue)
172
+ .map(([fieldName, fieldValue]) => `${fieldName}=${fieldValue}`)
173
+ .join(',')})`;
174
+ }
175
+
176
+ public getFieldSet(): ReadonlySet<keyof TFields> {
177
+ return new Set(Object.keys(this.compositeFieldValue) as (keyof TFields)[]);
178
+ }
179
+
180
+ public static deserialize<
181
+ TFields extends Record<string, any>,
182
+ TCompositeField extends EntityCompositeField<TFields>,
183
+ >(
184
+ serialized: SerializedCompositeFieldValueHolder,
185
+ ): CompositeFieldValueHolder<TFields, TCompositeField> {
186
+ return new CompositeFieldValueHolder(
187
+ JSON.parse(serialized) as EntityCompositeFieldValue<TFields, TCompositeField>,
188
+ );
189
+ }
190
+
191
+ public serialize(): SerializedCompositeFieldValueHolder {
192
+ // Specify the ordered keys to serialize in a sorted manner to ensure consistent serialization
193
+ // between two objects of the same keys/values but different order.
194
+ // The replacer argument is "An array of strings and numbers that acts as an approved list
195
+ // for selecting the object properties that will be stringified."
196
+ // but it is a secondary effect of specifying the order of keys in the stringified object.
197
+ return JSON.stringify(
198
+ this.compositeFieldValue,
199
+ Object.keys(this.compositeFieldValue).sort(),
200
+ ) as SerializedCompositeFieldValueHolder;
201
+ }
202
+ }
203
+
204
+ export class CompositeFieldValueHolderMap<
205
+ TFields extends Record<string, any>,
206
+ N extends EntityCompositeField<TFields>,
207
+ V,
208
+ > extends LoadValueMap<
209
+ SerializedCompositeFieldValueHolder,
210
+ CompositeFieldValueHolder<TFields, N>,
211
+ V
212
+ > {
213
+ protected override deserializeKey(
214
+ serializedKey: SerializedCompositeFieldValueHolder,
215
+ ): CompositeFieldValueHolder<TFields, N> {
216
+ return CompositeFieldValueHolder.deserialize(serializedKey);
217
+ }
218
+ }
@@ -0,0 +1,78 @@
1
+ import { EntityCompositeField, EntityCompositeFieldValue } from '../EntityConfiguration';
2
+ import {
3
+ SerializedCompositeFieldValueHolder,
4
+ CompositeFieldValueHolder,
5
+ } from './CompositeFieldHolder';
6
+
7
+ export class CompositeFieldValueMap<
8
+ TFields extends Record<string, any>,
9
+ N extends EntityCompositeField<TFields>,
10
+ TOutput,
11
+ > implements ReadonlyMap<EntityCompositeFieldValue<TFields, N>, TOutput>
12
+ {
13
+ private readonly map: Map<SerializedCompositeFieldValueHolder, TOutput>;
14
+
15
+ constructor(entries: [CompositeFieldValueHolder<TFields, N>, TOutput][]) {
16
+ const map = new Map<SerializedCompositeFieldValueHolder, TOutput>();
17
+ for (const [key, value] of entries) {
18
+ map.set(key.serialize(), value);
19
+ }
20
+ this.map = map;
21
+ }
22
+
23
+ get(compositeFieldValue: EntityCompositeFieldValue<TFields, N>): TOutput | undefined {
24
+ return this.map.get(new CompositeFieldValueHolder(compositeFieldValue).serialize());
25
+ }
26
+
27
+ has(compositeFieldValue: EntityCompositeFieldValue<TFields, N>): boolean {
28
+ return this.map.has(new CompositeFieldValueHolder(compositeFieldValue).serialize());
29
+ }
30
+
31
+ forEach(
32
+ callbackfn: (
33
+ value: TOutput,
34
+ key: EntityCompositeFieldValue<TFields, N>,
35
+ map: CompositeFieldValueMap<TFields, N, TOutput>,
36
+ ) => void,
37
+ thisArg?: any,
38
+ ): void {
39
+ this.map.forEach((value, key) => {
40
+ callbackfn.call(
41
+ thisArg,
42
+ value,
43
+ CompositeFieldValueHolder.deserialize<TFields, N>(key).compositeFieldValue,
44
+ this,
45
+ );
46
+ });
47
+ }
48
+
49
+ get size(): number {
50
+ return this.map.size;
51
+ }
52
+
53
+ *entries(): MapIterator<[EntityCompositeFieldValue<TFields, N>, TOutput]> {
54
+ for (const [key, value] of this.map.entries()) {
55
+ yield [CompositeFieldValueHolder.deserialize<TFields, N>(key).compositeFieldValue, value];
56
+ }
57
+ }
58
+
59
+ *keys(): MapIterator<EntityCompositeFieldValue<TFields, N>> {
60
+ for (const key of this.map.keys()) {
61
+ yield CompositeFieldValueHolder.deserialize<TFields, N>(key).compositeFieldValue;
62
+ }
63
+ }
64
+
65
+ *values(): MapIterator<TOutput> {
66
+ for (const value of this.map.values()) {
67
+ yield value;
68
+ }
69
+ }
70
+
71
+ [Symbol.iterator](): MapIterator<[EntityCompositeFieldValue<TFields, N>, TOutput]> {
72
+ return this.entries();
73
+ }
74
+
75
+ get [Symbol.toStringTag](): string {
76
+ return 'CompositeFieldValueMap';
77
+ }
78
+ }
@@ -1,4 +1,5 @@
1
1
  import DataLoader from 'dataloader';
2
+ import invariant from 'invariant';
2
3
 
3
4
  import ReadThroughEntityCache from './ReadThroughEntityCache';
4
5
  import EntityDatabaseAdapter, {
@@ -9,6 +10,7 @@ import EntityDatabaseAdapter, {
9
10
  import { EntityQueryContext } from '../EntityQueryContext';
10
11
  import EntityQueryContextProvider from '../EntityQueryContextProvider';
11
12
  import { partitionErrors } from '../entityUtils';
13
+ import { IEntityLoadKey, IEntityLoadValue, LoadPair } from './EntityLoadInterfaces';
12
14
  import {
13
15
  timeAndLogLoadEventAsync,
14
16
  timeAndLogLoadMapEventAsync,
@@ -17,7 +19,7 @@ import IEntityMetricsAdapter, {
17
19
  EntityMetricsLoadType,
18
20
  IncrementLoadCountEventType,
19
21
  } from '../metrics/IEntityMetricsAdapter';
20
- import { computeIfAbsent, zipToMap } from '../utils/collections/maps';
22
+ import { computeIfAbsent } from '../utils/collections/maps';
21
23
 
22
24
  /**
23
25
  * A data manager is responsible for orchestrating multiple sources of entity
@@ -25,120 +27,138 @@ import { computeIfAbsent, zipToMap } from '../utils/collections/maps';
25
27
  *
26
28
  * It is also responsible for invalidating all sources of data when mutated using EntityMutator.
27
29
  */
28
- export default class EntityDataManager<TFields extends Record<string, any>> {
29
- private readonly fieldDataLoaders: Map<
30
- keyof TFields,
31
- DataLoader<NonNullable<TFields[keyof TFields]>, readonly Readonly<TFields>[]>
32
- > = new Map();
30
+ export default class EntityDataManager<
31
+ TFields extends Record<string, any>,
32
+ TIDField extends keyof TFields,
33
+ > {
34
+ private readonly dataloaders: Map<string, DataLoader<unknown, readonly Readonly<TFields>[]>> =
35
+ new Map();
33
36
 
34
37
  constructor(
35
- private readonly databaseAdapter: EntityDatabaseAdapter<TFields>,
36
- private readonly entityCache: ReadThroughEntityCache<TFields>,
38
+ private readonly databaseAdapter: EntityDatabaseAdapter<TFields, TIDField>,
39
+ private readonly entityCache: ReadThroughEntityCache<TFields, TIDField>,
37
40
  private readonly queryContextProvider: EntityQueryContextProvider,
38
41
  private readonly metricsAdapter: IEntityMetricsAdapter,
39
42
  private readonly entityClassName: string,
40
43
  ) {}
41
44
 
42
- private getFieldDataLoaderForFieldName<N extends keyof TFields>(
43
- fieldName: N,
44
- ): DataLoader<NonNullable<TFields[N]>, readonly Readonly<TFields>[]> {
45
- return computeIfAbsent(this.fieldDataLoaders, fieldName, () => {
46
- return new DataLoader(
47
- async (
48
- fieldValues: readonly NonNullable<TFields[N]>[],
49
- ): Promise<readonly (readonly TFields[])[]> => {
50
- const objectMap = await this.loadManyForDataLoaderByFieldEqualingAsync(
51
- fieldName,
52
- fieldValues,
53
- );
54
- return fieldValues.map((fv) => objectMap.get(fv) ?? []);
55
- },
56
- );
57
- });
45
+ private getDataLoaderForLoadKey<
46
+ TLoadKey extends IEntityLoadKey<TFields, TIDField, TSerializedLoadValue, TLoadValue>,
47
+ TSerializedLoadValue,
48
+ TLoadValue extends IEntityLoadValue<TSerializedLoadValue>,
49
+ >(key: TLoadKey): DataLoader<TSerializedLoadValue, readonly Readonly<TFields>[]> {
50
+ return computeIfAbsent(
51
+ this.dataloaders,
52
+ key.getLoadMethodType() + key.getDataManagerDataLoaderKey(),
53
+ () => {
54
+ return new DataLoader(
55
+ async (
56
+ serializedLoadValues: readonly TSerializedLoadValue[],
57
+ ): Promise<readonly (readonly TFields[])[]> => {
58
+ const values = serializedLoadValues.map((serializedLoadValue) =>
59
+ key.deserializeLoadValue(serializedLoadValue),
60
+ );
61
+ const objectMap = await this.loadManyForDataLoaderAsync(key, values);
62
+ return values.map((value) => objectMap.get(value) ?? []);
63
+ },
64
+ );
65
+ },
66
+ );
58
67
  }
59
68
 
60
- private async loadManyForDataLoaderByFieldEqualingAsync<N extends keyof TFields>(
61
- fieldName: N,
62
- fieldValues: readonly NonNullable<TFields[N]>[],
63
- ): Promise<ReadonlyMap<NonNullable<TFields[N]>, readonly Readonly<TFields>[]>> {
69
+ private async loadManyForDataLoaderAsync<
70
+ TLoadKey extends IEntityLoadKey<TFields, TIDField, TSerializedLoadValue, TLoadValue>,
71
+ TSerializedLoadValue,
72
+ TLoadValue extends IEntityLoadValue<TSerializedLoadValue>,
73
+ >(
74
+ key: TLoadKey,
75
+ values: readonly TLoadValue[],
76
+ ): Promise<ReadonlyMap<TLoadValue, readonly Readonly<TFields>[]>> {
64
77
  this.metricsAdapter.incrementDataManagerLoadCount({
65
78
  type: IncrementLoadCountEventType.CACHE,
66
- fieldValueCount: fieldValues.length,
79
+ fieldValueCount: values.length,
67
80
  entityClassName: this.entityClassName,
81
+ loadType: key.getLoadMethodType(),
82
+ });
83
+
84
+ return await this.entityCache.readManyThroughAsync(key, values, async (fetcherValues) => {
85
+ this.metricsAdapter.incrementDataManagerLoadCount({
86
+ type: IncrementLoadCountEventType.DATABASE,
87
+ fieldValueCount: fetcherValues.length,
88
+ entityClassName: this.entityClassName,
89
+ loadType: key.getLoadMethodType(),
90
+ });
91
+ return await this.databaseAdapter.fetchManyWhereAsync(
92
+ this.queryContextProvider.getQueryContext(),
93
+ key,
94
+ fetcherValues,
95
+ );
68
96
  });
69
- return await this.entityCache.readManyThroughAsync(
70
- fieldName,
71
- fieldValues,
72
- async (fetcherValues) => {
73
- this.metricsAdapter.incrementDataManagerLoadCount({
74
- type: IncrementLoadCountEventType.DATABASE,
75
- fieldValueCount: fieldValues.length,
76
- entityClassName: this.entityClassName,
77
- });
78
- return await this.databaseAdapter.fetchManyWhereAsync(
79
- this.queryContextProvider.getQueryContext(),
80
- fieldName,
81
- fetcherValues,
82
- );
83
- },
84
- );
85
97
  }
86
98
 
87
99
  /**
88
- * Load many objects where fieldName is one of fieldValues.
100
+ * Load many objects through read-through dataloader (batcher) and cache (optional).
89
101
  *
90
102
  * @param queryContext - query context in which to perform the load
91
- * @param fieldName - object field being queried
92
- * @param fieldValues - fieldName field values being queried
93
- * @returns map from fieldValue to objects that match the query for that fieldValue
103
+ * @param key - load key being queried
104
+ * @param values - load values being queried for the key
105
+ * @returns map from load value to objects that match the query for that load value
94
106
  */
95
- async loadManyByFieldEqualingAsync<N extends keyof TFields>(
107
+ async loadManyEqualingAsync<
108
+ TLoadKey extends IEntityLoadKey<TFields, TIDField, TSerializedLoadValue, TLoadValue>,
109
+ TSerializedLoadValue,
110
+ TLoadValue extends IEntityLoadValue<TSerializedLoadValue>,
111
+ >(
96
112
  queryContext: EntityQueryContext,
97
- fieldName: N,
98
- fieldValues: readonly NonNullable<TFields[N]>[],
99
- ): Promise<ReadonlyMap<NonNullable<TFields[N]>, readonly Readonly<TFields>[]>> {
113
+ key: TLoadKey,
114
+ values: readonly TLoadValue[],
115
+ ): Promise<ReadonlyMap<TLoadValue, readonly Readonly<TFields>[]>> {
100
116
  return await timeAndLogLoadMapEventAsync(
101
117
  this.metricsAdapter,
102
118
  EntityMetricsLoadType.LOAD_MANY,
103
119
  this.entityClassName,
104
- )(this.loadManyByFieldEqualingInternalAsync(queryContext, fieldName, fieldValues));
120
+ )(this.loadManyEqualingInternalAsync(queryContext, key, values));
105
121
  }
106
122
 
107
- private async loadManyByFieldEqualingInternalAsync<N extends keyof TFields>(
123
+ private async loadManyEqualingInternalAsync<
124
+ TLoadKey extends IEntityLoadKey<TFields, TIDField, TSerializedLoadValue, TLoadValue>,
125
+ TSerializedLoadValue,
126
+ TLoadValue extends IEntityLoadValue<TSerializedLoadValue>,
127
+ >(
108
128
  queryContext: EntityQueryContext,
109
- fieldName: N,
110
- fieldValues: readonly NonNullable<TFields[N]>[],
111
- ): Promise<ReadonlyMap<NonNullable<TFields[N]>, readonly Readonly<TFields>[]>> {
112
- const nullOrUndefinedValueIndex = fieldValues.findIndex(
113
- (value) => value === null || value === undefined,
114
- );
115
- if (nullOrUndefinedValueIndex >= 0) {
116
- throw new Error(
117
- `Invalid load: ${this.entityClassName} (${String(fieldName)} = ${
118
- fieldValues[nullOrUndefinedValueIndex]
119
- })`,
120
- );
121
- }
129
+ key: TLoadKey,
130
+ values: readonly TLoadValue[],
131
+ ): Promise<ReadonlyMap<TLoadValue, readonly Readonly<TFields>[]>> {
132
+ key.validateRuntimeLoadValuesForDataManagerDataLoader(values, this.entityClassName);
122
133
 
123
134
  // don't cache when in transaction, as rollbacks complicate things significantly
124
135
  if (queryContext.isInTransaction()) {
125
- return await this.databaseAdapter.fetchManyWhereAsync(queryContext, fieldName, fieldValues);
136
+ return await this.databaseAdapter.fetchManyWhereAsync(queryContext, key, values);
126
137
  }
127
138
 
128
139
  this.metricsAdapter.incrementDataManagerLoadCount({
129
140
  type: IncrementLoadCountEventType.DATALOADER,
130
- fieldValueCount: fieldValues.length,
141
+ fieldValueCount: values.length,
131
142
  entityClassName: this.entityClassName,
143
+ loadType: key.getLoadMethodType(),
132
144
  });
133
- const dataLoader = this.getFieldDataLoaderForFieldName(fieldName);
134
- const results = await dataLoader.loadMany(fieldValues);
135
- const [values, errors] = partitionErrors(results);
145
+ const dataLoader = this.getDataLoaderForLoadKey(key);
146
+ const results = await dataLoader.loadMany(values.map((v) => key.serializeLoadValue(v)));
147
+ const [successfulValues, errors] = partitionErrors(results);
136
148
  if (errors.length > 0) {
137
149
  const error = errors[0]!;
138
150
  throw error;
139
151
  }
140
152
 
141
- return zipToMap(fieldValues, values);
153
+ invariant(
154
+ values.length === successfulValues.length,
155
+ `length mismatch between values (${values.length}) and successful values (${successfulValues.length})`,
156
+ );
157
+ const mapToReturn = key.vendNewLoadValueMap<readonly Readonly<TFields>[]>();
158
+ for (let i = 0; i < successfulValues.length; i++) {
159
+ mapToReturn.set(values[i]!, successfulValues[i]!);
160
+ }
161
+ return mapToReturn;
142
162
  }
143
163
 
144
164
  /**
@@ -197,32 +217,23 @@ export default class EntityDataManager<TFields extends Record<string, any>> {
197
217
  );
198
218
  }
199
219
 
200
- private async invalidateManyByFieldEqualingAsync<N extends keyof TFields>(
201
- fieldName: N,
202
- fieldValues: readonly NonNullable<TFields[N]>[],
203
- ): Promise<void> {
204
- await this.entityCache.invalidateManyAsync(fieldName, fieldValues);
205
- const dataLoader = this.getFieldDataLoaderForFieldName(fieldName);
206
- fieldValues.forEach((fieldValue) => dataLoader.clear(fieldValue));
220
+ private async invalidateOneAsync<
221
+ TLoadKey extends IEntityLoadKey<TFields, TIDField, TSerializedLoadValue, TLoadValue>,
222
+ TSerializedLoadValue,
223
+ TLoadValue extends IEntityLoadValue<TSerializedLoadValue>,
224
+ >(key: TLoadKey, value: TLoadValue): Promise<void> {
225
+ await this.entityCache.invalidateManyAsync(key, [value]);
226
+ this.getDataLoaderForLoadKey(key).clear(key.serializeLoadValue(value));
207
227
  }
208
228
 
209
229
  /**
210
- * Invalidate all caches, in-memory or otherwise, for an object.
211
- *
212
- * @param objectFields - object to invalidate from all applicable caches
230
+ * Invalidate all caches, in-memory or otherwise, for sets of key-value pairs.
231
+ * @param pairs - key-value pairs to invalidate
213
232
  */
214
- async invalidateObjectFieldsAsync(objectFields: Readonly<TFields>): Promise<void> {
233
+ public async invalidateKeyValuePairsAsync(
234
+ pairs: readonly LoadPair<TFields, TIDField, any, any, any>[],
235
+ ): Promise<void> {
215
236
  // TODO(wschurman): check for races with load
216
- const keys = Object.keys(objectFields) as (keyof TFields)[];
217
- await Promise.all(
218
- keys.map(async (fieldName: keyof TFields) => {
219
- const value = objectFields[fieldName];
220
- if (value !== undefined) {
221
- await this.invalidateManyByFieldEqualingAsync(fieldName, [
222
- value as NonNullable<TFields[keyof TFields]>,
223
- ]);
224
- }
225
- }),
226
- );
237
+ await Promise.all(pairs.map(([key, value]) => this.invalidateOneAsync(key, value)));
227
238
  }
228
239
  }