@expo/entity 0.26.1 → 0.28.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 (106) hide show
  1. package/LICENSE +21 -0
  2. package/build/ComposedEntityCacheAdapter.d.ts +1 -1
  3. package/build/ComposedEntityCacheAdapter.js +1 -1
  4. package/build/ComposedSecondaryEntityCache.d.ts +1 -1
  5. package/build/ComposedSecondaryEntityCache.js +1 -1
  6. package/build/EnforcingEntityLoader.d.ts +10 -10
  7. package/build/EnforcingEntityLoader.js +8 -8
  8. package/build/EnforcingEntityLoader.js.map +1 -1
  9. package/build/Entity.d.ts +5 -5
  10. package/build/Entity.js +5 -5
  11. package/build/EntityAssociationLoader.d.ts +4 -4
  12. package/build/EntityCacheAdapter.d.ts +1 -1
  13. package/build/EntityCompanion.d.ts +1 -1
  14. package/build/EntityCompanion.js +1 -1
  15. package/build/EntityCompanionProvider.d.ts +9 -9
  16. package/build/EntityCompanionProvider.js +3 -3
  17. package/build/EntityConfiguration.d.ts +2 -2
  18. package/build/EntityDatabaseAdapter.d.ts +25 -6
  19. package/build/EntityDatabaseAdapter.js +8 -2
  20. package/build/EntityDatabaseAdapter.js.map +1 -1
  21. package/build/EntityFieldDefinition.d.ts +2 -2
  22. package/build/EntityFields.d.ts +9 -22
  23. package/build/EntityFields.js +10 -29
  24. package/build/EntityFields.js.map +1 -1
  25. package/build/EntityLoader.d.ts +10 -10
  26. package/build/EntityLoader.js +8 -8
  27. package/build/EntityLoader.js.map +1 -1
  28. package/build/EntityMutationTriggerConfiguration.d.ts +1 -1
  29. package/build/EntityMutationTriggerConfiguration.js +1 -1
  30. package/build/EntityMutator.d.ts +1 -1
  31. package/build/EntityMutator.js +1 -1
  32. package/build/EntityPrivacyPolicy.d.ts +6 -6
  33. package/build/EntityPrivacyPolicy.js +6 -6
  34. package/build/EntityQueryContext.d.ts +23 -3
  35. package/build/EntityQueryContext.js +43 -6
  36. package/build/EntityQueryContext.js.map +1 -1
  37. package/build/EntityQueryContextProvider.d.ts +10 -2
  38. package/build/EntityQueryContextProvider.js +18 -1
  39. package/build/EntityQueryContextProvider.js.map +1 -1
  40. package/build/EntitySecondaryCacheLoader.d.ts +1 -1
  41. package/build/EntitySecondaryCacheLoader.js +1 -1
  42. package/build/GenericSecondaryEntityCache.d.ts +1 -1
  43. package/build/GenericSecondaryEntityCache.js +1 -1
  44. package/build/ReadonlyEntity.d.ts +1 -1
  45. package/build/ReadonlyEntity.js +1 -1
  46. package/build/ViewerContext.d.ts +2 -2
  47. package/build/ViewerContext.js +2 -2
  48. package/build/ViewerScopedEntityCompanion.d.ts +2 -2
  49. package/build/ViewerScopedEntityCompanion.js +2 -2
  50. package/build/ViewerScopedEntityLoaderFactory.d.ts +1 -1
  51. package/build/ViewerScopedEntityLoaderFactory.js +1 -1
  52. package/build/ViewerScopedEntityMutatorFactory.d.ts +1 -1
  53. package/build/ViewerScopedEntityMutatorFactory.js +1 -1
  54. package/build/__tests__/EntityFields-test.js +0 -4
  55. package/build/__tests__/EntityFields-test.js.map +1 -1
  56. package/build/__tests__/EntityQueryContext-test.js +39 -0
  57. package/build/__tests__/EntityQueryContext-test.js.map +1 -1
  58. package/build/internal/EntityDataManager.d.ts +5 -5
  59. package/build/internal/EntityDataManager.js +3 -3
  60. package/build/internal/EntityDataManager.js.map +1 -1
  61. package/build/internal/ReadThroughEntityCache.d.ts +2 -2
  62. package/build/internal/ReadThroughEntityCache.js +2 -2
  63. package/build/metrics/IEntityMetricsAdapter.d.ts +10 -10
  64. package/build/rules/PrivacyPolicyRule.d.ts +1 -1
  65. package/build/rules/PrivacyPolicyRule.js +1 -1
  66. package/build/utils/collections/maps.d.ts +1 -1
  67. package/build/utils/collections/maps.js +1 -1
  68. package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +1 -2
  69. package/build/utils/testing/StubQueryContextProvider.d.ts +2 -1
  70. package/build/utils/testing/StubQueryContextProvider.js +5 -0
  71. package/build/utils/testing/StubQueryContextProvider.js.map +1 -1
  72. package/package.json +3 -2
  73. package/src/ComposedEntityCacheAdapter.ts +1 -1
  74. package/src/ComposedSecondaryEntityCache.ts +1 -1
  75. package/src/EnforcingEntityLoader.ts +14 -10
  76. package/src/Entity.ts +5 -5
  77. package/src/EntityAssociationLoader.ts +4 -4
  78. package/src/EntityCacheAdapter.ts +1 -1
  79. package/src/EntityCompanion.ts +1 -1
  80. package/src/EntityCompanionProvider.ts +9 -9
  81. package/src/EntityConfiguration.ts +2 -2
  82. package/src/EntityDatabaseAdapter.ts +43 -6
  83. package/src/EntityFieldDefinition.ts +2 -2
  84. package/src/EntityFields.ts +9 -28
  85. package/src/EntityLoader.ts +10 -9
  86. package/src/EntityMutationTriggerConfiguration.ts +1 -1
  87. package/src/EntityMutator.ts +1 -1
  88. package/src/EntityPrivacyPolicy.ts +6 -6
  89. package/src/EntityQueryContext.ts +63 -3
  90. package/src/EntityQueryContextProvider.ts +34 -2
  91. package/src/EntitySecondaryCacheLoader.ts +1 -1
  92. package/src/GenericSecondaryEntityCache.ts +1 -1
  93. package/src/ReadonlyEntity.ts +1 -1
  94. package/src/ViewerContext.ts +2 -2
  95. package/src/ViewerScopedEntityCompanion.ts +2 -2
  96. package/src/ViewerScopedEntityLoaderFactory.ts +1 -1
  97. package/src/ViewerScopedEntityMutatorFactory.ts +1 -1
  98. package/src/__tests__/EntityFields-test.ts +0 -12
  99. package/src/__tests__/EntityQueryContext-test.ts +50 -0
  100. package/src/internal/EntityDataManager.ts +5 -4
  101. package/src/internal/ReadThroughEntityCache.ts +2 -2
  102. package/src/metrics/IEntityMetricsAdapter.ts +10 -10
  103. package/src/rules/PrivacyPolicyRule.ts +1 -1
  104. package/src/utils/collections/maps.ts +1 -1
  105. package/src/utils/testing/PrivacyPolicyRuleTestUtils.ts +1 -1
  106. package/src/utils/testing/StubQueryContextProvider.ts +7 -1
@@ -12,7 +12,7 @@ export type PreCommitCallback = (
12
12
  * Entity framework representation of transactional and non-transactional database
13
13
  * query execution units.
14
14
  *
15
- * The behavior of {@link EntityMutator} and {@link EntityLoader}
15
+ * The behavior of EntityMutator and EntityLoader
16
16
  * differs when in a transactional context.
17
17
  */
18
18
  export abstract class EntityQueryContext {
@@ -31,7 +31,7 @@ export abstract class EntityQueryContext {
31
31
 
32
32
  /**
33
33
  * Entity framework representation of a non-transactional query execution unit.
34
- * When supplied to {@link EntityMutator} and {@link EntityLoader} methods, they will be
34
+ * When supplied to EntityMutator and EntityLoader methods, they will be
35
35
  * run independently of any running transaction (though mutations start their own
36
36
  * independent transactions internally when not being run in a transaction).
37
37
  */
@@ -56,7 +56,7 @@ export class EntityNonTransactionalQueryContext extends EntityQueryContext {
56
56
 
57
57
  /**
58
58
  * Entity framework representation of a transactional query execution unit. When supplied
59
- * to {@link EntityMutator} and {@link EntityLoader} methods, those methods and their
59
+ * to EntityMutator and EntityLoader methods, those methods and their
60
60
  * dependent triggers and validators will run within the transaction.
61
61
  */
62
62
  export class EntityTransactionalQueryContext extends EntityQueryContext {
@@ -65,6 +65,13 @@ export class EntityTransactionalQueryContext extends EntityQueryContext {
65
65
 
66
66
  private readonly preCommitCallbacks: { callback: PreCommitCallback; order: number }[] = [];
67
67
 
68
+ constructor(
69
+ queryInterface: any,
70
+ private readonly entityQueryContextProvider: EntityQueryContextProvider
71
+ ) {
72
+ super(queryInterface);
73
+ }
74
+
68
75
  /**
69
76
  * Schedule a pre-commit callback. These will be run within the transaction right before it is
70
77
  * committed, and will be run in the order specified. Ordering of callbacks scheduled with the
@@ -129,4 +136,57 @@ export class EntityTransactionalQueryContext extends EntityQueryContext {
129
136
  ): Promise<T> {
130
137
  return await transactionScope(this);
131
138
  }
139
+
140
+ async runInNestedTransactionAsync<T>(
141
+ transactionScope: (innerQueryContext: EntityTransactionalQueryContext) => Promise<T>
142
+ ): Promise<T> {
143
+ return await this.entityQueryContextProvider.runInNestedTransactionAsync(
144
+ this,
145
+ transactionScope
146
+ );
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Entity framework representation of a nested transactional query execution unit. When supplied
152
+ * to EntityMutator and EntityLoader methods, those methods and their
153
+ * dependent triggers and validators will run within the nested transaction.
154
+ *
155
+ * This exists to forward post-commit callbacks to the parent query context.
156
+ */
157
+ export class EntityNestedTransactionalQueryContext extends EntityTransactionalQueryContext {
158
+ private readonly postCommitInvalidationCallbacksToTransfer: PostCommitCallback[] = [];
159
+ private readonly postCommitCallbacksToTransfer: PostCommitCallback[] = [];
160
+
161
+ constructor(
162
+ queryInterface: any,
163
+ private readonly parentQueryContext: EntityTransactionalQueryContext,
164
+ entityQueryContextProvider: EntityQueryContextProvider
165
+ ) {
166
+ super(queryInterface, entityQueryContextProvider);
167
+ }
168
+
169
+ public override appendPostCommitCallback(callback: PostCommitCallback): void {
170
+ this.postCommitInvalidationCallbacksToTransfer.push(callback);
171
+ }
172
+
173
+ public override appendPostCommitInvalidationCallback(callback: PostCommitCallback): void {
174
+ this.postCommitCallbacksToTransfer.push(callback);
175
+ }
176
+
177
+ public override runPostCommitCallbacksAsync(): Promise<void> {
178
+ throw new Error(
179
+ 'Must not call runPostCommitCallbacksAsync on EntityNestedTransactionalQueryContext'
180
+ );
181
+ }
182
+
183
+ public transferPostCommitCallbacksToParent(): void {
184
+ for (const callback of this.postCommitInvalidationCallbacksToTransfer) {
185
+ this.parentQueryContext.appendPostCommitInvalidationCallback(callback);
186
+ }
187
+
188
+ for (const callback of this.postCommitCallbacksToTransfer) {
189
+ this.parentQueryContext.appendPostCommitCallback(callback);
190
+ }
191
+ }
132
192
  }
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  EntityTransactionalQueryContext,
3
3
  EntityNonTransactionalQueryContext,
4
+ EntityNestedTransactionalQueryContext,
4
5
  } from './EntityQueryContext';
5
6
 
6
7
  /**
@@ -20,12 +21,16 @@ export default abstract class EntityQueryContextProvider {
20
21
  protected abstract getQueryInterface(): any;
21
22
 
22
23
  /**
23
- * Vend a transaction runner for use in {@link runInTransactionAsync}.
24
+ * Vend a transaction runner for use in runInTransactionAsync.
24
25
  */
25
26
  protected abstract createTransactionRunner<T>(): (
26
27
  transactionScope: (queryInterface: any) => Promise<T>
27
28
  ) => Promise<T>;
28
29
 
30
+ protected abstract createNestedTransactionRunner<T>(
31
+ outerQueryInterface: any
32
+ ): (transactionScope: (queryInterface: any) => Promise<T>) => Promise<T>;
33
+
29
34
  /**
30
35
  * Start a transaction and execute the provided transaction-scoped closure within the transaction.
31
36
  * @param transactionScope - async callback to execute within the transaction
@@ -36,7 +41,7 @@ export default abstract class EntityQueryContextProvider {
36
41
  const [returnedValue, queryContext] = await this.createTransactionRunner<
37
42
  [T, EntityTransactionalQueryContext]
38
43
  >()(async (queryInterface) => {
39
- const queryContext = new EntityTransactionalQueryContext(queryInterface);
44
+ const queryContext = new EntityTransactionalQueryContext(queryInterface, this);
40
45
  const result = await transactionScope(queryContext);
41
46
  await queryContext.runPreCommitCallbacksAsync();
42
47
  return [result, queryContext];
@@ -44,4 +49,31 @@ export default abstract class EntityQueryContextProvider {
44
49
  await queryContext.runPostCommitCallbacksAsync();
45
50
  return returnedValue;
46
51
  }
52
+
53
+ /**
54
+ * Start a nested transaction from the specified parent transaction and execure the
55
+ * provided nested-transaction-scoped closure within the nested transaction.
56
+ * @param outerQueryContext - the query context of the parent transaction
57
+ * @param transactionScope - async callback to execute within the nested transaction
58
+ */
59
+ async runInNestedTransactionAsync<T>(
60
+ outerQueryContext: EntityTransactionalQueryContext,
61
+ transactionScope: (innerQueryContext: EntityNestedTransactionalQueryContext) => Promise<T>
62
+ ): Promise<T> {
63
+ const [returnedValue, innerQueryContext] = await this.createNestedTransactionRunner<
64
+ [T, EntityNestedTransactionalQueryContext]
65
+ >(outerQueryContext.getQueryInterface())(async (innerQueryInterface) => {
66
+ const innerQueryContext = new EntityNestedTransactionalQueryContext(
67
+ innerQueryInterface,
68
+ outerQueryContext,
69
+ this
70
+ );
71
+ const result = await transactionScope(innerQueryContext);
72
+ await innerQueryContext.runPreCommitCallbacksAsync();
73
+ return [result, innerQueryContext];
74
+ });
75
+ // post-commit callbacks are appended to parent transaction instead of run, but only after the transaction has succeeded
76
+ innerQueryContext.transferPostCommitCallbacksToParent();
77
+ return returnedValue;
78
+ }
47
79
  }
@@ -40,7 +40,7 @@ export interface ISecondaryEntityCache<TFields, TLoadParams> {
40
40
  * when the underlying data of a cache key could be stale.
41
41
  *
42
42
  * This is most commonly used to further optimize hot paths that cannot make use of normal entity cache loading
43
- * due to use of a non-unique-field-based {@link EntityLoader} method like `loadManyByFieldEqualityConjunctionAsync` or
43
+ * due to use of a non-unique-field-based EntityLoader method like `loadManyByFieldEqualityConjunctionAsync` or
44
44
  * `loadManyByRawWhereClauseAsync`.
45
45
  */
46
46
  export default abstract class EntitySecondaryCacheLoader<
@@ -8,7 +8,7 @@ import { filterMap, zipToMap } from './utils/collections/maps';
8
8
  /**
9
9
  * A custom secondary read-through entity cache is a way to add a custom second layer of caching for a particular
10
10
  * single entity load. One common way this may be used is to add a second layer of caching in a hot path that makes
11
- * a call to {@link EntityLoader.loadManyByFieldEqualityConjunctionAsync} is guaranteed to return at most one entity.
11
+ * a call to EntityLoader.loadManyByFieldEqualityConjunctionAsync is guaranteed to return at most one entity.
12
12
  */
13
13
  export default abstract class GenericSecondaryEntityCache<TFields, TLoadParams>
14
14
  implements ISecondaryEntityCache<TFields, TLoadParams>
@@ -82,7 +82,7 @@ export default abstract class ReadonlyEntity<
82
82
  }
83
83
 
84
84
  /**
85
- * @returns {@link EntityAssociationLoader} for this entity
85
+ * @returns EntityAssociationLoader for this entity
86
86
  */
87
87
  associationLoader(): EntityAssociationLoader<
88
88
  TFields,
@@ -7,9 +7,9 @@ import ViewerScopedEntityCompanion from './ViewerScopedEntityCompanion';
7
7
  import ViewerScopedEntityCompanionProvider from './ViewerScopedEntityCompanionProvider';
8
8
 
9
9
  /**
10
- * A viewer context encapsulates all information necessary to evaluate an {@link EntityPrivacyPolicy}.
10
+ * A viewer context encapsulates all information necessary to evaluate an EntityPrivacyPolicy.
11
11
  *
12
- * In combination with an {@link EntityCompanionProvider}, a viewer context is the
12
+ * In combination with an EntityCompanionProvider, a viewer context is the
13
13
  * entry point into the Entity framework.
14
14
  */
15
15
  export default class ViewerContext {
@@ -8,7 +8,7 @@ import ViewerScopedEntityMutatorFactory from './ViewerScopedEntityMutatorFactory
8
8
  import IEntityMetricsAdapter from './metrics/IEntityMetricsAdapter';
9
9
 
10
10
  /**
11
- * Provides a simpler API for loading and mutating entities by injecting the {@link ViewerContext}
11
+ * Provides a simpler API for loading and mutating entities by injecting the ViewerContext
12
12
  * from the viewer-scoped entity companion provider.
13
13
  */
14
14
  export default class ViewerScopedEntityCompanion<
@@ -79,7 +79,7 @@ export default class ViewerScopedEntityCompanion<
79
79
  }
80
80
 
81
81
  /**
82
- * Get the {@link IEntityMetricsAdapter} for this companion.
82
+ * Get the IEntityMetricsAdapter for this companion.
83
83
  */
84
84
  getMetricsAdapter(): IEntityMetricsAdapter {
85
85
  return this.entityCompanion.getMetricsAdapter();
@@ -6,7 +6,7 @@ import ReadonlyEntity from './ReadonlyEntity';
6
6
  import ViewerContext from './ViewerContext';
7
7
 
8
8
  /**
9
- * Provides a cleaner API for loading entities by passing through the {@link ViewerContext}.
9
+ * Provides a cleaner API for loading entities by passing through the ViewerContext.
10
10
  */
11
11
  export default class ViewerScopedEntityLoaderFactory<
12
12
  TFields,
@@ -6,7 +6,7 @@ import ReadonlyEntity from './ReadonlyEntity';
6
6
  import ViewerContext from './ViewerContext';
7
7
 
8
8
  /**
9
- * Provides a cleaner API for mutating entities by passing through the {@link ViewerContext}.
9
+ * Provides a cleaner API for mutating entities by passing through the ViewerContext.
10
10
  */
11
11
  export default class ViewerScopedEntityMutatorFactory<
12
12
  TFields,
@@ -11,8 +11,6 @@ import {
11
11
  StringArrayField,
12
12
  JSONObjectField,
13
13
  EnumField,
14
- JSONArrayField,
15
- MaybeJSONArrayField,
16
14
  } from '../EntityFields';
17
15
  import describeFieldTestCase from '../utils/testing/describeFieldTestCase';
18
16
 
@@ -71,13 +69,3 @@ describeFieldTestCase(
71
69
  );
72
70
  describeFieldTestCase(new JSONObjectField({ columnName: 'wat' }), [{}], [true, 'hello']);
73
71
  describeFieldTestCase(new EnumField({ columnName: 'wat' }), ['hello', 1], [true]);
74
- describeFieldTestCase(
75
- new JSONArrayField({ columnName: 'wat' }),
76
- [[[1, 2]] as any, [['hello']] as any], // jest test cases need extra wrapping array
77
- [1, 'hello']
78
- );
79
- describeFieldTestCase(
80
- new MaybeJSONArrayField({ columnName: 'wat' }),
81
- [1, 'hello', [['hello']]], // jest test cases need extra wrapping array
82
- []
83
- );
@@ -78,5 +78,55 @@ describe(EntityQueryContext, () => {
78
78
  expect(postCommitCallback).toHaveBeenCalledTimes(0);
79
79
  expect(postCommitInvalidationCallback).toHaveBeenCalledTimes(0);
80
80
  });
81
+
82
+ it('calls callbacks correctly for nested transactions', async () => {
83
+ const companionProvider = createUnitTestEntityCompanionProvider();
84
+ const viewerContext = new ViewerContext(companionProvider);
85
+
86
+ const preCommitCallback = jest.fn(async (): Promise<void> => {});
87
+ const preCommitNestedCallback = jest.fn(async (): Promise<void> => {});
88
+ const preCommitNestedCallbackThrow = jest.fn(async (): Promise<void> => {
89
+ throw new Error('wat');
90
+ });
91
+ const postCommitInvalidationCallback = jest.fn(async (): Promise<void> => {});
92
+ const postCommitCallback = jest.fn(async (): Promise<void> => {});
93
+
94
+ await viewerContext.runInTransactionForDatabaseAdaptorFlavorAsync(
95
+ 'postgres',
96
+ async (queryContext) => {
97
+ queryContext.appendPostCommitCallback(postCommitCallback);
98
+ queryContext.appendPostCommitInvalidationCallback(postCommitInvalidationCallback);
99
+ queryContext.appendPreCommitCallback(preCommitCallback, 0);
100
+
101
+ await Promise.all([
102
+ queryContext.runInNestedTransactionAsync(async (innerQueryContext) => {
103
+ innerQueryContext.appendPostCommitCallback(postCommitCallback);
104
+ innerQueryContext.appendPostCommitInvalidationCallback(
105
+ postCommitInvalidationCallback
106
+ );
107
+ innerQueryContext.appendPreCommitCallback(preCommitNestedCallback, 0);
108
+ }),
109
+ (async () => {
110
+ try {
111
+ await queryContext.runInNestedTransactionAsync(async (innerQueryContext) => {
112
+ // these two shouldn't be called
113
+ innerQueryContext.appendPostCommitCallback(postCommitCallback);
114
+ innerQueryContext.appendPostCommitInvalidationCallback(
115
+ postCommitInvalidationCallback
116
+ );
117
+ innerQueryContext.appendPreCommitCallback(preCommitNestedCallbackThrow, 0);
118
+ });
119
+ } catch {}
120
+ })(),
121
+ ]);
122
+ }
123
+ );
124
+
125
+ expect(preCommitCallback).toHaveBeenCalledTimes(1);
126
+ expect(preCommitNestedCallback).toHaveBeenCalledTimes(1);
127
+ expect(preCommitNestedCallbackThrow).toHaveBeenCalledTimes(1);
128
+ expect(postCommitCallback).toHaveBeenCalledTimes(2);
129
+ expect(postCommitInvalidationCallback).toHaveBeenCalledTimes(2);
130
+ });
81
131
  });
82
132
  });
@@ -3,6 +3,7 @@ import DataLoader from 'dataloader';
3
3
  import EntityDatabaseAdapter, {
4
4
  FieldEqualityCondition,
5
5
  QuerySelectionModifiers,
6
+ QuerySelectionModifiersWithOrderByRaw,
6
7
  } from '../EntityDatabaseAdapter';
7
8
  import { EntityQueryContext } from '../EntityQueryContext';
8
9
  import EntityQueryContextProvider from '../EntityQueryContextProvider';
@@ -20,9 +21,9 @@ import ReadThroughEntityCache from './ReadThroughEntityCache';
20
21
 
21
22
  /**
22
23
  * A data manager is responsible for orchestrating multiple sources of entity
23
- * data including local caches, {@link EntityCacheAdapter}, and {@link EntityDatabaseAdapter}.
24
+ * data including local caches, EntityCacheAdapter, and EntityDatabaseAdapter.
24
25
  *
25
- * It is also responsible for invalidating all sources of data when mutated using {@link EntityMutator}.
26
+ * It is also responsible for invalidating all sources of data when mutated using EntityMutator.
26
27
  */
27
28
  export default class EntityDataManager<TFields> {
28
29
  private readonly fieldDataLoaders: Map<
@@ -173,14 +174,14 @@ export default class EntityDataManager<TFields> {
173
174
  * @param queryContext - query context in which to perform the load
174
175
  * @param rawWhereClause - parameterized SQL WHERE clause with positional binding placeholders or named binding placeholders
175
176
  * @param bindings - array of positional bindings or object of named bindings
176
- * @param querySelectionModifiers - limit, offset, and orderBy for the query
177
+ * @param querySelectionModifiers - limit, offset, orderBy, and orderByRaw for the query
177
178
  * @returns array of objects matching the query
178
179
  */
179
180
  async loadManyByRawWhereClauseAsync(
180
181
  queryContext: EntityQueryContext,
181
182
  rawWhereClause: string,
182
183
  bindings: any[] | object,
183
- querySelectionModifiers: QuerySelectionModifiers<TFields>
184
+ querySelectionModifiers: QuerySelectionModifiersWithOrderByRaw<TFields>
184
185
  ): Promise<readonly Readonly<TFields>[]> {
185
186
  return await timeAndLogLoadEventAsync(
186
187
  this.metricsAdapter,
@@ -23,8 +23,8 @@ export type CacheLoadResult<TFields> =
23
23
  };
24
24
 
25
25
  /**
26
- * A read-through entity cache is responsible for coordinating {@link EntityDatabaseAdapter} and
27
- * {@link EntityCacheAdapter} within the {@link EntityDataManager}.
26
+ * A read-through entity cache is responsible for coordinating EntityDatabaseAdapter and
27
+ * EntityCacheAdapter within the EntityDataManager.
28
28
  */
29
29
  export default class ReadThroughEntityCache<TFields> {
30
30
  constructor(
@@ -10,16 +10,16 @@ export enum EntityMetricsLoadType {
10
10
  }
11
11
 
12
12
  /**
13
- * Event about a single call to an {@link EntityLoader} method.
13
+ * Event about a single call to an EntityLoader method.
14
14
  */
15
15
  export interface EntityMetricsLoadEvent {
16
16
  /**
17
- * {@link EntityMetricsLoadType} for this load.
17
+ * EntityMetricsLoadType for this load.
18
18
  */
19
19
  type: EntityMetricsLoadType;
20
20
 
21
21
  /**
22
- * Class name of the {@link Entity} being loaded.
22
+ * Class name of the Entity being loaded.
23
23
  */
24
24
  entityClassName: string;
25
25
 
@@ -42,12 +42,12 @@ export enum EntityMetricsMutationType {
42
42
 
43
43
  export interface EntityMetricsMutationEvent {
44
44
  /**
45
- * {@link EntityMetricsMutationType} for this mutation.
45
+ * EntityMetricsMutationType for this mutation.
46
46
  */
47
47
  type: EntityMetricsMutationType;
48
48
 
49
49
  /**
50
- * Class name of the {@link Entity} being mutated.
50
+ * Class name of the Entity being mutated.
51
51
  */
52
52
  entityClassName: string;
53
53
 
@@ -76,7 +76,7 @@ export enum IncrementLoadCountEventType {
76
76
  }
77
77
 
78
78
  /**
79
- * Event used to record dataloader, cache, and database load counts in {@link EntityDataManager}.
79
+ * Event used to record dataloader, cache, and database load counts in EntityDataManager.
80
80
  */
81
81
  export interface IncrementLoadCountEvent {
82
82
  /**
@@ -90,7 +90,7 @@ export interface IncrementLoadCountEvent {
90
90
  fieldValueCount: number;
91
91
 
92
92
  /**
93
- * Class name of the {@link Entity} being loaded.
93
+ * Class name of the Entity being loaded.
94
94
  */
95
95
  entityClassName: string;
96
96
  }
@@ -101,11 +101,11 @@ export enum EntityMetricsAuthorizationResult {
101
101
  }
102
102
 
103
103
  /**
104
- * Event used to record a singe {@link EntityPrivacyPolicy} authorization.
104
+ * Event used to record a singe EntityPrivacyPolicy authorization.
105
105
  */
106
106
  export interface EntityMetricsAuthorizationEvent {
107
107
  /**
108
- * Class name of the {@link Entity} being authorized.
108
+ * Class name of the Entity being authorized.
109
109
  */
110
110
  entityClassName: string;
111
111
  action: EntityAuthorizationAction;
@@ -119,7 +119,7 @@ export interface EntityMetricsAuthorizationEvent {
119
119
  */
120
120
  export default interface IEntityMetricsAdapter {
121
121
  /**
122
- * Called when a {@link EntityPrivacyPolicy} authorization succeeds or fails.
122
+ * Called when a EntityPrivacyPolicy authorization succeeds or fails.
123
123
  * @param authorizationEvent - info about the authorization event
124
124
  */
125
125
  logAuthorizationEvent(authorizationEvent: EntityMetricsAuthorizationEvent): void;
@@ -32,7 +32,7 @@ export enum RuleEvaluationResult {
32
32
  * rule in the privacy policy. If all rules in the policy SKIP, the policy is denied.
33
33
  *
34
34
  * Returning DENY from a rule is useful in a few notable cases:
35
- * - Preventing a CRUD action on an entity ({@link AlwaysDenyPrivacyPolicyRule})
35
+ * - Preventing a CRUD action on an entity (AlwaysDenyPrivacyPolicyRule)
36
36
  * - Blocking. For example, a user blocks another user from seeing their posts, and the rule
37
37
  * would be named something like `DenyIfViewerHasBeenBlockedPrivacyPolicyRule`.
38
38
  */
@@ -60,7 +60,7 @@ export const mapMapAsync = async function <K, V, M>(
60
60
 
61
61
  /**
62
62
  * Create a new Map by associating the value of each key with mapper executed for each key in the source map.
63
- * The opposite of {@link mapMap}. In the event two source keys map to the same result key, the second source key's
63
+ * The opposite of mapMap. In the event two source keys map to the same result key, the second source key's
64
64
  * value will overwrite the first, in which case the cardinality of the returned map may be smaller than the
65
65
  * source map's.
66
66
  *
@@ -17,7 +17,7 @@ export interface Case<
17
17
  entity: TEntity;
18
18
  }
19
19
 
20
- type CaseMap<
20
+ export type CaseMap<
21
21
  TFields,
22
22
  TID extends NonNullable<TFields[TSelectedFields]>,
23
23
  TViewerContext extends ViewerContext,
@@ -1,6 +1,6 @@
1
1
  import EntityQueryContextProvider from '../../EntityQueryContextProvider';
2
2
 
3
- class StubQueryContextProvider extends EntityQueryContextProvider {
3
+ export class StubQueryContextProvider extends EntityQueryContextProvider {
4
4
  protected getQueryInterface(): any {
5
5
  return {};
6
6
  }
@@ -10,6 +10,12 @@ class StubQueryContextProvider extends EntityQueryContextProvider {
10
10
  ) => Promise<T> {
11
11
  return (transactionScope) => Promise.resolve(transactionScope({}));
12
12
  }
13
+
14
+ protected createNestedTransactionRunner<T>(
15
+ _outerQueryInterface: any
16
+ ): (transactionScope: (queryInterface: any) => Promise<T>) => Promise<T> {
17
+ return (transactionScope) => Promise.resolve(transactionScope({}));
18
+ }
13
19
  }
14
20
 
15
21
  export default new StubQueryContextProvider();