@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
|
@@ -45,8 +45,8 @@ describe('Two entities backed by the same table', () => {
|
|
|
45
45
|
expect(successfulManyResults).toHaveLength(1);
|
|
46
46
|
expect(failedManyResults).toHaveLength(1);
|
|
47
47
|
|
|
48
|
-
expect(successfulManyResults[0]
|
|
49
|
-
expect(failedManyResults[0]
|
|
48
|
+
expect(successfulManyResults[0]!.enforceValue().getID()).toEqual(one.getID());
|
|
49
|
+
expect(failedManyResults[0]!.enforceError().message).toEqual(
|
|
50
50
|
'OneTestEntity must be instantiated with one data'
|
|
51
51
|
);
|
|
52
52
|
|
|
@@ -107,16 +107,16 @@ const testEntityConfiguration = new EntityConfiguration<TestFields>({
|
|
|
107
107
|
});
|
|
108
108
|
|
|
109
109
|
class TestEntityPrivacyPolicy extends EntityPrivacyPolicy<any, string, ViewerContext, any, any> {
|
|
110
|
-
protected readonly readRules = [
|
|
110
|
+
protected override readonly readRules = [
|
|
111
111
|
new AlwaysAllowPrivacyPolicyRule<any, string, ViewerContext, any, any>(),
|
|
112
112
|
];
|
|
113
|
-
protected readonly createRules = [
|
|
113
|
+
protected override readonly createRules = [
|
|
114
114
|
new AlwaysAllowPrivacyPolicyRule<any, string, ViewerContext, any, any>(),
|
|
115
115
|
];
|
|
116
|
-
protected readonly updateRules = [
|
|
116
|
+
protected override readonly updateRules = [
|
|
117
117
|
new AlwaysAllowPrivacyPolicyRule<any, string, ViewerContext, any, any>(),
|
|
118
118
|
];
|
|
119
|
-
protected readonly deleteRules = [
|
|
119
|
+
protected override readonly deleteRules = [
|
|
120
120
|
new AlwaysAllowPrivacyPolicyRule<any, string, ViewerContext, any, any>(),
|
|
121
121
|
];
|
|
122
122
|
}
|
|
@@ -115,16 +115,16 @@ const testEntityConfiguration = new EntityConfiguration<TestFields>({
|
|
|
115
115
|
});
|
|
116
116
|
|
|
117
117
|
class TestEntityPrivacyPolicy extends EntityPrivacyPolicy<any, string, ViewerContext, any, any> {
|
|
118
|
-
protected readonly readRules = [
|
|
118
|
+
protected override readonly readRules = [
|
|
119
119
|
new AlwaysAllowPrivacyPolicyRule<any, string, ViewerContext, any, any>(),
|
|
120
120
|
];
|
|
121
|
-
protected readonly createRules = [
|
|
121
|
+
protected override readonly createRules = [
|
|
122
122
|
new AlwaysAllowPrivacyPolicyRule<any, string, ViewerContext, any, any>(),
|
|
123
123
|
];
|
|
124
|
-
protected readonly updateRules = [
|
|
124
|
+
protected override readonly updateRules = [
|
|
125
125
|
new AlwaysAllowPrivacyPolicyRule<any, string, ViewerContext, any, any>(),
|
|
126
126
|
];
|
|
127
|
-
protected readonly deleteRules = [
|
|
127
|
+
protected override readonly deleteRules = [
|
|
128
128
|
new AlwaysAllowPrivacyPolicyRule<any, string, ViewerContext, any, any>(),
|
|
129
129
|
];
|
|
130
130
|
}
|
package/src/index.ts
CHANGED
|
@@ -26,12 +26,14 @@ export { default as EntityError } from './errors/EntityError';
|
|
|
26
26
|
export { default as EntityNotAuthorizedError } from './errors/EntityNotAuthorizedError';
|
|
27
27
|
export { default as EntityNotFoundError } from './errors/EntityNotFoundError';
|
|
28
28
|
export * from './EntityFields';
|
|
29
|
+
export * from './EntityFieldDefinition';
|
|
29
30
|
export { default as EntityLoader } from './EntityLoader';
|
|
30
31
|
export { default as EntityLoaderFactory } from './EntityLoaderFactory';
|
|
31
32
|
export { default as EntitySecondaryCacheLoader } from './EntitySecondaryCacheLoader';
|
|
32
33
|
export * from './EntitySecondaryCacheLoader';
|
|
33
34
|
export * from './EntityMutator';
|
|
34
35
|
export { default as EntityMutationValidator } from './EntityMutationValidator';
|
|
36
|
+
export * from './EntityMutationInfo';
|
|
35
37
|
export * from './EntityMutationTriggerConfiguration';
|
|
36
38
|
export { default as EntityMutationTriggerConfiguration } from './EntityMutationTriggerConfiguration';
|
|
37
39
|
export { default as EntityMutatorFactory } from './EntityMutatorFactory';
|
|
@@ -63,6 +65,7 @@ export { default as PrivacyPolicyRule } from './rules/PrivacyPolicyRule';
|
|
|
63
65
|
export * from './rules/PrivacyPolicyRule';
|
|
64
66
|
export * from './utils/testing/PrivacyPolicyRuleTestUtils';
|
|
65
67
|
export * from './utils/testing/StubCacheAdapter';
|
|
68
|
+
export { default as describeFieldTestCase } from './utils/testing/describeFieldTestCase';
|
|
66
69
|
export { default as StubDatabaseAdapter } from './utils/testing/StubDatabaseAdapter';
|
|
67
70
|
export { default as StubDatabaseAdapterProvider } from './utils/testing/StubDatabaseAdapterProvider';
|
|
68
71
|
export { default as StubQueryContextProvider } from './utils/testing/StubQueryContextProvider';
|
|
@@ -125,7 +125,8 @@ export default class EntityDataManager<TFields> {
|
|
|
125
125
|
const results = await dataLoader.loadMany(fieldValues);
|
|
126
126
|
const [values, errors] = partitionErrors(results);
|
|
127
127
|
if (errors.length > 0) {
|
|
128
|
-
|
|
128
|
+
const error = errors[0]!;
|
|
129
|
+
throw error;
|
|
129
130
|
}
|
|
130
131
|
|
|
131
132
|
return zipToMap(fieldValues, values);
|
|
@@ -34,7 +34,7 @@ const getObjects = (): Map<string, TestFields[]> =>
|
|
|
34
34
|
customIdField: '1',
|
|
35
35
|
testIndexedField: 'unique1',
|
|
36
36
|
stringField: 'hello',
|
|
37
|
-
|
|
37
|
+
intField: 1,
|
|
38
38
|
dateField: new Date(),
|
|
39
39
|
nullableField: null,
|
|
40
40
|
},
|
|
@@ -42,7 +42,7 @@ const getObjects = (): Map<string, TestFields[]> =>
|
|
|
42
42
|
customIdField: '2',
|
|
43
43
|
testIndexedField: 'unique2',
|
|
44
44
|
stringField: 'hello',
|
|
45
|
-
|
|
45
|
+
intField: 1,
|
|
46
46
|
dateField: new Date(),
|
|
47
47
|
nullableField: null,
|
|
48
48
|
},
|
|
@@ -50,7 +50,7 @@ const getObjects = (): Map<string, TestFields[]> =>
|
|
|
50
50
|
customIdField: '3',
|
|
51
51
|
testIndexedField: 'unique3',
|
|
52
52
|
stringField: 'world',
|
|
53
|
-
|
|
53
|
+
intField: 1,
|
|
54
54
|
dateField: new Date(),
|
|
55
55
|
nullableField: null,
|
|
56
56
|
},
|
|
@@ -298,7 +298,7 @@ describe(EntityDataManager, () => {
|
|
|
298
298
|
);
|
|
299
299
|
const queryContext = StubQueryContextProvider.getQueryContext();
|
|
300
300
|
|
|
301
|
-
const objectInQuestion = objects.get(testEntityConfiguration.tableName)![1]
|
|
301
|
+
const objectInQuestion = objects.get(testEntityConfiguration.tableName)![1]!;
|
|
302
302
|
|
|
303
303
|
const dbSpy = jest.spyOn(databaseAdapter, 'fetchManyWhereAsync');
|
|
304
304
|
const cacheSpy = jest.spyOn(entityCache, 'readManyThroughAsync');
|
|
@@ -337,7 +337,7 @@ describe(EntityDataManager, () => {
|
|
|
337
337
|
);
|
|
338
338
|
const queryContext = StubQueryContextProvider.getQueryContext();
|
|
339
339
|
|
|
340
|
-
const objectInQuestion = objects.get(testEntityConfiguration.tableName)![1]
|
|
340
|
+
const objectInQuestion = objects.get(testEntityConfiguration.tableName)![1]!;
|
|
341
341
|
|
|
342
342
|
const dbSpy = jest.spyOn(databaseAdapter, 'fetchManyWhereAsync');
|
|
343
343
|
const cacheSpy = jest.spyOn(entityCache, 'readManyThroughAsync');
|
|
@@ -425,7 +425,7 @@ describe(EntityDataManager, () => {
|
|
|
425
425
|
fieldValue: 'hello',
|
|
426
426
|
},
|
|
427
427
|
{
|
|
428
|
-
fieldName: '
|
|
428
|
+
fieldName: 'intField',
|
|
429
429
|
fieldValue: 1,
|
|
430
430
|
},
|
|
431
431
|
],
|
|
@@ -20,19 +20,21 @@ const makeEntityConfiguration = (cacheIdField: boolean): EntityConfiguration<Bla
|
|
|
20
20
|
cacheAdapterFlavor: 'redis',
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
const createIdFetcher =
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
};
|
|
23
|
+
const createIdFetcher =
|
|
24
|
+
(ids: string[]) =>
|
|
25
|
+
async <N extends keyof BlahFields>(
|
|
26
|
+
fetcherFieldValues: readonly NonNullable<BlahFields[N]>[]
|
|
27
|
+
): Promise<ReadonlyMap<NonNullable<BlahFields[N]>, readonly Readonly<BlahFields>[]>> => {
|
|
28
|
+
const results = new Map();
|
|
29
|
+
fetcherFieldValues.forEach((v) => {
|
|
30
|
+
if (ids.includes(v)) {
|
|
31
|
+
results.set(v, [{ id: v }]);
|
|
32
|
+
} else {
|
|
33
|
+
results.set(v, []);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return results;
|
|
37
|
+
};
|
|
36
38
|
|
|
37
39
|
describe(ReadThroughEntityCache, () => {
|
|
38
40
|
describe('readManyThroughAsync', () => {
|
|
@@ -4,62 +4,68 @@ import IEntityMetricsAdapter, {
|
|
|
4
4
|
EntityMetricsMutationType,
|
|
5
5
|
} from './IEntityMetricsAdapter';
|
|
6
6
|
|
|
7
|
-
export const timeAndLogLoadEventAsync =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
export const timeAndLogLoadEventAsync =
|
|
8
|
+
(
|
|
9
|
+
metricsAdapter: IEntityMetricsAdapter,
|
|
10
|
+
loadType: EntityMetricsLoadType,
|
|
11
|
+
entityClassName: string
|
|
12
|
+
) =>
|
|
13
|
+
async <TFields>(promise: Promise<readonly Readonly<TFields>[]>) => {
|
|
14
|
+
const startTime = Date.now();
|
|
15
|
+
const result = await promise;
|
|
16
|
+
const endTime = Date.now();
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
metricsAdapter.logDataManagerLoadEvent({
|
|
19
|
+
type: loadType,
|
|
20
|
+
entityClassName,
|
|
21
|
+
duration: endTime - startTime,
|
|
22
|
+
count: result.length,
|
|
23
|
+
});
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
};
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
25
27
|
|
|
26
|
-
export const timeAndLogLoadMapEventAsync =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
export const timeAndLogLoadMapEventAsync =
|
|
29
|
+
(
|
|
30
|
+
metricsAdapter: IEntityMetricsAdapter,
|
|
31
|
+
loadType: EntityMetricsLoadType,
|
|
32
|
+
entityClassName: string
|
|
33
|
+
) =>
|
|
34
|
+
async <TFields, N extends keyof TFields>(
|
|
35
|
+
promise: Promise<ReadonlyMap<NonNullable<TFields[N]>, readonly Readonly<TFields>[]>>
|
|
36
|
+
) => {
|
|
37
|
+
const startTime = Date.now();
|
|
38
|
+
const result = await promise;
|
|
39
|
+
const endTime = Date.now();
|
|
36
40
|
|
|
37
|
-
|
|
41
|
+
const count = reduceMap(result, (acc, v) => acc + v.length, 0);
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
metricsAdapter.logDataManagerLoadEvent({
|
|
44
|
+
type: loadType,
|
|
45
|
+
entityClassName,
|
|
46
|
+
duration: endTime - startTime,
|
|
47
|
+
count,
|
|
48
|
+
});
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
};
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
48
52
|
|
|
49
|
-
export const timeAndLogMutationEventAsync =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
export const timeAndLogMutationEventAsync =
|
|
54
|
+
(
|
|
55
|
+
metricsAdapter: IEntityMetricsAdapter,
|
|
56
|
+
mutationType: EntityMetricsMutationType,
|
|
57
|
+
entityClassName: string
|
|
58
|
+
) =>
|
|
59
|
+
async <T>(promise: Promise<T>) => {
|
|
60
|
+
const startTime = Date.now();
|
|
61
|
+
const result = await promise;
|
|
62
|
+
const endTime = Date.now();
|
|
57
63
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
metricsAdapter.logMutatorMutationEvent({
|
|
65
|
+
type: mutationType,
|
|
66
|
+
entityClassName,
|
|
67
|
+
duration: endTime - startTime,
|
|
68
|
+
});
|
|
63
69
|
|
|
64
|
-
|
|
65
|
-
};
|
|
70
|
+
return result;
|
|
71
|
+
};
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EntityAuthorizationAction,
|
|
3
|
+
EntityPrivacyPolicyEvaluationMode,
|
|
4
|
+
} from '../EntityPrivacyPolicy';
|
|
5
|
+
|
|
1
6
|
export enum EntityMetricsLoadType {
|
|
2
7
|
LOAD_MANY,
|
|
3
8
|
LOAD_MANY_EQUALITY_CONJUNCTION,
|
|
@@ -28,11 +33,29 @@ export interface IncrementLoadCountEvent {
|
|
|
28
33
|
entityClassName: string;
|
|
29
34
|
}
|
|
30
35
|
|
|
36
|
+
export enum EntityMetricsAuthorizationResult {
|
|
37
|
+
DENY,
|
|
38
|
+
ALLOW,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface EntityMetricsAuthorizationEvent {
|
|
42
|
+
entityClassName: string;
|
|
43
|
+
action: EntityAuthorizationAction;
|
|
44
|
+
evaluationResult: EntityMetricsAuthorizationResult;
|
|
45
|
+
privacyPolicyEvaluationMode: EntityPrivacyPolicyEvaluationMode;
|
|
46
|
+
}
|
|
47
|
+
|
|
31
48
|
/**
|
|
32
49
|
* An interface for gathering metrics about the Entity framework. Information about
|
|
33
50
|
* entity load and mutation operations is piped to an instance of this adapter.
|
|
34
51
|
*/
|
|
35
52
|
export default interface IEntityMetricsAdapter {
|
|
53
|
+
/**
|
|
54
|
+
* Called when a {@link EntityPrivacyPolicy} authorization succeeds or fails.
|
|
55
|
+
* @param authorizationEvent - info about the authorization event
|
|
56
|
+
*/
|
|
57
|
+
logAuthorizationEvent(authorizationEvent: EntityMetricsAuthorizationEvent): void;
|
|
58
|
+
|
|
36
59
|
/**
|
|
37
60
|
* Called when any load occurs.
|
|
38
61
|
* @param loadEvent - info about the load event
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import IEntityMetricsAdapter, {
|
|
2
|
+
EntityMetricsAuthorizationEvent,
|
|
2
3
|
EntityMetricsLoadEvent,
|
|
3
4
|
EntityMetricsMutationEvent,
|
|
4
5
|
IncrementLoadCountEvent,
|
|
5
6
|
} from './IEntityMetricsAdapter';
|
|
6
7
|
|
|
7
8
|
export default class NoOpEntityMetricsAdapter implements IEntityMetricsAdapter {
|
|
9
|
+
logAuthorizationEvent(_authorizationEvent: EntityMetricsAuthorizationEvent): void {}
|
|
8
10
|
logDataManagerLoadEvent(_loadEvent: EntityMetricsLoadEvent): void {}
|
|
9
11
|
logMutatorMutationEvent(_mutationEvent: EntityMetricsMutationEvent): void {}
|
|
10
12
|
incrementDataManagerDataloaderLoadCount(
|
|
@@ -28,16 +28,16 @@ export class DateIDTestEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
28
28
|
ViewerContext,
|
|
29
29
|
DateIDTestEntity
|
|
30
30
|
> {
|
|
31
|
-
protected readonly readRules = [
|
|
31
|
+
protected override readonly readRules = [
|
|
32
32
|
new AlwaysAllowPrivacyPolicyRule<DateIDTestFields, Date, ViewerContext, DateIDTestEntity>(),
|
|
33
33
|
];
|
|
34
|
-
protected readonly createRules = [
|
|
34
|
+
protected override readonly createRules = [
|
|
35
35
|
new AlwaysAllowPrivacyPolicyRule<DateIDTestFields, Date, ViewerContext, DateIDTestEntity>(),
|
|
36
36
|
];
|
|
37
|
-
protected readonly updateRules = [
|
|
37
|
+
protected override readonly updateRules = [
|
|
38
38
|
new AlwaysAllowPrivacyPolicyRule<DateIDTestFields, Date, ViewerContext, DateIDTestEntity>(),
|
|
39
39
|
];
|
|
40
|
-
protected readonly deleteRules = [
|
|
40
|
+
protected override readonly deleteRules = [
|
|
41
41
|
new AlwaysAllowPrivacyPolicyRule<DateIDTestFields, Date, ViewerContext, DateIDTestEntity>(),
|
|
42
42
|
];
|
|
43
43
|
}
|
|
@@ -31,7 +31,7 @@ export class SimpleTestEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
31
31
|
SimpleTestEntity,
|
|
32
32
|
SimpleTestFieldSelection
|
|
33
33
|
> {
|
|
34
|
-
protected readonly readRules = [
|
|
34
|
+
protected override readonly readRules = [
|
|
35
35
|
new AlwaysAllowPrivacyPolicyRule<
|
|
36
36
|
SimpleTestFields,
|
|
37
37
|
string,
|
|
@@ -40,7 +40,7 @@ export class SimpleTestEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
40
40
|
SimpleTestFieldSelection
|
|
41
41
|
>(),
|
|
42
42
|
];
|
|
43
|
-
protected readonly createRules = [
|
|
43
|
+
protected override readonly createRules = [
|
|
44
44
|
new AlwaysAllowPrivacyPolicyRule<
|
|
45
45
|
SimpleTestFields,
|
|
46
46
|
string,
|
|
@@ -49,7 +49,7 @@ export class SimpleTestEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
49
49
|
SimpleTestFieldSelection
|
|
50
50
|
>(),
|
|
51
51
|
];
|
|
52
|
-
protected readonly updateRules = [
|
|
52
|
+
protected override readonly updateRules = [
|
|
53
53
|
new AlwaysAllowPrivacyPolicyRule<
|
|
54
54
|
SimpleTestFields,
|
|
55
55
|
string,
|
|
@@ -58,7 +58,7 @@ export class SimpleTestEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
58
58
|
SimpleTestFieldSelection
|
|
59
59
|
>(),
|
|
60
60
|
];
|
|
61
|
-
protected readonly deleteRules = [
|
|
61
|
+
protected override readonly deleteRules = [
|
|
62
62
|
new AlwaysAllowPrivacyPolicyRule<
|
|
63
63
|
SimpleTestFields,
|
|
64
64
|
string,
|
|
@@ -3,7 +3,7 @@ import { result, Result } from '@expo/results';
|
|
|
3
3
|
import Entity from '../Entity';
|
|
4
4
|
import { EntityCompanionDefinition } from '../EntityCompanionProvider';
|
|
5
5
|
import EntityConfiguration from '../EntityConfiguration';
|
|
6
|
-
import { UUIDField, StringField, DateField,
|
|
6
|
+
import { UUIDField, StringField, DateField, IntField } from '../EntityFields';
|
|
7
7
|
import EntityPrivacyPolicy from '../EntityPrivacyPolicy';
|
|
8
8
|
import ViewerContext from '../ViewerContext';
|
|
9
9
|
import AlwaysAllowPrivacyPolicyRule from '../rules/AlwaysAllowPrivacyPolicyRule';
|
|
@@ -12,7 +12,7 @@ export type TestFields = {
|
|
|
12
12
|
customIdField: string;
|
|
13
13
|
testIndexedField: string;
|
|
14
14
|
stringField: string;
|
|
15
|
-
|
|
15
|
+
intField: number;
|
|
16
16
|
dateField: Date;
|
|
17
17
|
nullableField: string | null;
|
|
18
18
|
};
|
|
@@ -31,7 +31,7 @@ export const testEntityConfiguration = new EntityConfiguration<TestFields>({
|
|
|
31
31
|
stringField: new StringField({
|
|
32
32
|
columnName: 'string_field',
|
|
33
33
|
}),
|
|
34
|
-
|
|
34
|
+
intField: new IntField({
|
|
35
35
|
columnName: 'number_field',
|
|
36
36
|
}),
|
|
37
37
|
dateField: new DateField({
|
|
@@ -51,16 +51,16 @@ export class TestEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
51
51
|
ViewerContext,
|
|
52
52
|
TestEntity
|
|
53
53
|
> {
|
|
54
|
-
protected readonly readRules = [
|
|
54
|
+
protected override readonly readRules = [
|
|
55
55
|
new AlwaysAllowPrivacyPolicyRule<TestFields, string, ViewerContext, TestEntity>(),
|
|
56
56
|
];
|
|
57
|
-
protected readonly createRules = [
|
|
57
|
+
protected override readonly createRules = [
|
|
58
58
|
new AlwaysAllowPrivacyPolicyRule<TestFields, string, ViewerContext, TestEntity>(),
|
|
59
59
|
];
|
|
60
|
-
protected readonly updateRules = [
|
|
60
|
+
protected override readonly updateRules = [
|
|
61
61
|
new AlwaysAllowPrivacyPolicyRule<TestFields, string, ViewerContext, TestEntity>(),
|
|
62
62
|
];
|
|
63
|
-
protected readonly deleteRules = [
|
|
63
|
+
protected override readonly deleteRules = [
|
|
64
64
|
new AlwaysAllowPrivacyPolicyRule<TestFields, string, ViewerContext, TestEntity>(),
|
|
65
65
|
];
|
|
66
66
|
}
|
|
@@ -86,7 +86,7 @@ export default class TestEntity extends Entity<TestFields, string, ViewerContext
|
|
|
86
86
|
customIdField: testValue,
|
|
87
87
|
testIndexedField: 'hello',
|
|
88
88
|
stringField: 'hello',
|
|
89
|
-
|
|
89
|
+
intField: 1,
|
|
90
90
|
dateField: new Date(),
|
|
91
91
|
nullableField: null,
|
|
92
92
|
})
|
|
@@ -32,16 +32,16 @@ export class TestEntity2PrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
32
32
|
ViewerContext,
|
|
33
33
|
TestEntity2
|
|
34
34
|
> {
|
|
35
|
-
protected readonly readRules = [
|
|
35
|
+
protected override readonly readRules = [
|
|
36
36
|
new AlwaysAllowPrivacyPolicyRule<Test2Fields, string, ViewerContext, TestEntity2>(),
|
|
37
37
|
];
|
|
38
|
-
protected readonly createRules = [
|
|
38
|
+
protected override readonly createRules = [
|
|
39
39
|
new AlwaysAllowPrivacyPolicyRule<Test2Fields, string, ViewerContext, TestEntity2>(),
|
|
40
40
|
];
|
|
41
|
-
protected readonly updateRules = [
|
|
41
|
+
protected override readonly updateRules = [
|
|
42
42
|
new AlwaysAllowPrivacyPolicyRule<Test2Fields, string, ViewerContext, TestEntity2>(),
|
|
43
43
|
];
|
|
44
|
-
protected readonly deleteRules = [
|
|
44
|
+
protected override readonly deleteRules = [
|
|
45
45
|
new AlwaysAllowPrivacyPolicyRule<Test2Fields, string, ViewerContext, TestEntity2>(),
|
|
46
46
|
];
|
|
47
47
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Entity from '../Entity';
|
|
2
2
|
import { EntityCompanionDefinition } from '../EntityCompanionProvider';
|
|
3
3
|
import EntityConfiguration from '../EntityConfiguration';
|
|
4
|
-
import {
|
|
4
|
+
import { IntField } from '../EntityFields';
|
|
5
5
|
import EntityPrivacyPolicy from '../EntityPrivacyPolicy';
|
|
6
6
|
import ViewerContext from '../ViewerContext';
|
|
7
7
|
import AlwaysAllowPrivacyPolicyRule from '../rules/AlwaysAllowPrivacyPolicyRule';
|
|
@@ -14,7 +14,7 @@ export const numberKeyEntityConfiguration = new EntityConfiguration<NumberKeyFie
|
|
|
14
14
|
idField: 'id',
|
|
15
15
|
tableName: 'simple_test_entity_should_not_write_to_db',
|
|
16
16
|
schema: {
|
|
17
|
-
id: new
|
|
17
|
+
id: new IntField({
|
|
18
18
|
columnName: 'custom_id',
|
|
19
19
|
}),
|
|
20
20
|
},
|
|
@@ -28,16 +28,16 @@ export class NumberKeyPrivacyPolicy extends EntityPrivacyPolicy<
|
|
|
28
28
|
ViewerContext,
|
|
29
29
|
NumberKeyEntity
|
|
30
30
|
> {
|
|
31
|
-
protected readonly readRules = [
|
|
31
|
+
protected override readonly readRules = [
|
|
32
32
|
new AlwaysAllowPrivacyPolicyRule<NumberKeyFields, number, ViewerContext, NumberKeyEntity>(),
|
|
33
33
|
];
|
|
34
|
-
protected readonly createRules = [
|
|
34
|
+
protected override readonly createRules = [
|
|
35
35
|
new AlwaysAllowPrivacyPolicyRule<NumberKeyFields, number, ViewerContext, NumberKeyEntity>(),
|
|
36
36
|
];
|
|
37
|
-
protected readonly updateRules = [
|
|
37
|
+
protected override readonly updateRules = [
|
|
38
38
|
new AlwaysAllowPrivacyPolicyRule<NumberKeyFields, number, ViewerContext, NumberKeyEntity>(),
|
|
39
39
|
];
|
|
40
|
-
protected readonly deleteRules = [
|
|
40
|
+
protected override readonly deleteRules = [
|
|
41
41
|
new AlwaysAllowPrivacyPolicyRule<NumberKeyFields, number, ViewerContext, NumberKeyEntity>(),
|
|
42
42
|
];
|
|
43
43
|
}
|
|
@@ -8,7 +8,7 @@ import EntityDatabaseAdapter, {
|
|
|
8
8
|
TableQuerySelectionModifiers,
|
|
9
9
|
OrderByOrdering,
|
|
10
10
|
} from '../../EntityDatabaseAdapter';
|
|
11
|
-
import { StringField,
|
|
11
|
+
import { StringField, IntField } from '../../EntityFields';
|
|
12
12
|
import {
|
|
13
13
|
getDatabaseFieldForEntityField,
|
|
14
14
|
FieldTransformerMap,
|
|
@@ -71,7 +71,7 @@ export default class StubDatabaseAdapter<T> extends EntityDatabaseAdapter<T> {
|
|
|
71
71
|
return 0;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
const currentOrderBy = orderBys[0]
|
|
74
|
+
const currentOrderBy = orderBys[0]!;
|
|
75
75
|
const aField = objectA[currentOrderBy.columnName];
|
|
76
76
|
const bField = objectB[currentOrderBy.columnName];
|
|
77
77
|
switch (currentOrderBy.order) {
|
|
@@ -161,7 +161,7 @@ export default class StubDatabaseAdapter<T> extends EntityDatabaseAdapter<T> {
|
|
|
161
161
|
invariant(idSchemaField, `No schema field found for ${this.entityConfiguration2.idField}`);
|
|
162
162
|
if (idSchemaField instanceof StringField) {
|
|
163
163
|
return uuidv4();
|
|
164
|
-
} else if (idSchemaField instanceof
|
|
164
|
+
} else if (idSchemaField instanceof IntField) {
|
|
165
165
|
return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
|
|
166
166
|
} else {
|
|
167
167
|
throw new Error(
|
|
@@ -211,7 +211,7 @@ export default class StubDatabaseAdapter<T> extends EntityDatabaseAdapter<T> {
|
|
|
211
211
|
...objectCollection[objectIndex],
|
|
212
212
|
...object,
|
|
213
213
|
};
|
|
214
|
-
return [objectCollection[objectIndex]];
|
|
214
|
+
return [objectCollection[objectIndex]!];
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
protected async deleteInternalAsync(
|