@expo/entity 0.25.3 → 0.27.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 (178) hide show
  1. package/LICENSE +21 -0
  2. package/build/ComposedEntityCacheAdapter.d.ts +4 -2
  3. package/build/ComposedEntityCacheAdapter.js +39 -3
  4. package/build/ComposedEntityCacheAdapter.js.map +1 -1
  5. package/build/ComposedSecondaryEntityCache.d.ts +3 -2
  6. package/build/ComposedSecondaryEntityCache.js +3 -2
  7. package/build/ComposedSecondaryEntityCache.js.map +1 -1
  8. package/build/EnforcingEntityLoader.d.ts +10 -10
  9. package/build/EnforcingEntityLoader.js +8 -8
  10. package/build/EnforcingEntityLoader.js.map +1 -1
  11. package/build/Entity.d.ts +5 -5
  12. package/build/Entity.js +9 -9
  13. package/build/Entity.js.map +1 -1
  14. package/build/EntityAssociationLoader.d.ts +9 -4
  15. package/build/EntityAssociationLoader.js +5 -0
  16. package/build/EntityAssociationLoader.js.map +1 -1
  17. package/build/EntityCacheAdapter.d.ts +1 -1
  18. package/build/EntityCompanion.d.ts +1 -1
  19. package/build/EntityCompanion.js +1 -1
  20. package/build/EntityCompanionProvider.d.ts +9 -9
  21. package/build/EntityCompanionProvider.js +3 -3
  22. package/build/EntityConfiguration.d.ts +2 -2
  23. package/build/EntityDatabaseAdapter.d.ts +15 -6
  24. package/build/EntityDatabaseAdapter.js +8 -2
  25. package/build/EntityDatabaseAdapter.js.map +1 -1
  26. package/build/EntityFieldDefinition.d.ts +16 -8
  27. package/build/EntityFieldDefinition.js +12 -5
  28. package/build/EntityFieldDefinition.js.map +1 -1
  29. package/build/EntityFields.d.ts +11 -11
  30. package/build/EntityFields.js +11 -11
  31. package/build/EntityLoader.d.ts +7 -7
  32. package/build/EntityLoader.js +7 -7
  33. package/build/EntityLoader.js.map +1 -1
  34. package/build/EntityMutationInfo.d.ts +2 -0
  35. package/build/EntityMutationTriggerConfiguration.d.ts +1 -1
  36. package/build/EntityMutationTriggerConfiguration.js +1 -1
  37. package/build/EntityMutator.d.ts +7 -9
  38. package/build/EntityMutator.js +59 -47
  39. package/build/EntityMutator.js.map +1 -1
  40. package/build/EntityMutatorFactory.d.ts +4 -4
  41. package/build/EntityMutatorFactory.js +6 -6
  42. package/build/EntityMutatorFactory.js.map +1 -1
  43. package/build/EntityPrivacyPolicy.d.ts +18 -5
  44. package/build/EntityPrivacyPolicy.js +18 -5
  45. package/build/EntityPrivacyPolicy.js.map +1 -1
  46. package/build/EntityQueryContext.d.ts +12 -1
  47. package/build/EntityQueryContext.js +12 -1
  48. package/build/EntityQueryContext.js.map +1 -1
  49. package/build/EntityQueryContextProvider.d.ts +1 -1
  50. package/build/EntitySecondaryCacheLoader.d.ts +1 -1
  51. package/build/EntitySecondaryCacheLoader.js +1 -1
  52. package/build/GenericSecondaryEntityCache.d.ts +1 -1
  53. package/build/GenericSecondaryEntityCache.js +1 -1
  54. package/build/ReadonlyEntity.d.ts +1 -1
  55. package/build/ReadonlyEntity.js +1 -1
  56. package/build/ViewerContext.d.ts +2 -2
  57. package/build/ViewerContext.js +2 -2
  58. package/build/ViewerScopedEntityCompanion.d.ts +2 -2
  59. package/build/ViewerScopedEntityCompanion.js +2 -2
  60. package/build/ViewerScopedEntityLoaderFactory.d.ts +1 -1
  61. package/build/ViewerScopedEntityLoaderFactory.js +1 -1
  62. package/build/ViewerScopedEntityMutatorFactory.d.ts +5 -5
  63. package/build/ViewerScopedEntityMutatorFactory.js +7 -7
  64. package/build/ViewerScopedEntityMutatorFactory.js.map +1 -1
  65. package/build/__tests__/ComposedCacheAdapter-test.js +37 -4
  66. package/build/__tests__/ComposedCacheAdapter-test.js.map +1 -1
  67. package/build/__tests__/EntityCommonUseCases-test.js +5 -1
  68. package/build/__tests__/EntityCommonUseCases-test.js.map +1 -1
  69. package/build/__tests__/EntityCompanion-test.js +5 -1
  70. package/build/__tests__/EntityCompanion-test.js.map +1 -1
  71. package/build/__tests__/EntityCompanionProvider-test.js +5 -1
  72. package/build/__tests__/EntityCompanionProvider-test.js.map +1 -1
  73. package/build/__tests__/EntityEdges-test.js +199 -33
  74. package/build/__tests__/EntityEdges-test.js.map +1 -1
  75. package/build/__tests__/EntityLoader-test.js +5 -1
  76. package/build/__tests__/EntityLoader-test.js.map +1 -1
  77. package/build/__tests__/EntityMutator-test.js +38 -53
  78. package/build/__tests__/EntityMutator-test.js.map +1 -1
  79. package/build/__tests__/EntityPrivacyPolicy-test.js +5 -1
  80. package/build/__tests__/EntityPrivacyPolicy-test.js.map +1 -1
  81. package/build/__tests__/EntitySelfReferentialEdges-test.js +2 -2
  82. package/build/__tests__/EntitySelfReferentialEdges-test.js.map +1 -1
  83. package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js +5 -1
  84. package/build/__tests__/ViewerScopedEntityCompanionProvider-test.js.map +1 -1
  85. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js +2 -3
  86. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js.map +1 -1
  87. package/build/errors/EntityCacheAdapterError.js +5 -1
  88. package/build/errors/EntityCacheAdapterError.js.map +1 -1
  89. package/build/errors/EntityDatabaseAdapterError.js +5 -1
  90. package/build/errors/EntityDatabaseAdapterError.js.map +1 -1
  91. package/build/errors/EntityInvalidFieldValueError.js +6 -2
  92. package/build/errors/EntityInvalidFieldValueError.js.map +1 -1
  93. package/build/errors/EntityNotAuthorizedError.js +5 -1
  94. package/build/errors/EntityNotAuthorizedError.js.map +1 -1
  95. package/build/errors/EntityNotFoundError.js +6 -2
  96. package/build/errors/EntityNotFoundError.js.map +1 -1
  97. package/build/index.js +5 -1
  98. package/build/index.js.map +1 -1
  99. package/build/internal/EntityDataManager.d.ts +5 -5
  100. package/build/internal/EntityDataManager.js +10 -7
  101. package/build/internal/EntityDataManager.js.map +1 -1
  102. package/build/internal/EntityFieldTransformationUtils.js +1 -1
  103. package/build/internal/EntityFieldTransformationUtils.js.map +1 -1
  104. package/build/internal/ReadThroughEntityCache.d.ts +2 -2
  105. package/build/internal/ReadThroughEntityCache.js +3 -3
  106. package/build/internal/ReadThroughEntityCache.js.map +1 -1
  107. package/build/internal/__tests__/EntityDataManager-test.js +12 -7
  108. package/build/internal/__tests__/EntityDataManager-test.js.map +1 -1
  109. package/build/internal/__tests__/ReadThroughEntityCache-test.js +5 -1
  110. package/build/internal/__tests__/ReadThroughEntityCache-test.js.map +1 -1
  111. package/build/metrics/IEntityMetricsAdapter.d.ts +63 -18
  112. package/build/metrics/IEntityMetricsAdapter.js +17 -1
  113. package/build/metrics/IEntityMetricsAdapter.js.map +1 -1
  114. package/build/metrics/NoOpEntityMetricsAdapter.d.ts +1 -3
  115. package/build/metrics/NoOpEntityMetricsAdapter.js +1 -3
  116. package/build/metrics/NoOpEntityMetricsAdapter.js.map +1 -1
  117. package/build/rules/AlwaysAllowPrivacyPolicyRule.js +5 -1
  118. package/build/rules/AlwaysAllowPrivacyPolicyRule.js.map +1 -1
  119. package/build/rules/AlwaysDenyPrivacyPolicyRule.js +5 -1
  120. package/build/rules/AlwaysDenyPrivacyPolicyRule.js.map +1 -1
  121. package/build/rules/AlwaysSkipPrivacyPolicyRule.js +5 -1
  122. package/build/rules/AlwaysSkipPrivacyPolicyRule.js.map +1 -1
  123. package/build/rules/PrivacyPolicyRule.d.ts +1 -1
  124. package/build/rules/PrivacyPolicyRule.js +1 -1
  125. package/build/utils/collections/maps.d.ts +1 -1
  126. package/build/utils/collections/maps.js +1 -1
  127. package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +1 -2
  128. package/build/utils/testing/StubDatabaseAdapter.js +6 -2
  129. package/build/utils/testing/StubDatabaseAdapter.js.map +1 -1
  130. package/build/utils/testing/StubQueryContextProvider.d.ts +1 -1
  131. package/build/utils/testing/StubQueryContextProvider.js +2 -0
  132. package/build/utils/testing/StubQueryContextProvider.js.map +1 -1
  133. package/package.json +3 -2
  134. package/src/ComposedEntityCacheAdapter.ts +44 -3
  135. package/src/ComposedSecondaryEntityCache.ts +3 -2
  136. package/src/EnforcingEntityLoader.ts +14 -10
  137. package/src/Entity.ts +9 -9
  138. package/src/EntityAssociationLoader.ts +9 -4
  139. package/src/EntityCacheAdapter.ts +1 -1
  140. package/src/EntityCompanion.ts +1 -1
  141. package/src/EntityCompanionProvider.ts +9 -9
  142. package/src/EntityConfiguration.ts +2 -2
  143. package/src/EntityDatabaseAdapter.ts +33 -6
  144. package/src/EntityFieldDefinition.ts +15 -6
  145. package/src/EntityFields.ts +11 -11
  146. package/src/EntityLoader.ts +11 -8
  147. package/src/EntityMutationInfo.ts +2 -0
  148. package/src/EntityMutationTriggerConfiguration.ts +1 -1
  149. package/src/EntityMutator.ts +99 -68
  150. package/src/EntityMutatorFactory.ts +4 -10
  151. package/src/EntityPrivacyPolicy.ts +20 -5
  152. package/src/EntityQueryContext.ts +12 -1
  153. package/src/EntityQueryContextProvider.ts +1 -1
  154. package/src/EntitySecondaryCacheLoader.ts +1 -1
  155. package/src/GenericSecondaryEntityCache.ts +1 -1
  156. package/src/ReadonlyEntity.ts +1 -1
  157. package/src/ViewerContext.ts +2 -2
  158. package/src/ViewerScopedEntityCompanion.ts +2 -2
  159. package/src/ViewerScopedEntityLoaderFactory.ts +1 -1
  160. package/src/ViewerScopedEntityMutatorFactory.ts +8 -23
  161. package/src/__tests__/ComposedCacheAdapter-test.ts +43 -4
  162. package/src/__tests__/EntityEdges-test.ts +287 -32
  163. package/src/__tests__/EntityMutator-test.ts +33 -54
  164. package/src/__tests__/EntitySelfReferentialEdges-test.ts +2 -2
  165. package/src/__tests__/ViewerScopedEntityMutatorFactory-test.ts +2 -6
  166. package/src/errors/EntityInvalidFieldValueError.ts +1 -1
  167. package/src/errors/EntityNotFoundError.ts +1 -1
  168. package/src/internal/EntityDataManager.ts +18 -9
  169. package/src/internal/EntityFieldTransformationUtils.ts +1 -1
  170. package/src/internal/ReadThroughEntityCache.ts +5 -3
  171. package/src/internal/__tests__/EntityDataManager-test.ts +11 -8
  172. package/src/metrics/IEntityMetricsAdapter.ts +73 -20
  173. package/src/metrics/NoOpEntityMetricsAdapter.ts +1 -5
  174. package/src/rules/PrivacyPolicyRule.ts +1 -1
  175. package/src/utils/collections/maps.ts +1 -1
  176. package/src/utils/testing/PrivacyPolicyRuleTestUtils.ts +1 -1
  177. package/src/utils/testing/StubDatabaseAdapter.ts +4 -1
  178. package/src/utils/testing/StubQueryContextProvider.ts +1 -1
package/src/Entity.ts CHANGED
@@ -11,19 +11,19 @@ import ViewerContext from './ViewerContext';
11
11
  * Entity is a privacy-first data model.
12
12
  *
13
13
  * A instance of an entity represents a single "row" of persisted data in a database that a
14
- * viewer, represented by the corresponding {@link ViewerContext}, has permission to read.
14
+ * viewer, represented by the corresponding ViewerContext, has permission to read.
15
15
  *
16
16
  * Create, read, update, and delete permissions for an entity are declaratively defined using an
17
- * {@link EntityPrivacyPolicy}.
17
+ * EntityPrivacyPolicy.
18
18
  *
19
- * Entites are loaded through an {@link EntityLoader}, which is responsible for
19
+ * Entites are loaded through an EntityLoader, which is responsible for
20
20
  * orchestrating fetching, caching, and authorization of reading "rows".
21
21
  *
22
- * Entities are mutated and deleted through an {@link EntityMutator}, which is responsible for
22
+ * Entities are mutated and deleted through an EntityMutator, which is responsible for
23
23
  * orchestrating database writes, cache invalidation, and authorization of writing "rows".
24
24
  *
25
25
  * All concrete entity implementations should extend this class and provide their
26
- * own {@link EntityCompanionDefinition}.
26
+ * own EntityCompanionDefinition.
27
27
  */
28
28
  export default abstract class Entity<
29
29
  TFields,
@@ -69,7 +69,7 @@ export default abstract class Entity<
69
69
  return viewerContext
70
70
  .getViewerScopedEntityCompanionForClass(this)
71
71
  .getMutatorFactory()
72
- .forCreate(queryContext, { cascadingDeleteCause: null });
72
+ .forCreate(queryContext);
73
73
  }
74
74
 
75
75
  /**
@@ -111,7 +111,7 @@ export default abstract class Entity<
111
111
  .getViewerContext()
112
112
  .getViewerScopedEntityCompanionForClass(this)
113
113
  .getMutatorFactory()
114
- .forUpdate(existingEntity, queryContext, { cascadingDeleteCause: null });
114
+ .forUpdate(existingEntity, queryContext);
115
115
  }
116
116
 
117
117
  /**
@@ -152,7 +152,7 @@ export default abstract class Entity<
152
152
  .getViewerContext()
153
153
  .getViewerScopedEntityCompanionForClass(this)
154
154
  .getMutatorFactory()
155
- .forDelete(existingEntity, queryContext, { cascadingDeleteCause: null })
155
+ .forDelete(existingEntity, queryContext)
156
156
  .deleteAsync();
157
157
  }
158
158
 
@@ -194,7 +194,7 @@ export default abstract class Entity<
194
194
  .getViewerContext()
195
195
  .getViewerScopedEntityCompanionForClass(this)
196
196
  .getMutatorFactory()
197
- .forDelete(existingEntity, queryContext, { cascadingDeleteCause: null })
197
+ .forDelete(existingEntity, queryContext)
198
198
  .enforceDeleteAsync();
199
199
  }
200
200
 
@@ -6,6 +6,11 @@ import { EntityQueryContext } from './EntityQueryContext';
6
6
  import ReadonlyEntity from './ReadonlyEntity';
7
7
  import ViewerContext from './ViewerContext';
8
8
 
9
+ /**
10
+ * An association loader is a set of convenience methods for loading entities
11
+ * associated with an entity. In relational databases, these entities are often referenced
12
+ * by foreign keys.
13
+ */
9
14
  export default class EntityAssociationLoader<
10
15
  TFields,
11
16
  TID extends NonNullable<TFields[TSelectedFields]>,
@@ -246,7 +251,7 @@ export default class EntityAssociationLoader<
246
251
  }
247
252
 
248
253
  /**
249
- * Load an associated entity by folding a sequence of {@link EntityLoadThroughDirective}. At each
254
+ * Load an associated entity by folding a sequence of EntityLoadThroughDirective. At each
250
255
  * fold step, load an associated entity identified by a field value of the current fold value.
251
256
  * @param loadDirectives - associated entity load directives instructing each step of the fold
252
257
  * @param queryContext - query context in which to perform the loads
@@ -280,7 +285,7 @@ export default class EntityAssociationLoader<
280
285
  ): Promise<Result<TEntity2> | null>;
281
286
 
282
287
  /**
283
- * Load an associated entity by folding a sequence of {@link EntityLoadThroughDirective}. At each
288
+ * Load an associated entity by folding a sequence of EntityLoadThroughDirective. At each
284
289
  * fold step, load an associated entity identified by a field value of the current fold value.
285
290
  * @param loadDirectives - associated entity load directives instructing each step of the fold
286
291
  * @param queryContext - query context in which to perform the loads
@@ -335,7 +340,7 @@ export default class EntityAssociationLoader<
335
340
  ): Promise<Result<TEntity3> | null>;
336
341
 
337
342
  /**
338
- * Load an associated entity by folding a sequence of {@link EntityLoadThroughDirective}. At each
343
+ * Load an associated entity by folding a sequence of EntityLoadThroughDirective. At each
339
344
  * fold step, load an associated entity identified by a field value of the current fold value.
340
345
  * @param loadDirectives - associated entity load directives instructing each step of the fold
341
346
  * @param queryContext - query context in which to perform the loads
@@ -411,7 +416,7 @@ export default class EntityAssociationLoader<
411
416
  ): Promise<Result<TEntity4> | null>;
412
417
 
413
418
  /**
414
- * Load an associated entity by folding a sequence of {@link EntityLoadThroughDirective}. At each
419
+ * Load an associated entity by folding a sequence of EntityLoadThroughDirective. At each
415
420
  * fold step, load an associated entity identified by a field value of the current fold value.
416
421
  * @param loadDirectives - associated entity load directives instructing each step of the fold
417
422
  * @param queryContext - query context in which to perform the loads
@@ -32,7 +32,7 @@ export default abstract class EntityCacheAdapter<TFields> {
32
32
  /**
33
33
  * Negatively cache objects that could not be found in the cache or DB.
34
34
  * @param fieldName - object field being queried
35
- * @param fieldValues - fieldValues for objects reported as {@link CacheStatus.NEGATIVE}
35
+ * @param fieldValues - fieldValues for objects reported as CacheStatus.NEGATIVE
36
36
  * in the cache and not found in the DB.
37
37
  */
38
38
  public abstract cacheDBMissesAsync<N extends keyof TFields>(
@@ -132,7 +132,7 @@ export default class EntityCompanion<
132
132
  }
133
133
 
134
134
  /**
135
- * Get the {@link IEntityMetricsAdapter} for this companion.
135
+ * Get the IEntityMetricsAdapter for this companion.
136
136
  */
137
137
  getMetricsAdapter(): IEntityMetricsAdapter {
138
138
  return this.metricsAdapter;
@@ -109,15 +109,15 @@ export class EntityCompanionDefinition<
109
109
  TSelectedFields
110
110
  >;
111
111
  /**
112
- * The {@link EntityConfiguration} for this entity.
112
+ * The EntityConfiguration for this entity.
113
113
  */
114
114
  entityConfiguration: EntityConfiguration<TFields>;
115
115
  /**
116
- * The {@link EntityPrivacyPolicy} class for this entity.
116
+ * The EntityPrivacyPolicy class for this entity.
117
117
  */
118
118
  privacyPolicyClass: IPrivacyPolicyClass<TPrivacyPolicy>;
119
119
  /**
120
- * An optional list of {@link EntityMutationValidator} for this entity.
120
+ * An optional list of EntityMutationValidator for this entity.
121
121
  */
122
122
  mutationValidators?: () => EntityMutationValidator<
123
123
  TFields,
@@ -127,7 +127,7 @@ export class EntityCompanionDefinition<
127
127
  TSelectedFields
128
128
  >[];
129
129
  /**
130
- * An optional list of {@link EntityMutationTrigger} for this entity.
130
+ * An optional list of EntityMutationTrigger for this entity.
131
131
  */
132
132
  mutationTriggers?: () => EntityMutationTriggerConfiguration<
133
133
  TFields,
@@ -137,8 +137,8 @@ export class EntityCompanionDefinition<
137
137
  TSelectedFields
138
138
  >;
139
139
  /**
140
- * An optional subset of fields defined in the {@link EntityConfiguration} which belong to this entity.
141
- * For use when multiple types of entities are backed by a single table ({@link EntityConfiguration}) yet
140
+ * An optional subset of fields defined in the EntityConfiguration which belong to this entity.
141
+ * For use when multiple types of entities are backed by a single table (EntityConfiguration) yet
142
142
  * only expose a subset of the fields.
143
143
  */
144
144
  entitySelectedFields?: TSelectedFields[];
@@ -155,11 +155,11 @@ export class EntityCompanionDefinition<
155
155
  /**
156
156
  * An instance of the Entity framework.
157
157
  *
158
- * Required to create a {@link ViewerContext}, which is the application entry point
158
+ * Required to create a ViewerContext, which is the application entry point
159
159
  * into the framework.
160
160
  *
161
161
  * Internally, this is a lazy entity companion factory that instantiates and caches one
162
- * {@link EntityCompanion} for each type of {@link Entity}.
162
+ * EntityCompanion for each type of Entity.
163
163
  */
164
164
  export default class EntityCompanionProvider {
165
165
  private readonly companionMap: Map<string, EntityCompanion<any, any, any, any, any, any>> =
@@ -169,7 +169,7 @@ export default class EntityCompanionProvider {
169
169
 
170
170
  /**
171
171
  * Instantiate an Entity framework.
172
- * @param metricsAdapter - An {@link IEntityMetricsAdapter} for collecting metrics on this instance
172
+ * @param metricsAdapter - An IEntityMetricsAdapter for collecting metrics on this instance
173
173
  * @param databaseAdapterFlavors - Database adapter configurations for this instance
174
174
  * @param cacheAdapterFlavors - Cache adapter configurations for this instance
175
175
  */
@@ -41,12 +41,12 @@ export default class EntityConfiguration<TFields> {
41
41
  tableName: string;
42
42
 
43
43
  /**
44
- * Map from each entity field to an {@link EntityFieldDefinition} specifying information about the field.
44
+ * Map from each entity field to an EntityFieldDefinition specifying information about the field.
45
45
  */
46
46
  schema: Record<keyof TFields, EntityFieldDefinition<any>>;
47
47
 
48
48
  /**
49
- * List of other entity types that reference this type in {@link EntityFieldDefinition} associations.
49
+ * List of other entity types that reference this type in EntityFieldDefinition associations.
50
50
  */
51
51
  getInboundEdges?: () => IEntityClass<any, any, any, any, any, any>[];
52
52
 
@@ -7,12 +7,18 @@ import {
7
7
  FieldTransformerMap,
8
8
  } from './internal/EntityFieldTransformationUtils';
9
9
 
10
- interface SingleValueFieldEqualityCondition<TFields, N extends keyof TFields = keyof TFields> {
10
+ export interface SingleValueFieldEqualityCondition<
11
+ TFields,
12
+ N extends keyof TFields = keyof TFields
13
+ > {
11
14
  fieldName: N;
12
15
  fieldValue: TFields[N];
13
16
  }
14
17
 
15
- interface MultiValueFieldEqualityCondition<TFields, N extends keyof TFields = keyof TFields> {
18
+ export interface MultiValueFieldEqualityCondition<
19
+ TFields,
20
+ N extends keyof TFields = keyof TFields
21
+ > {
16
22
  fieldName: N;
17
23
  fieldValues: readonly TFields[N][];
18
24
  }
@@ -68,6 +74,14 @@ export interface QuerySelectionModifiers<TFields> {
68
74
  limit?: number;
69
75
  }
70
76
 
77
+ export interface QuerySelectionModifiersWithOrderByRaw<TFields>
78
+ extends QuerySelectionModifiers<TFields> {
79
+ /**
80
+ * Order the entities by a raw SQL `ORDER BY` clause.
81
+ */
82
+ orderByRaw?: string;
83
+ }
84
+
71
85
  export interface TableQuerySelectionModifiers {
72
86
  orderBy:
73
87
  | {
@@ -79,6 +93,10 @@ export interface TableQuerySelectionModifiers {
79
93
  limit: number | undefined;
80
94
  }
81
95
 
96
+ export interface TableQuerySelectionModifiersWithOrderByRaw extends TableQuerySelectionModifiers {
97
+ orderByRaw: string | undefined;
98
+ }
99
+
82
100
  /**
83
101
  * A database adapter is an interface by which entity objects can be
84
102
  * fetched, inserted, updated, and deleted from a database. This base class
@@ -149,7 +167,7 @@ export default abstract class EntityDatabaseAdapter<TFields> {
149
167
  *
150
168
  * @param queryContext - query context with which to perform the fetch
151
169
  * @param fieldEqualityOperands - list of field equality where clause operand specifications
152
- * @param querySelectionModifiers - limit, offset, and orderBy for the query
170
+ * @param querySelectionModifiers - limit, offset, orderBy, and orderByRaw for the query
153
171
  * @returns array of objects matching the query
154
172
  */
155
173
  async fetchManyByFieldEqualityConjunctionAsync<N extends keyof TFields>(
@@ -207,14 +225,14 @@ export default abstract class EntityDatabaseAdapter<TFields> {
207
225
  queryContext: EntityQueryContext,
208
226
  rawWhereClause: string,
209
227
  bindings: any[] | object,
210
- querySelectionModifiers: QuerySelectionModifiers<TFields>
228
+ querySelectionModifiers: QuerySelectionModifiersWithOrderByRaw<TFields>
211
229
  ): Promise<readonly Readonly<TFields>[]> {
212
230
  const results = await this.fetchManyByRawWhereClauseInternalAsync(
213
231
  queryContext.getQueryInterface(),
214
232
  this.entityConfiguration.tableName,
215
233
  rawWhereClause,
216
234
  bindings,
217
- this.convertToTableQueryModifiers(querySelectionModifiers)
235
+ this.convertToTableQueryModifiersWithOrderByRaw(querySelectionModifiers)
218
236
  );
219
237
 
220
238
  return results.map((result) =>
@@ -227,7 +245,7 @@ export default abstract class EntityDatabaseAdapter<TFields> {
227
245
  tableName: string,
228
246
  rawWhereClause: string,
229
247
  bindings: any[] | object,
230
- querySelectionModifiers: TableQuerySelectionModifiers
248
+ querySelectionModifiers: TableQuerySelectionModifiersWithOrderByRaw
231
249
  ): Promise<object[]>;
232
250
 
233
251
  /**
@@ -363,6 +381,15 @@ export default abstract class EntityDatabaseAdapter<TFields> {
363
381
  id: any
364
382
  ): Promise<number>;
365
383
 
384
+ private convertToTableQueryModifiersWithOrderByRaw(
385
+ querySelectionModifiers: QuerySelectionModifiersWithOrderByRaw<TFields>
386
+ ): TableQuerySelectionModifiersWithOrderByRaw {
387
+ return {
388
+ ...this.convertToTableQueryModifiers(querySelectionModifiers),
389
+ orderByRaw: querySelectionModifiers.orderByRaw,
390
+ };
391
+ }
392
+
366
393
  private convertToTableQueryModifiers(
367
394
  querySelectionModifiers: QuerySelectionModifiers<TFields>
368
395
  ): TableQuerySelectionModifiers {
@@ -5,13 +5,21 @@ import ViewerContext from './ViewerContext';
5
5
 
6
6
  export enum EntityEdgeDeletionBehavior {
7
7
  /**
8
- * Default. Invalidate the cache for all entities that reference the entity
8
+ * Invalidate the cache for all entities that reference the entity
9
9
  * being deleted through this field, and transitively run deletions on those entities.
10
10
  * This is most useful when the database itself expresses foreign
11
- * keys and cascading deletes or set nulls and the entity framework just needs to
11
+ * keys and cascading deletes and the entity framework just needs to
12
12
  * be kept consistent with the state of the database.
13
13
  */
14
- CASCADE_DELETE_INVALIDATE_CACHE,
14
+ CASCADE_DELETE_INVALIDATE_CACHE_ONLY,
15
+
16
+ /**
17
+ * Invalidate the cache for all entities that reference the entity
18
+ * being deleted through this field. This is most useful when the database itself expresses
19
+ * foreign keys and cascading "SET NULL"s and the entity framework just needs to be
20
+ * kept consistent with the state of the database.
21
+ */
22
+ SET_NULL_INVALIDATE_CACHE_ONLY,
15
23
 
16
24
  /**
17
25
  * Delete all entities that reference the entity being deleted through this field. This is very similar
@@ -74,16 +82,17 @@ export interface EntityAssociationDefinition<
74
82
  *
75
83
  * @remarks
76
84
  * The entity framework doesn't prescribe a one-size-fits-all solution for referential
77
- * integrity; instead it exposes mechanisms that supports both database foreign key constraints
85
+ * integrity; instead it exposes mechanisms that support both database foreign key constraints
78
86
  * and implicit entity-specified foreign keys. Choosing which approach to use often depends on
79
87
  * application requirements, and sometimes even a mix-and-match is the right choice.
80
88
  *
81
89
  * - If referential integrity is critical to your application, database foreign key constraints
82
- * combined with {@link EntityEdgeDeletionBehavior.CASACDE_DELETE_INVALIDATE_CACHE} are recommended.
90
+ * combined with EntityEdgeDeletionBehavior.CASCADE_DELETE_INVALIDATE_CACHE_ONLY or
91
+ * EntityEdgeDeletionBehavior.SET_NULL_INVALIDATE_CACHE_ONLY are recommended.
83
92
  * - If the database being used doesn't support foreign keys, then using the entity framework for referential
84
93
  * integrity is recommended.
85
94
  */
86
- edgeDeletionBehavior?: EntityEdgeDeletionBehavior;
95
+ edgeDeletionBehavior: EntityEdgeDeletionBehavior;
87
96
  }
88
97
 
89
98
  /**
@@ -3,7 +3,7 @@ import { validate as validateUUID } from 'uuid';
3
3
  import { EntityFieldDefinition } from './EntityFieldDefinition';
4
4
 
5
5
  /**
6
- * {@link EntityFieldDefinition} for a column with a JS string type.
6
+ * EntityFieldDefinition for a column with a JS string type.
7
7
  */
8
8
  export class StringField extends EntityFieldDefinition<string> {
9
9
  protected validateInputValueInternal(value: string): boolean {
@@ -12,7 +12,7 @@ export class StringField extends EntityFieldDefinition<string> {
12
12
  }
13
13
 
14
14
  /**
15
- * {@link EntityFieldDefinition} for a column with a JS string type.
15
+ * EntityFieldDefinition for a column with a JS string type.
16
16
  * Enforces that the string is a valid UUID.
17
17
  */
18
18
  export class UUIDField extends StringField {
@@ -22,7 +22,7 @@ export class UUIDField extends StringField {
22
22
  }
23
23
 
24
24
  /**
25
- * {@link EntityFieldDefinition} for a column with a JS Date type.
25
+ * EntityFieldDefinition for a column with a JS Date type.
26
26
  */
27
27
  export class DateField extends EntityFieldDefinition<Date> {
28
28
  protected validateInputValueInternal(value: Date): boolean {
@@ -31,7 +31,7 @@ export class DateField extends EntityFieldDefinition<Date> {
31
31
  }
32
32
 
33
33
  /**
34
- * {@link EntityFieldDefinition} for a column with a JS boolean type.
34
+ * EntityFieldDefinition for a column with a JS boolean type.
35
35
  */
36
36
  export class BooleanField extends EntityFieldDefinition<boolean> {
37
37
  protected validateInputValueInternal(value: boolean): boolean {
@@ -40,7 +40,7 @@ export class BooleanField extends EntityFieldDefinition<boolean> {
40
40
  }
41
41
 
42
42
  /**
43
- * {@link EntityFieldDefinition} for a column with a JS number type.
43
+ * EntityFieldDefinition for a column with a JS number type.
44
44
  * Enforces that the number is an integer.
45
45
  */
46
46
  export class IntField extends EntityFieldDefinition<number> {
@@ -50,7 +50,7 @@ export class IntField extends EntityFieldDefinition<number> {
50
50
  }
51
51
 
52
52
  /**
53
- * {@link EntityFieldDefinition} for a column with a JS number type.
53
+ * EntityFieldDefinition for a column with a JS number type.
54
54
  * Enforces that the number is a float (which includes integers in JS).
55
55
  */
56
56
  export class FloatField extends EntityFieldDefinition<number> {
@@ -60,7 +60,7 @@ export class FloatField extends EntityFieldDefinition<number> {
60
60
  }
61
61
 
62
62
  /**
63
- * {@link EntityFieldDefinition} for a column with a JS string array type.
63
+ * EntityFieldDefinition for a column with a JS string array type.
64
64
  * Enforces that every member of the string array is a string.
65
65
  */
66
66
  export class StringArrayField extends EntityFieldDefinition<string[]> {
@@ -70,7 +70,7 @@ export class StringArrayField extends EntityFieldDefinition<string[]> {
70
70
  }
71
71
 
72
72
  /**
73
- * {@link EntityFieldDefinition} for a column with a JS JSON object type.
73
+ * EntityFieldDefinition for a column with a JS JSON object type.
74
74
  */
75
75
  export class JSONObjectField extends EntityFieldDefinition<object> {
76
76
  protected validateInputValueInternal(value: object): boolean {
@@ -79,7 +79,7 @@ export class JSONObjectField extends EntityFieldDefinition<object> {
79
79
  }
80
80
 
81
81
  /**
82
- * {@link EntityFieldDefinition} for a enum column with a JS string or number type.
82
+ * EntityFieldDefinition for a enum column with a JS string or number type.
83
83
  */
84
84
  export class EnumField extends EntityFieldDefinition<string | number> {
85
85
  protected validateInputValueInternal(value: string | number): boolean {
@@ -88,7 +88,7 @@ export class EnumField extends EntityFieldDefinition<string | number> {
88
88
  }
89
89
 
90
90
  /**
91
- * {@link EntityFieldDefinition} for a column with a JS JSON array type.
91
+ * EntityFieldDefinition for a column with a JS JSON array type.
92
92
  */
93
93
  export class JSONArrayField extends EntityFieldDefinition<any[]> {
94
94
  protected validateInputValueInternal(value: any[]): boolean {
@@ -97,7 +97,7 @@ export class JSONArrayField extends EntityFieldDefinition<any[]> {
97
97
  }
98
98
 
99
99
  /**
100
- * {@link EntityFieldDefinition} for a column that may be a JS JSON array type.
100
+ * EntityFieldDefinition for a column that may be a JS JSON array type.
101
101
  * Does not do any validation.
102
102
  */
103
103
  export class MaybeJSONArrayField extends EntityFieldDefinition<any | any[]> {
@@ -8,6 +8,7 @@ import {
8
8
  FieldEqualityCondition,
9
9
  QuerySelectionModifiers,
10
10
  isSingleValueFieldEqualityCondition,
11
+ QuerySelectionModifiersWithOrderByRaw,
11
12
  } from './EntityDatabaseAdapter';
12
13
  import EntityPrivacyPolicy, { EntityPrivacyPolicyEvaluationContext } from './EntityPrivacyPolicy';
13
14
  import { EntityQueryContext } from './EntityQueryContext';
@@ -21,7 +22,7 @@ import { mapMap, mapMapAsync } from './utils/collections/maps';
21
22
 
22
23
  /**
23
24
  * The primary interface for loading entities. All normal loads are batched,
24
- * cached, and authorized against the entity's {@link EntityPrivacyPolicy}.
25
+ * cached, and authorized against the entity's EntityPrivacyPolicy.
25
26
  */
26
27
  export default class EntityLoader<
27
28
  TFields,
@@ -126,7 +127,9 @@ export default class EntityLoader<
126
127
  const entityResults = await this.loadManyByFieldEqualingAsync(uniqueFieldName, fieldValue);
127
128
  invariant(
128
129
  entityResults.length <= 1,
129
- `loadByFieldEqualing: Multiple entities of type ${this.entityClass.name} found for ${uniqueFieldName}=${fieldValue}`
130
+ `loadByFieldEqualing: Multiple entities of type ${this.entityClass.name} found for ${String(
131
+ uniqueFieldName
132
+ )}=${fieldValue}`
130
133
  );
131
134
  return entityResults[0] ?? null;
132
135
  }
@@ -242,12 +245,12 @@ export default class EntityLoader<
242
245
  * bindings: `[1]`
243
246
  * Entites returned `WHERE id = 1`
244
247
  *
245
- * {@link http://knexjs.org/#Builder-whereRaw}
246
- * {@link http://knexjs.org/#Raw-Bindings}
248
+ * http://knexjs.org/#Builder-whereRaw
249
+ * http://knexjs.org/#Raw-Bindings
247
250
  *
248
251
  * @param rawWhereClause - parameterized SQL WHERE clause with positional binding placeholders or named binding placeholders
249
252
  * @param bindings - array of positional bindings or object of named bindings
250
- * @param querySelectionModifiers - limit, offset, and orderBy for the query
253
+ * @param querySelectionModifiers - limit, offset, orderBy, and orderByRaw for the query
251
254
  * @returns array of entity results that match the query, where result error can be UnauthorizedError
252
255
  * @throws Error when rawWhereClause or bindings are invalid
253
256
  *
@@ -256,7 +259,7 @@ export default class EntityLoader<
256
259
  async loadManyByRawWhereClauseAsync(
257
260
  rawWhereClause: string,
258
261
  bindings: any[] | object,
259
- querySelectionModifiers: QuerySelectionModifiers<TFields> = {}
262
+ querySelectionModifiers: QuerySelectionModifiersWithOrderByRaw<TFields> = {}
260
263
  ): Promise<readonly Result<TEntity>[]> {
261
264
  const fieldObjects = await this.dataManager.loadManyByRawWhereClauseAsync(
262
265
  this.queryContext,
@@ -284,7 +287,7 @@ export default class EntityLoader<
284
287
  }
285
288
 
286
289
  /**
287
- * Invalidate all caches for an entity's fields. Exposed primarily for internal use by {@link EntityMutator}.
290
+ * Invalidate all caches for an entity's fields. Exposed primarily for internal use by EntityMutator.
288
291
  * @param objectFields - entity data object to be invalidated
289
292
  */
290
293
  async invalidateFieldsAsync(objectFields: Readonly<TFields>): Promise<void> {
@@ -350,7 +353,7 @@ export default class EntityLoader<
350
353
  fieldValues: readonly TFields[N][]
351
354
  ): void {
352
355
  const fieldDefinition = this.entityConfiguration.schema.get(fieldName);
353
- invariant(fieldDefinition, `must have field definition for field = ${fieldName}`);
356
+ invariant(fieldDefinition, `must have field definition for field = ${String(fieldName)}`);
354
357
  for (const fieldValue of fieldValues) {
355
358
  const isInputValid = fieldDefinition.validateInputValue(fieldValue);
356
359
  if (!isInputValid) {
@@ -20,6 +20,7 @@ export type EntityValidatorMutationInfo<
20
20
  | {
21
21
  type: EntityMutationType.UPDATE;
22
22
  previousValue: TEntity;
23
+ cascadingDeleteCause: EntityCascadingDeletionInfo | null;
23
24
  };
24
25
 
25
26
  /**
@@ -50,6 +51,7 @@ export type EntityTriggerMutationInfo<
50
51
  | {
51
52
  type: EntityMutationType.UPDATE;
52
53
  previousValue: TEntity;
54
+ cascadingDeleteCause: EntityCascadingDeletionInfo | null;
53
55
  }
54
56
  | {
55
57
  type: EntityMutationType.DELETE;
@@ -85,7 +85,7 @@ export abstract class EntityMutationTrigger<
85
85
  }
86
86
 
87
87
  /**
88
- * A non-transactional trigger is like a {@link EntityMutationTrigger} but used for afterCommit triggers
88
+ * A non-transactional trigger is like a EntityMutationTrigger but used for afterCommit triggers
89
89
  * since they explicitly occur outside of the transaction.
90
90
  */
91
91
  export abstract class EntityNonTransactionalMutationTrigger<