@expo/entity 0.35.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/AuthorizationResultBasedEntityLoader.d.ts +128 -0
- package/build/AuthorizationResultBasedEntityLoader.js +196 -0
- package/build/AuthorizationResultBasedEntityLoader.js.map +1 -0
- package/build/ComposedEntityCacheAdapter.js +1 -0
- package/build/ComposedEntityCacheAdapter.js.map +1 -1
- package/build/ComposedSecondaryEntityCache.js +1 -0
- package/build/ComposedSecondaryEntityCache.js.map +1 -1
- package/build/EnforcingEntityLoader.d.ts +5 -4
- package/build/EnforcingEntityLoader.js +4 -2
- package/build/EnforcingEntityLoader.js.map +1 -1
- package/build/Entity.d.ts +0 -27
- package/build/Entity.js +0 -50
- package/build/Entity.js.map +1 -1
- package/build/EntityAssociationLoader.d.ts +1 -1
- package/build/EntityAssociationLoader.js +17 -8
- package/build/EntityAssociationLoader.js.map +1 -1
- package/build/EntityCompanion.js +9 -1
- package/build/EntityCompanion.js.map +1 -1
- package/build/EntityCompanionProvider.d.ts +3 -1
- package/build/EntityCompanionProvider.js +10 -4
- package/build/EntityCompanionProvider.js.map +1 -1
- package/build/EntityConfiguration.d.ts +2 -1
- package/build/EntityConfiguration.js +19 -1
- package/build/EntityConfiguration.js.map +1 -1
- package/build/EntityDatabaseAdapter.d.ts +2 -2
- package/build/EntityDatabaseAdapter.js +5 -3
- package/build/EntityDatabaseAdapter.js.map +1 -1
- package/build/EntityFieldDefinition.d.ts +21 -10
- package/build/EntityFieldDefinition.js +8 -9
- package/build/EntityFieldDefinition.js.map +1 -1
- package/build/EntityFields.d.ts +10 -0
- package/build/EntityFields.js +15 -1
- package/build/EntityFields.js.map +1 -1
- package/build/EntityLoader.d.ts +12 -125
- package/build/EntityLoader.js +24 -239
- package/build/EntityLoader.js.map +1 -1
- package/build/EntityLoaderFactory.d.ts +1 -1
- package/build/EntityLoaderFactory.js +3 -0
- package/build/EntityLoaderFactory.js.map +1 -1
- package/build/EntityLoaderUtils.d.ts +58 -0
- package/build/EntityLoaderUtils.js +109 -0
- package/build/EntityLoaderUtils.js.map +1 -0
- package/build/EntityMutator.d.ts +1 -0
- package/build/EntityMutator.js +71 -56
- package/build/EntityMutator.js.map +1 -1
- package/build/EntityMutatorFactory.js +9 -0
- package/build/EntityMutatorFactory.js.map +1 -1
- package/build/EntityPrivacyPolicy.d.ts +11 -5
- package/build/EntityPrivacyPolicy.js +5 -7
- package/build/EntityPrivacyPolicy.js.map +1 -1
- package/build/EntityQueryContext.d.ts +2 -1
- package/build/EntityQueryContext.js +11 -6
- package/build/EntityQueryContext.js.map +1 -1
- package/build/EntitySecondaryCacheLoader.js +5 -1
- package/build/EntitySecondaryCacheLoader.js.map +1 -1
- package/build/GenericEntityCacheAdapter.js +1 -0
- package/build/GenericEntityCacheAdapter.js.map +1 -1
- package/build/GenericSecondaryEntityCache.js +2 -0
- package/build/GenericSecondaryEntityCache.js.map +1 -1
- package/build/IEntityCacheAdapterProvider.d.ts +1 -1
- package/build/IEntityDatabaseAdapterProvider.d.ts +1 -1
- package/build/ReadonlyEntity.js +5 -1
- package/build/ReadonlyEntity.js.map +1 -1
- package/build/ViewerContext.js +2 -0
- package/build/ViewerContext.js.map +1 -1
- package/build/ViewerScopedEntityCompanion.js +2 -0
- package/build/ViewerScopedEntityCompanion.js.map +1 -1
- package/build/ViewerScopedEntityCompanionProvider.d.ts +0 -1
- package/build/ViewerScopedEntityCompanionProvider.js +2 -1
- package/build/ViewerScopedEntityCompanionProvider.js.map +1 -1
- package/build/ViewerScopedEntityLoaderFactory.d.ts +1 -1
- package/build/ViewerScopedEntityLoaderFactory.js +2 -0
- package/build/ViewerScopedEntityLoaderFactory.js.map +1 -1
- package/build/ViewerScopedEntityMutatorFactory.js +2 -0
- package/build/ViewerScopedEntityMutatorFactory.js.map +1 -1
- package/build/__tests__/ComposedCacheAdapter-test.js +2 -0
- package/build/__tests__/ComposedCacheAdapter-test.js.map +1 -1
- package/build/__tests__/ComposedSecondaryEntityCache-test.js +1 -0
- package/build/__tests__/ComposedSecondaryEntityCache-test.js.map +1 -1
- package/build/__tests__/EnforcingEntityLoader-test.js +101 -113
- package/build/__tests__/EnforcingEntityLoader-test.js.map +1 -1
- package/build/__tests__/Entity-test.js +0 -132
- package/build/__tests__/Entity-test.js.map +1 -1
- package/build/__tests__/EntityAssociationLoader-test.js +6 -2
- package/build/__tests__/EntityAssociationLoader-test.js.map +1 -1
- package/build/__tests__/EntityCommonUseCases-test.js +24 -22
- package/build/__tests__/EntityCommonUseCases-test.js.map +1 -1
- package/build/__tests__/EntityCompanion-test.js +26 -3
- package/build/__tests__/EntityCompanion-test.js.map +1 -1
- package/build/__tests__/EntityConfiguration-test.js +103 -0
- package/build/__tests__/EntityConfiguration-test.js.map +1 -0
- package/build/__tests__/EntityDatabaseAdapter-test.js +6 -0
- package/build/__tests__/EntityDatabaseAdapter-test.js.map +1 -1
- package/build/__tests__/EntityEdges-test.js +61 -20
- package/build/__tests__/EntityEdges-test.js.map +1 -1
- package/build/__tests__/EntityFields-test.js +6 -0
- package/build/__tests__/EntityFields-test.js.map +1 -1
- package/build/__tests__/EntityLoader-constructor-test.js +16 -17
- package/build/__tests__/EntityLoader-constructor-test.js.map +1 -1
- package/build/__tests__/EntityLoader-test.js +74 -22
- package/build/__tests__/EntityLoader-test.js.map +1 -1
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js +12 -15
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js.map +1 -1
- package/build/__tests__/EntityMutator-test.js +54 -9
- package/build/__tests__/EntityMutator-test.js.map +1 -1
- package/build/__tests__/EntityPrivacyPolicy-test.js +77 -59
- package/build/__tests__/EntityPrivacyPolicy-test.js.map +1 -1
- package/build/__tests__/EntityQueryContext-test.js +9 -0
- package/build/__tests__/EntityQueryContext-test.js.map +1 -1
- package/build/__tests__/EntitySelfReferentialEdges-test.js +42 -25
- package/build/__tests__/EntitySelfReferentialEdges-test.js.map +1 -1
- package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js.map +1 -1
- package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js +20 -18
- package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js.map +1 -1
- package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js +12 -15
- package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js.map +1 -1
- package/build/entityUtils.d.ts +1 -1
- package/build/entityUtils.js.map +1 -1
- package/build/errors/EntityCacheAdapterError.js +2 -5
- package/build/errors/EntityCacheAdapterError.js.map +1 -1
- package/build/errors/EntityDatabaseAdapterError.js +14 -35
- package/build/errors/EntityDatabaseAdapterError.js.map +1 -1
- package/build/errors/EntityError.js +1 -0
- package/build/errors/EntityError.js.map +1 -1
- package/build/errors/EntityInvalidFieldValueError.js +2 -2
- package/build/errors/EntityInvalidFieldValueError.js.map +1 -1
- package/build/errors/EntityNotAuthorizedError.js +3 -2
- package/build/errors/EntityNotAuthorizedError.js.map +1 -1
- package/build/errors/EntityNotFoundError.js +2 -2
- package/build/errors/EntityNotFoundError.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/internal/EntityDataManager.d.ts +1 -1
- package/build/internal/EntityDataManager.js +6 -1
- package/build/internal/EntityDataManager.js.map +1 -1
- package/build/internal/EntityFieldTransformationUtils.d.ts +5 -5
- package/build/internal/EntityFieldTransformationUtils.js +5 -8
- package/build/internal/EntityFieldTransformationUtils.js.map +1 -1
- package/build/internal/EntityTableDataCoordinator.d.ts +1 -1
- package/build/internal/EntityTableDataCoordinator.js +5 -0
- package/build/internal/EntityTableDataCoordinator.js.map +1 -1
- package/build/internal/ReadThroughEntityCache.d.ts +1 -1
- package/build/internal/ReadThroughEntityCache.js +2 -0
- package/build/internal/ReadThroughEntityCache.js.map +1 -1
- package/build/internal/__tests__/EntityFieldTransformationUtils-test.js +6 -2
- package/build/internal/__tests__/EntityFieldTransformationUtils-test.js.map +1 -1
- package/build/internal/__tests__/ReadThroughEntityCache-test.js +33 -0
- package/build/internal/__tests__/ReadThroughEntityCache-test.js.map +1 -1
- package/build/metrics/IEntityMetricsAdapter.d.ts +1 -1
- package/build/rules/AlwaysAllowPrivacyPolicyRule.d.ts +1 -1
- package/build/rules/AlwaysAllowPrivacyPolicyRule.js.map +1 -1
- package/build/rules/AlwaysDenyPrivacyPolicyRule.d.ts +1 -1
- package/build/rules/AlwaysDenyPrivacyPolicyRule.js.map +1 -1
- package/build/rules/AlwaysSkipPrivacyPolicyRule.d.ts +1 -1
- package/build/rules/AlwaysSkipPrivacyPolicyRule.js.map +1 -1
- package/build/rules/PrivacyPolicyRule.d.ts +1 -1
- package/build/rules/PrivacyPolicyRule.js.map +1 -1
- package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js.map +1 -1
- package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js.map +1 -1
- package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js.map +1 -1
- package/build/testfixtures/DateIDTestEntity.js +12 -15
- package/build/testfixtures/DateIDTestEntity.js.map +1 -1
- package/build/testfixtures/SimpleTestEntity.js +12 -15
- package/build/testfixtures/SimpleTestEntity.js.map +1 -1
- package/build/testfixtures/TestEntity.js +12 -15
- package/build/testfixtures/TestEntity.js.map +1 -1
- package/build/testfixtures/TestEntity2.js +12 -15
- package/build/testfixtures/TestEntity2.js.map +1 -1
- package/build/testfixtures/TestEntityNumberKey.js +12 -15
- package/build/testfixtures/TestEntityNumberKey.js.map +1 -1
- package/build/testfixtures/TestEntityWithMutationTriggers.d.ts +36 -0
- package/build/testfixtures/TestEntityWithMutationTriggers.js +82 -0
- package/build/testfixtures/TestEntityWithMutationTriggers.js.map +1 -0
- package/build/utils/EntityPrivacyUtils.d.ts +34 -0
- package/build/utils/EntityPrivacyUtils.js +160 -0
- package/build/utils/EntityPrivacyUtils.js.map +1 -0
- package/build/utils/__tests__/EntityPrivacyUtils-test.d.ts +1 -0
- package/build/utils/__tests__/EntityPrivacyUtils-test.js +395 -0
- package/build/utils/__tests__/EntityPrivacyUtils-test.js.map +1 -0
- package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.d.ts +1 -0
- package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.js +26 -0
- package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.js.map +1 -0
- package/build/utils/collections/maps.js.map +1 -1
- package/build/utils/mergeEntityMutationTriggerConfigurations.d.ts +4 -0
- package/build/utils/mergeEntityMutationTriggerConfigurations.js +28 -0
- package/build/utils/mergeEntityMutationTriggerConfigurations.js.map +1 -0
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +1 -1
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.js.map +1 -1
- package/build/utils/testing/StubCacheAdapter.d.ts +3 -3
- package/build/utils/testing/StubCacheAdapter.js +3 -3
- package/build/utils/testing/StubCacheAdapter.js.map +1 -1
- package/build/utils/testing/StubDatabaseAdapter.d.ts +2 -2
- package/build/utils/testing/StubDatabaseAdapter.js +4 -2
- package/build/utils/testing/StubDatabaseAdapter.js.map +1 -1
- package/build/utils/testing/StubDatabaseAdapterProvider.d.ts +1 -1
- package/build/utils/testing/StubDatabaseAdapterProvider.js +1 -3
- package/build/utils/testing/StubDatabaseAdapterProvider.js.map +1 -1
- package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.d.ts +1 -0
- package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.js +42 -0
- package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.js.map +1 -0
- package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js +53 -0
- package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js.map +1 -1
- package/build/utils/testing/describeFieldTestCase.js.map +1 -1
- package/package.json +4 -3
- package/src/AuthorizationResultBasedEntityLoader.ts +297 -0
- package/src/ComposedEntityCacheAdapter.ts +6 -6
- package/src/ComposedSecondaryEntityCache.ts +8 -8
- package/src/EnforcingEntityLoader.ts +20 -19
- package/src/Entity.ts +11 -126
- package/src/EntityAssociationLoader.ts +40 -41
- package/src/EntityCompanion.ts +8 -4
- package/src/EntityCompanionProvider.ts +24 -16
- package/src/EntityConfiguration.ts +18 -7
- package/src/EntityDatabaseAdapter.ts +41 -41
- package/src/EntityFieldDefinition.ts +28 -18
- package/src/EntityFields.ts +15 -0
- package/src/EntityLoader.ts +63 -357
- package/src/EntityLoaderFactory.ts +10 -4
- package/src/EntityLoaderUtils.ts +149 -0
- package/src/EntityMutationInfo.ts +2 -2
- package/src/EntityMutationTriggerConfiguration.ts +5 -5
- package/src/EntityMutationValidator.ts +2 -2
- package/src/EntityMutator.ts +146 -144
- package/src/EntityMutatorFactory.ts +8 -8
- package/src/EntityPrivacyPolicy.ts +78 -28
- package/src/EntityQueryContext.ts +14 -13
- package/src/EntityQueryContextProvider.ts +5 -5
- package/src/EntitySecondaryCacheLoader.ts +13 -11
- package/src/GenericEntityCacheAdapter.ts +10 -10
- package/src/GenericSecondaryEntityCache.ts +6 -6
- package/src/IEntityCacheAdapter.ts +4 -4
- package/src/IEntityCacheAdapterProvider.ts +2 -2
- package/src/IEntityDatabaseAdapterProvider.ts +2 -2
- package/src/ReadonlyEntity.ts +5 -5
- package/src/ViewerContext.ts +5 -5
- package/src/ViewerScopedEntityCompanion.ts +4 -4
- package/src/ViewerScopedEntityCompanionProvider.ts +4 -5
- package/src/ViewerScopedEntityLoaderFactory.ts +10 -4
- package/src/ViewerScopedEntityMutatorFactory.ts +5 -5
- package/src/__tests__/ComposedCacheAdapter-test.ts +12 -10
- package/src/__tests__/ComposedSecondaryEntityCache-test.ts +8 -8
- package/src/__tests__/EnforcingEntityLoader-test.ts +236 -159
- package/src/__tests__/Entity-test.ts +0 -202
- package/src/__tests__/EntityAssociationLoader-test.ts +29 -25
- package/src/__tests__/EntityCommonUseCases-test.ts +29 -13
- package/src/__tests__/EntityCompanion-test.ts +57 -5
- package/src/__tests__/EntityConfiguration-test.ts +118 -0
- package/src/__tests__/EntityDatabaseAdapter-test.ts +11 -11
- package/src/__tests__/EntityEdges-test.ts +108 -36
- package/src/__tests__/EntityFields-test.ts +14 -2
- package/src/__tests__/EntityLoader-constructor-test.ts +20 -7
- package/src/__tests__/EntityLoader-test.ts +214 -86
- package/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts +2 -2
- package/src/__tests__/EntityMutator-test.ts +281 -96
- package/src/__tests__/EntityPrivacyPolicy-test.ts +166 -53
- package/src/__tests__/EntityQueryContext-test.ts +30 -12
- package/src/__tests__/EntitySecondaryCacheLoader-test.ts +7 -7
- package/src/__tests__/EntitySelfReferentialEdges-test.ts +46 -26
- package/src/__tests__/GenericEntityCacheAdapter-test.ts +2 -2
- package/src/__tests__/ViewerContext-test.ts +1 -1
- package/src/__tests__/ViewerScopedEntityCompanion-test.ts +2 -2
- package/src/__tests__/ViewerScopedEntityCompanionProvider-test.ts +2 -2
- package/src/__tests__/ViewerScopedEntityLoaderFactory-test.ts +2 -1
- package/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts +19 -19
- package/src/__tests__/entityUtils-test.ts +2 -2
- package/src/entityUtils.ts +4 -4
- package/src/errors/EntityError.ts +4 -1
- package/src/errors/EntityInvalidFieldValueError.ts +2 -2
- package/src/errors/EntityNotAuthorizedError.ts +3 -3
- package/src/errors/EntityNotFoundError.ts +2 -2
- package/src/index.ts +1 -0
- package/src/internal/EntityDataManager.ts +24 -24
- package/src/internal/EntityFieldTransformationUtils.ts +39 -32
- package/src/internal/EntityTableDataCoordinator.ts +3 -3
- package/src/internal/ReadThroughEntityCache.ts +9 -9
- package/src/internal/__tests__/EntityDataManager-test.ts +51 -51
- package/src/internal/__tests__/EntityFieldTransformationUtils-test.ts +14 -10
- package/src/internal/__tests__/ReadThroughEntityCache-test.ts +74 -18
- package/src/metrics/EntityMetricsUtils.ts +4 -4
- package/src/metrics/IEntityMetricsAdapter.ts +1 -1
- package/src/rules/AlwaysAllowPrivacyPolicyRule.ts +9 -3
- package/src/rules/AlwaysDenyPrivacyPolicyRule.ts +9 -3
- package/src/rules/AlwaysSkipPrivacyPolicyRule.ts +9 -3
- package/src/rules/PrivacyPolicyRule.ts +9 -3
- package/src/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.ts +2 -1
- package/src/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.ts +2 -1
- package/src/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.ts +2 -1
- package/src/testfixtures/TestEntity.ts +1 -1
- package/src/testfixtures/TestEntityWithMutationTriggers.ts +156 -0
- package/src/utils/EntityPrivacyUtils.ts +325 -0
- package/src/utils/__tests__/EntityPrivacyUtils-test.ts +570 -0
- package/src/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.ts +29 -0
- package/src/utils/collections/__tests__/maps-test.ts +2 -2
- package/src/utils/collections/maps.ts +11 -11
- package/src/utils/mergeEntityMutationTriggerConfigurations.ts +44 -0
- package/src/utils/testing/PrivacyPolicyRuleTestUtils.ts +25 -22
- package/src/utils/testing/StubCacheAdapter.ts +17 -15
- package/src/utils/testing/StubDatabaseAdapter.ts +35 -30
- package/src/utils/testing/StubDatabaseAdapterProvider.ts +2 -2
- package/src/utils/testing/StubQueryContextProvider.ts +2 -2
- package/src/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.ts +42 -0
- package/src/utils/testing/__tests__/StubDatabaseAdapter-test.ts +111 -29
- package/src/utils/testing/createUnitTestEntityCompanionProvider.ts +2 -2
- package/src/utils/testing/describeFieldTestCase.ts +1 -1
- package/build/__tests__/EntityDataConfiguration-test.js +0 -68
- package/build/__tests__/EntityDataConfiguration-test.js.map +0 -1
- package/src/__tests__/EntityDataConfiguration-test.ts +0 -77
- /package/build/__tests__/{EntityDataConfiguration-test.d.ts → EntityConfiguration-test.d.ts} +0 -0
package/build/EntityLoader.js
CHANGED
|
@@ -3,20 +3,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const
|
|
7
|
-
const invariant_1 = __importDefault(require("invariant"));
|
|
8
|
-
const nullthrows_1 = __importDefault(require("nullthrows"));
|
|
6
|
+
const AuthorizationResultBasedEntityLoader_1 = __importDefault(require("./AuthorizationResultBasedEntityLoader"));
|
|
9
7
|
const EnforcingEntityLoader_1 = __importDefault(require("./EnforcingEntityLoader"));
|
|
10
|
-
const
|
|
11
|
-
const entityUtils_1 = require("./entityUtils");
|
|
12
|
-
const EntityInvalidFieldValueError_1 = __importDefault(require("./errors/EntityInvalidFieldValueError"));
|
|
13
|
-
const EntityNotFoundError_1 = __importDefault(require("./errors/EntityNotFoundError"));
|
|
14
|
-
const maps_1 = require("./utils/collections/maps");
|
|
8
|
+
const EntityLoaderUtils_1 = __importDefault(require("./EntityLoaderUtils"));
|
|
15
9
|
/**
|
|
16
10
|
* The primary interface for loading entities. All normal loads are batched,
|
|
17
11
|
* cached, and authorized against the entity's EntityPrivacyPolicy.
|
|
18
12
|
*/
|
|
19
13
|
class EntityLoader {
|
|
14
|
+
viewerContext;
|
|
15
|
+
queryContext;
|
|
16
|
+
privacyPolicyEvaluationContext;
|
|
17
|
+
entityConfiguration;
|
|
18
|
+
entityClass;
|
|
19
|
+
entitySelectedFields;
|
|
20
|
+
privacyPolicy;
|
|
21
|
+
dataManager;
|
|
22
|
+
metricsAdapter;
|
|
23
|
+
utilsPrivate;
|
|
20
24
|
constructor(viewerContext, queryContext, privacyPolicyEvaluationContext, entityConfiguration, entityClass, entitySelectedFields, privacyPolicy, dataManager, metricsAdapter) {
|
|
21
25
|
this.viewerContext = viewerContext;
|
|
22
26
|
this.queryContext = queryContext;
|
|
@@ -27,249 +31,30 @@ class EntityLoader {
|
|
|
27
31
|
this.privacyPolicy = privacyPolicy;
|
|
28
32
|
this.dataManager = dataManager;
|
|
29
33
|
this.metricsAdapter = metricsAdapter;
|
|
34
|
+
this.utilsPrivate = new EntityLoaderUtils_1.default(this.viewerContext, this.queryContext, this.privacyPolicyEvaluationContext, this.entityConfiguration, this.entityClass, this.entitySelectedFields, this.privacyPolicy, this.dataManager, this.metricsAdapter);
|
|
30
35
|
}
|
|
31
36
|
/**
|
|
32
|
-
* Enforcing
|
|
37
|
+
* Enforcing entity loader. All loads through this loader are
|
|
33
38
|
* guaranteed to be the values of successful results (or null for some loader methods),
|
|
34
39
|
* and will throw otherwise.
|
|
35
40
|
*/
|
|
36
41
|
enforcing() {
|
|
37
|
-
return new EnforcingEntityLoader_1.default(this);
|
|
42
|
+
return new EnforcingEntityLoader_1.default(this.withAuthorizationResults());
|
|
38
43
|
}
|
|
39
44
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* @returns map from fieldValue to entity results that match the query for that fieldValue,
|
|
44
|
-
* where result errors can be UnauthorizedError
|
|
45
|
+
* Authorization-result-based entity loader. All loads through this
|
|
46
|
+
* loader are are results (or null for some loader methods), where an unsuccessful result
|
|
47
|
+
* means an authorization error or entity construction error occurred. Other errors are thrown.
|
|
45
48
|
*/
|
|
46
|
-
|
|
47
|
-
this.
|
|
48
|
-
const fieldValuesToFieldObjects = await this.dataManager.loadManyByFieldEqualingAsync(this.queryContext, fieldName, fieldValues);
|
|
49
|
-
return await this.constructAndAuthorizeEntitiesAsync(fieldValuesToFieldObjects);
|
|
49
|
+
withAuthorizationResults() {
|
|
50
|
+
return new AuthorizationResultBasedEntityLoader_1.default(this.queryContext, this.entityConfiguration, this.entityClass, this.dataManager, this.metricsAdapter, this.utilsPrivate);
|
|
50
51
|
}
|
|
51
52
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* @param fieldValue - fieldName field value being queried
|
|
55
|
-
* @returns array of entity results that match the query for fieldValue, where result error can be UnauthorizedError
|
|
53
|
+
* Entity loader utilities for things like cache invalidation, entity construction, and authorization.
|
|
54
|
+
* Calling into these should only be necessary in rare cases.
|
|
56
55
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const entityResultsForFieldValue = entityResults.get(fieldValue);
|
|
60
|
-
(0, invariant_1.default)(entityResultsForFieldValue !== undefined, `${fieldValue} should be guaranteed to be present in returned map of entities`);
|
|
61
|
-
return entityResultsForFieldValue;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Load an entity where fieldName equals fieldValue, or null if no entity exists.
|
|
65
|
-
* @param uniqueFieldName - entity field being queried
|
|
66
|
-
* @param fieldValue - uniqueFieldName field value being queried
|
|
67
|
-
* @returns entity result where uniqueFieldName equals fieldValue, or null if no entity matches the condition.
|
|
68
|
-
* @throws when multiple entities match the condition
|
|
69
|
-
*/
|
|
70
|
-
async loadByFieldEqualingAsync(uniqueFieldName, fieldValue) {
|
|
71
|
-
const entityResults = await this.loadManyByFieldEqualingAsync(uniqueFieldName, fieldValue);
|
|
72
|
-
(0, invariant_1.default)(entityResults.length <= 1, `loadByFieldEqualing: Multiple entities of type ${this.entityClass.name} found for ${String(uniqueFieldName)}=${fieldValue}`);
|
|
73
|
-
return entityResults[0] ?? null;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Loads an entity by a specified ID.
|
|
77
|
-
* @param id - ID of the entity
|
|
78
|
-
* @returns entity result for matching ID, where result error can be UnauthorizedError or EntityNotFoundError.
|
|
79
|
-
*/
|
|
80
|
-
async loadByIDAsync(id) {
|
|
81
|
-
const entityResults = await this.loadManyByIDsAsync([id]);
|
|
82
|
-
const entityResult = entityResults.get(id);
|
|
83
|
-
if (entityResult === undefined) {
|
|
84
|
-
return (0, results_1.result)(new EntityNotFoundError_1.default(this.entityClass, this.entityConfiguration.idField, id));
|
|
85
|
-
}
|
|
86
|
-
return entityResult;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Load an entity by a specified ID, or return null if non-existent.
|
|
90
|
-
* @param id - ID of the entity
|
|
91
|
-
* @returns entity result for matching ID, or null if no entity exists for ID.
|
|
92
|
-
*/
|
|
93
|
-
async loadByIDNullableAsync(id) {
|
|
94
|
-
return await this.loadByFieldEqualingAsync(this.entityConfiguration.idField, id);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Loads many entities for a list of IDs.
|
|
98
|
-
* @param viewerContext - viewer context of loading user
|
|
99
|
-
* @param ids - IDs of the entities to load
|
|
100
|
-
* @returns map from ID to corresponding entity result, where result error can be UnauthorizedError or EntityNotFoundError.
|
|
101
|
-
*/
|
|
102
|
-
async loadManyByIDsAsync(ids) {
|
|
103
|
-
const entityResults = (await this.loadManyByFieldEqualingManyAsync(this.entityConfiguration.idField, ids));
|
|
104
|
-
return (0, maps_1.mapMap)(entityResults, (entityResultsForId, id) => {
|
|
105
|
-
const entityResult = entityResultsForId[0];
|
|
106
|
-
return (entityResult ??
|
|
107
|
-
(0, results_1.result)(new EntityNotFoundError_1.default(this.entityClass, this.entityConfiguration.idField, id)));
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Loads many entities for a list of IDs, returning null for any IDs that are non-existent.
|
|
112
|
-
* @param ids - IDs of the entities to load
|
|
113
|
-
* @returns map from ID to nullable corresponding entity result, where result error can be UnauthorizedError or EntityNotFoundError.
|
|
114
|
-
*/
|
|
115
|
-
async loadManyByIDsNullableAsync(ids) {
|
|
116
|
-
const entityResults = (await this.loadManyByFieldEqualingManyAsync(this.entityConfiguration.idField, ids));
|
|
117
|
-
return (0, maps_1.mapMap)(entityResults, (entityResultsForId) => {
|
|
118
|
-
return entityResultsForId[0] ?? null;
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Loads the first entity matching the selection constructed from the conjunction of specified
|
|
123
|
-
* operands, or null if no matching entity exists. Entities loaded using this method are not
|
|
124
|
-
* batched or cached.
|
|
125
|
-
*
|
|
126
|
-
* This is a convenience method for {@link loadManyByFieldEqualityConjunctionAsync}. However, the
|
|
127
|
-
* `orderBy` option must be specified to define what "first" means. If ordering doesn't matter,
|
|
128
|
-
* explicitly pass in an empty array.
|
|
129
|
-
*
|
|
130
|
-
* @param fieldEqualityOperands - list of field equality selection operand specifications
|
|
131
|
-
* @param querySelectionModifiers - orderBy and optional offset for the query
|
|
132
|
-
* @returns the first entity results that matches the query, where result error can be
|
|
133
|
-
* UnauthorizedError
|
|
134
|
-
*/
|
|
135
|
-
async loadFirstByFieldEqualityConjunctionAsync(fieldEqualityOperands, querySelectionModifiers) {
|
|
136
|
-
const results = await this.loadManyByFieldEqualityConjunctionAsync(fieldEqualityOperands, {
|
|
137
|
-
...querySelectionModifiers,
|
|
138
|
-
limit: 1,
|
|
139
|
-
});
|
|
140
|
-
return results[0] ?? null;
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Loads many entities matching the selection constructed from the conjunction of specified operands.
|
|
144
|
-
* Entities loaded using this method are not batched or cached.
|
|
145
|
-
*
|
|
146
|
-
* @example
|
|
147
|
-
* fieldEqualityOperands:
|
|
148
|
-
* `[{fieldName: 'hello', fieldValue: 1}, {fieldName: 'world', fieldValues: [2, 3]}]`
|
|
149
|
-
* Entities returned with a SQL EntityDatabaseAdapter:
|
|
150
|
-
* `WHERE hello = 1 AND world = ANY({2, 3})`
|
|
151
|
-
*
|
|
152
|
-
* @param fieldEqualityOperands - list of field equality selection operand specifications
|
|
153
|
-
* @param querySelectionModifiers - limit, offset, and orderBy for the query
|
|
154
|
-
* @returns array of entity results that match the query, where result error can be UnauthorizedError
|
|
155
|
-
*/
|
|
156
|
-
async loadManyByFieldEqualityConjunctionAsync(fieldEqualityOperands, querySelectionModifiers = {}) {
|
|
157
|
-
for (const fieldEqualityOperand of fieldEqualityOperands) {
|
|
158
|
-
const fieldValues = (0, EntityDatabaseAdapter_1.isSingleValueFieldEqualityCondition)(fieldEqualityOperand)
|
|
159
|
-
? [fieldEqualityOperand.fieldValue]
|
|
160
|
-
: fieldEqualityOperand.fieldValues;
|
|
161
|
-
this.validateFieldValues(fieldEqualityOperand.fieldName, fieldValues);
|
|
162
|
-
}
|
|
163
|
-
const fieldObjects = await this.dataManager.loadManyByFieldEqualityConjunctionAsync(this.queryContext, fieldEqualityOperands, querySelectionModifiers);
|
|
164
|
-
const uncheckedEntityResults = this.tryConstructEntities(fieldObjects);
|
|
165
|
-
return await Promise.all(uncheckedEntityResults.map(async (uncheckedEntityResult) => {
|
|
166
|
-
if (!uncheckedEntityResult.ok) {
|
|
167
|
-
return uncheckedEntityResult;
|
|
168
|
-
}
|
|
169
|
-
return await (0, results_1.asyncResult)(this.privacyPolicy.authorizeReadAsync(this.viewerContext, this.queryContext, this.privacyPolicyEvaluationContext, uncheckedEntityResult.value, this.metricsAdapter));
|
|
170
|
-
}));
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Loads many entities matching the raw WHERE clause. Corresponds to the knex `whereRaw` argument format.
|
|
174
|
-
*
|
|
175
|
-
* @remarks
|
|
176
|
-
* Important notes:
|
|
177
|
-
* - Fields in clause are database column names instead of transformed entity field names.
|
|
178
|
-
* - Entities loaded using this method are not batched or cached.
|
|
179
|
-
* - Not all database adapters implement the ability to execute this method of fetching entities.
|
|
180
|
-
*
|
|
181
|
-
* @example
|
|
182
|
-
* rawWhereClause: `id = ?`
|
|
183
|
-
* bindings: `[1]`
|
|
184
|
-
* Entites returned `WHERE id = 1`
|
|
185
|
-
*
|
|
186
|
-
* http://knexjs.org/#Builder-whereRaw
|
|
187
|
-
* http://knexjs.org/#Raw-Bindings
|
|
188
|
-
*
|
|
189
|
-
* @param rawWhereClause - parameterized SQL WHERE clause with positional binding placeholders or named binding placeholders
|
|
190
|
-
* @param bindings - array of positional bindings or object of named bindings
|
|
191
|
-
* @param querySelectionModifiers - limit, offset, orderBy, and orderByRaw for the query
|
|
192
|
-
* @returns array of entity results that match the query, where result error can be UnauthorizedError
|
|
193
|
-
* @throws Error when rawWhereClause or bindings are invalid
|
|
194
|
-
*
|
|
195
|
-
* @deprecated prefer caching loaders
|
|
196
|
-
*/
|
|
197
|
-
async loadManyByRawWhereClauseAsync(rawWhereClause, bindings, querySelectionModifiers = {}) {
|
|
198
|
-
const fieldObjects = await this.dataManager.loadManyByRawWhereClauseAsync(this.queryContext, rawWhereClause, bindings, querySelectionModifiers);
|
|
199
|
-
const uncheckedEntityResults = this.tryConstructEntities(fieldObjects);
|
|
200
|
-
return await Promise.all(uncheckedEntityResults.map(async (uncheckedEntityResult) => {
|
|
201
|
-
if (!uncheckedEntityResult.ok) {
|
|
202
|
-
return uncheckedEntityResult;
|
|
203
|
-
}
|
|
204
|
-
return await (0, results_1.asyncResult)(this.privacyPolicy.authorizeReadAsync(this.viewerContext, this.queryContext, this.privacyPolicyEvaluationContext, uncheckedEntityResult.value, this.metricsAdapter));
|
|
205
|
-
}));
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* Invalidate all caches for an entity's fields. Exposed primarily for internal use by EntityMutator.
|
|
209
|
-
* @param objectFields - entity data object to be invalidated
|
|
210
|
-
*/
|
|
211
|
-
async invalidateFieldsAsync(objectFields) {
|
|
212
|
-
await this.dataManager.invalidateObjectFieldsAsync(objectFields);
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Invalidate all caches for an entity. One potential use case would be to keep the entity
|
|
216
|
-
* framework in sync with changes made to data outside of the framework.
|
|
217
|
-
* @param entity - entity to be invalidated
|
|
218
|
-
*/
|
|
219
|
-
async invalidateEntityAsync(entity) {
|
|
220
|
-
await this.invalidateFieldsAsync(entity.getAllDatabaseFields());
|
|
221
|
-
}
|
|
222
|
-
tryConstructEntities(fieldsObjects) {
|
|
223
|
-
return fieldsObjects.map((fieldsObject) => {
|
|
224
|
-
try {
|
|
225
|
-
return (0, results_1.result)(this.constructEntity(fieldsObject));
|
|
226
|
-
}
|
|
227
|
-
catch (e) {
|
|
228
|
-
if (!(e instanceof Error)) {
|
|
229
|
-
throw e;
|
|
230
|
-
}
|
|
231
|
-
return (0, results_1.result)(e);
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
constructEntity(fieldsObject) {
|
|
236
|
-
const idField = this.entityConfiguration.idField;
|
|
237
|
-
const id = (0, nullthrows_1.default)(fieldsObject[idField], 'must provide ID to create an entity');
|
|
238
|
-
const entitySelectedFields = this.entitySelectedFields ?? Array.from(this.entityConfiguration.schema.keys());
|
|
239
|
-
const selectedFields = (0, entityUtils_1.pick)(fieldsObject, entitySelectedFields);
|
|
240
|
-
return new this.entityClass({
|
|
241
|
-
viewerContext: this.viewerContext,
|
|
242
|
-
id: id,
|
|
243
|
-
databaseFields: fieldsObject,
|
|
244
|
-
selectedFields,
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Construct and authorize entities from fields map, returning error results for entities that fail
|
|
249
|
-
* to construct or fail to authorize.
|
|
250
|
-
*
|
|
251
|
-
* @param map - map from an arbitrary key type to an array of entity field objects
|
|
252
|
-
*/
|
|
253
|
-
async constructAndAuthorizeEntitiesAsync(map) {
|
|
254
|
-
const uncheckedEntityResultsMap = (0, maps_1.mapMap)(map, (fieldObjects) => this.tryConstructEntities(fieldObjects));
|
|
255
|
-
return await (0, maps_1.mapMapAsync)(uncheckedEntityResultsMap, async (uncheckedEntityResults) => {
|
|
256
|
-
return await Promise.all(uncheckedEntityResults.map(async (uncheckedEntityResult) => {
|
|
257
|
-
if (!uncheckedEntityResult.ok) {
|
|
258
|
-
return uncheckedEntityResult;
|
|
259
|
-
}
|
|
260
|
-
return await (0, results_1.asyncResult)(this.privacyPolicy.authorizeReadAsync(this.viewerContext, this.queryContext, this.privacyPolicyEvaluationContext, uncheckedEntityResult.value, this.metricsAdapter));
|
|
261
|
-
}));
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
validateFieldValues(fieldName, fieldValues) {
|
|
265
|
-
const fieldDefinition = this.entityConfiguration.schema.get(fieldName);
|
|
266
|
-
(0, invariant_1.default)(fieldDefinition, `must have field definition for field = ${String(fieldName)}`);
|
|
267
|
-
for (const fieldValue of fieldValues) {
|
|
268
|
-
const isInputValid = fieldDefinition.validateInputValue(fieldValue);
|
|
269
|
-
if (!isInputValid) {
|
|
270
|
-
throw new EntityInvalidFieldValueError_1.default(this.entityClass, fieldName, fieldValue);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
56
|
+
utils() {
|
|
57
|
+
return this.utilsPrivate;
|
|
273
58
|
}
|
|
274
59
|
}
|
|
275
60
|
exports.default = EntityLoader;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityLoader.js","sourceRoot":"","sources":["../src/EntityLoader.ts"],"names":[],"mappings":";;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"EntityLoader.js","sourceRoot":"","sources":["../src/EntityLoader.ts"],"names":[],"mappings":";;;;;AAAA,kHAA0F;AAC1F,oFAA4D;AAG5D,4EAAoD;AAQpD;;;GAGG;AACH,MAAqB,YAAY;IAwBZ;IACA;IACA;IAOA;IACA;IAQA;IACA;IACA;IACE;IA/BJ,YAAY,CAO3B;IAEF,YACmB,aAA6B,EAC7B,YAAgC,EAChC,8BAMhB,EACgB,mBAAiD,EACjD,WAOhB,EACgB,oBAAmD,EACnD,aAA6B,EAC7B,WAAuC,EACrC,cAAqC;QArBvC,kBAAa,GAAb,aAAa,CAAgB;QAC7B,iBAAY,GAAZ,YAAY,CAAoB;QAChC,mCAA8B,GAA9B,8BAA8B,CAM9C;QACgB,wBAAmB,GAAnB,mBAAmB,CAA8B;QACjD,gBAAW,GAAX,WAAW,CAO3B;QACgB,yBAAoB,GAApB,oBAAoB,CAA+B;QACnD,kBAAa,GAAb,aAAa,CAAgB;QAC7B,gBAAW,GAAX,WAAW,CAA4B;QACrC,mBAAc,GAAd,cAAc,CAAuB;QAExD,IAAI,CAAC,YAAY,GAAG,IAAI,2BAAiB,CACvC,IAAI,CAAC,aAAa,EAClB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,8BAA8B,EACnC,IAAI,CAAC,mBAAmB,EACxB,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,oBAAoB,EACzB,IAAI,CAAC,aAAa,EAClB,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,cAAc,CACpB,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,SAAS;QAQP,OAAO,IAAI,+BAAqB,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC,CAAC;IACpE,CAAC;IAED;;;;OAIG;IACH,wBAAwB;QAQtB,OAAO,IAAI,8CAAoC,CAC7C,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,mBAAmB,EACxB,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,cAAc,EACnB,IAAI,CAAC,YAAY,CAClB,CAAC;IACJ,CAAC;IAED;;;OAGG;IACI,KAAK;QAQV,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;CACF;AAjHD,+BAiHC"}
|
|
@@ -19,5 +19,5 @@ export default class EntityLoaderFactory<TFields extends object, TID extends Non
|
|
|
19
19
|
* @param viewerContext - viewer context of loading user
|
|
20
20
|
* @param queryContext - query context in which to perform the load
|
|
21
21
|
*/
|
|
22
|
-
forLoad(viewerContext: TViewerContext, queryContext: EntityQueryContext, privacyPolicyEvaluationContext: EntityPrivacyPolicyEvaluationContext): EntityLoader<TFields, TID, TViewerContext, TEntity, TPrivacyPolicy, TSelectedFields>;
|
|
22
|
+
forLoad(viewerContext: TViewerContext, queryContext: EntityQueryContext, privacyPolicyEvaluationContext: EntityPrivacyPolicyEvaluationContext<TFields, TID, TViewerContext, TEntity, TSelectedFields>): EntityLoader<TFields, TID, TViewerContext, TEntity, TPrivacyPolicy, TSelectedFields>;
|
|
23
23
|
}
|
|
@@ -8,6 +8,9 @@ const EntityLoader_1 = __importDefault(require("./EntityLoader"));
|
|
|
8
8
|
* The primary entry point for loading entities.
|
|
9
9
|
*/
|
|
10
10
|
class EntityLoaderFactory {
|
|
11
|
+
entityCompanion;
|
|
12
|
+
dataManager;
|
|
13
|
+
metricsAdapter;
|
|
11
14
|
constructor(entityCompanion, dataManager, metricsAdapter) {
|
|
12
15
|
this.entityCompanion = entityCompanion;
|
|
13
16
|
this.dataManager = dataManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityLoaderFactory.js","sourceRoot":"","sources":["../src/EntityLoaderFactory.ts"],"names":[],"mappings":";;;;;AACA,kEAA0C;AAQ1C;;GAEG;AACH,MAAqB,mBAAmB;
|
|
1
|
+
{"version":3,"file":"EntityLoaderFactory.js","sourceRoot":"","sources":["../src/EntityLoaderFactory.ts"],"names":[],"mappings":";;;;;AACA,kEAA0C;AAQ1C;;GAEG;AACH,MAAqB,mBAAmB;IAenB;IAQA;IACE;IAVrB,YACmB,eAOhB,EACgB,WAAuC,EACrC,cAAqC;QATvC,oBAAe,GAAf,eAAe,CAO/B;QACgB,gBAAW,GAAX,WAAW,CAA4B;QACrC,mBAAc,GAAd,cAAc,CAAuB;IACvD,CAAC;IAEJ;;;;OAIG;IACH,OAAO,CACL,aAA6B,EAC7B,YAAgC,EAChC,8BAMC;QAED,OAAO,IAAI,sBAAY,CACrB,aAAa,EACb,YAAY,EACZ,8BAA8B,EAC9B,IAAI,CAAC,eAAe,CAAC,yBAAyB,CAAC,mBAAmB,EAClE,IAAI,CAAC,eAAe,CAAC,yBAAyB,CAAC,WAAW,EAC1D,IAAI,CAAC,eAAe,CAAC,yBAAyB,CAAC,oBAAoB,EACnE,IAAI,CAAC,eAAe,CAAC,aAAa,EAClC,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,cAAc,CACpB,CAAC;IACJ,CAAC;CACF;AAvDD,sCAuDC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Result } from '@expo/results';
|
|
2
|
+
import { IEntityClass } from './Entity';
|
|
3
|
+
import EntityConfiguration from './EntityConfiguration';
|
|
4
|
+
import EntityPrivacyPolicy, { EntityPrivacyPolicyEvaluationContext } from './EntityPrivacyPolicy';
|
|
5
|
+
import { EntityQueryContext } from './EntityQueryContext';
|
|
6
|
+
import ReadonlyEntity from './ReadonlyEntity';
|
|
7
|
+
import ViewerContext from './ViewerContext';
|
|
8
|
+
import EntityDataManager from './internal/EntityDataManager';
|
|
9
|
+
import IEntityMetricsAdapter from './metrics/IEntityMetricsAdapter';
|
|
10
|
+
/**
|
|
11
|
+
* Entity loader utilities for things like invalidation, entity construction, and authorization.
|
|
12
|
+
* Methods are exposed publicly since in rare cases they may need to be called manually.
|
|
13
|
+
*/
|
|
14
|
+
export default class EntityLoaderUtils<TFields extends object, TID extends NonNullable<TFields[TSelectedFields]>, TViewerContext extends ViewerContext, TEntity extends ReadonlyEntity<TFields, TID, TViewerContext, TSelectedFields>, TPrivacyPolicy extends EntityPrivacyPolicy<TFields, TID, TViewerContext, TEntity, TSelectedFields>, TSelectedFields extends keyof TFields> {
|
|
15
|
+
private readonly viewerContext;
|
|
16
|
+
private readonly queryContext;
|
|
17
|
+
private readonly privacyPolicyEvaluationContext;
|
|
18
|
+
private readonly entityConfiguration;
|
|
19
|
+
private readonly entityClass;
|
|
20
|
+
private readonly entitySelectedFields;
|
|
21
|
+
private readonly privacyPolicy;
|
|
22
|
+
private readonly dataManager;
|
|
23
|
+
protected readonly metricsAdapter: IEntityMetricsAdapter;
|
|
24
|
+
constructor(viewerContext: TViewerContext, queryContext: EntityQueryContext, privacyPolicyEvaluationContext: EntityPrivacyPolicyEvaluationContext<TFields, TID, TViewerContext, TEntity, TSelectedFields>, entityConfiguration: EntityConfiguration<TFields>, entityClass: IEntityClass<TFields, TID, TViewerContext, TEntity, TPrivacyPolicy, TSelectedFields>, entitySelectedFields: TSelectedFields[] | undefined, privacyPolicy: TPrivacyPolicy, dataManager: EntityDataManager<TFields>, metricsAdapter: IEntityMetricsAdapter);
|
|
25
|
+
/**
|
|
26
|
+
* Invalidate all caches for an entity's fields. Exposed primarily for internal use by EntityMutator.
|
|
27
|
+
* @param objectFields - entity data object to be invalidated
|
|
28
|
+
*/
|
|
29
|
+
invalidateFieldsAsync(objectFields: Readonly<TFields>): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Invalidate all caches for an entity. One potential use case would be to keep the entity
|
|
32
|
+
* framework in sync with changes made to data outside of the framework.
|
|
33
|
+
* @param entity - entity to be invalidated
|
|
34
|
+
*/
|
|
35
|
+
invalidateEntityAsync(entity: TEntity): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Construct an entity from a fields object (applying field selection if applicable),
|
|
38
|
+
* checking that the ID field is specified.
|
|
39
|
+
*
|
|
40
|
+
* @param fieldsObject - fields object
|
|
41
|
+
*/
|
|
42
|
+
constructEntity(fieldsObject: TFields): TEntity;
|
|
43
|
+
/**
|
|
44
|
+
* Construct and authorize entities from fields map, returning error results for entities that fail
|
|
45
|
+
* to construct or fail to authorize.
|
|
46
|
+
*
|
|
47
|
+
* @param map - map from an arbitrary key type to an array of entity field objects
|
|
48
|
+
*/
|
|
49
|
+
constructAndAuthorizeEntitiesAsync<K>(map: ReadonlyMap<K, readonly Readonly<TFields>[]>): Promise<ReadonlyMap<K, readonly Result<TEntity>[]>>;
|
|
50
|
+
/**
|
|
51
|
+
* Construct and authorize entities from field objects array, returning error results for entities that fail
|
|
52
|
+
* to construct or fail to authorize.
|
|
53
|
+
*
|
|
54
|
+
* @param fieldObjects - array of field objects
|
|
55
|
+
*/
|
|
56
|
+
constructAndAuthorizeEntitiesArrayAsync(fieldObjects: readonly Readonly<TFields>[]): Promise<readonly Result<TEntity>[]>;
|
|
57
|
+
private tryConstructEntities;
|
|
58
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const results_1 = require("@expo/results");
|
|
7
|
+
const nullthrows_1 = __importDefault(require("nullthrows"));
|
|
8
|
+
const entityUtils_1 = require("./entityUtils");
|
|
9
|
+
const maps_1 = require("./utils/collections/maps");
|
|
10
|
+
/**
|
|
11
|
+
* Entity loader utilities for things like invalidation, entity construction, and authorization.
|
|
12
|
+
* Methods are exposed publicly since in rare cases they may need to be called manually.
|
|
13
|
+
*/
|
|
14
|
+
class EntityLoaderUtils {
|
|
15
|
+
viewerContext;
|
|
16
|
+
queryContext;
|
|
17
|
+
privacyPolicyEvaluationContext;
|
|
18
|
+
entityConfiguration;
|
|
19
|
+
entityClass;
|
|
20
|
+
entitySelectedFields;
|
|
21
|
+
privacyPolicy;
|
|
22
|
+
dataManager;
|
|
23
|
+
metricsAdapter;
|
|
24
|
+
constructor(viewerContext, queryContext, privacyPolicyEvaluationContext, entityConfiguration, entityClass, entitySelectedFields, privacyPolicy, dataManager, metricsAdapter) {
|
|
25
|
+
this.viewerContext = viewerContext;
|
|
26
|
+
this.queryContext = queryContext;
|
|
27
|
+
this.privacyPolicyEvaluationContext = privacyPolicyEvaluationContext;
|
|
28
|
+
this.entityConfiguration = entityConfiguration;
|
|
29
|
+
this.entityClass = entityClass;
|
|
30
|
+
this.entitySelectedFields = entitySelectedFields;
|
|
31
|
+
this.privacyPolicy = privacyPolicy;
|
|
32
|
+
this.dataManager = dataManager;
|
|
33
|
+
this.metricsAdapter = metricsAdapter;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Invalidate all caches for an entity's fields. Exposed primarily for internal use by EntityMutator.
|
|
37
|
+
* @param objectFields - entity data object to be invalidated
|
|
38
|
+
*/
|
|
39
|
+
async invalidateFieldsAsync(objectFields) {
|
|
40
|
+
await this.dataManager.invalidateObjectFieldsAsync(objectFields);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Invalidate all caches for an entity. One potential use case would be to keep the entity
|
|
44
|
+
* framework in sync with changes made to data outside of the framework.
|
|
45
|
+
* @param entity - entity to be invalidated
|
|
46
|
+
*/
|
|
47
|
+
async invalidateEntityAsync(entity) {
|
|
48
|
+
await this.invalidateFieldsAsync(entity.getAllDatabaseFields());
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Construct an entity from a fields object (applying field selection if applicable),
|
|
52
|
+
* checking that the ID field is specified.
|
|
53
|
+
*
|
|
54
|
+
* @param fieldsObject - fields object
|
|
55
|
+
*/
|
|
56
|
+
constructEntity(fieldsObject) {
|
|
57
|
+
const idField = this.entityConfiguration.idField;
|
|
58
|
+
const id = (0, nullthrows_1.default)(fieldsObject[idField], 'must provide ID to create an entity');
|
|
59
|
+
const entitySelectedFields = this.entitySelectedFields ?? Array.from(this.entityConfiguration.schema.keys());
|
|
60
|
+
const selectedFields = (0, entityUtils_1.pick)(fieldsObject, entitySelectedFields);
|
|
61
|
+
return new this.entityClass({
|
|
62
|
+
viewerContext: this.viewerContext,
|
|
63
|
+
id: id,
|
|
64
|
+
databaseFields: fieldsObject,
|
|
65
|
+
selectedFields,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Construct and authorize entities from fields map, returning error results for entities that fail
|
|
70
|
+
* to construct or fail to authorize.
|
|
71
|
+
*
|
|
72
|
+
* @param map - map from an arbitrary key type to an array of entity field objects
|
|
73
|
+
*/
|
|
74
|
+
async constructAndAuthorizeEntitiesAsync(map) {
|
|
75
|
+
return await (0, maps_1.mapMapAsync)(map, async (fieldObjects) => {
|
|
76
|
+
return await this.constructAndAuthorizeEntitiesArrayAsync(fieldObjects);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Construct and authorize entities from field objects array, returning error results for entities that fail
|
|
81
|
+
* to construct or fail to authorize.
|
|
82
|
+
*
|
|
83
|
+
* @param fieldObjects - array of field objects
|
|
84
|
+
*/
|
|
85
|
+
async constructAndAuthorizeEntitiesArrayAsync(fieldObjects) {
|
|
86
|
+
const uncheckedEntityResults = this.tryConstructEntities(fieldObjects);
|
|
87
|
+
return await Promise.all(uncheckedEntityResults.map(async (uncheckedEntityResult) => {
|
|
88
|
+
if (!uncheckedEntityResult.ok) {
|
|
89
|
+
return uncheckedEntityResult;
|
|
90
|
+
}
|
|
91
|
+
return await (0, results_1.asyncResult)(this.privacyPolicy.authorizeReadAsync(this.viewerContext, this.queryContext, this.privacyPolicyEvaluationContext, uncheckedEntityResult.value, this.metricsAdapter));
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
tryConstructEntities(fieldsObjects) {
|
|
95
|
+
return fieldsObjects.map((fieldsObject) => {
|
|
96
|
+
try {
|
|
97
|
+
return (0, results_1.result)(this.constructEntity(fieldsObject));
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
if (!(e instanceof Error)) {
|
|
101
|
+
throw e;
|
|
102
|
+
}
|
|
103
|
+
return (0, results_1.result)(e);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
exports.default = EntityLoaderUtils;
|
|
109
|
+
//# sourceMappingURL=EntityLoaderUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityLoaderUtils.js","sourceRoot":"","sources":["../src/EntityLoaderUtils.ts"],"names":[],"mappings":"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"}
|
package/build/EntityMutator.d.ts
CHANGED
|
@@ -79,6 +79,7 @@ export declare class UpdateMutator<TFields extends object, TID extends NonNullab
|
|
|
79
79
|
enforceUpdateAsync(): Promise<TEntity>;
|
|
80
80
|
private updateInTransactionAsync;
|
|
81
81
|
private updateInternalAsync;
|
|
82
|
+
private ensureStableIDField;
|
|
82
83
|
}
|
|
83
84
|
/**
|
|
84
85
|
* Mutator for deleting an existing entity.
|