@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
@@ -0,0 +1,354 @@
1
+ import { enforceAsyncResult } from '@expo/results';
2
+ import { v4 as uuidv4 } from 'uuid';
3
+
4
+ import AuthorizationResultBasedEntityAssociationLoader from '../AuthorizationResultBasedEntityAssociationLoader';
5
+ import { enforceResultsAsync } from '../entityUtils';
6
+ import TestEntity from '../testfixtures/TestEntity';
7
+ import TestEntity2 from '../testfixtures/TestEntity2';
8
+ import TestViewerContext from '../testfixtures/TestViewerContext';
9
+ import { createUnitTestEntityCompanionProvider } from '../utils/testing/createUnitTestEntityCompanionProvider';
10
+
11
+ describe(AuthorizationResultBasedEntityAssociationLoader, () => {
12
+ describe('loadAssociatedEntityAsync', () => {
13
+ it('loads associated entities by ID and correctly handles a null value', async () => {
14
+ const companionProvider = createUnitTestEntityCompanionProvider();
15
+ const viewerContext = new TestViewerContext(companionProvider);
16
+ const testOtherEntity = await enforceAsyncResult(
17
+ TestEntity.creator(viewerContext).withAuthorizationResults().createAsync(),
18
+ );
19
+ const testEntity = await enforceAsyncResult(
20
+ TestEntity.creator(viewerContext)
21
+ .withAuthorizationResults()
22
+ .setField('stringField', testOtherEntity.getID())
23
+ .createAsync(),
24
+ );
25
+ const loadedOther = await enforceAsyncResult(
26
+ testEntity
27
+ .associationLoader()
28
+ .withAuthorizationResults()
29
+ .loadAssociatedEntityAsync('stringField', TestEntity),
30
+ );
31
+ expect(loadedOther.getID()).toEqual(testOtherEntity.getID());
32
+
33
+ const loadedOther2 = await enforceAsyncResult(
34
+ testEntity
35
+ .associationLoader()
36
+ .withAuthorizationResults()
37
+ .loadAssociatedEntityAsync('nullableField', TestEntity),
38
+ );
39
+ expect(loadedOther2).toBeNull();
40
+ });
41
+ });
42
+
43
+ describe('loadManyAssociatedEntitiesAsync', () => {
44
+ it('loads many associated entities referencing this entity', async () => {
45
+ const companionProvider = createUnitTestEntityCompanionProvider();
46
+ const viewerContext = new TestViewerContext(companionProvider);
47
+ const testEntity = await enforceAsyncResult(
48
+ TestEntity.creator(viewerContext).withAuthorizationResults().createAsync(),
49
+ );
50
+ const testOtherEntity1 = await enforceAsyncResult(
51
+ TestEntity.creator(viewerContext)
52
+ .withAuthorizationResults()
53
+ .setField('stringField', testEntity.getID())
54
+ .createAsync(),
55
+ );
56
+ const testOtherEntity2 = await enforceAsyncResult(
57
+ TestEntity.creator(viewerContext)
58
+ .withAuthorizationResults()
59
+ .setField('stringField', testEntity.getID())
60
+ .createAsync(),
61
+ );
62
+ const loaded = await enforceResultsAsync(
63
+ testEntity
64
+ .associationLoader()
65
+ .withAuthorizationResults()
66
+ .loadManyAssociatedEntitiesAsync(TestEntity, 'stringField'),
67
+ );
68
+ expect(loaded).toHaveLength(2);
69
+ expect(loaded.find((e) => e.getID() === testOtherEntity1.getID())).not.toBeUndefined();
70
+ expect(loaded.find((e) => e.getID() === testOtherEntity2.getID())).not.toBeUndefined();
71
+ });
72
+ });
73
+
74
+ describe('loadAssociatedEntityByFieldEqualingAsync', () => {
75
+ it('loads associated entity by field equaling', async () => {
76
+ const companionProvider = createUnitTestEntityCompanionProvider();
77
+ const viewerContext = new TestViewerContext(companionProvider);
78
+ const testOtherEntity = await enforceAsyncResult(
79
+ TestEntity.creator(viewerContext).withAuthorizationResults().createAsync(),
80
+ );
81
+ const testEntity = await enforceAsyncResult(
82
+ TestEntity.creator(viewerContext)
83
+ .withAuthorizationResults()
84
+ .setField('stringField', testOtherEntity.getID())
85
+ .createAsync(),
86
+ );
87
+ const loadedOtherResult = await testEntity
88
+ .associationLoader()
89
+ .withAuthorizationResults()
90
+ .loadAssociatedEntityByFieldEqualingAsync('stringField', TestEntity, 'customIdField');
91
+ expect(loadedOtherResult?.enforceValue().getID()).toEqual(testOtherEntity.getID());
92
+ });
93
+
94
+ it('returns null when loading associated entities by field equaling a non existent association', async () => {
95
+ const companionProvider = createUnitTestEntityCompanionProvider();
96
+ const viewerContext = new TestViewerContext(companionProvider);
97
+ const testEntity = await enforceAsyncResult(
98
+ TestEntity.creator(viewerContext)
99
+ .withAuthorizationResults()
100
+ .setField('stringField', uuidv4())
101
+ .createAsync(),
102
+ );
103
+ const loadedOtherResult = await testEntity
104
+ .associationLoader()
105
+ .withAuthorizationResults()
106
+ .loadAssociatedEntityByFieldEqualingAsync('stringField', TestEntity, 'customIdField');
107
+ expect(loadedOtherResult).toBeNull();
108
+ });
109
+
110
+ it('returns null when load-by field is null', async () => {
111
+ const companionProvider = createUnitTestEntityCompanionProvider();
112
+ const viewerContext = new TestViewerContext(companionProvider);
113
+ const testEntity = await enforceAsyncResult(
114
+ TestEntity.creator(viewerContext)
115
+ .withAuthorizationResults()
116
+ .setField('stringField', 'blah')
117
+ .createAsync(),
118
+ );
119
+ const loadedOtherResult = await testEntity
120
+ .associationLoader()
121
+ .withAuthorizationResults()
122
+ .loadAssociatedEntityByFieldEqualingAsync('nullableField', TestEntity, 'customIdField');
123
+ expect(loadedOtherResult).toBeNull();
124
+ });
125
+ });
126
+
127
+ describe('loadManyAssociatedEntitiesByFieldEqualingAsync', () => {
128
+ it('loads many associated entities by field equaling', async () => {
129
+ const companionProvider = createUnitTestEntityCompanionProvider();
130
+ const viewerContext = new TestViewerContext(companionProvider);
131
+ const testEntity = await enforceAsyncResult(
132
+ TestEntity.creator(viewerContext).withAuthorizationResults().createAsync(),
133
+ );
134
+ const testOtherEntity1 = await enforceAsyncResult(
135
+ TestEntity.creator(viewerContext)
136
+ .withAuthorizationResults()
137
+ .setField('stringField', testEntity.getID())
138
+ .createAsync(),
139
+ );
140
+ const testOtherEntity2 = await enforceAsyncResult(
141
+ TestEntity.creator(viewerContext)
142
+ .withAuthorizationResults()
143
+ .setField('stringField', testEntity.getID())
144
+ .createAsync(),
145
+ );
146
+ const loaded = await enforceResultsAsync(
147
+ testEntity
148
+ .associationLoader()
149
+ .withAuthorizationResults()
150
+ .loadManyAssociatedEntitiesByFieldEqualingAsync(
151
+ 'customIdField',
152
+ TestEntity,
153
+ 'stringField',
154
+ ),
155
+ );
156
+ expect(loaded).toHaveLength(2);
157
+ expect(loaded.find((e) => e.getID() === testOtherEntity1.getID())).not.toBeUndefined();
158
+ expect(loaded.find((e) => e.getID() === testOtherEntity2.getID())).not.toBeUndefined();
159
+ });
160
+
161
+ it('returns empty results when field being queried by is null', async () => {
162
+ const companionProvider = createUnitTestEntityCompanionProvider();
163
+ const viewerContext = new TestViewerContext(companionProvider);
164
+ const testEntity = await enforceAsyncResult(
165
+ TestEntity.creator(viewerContext).withAuthorizationResults().createAsync(),
166
+ );
167
+ const loaded = await enforceResultsAsync(
168
+ testEntity
169
+ .associationLoader()
170
+ .withAuthorizationResults()
171
+ .loadManyAssociatedEntitiesByFieldEqualingAsync(
172
+ 'nullableField',
173
+ TestEntity,
174
+ 'stringField',
175
+ ),
176
+ );
177
+ expect(loaded).toHaveLength(0);
178
+ });
179
+ });
180
+
181
+ describe('loadAssociatedEntityThroughAsync', () => {
182
+ it('chain loads associated entities', async () => {
183
+ const companionProvider = createUnitTestEntityCompanionProvider();
184
+ const viewerContext = new TestViewerContext(companionProvider);
185
+ const testEntity4 = await enforceAsyncResult(
186
+ TestEntity.creator(viewerContext).withAuthorizationResults().createAsync(),
187
+ );
188
+ const testEntity3 = await enforceAsyncResult(
189
+ TestEntity2.creator(viewerContext)
190
+ .withAuthorizationResults()
191
+ .setField('foreignKey', testEntity4.getID())
192
+ .createAsync(),
193
+ );
194
+ const testEntity2 = await enforceAsyncResult(
195
+ TestEntity.creator(viewerContext)
196
+ .withAuthorizationResults()
197
+ .setField('testIndexedField', testEntity3.getID())
198
+ .createAsync(),
199
+ );
200
+ const testEntity = await enforceAsyncResult(
201
+ TestEntity2.creator(viewerContext)
202
+ .withAuthorizationResults()
203
+ .setField('foreignKey', testEntity2.getID())
204
+ .createAsync(),
205
+ );
206
+
207
+ const loaded2Result = await testEntity
208
+ .associationLoader()
209
+ .withAuthorizationResults()
210
+ .loadAssociatedEntityThroughAsync([
211
+ {
212
+ associatedEntityClass: TestEntity,
213
+ fieldIdentifyingAssociatedEntity: 'foreignKey',
214
+ },
215
+ ]);
216
+ expect(loaded2Result?.enforceValue().getID()).toEqual(testEntity2.getID());
217
+
218
+ const loaded3Result = await testEntity
219
+ .associationLoader()
220
+ .withAuthorizationResults()
221
+ .loadAssociatedEntityThroughAsync([
222
+ {
223
+ associatedEntityClass: TestEntity,
224
+ fieldIdentifyingAssociatedEntity: 'foreignKey',
225
+ },
226
+ {
227
+ associatedEntityClass: TestEntity2,
228
+ fieldIdentifyingAssociatedEntity: 'testIndexedField',
229
+ },
230
+ ]);
231
+ expect(loaded3Result?.enforceValue().getID()).toEqual(testEntity3.getID());
232
+
233
+ const loaded4Result = await testEntity
234
+ .associationLoader()
235
+ .withAuthorizationResults()
236
+ .loadAssociatedEntityThroughAsync([
237
+ {
238
+ associatedEntityClass: TestEntity,
239
+ fieldIdentifyingAssociatedEntity: 'foreignKey',
240
+ },
241
+ {
242
+ associatedEntityClass: TestEntity2,
243
+ fieldIdentifyingAssociatedEntity: 'testIndexedField',
244
+ },
245
+ {
246
+ associatedEntityClass: TestEntity,
247
+ fieldIdentifyingAssociatedEntity: 'foreignKey',
248
+ },
249
+ ]);
250
+ expect(loaded4Result?.enforceValue().getID()).toEqual(testEntity4.getID());
251
+ });
252
+
253
+ it('fails when chain loading associated entity fails', async () => {
254
+ const companionProvider = createUnitTestEntityCompanionProvider();
255
+ const viewerContext = new TestViewerContext(companionProvider);
256
+
257
+ const testEntity = await enforceAsyncResult(
258
+ TestEntity2.creator(viewerContext)
259
+ .withAuthorizationResults()
260
+ .setField('foreignKey', uuidv4())
261
+ .createAsync(),
262
+ );
263
+
264
+ const loadResult = await testEntity
265
+ .associationLoader()
266
+ .withAuthorizationResults()
267
+ .loadAssociatedEntityThroughAsync([
268
+ {
269
+ associatedEntityClass: TestEntity,
270
+ fieldIdentifyingAssociatedEntity: 'foreignKey',
271
+ },
272
+ ]);
273
+ expect(loadResult?.ok).toBe(false);
274
+ });
275
+
276
+ it('supports chain loading by field equality', async () => {
277
+ const companionProvider = createUnitTestEntityCompanionProvider();
278
+ const viewerContext = new TestViewerContext(companionProvider);
279
+
280
+ const fieldValue = uuidv4();
281
+ const testEntity2 = await enforceAsyncResult(
282
+ TestEntity.creator(viewerContext)
283
+ .withAuthorizationResults()
284
+ .setField('stringField', fieldValue)
285
+ .createAsync(),
286
+ );
287
+ const testEntity = await enforceAsyncResult(
288
+ TestEntity2.creator(viewerContext)
289
+ .withAuthorizationResults()
290
+ .setField('foreignKey', fieldValue)
291
+ .createAsync(),
292
+ );
293
+
294
+ const loaded2Result = await testEntity
295
+ .associationLoader()
296
+ .withAuthorizationResults()
297
+ .loadAssociatedEntityThroughAsync([
298
+ {
299
+ associatedEntityClass: TestEntity,
300
+ fieldIdentifyingAssociatedEntity: 'foreignKey',
301
+ associatedEntityLookupByField: 'stringField',
302
+ },
303
+ ]);
304
+ expect(loaded2Result?.enforceValue().getID()).toEqual(testEntity2.getID());
305
+ });
306
+
307
+ it('returns null when chain loading by field equality returns null', async () => {
308
+ const companionProvider = createUnitTestEntityCompanionProvider();
309
+ const viewerContext = new TestViewerContext(companionProvider);
310
+
311
+ const testEntity = await enforceAsyncResult(
312
+ TestEntity2.creator(viewerContext)
313
+ .withAuthorizationResults()
314
+ .setField('foreignKey', uuidv4())
315
+ .createAsync(),
316
+ );
317
+
318
+ const loaded2Result = await testEntity
319
+ .associationLoader()
320
+ .withAuthorizationResults()
321
+ .loadAssociatedEntityThroughAsync([
322
+ {
323
+ associatedEntityClass: TestEntity,
324
+ fieldIdentifyingAssociatedEntity: 'foreignKey',
325
+ associatedEntityLookupByField: 'stringField',
326
+ },
327
+ ]);
328
+ expect(loaded2Result).toBeNull();
329
+ });
330
+
331
+ it('returns null when chain loading by field is null', async () => {
332
+ const companionProvider = createUnitTestEntityCompanionProvider();
333
+ const viewerContext = new TestViewerContext(companionProvider);
334
+
335
+ const testEntity = await enforceAsyncResult(
336
+ TestEntity.creator(viewerContext)
337
+ .withAuthorizationResults()
338
+ .setField('nullableField', null)
339
+ .createAsync(),
340
+ );
341
+
342
+ const loadedResult = await testEntity
343
+ .associationLoader()
344
+ .withAuthorizationResults()
345
+ .loadAssociatedEntityThroughAsync([
346
+ {
347
+ associatedEntityClass: TestEntity,
348
+ fieldIdentifyingAssociatedEntity: 'nullableField',
349
+ },
350
+ ]);
351
+ expect(loadedResult).toBeNull();
352
+ });
353
+ });
354
+ });
@@ -1,10 +1,11 @@
1
1
  import { instance, mock } from 'ts-mockito';
2
2
 
3
+ import AuthorizationResultBasedEntityLoader from '../AuthorizationResultBasedEntityLoader';
3
4
  import Entity from '../Entity';
4
5
  import { EntityCompanionDefinition } from '../EntityCompanionProvider';
5
6
  import EntityConfiguration from '../EntityConfiguration';
6
7
  import { StringField } from '../EntityFields';
7
- import EntityLoader from '../EntityLoader';
8
+ import EntityLoaderUtils from '../EntityLoaderUtils';
8
9
  import EntityPrivacyPolicy, { EntityPrivacyPolicyEvaluationContext } from '../EntityPrivacyPolicy';
9
10
  import ViewerContext from '../ViewerContext';
10
11
  import EntityDataManager from '../internal/EntityDataManager';
@@ -94,7 +95,7 @@ export default class TestEntity extends Entity<
94
95
  selectedFields: Readonly<TestFields>;
95
96
  }) {
96
97
  if (constructorParams.selectedFields.id === ID_SENTINEL_THROW_LITERAL) {
97
- // eslint-disable-next-line no-throw-literal,@typescript-eslint/no-throw-literal
98
+ // eslint-disable-next-line no-throw-literal,@typescript-eslint/only-throw-error
98
99
  throw 'hello';
99
100
  } else if (constructorParams.selectedFields.id === ID_SENTINEL_THROW_ERROR) {
100
101
  throw new Error('world');
@@ -118,7 +119,7 @@ export default class TestEntity extends Entity<
118
119
  }
119
120
  }
120
121
 
121
- describe(EntityLoader, () => {
122
+ describe(AuthorizationResultBasedEntityLoader, () => {
122
123
  it('handles thrown errors and literals from constructor', async () => {
123
124
  const viewerContext = instance(mock(ViewerContext));
124
125
  const privacyPolicyEvaluationContext =
@@ -134,7 +135,7 @@ describe(EntityLoader, () => {
134
135
  >(),
135
136
  );
136
137
  const metricsAdapter = instance(mock<IEntityMetricsAdapter>());
137
- const queryContext = StubQueryContextProvider.getQueryContext();
138
+ const queryContext = new StubQueryContextProvider().getQueryContext();
138
139
 
139
140
  const databaseAdapter = new StubDatabaseAdapter<TestFields>(
140
141
  testEntityConfiguration,
@@ -162,11 +163,11 @@ describe(EntityLoader, () => {
162
163
  const dataManager = new EntityDataManager(
163
164
  databaseAdapter,
164
165
  entityCache,
165
- StubQueryContextProvider,
166
+ new StubQueryContextProvider(),
166
167
  metricsAdapter,
167
168
  TestEntity.name,
168
169
  );
169
- const entityLoader = new EntityLoader(
170
+ const utils = new EntityLoaderUtils(
170
171
  viewerContext,
171
172
  queryContext,
172
173
  privacyPolicyEvaluationContext,
@@ -177,19 +178,25 @@ describe(EntityLoader, () => {
177
178
  dataManager,
178
179
  metricsAdapter,
179
180
  );
181
+ const entityLoader = new AuthorizationResultBasedEntityLoader(
182
+ queryContext,
183
+ testEntityConfiguration,
184
+ TestEntity,
185
+ dataManager,
186
+ metricsAdapter,
187
+ utils,
188
+ );
180
189
 
181
190
  let capturedThrownThing1: any;
182
191
  try {
183
- await entityLoader.withAuthorizationResults().loadByIDAsync(ID_SENTINEL_THROW_LITERAL);
192
+ await entityLoader.loadByIDAsync(ID_SENTINEL_THROW_LITERAL);
184
193
  } catch (e) {
185
194
  capturedThrownThing1 = e;
186
195
  }
187
196
  expect(capturedThrownThing1).not.toBeInstanceOf(Error);
188
197
  expect(capturedThrownThing1).toEqual('hello');
189
198
 
190
- const result = await entityLoader
191
- .withAuthorizationResults()
192
- .loadByIDAsync(ID_SENTINEL_THROW_ERROR);
199
+ const result = await entityLoader.loadByIDAsync(ID_SENTINEL_THROW_ERROR);
193
200
  expect(result.ok).toBe(false);
194
201
  expect(result.enforceError().message).toEqual('world');
195
202
  });