@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
|
@@ -61,7 +61,7 @@ export interface EntityCompanionDefinition<
|
|
|
61
61
|
TEntity,
|
|
62
62
|
TSelectedFields
|
|
63
63
|
>,
|
|
64
|
-
TSelectedFields extends keyof TFields = keyof TFields
|
|
64
|
+
TSelectedFields extends keyof TFields = keyof TFields,
|
|
65
65
|
> {
|
|
66
66
|
/**
|
|
67
67
|
* The concrete Entity class for which this is the definition.
|
|
@@ -139,6 +139,7 @@ export default class EntityCompanionProvider {
|
|
|
139
139
|
* @param metricsAdapter - An IEntityMetricsAdapter for collecting metrics on this instance
|
|
140
140
|
* @param databaseAdapterFlavors - Database adapter configurations for this instance
|
|
141
141
|
* @param cacheAdapterFlavors - Cache adapter configurations for this instance
|
|
142
|
+
* @param globalMutationTriggers - Optional set of EntityMutationTrigger to run for all entity mutations systemwide.
|
|
142
143
|
*/
|
|
143
144
|
constructor(
|
|
144
145
|
public readonly metricsAdapter: IEntityMetricsAdapter,
|
|
@@ -146,7 +147,14 @@ export default class EntityCompanionProvider {
|
|
|
146
147
|
DatabaseAdapterFlavor,
|
|
147
148
|
DatabaseAdapterFlavorDefinition
|
|
148
149
|
>,
|
|
149
|
-
private cacheAdapterFlavors: ReadonlyMap<CacheAdapterFlavor, CacheAdapterFlavorDefinition
|
|
150
|
+
private cacheAdapterFlavors: ReadonlyMap<CacheAdapterFlavor, CacheAdapterFlavorDefinition>,
|
|
151
|
+
readonly globalMutationTriggers: EntityMutationTriggerConfiguration<
|
|
152
|
+
any,
|
|
153
|
+
any,
|
|
154
|
+
any,
|
|
155
|
+
any,
|
|
156
|
+
any
|
|
157
|
+
> = {},
|
|
150
158
|
) {}
|
|
151
159
|
|
|
152
160
|
/**
|
|
@@ -167,7 +175,7 @@ export default class EntityCompanionProvider {
|
|
|
167
175
|
TEntity,
|
|
168
176
|
TSelectedFields
|
|
169
177
|
>,
|
|
170
|
-
TSelectedFields extends keyof TFields
|
|
178
|
+
TSelectedFields extends keyof TFields,
|
|
171
179
|
>(
|
|
172
180
|
entityClass: IEntityClass<
|
|
173
181
|
TFields,
|
|
@@ -176,58 +184,58 @@ export default class EntityCompanionProvider {
|
|
|
176
184
|
TEntity,
|
|
177
185
|
TPrivacyPolicy,
|
|
178
186
|
TSelectedFields
|
|
179
|
-
|
|
187
|
+
>,
|
|
180
188
|
): EntityCompanion<TFields, TID, TViewerContext, TEntity, TPrivacyPolicy, TSelectedFields> {
|
|
181
189
|
const entityCompanionDefinition = computeIfAbsent(
|
|
182
190
|
this.companionDefinitionMap,
|
|
183
191
|
entityClass.name,
|
|
184
|
-
() => entityClass.defineCompanionDefinition()
|
|
192
|
+
() => entityClass.defineCompanionDefinition(),
|
|
185
193
|
);
|
|
186
194
|
const tableDataCoordinator = this.getTableDataCoordinatorForEntity(
|
|
187
195
|
entityCompanionDefinition.entityConfiguration,
|
|
188
|
-
entityClass.name
|
|
196
|
+
entityClass.name,
|
|
189
197
|
);
|
|
190
198
|
return computeIfAbsent(this.companionMap, entityClass.name, () => {
|
|
191
199
|
return new EntityCompanion(
|
|
192
200
|
this,
|
|
193
201
|
entityCompanionDefinition,
|
|
194
202
|
tableDataCoordinator,
|
|
195
|
-
this.metricsAdapter
|
|
203
|
+
this.metricsAdapter,
|
|
196
204
|
);
|
|
197
205
|
});
|
|
198
206
|
}
|
|
199
207
|
|
|
200
208
|
getQueryContextProviderForDatabaseAdaptorFlavor(
|
|
201
|
-
databaseAdapterFlavor: DatabaseAdapterFlavor
|
|
209
|
+
databaseAdapterFlavor: DatabaseAdapterFlavor,
|
|
202
210
|
): EntityQueryContextProvider {
|
|
203
211
|
const entityDatabaseAdapterFlavor = this.databaseAdapterFlavors.get(databaseAdapterFlavor);
|
|
204
212
|
invariant(
|
|
205
213
|
entityDatabaseAdapterFlavor,
|
|
206
|
-
`No database adaptor configuration found for flavor: ${databaseAdapterFlavor}
|
|
214
|
+
`No database adaptor configuration found for flavor: ${databaseAdapterFlavor}`,
|
|
207
215
|
);
|
|
208
216
|
|
|
209
217
|
return entityDatabaseAdapterFlavor.queryContextProvider;
|
|
210
218
|
}
|
|
211
219
|
|
|
212
|
-
private getTableDataCoordinatorForEntity<TFields
|
|
220
|
+
private getTableDataCoordinatorForEntity<TFields extends Record<string, any>>(
|
|
213
221
|
entityConfiguration: EntityConfiguration<TFields>,
|
|
214
|
-
entityClassName: string
|
|
222
|
+
entityClassName: string,
|
|
215
223
|
): EntityTableDataCoordinator<TFields> {
|
|
216
224
|
return computeIfAbsent(this.tableDataCoordinatorMap, entityConfiguration.tableName, () => {
|
|
217
225
|
const entityDatabaseAdapterFlavor = this.databaseAdapterFlavors.get(
|
|
218
|
-
entityConfiguration.databaseAdapterFlavor
|
|
226
|
+
entityConfiguration.databaseAdapterFlavor,
|
|
219
227
|
);
|
|
220
228
|
invariant(
|
|
221
229
|
entityDatabaseAdapterFlavor,
|
|
222
|
-
`No database adaptor configuration found for flavor: ${entityConfiguration.databaseAdapterFlavor}
|
|
230
|
+
`No database adaptor configuration found for flavor: ${entityConfiguration.databaseAdapterFlavor}`,
|
|
223
231
|
);
|
|
224
232
|
|
|
225
233
|
const entityCacheAdapterFlavor = this.cacheAdapterFlavors.get(
|
|
226
|
-
entityConfiguration.cacheAdapterFlavor
|
|
234
|
+
entityConfiguration.cacheAdapterFlavor,
|
|
227
235
|
);
|
|
228
236
|
invariant(
|
|
229
237
|
entityCacheAdapterFlavor,
|
|
230
|
-
`No cache adaptor configuration found for flavor: ${entityConfiguration.cacheAdapterFlavor}
|
|
238
|
+
`No cache adaptor configuration found for flavor: ${entityConfiguration.cacheAdapterFlavor}`,
|
|
231
239
|
);
|
|
232
240
|
|
|
233
241
|
return new EntityTableDataCoordinator(
|
|
@@ -236,7 +244,7 @@ export default class EntityCompanionProvider {
|
|
|
236
244
|
entityCacheAdapterFlavor.cacheAdapterProvider,
|
|
237
245
|
entityDatabaseAdapterFlavor.queryContextProvider,
|
|
238
246
|
this.metricsAdapter,
|
|
239
|
-
entityClassName
|
|
247
|
+
entityClassName,
|
|
240
248
|
);
|
|
241
249
|
});
|
|
242
250
|
}
|
|
@@ -7,7 +7,7 @@ import { mapMap, invertMap, reduceMap } from './utils/collections/maps';
|
|
|
7
7
|
* The data storage configuration for a type of Entity. Contains information relating to IDs,
|
|
8
8
|
* cachable fields, field mappings, and types of cache and database adapter.
|
|
9
9
|
*/
|
|
10
|
-
export default class EntityConfiguration<TFields
|
|
10
|
+
export default class EntityConfiguration<TFields extends Record<string, any>> {
|
|
11
11
|
readonly idField: keyof TFields;
|
|
12
12
|
readonly tableName: string;
|
|
13
13
|
readonly cacheableKeys: ReadonlySet<keyof TFields>;
|
|
@@ -75,18 +75,29 @@ export default class EntityConfiguration<TFields> {
|
|
|
75
75
|
|
|
76
76
|
// external schema is a Record to typecheck that all fields have FieldDefinitions,
|
|
77
77
|
// but internally the most useful representation is a map for lookups
|
|
78
|
-
|
|
79
|
-
this.schema = new Map(Object.entries(schema)
|
|
78
|
+
EntityConfiguration.validateSchema(schema);
|
|
79
|
+
this.schema = new Map(Object.entries(schema));
|
|
80
80
|
|
|
81
81
|
this.cacheableKeys = EntityConfiguration.computeCacheableKeys(this.schema);
|
|
82
82
|
this.entityToDBFieldsKeyMapping = EntityConfiguration.computeEntityToDBFieldsKeyMapping(
|
|
83
|
-
this.schema
|
|
83
|
+
this.schema,
|
|
84
84
|
);
|
|
85
85
|
this.dbToEntityFieldsKeyMapping = invertMap(this.entityToDBFieldsKeyMapping);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
private static validateSchema<TFields extends Record<string, any>>(schema: TFields): void {
|
|
89
|
+
const disallowedFieldsKeys = Object.getOwnPropertyNames(Object.prototype);
|
|
90
|
+
for (const disallowedFieldsKey of disallowedFieldsKeys) {
|
|
91
|
+
if (Object.hasOwn(schema, disallowedFieldsKey)) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`Entity field name not allowed to prevent conflicts with standard Object prototype fields: ${disallowedFieldsKey}`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
88
99
|
private static computeCacheableKeys<TFields>(
|
|
89
|
-
schema: ReadonlyMap<keyof TFields, EntityFieldDefinition<any
|
|
100
|
+
schema: ReadonlyMap<keyof TFields, EntityFieldDefinition<any>>,
|
|
90
101
|
): ReadonlySet<keyof TFields> {
|
|
91
102
|
return reduceMap(
|
|
92
103
|
schema,
|
|
@@ -96,12 +107,12 @@ export default class EntityConfiguration<TFields> {
|
|
|
96
107
|
}
|
|
97
108
|
return acc;
|
|
98
109
|
},
|
|
99
|
-
new Set<keyof TFields>()
|
|
110
|
+
new Set<keyof TFields>(),
|
|
100
111
|
);
|
|
101
112
|
}
|
|
102
113
|
|
|
103
114
|
private static computeEntityToDBFieldsKeyMapping<TFields>(
|
|
104
|
-
schema: ReadonlyMap<keyof TFields, EntityFieldDefinition<any
|
|
115
|
+
schema: ReadonlyMap<keyof TFields, EntityFieldDefinition<any>>,
|
|
105
116
|
): ReadonlyMap<keyof TFields, string> {
|
|
106
117
|
return mapMap(schema, (v) => v.columnName);
|
|
107
118
|
}
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
*/
|
|
13
13
|
export interface SingleValueFieldEqualityCondition<
|
|
14
14
|
TFields,
|
|
15
|
-
N extends keyof TFields = keyof TFields
|
|
15
|
+
N extends keyof TFields = keyof TFields,
|
|
16
16
|
> {
|
|
17
17
|
fieldName: N;
|
|
18
18
|
fieldValue: TFields[N];
|
|
@@ -23,7 +23,7 @@ export interface SingleValueFieldEqualityCondition<
|
|
|
23
23
|
*/
|
|
24
24
|
export interface MultiValueFieldEqualityCondition<
|
|
25
25
|
TFields,
|
|
26
|
-
N extends keyof TFields = keyof TFields
|
|
26
|
+
N extends keyof TFields = keyof TFields,
|
|
27
27
|
> {
|
|
28
28
|
fieldName: N;
|
|
29
29
|
fieldValues: readonly TFields[N][];
|
|
@@ -39,9 +39,9 @@ export type FieldEqualityCondition<TFields, N extends keyof TFields = keyof TFie
|
|
|
39
39
|
|
|
40
40
|
export function isSingleValueFieldEqualityCondition<
|
|
41
41
|
TFields,
|
|
42
|
-
N extends keyof TFields = keyof TFields
|
|
42
|
+
N extends keyof TFields = keyof TFields,
|
|
43
43
|
>(
|
|
44
|
-
condition: FieldEqualityCondition<TFields, N
|
|
44
|
+
condition: FieldEqualityCondition<TFields, N>,
|
|
45
45
|
): condition is SingleValueFieldEqualityCondition<TFields, N> {
|
|
46
46
|
return (condition as SingleValueFieldEqualityCondition<TFields, N>).fieldValue !== undefined;
|
|
47
47
|
}
|
|
@@ -113,7 +113,7 @@ export interface TableQuerySelectionModifiersWithOrderByRaw extends TableQuerySe
|
|
|
113
113
|
* handles all entity field transformation. Subclasses are responsible for
|
|
114
114
|
* implementing database-specific logic for a type of database.
|
|
115
115
|
*/
|
|
116
|
-
export default abstract class EntityDatabaseAdapter<TFields
|
|
116
|
+
export default abstract class EntityDatabaseAdapter<TFields extends Record<string, any>> {
|
|
117
117
|
private readonly fieldTransformerMap: FieldTransformerMap;
|
|
118
118
|
|
|
119
119
|
constructor(private readonly entityConfiguration: EntityConfiguration<TFields>) {
|
|
@@ -137,18 +137,18 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
137
137
|
*/
|
|
138
138
|
async fetchManyWhereAsync<K extends keyof TFields>(
|
|
139
139
|
queryContext: EntityQueryContext,
|
|
140
|
-
|
|
141
|
-
fieldValues: readonly NonNullable<TFields[K]>[]
|
|
140
|
+
fieldName: K,
|
|
141
|
+
fieldValues: readonly NonNullable<TFields[K]>[],
|
|
142
142
|
): Promise<ReadonlyMap<NonNullable<TFields[K]>, readonly Readonly<TFields>[]>> {
|
|
143
|
-
const fieldColumn = getDatabaseFieldForEntityField(this.entityConfiguration,
|
|
143
|
+
const fieldColumn = getDatabaseFieldForEntityField(this.entityConfiguration, fieldName);
|
|
144
144
|
const results = await this.fetchManyWhereInternalAsync(
|
|
145
145
|
queryContext.getQueryInterface(),
|
|
146
146
|
this.entityConfiguration.tableName,
|
|
147
147
|
fieldColumn,
|
|
148
|
-
fieldValues
|
|
148
|
+
fieldValues,
|
|
149
149
|
);
|
|
150
150
|
const objects = results.map((result) =>
|
|
151
|
-
transformDatabaseObjectToFields(this.entityConfiguration, this.fieldTransformerMap, result)
|
|
151
|
+
transformDatabaseObjectToFields(this.entityConfiguration, this.fieldTransformerMap, result),
|
|
152
152
|
);
|
|
153
153
|
|
|
154
154
|
const objectMap = new Map();
|
|
@@ -157,7 +157,7 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
objects.forEach((object) => {
|
|
160
|
-
const objectFieldValue = object[
|
|
160
|
+
const objectFieldValue = object[fieldName];
|
|
161
161
|
objectMap.get(objectFieldValue).push(object);
|
|
162
162
|
});
|
|
163
163
|
|
|
@@ -168,7 +168,7 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
168
168
|
queryInterface: any,
|
|
169
169
|
tableName: string,
|
|
170
170
|
tableField: string,
|
|
171
|
-
tableValues: readonly any[]
|
|
171
|
+
tableValues: readonly any[],
|
|
172
172
|
): Promise<object[]>;
|
|
173
173
|
|
|
174
174
|
/**
|
|
@@ -183,7 +183,7 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
183
183
|
async fetchManyByFieldEqualityConjunctionAsync<N extends keyof TFields>(
|
|
184
184
|
queryContext: EntityQueryContext,
|
|
185
185
|
fieldEqualityOperands: FieldEqualityCondition<TFields, N>[],
|
|
186
|
-
querySelectionModifiers: QuerySelectionModifiers<TFields
|
|
186
|
+
querySelectionModifiers: QuerySelectionModifiers<TFields>,
|
|
187
187
|
): Promise<readonly Readonly<TFields>[]> {
|
|
188
188
|
const tableFieldSingleValueOperands: TableFieldSingleValueEqualityCondition[] = [];
|
|
189
189
|
const tableFieldMultipleValueOperands: TableFieldMultiValueEqualityCondition[] = [];
|
|
@@ -206,11 +206,11 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
206
206
|
this.entityConfiguration.tableName,
|
|
207
207
|
tableFieldSingleValueOperands,
|
|
208
208
|
tableFieldMultipleValueOperands,
|
|
209
|
-
this.convertToTableQueryModifiers(querySelectionModifiers)
|
|
209
|
+
this.convertToTableQueryModifiers(querySelectionModifiers),
|
|
210
210
|
);
|
|
211
211
|
|
|
212
212
|
return results.map((result) =>
|
|
213
|
-
transformDatabaseObjectToFields(this.entityConfiguration, this.fieldTransformerMap, result)
|
|
213
|
+
transformDatabaseObjectToFields(this.entityConfiguration, this.fieldTransformerMap, result),
|
|
214
214
|
);
|
|
215
215
|
}
|
|
216
216
|
|
|
@@ -219,7 +219,7 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
219
219
|
tableName: string,
|
|
220
220
|
tableFieldSingleValueEqualityOperands: TableFieldSingleValueEqualityCondition[],
|
|
221
221
|
tableFieldMultiValueEqualityOperands: TableFieldMultiValueEqualityCondition[],
|
|
222
|
-
querySelectionModifiers: TableQuerySelectionModifiers
|
|
222
|
+
querySelectionModifiers: TableQuerySelectionModifiers,
|
|
223
223
|
): Promise<object[]>;
|
|
224
224
|
|
|
225
225
|
/**
|
|
@@ -235,18 +235,18 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
235
235
|
queryContext: EntityQueryContext,
|
|
236
236
|
rawWhereClause: string,
|
|
237
237
|
bindings: any[] | object,
|
|
238
|
-
querySelectionModifiers: QuerySelectionModifiersWithOrderByRaw<TFields
|
|
238
|
+
querySelectionModifiers: QuerySelectionModifiersWithOrderByRaw<TFields>,
|
|
239
239
|
): Promise<readonly Readonly<TFields>[]> {
|
|
240
240
|
const results = await this.fetchManyByRawWhereClauseInternalAsync(
|
|
241
241
|
queryContext.getQueryInterface(),
|
|
242
242
|
this.entityConfiguration.tableName,
|
|
243
243
|
rawWhereClause,
|
|
244
244
|
bindings,
|
|
245
|
-
this.convertToTableQueryModifiersWithOrderByRaw(querySelectionModifiers)
|
|
245
|
+
this.convertToTableQueryModifiersWithOrderByRaw(querySelectionModifiers),
|
|
246
246
|
);
|
|
247
247
|
|
|
248
248
|
return results.map((result) =>
|
|
249
|
-
transformDatabaseObjectToFields(this.entityConfiguration, this.fieldTransformerMap, result)
|
|
249
|
+
transformDatabaseObjectToFields(this.entityConfiguration, this.fieldTransformerMap, result),
|
|
250
250
|
);
|
|
251
251
|
}
|
|
252
252
|
|
|
@@ -255,7 +255,7 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
255
255
|
tableName: string,
|
|
256
256
|
rawWhereClause: string,
|
|
257
257
|
bindings: any[] | object,
|
|
258
|
-
querySelectionModifiers: TableQuerySelectionModifiersWithOrderByRaw
|
|
258
|
+
querySelectionModifiers: TableQuerySelectionModifiersWithOrderByRaw,
|
|
259
259
|
): Promise<object[]>;
|
|
260
260
|
|
|
261
261
|
/**
|
|
@@ -267,40 +267,40 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
267
267
|
*/
|
|
268
268
|
async insertAsync(
|
|
269
269
|
queryContext: EntityQueryContext,
|
|
270
|
-
object: Readonly<Partial<TFields
|
|
270
|
+
object: Readonly<Partial<TFields>>,
|
|
271
271
|
): Promise<Readonly<TFields>> {
|
|
272
272
|
const dbObject = transformFieldsToDatabaseObject(
|
|
273
273
|
this.entityConfiguration,
|
|
274
274
|
this.fieldTransformerMap,
|
|
275
|
-
object
|
|
275
|
+
object,
|
|
276
276
|
);
|
|
277
277
|
const results = await this.insertInternalAsync(
|
|
278
278
|
queryContext.getQueryInterface(),
|
|
279
279
|
this.entityConfiguration.tableName,
|
|
280
|
-
dbObject
|
|
280
|
+
dbObject,
|
|
281
281
|
);
|
|
282
282
|
|
|
283
283
|
if (results.length > 1) {
|
|
284
284
|
throw new Error(
|
|
285
|
-
`Excessive results from database adapter insert: ${this.entityConfiguration.tableName}
|
|
285
|
+
`Excessive results from database adapter insert: ${this.entityConfiguration.tableName}`,
|
|
286
286
|
);
|
|
287
287
|
} else if (results.length === 0) {
|
|
288
288
|
throw new Error(
|
|
289
|
-
`Empty results from database adapter insert: ${this.entityConfiguration.tableName}
|
|
289
|
+
`Empty results from database adapter insert: ${this.entityConfiguration.tableName}`,
|
|
290
290
|
);
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
return transformDatabaseObjectToFields(
|
|
294
294
|
this.entityConfiguration,
|
|
295
295
|
this.fieldTransformerMap,
|
|
296
|
-
results[0]
|
|
296
|
+
results[0]!,
|
|
297
297
|
);
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
protected abstract insertInternalAsync(
|
|
301
301
|
queryInterface: any,
|
|
302
302
|
tableName: string,
|
|
303
|
-
object: object
|
|
303
|
+
object: object,
|
|
304
304
|
): Promise<object[]>;
|
|
305
305
|
|
|
306
306
|
/**
|
|
@@ -316,36 +316,36 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
316
316
|
queryContext: EntityQueryContext,
|
|
317
317
|
idField: K,
|
|
318
318
|
id: any,
|
|
319
|
-
object: Readonly<Partial<TFields
|
|
319
|
+
object: Readonly<Partial<TFields>>,
|
|
320
320
|
): Promise<Readonly<TFields>> {
|
|
321
321
|
const idColumn = getDatabaseFieldForEntityField(this.entityConfiguration, idField);
|
|
322
322
|
const dbObject = transformFieldsToDatabaseObject(
|
|
323
323
|
this.entityConfiguration,
|
|
324
324
|
this.fieldTransformerMap,
|
|
325
|
-
object
|
|
325
|
+
object,
|
|
326
326
|
);
|
|
327
327
|
const results = await this.updateInternalAsync(
|
|
328
328
|
queryContext.getQueryInterface(),
|
|
329
329
|
this.entityConfiguration.tableName,
|
|
330
330
|
idColumn,
|
|
331
331
|
id,
|
|
332
|
-
dbObject
|
|
332
|
+
dbObject,
|
|
333
333
|
);
|
|
334
334
|
|
|
335
335
|
if (results.length > 1) {
|
|
336
336
|
throw new Error(
|
|
337
|
-
`Excessive results from database adapter update: ${this.entityConfiguration.tableName}(id = ${id})
|
|
337
|
+
`Excessive results from database adapter update: ${this.entityConfiguration.tableName}(id = ${id})`,
|
|
338
338
|
);
|
|
339
339
|
} else if (results.length === 0) {
|
|
340
340
|
throw new Error(
|
|
341
|
-
`Empty results from database adapter update: ${this.entityConfiguration.tableName}(id = ${id})
|
|
341
|
+
`Empty results from database adapter update: ${this.entityConfiguration.tableName}(id = ${id})`,
|
|
342
342
|
);
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
return transformDatabaseObjectToFields(
|
|
346
346
|
this.entityConfiguration,
|
|
347
347
|
this.fieldTransformerMap,
|
|
348
|
-
results[0]
|
|
348
|
+
results[0]!,
|
|
349
349
|
);
|
|
350
350
|
}
|
|
351
351
|
|
|
@@ -354,7 +354,7 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
354
354
|
tableName: string,
|
|
355
355
|
tableIdField: string,
|
|
356
356
|
id: any,
|
|
357
|
-
object: object
|
|
357
|
+
object: object,
|
|
358
358
|
): Promise<object[]>;
|
|
359
359
|
|
|
360
360
|
/**
|
|
@@ -367,19 +367,19 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
367
367
|
async deleteAsync<K extends keyof TFields>(
|
|
368
368
|
queryContext: EntityQueryContext,
|
|
369
369
|
idField: K,
|
|
370
|
-
id: any
|
|
370
|
+
id: any,
|
|
371
371
|
): Promise<void> {
|
|
372
372
|
const idColumn = getDatabaseFieldForEntityField(this.entityConfiguration, idField);
|
|
373
373
|
const numDeleted = await this.deleteInternalAsync(
|
|
374
374
|
queryContext.getQueryInterface(),
|
|
375
375
|
this.entityConfiguration.tableName,
|
|
376
376
|
idColumn,
|
|
377
|
-
id
|
|
377
|
+
id,
|
|
378
378
|
);
|
|
379
379
|
|
|
380
380
|
if (numDeleted > 1) {
|
|
381
381
|
throw new Error(
|
|
382
|
-
`Excessive deletions from database adapter delete: ${this.entityConfiguration.tableName}(id = ${id})
|
|
382
|
+
`Excessive deletions from database adapter delete: ${this.entityConfiguration.tableName}(id = ${id})`,
|
|
383
383
|
);
|
|
384
384
|
}
|
|
385
385
|
}
|
|
@@ -388,11 +388,11 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
388
388
|
queryInterface: any,
|
|
389
389
|
tableName: string,
|
|
390
390
|
tableIdField: string,
|
|
391
|
-
id: any
|
|
391
|
+
id: any,
|
|
392
392
|
): Promise<number>;
|
|
393
393
|
|
|
394
394
|
private convertToTableQueryModifiersWithOrderByRaw(
|
|
395
|
-
querySelectionModifiers: QuerySelectionModifiersWithOrderByRaw<TFields
|
|
395
|
+
querySelectionModifiers: QuerySelectionModifiersWithOrderByRaw<TFields>,
|
|
396
396
|
): TableQuerySelectionModifiersWithOrderByRaw {
|
|
397
397
|
return {
|
|
398
398
|
...this.convertToTableQueryModifiers(querySelectionModifiers),
|
|
@@ -401,7 +401,7 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
401
401
|
}
|
|
402
402
|
|
|
403
403
|
private convertToTableQueryModifiers(
|
|
404
|
-
querySelectionModifiers: QuerySelectionModifiers<TFields
|
|
404
|
+
querySelectionModifiers: QuerySelectionModifiers<TFields>,
|
|
405
405
|
): TableQuerySelectionModifiers {
|
|
406
406
|
const orderBy = querySelectionModifiers.orderBy;
|
|
407
407
|
return {
|
|
@@ -410,7 +410,7 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
410
410
|
? orderBy.map((orderBySpecification) => ({
|
|
411
411
|
columnName: getDatabaseFieldForEntityField(
|
|
412
412
|
this.entityConfiguration,
|
|
413
|
-
orderBySpecification.fieldName
|
|
413
|
+
orderBySpecification.fieldName,
|
|
414
414
|
),
|
|
415
415
|
order: orderBySpecification.order,
|
|
416
416
|
}))
|
|
@@ -56,7 +56,7 @@ export interface EntityAssociationDefinition<
|
|
|
56
56
|
TAssociatedEntity,
|
|
57
57
|
TAssociatedSelectedFields
|
|
58
58
|
>,
|
|
59
|
-
TAssociatedSelectedFields extends keyof TAssociatedFields = keyof TAssociatedFields
|
|
59
|
+
TAssociatedSelectedFields extends keyof TAssociatedFields = keyof TAssociatedFields,
|
|
60
60
|
> {
|
|
61
61
|
/**
|
|
62
62
|
* Class of entity on the other end of this edge.
|
|
@@ -95,6 +95,28 @@ export interface EntityAssociationDefinition<
|
|
|
95
95
|
edgeDeletionBehavior: EntityEdgeDeletionBehavior;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Options for EntityFieldDefinition
|
|
100
|
+
*/
|
|
101
|
+
export interface EntityFieldDefinitionOptions {
|
|
102
|
+
/**
|
|
103
|
+
* Column name in the database.
|
|
104
|
+
*/
|
|
105
|
+
columnName: string;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Whether or not to cache loaded instances of the entity by this field. The column name is
|
|
109
|
+
* used to derive a cache key for the cache entry. If true, this column must be able uniquely
|
|
110
|
+
* identify the entity.
|
|
111
|
+
*/
|
|
112
|
+
cache?: boolean;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Defines the association behavior for an entity that this column references.
|
|
116
|
+
*/
|
|
117
|
+
association?: EntityAssociationDefinition<any, any, any, any, any, any>;
|
|
118
|
+
}
|
|
119
|
+
|
|
98
120
|
/**
|
|
99
121
|
* Definition for a field referencing a column in the underlying database. Specifies things like
|
|
100
122
|
* cache behavior and associations, and handles input validation.
|
|
@@ -105,24 +127,12 @@ export abstract class EntityFieldDefinition<T> {
|
|
|
105
127
|
readonly association: EntityAssociationDefinition<any, any, any, any, any, any> | undefined;
|
|
106
128
|
/**
|
|
107
129
|
*
|
|
108
|
-
* @param
|
|
109
|
-
* @param cache - Whether or not to cache loaded instances of the entity by this field. The column name is
|
|
110
|
-
* used to derive a cache key for the cache entry. If true, this column must be able uniquely
|
|
111
|
-
* identify the entity.
|
|
112
|
-
* @param association - Defines the association behavior for an entity that this column references.
|
|
130
|
+
* @param options - options for this field definition
|
|
113
131
|
*/
|
|
114
|
-
constructor({
|
|
115
|
-
columnName
|
|
116
|
-
cache = false
|
|
117
|
-
association
|
|
118
|
-
}: {
|
|
119
|
-
columnName: string;
|
|
120
|
-
cache?: boolean;
|
|
121
|
-
association?: EntityAssociationDefinition<any, any, any, any, any, any>;
|
|
122
|
-
}) {
|
|
123
|
-
this.columnName = columnName;
|
|
124
|
-
this.cache = cache;
|
|
125
|
-
this.association = association;
|
|
132
|
+
constructor(options: EntityFieldDefinitionOptions) {
|
|
133
|
+
this.columnName = options.columnName;
|
|
134
|
+
this.cache = options.cache ?? false;
|
|
135
|
+
this.association = options.association;
|
|
126
136
|
}
|
|
127
137
|
|
|
128
138
|
/**
|
package/src/EntityFields.ts
CHANGED
|
@@ -88,3 +88,18 @@ export class EnumField extends EntityFieldDefinition<string | number> {
|
|
|
88
88
|
return typeof value === 'number' || typeof value === 'string';
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* EntityFieldDefinition for a enum column with a strict typescript enum type.
|
|
94
|
+
*/
|
|
95
|
+
export class StrictEnumField<T extends object> extends EnumField {
|
|
96
|
+
private readonly enum: T;
|
|
97
|
+
constructor(options: ConstructorParameters<typeof EnumField>[0] & { enum: T }) {
|
|
98
|
+
super(options);
|
|
99
|
+
this.enum = options.enum;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
protected override validateInputValueInternal(value: string | number): boolean {
|
|
103
|
+
return super.validateInputValueInternal(value) && Object.values(this.enum).includes(value);
|
|
104
|
+
}
|
|
105
|
+
}
|