@expo/entity 0.40.0 → 0.42.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 (433) hide show
  1. package/build/AuthorizationResultBasedEntityAssociationLoader.d.ts +16 -16
  2. package/build/AuthorizationResultBasedEntityAssociationLoader.js +2 -4
  3. package/build/AuthorizationResultBasedEntityAssociationLoader.js.map +1 -1
  4. package/build/AuthorizationResultBasedEntityLoader.d.ts +39 -67
  5. package/build/AuthorizationResultBasedEntityLoader.js +85 -62
  6. package/build/AuthorizationResultBasedEntityLoader.js.map +1 -1
  7. package/build/AuthorizationResultBasedEntityMutator.d.ts +16 -16
  8. package/build/AuthorizationResultBasedEntityMutator.js.map +1 -1
  9. package/build/ComposedEntityCacheAdapter.d.ts +7 -6
  10. package/build/ComposedEntityCacheAdapter.js +28 -28
  11. package/build/ComposedEntityCacheAdapter.js.map +1 -1
  12. package/build/ComposedSecondaryEntityCache.d.ts +1 -1
  13. package/build/ComposedSecondaryEntityCache.js.map +1 -1
  14. package/build/EnforcingEntityAssociationLoader.d.ts +15 -15
  15. package/build/EnforcingEntityAssociationLoader.js.map +1 -1
  16. package/build/EnforcingEntityCreator.d.ts +2 -2
  17. package/build/EnforcingEntityDeleter.d.ts +2 -2
  18. package/build/EnforcingEntityLoader.d.ts +104 -18
  19. package/build/EnforcingEntityLoader.js +113 -12
  20. package/build/EnforcingEntityLoader.js.map +1 -1
  21. package/build/EnforcingEntityUpdater.d.ts +2 -2
  22. package/build/Entity.d.ts +32 -10
  23. package/build/Entity.js +41 -3
  24. package/build/Entity.js.map +1 -1
  25. package/build/EntityAssociationLoader.d.ts +3 -3
  26. package/build/EntityCompanion.d.ts +5 -5
  27. package/build/EntityCompanion.js.map +1 -1
  28. package/build/EntityCompanionProvider.d.ts +6 -6
  29. package/build/EntityCompanionProvider.js.map +1 -1
  30. package/build/EntityConfiguration.d.ts +46 -5
  31. package/build/EntityConfiguration.js +39 -1
  32. package/build/EntityConfiguration.js.map +1 -1
  33. package/build/EntityCreator.d.ts +4 -4
  34. package/build/EntityDatabaseAdapter.d.ts +15 -14
  35. package/build/EntityDatabaseAdapter.js +20 -12
  36. package/build/EntityDatabaseAdapter.js.map +1 -1
  37. package/build/EntityDeleter.d.ts +4 -4
  38. package/build/EntityFieldDefinition.d.ts +20 -10
  39. package/build/EntityFieldDefinition.js +3 -1
  40. package/build/EntityFieldDefinition.js.map +1 -1
  41. package/build/EntityFields.d.ts +14 -12
  42. package/build/EntityFields.js.map +1 -1
  43. package/build/EntityLoader.d.ts +5 -5
  44. package/build/EntityLoaderFactory.d.ts +3 -3
  45. package/build/EntityLoaderFactory.js.map +1 -1
  46. package/build/EntityLoaderUtils.d.ts +2 -2
  47. package/build/EntityLoaderUtils.js +27 -1
  48. package/build/EntityLoaderUtils.js.map +1 -1
  49. package/build/EntityMutationInfo.d.ts +2 -2
  50. package/build/EntityMutationTriggerConfiguration.d.ts +14 -14
  51. package/build/EntityMutationTriggerConfiguration.js.map +1 -1
  52. package/build/EntityMutationValidator.d.ts +2 -2
  53. package/build/EntityMutatorFactory.d.ts +5 -5
  54. package/build/EntityMutatorFactory.js.map +1 -1
  55. package/build/EntityPrivacyPolicy.d.ts +14 -14
  56. package/build/EntityPrivacyPolicy.js.map +1 -1
  57. package/build/EntitySecondaryCacheLoader.d.ts +4 -4
  58. package/build/EntityUpdater.d.ts +4 -4
  59. package/build/GenericEntityCacheAdapter.d.ts +7 -6
  60. package/build/GenericEntityCacheAdapter.js +13 -14
  61. package/build/GenericEntityCacheAdapter.js.map +1 -1
  62. package/build/GenericSecondaryEntityCache.d.ts +3 -3
  63. package/build/GenericSecondaryEntityCache.js.map +1 -1
  64. package/build/IEntityCacheAdapter.d.ts +17 -16
  65. package/build/IEntityCacheAdapterProvider.d.ts +1 -1
  66. package/build/IEntityDatabaseAdapterProvider.d.ts +1 -1
  67. package/build/IEntityGenericCacher.d.ts +15 -5
  68. package/build/ReadonlyEntity.d.ts +27 -8
  69. package/build/ReadonlyEntity.js +31 -3
  70. package/build/ReadonlyEntity.js.map +1 -1
  71. package/build/ViewerContext.d.ts +1 -1
  72. package/build/ViewerScopedEntityCompanion.d.ts +5 -5
  73. package/build/ViewerScopedEntityCompanionProvider.d.ts +1 -1
  74. package/build/ViewerScopedEntityLoaderFactory.d.ts +3 -3
  75. package/build/ViewerScopedEntityMutatorFactory.d.ts +5 -5
  76. package/build/entityUtils.d.ts +1 -1
  77. package/build/entityUtils.js.map +1 -1
  78. package/build/errors/EntityInvalidFieldValueError.d.ts +2 -2
  79. package/build/errors/EntityNotAuthorizedError.d.ts +1 -1
  80. package/build/errors/EntityNotFoundError.d.ts +2 -2
  81. package/build/index.d.ts +7 -7
  82. package/build/index.js +8 -13
  83. package/build/index.js.map +1 -1
  84. package/build/internal/CompositeFieldHolder.d.ts +48 -0
  85. package/build/internal/CompositeFieldHolder.js +116 -0
  86. package/build/internal/CompositeFieldHolder.js.map +1 -0
  87. package/build/internal/CompositeFieldValueMap.d.ts +15 -0
  88. package/build/internal/CompositeFieldValueMap.js +51 -0
  89. package/build/internal/CompositeFieldValueMap.js.map +1 -0
  90. package/build/internal/EntityDataManager.d.ts +16 -16
  91. package/build/internal/EntityDataManager.js +42 -45
  92. package/build/internal/EntityDataManager.js.map +1 -1
  93. package/build/internal/EntityFieldTransformationUtils.d.ts +5 -5
  94. package/build/internal/EntityFieldTransformationUtils.js.map +1 -1
  95. package/build/internal/EntityLoadInterfaces.d.ts +104 -0
  96. package/build/internal/EntityLoadInterfaces.js +25 -0
  97. package/build/internal/EntityLoadInterfaces.js.map +1 -0
  98. package/build/internal/EntityTableDataCoordinator.d.ts +6 -6
  99. package/build/internal/EntityTableDataCoordinator.js.map +1 -1
  100. package/build/internal/ReadThroughEntityCache.d.ts +17 -16
  101. package/build/internal/ReadThroughEntityCache.js +36 -36
  102. package/build/internal/ReadThroughEntityCache.js.map +1 -1
  103. package/build/internal/SingleFieldHolder.d.ts +34 -0
  104. package/build/internal/SingleFieldHolder.js +90 -0
  105. package/build/internal/SingleFieldHolder.js.map +1 -0
  106. package/build/metrics/EntityMetricsUtils.d.ts +2 -1
  107. package/build/metrics/EntityMetricsUtils.js.map +1 -1
  108. package/build/metrics/IEntityMetricsAdapter.d.ts +5 -0
  109. package/build/metrics/IEntityMetricsAdapter.js.map +1 -1
  110. package/build/rules/AlwaysAllowPrivacyPolicyRule.d.ts +2 -2
  111. package/build/rules/AlwaysAllowPrivacyPolicyRule.js.map +1 -1
  112. package/build/rules/AlwaysDenyPrivacyPolicyRule.d.ts +2 -2
  113. package/build/rules/AlwaysDenyPrivacyPolicyRule.js.map +1 -1
  114. package/build/rules/AlwaysSkipPrivacyPolicyRule.d.ts +2 -2
  115. package/build/rules/AlwaysSkipPrivacyPolicyRule.js.map +1 -1
  116. package/build/rules/PrivacyPolicyRule.d.ts +2 -2
  117. package/build/tsconfig.build.tsbuildinfo +1 -0
  118. package/build/utils/EntityPrivacyUtils.d.ts +4 -4
  119. package/build/utils/EntityPrivacyUtils.js.map +1 -1
  120. package/build/utils/collections/SerializableKeyMap.d.ts +27 -0
  121. package/build/utils/collections/SerializableKeyMap.js +60 -0
  122. package/build/utils/collections/SerializableKeyMap.js.map +1 -0
  123. package/build/utils/collections/maps.js +1 -2
  124. package/build/utils/collections/maps.js.map +1 -1
  125. package/build/utils/collections/sets.d.ts +1 -0
  126. package/build/utils/collections/sets.js +7 -0
  127. package/build/utils/collections/sets.js.map +1 -0
  128. package/build/utils/mergeEntityMutationTriggerConfigurations.d.ts +1 -1
  129. package/package.json +8 -5
  130. package/src/AuthorizationResultBasedEntityAssociationLoader.ts +58 -53
  131. package/src/AuthorizationResultBasedEntityLoader.ts +194 -81
  132. package/src/AuthorizationResultBasedEntityMutator.ts +71 -45
  133. package/src/ComposedEntityCacheAdapter.ts +55 -46
  134. package/src/ComposedSecondaryEntityCache.ts +5 -2
  135. package/src/EnforcingEntityAssociationLoader.ts +52 -44
  136. package/src/EnforcingEntityCreator.ts +5 -5
  137. package/src/EnforcingEntityDeleter.ts +5 -5
  138. package/src/EnforcingEntityLoader.ts +158 -21
  139. package/src/EnforcingEntityUpdater.ts +5 -5
  140. package/src/Entity.ts +185 -29
  141. package/src/EntityAssociationLoader.ts +6 -6
  142. package/src/EntityCompanion.ts +11 -11
  143. package/src/EntityCompanionProvider.ts +21 -18
  144. package/src/EntityConfiguration.ts +123 -9
  145. package/src/EntityCreator.ts +7 -7
  146. package/src/EntityDatabaseAdapter.ts +51 -28
  147. package/src/EntityDeleter.ts +7 -7
  148. package/src/EntityFieldDefinition.ts +32 -12
  149. package/src/EntityFields.ts +49 -12
  150. package/src/EntityLoader.ts +8 -8
  151. package/src/EntityLoaderFactory.ts +8 -8
  152. package/src/EntityLoaderUtils.ts +39 -10
  153. package/src/EntityMutationInfo.ts +6 -6
  154. package/src/EntityMutationTriggerConfiguration.ts +68 -20
  155. package/src/EntityMutationValidator.ts +4 -4
  156. package/src/EntityMutatorFactory.ts +13 -13
  157. package/src/EntityPrivacyPolicy.ts +50 -26
  158. package/src/EntitySecondaryCacheLoader.ts +6 -6
  159. package/src/EntityUpdater.ts +7 -7
  160. package/src/GenericEntityCacheAdapter.ts +39 -28
  161. package/src/GenericSecondaryEntityCache.ts +6 -3
  162. package/src/IEntityCacheAdapter.ts +45 -25
  163. package/src/IEntityCacheAdapterProvider.ts +3 -3
  164. package/src/IEntityDatabaseAdapterProvider.ts +3 -3
  165. package/src/IEntityGenericCacher.ts +33 -5
  166. package/src/ReadonlyEntity.ts +129 -16
  167. package/src/ViewerContext.ts +5 -5
  168. package/src/ViewerScopedEntityCompanion.ts +7 -7
  169. package/src/ViewerScopedEntityCompanionProvider.ts +6 -6
  170. package/src/ViewerScopedEntityLoaderFactory.ts +7 -7
  171. package/src/ViewerScopedEntityMutatorFactory.ts +8 -8
  172. package/src/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.ts +41 -72
  173. package/src/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.ts +14 -13
  174. package/src/__tests__/AuthorizationResultBasedEntityLoader-test.ts +367 -69
  175. package/src/__tests__/ComposedCacheAdapter-test.ts +235 -117
  176. package/src/__tests__/EnforcingEntityLoader-test.ts +135 -1
  177. package/src/__tests__/Entity-test.ts +64 -11
  178. package/src/__tests__/EntityAssociationLoader-test.ts +6 -8
  179. package/src/__tests__/EntityCommonUseCases-test.ts +25 -28
  180. package/src/__tests__/EntityCompanion-test.ts +4 -4
  181. package/src/__tests__/EntityCompanionProvider-test.ts +9 -8
  182. package/src/__tests__/EntityConfiguration-test.ts +85 -6
  183. package/src/__tests__/EntityDatabaseAdapter-test.ts +113 -17
  184. package/src/__tests__/EntityEdges-test.ts +135 -138
  185. package/src/__tests__/EntityFields-test.ts +2 -2
  186. package/src/__tests__/EntityLoader-test.ts +5 -7
  187. package/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts +17 -19
  188. package/src/__tests__/EntityMutator-SingleCompositeFieldCacheConsistency-test.ts +73 -0
  189. package/src/__tests__/EntityMutator-test.ts +74 -46
  190. package/src/__tests__/EntityPrivacyPolicy-test.ts +51 -74
  191. package/src/__tests__/EntityQueryContext-test.ts +1 -1
  192. package/src/__tests__/EntitySecondaryCacheLoader-test.ts +9 -9
  193. package/src/__tests__/EntitySelfReferentialEdges-test.ts +119 -122
  194. package/src/__tests__/GenericEntityCacheAdapter-test.ts +83 -28
  195. package/src/__tests__/ReadonlyEntity-test.ts +49 -9
  196. package/src/__tests__/ViewerContext-test.ts +1 -1
  197. package/src/__tests__/ViewerScopedEntityCompanion-test.ts +5 -2
  198. package/src/__tests__/ViewerScopedEntityCompanionProvider-test.ts +1 -1
  199. package/src/__tests__/ViewerScopedEntityMutatorFactory-test.ts +12 -3
  200. package/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts +25 -27
  201. package/src/__tests__/cases/TwoEntitySameTableOverlappingRows-test.ts +28 -34
  202. package/src/entityUtils.ts +4 -1
  203. package/src/errors/EntityInvalidFieldValueError.ts +5 -5
  204. package/src/errors/EntityNotAuthorizedError.ts +3 -3
  205. package/src/errors/EntityNotFoundError.ts +5 -5
  206. package/src/index.ts +7 -7
  207. package/src/internal/CompositeFieldHolder.ts +218 -0
  208. package/src/internal/CompositeFieldValueMap.ts +78 -0
  209. package/src/internal/EntityDataManager.ts +107 -96
  210. package/src/internal/EntityFieldTransformationUtils.ts +33 -14
  211. package/src/internal/EntityLoadInterfaces.ts +143 -0
  212. package/src/internal/EntityTableDataCoordinator.ts +8 -5
  213. package/src/internal/ReadThroughEntityCache.ts +63 -50
  214. package/src/internal/SingleFieldHolder.ts +131 -0
  215. package/src/internal/__tests__/CompositeFieldHolder-test.ts +25 -0
  216. package/src/internal/__tests__/CompositeFieldValueMap-test.ts +43 -0
  217. package/src/internal/__tests__/EntityDataManager-test.ts +308 -91
  218. package/src/internal/__tests__/EntityFieldTransformationUtils-test.ts +3 -2
  219. package/src/internal/__tests__/ReadThroughEntityCache-test.ts +315 -107
  220. package/src/metrics/EntityMetricsUtils.ts +7 -2
  221. package/src/metrics/IEntityMetricsAdapter.ts +6 -0
  222. package/src/rules/AlwaysAllowPrivacyPolicyRule.ts +5 -5
  223. package/src/rules/AlwaysDenyPrivacyPolicyRule.ts +5 -5
  224. package/src/rules/AlwaysSkipPrivacyPolicyRule.ts +5 -5
  225. package/src/rules/PrivacyPolicyRule.ts +4 -4
  226. package/src/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.ts +1 -1
  227. package/src/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.ts +1 -1
  228. package/src/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.ts +1 -1
  229. package/src/utils/EntityPrivacyUtils.ts +72 -30
  230. package/src/utils/{testing → __testfixtures__}/PrivacyPolicyRuleTestUtils.ts +26 -26
  231. package/src/{testfixtures → utils/__testfixtures__}/SimpleTestEntity.ts +16 -15
  232. package/src/utils/__testfixtures__/StubCacheAdapter.ts +164 -0
  233. package/src/utils/{testing → __testfixtures__}/StubDatabaseAdapter.ts +19 -12
  234. package/src/utils/{testing → __testfixtures__}/StubDatabaseAdapterProvider.ts +4 -4
  235. package/src/utils/__testfixtures__/TSMockitoExtensions.ts +69 -0
  236. package/src/{testfixtures → utils/__testfixtures__}/TestEntity.ts +21 -15
  237. package/src/{testfixtures → utils/__testfixtures__}/TestEntity2.ts +16 -15
  238. package/src/{testfixtures → utils/__testfixtures__}/TestEntityWithMutationTriggers.ts +23 -22
  239. package/src/{testfixtures → utils/__testfixtures__}/TestViewerContext.ts +1 -1
  240. package/src/utils/{testing → __testfixtures__}/describeFieldTestCase.ts +1 -1
  241. package/src/utils/__tests__/EntityPrivacyUtils-test.ts +81 -113
  242. package/src/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.ts +31 -30
  243. package/src/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.ts +1 -1
  244. package/src/utils/collections/SerializableKeyMap.ts +84 -0
  245. package/src/utils/collections/__tests__/SerializableKeyMap-test.ts +119 -0
  246. package/src/utils/collections/__tests__/sets-test.ts +17 -0
  247. package/src/utils/collections/maps.ts +7 -8
  248. package/src/utils/collections/sets.ts +3 -0
  249. package/src/utils/mergeEntityMutationTriggerConfigurations.ts +5 -5
  250. package/build/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.d.ts +0 -1
  251. package/build/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.js +0 -273
  252. package/build/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.js.map +0 -1
  253. package/build/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.d.ts +0 -26
  254. package/build/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.js +0 -110
  255. package/build/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.js.map +0 -1
  256. package/build/__tests__/AuthorizationResultBasedEntityLoader-test.d.ts +0 -1
  257. package/build/__tests__/AuthorizationResultBasedEntityLoader-test.js +0 -401
  258. package/build/__tests__/AuthorizationResultBasedEntityLoader-test.js.map +0 -1
  259. package/build/__tests__/ComposedCacheAdapter-test.d.ts +0 -1
  260. package/build/__tests__/ComposedCacheAdapter-test.js +0 -229
  261. package/build/__tests__/ComposedCacheAdapter-test.js.map +0 -1
  262. package/build/__tests__/ComposedSecondaryEntityCache-test.d.ts +0 -1
  263. package/build/__tests__/ComposedSecondaryEntityCache-test.js +0 -66
  264. package/build/__tests__/ComposedSecondaryEntityCache-test.js.map +0 -1
  265. package/build/__tests__/EnforcingEntityAssociationLoader-test.d.ts +0 -1
  266. package/build/__tests__/EnforcingEntityAssociationLoader-test.js +0 -115
  267. package/build/__tests__/EnforcingEntityAssociationLoader-test.js.map +0 -1
  268. package/build/__tests__/EnforcingEntityLoader-test.d.ts +0 -1
  269. package/build/__tests__/EnforcingEntityLoader-test.js +0 -253
  270. package/build/__tests__/EnforcingEntityLoader-test.js.map +0 -1
  271. package/build/__tests__/Entity-test.d.ts +0 -1
  272. package/build/__tests__/Entity-test.js +0 -54
  273. package/build/__tests__/Entity-test.js.map +0 -1
  274. package/build/__tests__/EntityAssociationLoader-test.d.ts +0 -1
  275. package/build/__tests__/EntityAssociationLoader-test.js +0 -30
  276. package/build/__tests__/EntityAssociationLoader-test.js.map +0 -1
  277. package/build/__tests__/EntityCommonUseCases-test.d.ts +0 -1
  278. package/build/__tests__/EntityCommonUseCases-test.js +0 -154
  279. package/build/__tests__/EntityCommonUseCases-test.js.map +0 -1
  280. package/build/__tests__/EntityCompanion-test.d.ts +0 -1
  281. package/build/__tests__/EntityCompanion-test.js +0 -77
  282. package/build/__tests__/EntityCompanion-test.js.map +0 -1
  283. package/build/__tests__/EntityCompanionProvider-test.d.ts +0 -1
  284. package/build/__tests__/EntityCompanionProvider-test.js +0 -54
  285. package/build/__tests__/EntityCompanionProvider-test.js.map +0 -1
  286. package/build/__tests__/EntityConfiguration-test.d.ts +0 -1
  287. package/build/__tests__/EntityConfiguration-test.js +0 -103
  288. package/build/__tests__/EntityConfiguration-test.js.map +0 -1
  289. package/build/__tests__/EntityDatabaseAdapter-test.d.ts +0 -1
  290. package/build/__tests__/EntityDatabaseAdapter-test.js +0 -146
  291. package/build/__tests__/EntityDatabaseAdapter-test.js.map +0 -1
  292. package/build/__tests__/EntityEdges-test.d.ts +0 -1
  293. package/build/__tests__/EntityEdges-test.js +0 -755
  294. package/build/__tests__/EntityEdges-test.js.map +0 -1
  295. package/build/__tests__/EntityFields-test.d.ts +0 -1
  296. package/build/__tests__/EntityFields-test.js +0 -63
  297. package/build/__tests__/EntityFields-test.js.map +0 -1
  298. package/build/__tests__/EntityLoader-test.d.ts +0 -1
  299. package/build/__tests__/EntityLoader-test.js +0 -36
  300. package/build/__tests__/EntityLoader-test.js.map +0 -1
  301. package/build/__tests__/EntityMutator-MutationCacheConsistency-test.d.ts +0 -1
  302. package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js +0 -77
  303. package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js.map +0 -1
  304. package/build/__tests__/EntityMutator-test.d.ts +0 -1
  305. package/build/__tests__/EntityMutator-test.js +0 -741
  306. package/build/__tests__/EntityMutator-test.js.map +0 -1
  307. package/build/__tests__/EntityPrivacyPolicy-test.d.ts +0 -1
  308. package/build/__tests__/EntityPrivacyPolicy-test.js +0 -463
  309. package/build/__tests__/EntityPrivacyPolicy-test.js.map +0 -1
  310. package/build/__tests__/EntityQueryContext-test.d.ts +0 -1
  311. package/build/__tests__/EntityQueryContext-test.js +0 -116
  312. package/build/__tests__/EntityQueryContext-test.js.map +0 -1
  313. package/build/__tests__/EntitySecondaryCacheLoader-test.d.ts +0 -1
  314. package/build/__tests__/EntitySecondaryCacheLoader-test.js +0 -60
  315. package/build/__tests__/EntitySecondaryCacheLoader-test.js.map +0 -1
  316. package/build/__tests__/EntitySelfReferentialEdges-test.d.ts +0 -1
  317. package/build/__tests__/EntitySelfReferentialEdges-test.js +0 -247
  318. package/build/__tests__/EntitySelfReferentialEdges-test.js.map +0 -1
  319. package/build/__tests__/GenericEntityCacheAdapter-test.d.ts +0 -1
  320. package/build/__tests__/GenericEntityCacheAdapter-test.js +0 -80
  321. package/build/__tests__/GenericEntityCacheAdapter-test.js.map +0 -1
  322. package/build/__tests__/ReadonlyEntity-test.d.ts +0 -1
  323. package/build/__tests__/ReadonlyEntity-test.js +0 -178
  324. package/build/__tests__/ReadonlyEntity-test.js.map +0 -1
  325. package/build/__tests__/ViewerContext-test.d.ts +0 -1
  326. package/build/__tests__/ViewerContext-test.js +0 -30
  327. package/build/__tests__/ViewerContext-test.js.map +0 -1
  328. package/build/__tests__/ViewerScopedEntityCompanion-test.d.ts +0 -1
  329. package/build/__tests__/ViewerScopedEntityCompanion-test.js +0 -20
  330. package/build/__tests__/ViewerScopedEntityCompanion-test.js.map +0 -1
  331. package/build/__tests__/ViewerScopedEntityCompanionProvider-test.d.ts +0 -1
  332. package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js +0 -20
  333. package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js.map +0 -1
  334. package/build/__tests__/ViewerScopedEntityLoaderFactory-test.d.ts +0 -1
  335. package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js +0 -23
  336. package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js.map +0 -1
  337. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.d.ts +0 -1
  338. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js +0 -22
  339. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js.map +0 -1
  340. package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.d.ts +0 -1
  341. package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js +0 -129
  342. package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js.map +0 -1
  343. package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.d.ts +0 -1
  344. package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js +0 -136
  345. package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js.map +0 -1
  346. package/build/__tests__/entityUtils-test.d.ts +0 -1
  347. package/build/__tests__/entityUtils-test.js +0 -87
  348. package/build/__tests__/entityUtils-test.js.map +0 -1
  349. package/build/internal/__tests__/EntityDataManager-test.d.ts +0 -1
  350. package/build/internal/__tests__/EntityDataManager-test.js +0 -373
  351. package/build/internal/__tests__/EntityDataManager-test.js.map +0 -1
  352. package/build/internal/__tests__/EntityFieldTransformationUtils-test.d.ts +0 -1
  353. package/build/internal/__tests__/EntityFieldTransformationUtils-test.js +0 -136
  354. package/build/internal/__tests__/EntityFieldTransformationUtils-test.js.map +0 -1
  355. package/build/internal/__tests__/ReadThroughEntityCache-test.d.ts +0 -1
  356. package/build/internal/__tests__/ReadThroughEntityCache-test.js +0 -206
  357. package/build/internal/__tests__/ReadThroughEntityCache-test.js.map +0 -1
  358. package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.d.ts +0 -1
  359. package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js +0 -21
  360. package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js.map +0 -1
  361. package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.d.ts +0 -1
  362. package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js +0 -21
  363. package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js.map +0 -1
  364. package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.d.ts +0 -1
  365. package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js +0 -21
  366. package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js.map +0 -1
  367. package/build/testfixtures/DateIDTestEntity.d.ts +0 -19
  368. package/build/testfixtures/DateIDTestEntity.js +0 -48
  369. package/build/testfixtures/DateIDTestEntity.js.map +0 -1
  370. package/build/testfixtures/SimpleTestEntity.d.ts +0 -20
  371. package/build/testfixtures/SimpleTestEntity.js +0 -48
  372. package/build/testfixtures/SimpleTestEntity.js.map +0 -1
  373. package/build/testfixtures/TestEntity.d.ts +0 -30
  374. package/build/testfixtures/TestEntity.js +0 -93
  375. package/build/testfixtures/TestEntity.js.map +0 -1
  376. package/build/testfixtures/TestEntity2.d.ts +0 -20
  377. package/build/testfixtures/TestEntity2.js +0 -51
  378. package/build/testfixtures/TestEntity2.js.map +0 -1
  379. package/build/testfixtures/TestEntityNumberKey.d.ts +0 -19
  380. package/build/testfixtures/TestEntityNumberKey.js +0 -48
  381. package/build/testfixtures/TestEntityNumberKey.js.map +0 -1
  382. package/build/testfixtures/TestEntityWithMutationTriggers.d.ts +0 -36
  383. package/build/testfixtures/TestEntityWithMutationTriggers.js +0 -82
  384. package/build/testfixtures/TestEntityWithMutationTriggers.js.map +0 -1
  385. package/build/testfixtures/TestViewerContext.d.ts +0 -3
  386. package/build/testfixtures/TestViewerContext.js +0 -10
  387. package/build/testfixtures/TestViewerContext.js.map +0 -1
  388. package/build/utils/__tests__/EntityPrivacyUtils-test.d.ts +0 -1
  389. package/build/utils/__tests__/EntityPrivacyUtils-test.js +0 -520
  390. package/build/utils/__tests__/EntityPrivacyUtils-test.js.map +0 -1
  391. package/build/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.d.ts +0 -1
  392. package/build/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.js +0 -181
  393. package/build/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.js.map +0 -1
  394. package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.d.ts +0 -1
  395. package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.js +0 -26
  396. package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.js.map +0 -1
  397. package/build/utils/collections/__tests__/maps-test.d.ts +0 -1
  398. package/build/utils/collections/__tests__/maps-test.js +0 -120
  399. package/build/utils/collections/__tests__/maps-test.js.map +0 -1
  400. package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +0 -28
  401. package/build/utils/testing/PrivacyPolicyRuleTestUtils.js +0 -52
  402. package/build/utils/testing/PrivacyPolicyRuleTestUtils.js.map +0 -1
  403. package/build/utils/testing/StubCacheAdapter.d.ts +0 -27
  404. package/build/utils/testing/StubCacheAdapter.js +0 -86
  405. package/build/utils/testing/StubCacheAdapter.js.map +0 -1
  406. package/build/utils/testing/StubDatabaseAdapter.d.ts +0 -25
  407. package/build/utils/testing/StubDatabaseAdapter.js +0 -191
  408. package/build/utils/testing/StubDatabaseAdapter.js.map +0 -1
  409. package/build/utils/testing/StubDatabaseAdapterProvider.d.ts +0 -7
  410. package/build/utils/testing/StubDatabaseAdapterProvider.js +0 -14
  411. package/build/utils/testing/StubDatabaseAdapterProvider.js.map +0 -1
  412. package/build/utils/testing/StubQueryContextProvider.d.ts +0 -7
  413. package/build/utils/testing/StubQueryContextProvider.js +0 -19
  414. package/build/utils/testing/StubQueryContextProvider.js.map +0 -1
  415. package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.d.ts +0 -1
  416. package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.js +0 -42
  417. package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.js.map +0 -1
  418. package/build/utils/testing/__tests__/StubDatabaseAdapter-test.d.ts +0 -1
  419. package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js +0 -402
  420. package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js.map +0 -1
  421. package/build/utils/testing/createUnitTestEntityCompanionProvider.d.ts +0 -7
  422. package/build/utils/testing/createUnitTestEntityCompanionProvider.js +0 -36
  423. package/build/utils/testing/createUnitTestEntityCompanionProvider.js.map +0 -1
  424. package/build/utils/testing/describeFieldTestCase.d.ts +0 -2
  425. package/build/utils/testing/describeFieldTestCase.js +0 -18
  426. package/build/utils/testing/describeFieldTestCase.js.map +0 -1
  427. package/src/testfixtures/DateIDTestEntity.ts +0 -59
  428. package/src/testfixtures/TestEntityNumberKey.ts +0 -59
  429. package/src/utils/testing/StubCacheAdapter.ts +0 -122
  430. package/src/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.ts +0 -42
  431. package/src/utils/testing/__tests__/StubDatabaseAdapter-test.ts +0 -548
  432. /package/src/utils/{testing → __testfixtures__}/StubQueryContextProvider.ts +0 -0
  433. /package/src/utils/{testing → __testfixtures__}/createUnitTestEntityCompanionProvider.ts +0 -0
@@ -1,20 +1,120 @@
1
+ import invariant from 'invariant';
2
+
1
3
  import { IEntityClass } from './Entity';
2
4
  import { DatabaseAdapterFlavor, CacheAdapterFlavor } from './EntityCompanionProvider';
3
5
  import { EntityFieldDefinition } from './EntityFieldDefinition';
6
+ import {
7
+ CompositeFieldHolder,
8
+ SerializedCompositeFieldHolder,
9
+ } from './internal/CompositeFieldHolder';
4
10
  import { mapMap, invertMap, reduceMap } from './utils/collections/maps';
5
11
 
12
+ /**
13
+ * A composite field is an unordered set of fields by which entities can be loaded in a batched
14
+ * and (optionally) cached manner akin to how normal fieldName loads are batched and (optionally) cached.
15
+ */
16
+ export type EntityCompositeField<TFields extends Record<string, any>> = readonly (keyof TFields)[];
17
+
18
+ /**
19
+ * Specification of composite field for an entity and whether it can be cached.
20
+ */
21
+ export type EntityCompositeFieldDefinition<TFields extends Record<string, any>> = {
22
+ /**
23
+ * The composite field.
24
+ */
25
+ compositeField: EntityCompositeField<TFields>;
26
+
27
+ /**
28
+ * Whether or not to cache loaded instances of the entity by this composite field. The column names in
29
+ * the composite field are used to derive a cache key for the cache entry. If true, the set of columns
30
+ * must be able uniquely identify the entity and the database must have a unique constraint on the
31
+ * set of columns.
32
+ */
33
+ cache: boolean;
34
+ };
35
+
36
+ /**
37
+ * A composite field value is a mapping of fields to values for a composite field.
38
+ */
39
+ export type EntityCompositeFieldValue<
40
+ TFields extends Record<string, any>,
41
+ TCompositeField extends EntityCompositeField<TFields>,
42
+ > = Record<TCompositeField[number], NonNullable<TFields[TCompositeField[number]]>>;
43
+
44
+ /**
45
+ * Helper class to validate and store composite field information.
46
+ */
47
+ export class CompositeFieldInfo<
48
+ TFields extends Record<string, any>,
49
+ TIDField extends keyof TFields,
50
+ > {
51
+ private readonly compositeFieldInfoMap: ReadonlyMap<
52
+ SerializedCompositeFieldHolder,
53
+ {
54
+ compositeFieldHolder: CompositeFieldHolder<TFields, TIDField>;
55
+ cache: boolean;
56
+ }
57
+ >;
58
+
59
+ constructor(compositeFieldsDefinitions: EntityCompositeFieldDefinition<TFields>[]) {
60
+ this.compositeFieldInfoMap = new Map(
61
+ compositeFieldsDefinitions.map((keyDefinition) => {
62
+ invariant(
63
+ keyDefinition.compositeField.length >= 2,
64
+ 'Composite field must have at least two sub-fields',
65
+ );
66
+ invariant(
67
+ keyDefinition.compositeField.length === new Set(keyDefinition.compositeField).size,
68
+ 'Composite field must have unique sub-fields',
69
+ );
70
+ const compositeFieldHolder = new CompositeFieldHolder(keyDefinition.compositeField);
71
+ return [
72
+ compositeFieldHolder.serialize(),
73
+ { compositeFieldHolder, cache: keyDefinition.cache ?? false },
74
+ ];
75
+ }),
76
+ );
77
+ }
78
+
79
+ public getCompositeFieldHolderForCompositeField(
80
+ compositeField: EntityCompositeField<TFields>,
81
+ ): CompositeFieldHolder<TFields, TIDField> | undefined {
82
+ return this.compositeFieldInfoMap.get(new CompositeFieldHolder(compositeField).serialize())
83
+ ?.compositeFieldHolder;
84
+ }
85
+
86
+ public getAllCompositeFieldHolders(): readonly CompositeFieldHolder<TFields, TIDField>[] {
87
+ return Array.from(this.compositeFieldInfoMap.values()).map((v) => v.compositeFieldHolder);
88
+ }
89
+
90
+ public canCacheCompositeField(compositeField: EntityCompositeField<TFields>): boolean {
91
+ const compositeFieldInfo = this.compositeFieldInfoMap.get(
92
+ new CompositeFieldHolder(compositeField).serialize(),
93
+ );
94
+ invariant(
95
+ compositeFieldInfo,
96
+ `Composite field (${compositeField.join(',')}) not found in entity configuration`,
97
+ );
98
+ return compositeFieldInfo.cache;
99
+ }
100
+ }
101
+
6
102
  /**
7
103
  * The data storage configuration for a type of Entity. Contains information relating to IDs,
8
104
  * cachable fields, field mappings, and types of cache and database adapter.
9
105
  */
10
- export default class EntityConfiguration<TFields extends Record<string, any>> {
106
+ export default class EntityConfiguration<
107
+ TFields extends Record<string, any>,
108
+ TIDField extends keyof TFields,
109
+ > {
11
110
  readonly idField: keyof TFields;
12
111
  readonly tableName: string;
13
112
  readonly cacheableKeys: ReadonlySet<keyof TFields>;
113
+ readonly compositeFieldInfo: CompositeFieldInfo<TFields, TIDField>;
14
114
  readonly cacheKeyVersion: number;
15
115
 
16
116
  readonly inboundEdges: IEntityClass<any, any, any, any, any, any>[];
17
- readonly schema: ReadonlyMap<keyof TFields, EntityFieldDefinition<any>>;
117
+ readonly schema: ReadonlyMap<keyof TFields, EntityFieldDefinition<any, any>>;
18
118
  readonly entityToDBFieldsKeyMapping: ReadonlyMap<keyof TFields, string>;
19
119
  readonly dbToEntityFieldsKeyMapping: ReadonlyMap<string, keyof TFields>;
20
120
 
@@ -27,13 +127,14 @@ export default class EntityConfiguration<TFields extends Record<string, any>> {
27
127
  schema,
28
128
  inboundEdges = [],
29
129
  cacheKeyVersion = 0,
130
+ compositeFieldDefinitions,
30
131
  databaseAdapterFlavor,
31
132
  cacheAdapterFlavor,
32
133
  }: {
33
134
  /**
34
135
  * The field used to identify this entity. Must be a unique field in the table.
35
136
  */
36
- idField: keyof TFields;
137
+ idField: TIDField;
37
138
 
38
139
  /**
39
140
  * The name of the table where entities of this type are stored.
@@ -43,7 +144,8 @@ export default class EntityConfiguration<TFields extends Record<string, any>> {
43
144
  /**
44
145
  * Map from each entity field to an EntityFieldDefinition specifying information about the field.
45
146
  */
46
- schema: Record<keyof TFields, EntityFieldDefinition<any>>;
147
+ schema: Omit<Record<keyof TFields, EntityFieldDefinition<any, false>>, TIDField> &
148
+ Record<TIDField, EntityFieldDefinition<any, true>>;
47
149
 
48
150
  /**
49
151
  * List of other entity types that reference this type in EntityFieldDefinition associations.
@@ -56,6 +158,11 @@ export default class EntityConfiguration<TFields extends Record<string, any>> {
56
158
  */
57
159
  cacheKeyVersion?: number;
58
160
 
161
+ /**
162
+ * Composite field definitions for this entity.
163
+ */
164
+ compositeFieldDefinitions?: EntityCompositeFieldDefinition<TFields>[];
165
+
59
166
  /**
60
167
  * Backing database and transaction type for this entity.
61
168
  */
@@ -75,17 +182,24 @@ export default class EntityConfiguration<TFields extends Record<string, any>> {
75
182
 
76
183
  // external schema is a Record to typecheck that all fields have FieldDefinitions,
77
184
  // but internally the most useful representation is a map for lookups
78
- EntityConfiguration.validateSchema(schema);
185
+ EntityConfiguration.validateSchema<TFields, TIDField>(schema);
79
186
  this.schema = new Map(Object.entries(schema));
80
187
 
81
188
  this.cacheableKeys = EntityConfiguration.computeCacheableKeys(this.schema);
189
+ this.compositeFieldInfo = new CompositeFieldInfo(compositeFieldDefinitions ?? []);
82
190
  this.entityToDBFieldsKeyMapping = EntityConfiguration.computeEntityToDBFieldsKeyMapping(
83
191
  this.schema,
84
192
  );
85
193
  this.dbToEntityFieldsKeyMapping = invertMap(this.entityToDBFieldsKeyMapping);
86
194
  }
87
195
 
88
- private static validateSchema<TFields extends Record<string, any>>(schema: TFields): void {
196
+ private static validateSchema<
197
+ TFields extends Record<string, any>,
198
+ TIDField extends keyof TFields,
199
+ >(
200
+ schema: Omit<Record<keyof TFields, EntityFieldDefinition<any, false>>, TIDField> &
201
+ Record<TIDField, EntityFieldDefinition<any, true>>,
202
+ ): void {
89
203
  const disallowedFieldsKeys = Object.getOwnPropertyNames(Object.prototype);
90
204
  for (const disallowedFieldsKey of disallowedFieldsKeys) {
91
205
  if (Object.hasOwn(schema, disallowedFieldsKey)) {
@@ -96,8 +210,8 @@ export default class EntityConfiguration<TFields extends Record<string, any>> {
96
210
  }
97
211
  }
98
212
 
99
- private static computeCacheableKeys<TFields>(
100
- schema: ReadonlyMap<keyof TFields, EntityFieldDefinition<any>>,
213
+ private static computeCacheableKeys<TFields extends Record<string, any>>(
214
+ schema: ReadonlyMap<keyof TFields, EntityFieldDefinition<any, any>>,
101
215
  ): ReadonlySet<keyof TFields> {
102
216
  return reduceMap(
103
217
  schema,
@@ -112,7 +226,7 @@ export default class EntityConfiguration<TFields extends Record<string, any>> {
112
226
  }
113
227
 
114
228
  private static computeEntityToDBFieldsKeyMapping<TFields>(
115
- schema: ReadonlyMap<keyof TFields, EntityFieldDefinition<any>>,
229
+ schema: ReadonlyMap<keyof TFields, EntityFieldDefinition<any, any>>,
116
230
  ): ReadonlyMap<keyof TFields, string> {
117
231
  return mapMap(schema, (v) => v.columnName);
118
232
  }
@@ -10,14 +10,14 @@ import ViewerContext from './ViewerContext';
10
10
  * The primary interface for creating entities.
11
11
  */
12
12
  export default class EntityCreator<
13
- TFields extends object,
14
- TID extends NonNullable<TFields[TSelectedFields]>,
13
+ TFields extends Record<string, any>,
14
+ TIDField extends keyof NonNullable<Pick<TFields, TSelectedFields>>,
15
15
  TViewerContext extends ViewerContext,
16
16
  TViewerContext2 extends TViewerContext,
17
- TEntity extends ReadonlyEntity<TFields, TID, TViewerContext, TSelectedFields>,
17
+ TEntity extends ReadonlyEntity<TFields, TIDField, TViewerContext, TSelectedFields>,
18
18
  TPrivacyPolicy extends EntityPrivacyPolicy<
19
19
  TFields,
20
- TID,
20
+ TIDField,
21
21
  TViewerContext,
22
22
  TEntity,
23
23
  TSelectedFields
@@ -29,7 +29,7 @@ export default class EntityCreator<
29
29
  private readonly queryContext: EntityQueryContext,
30
30
  private readonly entityClass: IEntityClass<
31
31
  TFields,
32
- TID,
32
+ TIDField,
33
33
  TViewerContext,
34
34
  TEntity,
35
35
  TPrivacyPolicy,
@@ -43,7 +43,7 @@ export default class EntityCreator<
43
43
  */
44
44
  enforcing(): EnforcingEntityCreator<
45
45
  TFields,
46
- TID,
46
+ TIDField,
47
47
  TViewerContext,
48
48
  TEntity,
49
49
  TPrivacyPolicy,
@@ -59,7 +59,7 @@ export default class EntityCreator<
59
59
  */
60
60
  withAuthorizationResults(): AuthorizationResultBasedCreateMutator<
61
61
  TFields,
62
- TID,
62
+ TIDField,
63
63
  TViewerContext,
64
64
  TEntity,
65
65
  TPrivacyPolicy,
@@ -1,3 +1,5 @@
1
+ import invariant from 'invariant';
2
+
1
3
  import EntityConfiguration from './EntityConfiguration';
2
4
  import { EntityQueryContext } from './EntityQueryContext';
3
5
  import {
@@ -6,12 +8,13 @@ import {
6
8
  transformFieldsToDatabaseObject,
7
9
  FieldTransformerMap,
8
10
  } from './internal/EntityFieldTransformationUtils';
11
+ import { IEntityLoadKey, IEntityLoadValue } from './internal/EntityLoadInterfaces';
9
12
 
10
13
  /**
11
14
  * Equality operand that is used for selecting entities with a field with a single value.
12
15
  */
13
16
  export interface SingleValueFieldEqualityCondition<
14
- TFields,
17
+ TFields extends Record<string, any>,
15
18
  N extends keyof TFields = keyof TFields,
16
19
  > {
17
20
  fieldName: N;
@@ -22,7 +25,7 @@ export interface SingleValueFieldEqualityCondition<
22
25
  * Equality operand that is used for selecting entities with a field matching one of multiple values.
23
26
  */
24
27
  export interface MultiValueFieldEqualityCondition<
25
- TFields,
28
+ TFields extends Record<string, any>,
26
29
  N extends keyof TFields = keyof TFields,
27
30
  > {
28
31
  fieldName: N;
@@ -33,12 +36,13 @@ export interface MultiValueFieldEqualityCondition<
33
36
  * A single equality operand for use in a selection clause.
34
37
  * See EntityLoader.loadManyByFieldEqualityConjunctionAsync documentation for examples.
35
38
  */
36
- export type FieldEqualityCondition<TFields, N extends keyof TFields = keyof TFields> =
37
- | SingleValueFieldEqualityCondition<TFields, N>
38
- | MultiValueFieldEqualityCondition<TFields, N>;
39
+ export type FieldEqualityCondition<
40
+ TFields extends Record<string, any>,
41
+ N extends keyof TFields = keyof TFields,
42
+ > = SingleValueFieldEqualityCondition<TFields, N> | MultiValueFieldEqualityCondition<TFields, N>;
39
43
 
40
44
  export function isSingleValueFieldEqualityCondition<
41
- TFields,
45
+ TFields extends Record<string, any>,
42
46
  N extends keyof TFields = keyof TFields,
43
47
  >(
44
48
  condition: FieldEqualityCondition<TFields, N>,
@@ -64,7 +68,7 @@ export enum OrderByOrdering {
64
68
  /**
65
69
  * SQL modifiers that only affect the selection but not the projection.
66
70
  */
67
- export interface QuerySelectionModifiers<TFields> {
71
+ export interface QuerySelectionModifiers<TFields extends Record<string, any>> {
68
72
  /**
69
73
  * Order the entities by specified columns and orders.
70
74
  */
@@ -84,7 +88,7 @@ export interface QuerySelectionModifiers<TFields> {
84
88
  limit?: number;
85
89
  }
86
90
 
87
- export interface QuerySelectionModifiersWithOrderByRaw<TFields>
91
+ export interface QuerySelectionModifiersWithOrderByRaw<TFields extends Record<string, any>>
88
92
  extends QuerySelectionModifiers<TFields> {
89
93
  /**
90
94
  * Order the entities by a raw SQL `ORDER BY` clause.
@@ -113,10 +117,13 @@ export interface TableQuerySelectionModifiersWithOrderByRaw extends TableQuerySe
113
117
  * handles all entity field transformation. Subclasses are responsible for
114
118
  * implementing database-specific logic for a type of database.
115
119
  */
116
- export default abstract class EntityDatabaseAdapter<TFields extends Record<string, any>> {
120
+ export default abstract class EntityDatabaseAdapter<
121
+ TFields extends Record<string, any>,
122
+ TIDField extends keyof TFields,
123
+ > {
117
124
  private readonly fieldTransformerMap: FieldTransformerMap;
118
125
 
119
- constructor(private readonly entityConfiguration: EntityConfiguration<TFields>) {
126
+ constructor(private readonly entityConfiguration: EntityConfiguration<TFields, TIDField>) {
120
127
  this.fieldTransformerMap = this.getFieldTransformerMap();
121
128
  }
122
129
 
@@ -128,37 +135,53 @@ export default abstract class EntityDatabaseAdapter<TFields extends Record<strin
128
135
  protected abstract getFieldTransformerMap(): FieldTransformerMap;
129
136
 
130
137
  /**
131
- * Fetch many objects where fieldName is one of fieldValues.
138
+ * Fetch many objects where key is one of values.
132
139
  *
133
140
  * @param queryContext - query context with which to perform the fetch
134
- * @param fieldName - object field being queried
135
- * @param fieldValues - fieldName field values being queried
136
- * @returns map from fieldValue to objects that match the query for that fieldValue
141
+ * @param key - load key being queried
142
+ * @param values - load values being queried
143
+ * @returns map from value to objects that match the query for that value
137
144
  */
138
- async fetchManyWhereAsync<K extends keyof TFields>(
145
+ async fetchManyWhereAsync<
146
+ TLoadKey extends IEntityLoadKey<TFields, TIDField, TSerializedLoadValue, TLoadValue>,
147
+ TSerializedLoadValue,
148
+ TLoadValue extends IEntityLoadValue<TSerializedLoadValue>,
149
+ >(
139
150
  queryContext: EntityQueryContext,
140
- fieldName: K,
141
- fieldValues: readonly NonNullable<TFields[K]>[],
142
- ): Promise<ReadonlyMap<NonNullable<TFields[K]>, readonly Readonly<TFields>[]>> {
143
- const fieldColumn = getDatabaseFieldForEntityField(this.entityConfiguration, fieldName);
151
+ key: TLoadKey,
152
+ values: readonly TLoadValue[],
153
+ ): Promise<ReadonlyMap<TLoadValue, readonly Readonly<TFields>[]>> {
154
+ const keyDatabaseColumns = key.getDatabaseColumns(this.entityConfiguration);
155
+ const valueDatabaseValues = values.map((value) => key.getDatabaseValues(value));
156
+
144
157
  const results = await this.fetchManyWhereInternalAsync(
145
158
  queryContext.getQueryInterface(),
146
159
  this.entityConfiguration.tableName,
147
- fieldColumn,
148
- fieldValues,
160
+ keyDatabaseColumns,
161
+ valueDatabaseValues,
149
162
  );
163
+
150
164
  const objects = results.map((result) =>
151
165
  transformDatabaseObjectToFields(this.entityConfiguration, this.fieldTransformerMap, result),
152
166
  );
153
167
 
154
- const objectMap = new Map();
155
- for (const fieldValue of fieldValues) {
156
- objectMap.set(fieldValue, []);
168
+ const objectMap = key.vendNewLoadValueMap<Readonly<TFields>[]>();
169
+ for (const value of values) {
170
+ objectMap.set(value, []);
157
171
  }
158
172
 
159
173
  objects.forEach((object) => {
160
- const objectFieldValue = object[fieldName];
161
- objectMap.get(objectFieldValue).push(object);
174
+ const objectMapKeyForObject = key.getLoadValueForObject(object);
175
+ invariant(
176
+ objectMapKeyForObject !== null,
177
+ `One or more fields from the object is invalid for key ${key}; ${JSON.stringify(object)}. This may indicate a faulty database adapter implementation.`,
178
+ );
179
+ const objectList = objectMap.get(objectMapKeyForObject);
180
+ invariant(
181
+ objectList !== undefined,
182
+ `Unexpected object field value during database result transformation: ${objectMapKeyForObject}. This should never happen.`,
183
+ );
184
+ objectList.push(object);
162
185
  });
163
186
 
164
187
  return objectMap;
@@ -167,8 +190,8 @@ export default abstract class EntityDatabaseAdapter<TFields extends Record<strin
167
190
  protected abstract fetchManyWhereInternalAsync(
168
191
  queryInterface: any,
169
192
  tableName: string,
170
- tableField: string,
171
- tableValues: readonly any[],
193
+ tableColumns: readonly string[],
194
+ tableTuples: (readonly any[])[],
172
195
  ): Promise<object[]>;
173
196
 
174
197
  /**
@@ -10,13 +10,13 @@ import ViewerContext from './ViewerContext';
10
10
  * The primary interface for deleting entities.
11
11
  */
12
12
  export default class EntityDeleter<
13
- TFields extends object,
14
- TID extends NonNullable<TFields[TSelectedFields]>,
13
+ TFields extends Record<string, any>,
14
+ TIDField extends keyof NonNullable<Pick<TFields, TSelectedFields>>,
15
15
  TViewerContext extends ViewerContext,
16
- TEntity extends ReadonlyEntity<TFields, TID, TViewerContext, TSelectedFields>,
16
+ TEntity extends ReadonlyEntity<TFields, TIDField, TViewerContext, TSelectedFields>,
17
17
  TPrivacyPolicy extends EntityPrivacyPolicy<
18
18
  TFields,
19
- TID,
19
+ TIDField,
20
20
  TViewerContext,
21
21
  TEntity,
22
22
  TSelectedFields
@@ -28,7 +28,7 @@ export default class EntityDeleter<
28
28
  private readonly queryContext: EntityQueryContext,
29
29
  private readonly entityClass: IEntityClass<
30
30
  TFields,
31
- TID,
31
+ TIDField,
32
32
  TViewerContext,
33
33
  TEntity,
34
34
  TPrivacyPolicy,
@@ -42,7 +42,7 @@ export default class EntityDeleter<
42
42
  */
43
43
  enforcing(): EnforcingEntityDeleter<
44
44
  TFields,
45
- TID,
45
+ TIDField,
46
46
  TViewerContext,
47
47
  TEntity,
48
48
  TPrivacyPolicy,
@@ -58,7 +58,7 @@ export default class EntityDeleter<
58
58
  */
59
59
  withAuthorizationResults(): AuthorizationResultBasedDeleteMutator<
60
60
  TFields,
61
- TID,
61
+ TIDField,
62
62
  TViewerContext,
63
63
  TEntity,
64
64
  TPrivacyPolicy,
@@ -71,16 +71,16 @@ export enum EntityEdgeDeletionAuthorizationInferenceBehavior {
71
71
  export interface EntityAssociationDefinition<
72
72
  TViewerContext extends ViewerContext,
73
73
  TAssociatedFields extends object,
74
- TAssociatedID extends NonNullable<TAssociatedFields[TAssociatedSelectedFields]>,
74
+ TAssociatedIDField extends keyof NonNullable<Pick<TAssociatedFields, TAssociatedSelectedFields>>,
75
75
  TAssociatedEntity extends ReadonlyEntity<
76
76
  TAssociatedFields,
77
- TAssociatedID,
77
+ TAssociatedIDField,
78
78
  TViewerContext,
79
79
  TAssociatedSelectedFields
80
80
  >,
81
81
  TAssociatedPrivacyPolicy extends EntityPrivacyPolicy<
82
82
  TAssociatedFields,
83
- TAssociatedID,
83
+ TAssociatedIDField,
84
84
  TViewerContext,
85
85
  TAssociatedEntity,
86
86
  TAssociatedSelectedFields
@@ -92,7 +92,7 @@ export interface EntityAssociationDefinition<
92
92
  */
93
93
  associatedEntityClass: IEntityClass<
94
94
  TAssociatedFields,
95
- TAssociatedID,
95
+ TAssociatedIDField,
96
96
  TViewerContext,
97
97
  TAssociatedEntity,
98
98
  TAssociatedPrivacyPolicy,
@@ -135,38 +135,58 @@ export interface EntityAssociationDefinition<
135
135
  /**
136
136
  * Options for EntityFieldDefinition
137
137
  */
138
- export interface EntityFieldDefinitionOptions {
138
+ export interface EntityFieldDefinitionOptionsBase {
139
139
  /**
140
140
  * Column name in the database.
141
141
  */
142
142
  columnName: string;
143
143
 
144
+ /**
145
+ * Defines the association behavior for an entity that this column references.
146
+ */
147
+ association?: EntityAssociationDefinition<any, any, any, any, any, any>;
148
+ }
149
+
150
+ export interface EntityFieldDefinitionOptionsExplicitCache
151
+ extends EntityFieldDefinitionOptionsBase {
144
152
  /**
145
153
  * Whether or not to cache loaded instances of the entity by this field. The column name is
146
154
  * used to derive a cache key for the cache entry. If true, this column must be able uniquely
147
- * identify the entity.
155
+ * identify the entity and the database must have a unique constraint on the column.
148
156
  */
149
- cache?: boolean;
157
+ cache: boolean;
158
+ }
150
159
 
160
+ export interface EntityFieldDefinitionOptions extends EntityFieldDefinitionOptionsBase {
151
161
  /**
152
- * Defines the association behavior for an entity that this column references.
162
+ * Whether or not to cache loaded instances of the entity by this field. The column name is
163
+ * used to derive a cache key for the cache entry. If true, this column must be able uniquely
164
+ * identify the entity and the database must have a unique constraint on the column.
153
165
  */
154
- association?: EntityAssociationDefinition<any, any, any, any, any, any>;
166
+ cache?: boolean;
155
167
  }
156
168
 
157
169
  /**
158
170
  * Definition for a field referencing a column in the underlying database. Specifies things like
159
171
  * cache behavior and associations, and handles input validation.
160
172
  */
161
- export abstract class EntityFieldDefinition<T> {
173
+ export abstract class EntityFieldDefinition<T, TRequireExplicitCache extends boolean> {
162
174
  readonly columnName: string;
163
175
  readonly cache: boolean;
164
176
  readonly association: EntityAssociationDefinition<any, any, any, any, any, any> | undefined;
177
+
178
+ // @ts-expect-error this is to ensure that different constructor requirements produce incompatible
179
+ // objects in the eyes of the type system
180
+ private readonly cacheRawSentinel: TRequireExplicitCache;
181
+
165
182
  /**
166
- *
167
183
  * @param options - options for this field definition
168
184
  */
169
- constructor(options: EntityFieldDefinitionOptions) {
185
+ constructor(
186
+ options: TRequireExplicitCache extends true
187
+ ? EntityFieldDefinitionOptionsExplicitCache
188
+ : EntityFieldDefinitionOptions,
189
+ ) {
170
190
  this.columnName = options.columnName;
171
191
  this.cache = options.cache ?? false;
172
192
  this.association = options.association;