@expo/entity 0.38.0 → 0.40.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 (206) hide show
  1. package/build/AuthorizationResultBasedEntityAssociationLoader.d.ts +99 -0
  2. package/build/AuthorizationResultBasedEntityAssociationLoader.js +124 -0
  3. package/build/AuthorizationResultBasedEntityAssociationLoader.js.map +1 -0
  4. package/build/AuthorizationResultBasedEntityLoader.d.ts +1 -1
  5. package/build/AuthorizationResultBasedEntityLoader.js.map +1 -1
  6. package/build/{EntityMutator.d.ts → AuthorizationResultBasedEntityMutator.d.ts} +5 -17
  7. package/build/{EntityMutator.js → AuthorizationResultBasedEntityMutator.js} +22 -48
  8. package/build/AuthorizationResultBasedEntityMutator.js.map +1 -0
  9. package/build/EnforcingEntityAssociationLoader.d.ts +79 -0
  10. package/build/EnforcingEntityAssociationLoader.js +62 -0
  11. package/build/EnforcingEntityAssociationLoader.js.map +1 -0
  12. package/build/EnforcingEntityCreator.d.ts +24 -0
  13. package/build/EnforcingEntityCreator.js +32 -0
  14. package/build/EnforcingEntityCreator.js.map +1 -0
  15. package/build/EnforcingEntityDeleter.d.ts +17 -0
  16. package/build/EnforcingEntityDeleter.js +22 -0
  17. package/build/EnforcingEntityDeleter.js.map +1 -0
  18. package/build/EnforcingEntityUpdater.d.ts +24 -0
  19. package/build/EnforcingEntityUpdater.js +32 -0
  20. package/build/EnforcingEntityUpdater.js.map +1 -0
  21. package/build/Entity.d.ts +8 -12
  22. package/build/Entity.js +9 -34
  23. package/build/Entity.js.map +1 -1
  24. package/build/EntityAssociationLoader.d.ts +12 -91
  25. package/build/EntityAssociationLoader.js +20 -126
  26. package/build/EntityAssociationLoader.js.map +1 -1
  27. package/build/EntityCompanionProvider.d.ts +2 -2
  28. package/build/EntityCompanionProvider.js.map +1 -1
  29. package/build/EntityCreator.d.ts +27 -0
  30. package/build/EntityCreator.js +39 -0
  31. package/build/EntityCreator.js.map +1 -0
  32. package/build/EntityDatabaseAdapter.js +2 -2
  33. package/build/EntityDatabaseAdapter.js.map +1 -1
  34. package/build/EntityDeleter.d.ts +27 -0
  35. package/build/EntityDeleter.js +40 -0
  36. package/build/EntityDeleter.js.map +1 -0
  37. package/build/EntityLoader.d.ts +4 -14
  38. package/build/EntityLoader.js +7 -20
  39. package/build/EntityLoader.js.map +1 -1
  40. package/build/EntityLoaderFactory.d.ts +2 -2
  41. package/build/EntityLoaderFactory.js +4 -2
  42. package/build/EntityLoaderFactory.js.map +1 -1
  43. package/build/EntityMutatorFactory.d.ts +4 -4
  44. package/build/EntityMutatorFactory.js +4 -4
  45. package/build/EntityMutatorFactory.js.map +1 -1
  46. package/build/EntitySecondaryCacheLoader.d.ts +3 -3
  47. package/build/EntitySecondaryCacheLoader.js +1 -3
  48. package/build/EntitySecondaryCacheLoader.js.map +1 -1
  49. package/build/EntityUpdater.d.ts +27 -0
  50. package/build/EntityUpdater.js +40 -0
  51. package/build/EntityUpdater.js.map +1 -0
  52. package/build/ReadonlyEntity.d.ts +2 -2
  53. package/build/ReadonlyEntity.js +4 -6
  54. package/build/ReadonlyEntity.js.map +1 -1
  55. package/build/ViewerScopedEntityLoaderFactory.d.ts +2 -2
  56. package/build/ViewerScopedEntityLoaderFactory.js.map +1 -1
  57. package/build/ViewerScopedEntityMutatorFactory.d.ts +4 -4
  58. package/build/ViewerScopedEntityMutatorFactory.js.map +1 -1
  59. package/build/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.d.ts +1 -0
  60. package/build/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.js +273 -0
  61. package/build/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.js.map +1 -0
  62. package/build/__tests__/{EntityLoader-constructor-test.js → AuthorizationResultBasedEntityLoader-constructor-test.js} +11 -11
  63. package/build/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.js.map +1 -0
  64. package/build/__tests__/AuthorizationResultBasedEntityLoader-test.d.ts +1 -0
  65. package/build/__tests__/AuthorizationResultBasedEntityLoader-test.js +401 -0
  66. package/build/__tests__/AuthorizationResultBasedEntityLoader-test.js.map +1 -0
  67. package/build/__tests__/EnforcingEntityAssociationLoader-test.d.ts +1 -0
  68. package/build/__tests__/EnforcingEntityAssociationLoader-test.js +115 -0
  69. package/build/__tests__/EnforcingEntityAssociationLoader-test.js.map +1 -0
  70. package/build/__tests__/Entity-test.js +23 -5
  71. package/build/__tests__/Entity-test.js.map +1 -1
  72. package/build/__tests__/EntityAssociationLoader-test.js +14 -184
  73. package/build/__tests__/EntityAssociationLoader-test.js.map +1 -1
  74. package/build/__tests__/EntityCommonUseCases-test.js +34 -12
  75. package/build/__tests__/EntityCommonUseCases-test.js.map +1 -1
  76. package/build/__tests__/EntityCompanion-test.js +17 -7
  77. package/build/__tests__/EntityCompanion-test.js.map +1 -1
  78. package/build/__tests__/EntityDatabaseAdapter-test.js.map +1 -1
  79. package/build/__tests__/EntityEdges-test.js +41 -23
  80. package/build/__tests__/EntityEdges-test.js.map +1 -1
  81. package/build/__tests__/EntityLoader-test.js +22 -386
  82. package/build/__tests__/EntityLoader-test.js.map +1 -1
  83. package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js +4 -3
  84. package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js.map +1 -1
  85. package/build/__tests__/EntityMutator-test.js +67 -70
  86. package/build/__tests__/EntityMutator-test.js.map +1 -1
  87. package/build/__tests__/EntityPrivacyPolicy-test.js +17 -7
  88. package/build/__tests__/EntityPrivacyPolicy-test.js.map +1 -1
  89. package/build/__tests__/EntitySecondaryCacheLoader-test.js +7 -7
  90. package/build/__tests__/EntitySecondaryCacheLoader-test.js.map +1 -1
  91. package/build/__tests__/EntitySelfReferentialEdges-test.js +36 -24
  92. package/build/__tests__/EntitySelfReferentialEdges-test.js.map +1 -1
  93. package/build/__tests__/ReadonlyEntity-test.js +1 -1
  94. package/build/__tests__/ReadonlyEntity-test.js.map +1 -1
  95. package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js +4 -2
  96. package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js.map +1 -1
  97. package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js +7 -4
  98. package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js.map +1 -1
  99. package/build/__tests__/entityUtils-test.js +8 -0
  100. package/build/__tests__/entityUtils-test.js.map +1 -1
  101. package/build/entityUtils.d.ts +7 -0
  102. package/build/entityUtils.js +20 -10
  103. package/build/entityUtils.js.map +1 -1
  104. package/build/errors/EntityCacheAdapterError.js +17 -7
  105. package/build/errors/EntityCacheAdapterError.js.map +1 -1
  106. package/build/errors/EntityDatabaseAdapterError.js +17 -7
  107. package/build/errors/EntityDatabaseAdapterError.js.map +1 -1
  108. package/build/errors/EntityInvalidFieldValueError.js +17 -7
  109. package/build/errors/EntityInvalidFieldValueError.js.map +1 -1
  110. package/build/errors/EntityNotAuthorizedError.js +17 -7
  111. package/build/errors/EntityNotAuthorizedError.js.map +1 -1
  112. package/build/errors/EntityNotFoundError.js +17 -7
  113. package/build/errors/EntityNotFoundError.js.map +1 -1
  114. package/build/index.d.ts +19 -11
  115. package/build/index.js +24 -7
  116. package/build/index.js.map +1 -1
  117. package/build/internal/EntityFieldTransformationUtils.js.map +1 -1
  118. package/build/internal/__tests__/EntityDataManager-test.js +42 -32
  119. package/build/internal/__tests__/EntityDataManager-test.js.map +1 -1
  120. package/build/internal/__tests__/ReadThroughEntityCache-test.js +17 -7
  121. package/build/internal/__tests__/ReadThroughEntityCache-test.js.map +1 -1
  122. package/build/rules/AlwaysAllowPrivacyPolicyRule.js +17 -7
  123. package/build/rules/AlwaysAllowPrivacyPolicyRule.js.map +1 -1
  124. package/build/rules/AlwaysDenyPrivacyPolicyRule.js +17 -7
  125. package/build/rules/AlwaysDenyPrivacyPolicyRule.js.map +1 -1
  126. package/build/rules/AlwaysSkipPrivacyPolicyRule.js +17 -7
  127. package/build/rules/AlwaysSkipPrivacyPolicyRule.js.map +1 -1
  128. package/build/utils/EntityPrivacyUtils.d.ts +32 -4
  129. package/build/utils/EntityPrivacyUtils.js +68 -24
  130. package/build/utils/EntityPrivacyUtils.js.map +1 -1
  131. package/build/utils/__tests__/EntityPrivacyUtils-test.js +148 -23
  132. package/build/utils/__tests__/EntityPrivacyUtils-test.js.map +1 -1
  133. package/build/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.js +8 -5
  134. package/build/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.js.map +1 -1
  135. package/build/utils/collections/__tests__/maps-test.js +1 -1
  136. package/build/utils/collections/__tests__/maps-test.js.map +1 -1
  137. package/build/utils/collections/maps.js +2 -2
  138. package/build/utils/collections/maps.js.map +1 -1
  139. package/build/utils/mergeEntityMutationTriggerConfigurations.js +1 -2
  140. package/build/utils/mergeEntityMutationTriggerConfigurations.js.map +1 -1
  141. package/build/utils/testing/PrivacyPolicyRuleTestUtils.js +1 -1
  142. package/build/utils/testing/PrivacyPolicyRuleTestUtils.js.map +1 -1
  143. package/build/utils/testing/StubDatabaseAdapter.js +17 -7
  144. package/build/utils/testing/StubDatabaseAdapter.js.map +1 -1
  145. package/build/utils/testing/StubQueryContextProvider.d.ts +1 -3
  146. package/build/utils/testing/StubQueryContextProvider.js +1 -3
  147. package/build/utils/testing/StubQueryContextProvider.js.map +1 -1
  148. package/build/utils/testing/createUnitTestEntityCompanionProvider.js +2 -1
  149. package/build/utils/testing/createUnitTestEntityCompanionProvider.js.map +1 -1
  150. package/build/utils/testing/describeFieldTestCase.js +1 -1
  151. package/build/utils/testing/describeFieldTestCase.js.map +1 -1
  152. package/package.json +19 -3
  153. package/src/AuthorizationResultBasedEntityAssociationLoader.ts +492 -0
  154. package/src/AuthorizationResultBasedEntityLoader.ts +2 -2
  155. package/src/{EntityMutator.ts → AuthorizationResultBasedEntityMutator.ts} +62 -58
  156. package/src/EnforcingEntityAssociationLoader.ts +390 -0
  157. package/src/EnforcingEntityCreator.ts +55 -0
  158. package/src/EnforcingEntityDeleter.ts +44 -0
  159. package/src/EnforcingEntityUpdater.ts +55 -0
  160. package/src/Entity.ts +20 -65
  161. package/src/EntityAssociationLoader.ts +38 -495
  162. package/src/EntityCompanionProvider.ts +5 -2
  163. package/src/EntityCreator.ts +73 -0
  164. package/src/EntityDeleter.ts +73 -0
  165. package/src/EntityLoader.ts +10 -49
  166. package/src/EntityLoaderFactory.ts +20 -3
  167. package/src/EntityMutatorFactory.ts +32 -7
  168. package/src/EntitySecondaryCacheLoader.ts +5 -7
  169. package/src/EntityUpdater.ts +73 -0
  170. package/src/ReadonlyEntity.ts +14 -13
  171. package/src/ViewerScopedEntityLoaderFactory.ts +9 -2
  172. package/src/ViewerScopedEntityMutatorFactory.ts +29 -4
  173. package/src/__tests__/AuthorizationResultBasedEntityAssociationLoader-test.ts +354 -0
  174. package/src/__tests__/{EntityLoader-constructor-test.ts → AuthorizationResultBasedEntityLoader-constructor-test.ts} +17 -10
  175. package/src/__tests__/AuthorizationResultBasedEntityLoader-test.ts +730 -0
  176. package/src/__tests__/EnforcingEntityAssociationLoader-test.ts +253 -0
  177. package/src/__tests__/Entity-test.ts +24 -5
  178. package/src/__tests__/EntityAssociationLoader-test.ts +16 -259
  179. package/src/__tests__/EntityCommonUseCases-test.ts +20 -8
  180. package/src/__tests__/EntityCompanion-test.ts +1 -1
  181. package/src/__tests__/EntityDatabaseAdapter-test.ts +6 -6
  182. package/src/__tests__/EntityEdges-test.ts +24 -16
  183. package/src/__tests__/EntityLoader-test.ts +25 -675
  184. package/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts +4 -3
  185. package/src/__tests__/EntityMutator-test.ts +116 -103
  186. package/src/__tests__/EntitySecondaryCacheLoader-test.ts +7 -7
  187. package/src/__tests__/EntitySelfReferentialEdges-test.ts +36 -24
  188. package/src/__tests__/ReadonlyEntity-test.ts +1 -1
  189. package/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts +4 -2
  190. package/src/__tests__/cases/TwoEntitySameTableOverlappingRows-test.ts +7 -4
  191. package/src/__tests__/entityUtils-test.ts +12 -0
  192. package/src/entityUtils.ts +24 -9
  193. package/src/index.ts +19 -11
  194. package/src/internal/EntityFieldTransformationUtils.ts +2 -2
  195. package/src/internal/__tests__/EntityDataManager-test.ts +29 -29
  196. package/src/utils/EntityPrivacyUtils.ts +188 -107
  197. package/src/utils/__tests__/EntityPrivacyUtils-test.ts +169 -29
  198. package/src/utils/__tests__/canViewerDeleteAsync-edgeDeletionPermissionInferenceBehavior-test.ts +8 -5
  199. package/src/utils/collections/__tests__/maps-test.ts +1 -1
  200. package/src/utils/testing/PrivacyPolicyRuleTestUtils.ts +1 -1
  201. package/src/utils/testing/StubDatabaseAdapter.ts +1 -1
  202. package/src/utils/testing/StubQueryContextProvider.ts +1 -3
  203. package/src/utils/testing/createUnitTestEntityCompanionProvider.ts +3 -1
  204. package/build/EntityMutator.js.map +0 -1
  205. package/build/__tests__/EntityLoader-constructor-test.js.map +0 -1
  206. /package/build/__tests__/{EntityLoader-constructor-test.d.ts → AuthorizationResultBasedEntityLoader-constructor-test.d.ts} +0 -0
@@ -1,687 +1,37 @@
1
- import { enforceAsyncResult } from '@expo/results';
2
- import { mock, instance, verify, spy, deepEqual, anyOfClass, anything, when } from 'ts-mockito';
3
- import { v4 as uuidv4 } from 'uuid';
4
-
5
- import { OrderByOrdering } from '../EntityDatabaseAdapter';
1
+ import AuthorizationResultBasedEntityLoader from '../AuthorizationResultBasedEntityLoader';
2
+ import EnforcingEntityLoader from '../EnforcingEntityLoader';
6
3
  import EntityLoader from '../EntityLoader';
7
- import { EntityPrivacyPolicyEvaluationContext } from '../EntityPrivacyPolicy';
4
+ import EntityLoaderUtils from '../EntityLoaderUtils';
8
5
  import ViewerContext from '../ViewerContext';
9
- import { enforceResultsAsync } from '../entityUtils';
10
- import EntityNotFoundError from '../errors/EntityNotFoundError';
11
- import EntityDataManager from '../internal/EntityDataManager';
12
- import ReadThroughEntityCache from '../internal/ReadThroughEntityCache';
13
- import IEntityMetricsAdapter from '../metrics/IEntityMetricsAdapter';
14
- import TestEntity, {
15
- TestFields,
16
- TestEntityPrivacyPolicy,
17
- testEntityConfiguration,
18
- } from '../testfixtures/TestEntity';
19
- import { NoCacheStubCacheAdapterProvider } from '../utils/testing/StubCacheAdapter';
20
- import StubDatabaseAdapter from '../utils/testing/StubDatabaseAdapter';
21
- import StubQueryContextProvider from '../utils/testing/StubQueryContextProvider';
6
+ import SimpleTestEntity from '../testfixtures/SimpleTestEntity';
7
+ import { createUnitTestEntityCompanionProvider } from '../utils/testing/createUnitTestEntityCompanionProvider';
22
8
 
23
9
  describe(EntityLoader, () => {
24
- it('loads entities', async () => {
25
- const dateToInsert = new Date();
26
- const viewerContext = instance(mock(ViewerContext));
27
- const privacyPolicyEvaluationContext =
28
- instance(
29
- mock<EntityPrivacyPolicyEvaluationContext<TestFields, string, ViewerContext, TestEntity>>(),
10
+ describe('enforcing', () => {
11
+ it('creates a new EnforcingEntityLoader', async () => {
12
+ const companionProvider = createUnitTestEntityCompanionProvider();
13
+ const viewerContext = new ViewerContext(companionProvider);
14
+ expect(SimpleTestEntity.loader(viewerContext).enforcing()).toBeInstanceOf(
15
+ EnforcingEntityLoader,
30
16
  );
31
- const metricsAdapter = instance(mock<IEntityMetricsAdapter>());
32
- const queryContext = StubQueryContextProvider.getQueryContext();
33
-
34
- const id1 = uuidv4();
35
- const id2 = uuidv4();
36
- const databaseAdapter = new StubDatabaseAdapter<TestFields>(
37
- testEntityConfiguration,
38
- StubDatabaseAdapter.convertFieldObjectsToDataStore(
39
- testEntityConfiguration,
40
- new Map([
41
- [
42
- testEntityConfiguration.tableName,
43
- [
44
- {
45
- customIdField: id1,
46
- testIndexedField: 'h1',
47
- intField: 5,
48
- stringField: 'huh',
49
- dateField: dateToInsert,
50
- nullableField: null,
51
- },
52
- {
53
- customIdField: id2,
54
- testIndexedField: 'h2',
55
- intField: 3,
56
- stringField: 'huh',
57
- dateField: dateToInsert,
58
- nullableField: null,
59
- },
60
- ],
61
- ],
62
- ]),
63
- ),
64
- );
65
- const privacyPolicy = new TestEntityPrivacyPolicy();
66
- const cacheAdapterProvider = new NoCacheStubCacheAdapterProvider();
67
- const cacheAdapter = cacheAdapterProvider.getCacheAdapter(testEntityConfiguration);
68
- const entityCache = new ReadThroughEntityCache(testEntityConfiguration, cacheAdapter);
69
- const dataManager = new EntityDataManager(
70
- databaseAdapter,
71
- entityCache,
72
- StubQueryContextProvider,
73
- instance(mock<IEntityMetricsAdapter>()),
74
- TestEntity.name,
75
- );
76
- const entityLoader = new EntityLoader(
77
- viewerContext,
78
- queryContext,
79
- privacyPolicyEvaluationContext,
80
- testEntityConfiguration,
81
- TestEntity,
82
- /* entitySelectedFields */ undefined,
83
- privacyPolicy,
84
- dataManager,
85
- metricsAdapter,
86
- );
87
- const entity = await enforceAsyncResult(
88
- entityLoader.withAuthorizationResults().loadByIDAsync(id1),
89
- );
90
- expect(entity.getID()).toEqual(id1);
91
- expect(entity.getField('dateField')).toEqual(dateToInsert);
92
-
93
- const entities = await enforceResultsAsync(
94
- entityLoader.withAuthorizationResults().loadManyByFieldEqualingAsync('stringField', 'huh'),
95
- );
96
- expect(entities.map((m) => m.getID())).toEqual([id1, id2]);
97
-
98
- const entityResultNumber3 = await entityLoader
99
- .withAuthorizationResults()
100
- .loadByFieldEqualingAsync('intField', 3);
101
- expect(entityResultNumber3).not.toBeNull();
102
- expect(entityResultNumber3!.enforceValue().getID()).toEqual(id2);
103
-
104
- const entityResultNumber4 = await entityLoader
105
- .withAuthorizationResults()
106
- .loadByFieldEqualingAsync('intField', 4);
107
- expect(entityResultNumber4).toBeNull();
108
-
109
- const entityResultDuplicateValues = await entityLoader
110
- .enforcing()
111
- .loadManyByFieldEqualingManyAsync('stringField', ['huh', 'huh']);
112
- expect(entityResultDuplicateValues.size).toBe(1);
113
- expect(entityResultDuplicateValues.get('huh')?.map((m) => m.getID())).toEqual([id1, id2]);
114
-
115
- await expect(
116
- entityLoader.withAuthorizationResults().loadByFieldEqualingAsync('stringField', 'huh'),
117
- ).rejects.toThrowError(
118
- 'loadByFieldEqualing: Multiple entities of type TestEntity found for stringField=huh',
119
- );
120
-
121
- await expect(
122
- entityLoader.withAuthorizationResults().loadByIDNullableAsync(uuidv4()),
123
- ).resolves.toBeNull();
124
- await expect(
125
- entityLoader.withAuthorizationResults().loadByIDNullableAsync(id1),
126
- ).resolves.not.toBeNull();
127
-
128
- const nonExistentId = uuidv4();
129
- const manyIdResults = await entityLoader
130
- .withAuthorizationResults()
131
- .loadManyByIDsNullableAsync([nonExistentId, id1]);
132
- expect(manyIdResults.get(nonExistentId)).toBeNull();
133
- expect(manyIdResults.get(id1)).not.toBeNull();
134
-
135
- await expect(
136
- enforceAsyncResult(entityLoader.withAuthorizationResults().loadByIDAsync(nonExistentId)),
137
- ).rejects.toThrow(EntityNotFoundError);
138
-
139
- await expect(
140
- entityLoader.withAuthorizationResults().loadByIDAsync('not-a-uuid'),
141
- ).rejects.toThrowError('Entity field not valid: TestEntity (customIdField = not-a-uuid)');
17
+ });
142
18
  });
143
19
 
144
- it('loads entities with loadManyByFieldEqualityConjunction', async () => {
145
- const privacyPolicy = new TestEntityPrivacyPolicy();
146
- const spiedPrivacyPolicy = spy(privacyPolicy);
147
- const viewerContext = instance(mock(ViewerContext));
148
- const privacyPolicyEvaluationContext =
149
- instance(
150
- mock<EntityPrivacyPolicyEvaluationContext<TestFields, string, ViewerContext, TestEntity>>(),
20
+ describe('withAuthorizationResults', () => {
21
+ it('creates a new AuthorizationResultBasedEntityLoader', async () => {
22
+ const companionProvider = createUnitTestEntityCompanionProvider();
23
+ const viewerContext = new ViewerContext(companionProvider);
24
+ expect(SimpleTestEntity.loader(viewerContext).withAuthorizationResults()).toBeInstanceOf(
25
+ AuthorizationResultBasedEntityLoader,
151
26
  );
152
- const metricsAdapter = instance(mock<IEntityMetricsAdapter>());
153
- const queryContext = StubQueryContextProvider.getQueryContext();
154
-
155
- const id1 = uuidv4();
156
- const id2 = uuidv4();
157
- const id3 = uuidv4();
158
- const databaseAdapter = new StubDatabaseAdapter<TestFields>(
159
- testEntityConfiguration,
160
- StubDatabaseAdapter.convertFieldObjectsToDataStore(
161
- testEntityConfiguration,
162
- new Map([
163
- [
164
- testEntityConfiguration.tableName,
165
- [
166
- {
167
- customIdField: id1,
168
- stringField: 'huh',
169
- intField: 4,
170
- testIndexedField: '4',
171
- dateField: new Date(),
172
- nullableField: null,
173
- },
174
- {
175
- customIdField: id2,
176
- stringField: 'huh',
177
- intField: 4,
178
- testIndexedField: '5',
179
- dateField: new Date(),
180
- nullableField: null,
181
- },
182
- {
183
- customIdField: id3,
184
- stringField: 'huh2',
185
- intField: 4,
186
- testIndexedField: '6',
187
- dateField: new Date(),
188
- nullableField: null,
189
- },
190
- ],
191
- ],
192
- ]),
193
- ),
194
- );
195
- const cacheAdapterProvider = new NoCacheStubCacheAdapterProvider();
196
- const cacheAdapter = cacheAdapterProvider.getCacheAdapter(testEntityConfiguration);
197
- const entityCache = new ReadThroughEntityCache(testEntityConfiguration, cacheAdapter);
198
- const dataManager = new EntityDataManager(
199
- databaseAdapter,
200
- entityCache,
201
- StubQueryContextProvider,
202
- instance(mock<IEntityMetricsAdapter>()),
203
- TestEntity.name,
204
- );
205
- const entityLoader = new EntityLoader(
206
- viewerContext,
207
- queryContext,
208
- privacyPolicyEvaluationContext,
209
- testEntityConfiguration,
210
- TestEntity,
211
- /* entitySelectedFields */ undefined,
212
- privacyPolicy,
213
- dataManager,
214
- metricsAdapter,
215
- );
216
- const entities = await enforceResultsAsync(
217
- entityLoader.withAuthorizationResults().loadManyByFieldEqualityConjunctionAsync([
218
- {
219
- fieldName: 'stringField',
220
- fieldValue: 'huh',
221
- },
222
- {
223
- fieldName: 'intField',
224
- fieldValues: [4],
225
- },
226
- ]),
227
- );
228
- expect(entities).toHaveLength(2);
229
- verify(
230
- spiedPrivacyPolicy.authorizeReadAsync(
231
- viewerContext,
232
- queryContext,
233
- privacyPolicyEvaluationContext,
234
- anyOfClass(TestEntity),
235
- anything(),
236
- ),
237
- ).twice();
238
-
239
- await expect(
240
- entityLoader
241
- .withAuthorizationResults()
242
- .loadManyByFieldEqualityConjunctionAsync([
243
- { fieldName: 'customIdField', fieldValue: 'not-a-uuid' },
244
- ]),
245
- ).rejects.toThrowError('Entity field not valid: TestEntity (customIdField = not-a-uuid)');
27
+ });
246
28
  });
247
29
 
248
- it('loads entities with loadFirstByFieldEqualityConjunction', async () => {
249
- const privacyPolicy = new TestEntityPrivacyPolicy();
250
- const spiedPrivacyPolicy = spy(privacyPolicy);
251
- const viewerContext = instance(mock(ViewerContext));
252
- const privacyPolicyEvaluationContext =
253
- instance(
254
- mock<EntityPrivacyPolicyEvaluationContext<TestFields, string, ViewerContext, TestEntity>>(),
255
- );
256
- const metricsAdapter = instance(mock<IEntityMetricsAdapter>());
257
- const queryContext = StubQueryContextProvider.getQueryContext();
258
-
259
- const id1 = uuidv4();
260
- const id2 = uuidv4();
261
- const id3 = uuidv4();
262
- const databaseAdapter = new StubDatabaseAdapter<TestFields>(
263
- testEntityConfiguration,
264
- StubDatabaseAdapter.convertFieldObjectsToDataStore(
265
- testEntityConfiguration,
266
- new Map([
267
- [
268
- testEntityConfiguration.tableName,
269
- [
270
- {
271
- customIdField: id1,
272
- stringField: 'huh',
273
- intField: 4,
274
- testIndexedField: '4',
275
- dateField: new Date(),
276
- nullableField: null,
277
- },
278
- {
279
- customIdField: id2,
280
- stringField: 'huh',
281
- intField: 4,
282
- testIndexedField: '5',
283
- dateField: new Date(),
284
- nullableField: null,
285
- },
286
- {
287
- customIdField: id3,
288
- stringField: 'huh2',
289
- intField: 4,
290
- testIndexedField: '6',
291
- dateField: new Date(),
292
- nullableField: null,
293
- },
294
- ],
295
- ],
296
- ]),
297
- ),
298
- );
299
- const cacheAdapterProvider = new NoCacheStubCacheAdapterProvider();
300
- const cacheAdapter = cacheAdapterProvider.getCacheAdapter(testEntityConfiguration);
301
- const entityCache = new ReadThroughEntityCache(testEntityConfiguration, cacheAdapter);
302
- const dataManager = new EntityDataManager(
303
- databaseAdapter,
304
- entityCache,
305
- StubQueryContextProvider,
306
- instance(mock<IEntityMetricsAdapter>()),
307
- TestEntity.name,
308
- );
309
- const entityLoader = new EntityLoader(
310
- viewerContext,
311
- queryContext,
312
- privacyPolicyEvaluationContext,
313
- testEntityConfiguration,
314
- TestEntity,
315
- /* entitySelectedFields */ undefined,
316
- privacyPolicy,
317
- dataManager,
318
- metricsAdapter,
319
- );
320
- const result = await entityLoader
321
- .withAuthorizationResults()
322
- .loadFirstByFieldEqualityConjunctionAsync(
323
- [
324
- {
325
- fieldName: 'stringField',
326
- fieldValue: 'huh',
327
- },
328
- {
329
- fieldName: 'intField',
330
- fieldValue: 4,
331
- },
332
- ],
333
- { orderBy: [{ fieldName: 'testIndexedField', order: OrderByOrdering.DESCENDING }] },
334
- );
335
- expect(result).not.toBeNull();
336
- expect(result!.ok).toBe(true);
337
- expect(result!.enforceValue().getField('testIndexedField')).toEqual('5');
338
- verify(
339
- spiedPrivacyPolicy.authorizeReadAsync(
340
- viewerContext,
341
- queryContext,
342
- privacyPolicyEvaluationContext,
343
- anyOfClass(TestEntity),
344
- anything(),
345
- ),
346
- ).once();
347
- });
348
-
349
- it('loads entities with loadManyByRawWhereClauseAsync', async () => {
350
- const privacyPolicy = new TestEntityPrivacyPolicy();
351
- const spiedPrivacyPolicy = spy(privacyPolicy);
352
- const viewerContext = instance(mock(ViewerContext));
353
- const privacyPolicyEvaluationContext =
354
- instance(
355
- mock<EntityPrivacyPolicyEvaluationContext<TestFields, string, ViewerContext, TestEntity>>(),
356
- );
357
- const metricsAdapter = instance(mock<IEntityMetricsAdapter>());
358
- const queryContext = StubQueryContextProvider.getQueryContext();
359
-
360
- const dataManagerMock = mock<EntityDataManager<TestFields>>(EntityDataManager);
361
- when(
362
- dataManagerMock.loadManyByRawWhereClauseAsync(
363
- queryContext,
364
- anything(),
365
- anything(),
366
- anything(),
367
- ),
368
- ).thenResolve([
369
- {
370
- customIdField: 'id',
371
- stringField: 'huh',
372
- intField: 4,
373
- testIndexedField: '4',
374
- dateField: new Date(),
375
- nullableField: null,
376
- },
377
- ]);
378
- const dataManager = instance(dataManagerMock);
379
- const entityLoader = new EntityLoader(
380
- viewerContext,
381
- queryContext,
382
- privacyPolicyEvaluationContext,
383
- testEntityConfiguration,
384
- TestEntity,
385
- /* entitySelectedFields */ undefined,
386
- privacyPolicy,
387
- dataManager,
388
- metricsAdapter,
389
- );
390
- const result = await entityLoader
391
- .withAuthorizationResults()
392
- .loadManyByRawWhereClauseAsync('id = ?', [1], {
393
- orderBy: [{ fieldName: 'testIndexedField', order: OrderByOrdering.DESCENDING }],
394
- });
395
- expect(result).toHaveLength(1);
396
- expect(result[0]).not.toBeNull();
397
- expect(result[0]!.ok).toBe(true);
398
- expect(result[0]!.enforceValue().getField('testIndexedField')).toEqual('4');
399
- verify(
400
- spiedPrivacyPolicy.authorizeReadAsync(
401
- viewerContext,
402
- queryContext,
403
- privacyPolicyEvaluationContext,
404
- anyOfClass(TestEntity),
405
- anything(),
406
- ),
407
- ).once();
408
- });
409
-
410
- it('authorizes loaded entities', async () => {
411
- const privacyPolicy = new TestEntityPrivacyPolicy();
412
- const spiedPrivacyPolicy = spy(privacyPolicy);
413
-
414
- const viewerContext = instance(mock(ViewerContext));
415
- const privacyPolicyEvaluationContext =
416
- instance(
417
- mock<EntityPrivacyPolicyEvaluationContext<TestFields, string, ViewerContext, TestEntity>>(),
418
- );
419
- const metricsAdapter = instance(mock<IEntityMetricsAdapter>());
420
- const queryContext = StubQueryContextProvider.getQueryContext();
421
-
422
- const id1 = uuidv4();
423
- const databaseAdapter = new StubDatabaseAdapter<TestFields>(
424
- testEntityConfiguration,
425
- StubDatabaseAdapter.convertFieldObjectsToDataStore(
426
- testEntityConfiguration,
427
- new Map([
428
- [
429
- testEntityConfiguration.tableName,
430
- [
431
- {
432
- customIdField: id1,
433
- stringField: 'huh',
434
- testIndexedField: '1',
435
- intField: 3,
436
- dateField: new Date(),
437
- nullableField: null,
438
- },
439
- ],
440
- ],
441
- ]),
442
- ),
443
- );
444
- const cacheAdapterProvider = new NoCacheStubCacheAdapterProvider();
445
- const cacheAdapter = cacheAdapterProvider.getCacheAdapter(testEntityConfiguration);
446
- const entityCache = new ReadThroughEntityCache(testEntityConfiguration, cacheAdapter);
447
- const dataManager = new EntityDataManager(
448
- databaseAdapter,
449
- entityCache,
450
- StubQueryContextProvider,
451
- instance(mock<IEntityMetricsAdapter>()),
452
- TestEntity.name,
453
- );
454
- const entityLoader = new EntityLoader(
455
- viewerContext,
456
- queryContext,
457
- privacyPolicyEvaluationContext,
458
- testEntityConfiguration,
459
- TestEntity,
460
- /* entitySelectedFields */ undefined,
461
- privacyPolicy,
462
- dataManager,
463
- metricsAdapter,
464
- );
465
- const entity = await enforceAsyncResult(
466
- entityLoader.withAuthorizationResults().loadByIDAsync(id1),
467
- );
468
- verify(
469
- spiedPrivacyPolicy.authorizeReadAsync(
470
- viewerContext,
471
- queryContext,
472
- privacyPolicyEvaluationContext,
473
- entity,
474
- anything(),
475
- ),
476
- ).once();
477
- });
478
-
479
- it('invalidates upon invalidate one', async () => {
480
- const viewerContext = instance(mock(ViewerContext));
481
- const privacyPolicyEvaluationContext =
482
- instance(
483
- mock<EntityPrivacyPolicyEvaluationContext<TestFields, string, ViewerContext, TestEntity>>(),
484
- );
485
- const metricsAdapter = instance(mock<IEntityMetricsAdapter>());
486
- const queryContext = StubQueryContextProvider.getQueryContext();
487
- const privacyPolicy = instance(mock(TestEntityPrivacyPolicy));
488
- const dataManagerMock = mock<EntityDataManager<TestFields>>();
489
- const dataManagerInstance = instance(dataManagerMock);
490
-
491
- const id1 = uuidv4();
492
- const entityLoader = new EntityLoader(
493
- viewerContext,
494
- queryContext,
495
- privacyPolicyEvaluationContext,
496
- testEntityConfiguration,
497
- TestEntity,
498
- /* entitySelectedFields */ undefined,
499
- privacyPolicy,
500
- dataManagerInstance,
501
- metricsAdapter,
502
- );
503
- await entityLoader.utils().invalidateFieldsAsync({ customIdField: id1 } as any);
504
-
505
- verify(
506
- dataManagerMock.invalidateObjectFieldsAsync(deepEqual({ customIdField: id1 } as any)),
507
- ).once();
508
- });
509
-
510
- it('invalidates upon invalidate by field', async () => {
511
- const viewerContext = instance(mock(ViewerContext));
512
- const privacyPolicyEvaluationContext =
513
- instance(
514
- mock<EntityPrivacyPolicyEvaluationContext<TestFields, string, ViewerContext, TestEntity>>(),
515
- );
516
- const metricsAdapter = instance(mock<IEntityMetricsAdapter>());
517
- const queryContext = StubQueryContextProvider.getQueryContext();
518
- const privacyPolicy = instance(mock(TestEntityPrivacyPolicy));
519
- const dataManagerMock = mock<EntityDataManager<TestFields>>();
520
- const dataManagerInstance = instance(dataManagerMock);
521
-
522
- const id1 = uuidv4();
523
- const entityLoader = new EntityLoader(
524
- viewerContext,
525
- queryContext,
526
- privacyPolicyEvaluationContext,
527
- testEntityConfiguration,
528
- TestEntity,
529
- /* entitySelectedFields */ undefined,
530
- privacyPolicy,
531
- dataManagerInstance,
532
- metricsAdapter,
533
- );
534
- await entityLoader.utils().invalidateFieldsAsync({ customIdField: id1 } as any);
535
- verify(
536
- dataManagerMock.invalidateObjectFieldsAsync(deepEqual({ customIdField: id1 } as any)),
537
- ).once();
538
- });
539
-
540
- it('invalidates upon invalidate by entity', async () => {
541
- const viewerContext = instance(mock(ViewerContext));
542
- const privacyPolicyEvaluationContext =
543
- instance(
544
- mock<EntityPrivacyPolicyEvaluationContext<TestFields, string, ViewerContext, TestEntity>>(),
545
- );
546
- const metricsAdapter = instance(mock<IEntityMetricsAdapter>());
547
- const queryContext = StubQueryContextProvider.getQueryContext();
548
- const privacyPolicy = instance(mock(TestEntityPrivacyPolicy));
549
- const dataManagerMock = mock<EntityDataManager<TestFields>>();
550
- const dataManagerInstance = instance(dataManagerMock);
551
-
552
- const id1 = uuidv4();
553
- const entityMock = mock(TestEntity);
554
- when(entityMock.getAllDatabaseFields()).thenReturn({ customIdField: id1 } as any);
555
- const entityInstance = instance(entityMock);
556
-
557
- const entityLoader = new EntityLoader(
558
- viewerContext,
559
- queryContext,
560
- privacyPolicyEvaluationContext,
561
- testEntityConfiguration,
562
- TestEntity,
563
- /* entitySelectedFields */ undefined,
564
- privacyPolicy,
565
- dataManagerInstance,
566
- metricsAdapter,
567
- );
568
- await entityLoader.utils().invalidateEntityAsync(entityInstance);
569
- verify(
570
- dataManagerMock.invalidateObjectFieldsAsync(deepEqual({ customIdField: id1 } as any)),
571
- ).once();
572
- });
573
-
574
- it('returns error result when not allowed', async () => {
575
- const viewerContext = instance(mock(ViewerContext));
576
- const privacyPolicyEvaluationContext =
577
- instance(
578
- mock<EntityPrivacyPolicyEvaluationContext<TestFields, string, ViewerContext, TestEntity>>(),
579
- );
580
- const metricsAdapter = instance(mock<IEntityMetricsAdapter>());
581
- const queryContext = StubQueryContextProvider.getQueryContext();
582
- const privacyPolicyMock = mock(TestEntityPrivacyPolicy);
583
- const dataManagerMock = mock<EntityDataManager<TestFields>>();
584
-
585
- const id1 = uuidv4();
586
- when(
587
- dataManagerMock.loadManyByFieldEqualingAsync(anything(), anything(), anything()),
588
- ).thenResolve(new Map().set(id1, [{ customIdField: id1 }]));
589
-
590
- const rejectionError = new Error();
591
-
592
- when(
593
- privacyPolicyMock.authorizeReadAsync(
594
- viewerContext,
595
- queryContext,
596
- privacyPolicyEvaluationContext,
597
- anyOfClass(TestEntity),
598
- anything(),
599
- ),
600
- ).thenReject(rejectionError);
601
-
602
- const privacyPolicy = instance(privacyPolicyMock);
603
- const dataManagerInstance = instance(dataManagerMock);
604
-
605
- const entityLoader = new EntityLoader(
606
- viewerContext,
607
- queryContext,
608
- privacyPolicyEvaluationContext,
609
- testEntityConfiguration,
610
- TestEntity,
611
- /* entitySelectedFields */ undefined,
612
- privacyPolicy,
613
- dataManagerInstance,
614
- metricsAdapter,
615
- );
616
-
617
- const entityResult = await entityLoader.withAuthorizationResults().loadByIDAsync(id1);
618
- expect(entityResult.ok).toBe(false);
619
- expect(entityResult.reason).toEqual(rejectionError);
620
- expect(entityResult.value).toBe(undefined);
621
- });
622
-
623
- it('throws upon database adapter error', async () => {
624
- const viewerContext = instance(mock(ViewerContext));
625
- const privacyPolicyEvaluationContext =
626
- instance(
627
- mock<EntityPrivacyPolicyEvaluationContext<TestFields, string, ViewerContext, TestEntity>>(),
628
- );
629
- const metricsAdapter = instance(mock<IEntityMetricsAdapter>());
630
- const queryContext = StubQueryContextProvider.getQueryContext();
631
- const privacyPolicy = instance(mock(TestEntityPrivacyPolicy));
632
- const dataManagerMock = mock<EntityDataManager<TestFields>>();
633
-
634
- const error = new Error();
635
-
636
- when(
637
- dataManagerMock.loadManyByFieldEqualingAsync(anything(), anything(), anything()),
638
- ).thenReject(error);
639
-
640
- const dataManagerInstance = instance(dataManagerMock);
641
-
642
- const entityLoader = new EntityLoader(
643
- viewerContext,
644
- queryContext,
645
- privacyPolicyEvaluationContext,
646
- testEntityConfiguration,
647
- TestEntity,
648
- /* entitySelectedFields */ undefined,
649
- privacyPolicy,
650
- dataManagerInstance,
651
- metricsAdapter,
652
- );
653
-
654
- const loadByValue = uuidv4();
655
-
656
- await expect(
657
- entityLoader.withAuthorizationResults().loadByIDAsync(loadByValue),
658
- ).rejects.toEqual(error);
659
- await expect(entityLoader.enforcing().loadByIDAsync(loadByValue)).rejects.toEqual(error);
660
- await expect(
661
- entityLoader.withAuthorizationResults().loadManyByIDsAsync([loadByValue]),
662
- ).rejects.toEqual(error);
663
- await expect(entityLoader.enforcing().loadManyByIDsAsync([loadByValue])).rejects.toEqual(error);
664
- await expect(
665
- entityLoader.withAuthorizationResults().loadManyByIDsNullableAsync([loadByValue]),
666
- ).rejects.toEqual(error);
667
- await expect(
668
- entityLoader.enforcing().loadManyByIDsNullableAsync([loadByValue]),
669
- ).rejects.toEqual(error);
670
- await expect(
671
- entityLoader
672
- .withAuthorizationResults()
673
- .loadManyByFieldEqualingAsync('customIdField', loadByValue),
674
- ).rejects.toEqual(error);
675
- await expect(
676
- entityLoader.enforcing().loadManyByFieldEqualingAsync('customIdField', loadByValue),
677
- ).rejects.toEqual(error);
678
- await expect(
679
- entityLoader
680
- .withAuthorizationResults()
681
- .loadManyByFieldEqualingManyAsync('customIdField', [loadByValue]),
682
- ).rejects.toEqual(error);
683
- await expect(
684
- entityLoader.enforcing().loadManyByFieldEqualingManyAsync('customIdField', [loadByValue]),
685
- ).rejects.toEqual(error);
30
+ describe('utils', () => {
31
+ it('returns a instance of EntityLoaderUtils', async () => {
32
+ const companionProvider = createUnitTestEntityCompanionProvider();
33
+ const viewerContext = new ViewerContext(companionProvider);
34
+ expect(SimpleTestEntity.loader(viewerContext).utils()).toBeInstanceOf(EntityLoaderUtils);
35
+ });
686
36
  });
687
37
  });