@expo/entity 0.17.0 → 0.21.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.
Files changed (215) hide show
  1. package/build/EnforcingEntityLoader.js +2 -2
  2. package/build/EnforcingEntityLoader.js.map +1 -1
  3. package/build/Entity.js +8 -2
  4. package/build/Entity.js.map +1 -1
  5. package/build/EntityAssociationLoader.js +3 -3
  6. package/build/EntityAssociationLoader.js.map +1 -1
  7. package/build/EntityCompanion.d.ts +5 -0
  8. package/build/EntityCompanion.js +8 -1
  9. package/build/EntityCompanion.js.map +1 -1
  10. package/build/EntityCompanionProvider.d.ts +1 -1
  11. package/build/EntityCompanionProvider.js +5 -5
  12. package/build/EntityCompanionProvider.js.map +1 -1
  13. package/build/EntityConfiguration.d.ts +1 -1
  14. package/build/EntityConfiguration.js +3 -3
  15. package/build/EntityConfiguration.js.map +1 -1
  16. package/build/EntityDatabaseAdapter.d.ts +4 -4
  17. package/build/EntityDatabaseAdapter.js +13 -13
  18. package/build/EntityDatabaseAdapter.js.map +1 -1
  19. package/build/EntityFieldDefinition.d.ts +77 -0
  20. package/build/EntityFieldDefinition.js +53 -0
  21. package/build/EntityFieldDefinition.js.map +1 -0
  22. package/build/EntityFields.d.ts +1 -77
  23. package/build/EntityFields.js +13 -61
  24. package/build/EntityFields.js.map +1 -1
  25. package/build/EntityLoader.d.ts +3 -1
  26. package/build/EntityLoader.js +19 -15
  27. package/build/EntityLoader.js.map +1 -1
  28. package/build/EntityLoaderFactory.d.ts +3 -1
  29. package/build/EntityLoaderFactory.js +3 -2
  30. package/build/EntityLoaderFactory.js.map +1 -1
  31. package/build/EntityMutationInfo.d.ts +26 -0
  32. package/build/EntityMutationInfo.js +10 -0
  33. package/build/EntityMutationInfo.js.map +1 -0
  34. package/build/EntityMutationTriggerConfiguration.d.ts +4 -4
  35. package/build/EntityMutationValidator.d.ts +3 -3
  36. package/build/EntityMutationValidator.js.map +1 -1
  37. package/build/EntityMutator.d.ts +5 -16
  38. package/build/EntityMutator.js +62 -58
  39. package/build/EntityMutator.js.map +1 -1
  40. package/build/EntityPrivacyPolicy.d.ts +5 -4
  41. package/build/EntityPrivacyPolicy.js +60 -12
  42. package/build/EntityPrivacyPolicy.js.map +1 -1
  43. package/build/EntityQueryContext.d.ts +24 -0
  44. package/build/EntityQueryContext.js +43 -0
  45. package/build/EntityQueryContext.js.map +1 -1
  46. package/build/EntityQueryContextProvider.js +1 -0
  47. package/build/EntityQueryContextProvider.js.map +1 -1
  48. package/build/EntitySecondaryCacheLoader.js +2 -2
  49. package/build/EntitySecondaryCacheLoader.js.map +1 -1
  50. package/build/ReadonlyEntity.js +3 -4
  51. package/build/ReadonlyEntity.js.map +1 -1
  52. package/build/ViewerScopedEntityCompanion.d.ts +5 -0
  53. package/build/ViewerScopedEntityCompanion.js +6 -0
  54. package/build/ViewerScopedEntityCompanion.js.map +1 -1
  55. package/build/__tests__/EnforcingEntityLoader-test.js +82 -82
  56. package/build/__tests__/EnforcingEntityLoader-test.js.map +1 -1
  57. package/build/__tests__/Entity-test.js +6 -6
  58. package/build/__tests__/Entity-test.js.map +1 -1
  59. package/build/__tests__/EntityAssociationLoader-test.js +40 -40
  60. package/build/__tests__/EntityAssociationLoader-test.js.map +1 -1
  61. package/build/__tests__/EntityCommonUseCases-test.js +11 -11
  62. package/build/__tests__/EntityCommonUseCases-test.js.map +1 -1
  63. package/build/__tests__/EntityCompanion-test.js +3 -3
  64. package/build/__tests__/EntityCompanion-test.js.map +1 -1
  65. package/build/__tests__/EntityCompanionProvider-test.js +1 -1
  66. package/build/__tests__/EntityCompanionProvider-test.js.map +1 -1
  67. package/build/__tests__/EntityDatabaseAdapter-test.js +12 -12
  68. package/build/__tests__/EntityDatabaseAdapter-test.js.map +1 -1
  69. package/build/__tests__/EntityEdges-test.js +103 -6
  70. package/build/__tests__/EntityEdges-test.js.map +1 -1
  71. package/build/__tests__/EntityFields-test.js +18 -27
  72. package/build/__tests__/EntityFields-test.js.map +1 -1
  73. package/build/__tests__/EntityLoader-constructor-test.d.ts +22 -0
  74. package/build/__tests__/EntityLoader-constructor-test.js +111 -0
  75. package/build/__tests__/EntityLoader-constructor-test.js.map +1 -0
  76. package/build/__tests__/EntityLoader-test.js +72 -64
  77. package/build/__tests__/EntityLoader-test.js.map +1 -1
  78. package/build/__tests__/EntityMutator-MutationCacheConsistency-test.d.ts +1 -0
  79. package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js +81 -0
  80. package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js.map +1 -0
  81. package/build/__tests__/EntityMutator-test.js +116 -114
  82. package/build/__tests__/EntityMutator-test.js.map +1 -1
  83. package/build/__tests__/EntityPrivacyPolicy-test.js +143 -67
  84. package/build/__tests__/EntityPrivacyPolicy-test.js.map +1 -1
  85. package/build/__tests__/EntityQueryContext-test.d.ts +1 -0
  86. package/build/__tests__/EntityQueryContext-test.js +56 -0
  87. package/build/__tests__/EntityQueryContext-test.js.map +1 -0
  88. package/build/__tests__/EntitySecondaryCacheLoader-test.js +15 -15
  89. package/build/__tests__/EntitySecondaryCacheLoader-test.js.map +1 -1
  90. package/build/__tests__/EntitySelfReferentialEdges-test.js +13 -12
  91. package/build/__tests__/EntitySelfReferentialEdges-test.js.map +1 -1
  92. package/build/__tests__/ReadonlyEntity-test.js +11 -11
  93. package/build/__tests__/ReadonlyEntity-test.js.map +1 -1
  94. package/build/__tests__/ViewerContext-test.js +2 -2
  95. package/build/__tests__/ViewerContext-test.js.map +1 -1
  96. package/build/__tests__/ViewerScopedEntityCompanion-test.js +2 -2
  97. package/build/__tests__/ViewerScopedEntityCompanion-test.js.map +1 -1
  98. package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js +2 -2
  99. package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js.map +1 -1
  100. package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js +5 -5
  101. package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js.map +1 -1
  102. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js +5 -5
  103. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js.map +1 -1
  104. package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js +5 -5
  105. package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js.map +1 -1
  106. package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js +2 -2
  107. package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js.map +1 -1
  108. package/build/__tests__/entityUtils-test.js +21 -21
  109. package/build/__tests__/entityUtils-test.js.map +1 -1
  110. package/build/index.d.ts +3 -0
  111. package/build/index.js +5 -1
  112. package/build/index.js.map +1 -1
  113. package/build/internal/EntityDataManager.js +8 -7
  114. package/build/internal/EntityDataManager.js.map +1 -1
  115. package/build/internal/EntityFieldTransformationUtils.js +2 -2
  116. package/build/internal/EntityFieldTransformationUtils.js.map +1 -1
  117. package/build/internal/ReadThroughEntityCache.js +4 -4
  118. package/build/internal/ReadThroughEntityCache.js.map +1 -1
  119. package/build/internal/__tests__/EntityDataManager-test.js +17 -17
  120. package/build/internal/__tests__/EntityDataManager-test.js.map +1 -1
  121. package/build/internal/__tests__/EntityFieldTransformationUtils-test.js +8 -8
  122. package/build/internal/__tests__/EntityFieldTransformationUtils-test.js.map +1 -1
  123. package/build/internal/__tests__/ReadThroughEntityCache-test.js +48 -48
  124. package/build/internal/__tests__/ReadThroughEntityCache-test.js.map +1 -1
  125. package/build/metrics/EntityMetricsUtils.js +1 -1
  126. package/build/metrics/EntityMetricsUtils.js.map +1 -1
  127. package/build/metrics/IEntityMetricsAdapter.d.ts +16 -0
  128. package/build/metrics/IEntityMetricsAdapter.js +6 -1
  129. package/build/metrics/IEntityMetricsAdapter.js.map +1 -1
  130. package/build/metrics/NoOpEntityMetricsAdapter.d.ts +2 -1
  131. package/build/metrics/NoOpEntityMetricsAdapter.js +1 -0
  132. package/build/metrics/NoOpEntityMetricsAdapter.js.map +1 -1
  133. package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js +4 -4
  134. package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js.map +1 -1
  135. package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js +4 -4
  136. package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js.map +1 -1
  137. package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js +4 -4
  138. package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js.map +1 -1
  139. package/build/testfixtures/DateIDTestEntity.js.map +1 -1
  140. package/build/testfixtures/SimpleTestEntity.js.map +1 -1
  141. package/build/testfixtures/TestEntity.d.ts +5 -5
  142. package/build/testfixtures/TestEntity.js +2 -2
  143. package/build/testfixtures/TestEntity.js.map +1 -1
  144. package/build/testfixtures/TestEntity2.d.ts +5 -5
  145. package/build/testfixtures/TestEntity2.js.map +1 -1
  146. package/build/testfixtures/TestEntityNumberKey.js.map +1 -1
  147. package/build/utils/collections/__tests__/maps-test.js +13 -13
  148. package/build/utils/collections/__tests__/maps-test.js.map +1 -1
  149. package/build/utils/collections/maps.js +1 -1
  150. package/build/utils/collections/maps.js.map +1 -1
  151. package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +6 -6
  152. package/build/utils/testing/PrivacyPolicyRuleTestUtils.js +1 -1
  153. package/build/utils/testing/PrivacyPolicyRuleTestUtils.js.map +1 -1
  154. package/build/utils/testing/StubCacheAdapter.js +1 -1
  155. package/build/utils/testing/StubCacheAdapter.js.map +1 -1
  156. package/build/utils/testing/StubDatabaseAdapter.js +6 -6
  157. package/build/utils/testing/StubDatabaseAdapter.js.map +1 -1
  158. package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js +9 -9
  159. package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js.map +1 -1
  160. package/build/utils/testing/describeFieldTestCase.d.ts +2 -0
  161. package/build/utils/testing/describeFieldTestCase.js +18 -0
  162. package/build/utils/testing/describeFieldTestCase.js.map +1 -0
  163. package/package.json +2 -1
  164. package/src/Entity.ts +10 -2
  165. package/src/EntityAssociationLoader.ts +1 -1
  166. package/src/EntityCompanion.ts +10 -2
  167. package/src/EntityCompanionProvider.ts +5 -9
  168. package/src/EntityConfiguration.ts +1 -1
  169. package/src/EntityDatabaseAdapter.ts +10 -8
  170. package/src/EntityFieldDefinition.ts +124 -0
  171. package/src/EntityFields.ts +2 -125
  172. package/src/EntityLoader.ts +12 -4
  173. package/src/EntityLoaderFactory.ts +5 -2
  174. package/src/EntityMutationInfo.ts +47 -0
  175. package/src/EntityMutationTriggerConfiguration.ts +5 -5
  176. package/src/EntityMutationValidator.ts +10 -4
  177. package/src/EntityMutator.ts +98 -76
  178. package/src/EntityPrivacyPolicy.ts +77 -19
  179. package/src/EntityQueryContext.ts +54 -0
  180. package/src/EntityQueryContextProvider.ts +1 -0
  181. package/src/ReadonlyEntity.ts +3 -2
  182. package/src/ViewerScopedEntityCompanion.ts +8 -0
  183. package/src/__tests__/Entity-test.ts +8 -8
  184. package/src/__tests__/EntityCommonUseCases-test.ts +4 -4
  185. package/src/__tests__/EntityEdges-test.ts +169 -14
  186. package/src/__tests__/EntityFields-test.ts +2 -21
  187. package/src/__tests__/EntityLoader-constructor-test.ts +177 -0
  188. package/src/__tests__/EntityLoader-test.ts +39 -11
  189. package/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts +105 -0
  190. package/src/__tests__/EntityMutator-test.ts +140 -133
  191. package/src/__tests__/EntityPrivacyPolicy-test.ts +215 -78
  192. package/src/__tests__/EntityQueryContext-test.ts +82 -0
  193. package/src/__tests__/EntitySecondaryCacheLoader-test.ts +7 -9
  194. package/src/__tests__/EntitySelfReferentialEdges-test.ts +6 -5
  195. package/src/__tests__/ViewerContext-test.ts +7 -6
  196. package/src/__tests__/ViewerScopedEntityCompanion-test.ts +11 -10
  197. package/src/__tests__/ViewerScopedEntityMutatorFactory-test.ts +4 -3
  198. package/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts +6 -6
  199. package/src/__tests__/cases/TwoEntitySameTableOverlappingRows-test.ts +4 -4
  200. package/src/index.ts +3 -0
  201. package/src/internal/EntityDataManager.ts +2 -1
  202. package/src/internal/__tests__/EntityDataManager-test.ts +2 -2
  203. package/src/internal/__tests__/ReadThroughEntityCache-test.ts +15 -13
  204. package/src/metrics/EntityMetricsUtils.ts +56 -50
  205. package/src/metrics/IEntityMetricsAdapter.ts +23 -0
  206. package/src/metrics/NoOpEntityMetricsAdapter.ts +2 -0
  207. package/src/testfixtures/DateIDTestEntity.ts +4 -4
  208. package/src/testfixtures/SimpleTestEntity.ts +4 -4
  209. package/src/testfixtures/TestEntity.ts +4 -4
  210. package/src/testfixtures/TestEntity2.ts +4 -4
  211. package/src/testfixtures/TestEntityNumberKey.ts +4 -4
  212. package/src/utils/testing/StubDatabaseAdapter.ts +2 -2
  213. package/src/utils/testing/__tests__/StubDatabaseAdapter-test.ts +1 -1
  214. package/src/utils/testing/describeFieldTestCase.ts +21 -0
  215. package/CHANGELOG.md +0 -252
@@ -10,16 +10,17 @@ import TestEntity, { TestFields, TestEntityPrivacyPolicy } from '../testfixtures
10
10
  describe(ViewerScopedEntityCompanion, () => {
11
11
  it('returns viewer scoped loader and mutator factory', () => {
12
12
  const vc = instance(mock(ViewerContext));
13
- const entityCompanion = mock<
14
- EntityCompanion<
15
- TestFields,
16
- string,
17
- ViewerContext,
18
- TestEntity,
19
- TestEntityPrivacyPolicy,
20
- keyof TestFields
21
- >
22
- >();
13
+ const entityCompanion =
14
+ mock<
15
+ EntityCompanion<
16
+ TestFields,
17
+ string,
18
+ ViewerContext,
19
+ TestEntity,
20
+ TestEntityPrivacyPolicy,
21
+ keyof TestFields
22
+ >
23
+ >();
23
24
  const viewerScopedEntityCompanion = new ViewerScopedEntityCompanion(entityCompanion, vc);
24
25
  expect(viewerScopedEntityCompanion.getLoaderFactory()).toBeInstanceOf(
25
26
  ViewerScopedEntityLoaderFactory
@@ -10,9 +10,10 @@ describe(ViewerScopedEntityMutatorFactory, () => {
10
10
  it('correctly scopes viewer to entity mutations', async () => {
11
11
  const viewerContext = instance(mock(ViewerContext));
12
12
  const queryContext = instance(mock(EntityQueryContext));
13
- const baseMutatorFactory = mock<
14
- EntityMutatorFactory<TestFields, string, ViewerContext, TestEntity, TestEntityPrivacyPolicy>
15
- >(EntityMutatorFactory);
13
+ const baseMutatorFactory =
14
+ mock<
15
+ EntityMutatorFactory<TestFields, string, ViewerContext, TestEntity, TestEntityPrivacyPolicy>
16
+ >(EntityMutatorFactory);
16
17
  const baseMutatorFactoryInstance = instance(baseMutatorFactory);
17
18
 
18
19
  const viewerScopedEntityLoader = new ViewerScopedEntityMutatorFactory<
@@ -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].enforceValue().getID()).toEqual(one.getID());
49
- expect(failedManyResults[0].enforceError().message).toEqual(
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
- throw errors[0];
128
+ const error = errors[0]!;
129
+ throw error;
129
130
  }
130
131
 
131
132
  return zipToMap(fieldValues, values);
@@ -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');
@@ -20,19 +20,21 @@ const makeEntityConfiguration = (cacheIdField: boolean): EntityConfiguration<Bla
20
20
  cacheAdapterFlavor: 'redis',
21
21
  });
22
22
 
23
- const createIdFetcher = (ids: string[]) => async <N extends keyof BlahFields>(
24
- fetcherFieldValues: readonly NonNullable<BlahFields[N]>[]
25
- ): Promise<ReadonlyMap<NonNullable<BlahFields[N]>, readonly Readonly<BlahFields>[]>> => {
26
- const results = new Map();
27
- fetcherFieldValues.forEach((v) => {
28
- if (ids.includes(v)) {
29
- results.set(v, [{ id: v }]);
30
- } else {
31
- results.set(v, []);
32
- }
33
- });
34
- return results;
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
- metricsAdapter: IEntityMetricsAdapter,
9
- loadType: EntityMetricsLoadType,
10
- entityClassName: string
11
- ) => async <TFields>(promise: Promise<readonly Readonly<TFields>[]>) => {
12
- const startTime = Date.now();
13
- const result = await promise;
14
- const endTime = Date.now();
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
- metricsAdapter.logDataManagerLoadEvent({
17
- type: loadType,
18
- entityClassName,
19
- duration: endTime - startTime,
20
- count: result.length,
21
- });
18
+ metricsAdapter.logDataManagerLoadEvent({
19
+ type: loadType,
20
+ entityClassName,
21
+ duration: endTime - startTime,
22
+ count: result.length,
23
+ });
22
24
 
23
- return result;
24
- };
25
+ return result;
26
+ };
25
27
 
26
- export const timeAndLogLoadMapEventAsync = (
27
- metricsAdapter: IEntityMetricsAdapter,
28
- loadType: EntityMetricsLoadType,
29
- entityClassName: string
30
- ) => async <TFields, N extends keyof TFields>(
31
- promise: Promise<ReadonlyMap<NonNullable<TFields[N]>, readonly Readonly<TFields>[]>>
32
- ) => {
33
- const startTime = Date.now();
34
- const result = await promise;
35
- const endTime = Date.now();
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
- const count = reduceMap(result, (acc, v) => acc + v.length, 0);
41
+ const count = reduceMap(result, (acc, v) => acc + v.length, 0);
38
42
 
39
- metricsAdapter.logDataManagerLoadEvent({
40
- type: loadType,
41
- entityClassName,
42
- duration: endTime - startTime,
43
- count,
44
- });
43
+ metricsAdapter.logDataManagerLoadEvent({
44
+ type: loadType,
45
+ entityClassName,
46
+ duration: endTime - startTime,
47
+ count,
48
+ });
45
49
 
46
- return result;
47
- };
50
+ return result;
51
+ };
48
52
 
49
- export const timeAndLogMutationEventAsync = (
50
- metricsAdapter: IEntityMetricsAdapter,
51
- mutationType: EntityMetricsMutationType,
52
- entityClassName: string
53
- ) => async <T>(promise: Promise<T>) => {
54
- const startTime = Date.now();
55
- const result = await promise;
56
- const endTime = Date.now();
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
- metricsAdapter.logMutatorMutationEvent({
59
- type: mutationType,
60
- entityClassName,
61
- duration: endTime - startTime,
62
- });
64
+ metricsAdapter.logMutatorMutationEvent({
65
+ type: mutationType,
66
+ entityClassName,
67
+ duration: endTime - startTime,
68
+ });
63
69
 
64
- return result;
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,
@@ -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
  }
@@ -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
  }
@@ -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
  }
@@ -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) {
@@ -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(
@@ -247,7 +247,7 @@ describe(StubDatabaseAdapter, () => {
247
247
  {}
248
248
  );
249
249
  expect(results).toHaveLength(2);
250
- expect(results[0].nullableField).toBeNull();
250
+ expect(results[0]!.nullableField).toBeNull();
251
251
 
252
252
  const results2 = await databaseAdapter.fetchManyByFieldEqualityConjunctionAsync(
253
253
  queryContext,
@@ -0,0 +1,21 @@
1
+ import { EntityFieldDefinition } from '../../EntityFieldDefinition';
2
+
3
+ export default function describeFieldTestCase<T>(
4
+ fieldDefinition: EntityFieldDefinition<T>,
5
+ validValues: T[],
6
+ invalidValues: any[]
7
+ ): void {
8
+ describe(fieldDefinition.constructor.name, () => {
9
+ if (validValues.length > 0) {
10
+ test.each(validValues)(`${fieldDefinition.constructor.name}.valid %p`, (value) => {
11
+ expect(fieldDefinition.validateInputValue(value)).toBe(true);
12
+ });
13
+ }
14
+
15
+ if (invalidValues.length > 0) {
16
+ test.each(invalidValues)(`${fieldDefinition.constructor.name}.invalid %p`, (value) => {
17
+ expect(fieldDefinition.validateInputValue(value)).toBe(false);
18
+ });
19
+ }
20
+ });
21
+ }