@expo/entity 0.26.1 → 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.
- package/LICENSE +21 -0
- package/build/ComposedEntityCacheAdapter.d.ts +1 -1
- package/build/ComposedEntityCacheAdapter.js +1 -1
- package/build/ComposedSecondaryEntityCache.d.ts +1 -1
- package/build/ComposedSecondaryEntityCache.js +1 -1
- package/build/EnforcingEntityLoader.d.ts +10 -10
- package/build/EnforcingEntityLoader.js +8 -8
- package/build/EnforcingEntityLoader.js.map +1 -1
- package/build/Entity.d.ts +5 -5
- package/build/Entity.js +5 -5
- package/build/EntityAssociationLoader.d.ts +4 -4
- package/build/EntityCacheAdapter.d.ts +1 -1
- package/build/EntityCompanion.d.ts +1 -1
- package/build/EntityCompanion.js +1 -1
- package/build/EntityCompanionProvider.d.ts +9 -9
- package/build/EntityCompanionProvider.js +3 -3
- package/build/EntityConfiguration.d.ts +2 -2
- package/build/EntityDatabaseAdapter.d.ts +15 -6
- package/build/EntityDatabaseAdapter.js +8 -2
- package/build/EntityDatabaseAdapter.js.map +1 -1
- package/build/EntityFieldDefinition.d.ts +2 -2
- package/build/EntityFields.d.ts +11 -11
- package/build/EntityFields.js +11 -11
- package/build/EntityLoader.d.ts +7 -7
- package/build/EntityLoader.js +5 -5
- package/build/EntityLoader.js.map +1 -1
- package/build/EntityMutationTriggerConfiguration.d.ts +1 -1
- package/build/EntityMutationTriggerConfiguration.js +1 -1
- package/build/EntityMutator.d.ts +1 -1
- package/build/EntityMutator.js +1 -1
- package/build/EntityPrivacyPolicy.d.ts +6 -6
- package/build/EntityPrivacyPolicy.js +6 -6
- package/build/EntityQueryContext.d.ts +3 -3
- package/build/EntityQueryContext.js +3 -3
- package/build/EntityQueryContextProvider.d.ts +1 -1
- package/build/EntitySecondaryCacheLoader.d.ts +1 -1
- package/build/EntitySecondaryCacheLoader.js +1 -1
- package/build/GenericSecondaryEntityCache.d.ts +1 -1
- package/build/GenericSecondaryEntityCache.js +1 -1
- package/build/ReadonlyEntity.d.ts +1 -1
- package/build/ReadonlyEntity.js +1 -1
- package/build/ViewerContext.d.ts +2 -2
- package/build/ViewerContext.js +2 -2
- package/build/ViewerScopedEntityCompanion.d.ts +2 -2
- package/build/ViewerScopedEntityCompanion.js +2 -2
- package/build/ViewerScopedEntityLoaderFactory.d.ts +1 -1
- package/build/ViewerScopedEntityLoaderFactory.js +1 -1
- package/build/ViewerScopedEntityMutatorFactory.d.ts +1 -1
- package/build/ViewerScopedEntityMutatorFactory.js +1 -1
- package/build/internal/EntityDataManager.d.ts +5 -5
- package/build/internal/EntityDataManager.js +3 -3
- package/build/internal/EntityDataManager.js.map +1 -1
- package/build/internal/ReadThroughEntityCache.d.ts +2 -2
- package/build/internal/ReadThroughEntityCache.js +2 -2
- package/build/metrics/IEntityMetricsAdapter.d.ts +10 -10
- package/build/rules/PrivacyPolicyRule.d.ts +1 -1
- package/build/rules/PrivacyPolicyRule.js +1 -1
- package/build/utils/collections/maps.d.ts +1 -1
- package/build/utils/collections/maps.js +1 -1
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +1 -2
- package/build/utils/testing/StubQueryContextProvider.d.ts +1 -1
- package/build/utils/testing/StubQueryContextProvider.js +2 -0
- package/build/utils/testing/StubQueryContextProvider.js.map +1 -1
- package/package.json +3 -2
- package/src/ComposedEntityCacheAdapter.ts +1 -1
- package/src/ComposedSecondaryEntityCache.ts +1 -1
- package/src/EnforcingEntityLoader.ts +14 -10
- package/src/Entity.ts +5 -5
- package/src/EntityAssociationLoader.ts +4 -4
- package/src/EntityCacheAdapter.ts +1 -1
- package/src/EntityCompanion.ts +1 -1
- package/src/EntityCompanionProvider.ts +9 -9
- package/src/EntityConfiguration.ts +2 -2
- package/src/EntityDatabaseAdapter.ts +33 -6
- package/src/EntityFieldDefinition.ts +2 -2
- package/src/EntityFields.ts +11 -11
- package/src/EntityLoader.ts +7 -6
- package/src/EntityMutationTriggerConfiguration.ts +1 -1
- package/src/EntityMutator.ts +1 -1
- package/src/EntityPrivacyPolicy.ts +6 -6
- package/src/EntityQueryContext.ts +3 -3
- package/src/EntityQueryContextProvider.ts +1 -1
- package/src/EntitySecondaryCacheLoader.ts +1 -1
- package/src/GenericSecondaryEntityCache.ts +1 -1
- package/src/ReadonlyEntity.ts +1 -1
- package/src/ViewerContext.ts +2 -2
- package/src/ViewerScopedEntityCompanion.ts +2 -2
- package/src/ViewerScopedEntityLoaderFactory.ts +1 -1
- package/src/ViewerScopedEntityMutatorFactory.ts +1 -1
- package/src/internal/EntityDataManager.ts +5 -4
- package/src/internal/ReadThroughEntityCache.ts +2 -2
- package/src/metrics/IEntityMetricsAdapter.ts +10 -10
- package/src/rules/PrivacyPolicyRule.ts +1 -1
- package/src/utils/collections/maps.ts +1 -1
- package/src/utils/testing/PrivacyPolicyRuleTestUtils.ts +1 -1
- package/src/utils/testing/StubQueryContextProvider.ts +1 -1
|
@@ -7,12 +7,18 @@ import {
|
|
|
7
7
|
FieldTransformerMap,
|
|
8
8
|
} from './internal/EntityFieldTransformationUtils';
|
|
9
9
|
|
|
10
|
-
interface SingleValueFieldEqualityCondition<
|
|
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<
|
|
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
|
|
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:
|
|
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.
|
|
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:
|
|
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 {
|
|
@@ -87,8 +87,8 @@ export interface EntityAssociationDefinition<
|
|
|
87
87
|
* application requirements, and sometimes even a mix-and-match is the right choice.
|
|
88
88
|
*
|
|
89
89
|
* - If referential integrity is critical to your application, database foreign key constraints
|
|
90
|
-
* combined with
|
|
91
|
-
*
|
|
90
|
+
* combined with EntityEdgeDeletionBehavior.CASCADE_DELETE_INVALIDATE_CACHE_ONLY or
|
|
91
|
+
* EntityEdgeDeletionBehavior.SET_NULL_INVALIDATE_CACHE_ONLY are recommended.
|
|
92
92
|
* - If the database being used doesn't support foreign keys, then using the entity framework for referential
|
|
93
93
|
* integrity is recommended.
|
|
94
94
|
*/
|
package/src/EntityFields.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { validate as validateUUID } from 'uuid';
|
|
|
3
3
|
import { EntityFieldDefinition } from './EntityFieldDefinition';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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[]> {
|
package/src/EntityLoader.ts
CHANGED
|
@@ -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
|
|
25
|
+
* cached, and authorized against the entity's EntityPrivacyPolicy.
|
|
25
26
|
*/
|
|
26
27
|
export default class EntityLoader<
|
|
27
28
|
TFields,
|
|
@@ -244,12 +245,12 @@ export default class EntityLoader<
|
|
|
244
245
|
* bindings: `[1]`
|
|
245
246
|
* Entites returned `WHERE id = 1`
|
|
246
247
|
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
248
|
+
* http://knexjs.org/#Builder-whereRaw
|
|
249
|
+
* http://knexjs.org/#Raw-Bindings
|
|
249
250
|
*
|
|
250
251
|
* @param rawWhereClause - parameterized SQL WHERE clause with positional binding placeholders or named binding placeholders
|
|
251
252
|
* @param bindings - array of positional bindings or object of named bindings
|
|
252
|
-
* @param querySelectionModifiers - limit, offset, and
|
|
253
|
+
* @param querySelectionModifiers - limit, offset, orderBy, and orderByRaw for the query
|
|
253
254
|
* @returns array of entity results that match the query, where result error can be UnauthorizedError
|
|
254
255
|
* @throws Error when rawWhereClause or bindings are invalid
|
|
255
256
|
*
|
|
@@ -258,7 +259,7 @@ export default class EntityLoader<
|
|
|
258
259
|
async loadManyByRawWhereClauseAsync(
|
|
259
260
|
rawWhereClause: string,
|
|
260
261
|
bindings: any[] | object,
|
|
261
|
-
querySelectionModifiers:
|
|
262
|
+
querySelectionModifiers: QuerySelectionModifiersWithOrderByRaw<TFields> = {}
|
|
262
263
|
): Promise<readonly Result<TEntity>[]> {
|
|
263
264
|
const fieldObjects = await this.dataManager.loadManyByRawWhereClauseAsync(
|
|
264
265
|
this.queryContext,
|
|
@@ -286,7 +287,7 @@ export default class EntityLoader<
|
|
|
286
287
|
}
|
|
287
288
|
|
|
288
289
|
/**
|
|
289
|
-
* Invalidate all caches for an entity's fields. Exposed primarily for internal use by
|
|
290
|
+
* Invalidate all caches for an entity's fields. Exposed primarily for internal use by EntityMutator.
|
|
290
291
|
* @param objectFields - entity data object to be invalidated
|
|
291
292
|
*/
|
|
292
293
|
async invalidateFieldsAsync(objectFields: Readonly<TFields>): Promise<void> {
|
|
@@ -85,7 +85,7 @@ export abstract class EntityMutationTrigger<
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
|
-
* A non-transactional trigger is like a
|
|
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<
|
package/src/EntityMutator.ts
CHANGED
|
@@ -700,7 +700,7 @@ export class DeleteMutator<
|
|
|
700
700
|
/**
|
|
701
701
|
* Finds all entities referencing the specified entity and either deletes them, nullifies
|
|
702
702
|
* their references to the specified entity, or invalidates the cache depending on the
|
|
703
|
-
*
|
|
703
|
+
* OnDeleteBehavior of the field referencing the specified entity.
|
|
704
704
|
*
|
|
705
705
|
* @remarks
|
|
706
706
|
* This works by doing reverse fan-out queries:
|
|
@@ -20,7 +20,7 @@ export type EntityPrivacyPolicyEvaluationContext = {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* Evaluation mode for a
|
|
23
|
+
* Evaluation mode for a EntityPrivacyPolicy. Useful when transitioning to
|
|
24
24
|
* using Entity for privacy.
|
|
25
25
|
*/
|
|
26
26
|
export enum EntityPrivacyPolicyEvaluationMode {
|
|
@@ -75,7 +75,7 @@ export enum EntityAuthorizationAction {
|
|
|
75
75
|
*
|
|
76
76
|
* @remarks
|
|
77
77
|
*
|
|
78
|
-
* A privacy policy declares lists of
|
|
78
|
+
* A privacy policy declares lists of PrivacyPolicyRule for create, read, update, and delete actions
|
|
79
79
|
* for an entity and provides logic for authorizing an entity against rules.
|
|
80
80
|
*
|
|
81
81
|
* Evaluation of a list of rules is performed according the following example. This allows constructing of
|
|
@@ -149,7 +149,7 @@ export default abstract class EntityPrivacyPolicy<
|
|
|
149
149
|
* @param queryContext - query context in which to perform the create authorization
|
|
150
150
|
* @param entity - entity to authorize
|
|
151
151
|
* @returns entity if authorized
|
|
152
|
-
* @throws
|
|
152
|
+
* @throws EntityNotAuthorizedError when not authorized
|
|
153
153
|
*/
|
|
154
154
|
async authorizeCreateAsync(
|
|
155
155
|
viewerContext: TViewerContext,
|
|
@@ -175,7 +175,7 @@ export default abstract class EntityPrivacyPolicy<
|
|
|
175
175
|
* @param queryContext - query context in which to perform the read authorization
|
|
176
176
|
* @param entity - entity to authorize
|
|
177
177
|
* @returns entity if authorized
|
|
178
|
-
* @throws
|
|
178
|
+
* @throws EntityNotAuthorizedError when not authorized
|
|
179
179
|
*/
|
|
180
180
|
async authorizeReadAsync(
|
|
181
181
|
viewerContext: TViewerContext,
|
|
@@ -201,7 +201,7 @@ export default abstract class EntityPrivacyPolicy<
|
|
|
201
201
|
* @param queryContext - query context in which to perform the update authorization
|
|
202
202
|
* @param entity - entity to authorize
|
|
203
203
|
* @returns entity if authorized
|
|
204
|
-
* @throws
|
|
204
|
+
* @throws EntityNotAuthorizedError when not authorized
|
|
205
205
|
*/
|
|
206
206
|
async authorizeUpdateAsync(
|
|
207
207
|
viewerContext: TViewerContext,
|
|
@@ -227,7 +227,7 @@ export default abstract class EntityPrivacyPolicy<
|
|
|
227
227
|
* @param queryContext - query context in which to perform the delete authorization
|
|
228
228
|
* @param entity - entity to authorize
|
|
229
229
|
* @returns entity if authorized
|
|
230
|
-
* @throws
|
|
230
|
+
* @throws EntityNotAuthorizedError when not authorized
|
|
231
231
|
*/
|
|
232
232
|
async authorizeDeleteAsync(
|
|
233
233
|
viewerContext: TViewerContext,
|
|
@@ -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
|
|
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
|
|
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
|
|
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 {
|
|
@@ -20,7 +20,7 @@ export default abstract class EntityQueryContextProvider {
|
|
|
20
20
|
protected abstract getQueryInterface(): any;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* Vend a transaction runner for use in
|
|
23
|
+
* Vend a transaction runner for use in runInTransactionAsync.
|
|
24
24
|
*/
|
|
25
25
|
protected abstract createTransactionRunner<T>(): (
|
|
26
26
|
transactionScope: (queryInterface: any) => Promise<T>
|
|
@@ -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
|
|
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
|
|
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>
|
package/src/ReadonlyEntity.ts
CHANGED
package/src/ViewerContext.ts
CHANGED
|
@@ -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
|
|
10
|
+
* A viewer context encapsulates all information necessary to evaluate an EntityPrivacyPolicy.
|
|
11
11
|
*
|
|
12
|
-
* In combination with an
|
|
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
|
|
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
|
|
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
|
|
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
|
|
9
|
+
* Provides a cleaner API for mutating entities by passing through the ViewerContext.
|
|
10
10
|
*/
|
|
11
11
|
export default class ViewerScopedEntityMutatorFactory<
|
|
12
12
|
TFields,
|
|
@@ -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,
|
|
24
|
+
* data including local caches, EntityCacheAdapter, and EntityDatabaseAdapter.
|
|
24
25
|
*
|
|
25
|
-
* It is also responsible for invalidating all sources of data when mutated using
|
|
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
|
|
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:
|
|
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
|
|
27
|
-
*
|
|
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
|
|
13
|
+
* Event about a single call to an EntityLoader method.
|
|
14
14
|
*/
|
|
15
15
|
export interface EntityMetricsLoadEvent {
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* EntityMetricsLoadType for this load.
|
|
18
18
|
*/
|
|
19
19
|
type: EntityMetricsLoadType;
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* Class name of the
|
|
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
|
-
*
|
|
45
|
+
* EntityMetricsMutationType for this mutation.
|
|
46
46
|
*/
|
|
47
47
|
type: EntityMetricsMutationType;
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
-
* Class name of the
|
|
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
|
|
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
|
|
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
|
|
104
|
+
* Event used to record a singe EntityPrivacyPolicy authorization.
|
|
105
105
|
*/
|
|
106
106
|
export interface EntityMetricsAuthorizationEvent {
|
|
107
107
|
/**
|
|
108
|
-
* Class name of the
|
|
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
|
|
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 (
|
|
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
|
|
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
|
*
|
|
@@ -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
|
}
|