@expo/entity 0.41.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.
- package/build/AuthorizationResultBasedEntityAssociationLoader.d.ts +16 -16
- package/build/AuthorizationResultBasedEntityAssociationLoader.js.map +1 -1
- package/build/AuthorizationResultBasedEntityLoader.d.ts +39 -67
- package/build/AuthorizationResultBasedEntityLoader.js +85 -62
- package/build/AuthorizationResultBasedEntityLoader.js.map +1 -1
- package/build/AuthorizationResultBasedEntityMutator.d.ts +16 -16
- package/build/AuthorizationResultBasedEntityMutator.js.map +1 -1
- package/build/ComposedEntityCacheAdapter.d.ts +7 -6
- package/build/ComposedEntityCacheAdapter.js +28 -28
- package/build/ComposedEntityCacheAdapter.js.map +1 -1
- package/build/ComposedSecondaryEntityCache.d.ts +1 -1
- package/build/ComposedSecondaryEntityCache.js.map +1 -1
- package/build/EnforcingEntityAssociationLoader.d.ts +15 -15
- package/build/EnforcingEntityAssociationLoader.js.map +1 -1
- package/build/EnforcingEntityCreator.d.ts +2 -2
- package/build/EnforcingEntityDeleter.d.ts +2 -2
- package/build/EnforcingEntityLoader.d.ts +104 -18
- package/build/EnforcingEntityLoader.js +113 -12
- package/build/EnforcingEntityLoader.js.map +1 -1
- package/build/EnforcingEntityUpdater.d.ts +2 -2
- package/build/Entity.d.ts +10 -10
- package/build/Entity.js.map +1 -1
- package/build/EntityAssociationLoader.d.ts +3 -3
- package/build/EntityCompanion.d.ts +5 -5
- package/build/EntityCompanion.js.map +1 -1
- package/build/EntityCompanionProvider.d.ts +6 -6
- package/build/EntityCompanionProvider.js.map +1 -1
- package/build/EntityConfiguration.d.ts +46 -5
- package/build/EntityConfiguration.js +39 -1
- package/build/EntityConfiguration.js.map +1 -1
- package/build/EntityCreator.d.ts +4 -4
- package/build/EntityDatabaseAdapter.d.ts +15 -14
- package/build/EntityDatabaseAdapter.js +20 -12
- package/build/EntityDatabaseAdapter.js.map +1 -1
- package/build/EntityDeleter.d.ts +4 -4
- package/build/EntityFieldDefinition.d.ts +20 -10
- package/build/EntityFieldDefinition.js +3 -1
- package/build/EntityFieldDefinition.js.map +1 -1
- package/build/EntityFields.d.ts +14 -12
- package/build/EntityFields.js.map +1 -1
- package/build/EntityLoader.d.ts +5 -5
- package/build/EntityLoaderFactory.d.ts +3 -3
- package/build/EntityLoaderFactory.js.map +1 -1
- package/build/EntityLoaderUtils.d.ts +2 -2
- package/build/EntityLoaderUtils.js +27 -1
- package/build/EntityLoaderUtils.js.map +1 -1
- package/build/EntityMutationInfo.d.ts +2 -2
- package/build/EntityMutationTriggerConfiguration.d.ts +14 -14
- package/build/EntityMutationTriggerConfiguration.js.map +1 -1
- package/build/EntityMutationValidator.d.ts +2 -2
- package/build/EntityMutatorFactory.d.ts +5 -5
- package/build/EntityMutatorFactory.js.map +1 -1
- package/build/EntityPrivacyPolicy.d.ts +14 -14
- package/build/EntityPrivacyPolicy.js.map +1 -1
- package/build/EntitySecondaryCacheLoader.d.ts +4 -4
- package/build/EntityUpdater.d.ts +4 -4
- package/build/GenericEntityCacheAdapter.d.ts +7 -6
- package/build/GenericEntityCacheAdapter.js +13 -14
- package/build/GenericEntityCacheAdapter.js.map +1 -1
- package/build/GenericSecondaryEntityCache.d.ts +3 -3
- package/build/GenericSecondaryEntityCache.js.map +1 -1
- package/build/IEntityCacheAdapter.d.ts +17 -16
- package/build/IEntityCacheAdapterProvider.d.ts +1 -1
- package/build/IEntityDatabaseAdapterProvider.d.ts +1 -1
- package/build/IEntityGenericCacher.d.ts +15 -5
- package/build/ReadonlyEntity.d.ts +8 -8
- package/build/ReadonlyEntity.js.map +1 -1
- package/build/ViewerContext.d.ts +1 -1
- package/build/ViewerScopedEntityCompanion.d.ts +5 -5
- package/build/ViewerScopedEntityCompanionProvider.d.ts +1 -1
- package/build/ViewerScopedEntityLoaderFactory.d.ts +3 -3
- package/build/ViewerScopedEntityMutatorFactory.d.ts +5 -5
- package/build/entityUtils.d.ts +1 -1
- package/build/entityUtils.js.map +1 -1
- package/build/errors/EntityInvalidFieldValueError.d.ts +2 -2
- package/build/errors/EntityNotAuthorizedError.d.ts +1 -1
- package/build/errors/EntityNotFoundError.d.ts +2 -2
- package/build/index.d.ts +7 -7
- package/build/index.js +8 -13
- package/build/index.js.map +1 -1
- package/build/internal/CompositeFieldHolder.d.ts +48 -0
- package/build/internal/CompositeFieldHolder.js +116 -0
- package/build/internal/CompositeFieldHolder.js.map +1 -0
- package/build/internal/CompositeFieldValueMap.d.ts +15 -0
- package/build/internal/CompositeFieldValueMap.js +51 -0
- package/build/internal/CompositeFieldValueMap.js.map +1 -0
- package/build/internal/EntityDataManager.d.ts +16 -16
- package/build/internal/EntityDataManager.js +42 -45
- package/build/internal/EntityDataManager.js.map +1 -1
- package/build/internal/EntityFieldTransformationUtils.d.ts +5 -5
- package/build/internal/EntityFieldTransformationUtils.js.map +1 -1
- package/build/internal/EntityLoadInterfaces.d.ts +104 -0
- package/build/internal/EntityLoadInterfaces.js +25 -0
- package/build/internal/EntityLoadInterfaces.js.map +1 -0
- package/build/internal/EntityTableDataCoordinator.d.ts +6 -6
- package/build/internal/EntityTableDataCoordinator.js.map +1 -1
- package/build/internal/ReadThroughEntityCache.d.ts +17 -16
- package/build/internal/ReadThroughEntityCache.js +36 -36
- package/build/internal/ReadThroughEntityCache.js.map +1 -1
- package/build/internal/SingleFieldHolder.d.ts +34 -0
- package/build/internal/SingleFieldHolder.js +90 -0
- package/build/internal/SingleFieldHolder.js.map +1 -0
- package/build/metrics/EntityMetricsUtils.d.ts +2 -1
- package/build/metrics/EntityMetricsUtils.js.map +1 -1
- package/build/metrics/IEntityMetricsAdapter.d.ts +5 -0
- package/build/metrics/IEntityMetricsAdapter.js.map +1 -1
- package/build/rules/AlwaysAllowPrivacyPolicyRule.d.ts +2 -2
- package/build/rules/AlwaysAllowPrivacyPolicyRule.js.map +1 -1
- package/build/rules/AlwaysDenyPrivacyPolicyRule.d.ts +2 -2
- package/build/rules/AlwaysDenyPrivacyPolicyRule.js.map +1 -1
- package/build/rules/AlwaysSkipPrivacyPolicyRule.d.ts +2 -2
- package/build/rules/AlwaysSkipPrivacyPolicyRule.js.map +1 -1
- package/build/rules/PrivacyPolicyRule.d.ts +2 -2
- package/build/tsconfig.build.tsbuildinfo +1 -0
- package/build/utils/EntityPrivacyUtils.d.ts +4 -4
- package/build/utils/EntityPrivacyUtils.js.map +1 -1
- package/build/utils/collections/SerializableKeyMap.d.ts +27 -0
- package/build/utils/collections/SerializableKeyMap.js +60 -0
- package/build/utils/collections/SerializableKeyMap.js.map +1 -0
- package/build/utils/collections/maps.js +1 -2
- package/build/utils/collections/maps.js.map +1 -1
- package/build/utils/collections/sets.d.ts +1 -0
- package/build/utils/collections/sets.js +7 -0
- package/build/utils/collections/sets.js.map +1 -0
- package/build/utils/mergeEntityMutationTriggerConfigurations.d.ts +1 -1
- package/package.json +8 -5
- package/src/AuthorizationResultBasedEntityAssociationLoader.ts +56 -49
- package/src/AuthorizationResultBasedEntityLoader.ts +194 -81
- package/src/AuthorizationResultBasedEntityMutator.ts +71 -45
- package/src/ComposedEntityCacheAdapter.ts +55 -46
- package/src/ComposedSecondaryEntityCache.ts +5 -2
- package/src/EnforcingEntityAssociationLoader.ts +52 -44
- package/src/EnforcingEntityCreator.ts +5 -5
- package/src/EnforcingEntityDeleter.ts +5 -5
- package/src/EnforcingEntityLoader.ts +158 -21
- package/src/EnforcingEntityUpdater.ts +5 -5
- package/src/Entity.ts +39 -39
- package/src/EntityAssociationLoader.ts +6 -6
- package/src/EntityCompanion.ts +11 -11
- package/src/EntityCompanionProvider.ts +21 -18
- package/src/EntityConfiguration.ts +123 -9
- package/src/EntityCreator.ts +7 -7
- package/src/EntityDatabaseAdapter.ts +51 -28
- package/src/EntityDeleter.ts +7 -7
- package/src/EntityFieldDefinition.ts +32 -12
- package/src/EntityFields.ts +49 -12
- package/src/EntityLoader.ts +8 -8
- package/src/EntityLoaderFactory.ts +8 -8
- package/src/EntityLoaderUtils.ts +39 -10
- package/src/EntityMutationInfo.ts +6 -6
- package/src/EntityMutationTriggerConfiguration.ts +68 -20
- package/src/EntityMutationValidator.ts +4 -4
- package/src/EntityMutatorFactory.ts +13 -13
- package/src/EntityPrivacyPolicy.ts +50 -26
- package/src/EntitySecondaryCacheLoader.ts +6 -6
- package/src/EntityUpdater.ts +7 -7
- package/src/GenericEntityCacheAdapter.ts +39 -28
- package/src/GenericSecondaryEntityCache.ts +6 -3
- package/src/IEntityCacheAdapter.ts +45 -25
- package/src/IEntityCacheAdapterProvider.ts +3 -3
- package/src/IEntityDatabaseAdapterProvider.ts +3 -3
- package/src/IEntityGenericCacher.ts +33 -5
- package/src/ReadonlyEntity.ts +24 -24
- package/src/ViewerContext.ts +5 -5
- package/src/ViewerScopedEntityCompanion.ts +7 -7
- package/src/ViewerScopedEntityCompanionProvider.ts +6 -6
- package/src/ViewerScopedEntityLoaderFactory.ts +7 -7
- package/src/ViewerScopedEntityMutatorFactory.ts +8 -8
- package/src/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.ts +4 -4
- package/src/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.ts +14 -13
- package/src/__tests__/AuthorizationResultBasedEntityLoader-test.ts +367 -69
- package/src/__tests__/ComposedCacheAdapter-test.ts +235 -117
- package/src/__tests__/EnforcingEntityLoader-test.ts +135 -1
- package/src/__tests__/Entity-test.ts +2 -2
- package/src/__tests__/EntityAssociationLoader-test.ts +2 -2
- package/src/__tests__/EntityCommonUseCases-test.ts +11 -11
- package/src/__tests__/EntityCompanion-test.ts +4 -4
- package/src/__tests__/EntityCompanionProvider-test.ts +9 -8
- package/src/__tests__/EntityConfiguration-test.ts +85 -6
- package/src/__tests__/EntityDatabaseAdapter-test.ts +113 -17
- package/src/__tests__/EntityEdges-test.ts +97 -72
- package/src/__tests__/EntityFields-test.ts +2 -2
- package/src/__tests__/EntityLoader-test.ts +2 -2
- package/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts +11 -11
- package/src/__tests__/EntityMutator-SingleCompositeFieldCacheConsistency-test.ts +73 -0
- package/src/__tests__/EntityMutator-test.ts +74 -46
- package/src/__tests__/EntityPrivacyPolicy-test.ts +51 -74
- package/src/__tests__/EntityQueryContext-test.ts +1 -1
- package/src/__tests__/EntitySecondaryCacheLoader-test.ts +3 -3
- package/src/__tests__/EntitySelfReferentialEdges-test.ts +64 -39
- package/src/__tests__/GenericEntityCacheAdapter-test.ts +83 -28
- package/src/__tests__/ReadonlyEntity-test.ts +3 -3
- package/src/__tests__/ViewerContext-test.ts +1 -1
- package/src/__tests__/ViewerScopedEntityCompanion-test.ts +5 -2
- package/src/__tests__/ViewerScopedEntityCompanionProvider-test.ts +1 -1
- package/src/__tests__/ViewerScopedEntityMutatorFactory-test.ts +12 -3
- package/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts +12 -12
- package/src/__tests__/cases/TwoEntitySameTableOverlappingRows-test.ts +12 -12
- package/src/entityUtils.ts +4 -1
- package/src/errors/EntityInvalidFieldValueError.ts +5 -5
- package/src/errors/EntityNotAuthorizedError.ts +3 -3
- package/src/errors/EntityNotFoundError.ts +5 -5
- package/src/index.ts +7 -7
- package/src/internal/CompositeFieldHolder.ts +218 -0
- package/src/internal/CompositeFieldValueMap.ts +78 -0
- package/src/internal/EntityDataManager.ts +107 -96
- package/src/internal/EntityFieldTransformationUtils.ts +33 -14
- package/src/internal/EntityLoadInterfaces.ts +143 -0
- package/src/internal/EntityTableDataCoordinator.ts +8 -5
- package/src/internal/ReadThroughEntityCache.ts +63 -50
- package/src/internal/SingleFieldHolder.ts +131 -0
- package/src/internal/__tests__/CompositeFieldHolder-test.ts +25 -0
- package/src/internal/__tests__/CompositeFieldValueMap-test.ts +43 -0
- package/src/internal/__tests__/EntityDataManager-test.ts +308 -91
- package/src/internal/__tests__/EntityFieldTransformationUtils-test.ts +3 -2
- package/src/internal/__tests__/ReadThroughEntityCache-test.ts +315 -107
- package/src/metrics/EntityMetricsUtils.ts +7 -2
- package/src/metrics/IEntityMetricsAdapter.ts +6 -0
- package/src/rules/AlwaysAllowPrivacyPolicyRule.ts +5 -5
- package/src/rules/AlwaysDenyPrivacyPolicyRule.ts +5 -5
- package/src/rules/AlwaysSkipPrivacyPolicyRule.ts +5 -5
- package/src/rules/PrivacyPolicyRule.ts +4 -4
- package/src/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.ts +1 -1
- package/src/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.ts +1 -1
- package/src/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.ts +1 -1
- package/src/utils/EntityPrivacyUtils.ts +72 -30
- package/src/utils/{testing → __testfixtures__}/PrivacyPolicyRuleTestUtils.ts +26 -26
- package/src/{testfixtures → utils/__testfixtures__}/SimpleTestEntity.ts +16 -15
- package/src/utils/__testfixtures__/StubCacheAdapter.ts +164 -0
- package/src/utils/{testing → __testfixtures__}/StubDatabaseAdapter.ts +19 -12
- package/src/utils/{testing → __testfixtures__}/StubDatabaseAdapterProvider.ts +4 -4
- package/src/utils/__testfixtures__/TSMockitoExtensions.ts +69 -0
- package/src/{testfixtures → utils/__testfixtures__}/TestEntity.ts +21 -15
- package/src/{testfixtures → utils/__testfixtures__}/TestEntity2.ts +16 -15
- package/src/{testfixtures → utils/__testfixtures__}/TestEntityWithMutationTriggers.ts +23 -22
- package/src/{testfixtures → utils/__testfixtures__}/TestViewerContext.ts +1 -1
- package/src/utils/{testing → __testfixtures__}/describeFieldTestCase.ts +1 -1
- package/src/utils/__tests__/EntityPrivacyUtils-test.ts +62 -66
- package/src/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.ts +29 -25
- package/src/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.ts +1 -1
- package/src/utils/collections/SerializableKeyMap.ts +84 -0
- package/src/utils/collections/__tests__/SerializableKeyMap-test.ts +119 -0
- package/src/utils/collections/__tests__/sets-test.ts +17 -0
- package/src/utils/collections/maps.ts +7 -8
- package/src/utils/collections/sets.ts +3 -0
- package/src/utils/mergeEntityMutationTriggerConfigurations.ts +5 -5
- package/build/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.d.ts +0 -1
- package/build/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.js +0 -242
- package/build/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.js.map +0 -1
- package/build/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.d.ts +0 -26
- package/build/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.js +0 -110
- package/build/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.js.map +0 -1
- package/build/__tests__/AuthorizationResultBasedEntityLoader-test.d.ts +0 -1
- package/build/__tests__/AuthorizationResultBasedEntityLoader-test.js +0 -401
- package/build/__tests__/AuthorizationResultBasedEntityLoader-test.js.map +0 -1
- package/build/__tests__/ComposedCacheAdapter-test.d.ts +0 -1
- package/build/__tests__/ComposedCacheAdapter-test.js +0 -229
- package/build/__tests__/ComposedCacheAdapter-test.js.map +0 -1
- package/build/__tests__/ComposedSecondaryEntityCache-test.d.ts +0 -1
- package/build/__tests__/ComposedSecondaryEntityCache-test.js +0 -66
- package/build/__tests__/ComposedSecondaryEntityCache-test.js.map +0 -1
- package/build/__tests__/EnforcingEntityAssociationLoader-test.d.ts +0 -1
- package/build/__tests__/EnforcingEntityAssociationLoader-test.js +0 -115
- package/build/__tests__/EnforcingEntityAssociationLoader-test.js.map +0 -1
- package/build/__tests__/EnforcingEntityLoader-test.d.ts +0 -1
- package/build/__tests__/EnforcingEntityLoader-test.js +0 -253
- package/build/__tests__/EnforcingEntityLoader-test.js.map +0 -1
- package/build/__tests__/Entity-test.d.ts +0 -1
- package/build/__tests__/Entity-test.js +0 -94
- package/build/__tests__/Entity-test.js.map +0 -1
- package/build/__tests__/EntityAssociationLoader-test.d.ts +0 -1
- package/build/__tests__/EntityAssociationLoader-test.js +0 -30
- package/build/__tests__/EntityAssociationLoader-test.js.map +0 -1
- package/build/__tests__/EntityCommonUseCases-test.d.ts +0 -1
- package/build/__tests__/EntityCommonUseCases-test.js +0 -146
- package/build/__tests__/EntityCommonUseCases-test.js.map +0 -1
- package/build/__tests__/EntityCompanion-test.d.ts +0 -1
- package/build/__tests__/EntityCompanion-test.js +0 -77
- package/build/__tests__/EntityCompanion-test.js.map +0 -1
- package/build/__tests__/EntityCompanionProvider-test.d.ts +0 -1
- package/build/__tests__/EntityCompanionProvider-test.js +0 -54
- package/build/__tests__/EntityCompanionProvider-test.js.map +0 -1
- package/build/__tests__/EntityConfiguration-test.d.ts +0 -1
- package/build/__tests__/EntityConfiguration-test.js +0 -103
- package/build/__tests__/EntityConfiguration-test.js.map +0 -1
- package/build/__tests__/EntityDatabaseAdapter-test.d.ts +0 -1
- package/build/__tests__/EntityDatabaseAdapter-test.js +0 -146
- package/build/__tests__/EntityDatabaseAdapter-test.js.map +0 -1
- package/build/__tests__/EntityEdges-test.d.ts +0 -1
- package/build/__tests__/EntityEdges-test.js +0 -723
- package/build/__tests__/EntityEdges-test.js.map +0 -1
- package/build/__tests__/EntityFields-test.d.ts +0 -1
- package/build/__tests__/EntityFields-test.js +0 -63
- package/build/__tests__/EntityFields-test.js.map +0 -1
- package/build/__tests__/EntityLoader-test.d.ts +0 -1
- package/build/__tests__/EntityLoader-test.js +0 -36
- package/build/__tests__/EntityLoader-test.js.map +0 -1
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.d.ts +0 -1
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js +0 -73
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js.map +0 -1
- package/build/__tests__/EntityMutator-test.d.ts +0 -1
- package/build/__tests__/EntityMutator-test.js +0 -741
- package/build/__tests__/EntityMutator-test.js.map +0 -1
- package/build/__tests__/EntityPrivacyPolicy-test.d.ts +0 -1
- package/build/__tests__/EntityPrivacyPolicy-test.js +0 -463
- package/build/__tests__/EntityPrivacyPolicy-test.js.map +0 -1
- package/build/__tests__/EntityQueryContext-test.d.ts +0 -1
- package/build/__tests__/EntityQueryContext-test.js +0 -116
- package/build/__tests__/EntityQueryContext-test.js.map +0 -1
- package/build/__tests__/EntitySecondaryCacheLoader-test.d.ts +0 -1
- package/build/__tests__/EntitySecondaryCacheLoader-test.js +0 -60
- package/build/__tests__/EntitySecondaryCacheLoader-test.js.map +0 -1
- package/build/__tests__/EntitySelfReferentialEdges-test.d.ts +0 -1
- package/build/__tests__/EntitySelfReferentialEdges-test.js +0 -201
- package/build/__tests__/EntitySelfReferentialEdges-test.js.map +0 -1
- package/build/__tests__/GenericEntityCacheAdapter-test.d.ts +0 -1
- package/build/__tests__/GenericEntityCacheAdapter-test.js +0 -80
- package/build/__tests__/GenericEntityCacheAdapter-test.js.map +0 -1
- package/build/__tests__/ReadonlyEntity-test.d.ts +0 -1
- package/build/__tests__/ReadonlyEntity-test.js +0 -211
- package/build/__tests__/ReadonlyEntity-test.js.map +0 -1
- package/build/__tests__/ViewerContext-test.d.ts +0 -1
- package/build/__tests__/ViewerContext-test.js +0 -30
- package/build/__tests__/ViewerContext-test.js.map +0 -1
- package/build/__tests__/ViewerScopedEntityCompanion-test.d.ts +0 -1
- package/build/__tests__/ViewerScopedEntityCompanion-test.js +0 -20
- package/build/__tests__/ViewerScopedEntityCompanion-test.js.map +0 -1
- package/build/__tests__/ViewerScopedEntityCompanionProvider-test.d.ts +0 -1
- package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js +0 -20
- package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js.map +0 -1
- package/build/__tests__/ViewerScopedEntityLoaderFactory-test.d.ts +0 -1
- package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js +0 -23
- package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js.map +0 -1
- package/build/__tests__/ViewerScopedEntityMutatorFactory-test.d.ts +0 -1
- package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js +0 -22
- package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js.map +0 -1
- package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.d.ts +0 -1
- package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js +0 -123
- package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js.map +0 -1
- package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.d.ts +0 -1
- package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js +0 -121
- package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js.map +0 -1
- package/build/__tests__/entityUtils-test.d.ts +0 -1
- package/build/__tests__/entityUtils-test.js +0 -87
- package/build/__tests__/entityUtils-test.js.map +0 -1
- package/build/internal/__tests__/EntityDataManager-test.d.ts +0 -1
- package/build/internal/__tests__/EntityDataManager-test.js +0 -373
- package/build/internal/__tests__/EntityDataManager-test.js.map +0 -1
- package/build/internal/__tests__/EntityFieldTransformationUtils-test.d.ts +0 -1
- package/build/internal/__tests__/EntityFieldTransformationUtils-test.js +0 -136
- package/build/internal/__tests__/EntityFieldTransformationUtils-test.js.map +0 -1
- package/build/internal/__tests__/ReadThroughEntityCache-test.d.ts +0 -1
- package/build/internal/__tests__/ReadThroughEntityCache-test.js +0 -206
- package/build/internal/__tests__/ReadThroughEntityCache-test.js.map +0 -1
- package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.d.ts +0 -1
- package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js +0 -21
- package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js.map +0 -1
- package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.d.ts +0 -1
- package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js +0 -21
- package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js.map +0 -1
- package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.d.ts +0 -1
- package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js +0 -21
- package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js.map +0 -1
- package/build/testfixtures/DateIDTestEntity.d.ts +0 -19
- package/build/testfixtures/DateIDTestEntity.js +0 -48
- package/build/testfixtures/DateIDTestEntity.js.map +0 -1
- package/build/testfixtures/SimpleTestEntity.d.ts +0 -20
- package/build/testfixtures/SimpleTestEntity.js +0 -48
- package/build/testfixtures/SimpleTestEntity.js.map +0 -1
- package/build/testfixtures/TestEntity.d.ts +0 -30
- package/build/testfixtures/TestEntity.js +0 -93
- package/build/testfixtures/TestEntity.js.map +0 -1
- package/build/testfixtures/TestEntity2.d.ts +0 -20
- package/build/testfixtures/TestEntity2.js +0 -51
- package/build/testfixtures/TestEntity2.js.map +0 -1
- package/build/testfixtures/TestEntityNumberKey.d.ts +0 -19
- package/build/testfixtures/TestEntityNumberKey.js +0 -48
- package/build/testfixtures/TestEntityNumberKey.js.map +0 -1
- package/build/testfixtures/TestEntityWithMutationTriggers.d.ts +0 -36
- package/build/testfixtures/TestEntityWithMutationTriggers.js +0 -82
- package/build/testfixtures/TestEntityWithMutationTriggers.js.map +0 -1
- package/build/testfixtures/TestViewerContext.d.ts +0 -3
- package/build/testfixtures/TestViewerContext.js +0 -10
- package/build/testfixtures/TestViewerContext.js.map +0 -1
- package/build/utils/__tests__/EntityPrivacyUtils-test.d.ts +0 -1
- package/build/utils/__tests__/EntityPrivacyUtils-test.js +0 -486
- package/build/utils/__tests__/EntityPrivacyUtils-test.js.map +0 -1
- package/build/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.d.ts +0 -1
- package/build/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.js +0 -178
- package/build/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.js.map +0 -1
- package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.d.ts +0 -1
- package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.js +0 -26
- package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.js.map +0 -1
- package/build/utils/collections/__tests__/maps-test.d.ts +0 -1
- package/build/utils/collections/__tests__/maps-test.js +0 -120
- package/build/utils/collections/__tests__/maps-test.js.map +0 -1
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +0 -28
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.js +0 -52
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.js.map +0 -1
- package/build/utils/testing/StubCacheAdapter.d.ts +0 -27
- package/build/utils/testing/StubCacheAdapter.js +0 -86
- package/build/utils/testing/StubCacheAdapter.js.map +0 -1
- package/build/utils/testing/StubDatabaseAdapter.d.ts +0 -25
- package/build/utils/testing/StubDatabaseAdapter.js +0 -191
- package/build/utils/testing/StubDatabaseAdapter.js.map +0 -1
- package/build/utils/testing/StubDatabaseAdapterProvider.d.ts +0 -7
- package/build/utils/testing/StubDatabaseAdapterProvider.js +0 -14
- package/build/utils/testing/StubDatabaseAdapterProvider.js.map +0 -1
- package/build/utils/testing/StubQueryContextProvider.d.ts +0 -7
- package/build/utils/testing/StubQueryContextProvider.js +0 -19
- package/build/utils/testing/StubQueryContextProvider.js.map +0 -1
- package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.d.ts +0 -1
- package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.js +0 -42
- package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.js.map +0 -1
- package/build/utils/testing/__tests__/StubDatabaseAdapter-test.d.ts +0 -1
- package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js +0 -402
- package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js.map +0 -1
- package/build/utils/testing/createUnitTestEntityCompanionProvider.d.ts +0 -7
- package/build/utils/testing/createUnitTestEntityCompanionProvider.js +0 -36
- package/build/utils/testing/createUnitTestEntityCompanionProvider.js.map +0 -1
- package/build/utils/testing/describeFieldTestCase.d.ts +0 -2
- package/build/utils/testing/describeFieldTestCase.js +0 -18
- package/build/utils/testing/describeFieldTestCase.js.map +0 -1
- package/src/testfixtures/DateIDTestEntity.ts +0 -59
- package/src/testfixtures/TestEntityNumberKey.ts +0 -59
- package/src/utils/testing/StubCacheAdapter.ts +0 -122
- package/src/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.ts +0 -42
- package/src/utils/testing/__tests__/StubDatabaseAdapter-test.ts +0 -548
- /package/src/utils/{testing → __testfixtures__}/StubQueryContextProvider.ts +0 -0
- /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
|
|
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<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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:
|
|
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
|
|
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
|
|
92
|
-
* @param
|
|
93
|
-
* @returns map from
|
|
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
|
|
107
|
+
async loadManyEqualingAsync<
|
|
108
|
+
TLoadKey extends IEntityLoadKey<TFields, TIDField, TSerializedLoadValue, TLoadValue>,
|
|
109
|
+
TSerializedLoadValue,
|
|
110
|
+
TLoadValue extends IEntityLoadValue<TSerializedLoadValue>,
|
|
111
|
+
>(
|
|
96
112
|
queryContext: EntityQueryContext,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
): Promise<ReadonlyMap<
|
|
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.
|
|
120
|
+
)(this.loadManyEqualingInternalAsync(queryContext, key, values));
|
|
105
121
|
}
|
|
106
122
|
|
|
107
|
-
private async
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
): Promise<ReadonlyMap<
|
|
112
|
-
|
|
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,
|
|
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:
|
|
141
|
+
fieldValueCount: values.length,
|
|
131
142
|
entityClassName: this.entityClassName,
|
|
143
|
+
loadType: key.getLoadMethodType(),
|
|
132
144
|
});
|
|
133
|
-
const dataLoader = this.
|
|
134
|
-
const results = await dataLoader.loadMany(
|
|
135
|
-
const [
|
|
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
|
-
|
|
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
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
}
|