@expo/entity 0.16.0 → 0.20.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/EnforcingEntityLoader.js +2 -2
- package/build/EnforcingEntityLoader.js.map +1 -1
- package/build/Entity.js +8 -2
- package/build/Entity.js.map +1 -1
- package/build/EntityAssociationLoader.js +3 -3
- package/build/EntityAssociationLoader.js.map +1 -1
- package/build/EntityCompanion.d.ts +5 -0
- package/build/EntityCompanion.js +8 -1
- package/build/EntityCompanion.js.map +1 -1
- package/build/EntityCompanionProvider.d.ts +1 -1
- package/build/EntityCompanionProvider.js +5 -5
- package/build/EntityCompanionProvider.js.map +1 -1
- package/build/EntityConfiguration.d.ts +1 -1
- package/build/EntityConfiguration.js +3 -3
- package/build/EntityConfiguration.js.map +1 -1
- package/build/EntityDatabaseAdapter.d.ts +4 -4
- package/build/EntityDatabaseAdapter.js +13 -13
- package/build/EntityDatabaseAdapter.js.map +1 -1
- package/build/EntityFieldDefinition.d.ts +77 -0
- package/build/EntityFieldDefinition.js +53 -0
- package/build/EntityFieldDefinition.js.map +1 -0
- package/build/EntityFields.d.ts +5 -78
- package/build/EntityFields.js +19 -61
- package/build/EntityFields.js.map +1 -1
- package/build/EntityLoader.d.ts +3 -1
- package/build/EntityLoader.js +19 -15
- package/build/EntityLoader.js.map +1 -1
- package/build/EntityLoaderFactory.d.ts +3 -1
- package/build/EntityLoaderFactory.js +3 -2
- package/build/EntityLoaderFactory.js.map +1 -1
- package/build/EntityMutationInfo.d.ts +26 -0
- package/build/EntityMutationInfo.js +10 -0
- package/build/EntityMutationInfo.js.map +1 -0
- package/build/EntityMutationTriggerConfiguration.d.ts +4 -4
- package/build/EntityMutationValidator.d.ts +3 -3
- package/build/EntityMutationValidator.js.map +1 -1
- package/build/EntityMutator.d.ts +5 -16
- package/build/EntityMutator.js +62 -58
- package/build/EntityMutator.js.map +1 -1
- package/build/EntityPrivacyPolicy.d.ts +5 -4
- package/build/EntityPrivacyPolicy.js +60 -12
- package/build/EntityPrivacyPolicy.js.map +1 -1
- package/build/EntityQueryContext.d.ts +13 -0
- package/build/EntityQueryContext.js +18 -0
- package/build/EntityQueryContext.js.map +1 -1
- package/build/EntitySecondaryCacheLoader.js +2 -2
- package/build/EntitySecondaryCacheLoader.js.map +1 -1
- package/build/ReadonlyEntity.js +3 -4
- package/build/ReadonlyEntity.js.map +1 -1
- package/build/ViewerScopedEntityCompanion.d.ts +5 -0
- package/build/ViewerScopedEntityCompanion.js +6 -0
- package/build/ViewerScopedEntityCompanion.js.map +1 -1
- package/build/__tests__/EnforcingEntityLoader-test.js +82 -82
- package/build/__tests__/EnforcingEntityLoader-test.js.map +1 -1
- package/build/__tests__/Entity-test.js +6 -6
- package/build/__tests__/Entity-test.js.map +1 -1
- package/build/__tests__/EntityAssociationLoader-test.js +40 -40
- package/build/__tests__/EntityAssociationLoader-test.js.map +1 -1
- package/build/__tests__/EntityCommonUseCases-test.js +11 -11
- package/build/__tests__/EntityCommonUseCases-test.js.map +1 -1
- package/build/__tests__/EntityCompanion-test.js +3 -3
- package/build/__tests__/EntityCompanion-test.js.map +1 -1
- package/build/__tests__/EntityCompanionProvider-test.js +1 -1
- package/build/__tests__/EntityCompanionProvider-test.js.map +1 -1
- package/build/__tests__/EntityDatabaseAdapter-test.js +12 -12
- package/build/__tests__/EntityDatabaseAdapter-test.js.map +1 -1
- package/build/__tests__/EntityEdges-test.js +103 -6
- package/build/__tests__/EntityEdges-test.js.map +1 -1
- package/build/__tests__/EntityFields-test.js +18 -26
- package/build/__tests__/EntityFields-test.js.map +1 -1
- package/build/__tests__/EntityLoader-constructor-test.d.ts +22 -0
- package/build/__tests__/EntityLoader-constructor-test.js +111 -0
- package/build/__tests__/EntityLoader-constructor-test.js.map +1 -0
- package/build/__tests__/EntityLoader-test.js +81 -73
- package/build/__tests__/EntityLoader-test.js.map +1 -1
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.d.ts +1 -0
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js +81 -0
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js.map +1 -0
- package/build/__tests__/EntityMutator-test.js +138 -136
- package/build/__tests__/EntityMutator-test.js.map +1 -1
- package/build/__tests__/EntityPrivacyPolicy-test.js +143 -67
- package/build/__tests__/EntityPrivacyPolicy-test.js.map +1 -1
- package/build/__tests__/EntitySecondaryCacheLoader-test.js +15 -15
- package/build/__tests__/EntitySecondaryCacheLoader-test.js.map +1 -1
- package/build/__tests__/EntitySelfReferentialEdges-test.js +13 -12
- package/build/__tests__/EntitySelfReferentialEdges-test.js.map +1 -1
- package/build/__tests__/ReadonlyEntity-test.js +12 -12
- package/build/__tests__/ReadonlyEntity-test.js.map +1 -1
- package/build/__tests__/ViewerContext-test.js +2 -2
- package/build/__tests__/ViewerContext-test.js.map +1 -1
- package/build/__tests__/ViewerScopedEntityCompanion-test.js +2 -2
- package/build/__tests__/ViewerScopedEntityCompanion-test.js.map +1 -1
- package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js +2 -2
- package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js.map +1 -1
- package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js +5 -5
- package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js.map +1 -1
- package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js +5 -5
- package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js.map +1 -1
- package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js +5 -5
- package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js.map +1 -1
- package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js +2 -2
- package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js.map +1 -1
- package/build/__tests__/entityUtils-test.js +21 -21
- package/build/__tests__/entityUtils-test.js.map +1 -1
- package/build/index.d.ts +3 -0
- package/build/index.js +5 -1
- package/build/index.js.map +1 -1
- package/build/internal/EntityDataManager.js +8 -7
- package/build/internal/EntityDataManager.js.map +1 -1
- package/build/internal/EntityFieldTransformationUtils.js +2 -2
- package/build/internal/EntityFieldTransformationUtils.js.map +1 -1
- package/build/internal/ReadThroughEntityCache.js +4 -4
- package/build/internal/ReadThroughEntityCache.js.map +1 -1
- package/build/internal/__tests__/EntityDataManager-test.js +21 -21
- package/build/internal/__tests__/EntityDataManager-test.js.map +1 -1
- package/build/internal/__tests__/EntityFieldTransformationUtils-test.js +8 -8
- package/build/internal/__tests__/EntityFieldTransformationUtils-test.js.map +1 -1
- package/build/internal/__tests__/ReadThroughEntityCache-test.js +48 -48
- package/build/internal/__tests__/ReadThroughEntityCache-test.js.map +1 -1
- package/build/metrics/EntityMetricsUtils.js +1 -1
- package/build/metrics/EntityMetricsUtils.js.map +1 -1
- package/build/metrics/IEntityMetricsAdapter.d.ts +16 -0
- package/build/metrics/IEntityMetricsAdapter.js +6 -1
- package/build/metrics/IEntityMetricsAdapter.js.map +1 -1
- package/build/metrics/NoOpEntityMetricsAdapter.d.ts +2 -1
- package/build/metrics/NoOpEntityMetricsAdapter.js +1 -0
- package/build/metrics/NoOpEntityMetricsAdapter.js.map +1 -1
- package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js +4 -4
- package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js.map +1 -1
- package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js +4 -4
- package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js.map +1 -1
- package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js +4 -4
- package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js.map +1 -1
- package/build/testfixtures/DateIDTestEntity.js.map +1 -1
- package/build/testfixtures/SimpleTestEntity.js.map +1 -1
- package/build/testfixtures/TestEntity.d.ts +6 -6
- package/build/testfixtures/TestEntity.js +4 -4
- package/build/testfixtures/TestEntity.js.map +1 -1
- package/build/testfixtures/TestEntity2.d.ts +5 -5
- package/build/testfixtures/TestEntity2.js.map +1 -1
- package/build/testfixtures/TestEntityNumberKey.js +1 -1
- package/build/testfixtures/TestEntityNumberKey.js.map +1 -1
- package/build/utils/collections/__tests__/maps-test.js +13 -13
- package/build/utils/collections/__tests__/maps-test.js.map +1 -1
- package/build/utils/collections/maps.js +1 -1
- package/build/utils/collections/maps.js.map +1 -1
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +6 -6
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.js +1 -1
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.js.map +1 -1
- package/build/utils/testing/StubCacheAdapter.js +1 -1
- package/build/utils/testing/StubCacheAdapter.js.map +1 -1
- package/build/utils/testing/StubDatabaseAdapter.js +7 -7
- package/build/utils/testing/StubDatabaseAdapter.js.map +1 -1
- package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js +26 -26
- package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js.map +1 -1
- package/build/utils/testing/describeFieldTestCase.d.ts +2 -0
- package/build/utils/testing/describeFieldTestCase.js +18 -0
- package/build/utils/testing/describeFieldTestCase.js.map +1 -0
- package/package.json +2 -1
- package/src/Entity.ts +10 -2
- package/src/EntityAssociationLoader.ts +1 -1
- package/src/EntityCompanion.ts +10 -2
- package/src/EntityCompanionProvider.ts +5 -9
- package/src/EntityConfiguration.ts +1 -1
- package/src/EntityDatabaseAdapter.ts +10 -8
- package/src/EntityFieldDefinition.ts +124 -0
- package/src/EntityFields.ts +11 -126
- package/src/EntityLoader.ts +12 -4
- package/src/EntityLoaderFactory.ts +5 -2
- package/src/EntityMutationInfo.ts +47 -0
- package/src/EntityMutationTriggerConfiguration.ts +5 -5
- package/src/EntityMutationValidator.ts +10 -4
- package/src/EntityMutator.ts +98 -76
- package/src/EntityPrivacyPolicy.ts +77 -19
- package/src/EntityQueryContext.ts +20 -0
- package/src/ReadonlyEntity.ts +3 -2
- package/src/ViewerScopedEntityCompanion.ts +8 -0
- package/src/__tests__/Entity-test.ts +8 -8
- package/src/__tests__/EntityCommonUseCases-test.ts +4 -4
- package/src/__tests__/EntityEdges-test.ts +169 -14
- package/src/__tests__/EntityFields-test.ts +6 -23
- package/src/__tests__/EntityLoader-constructor-test.ts +177 -0
- package/src/__tests__/EntityLoader-test.ts +48 -20
- package/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts +105 -0
- package/src/__tests__/EntityMutator-test.ts +153 -146
- package/src/__tests__/EntityPrivacyPolicy-test.ts +215 -78
- package/src/__tests__/EntitySecondaryCacheLoader-test.ts +7 -9
- package/src/__tests__/EntitySelfReferentialEdges-test.ts +6 -5
- package/src/__tests__/ReadonlyEntity-test.ts +1 -1
- package/src/__tests__/ViewerContext-test.ts +7 -6
- package/src/__tests__/ViewerScopedEntityCompanion-test.ts +11 -10
- package/src/__tests__/ViewerScopedEntityMutatorFactory-test.ts +4 -3
- package/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts +6 -6
- package/src/__tests__/cases/TwoEntitySameTableOverlappingRows-test.ts +4 -4
- package/src/index.ts +3 -0
- package/src/internal/EntityDataManager.ts +2 -1
- package/src/internal/__tests__/EntityDataManager-test.ts +6 -6
- package/src/internal/__tests__/ReadThroughEntityCache-test.ts +15 -13
- package/src/metrics/EntityMetricsUtils.ts +56 -50
- package/src/metrics/IEntityMetricsAdapter.ts +23 -0
- package/src/metrics/NoOpEntityMetricsAdapter.ts +2 -0
- package/src/testfixtures/DateIDTestEntity.ts +4 -4
- package/src/testfixtures/SimpleTestEntity.ts +4 -4
- package/src/testfixtures/TestEntity.ts +8 -8
- package/src/testfixtures/TestEntity2.ts +4 -4
- package/src/testfixtures/TestEntityNumberKey.ts +6 -6
- package/src/utils/testing/StubDatabaseAdapter.ts +4 -4
- package/src/utils/testing/__tests__/StubDatabaseAdapter-test.ts +18 -18
- package/src/utils/testing/describeFieldTestCase.ts +21 -0
- package/CHANGELOG.md +0 -241
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo/entity",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "A privacy-first data model",
|
|
5
5
|
"files": [
|
|
6
6
|
"build",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"tsc": "tsc",
|
|
13
13
|
"clean": "rm -rf build coverage coverage-integration",
|
|
14
14
|
"lint": "eslint src",
|
|
15
|
+
"lint-fix": "eslint src --fix",
|
|
15
16
|
"test": "jest --rootDir . --config ../../resources/jest.config.js",
|
|
16
17
|
"integration": "../../resources/run-with-docker yarn integration-no-setup",
|
|
17
18
|
"integration-no-setup": "jest --config ../../resources/jest-integration.config.js --rootDir . --runInBand --passWithNoTests",
|
package/src/Entity.ts
CHANGED
|
@@ -243,12 +243,16 @@ export default abstract class Entity<
|
|
|
243
243
|
.getQueryContextProvider()
|
|
244
244
|
.getQueryContext()
|
|
245
245
|
): Promise<boolean> {
|
|
246
|
+
const companion = existingEntity
|
|
247
|
+
.getViewerContext()
|
|
248
|
+
.getViewerScopedEntityCompanionForClass(this);
|
|
246
249
|
const privacyPolicy = new (this.getCompanionDefinition().privacyPolicyClass)();
|
|
247
250
|
const evaluationResult = await asyncResult(
|
|
248
251
|
privacyPolicy.authorizeUpdateAsync(
|
|
249
252
|
existingEntity.getViewerContext(),
|
|
250
253
|
queryContext,
|
|
251
|
-
existingEntity
|
|
254
|
+
existingEntity,
|
|
255
|
+
companion.getMetricsAdapter()
|
|
252
256
|
)
|
|
253
257
|
);
|
|
254
258
|
return evaluationResult.ok;
|
|
@@ -292,12 +296,16 @@ export default abstract class Entity<
|
|
|
292
296
|
.getQueryContextProvider()
|
|
293
297
|
.getQueryContext()
|
|
294
298
|
): Promise<boolean> {
|
|
299
|
+
const companion = existingEntity
|
|
300
|
+
.getViewerContext()
|
|
301
|
+
.getViewerScopedEntityCompanionForClass(this);
|
|
295
302
|
const privacyPolicy = new (this.getCompanionDefinition().privacyPolicyClass)();
|
|
296
303
|
const evaluationResult = await asyncResult(
|
|
297
304
|
privacyPolicy.authorizeDeleteAsync(
|
|
298
305
|
existingEntity.getViewerContext(),
|
|
299
306
|
queryContext,
|
|
300
|
-
existingEntity
|
|
307
|
+
existingEntity,
|
|
308
|
+
companion.getMetricsAdapter()
|
|
301
309
|
)
|
|
302
310
|
);
|
|
303
311
|
return evaluationResult.ok;
|
|
@@ -71,7 +71,7 @@ export default class EntityAssociationLoader<
|
|
|
71
71
|
.getLoaderFactory()
|
|
72
72
|
.forLoad(queryContext);
|
|
73
73
|
|
|
74
|
-
return (await loader.loadByIDAsync(
|
|
74
|
+
return (await loader.loadByIDAsync(associatedEntityID as unknown as TAssociatedID)) as Result<
|
|
75
75
|
null extends TFields[TIdentifyingField] ? TAssociatedEntity | null : TAssociatedEntity
|
|
76
76
|
>;
|
|
77
77
|
}
|
package/src/EntityCompanion.ts
CHANGED
|
@@ -73,7 +73,7 @@ export default class EntityCompanion<
|
|
|
73
73
|
TEntity,
|
|
74
74
|
TSelectedFields
|
|
75
75
|
>,
|
|
76
|
-
metricsAdapter: IEntityMetricsAdapter
|
|
76
|
+
private readonly metricsAdapter: IEntityMetricsAdapter
|
|
77
77
|
) {
|
|
78
78
|
const privacyPolicy = new PrivacyPolicyClass();
|
|
79
79
|
this.entityLoaderFactory = new EntityLoaderFactory<
|
|
@@ -87,7 +87,8 @@ export default class EntityCompanion<
|
|
|
87
87
|
tableDataCoordinator.entityConfiguration,
|
|
88
88
|
entityClass,
|
|
89
89
|
privacyPolicy,
|
|
90
|
-
tableDataCoordinator.dataManager
|
|
90
|
+
tableDataCoordinator.dataManager,
|
|
91
|
+
metricsAdapter
|
|
91
92
|
);
|
|
92
93
|
this.entityMutatorFactory = new EntityMutatorFactory(
|
|
93
94
|
tableDataCoordinator.entityConfiguration,
|
|
@@ -129,4 +130,11 @@ export default class EntityCompanion<
|
|
|
129
130
|
getQueryContextProvider(): EntityQueryContextProvider {
|
|
130
131
|
return this.tableDataCoordinator.getQueryContextProvider();
|
|
131
132
|
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get the {@link IEntityMetricsAdapter} for this companion.
|
|
136
|
+
*/
|
|
137
|
+
getMetricsAdapter(): IEntityMetricsAdapter {
|
|
138
|
+
return this.metricsAdapter;
|
|
139
|
+
}
|
|
132
140
|
}
|
|
@@ -162,14 +162,10 @@ export class EntityCompanionDefinition<
|
|
|
162
162
|
* {@link EntityCompanion} for each type of {@link Entity}.
|
|
163
163
|
*/
|
|
164
164
|
export default class EntityCompanionProvider {
|
|
165
|
-
private readonly companionMap: Map<
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
private readonly tableDataCoordinatorMap: Map<
|
|
170
|
-
string,
|
|
171
|
-
EntityTableDataCoordinator<any>
|
|
172
|
-
> = new Map();
|
|
165
|
+
private readonly companionMap: Map<string, EntityCompanion<any, any, any, any, any, any>> =
|
|
166
|
+
new Map();
|
|
167
|
+
private readonly tableDataCoordinatorMap: Map<string, EntityTableDataCoordinator<any>> =
|
|
168
|
+
new Map();
|
|
173
169
|
|
|
174
170
|
/**
|
|
175
171
|
* Instantiate an Entity framework.
|
|
@@ -178,7 +174,7 @@ export default class EntityCompanionProvider {
|
|
|
178
174
|
* @param cacheAdapterFlavors - Cache adapter configurations for this instance
|
|
179
175
|
*/
|
|
180
176
|
constructor(
|
|
181
|
-
|
|
177
|
+
public readonly metricsAdapter: IEntityMetricsAdapter,
|
|
182
178
|
private databaseAdapterFlavors: ReadonlyMap<
|
|
183
179
|
DatabaseAdapterFlavor,
|
|
184
180
|
DatabaseAdapterFlavorDefinition
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IEntityClass } from './Entity';
|
|
2
2
|
import { DatabaseAdapterFlavor, CacheAdapterFlavor } from './EntityCompanionProvider';
|
|
3
|
-
import { EntityFieldDefinition } from './
|
|
3
|
+
import { EntityFieldDefinition } from './EntityFieldDefinition';
|
|
4
4
|
import { mapMap, invertMap, reduceMap } from './utils/collections/maps';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -69,12 +69,14 @@ export interface QuerySelectionModifiers<TFields> {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
export interface TableQuerySelectionModifiers {
|
|
72
|
-
orderBy
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
orderBy:
|
|
73
|
+
| {
|
|
74
|
+
columnName: string;
|
|
75
|
+
order: OrderByOrdering;
|
|
76
|
+
}[]
|
|
77
|
+
| undefined;
|
|
78
|
+
offset: number | undefined;
|
|
79
|
+
limit: number | undefined;
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
/**
|
|
@@ -263,7 +265,7 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
263
265
|
return transformDatabaseObjectToFields(
|
|
264
266
|
this.entityConfiguration,
|
|
265
267
|
this.fieldTransformerMap,
|
|
266
|
-
results[0]
|
|
268
|
+
results[0]!
|
|
267
269
|
);
|
|
268
270
|
}
|
|
269
271
|
|
|
@@ -315,7 +317,7 @@ export default abstract class EntityDatabaseAdapter<TFields> {
|
|
|
315
317
|
return transformDatabaseObjectToFields(
|
|
316
318
|
this.entityConfiguration,
|
|
317
319
|
this.fieldTransformerMap,
|
|
318
|
-
results[0]
|
|
320
|
+
results[0]!
|
|
319
321
|
);
|
|
320
322
|
}
|
|
321
323
|
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { IEntityClass } from './Entity';
|
|
2
|
+
import EntityPrivacyPolicy from './EntityPrivacyPolicy';
|
|
3
|
+
import ReadonlyEntity from './ReadonlyEntity';
|
|
4
|
+
import ViewerContext from './ViewerContext';
|
|
5
|
+
|
|
6
|
+
export enum EntityEdgeDeletionBehavior {
|
|
7
|
+
/**
|
|
8
|
+
* Default. Invalidate the cache for all entities that reference the entity
|
|
9
|
+
* being deleted through this field, and transitively run deletions on those entities.
|
|
10
|
+
* This is most useful when the database itself expresses foreign
|
|
11
|
+
* keys and cascading deletes or set nulls and the entity framework just needs to
|
|
12
|
+
* be kept consistent with the state of the database.
|
|
13
|
+
*/
|
|
14
|
+
CASCADE_DELETE_INVALIDATE_CACHE,
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Delete all entities that reference the entity being deleted through this field. This is very similar
|
|
18
|
+
* to SQL `ON DELETE CASCADE` but is done in the Entity framework instead of at the underlying level.
|
|
19
|
+
* This will also invalidate the cached referencing entities.
|
|
20
|
+
*/
|
|
21
|
+
CASCADE_DELETE,
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Set this field to null when the referenced entity is deleted. This is very similar
|
|
25
|
+
* to SQL `ON DELETE SET NULL` but is done in the Entity framework instead of at the underlying level.
|
|
26
|
+
* This will also invalidate the cached referencing entities.
|
|
27
|
+
*/
|
|
28
|
+
SET_NULL,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface EntityAssociationDefinition<
|
|
32
|
+
TViewerContext extends ViewerContext,
|
|
33
|
+
TAssociatedFields,
|
|
34
|
+
TAssociatedID extends NonNullable<TAssociatedFields[TAssociatedSelectedFields]>,
|
|
35
|
+
TAssociatedEntity extends ReadonlyEntity<
|
|
36
|
+
TAssociatedFields,
|
|
37
|
+
TAssociatedID,
|
|
38
|
+
TViewerContext,
|
|
39
|
+
TAssociatedSelectedFields
|
|
40
|
+
>,
|
|
41
|
+
TAssociatedPrivacyPolicy extends EntityPrivacyPolicy<
|
|
42
|
+
TAssociatedFields,
|
|
43
|
+
TAssociatedID,
|
|
44
|
+
TViewerContext,
|
|
45
|
+
TAssociatedEntity,
|
|
46
|
+
TAssociatedSelectedFields
|
|
47
|
+
>,
|
|
48
|
+
TAssociatedSelectedFields extends keyof TAssociatedFields = keyof TAssociatedFields
|
|
49
|
+
> {
|
|
50
|
+
/**
|
|
51
|
+
* Class of entity on the other end of this edge.
|
|
52
|
+
*/
|
|
53
|
+
getAssociatedEntityClass: () => IEntityClass<
|
|
54
|
+
TAssociatedFields,
|
|
55
|
+
TAssociatedID,
|
|
56
|
+
TViewerContext,
|
|
57
|
+
TAssociatedEntity,
|
|
58
|
+
TAssociatedPrivacyPolicy,
|
|
59
|
+
TAssociatedSelectedFields
|
|
60
|
+
>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Field by which to load the instance of associatedEntityClass. If not provided, the
|
|
64
|
+
* associatedEntityClass instance is fetched by its ID.
|
|
65
|
+
*/
|
|
66
|
+
associatedEntityLookupByField?: keyof TAssociatedFields;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* What action to perform on the current entity when the entity on the referencing end of
|
|
70
|
+
* this edge is deleted.
|
|
71
|
+
*
|
|
72
|
+
* @remarks
|
|
73
|
+
* The entity framework doesn't prescribe a one-size-fits-all solution for referential
|
|
74
|
+
* integrity; instead it exposes mechanisms that supports both database foreign key constraints
|
|
75
|
+
* and implicit entity-specified foreign keys. Choosing which approach to use often depends on
|
|
76
|
+
* application requirements, and sometimes even a mix-and-match is the right choice.
|
|
77
|
+
*
|
|
78
|
+
* - If referential integrity is critical to your application, database foreign key constraints
|
|
79
|
+
* combined with {@link EntityEdgeDeletionBehavior.CASACDE_DELETE_INVALIDATE_CACHE} are recommended.
|
|
80
|
+
* - If the database being used doesn't support foreign keys, then using the entity framework for referential
|
|
81
|
+
* integrity is recommended.
|
|
82
|
+
*/
|
|
83
|
+
edgeDeletionBehavior?: EntityEdgeDeletionBehavior;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export abstract class EntityFieldDefinition<T> {
|
|
87
|
+
readonly columnName: string;
|
|
88
|
+
readonly cache: boolean;
|
|
89
|
+
readonly association: EntityAssociationDefinition<any, any, any, any, any, any> | undefined;
|
|
90
|
+
/**
|
|
91
|
+
*
|
|
92
|
+
* @param columnName - Column name in the database.
|
|
93
|
+
* @param cache - Whether or not to cache loaded instances of the entity by this field. The column name is
|
|
94
|
+
* used to derive a cache key for the cache entry. If true, this column must be able uniquely
|
|
95
|
+
* identify the entity.
|
|
96
|
+
*/
|
|
97
|
+
constructor({
|
|
98
|
+
columnName,
|
|
99
|
+
cache = false,
|
|
100
|
+
association,
|
|
101
|
+
}: {
|
|
102
|
+
columnName: string;
|
|
103
|
+
cache?: boolean;
|
|
104
|
+
association?: EntityAssociationDefinition<any, any, any, any, any, any>;
|
|
105
|
+
}) {
|
|
106
|
+
this.columnName = columnName;
|
|
107
|
+
this.cache = cache;
|
|
108
|
+
this.association = association;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Validates input value for a field of this type. Null and undefined are considered valid by default. This is used for things like:
|
|
113
|
+
* - EntityLoader.loadByFieldValue - to ensure the value being loaded by is a valid value
|
|
114
|
+
* - EntityMutator.setField - to ensure the value being set is a valid value
|
|
115
|
+
*/
|
|
116
|
+
public validateInputValue(value: T | null | undefined): boolean {
|
|
117
|
+
if (value === null || value === undefined) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return this.validateInputValueInternal(value);
|
|
122
|
+
}
|
|
123
|
+
protected abstract validateInputValueInternal(value: T): boolean;
|
|
124
|
+
}
|
package/src/EntityFields.ts
CHANGED
|
@@ -1,129 +1,6 @@
|
|
|
1
1
|
import { validate as validateUUID } from 'uuid';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import EntityPrivacyPolicy from './EntityPrivacyPolicy';
|
|
5
|
-
import ReadonlyEntity from './ReadonlyEntity';
|
|
6
|
-
import ViewerContext from './ViewerContext';
|
|
7
|
-
|
|
8
|
-
export enum EntityEdgeDeletionBehavior {
|
|
9
|
-
/**
|
|
10
|
-
* Default. Invalidate the cache for all entities that reference the entity
|
|
11
|
-
* being deleted through this field, and transitively run deletions on those entities.
|
|
12
|
-
* This is most useful when the database itself expresses foreign
|
|
13
|
-
* keys and cascading deletes or set nulls and the entity framework just needs to
|
|
14
|
-
* be kept consistent with the state of the database.
|
|
15
|
-
*/
|
|
16
|
-
CASCADE_DELETE_INVALIDATE_CACHE,
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Delete all entities that reference the entity being deleted through this field. This is very similar
|
|
20
|
-
* to SQL `ON DELETE CASCADE` but is done in the Entity framework instead of at the underlying level.
|
|
21
|
-
* This will also invalidate the cached referencing entities.
|
|
22
|
-
*/
|
|
23
|
-
CASCADE_DELETE,
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Set this field to null when the referenced entity is deleted. This is very similar
|
|
27
|
-
* to SQL `ON DELETE SET NULL` but is done in the Entity framework instead of at the underlying level.
|
|
28
|
-
* This will also invalidate the cached referencing entities.
|
|
29
|
-
*/
|
|
30
|
-
SET_NULL,
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface EntityAssociationDefinition<
|
|
34
|
-
TViewerContext extends ViewerContext,
|
|
35
|
-
TAssociatedFields,
|
|
36
|
-
TAssociatedID extends NonNullable<TAssociatedFields[TAssociatedSelectedFields]>,
|
|
37
|
-
TAssociatedEntity extends ReadonlyEntity<
|
|
38
|
-
TAssociatedFields,
|
|
39
|
-
TAssociatedID,
|
|
40
|
-
TViewerContext,
|
|
41
|
-
TAssociatedSelectedFields
|
|
42
|
-
>,
|
|
43
|
-
TAssociatedPrivacyPolicy extends EntityPrivacyPolicy<
|
|
44
|
-
TAssociatedFields,
|
|
45
|
-
TAssociatedID,
|
|
46
|
-
TViewerContext,
|
|
47
|
-
TAssociatedEntity,
|
|
48
|
-
TAssociatedSelectedFields
|
|
49
|
-
>,
|
|
50
|
-
TAssociatedSelectedFields extends keyof TAssociatedFields = keyof TAssociatedFields
|
|
51
|
-
> {
|
|
52
|
-
/**
|
|
53
|
-
* Class of entity on the other end of this edge.
|
|
54
|
-
*/
|
|
55
|
-
getAssociatedEntityClass: () => IEntityClass<
|
|
56
|
-
TAssociatedFields,
|
|
57
|
-
TAssociatedID,
|
|
58
|
-
TViewerContext,
|
|
59
|
-
TAssociatedEntity,
|
|
60
|
-
TAssociatedPrivacyPolicy,
|
|
61
|
-
TAssociatedSelectedFields
|
|
62
|
-
>;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Field by which to load the instance of associatedEntityClass. If not provided, the
|
|
66
|
-
* associatedEntityClass instance is fetched by its ID.
|
|
67
|
-
*/
|
|
68
|
-
associatedEntityLookupByField?: keyof TAssociatedFields;
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* What action to perform on the current entity when the entity on the referencing end of
|
|
72
|
-
* this edge is deleted.
|
|
73
|
-
*
|
|
74
|
-
* @remarks
|
|
75
|
-
* The entity framework doesn't prescribe a one-size-fits-all solution for referential
|
|
76
|
-
* integrity; instead it exposes mechanisms that supports both database foreign key constraints
|
|
77
|
-
* and implicit entity-specified foreign keys. Choosing which approach to use often depends on
|
|
78
|
-
* application requirements, and sometimes even a mix-and-match is the right choice.
|
|
79
|
-
*
|
|
80
|
-
* - If referential integrity is critical to your application, database foreign key constraints
|
|
81
|
-
* combined with {@link EntityEdgeDeletionBehavior.CASACDE_DELETE_INVALIDATE_CACHE} are recommended.
|
|
82
|
-
* - If the database being used doesn't support foreign keys, then using the entity framework for referential
|
|
83
|
-
* integrity is recommended.
|
|
84
|
-
*/
|
|
85
|
-
edgeDeletionBehavior?: EntityEdgeDeletionBehavior;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export abstract class EntityFieldDefinition<T> {
|
|
89
|
-
readonly columnName: string;
|
|
90
|
-
readonly cache: boolean;
|
|
91
|
-
readonly association?: EntityAssociationDefinition<any, any, any, any, any, any>;
|
|
92
|
-
/**
|
|
93
|
-
*
|
|
94
|
-
* @param columnName - Column name in the database.
|
|
95
|
-
* @param cache - Whether or not to cache loaded instances of the entity by this field. The column name is
|
|
96
|
-
* used to derive a cache key for the cache entry. If true, this column must be able uniquely
|
|
97
|
-
* identify the entity.
|
|
98
|
-
*/
|
|
99
|
-
constructor({
|
|
100
|
-
columnName,
|
|
101
|
-
cache = false,
|
|
102
|
-
association,
|
|
103
|
-
}: {
|
|
104
|
-
columnName: string;
|
|
105
|
-
cache?: boolean;
|
|
106
|
-
association?: EntityAssociationDefinition<any, any, any, any, any, any>;
|
|
107
|
-
}) {
|
|
108
|
-
this.columnName = columnName;
|
|
109
|
-
this.cache = cache;
|
|
110
|
-
this.association = association;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Validates input value for a field of this type. Null and undefined are considered valid by default. This is used for things like:
|
|
115
|
-
* - EntityLoader.loadByFieldValue - to ensure the value being loaded by is a valid value
|
|
116
|
-
* - EntityMutator.setField - to ensure the value being set is a valid value
|
|
117
|
-
*/
|
|
118
|
-
public validateInputValue(value: T | null | undefined): boolean {
|
|
119
|
-
if (value === null || value === undefined) {
|
|
120
|
-
return true;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return this.validateInputValueInternal(value);
|
|
124
|
-
}
|
|
125
|
-
protected abstract validateInputValueInternal(value: T): boolean;
|
|
126
|
-
}
|
|
3
|
+
import { EntityFieldDefinition } from './EntityFieldDefinition';
|
|
127
4
|
|
|
128
5
|
export class StringField extends EntityFieldDefinition<string> {
|
|
129
6
|
protected validateInputValueInternal(value: string): boolean {
|
|
@@ -131,7 +8,7 @@ export class StringField extends EntityFieldDefinition<string> {
|
|
|
131
8
|
}
|
|
132
9
|
}
|
|
133
10
|
export class UUIDField extends StringField {
|
|
134
|
-
protected validateInputValueInternal(value: string): boolean {
|
|
11
|
+
protected override validateInputValueInternal(value: string): boolean {
|
|
135
12
|
return validateUUID(value);
|
|
136
13
|
}
|
|
137
14
|
}
|
|
@@ -145,11 +22,19 @@ export class BooleanField extends EntityFieldDefinition<boolean> {
|
|
|
145
22
|
return typeof value === 'boolean';
|
|
146
23
|
}
|
|
147
24
|
}
|
|
148
|
-
|
|
25
|
+
|
|
26
|
+
export class IntField extends EntityFieldDefinition<number> {
|
|
27
|
+
protected validateInputValueInternal(value: number): boolean {
|
|
28
|
+
return typeof value === 'number' && Number.isInteger(value);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class FloatField extends EntityFieldDefinition<number> {
|
|
149
33
|
protected validateInputValueInternal(value: number): boolean {
|
|
150
34
|
return typeof value === 'number';
|
|
151
35
|
}
|
|
152
36
|
}
|
|
37
|
+
|
|
153
38
|
export class StringArrayField extends EntityFieldDefinition<string[]> {
|
|
154
39
|
protected validateInputValueInternal(value: string[]): boolean {
|
|
155
40
|
return Array.isArray(value) && value.every((subValue) => typeof subValue === 'string');
|
package/src/EntityLoader.ts
CHANGED
|
@@ -16,6 +16,7 @@ import ViewerContext from './ViewerContext';
|
|
|
16
16
|
import EntityInvalidFieldValueError from './errors/EntityInvalidFieldValueError';
|
|
17
17
|
import EntityNotFoundError from './errors/EntityNotFoundError';
|
|
18
18
|
import EntityDataManager from './internal/EntityDataManager';
|
|
19
|
+
import IEntityMetricsAdapter from './metrics/IEntityMetricsAdapter';
|
|
19
20
|
import { mapMap, mapMapAsync } from './utils/collections/maps';
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -49,7 +50,8 @@ export default class EntityLoader<
|
|
|
49
50
|
TSelectedFields
|
|
50
51
|
>,
|
|
51
52
|
private readonly privacyPolicy: TPrivacyPolicy,
|
|
52
|
-
private readonly dataManager: EntityDataManager<TFields
|
|
53
|
+
private readonly dataManager: EntityDataManager<TFields>,
|
|
54
|
+
protected readonly metricsAdapter: IEntityMetricsAdapter
|
|
53
55
|
) {}
|
|
54
56
|
|
|
55
57
|
/**
|
|
@@ -216,7 +218,8 @@ export default class EntityLoader<
|
|
|
216
218
|
this.privacyPolicy.authorizeReadAsync(
|
|
217
219
|
this.viewerContext,
|
|
218
220
|
this.queryContext,
|
|
219
|
-
uncheckedEntityResult.value
|
|
221
|
+
uncheckedEntityResult.value,
|
|
222
|
+
this.metricsAdapter
|
|
220
223
|
)
|
|
221
224
|
);
|
|
222
225
|
})
|
|
@@ -269,7 +272,8 @@ export default class EntityLoader<
|
|
|
269
272
|
this.privacyPolicy.authorizeReadAsync(
|
|
270
273
|
this.viewerContext,
|
|
271
274
|
this.queryContext,
|
|
272
|
-
uncheckedEntityResult.value
|
|
275
|
+
uncheckedEntityResult.value,
|
|
276
|
+
this.metricsAdapter
|
|
273
277
|
)
|
|
274
278
|
);
|
|
275
279
|
})
|
|
@@ -298,6 +302,9 @@ export default class EntityLoader<
|
|
|
298
302
|
try {
|
|
299
303
|
return result(new this.entityClass(this.viewerContext, fieldsObject));
|
|
300
304
|
} catch (e) {
|
|
305
|
+
if (!(e instanceof Error)) {
|
|
306
|
+
throw e;
|
|
307
|
+
}
|
|
301
308
|
return result(e);
|
|
302
309
|
}
|
|
303
310
|
});
|
|
@@ -325,7 +332,8 @@ export default class EntityLoader<
|
|
|
325
332
|
this.privacyPolicy.authorizeReadAsync(
|
|
326
333
|
this.viewerContext,
|
|
327
334
|
this.queryContext,
|
|
328
|
-
uncheckedEntityResult.value
|
|
335
|
+
uncheckedEntityResult.value,
|
|
336
|
+
this.metricsAdapter
|
|
329
337
|
)
|
|
330
338
|
);
|
|
331
339
|
})
|
|
@@ -6,6 +6,7 @@ import { EntityQueryContext } from './EntityQueryContext';
|
|
|
6
6
|
import ReadonlyEntity from './ReadonlyEntity';
|
|
7
7
|
import ViewerContext from './ViewerContext';
|
|
8
8
|
import EntityDataManager from './internal/EntityDataManager';
|
|
9
|
+
import IEntityMetricsAdapter from './metrics/IEntityMetricsAdapter';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* The primary entry point for loading entities.
|
|
@@ -35,7 +36,8 @@ export default class EntityLoaderFactory<
|
|
|
35
36
|
TSelectedFields
|
|
36
37
|
>,
|
|
37
38
|
private readonly privacyPolicyClass: TPrivacyPolicy,
|
|
38
|
-
private readonly dataManager: EntityDataManager<TFields
|
|
39
|
+
private readonly dataManager: EntityDataManager<TFields>,
|
|
40
|
+
protected readonly metricsAdapter: IEntityMetricsAdapter
|
|
39
41
|
) {}
|
|
40
42
|
|
|
41
43
|
/**
|
|
@@ -53,7 +55,8 @@ export default class EntityLoaderFactory<
|
|
|
53
55
|
this.entityConfiguration,
|
|
54
56
|
this.entityClass,
|
|
55
57
|
this.privacyPolicyClass,
|
|
56
|
-
this.dataManager
|
|
58
|
+
this.dataManager,
|
|
59
|
+
this.metricsAdapter
|
|
57
60
|
);
|
|
58
61
|
}
|
|
59
62
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import Entity from './Entity';
|
|
2
|
+
import ViewerContext from './ViewerContext';
|
|
3
|
+
|
|
4
|
+
export enum EntityMutationType {
|
|
5
|
+
CREATE,
|
|
6
|
+
UPDATE,
|
|
7
|
+
DELETE,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type EntityValidatorMutationInfo<
|
|
11
|
+
TFields,
|
|
12
|
+
TID extends NonNullable<TFields[TSelectedFields]>,
|
|
13
|
+
TViewerContext extends ViewerContext,
|
|
14
|
+
TEntity extends Entity<TFields, TID, TViewerContext, TSelectedFields>,
|
|
15
|
+
TSelectedFields extends keyof TFields = keyof TFields
|
|
16
|
+
> =
|
|
17
|
+
| {
|
|
18
|
+
type: EntityMutationType.CREATE;
|
|
19
|
+
}
|
|
20
|
+
| {
|
|
21
|
+
type: EntityMutationType.UPDATE;
|
|
22
|
+
previousValue: TEntity;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type EntityMutationTriggerDeleteCascadeInfo<> = {
|
|
26
|
+
entity: Entity<any, any, any, any>;
|
|
27
|
+
cascadingDeleteCause: EntityMutationTriggerDeleteCascadeInfo | null;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type EntityTriggerMutationInfo<
|
|
31
|
+
TFields,
|
|
32
|
+
TID extends NonNullable<TFields[TSelectedFields]>,
|
|
33
|
+
TViewerContext extends ViewerContext,
|
|
34
|
+
TEntity extends Entity<TFields, TID, TViewerContext, TSelectedFields>,
|
|
35
|
+
TSelectedFields extends keyof TFields = keyof TFields
|
|
36
|
+
> =
|
|
37
|
+
| {
|
|
38
|
+
type: EntityMutationType.CREATE;
|
|
39
|
+
}
|
|
40
|
+
| {
|
|
41
|
+
type: EntityMutationType.UPDATE;
|
|
42
|
+
previousValue: TEntity;
|
|
43
|
+
}
|
|
44
|
+
| {
|
|
45
|
+
type: EntityMutationType.DELETE;
|
|
46
|
+
cascadingDeleteCause: EntityMutationTriggerDeleteCascadeInfo | null;
|
|
47
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { EntityTriggerMutationInfo } from './EntityMutationInfo';
|
|
2
|
+
import { EntityTransactionalQueryContext } from './EntityQueryContext';
|
|
3
3
|
import ReadonlyEntity from './ReadonlyEntity';
|
|
4
4
|
import ViewerContext from './ViewerContext';
|
|
5
5
|
|
|
@@ -78,9 +78,9 @@ export abstract class EntityMutationTrigger<
|
|
|
78
78
|
> {
|
|
79
79
|
abstract executeAsync(
|
|
80
80
|
viewerContext: TViewerContext,
|
|
81
|
-
queryContext:
|
|
81
|
+
queryContext: EntityTransactionalQueryContext,
|
|
82
82
|
entity: TEntity,
|
|
83
|
-
mutationInfo:
|
|
83
|
+
mutationInfo: EntityTriggerMutationInfo<TFields, TID, TViewerContext, TEntity, TSelectedFields>
|
|
84
84
|
): Promise<void>;
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -98,6 +98,6 @@ export abstract class EntityNonTransactionalMutationTrigger<
|
|
|
98
98
|
abstract executeAsync(
|
|
99
99
|
viewerContext: TViewerContext,
|
|
100
100
|
entity: TEntity,
|
|
101
|
-
mutationInfo:
|
|
101
|
+
mutationInfo: EntityTriggerMutationInfo<TFields, TID, TViewerContext, TEntity, TSelectedFields>
|
|
102
102
|
): Promise<void>;
|
|
103
103
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { EntityValidatorMutationInfo } from './EntityMutationInfo';
|
|
2
|
+
import { EntityTransactionalQueryContext } from './EntityQueryContext';
|
|
3
3
|
import ReadonlyEntity from './ReadonlyEntity';
|
|
4
4
|
import ViewerContext from './ViewerContext';
|
|
5
5
|
|
|
@@ -16,8 +16,14 @@ export default abstract class EntityMutationValidator<
|
|
|
16
16
|
> {
|
|
17
17
|
abstract executeAsync(
|
|
18
18
|
viewerContext: TViewerContext,
|
|
19
|
-
queryContext:
|
|
19
|
+
queryContext: EntityTransactionalQueryContext,
|
|
20
20
|
entity: TEntity,
|
|
21
|
-
mutationInfo:
|
|
21
|
+
mutationInfo: EntityValidatorMutationInfo<
|
|
22
|
+
TFields,
|
|
23
|
+
TID,
|
|
24
|
+
TViewerContext,
|
|
25
|
+
TEntity,
|
|
26
|
+
TSelectedFields
|
|
27
|
+
>
|
|
22
28
|
): Promise<void>;
|
|
23
29
|
}
|