@expo/entity 0.55.0 → 0.57.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/build/src/AuthorizationResultBasedEntityAssociationLoader.d.ts +1 -1
- package/build/src/AuthorizationResultBasedEntityAssociationLoader.js.map +1 -1
- package/build/src/AuthorizationResultBasedEntityLoader.d.ts +18 -24
- package/build/src/AuthorizationResultBasedEntityLoader.js +37 -56
- package/build/src/AuthorizationResultBasedEntityLoader.js.map +1 -1
- package/build/src/AuthorizationResultBasedEntityMutator.js +26 -19
- package/build/src/AuthorizationResultBasedEntityMutator.js.map +1 -1
- package/build/src/EnforcingEntityCreator.d.ts +1 -1
- package/build/src/EnforcingEntityCreator.js +1 -1
- package/build/src/EnforcingEntityLoader.d.ts +1 -58
- package/build/src/EnforcingEntityLoader.js +0 -65
- package/build/src/EnforcingEntityLoader.js.map +1 -1
- package/build/src/Entity.d.ts +6 -0
- package/build/src/Entity.js +6 -0
- package/build/src/Entity.js.map +1 -1
- package/build/src/EntityCompanion.d.ts +2 -2
- package/build/src/EntityCompanion.js.map +1 -1
- package/build/src/EntityCompanionProvider.d.ts +1 -1
- package/build/src/EntityCompanionProvider.js +4 -4
- package/build/src/EntityConfiguration.d.ts +1 -1
- package/build/src/EntityConfiguration.js +1 -2
- package/build/src/EntityConfiguration.js.map +1 -1
- package/build/src/{EntityLoaderUtils.d.ts → EntityConstructionUtils.d.ts} +15 -29
- package/build/src/EntityConstructionUtils.js +118 -0
- package/build/src/EntityConstructionUtils.js.map +1 -0
- package/build/src/EntityDatabaseAdapter.d.ts +10 -108
- package/build/src/EntityDatabaseAdapter.js +14 -76
- package/build/src/EntityDatabaseAdapter.js.map +1 -1
- package/build/src/EntityFieldDefinition.d.ts +1 -1
- package/build/src/EntityInvalidationUtils.d.ts +41 -0
- package/build/src/EntityInvalidationUtils.js +71 -0
- package/build/src/EntityInvalidationUtils.js.map +1 -0
- package/build/src/EntityLoader.d.ts +0 -6
- package/build/src/EntityLoader.js +0 -7
- package/build/src/EntityLoader.js.map +1 -1
- package/build/src/EntityLoaderFactory.d.ts +4 -0
- package/build/src/EntityLoaderFactory.js +10 -3
- package/build/src/EntityLoaderFactory.js.map +1 -1
- package/build/src/EntityPrivacyPolicy.d.ts +27 -0
- package/build/src/EntityPrivacyPolicy.js +22 -1
- package/build/src/EntityPrivacyPolicy.js.map +1 -1
- package/build/src/EntitySecondaryCacheLoader.d.ts +14 -3
- package/build/src/EntitySecondaryCacheLoader.js +21 -4
- package/build/src/EntitySecondaryCacheLoader.js.map +1 -1
- package/build/src/ReadonlyEntity.d.ts +4 -5
- package/build/src/ReadonlyEntity.js +7 -8
- package/build/src/ReadonlyEntity.js.map +1 -1
- package/build/src/ViewerContext.d.ts +6 -6
- package/build/src/ViewerContext.js +8 -8
- package/build/src/ViewerScopedEntityCompanion.d.ts +1 -1
- package/build/src/ViewerScopedEntityCompanion.js.map +1 -1
- package/build/src/ViewerScopedEntityLoaderFactory.d.ts +4 -0
- package/build/src/ViewerScopedEntityLoaderFactory.js +6 -0
- package/build/src/ViewerScopedEntityLoaderFactory.js.map +1 -1
- package/build/src/errors/EntityDatabaseAdapterError.d.ts +4 -0
- package/build/src/errors/EntityDatabaseAdapterError.js +13 -1
- package/build/src/errors/EntityDatabaseAdapterError.js.map +1 -1
- package/build/src/errors/EntityError.d.ts +2 -1
- package/build/src/errors/EntityError.js +1 -0
- package/build/src/errors/EntityError.js.map +1 -1
- package/build/src/index.d.ts +2 -1
- package/build/src/index.js +2 -1
- package/build/src/index.js.map +1 -1
- package/build/src/internal/EntityDataManager.d.ts +8 -16
- package/build/src/internal/EntityDataManager.js +8 -18
- package/build/src/internal/EntityDataManager.js.map +1 -1
- package/build/src/internal/EntityFieldTransformationUtils.js.map +1 -1
- package/build/src/internal/EntityLoadInterfaces.d.ts +2 -0
- package/build/src/internal/EntityLoadInterfaces.js +2 -0
- package/build/src/internal/EntityLoadInterfaces.js.map +1 -1
- package/build/src/internal/EntityTableDataCoordinator.d.ts +2 -0
- package/build/src/internal/EntityTableDataCoordinator.js +4 -0
- package/build/src/internal/EntityTableDataCoordinator.js.map +1 -1
- package/build/src/metrics/EntityMetricsUtils.d.ts +1 -0
- package/build/src/metrics/EntityMetricsUtils.js +15 -1
- package/build/src/metrics/EntityMetricsUtils.js.map +1 -1
- package/build/src/metrics/IEntityMetricsAdapter.d.ts +4 -1
- package/build/src/metrics/IEntityMetricsAdapter.js +3 -0
- package/build/src/metrics/IEntityMetricsAdapter.js.map +1 -1
- package/build/src/rules/AllowIfAllSubRulesAllowPrivacyPolicyRule.d.ts +2 -2
- package/build/src/rules/AllowIfAnySubRuleAllowsPrivacyPolicyRule.d.ts +2 -2
- package/build/src/rules/EvaluateIfEntityFieldPredicatePrivacyPolicyRule.d.ts +2 -2
- package/build/src/rules/PrivacyPolicyRule.d.ts +2 -2
- package/build/src/utils/EntityPrivacyUtils.js +11 -20
- package/build/src/utils/EntityPrivacyUtils.js.map +1 -1
- package/build/src/utils/collections/maps.d.ts +2 -2
- package/build/src/utils/collections/maps.js +2 -2
- package/package.json +4 -4
- package/src/AuthorizationResultBasedEntityAssociationLoader.ts +4 -7
- package/src/AuthorizationResultBasedEntityLoader.ts +58 -88
- package/src/AuthorizationResultBasedEntityMutator.ts +35 -20
- package/src/EnforcingEntityCreator.ts +1 -1
- package/src/EnforcingEntityLoader.ts +1 -95
- package/src/Entity.ts +6 -0
- package/src/EntityCompanion.ts +2 -2
- package/src/EntityCompanionProvider.ts +4 -4
- package/src/EntityConfiguration.ts +8 -5
- package/src/EntityConstructionUtils.ts +168 -0
- package/src/EntityDatabaseAdapter.ts +32 -222
- package/src/EntityFieldDefinition.ts +1 -1
- package/src/{EntityLoaderUtils.ts → EntityInvalidationUtils.ts} +5 -96
- package/src/EntityLoader.ts +0 -16
- package/src/EntityLoaderFactory.ts +50 -10
- package/src/EntityPrivacyPolicy.ts +44 -1
- package/src/EntitySecondaryCacheLoader.ts +54 -3
- package/src/ReadonlyEntity.ts +9 -11
- package/src/ViewerContext.ts +10 -10
- package/src/ViewerScopedEntityCompanion.ts +1 -1
- package/src/ViewerScopedEntityLoaderFactory.ts +37 -0
- package/src/__tests__/AuthorizationResultBasedEntityLoader-constructor-test.ts +3 -5
- package/src/__tests__/AuthorizationResultBasedEntityLoader-test.ts +34 -419
- package/src/__tests__/ComposedCacheAdapter-test.ts +3 -3
- package/src/__tests__/EnforcingEntityLoader-test.ts +2 -134
- package/src/__tests__/EntityCompanion-test.ts +18 -0
- package/src/__tests__/EntityConfiguration-test.ts +4 -4
- package/src/__tests__/EntityDatabaseAdapter-test.ts +33 -68
- package/src/__tests__/EntityEdges-test.ts +10 -10
- package/src/__tests__/EntityLoader-test.ts +6 -4
- package/src/__tests__/EntityMutator-test.ts +27 -15
- package/src/__tests__/EntityPrivacyPolicy-test.ts +102 -0
- package/src/__tests__/EntityQueryContext-test.ts +11 -11
- package/src/__tests__/EntitySecondaryCacheLoader-test.ts +10 -5
- package/src/__tests__/EntitySelfReferentialEdges-test.ts +6 -6
- package/src/__tests__/GenericEntityCacheAdapter-test.ts +18 -15
- package/src/__tests__/GenericSecondaryEntityCache-test.ts +27 -5
- package/src/__tests__/ReadonlyEntity-test.ts +6 -4
- package/src/__tests__/ViewerContext-test.ts +4 -4
- package/src/__tests__/ViewerScopedEntityCompanion-test.ts +1 -0
- package/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts +0 -17
- package/src/errors/EntityDatabaseAdapterError.ts +14 -0
- package/src/errors/EntityError.ts +1 -0
- package/src/errors/__tests__/EntityDatabaseAdapterError-test.ts +9 -0
- package/src/errors/__tests__/EntityError-test.ts +13 -5
- package/src/index.ts +2 -1
- package/src/internal/EntityDataManager.ts +19 -54
- package/src/internal/EntityFieldTransformationUtils.ts +5 -5
- package/src/internal/EntityLoadInterfaces.ts +2 -0
- package/src/internal/EntityTableDataCoordinator.ts +2 -2
- package/src/internal/__tests__/CompositeFieldHolder-test.ts +8 -2
- package/src/internal/__tests__/EntityDataManager-test.ts +71 -202
- package/src/internal/__tests__/ReadThroughEntityCache-test.ts +39 -24
- package/src/metrics/EntityMetricsUtils.ts +23 -0
- package/src/metrics/IEntityMetricsAdapter.ts +3 -0
- package/src/metrics/__tests__/EntityMetricsUtils-test.ts +120 -0
- package/src/rules/AllowIfAllSubRulesAllowPrivacyPolicyRule.ts +2 -2
- package/src/rules/AllowIfAnySubRuleAllowsPrivacyPolicyRule.ts +2 -2
- package/src/rules/EvaluateIfEntityFieldPredicatePrivacyPolicyRule.ts +2 -2
- package/src/rules/PrivacyPolicyRule.ts +2 -2
- package/src/rules/__tests__/AllowIfAllSubRulesAllowPrivacyPolicyRule-test.ts +4 -4
- package/src/rules/__tests__/AllowIfAnySubRuleAllowsPrivacyPolicyRule-test.ts +4 -4
- package/src/rules/__tests__/AllowIfInParentCascadeDeletionPrivacyPolicyRule-test.ts +11 -1
- package/src/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.ts +2 -2
- package/src/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.ts +2 -2
- package/src/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.ts +2 -2
- package/src/rules/__tests__/EvaluateIfEntityFieldPredicatePrivacyPolicyRule-test.ts +3 -3
- package/src/utils/EntityPrivacyUtils.ts +18 -29
- package/src/utils/__testfixtures__/PrivacyPolicyRuleTestUtils.ts +2 -2
- package/src/utils/__testfixtures__/StubDatabaseAdapter.ts +13 -101
- package/src/utils/__tests__/EntityCreationUtils-test.ts +6 -6
- package/src/utils/__tests__/EntityPrivacyUtils-test.ts +2 -2
- package/src/utils/collections/maps.ts +2 -2
- package/build/src/EntityLoaderUtils.js +0 -147
- package/build/src/EntityLoaderUtils.js.map +0 -1
|
@@ -354,13 +354,16 @@ async function canViewerDeleteInternalAsync<
|
|
|
354
354
|
entityCompanionProvider.getCompanionForEntity(inboundEdge).entityCompanionDefinition
|
|
355
355
|
.entityConfiguration;
|
|
356
356
|
|
|
357
|
-
const
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
357
|
+
const entityCompanion = viewerContext.getViewerScopedEntityCompanionForClass(inboundEdge);
|
|
358
|
+
const loaderFactory = entityCompanion.getLoaderFactory();
|
|
359
|
+
const loader = loaderFactory.forLoad(queryContext, {
|
|
360
|
+
previousValue: null,
|
|
361
|
+
cascadingDeleteCause: newCascadingDeleteCause,
|
|
362
|
+
});
|
|
363
|
+
const constructionUtils = loaderFactory.constructionUtils(queryContext, {
|
|
364
|
+
previousValue: null,
|
|
365
|
+
cascadingDeleteCause: newCascadingDeleteCause,
|
|
366
|
+
});
|
|
364
367
|
|
|
365
368
|
for (const [fieldName, fieldDefinition] of configurationForInboundEdge.schema) {
|
|
366
369
|
const association = fieldDefinition.association;
|
|
@@ -384,18 +387,12 @@ async function canViewerDeleteInternalAsync<
|
|
|
384
387
|
edgeDeletionPermissionInferenceBehavior ===
|
|
385
388
|
EntityEdgeDeletionAuthorizationInferenceBehavior.ONE_IMPLIES_ALL
|
|
386
389
|
) {
|
|
387
|
-
const singleEntityResultToTestForInboundEdge =
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
? sourceEntity.getField(association.associatedEntityLookupByField as any)
|
|
394
|
-
: sourceEntity.getID(),
|
|
395
|
-
},
|
|
396
|
-
],
|
|
397
|
-
{ orderBy: [] },
|
|
398
|
-
);
|
|
390
|
+
const singleEntityResultToTestForInboundEdge = await loader['loadOneByFieldEqualingAsync'](
|
|
391
|
+
fieldName,
|
|
392
|
+
association.associatedEntityLookupByField
|
|
393
|
+
? sourceEntity.getField(association.associatedEntityLookupByField)
|
|
394
|
+
: sourceEntity.getID(),
|
|
395
|
+
);
|
|
399
396
|
entityResultsToCheckForInboundEdge = singleEntityResultToTestForInboundEdge
|
|
400
397
|
? [singleEntityResultToTestForInboundEdge]
|
|
401
398
|
: [];
|
|
@@ -403,7 +400,7 @@ async function canViewerDeleteInternalAsync<
|
|
|
403
400
|
const entityResultsForInboundEdge = await loader.loadManyByFieldEqualingAsync(
|
|
404
401
|
fieldName,
|
|
405
402
|
association.associatedEntityLookupByField
|
|
406
|
-
? sourceEntity.getField(association.associatedEntityLookupByField
|
|
403
|
+
? sourceEntity.getField(association.associatedEntityLookupByField)
|
|
407
404
|
: sourceEntity.getID(),
|
|
408
405
|
);
|
|
409
406
|
entityResultsToCheckForInboundEdge = entityResultsForInboundEdge;
|
|
@@ -451,14 +448,6 @@ async function canViewerDeleteInternalAsync<
|
|
|
451
448
|
// privacy policy as it would be after the cascading SET NULL operation
|
|
452
449
|
const previousAndSyntheticEntitiesForInboundEdge = entitiesForInboundEdge.map(
|
|
453
450
|
(entity) => {
|
|
454
|
-
const entityLoader = viewerContext
|
|
455
|
-
.getViewerScopedEntityCompanionForClass(inboundEdge)
|
|
456
|
-
.getLoaderFactory()
|
|
457
|
-
.forLoad(queryContext, {
|
|
458
|
-
previousValue: entity,
|
|
459
|
-
cascadingDeleteCause: newCascadingDeleteCause,
|
|
460
|
-
});
|
|
461
|
-
|
|
462
451
|
const allFields = entity.getAllDatabaseFields();
|
|
463
452
|
const syntheticFields = {
|
|
464
453
|
...allFields,
|
|
@@ -467,7 +456,7 @@ async function canViewerDeleteInternalAsync<
|
|
|
467
456
|
|
|
468
457
|
return {
|
|
469
458
|
previousValue: entity,
|
|
470
|
-
syntheticallyUpdatedValue:
|
|
459
|
+
syntheticallyUpdatedValue: constructionUtils.constructEntity(syntheticFields),
|
|
471
460
|
};
|
|
472
461
|
},
|
|
473
462
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from '@jest/globals';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { EntityPrivacyPolicyRuleEvaluationContext } from '../../EntityPrivacyPolicy';
|
|
4
4
|
import { EntityQueryContext } from '../../EntityQueryContext';
|
|
5
5
|
import { ReadonlyEntity } from '../../ReadonlyEntity';
|
|
6
6
|
import { ViewerContext } from '../../ViewerContext';
|
|
@@ -15,7 +15,7 @@ export interface Case<
|
|
|
15
15
|
> {
|
|
16
16
|
viewerContext: TViewerContext;
|
|
17
17
|
queryContext: EntityQueryContext;
|
|
18
|
-
evaluationContext:
|
|
18
|
+
evaluationContext: EntityPrivacyPolicyRuleEvaluationContext<
|
|
19
19
|
TFields,
|
|
20
20
|
TIDField,
|
|
21
21
|
TViewerContext,
|
|
@@ -2,13 +2,7 @@ import invariant from 'invariant';
|
|
|
2
2
|
import { v7 as uuidv7 } from 'uuid';
|
|
3
3
|
|
|
4
4
|
import { EntityConfiguration } from '../../EntityConfiguration';
|
|
5
|
-
import {
|
|
6
|
-
EntityDatabaseAdapter,
|
|
7
|
-
OrderByOrdering,
|
|
8
|
-
TableFieldMultiValueEqualityCondition,
|
|
9
|
-
TableFieldSingleValueEqualityCondition,
|
|
10
|
-
TableQuerySelectionModifiers,
|
|
11
|
-
} from '../../EntityDatabaseAdapter';
|
|
5
|
+
import { EntityDatabaseAdapter } from '../../EntityDatabaseAdapter';
|
|
12
6
|
import { IntField, StringField } from '../../EntityFields';
|
|
13
7
|
import {
|
|
14
8
|
FieldTransformerMap,
|
|
@@ -84,101 +78,19 @@ export class StubDatabaseAdapter<
|
|
|
84
78
|
return [...results];
|
|
85
79
|
}
|
|
86
80
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
columnName: string;
|
|
90
|
-
order: OrderByOrdering;
|
|
91
|
-
}[],
|
|
92
|
-
objectA: { [key: string]: any },
|
|
93
|
-
objectB: { [key: string]: any },
|
|
94
|
-
): 0 | 1 | -1 {
|
|
95
|
-
if (orderBys.length === 0) {
|
|
96
|
-
return 0;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const currentOrderBy = orderBys[0]!;
|
|
100
|
-
const aField = objectA[currentOrderBy.columnName];
|
|
101
|
-
const bField = objectB[currentOrderBy.columnName];
|
|
102
|
-
switch (currentOrderBy.order) {
|
|
103
|
-
case OrderByOrdering.DESCENDING: {
|
|
104
|
-
// simulate NULLS FIRST for DESC
|
|
105
|
-
if (aField === null && bField === null) {
|
|
106
|
-
return 0;
|
|
107
|
-
} else if (aField === null) {
|
|
108
|
-
return -1;
|
|
109
|
-
} else if (bField === null) {
|
|
110
|
-
return 1;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return aField > bField
|
|
114
|
-
? -1
|
|
115
|
-
: aField < bField
|
|
116
|
-
? 1
|
|
117
|
-
: this.compareByOrderBys(orderBys.slice(1), objectA, objectB);
|
|
118
|
-
}
|
|
119
|
-
case OrderByOrdering.ASCENDING: {
|
|
120
|
-
// simulate NULLS LAST for ASC
|
|
121
|
-
if (aField === null && bField === null) {
|
|
122
|
-
return 0;
|
|
123
|
-
} else if (bField === null) {
|
|
124
|
-
return -1;
|
|
125
|
-
} else if (aField === null) {
|
|
126
|
-
return 1;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return bField > aField
|
|
130
|
-
? -1
|
|
131
|
-
: bField < aField
|
|
132
|
-
? 1
|
|
133
|
-
: this.compareByOrderBys(orderBys.slice(1), objectA, objectB);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
protected async fetchManyByFieldEqualityConjunctionInternalAsync(
|
|
139
|
-
_queryInterface: any,
|
|
81
|
+
protected async fetchOneWhereInternalAsync(
|
|
82
|
+
queryInterface: any,
|
|
140
83
|
tableName: string,
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
filteredObjects = filteredObjects.filter((obj) => tableValues.includes(obj[tableField]));
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const orderBy = querySelectionModifiers.orderBy;
|
|
155
|
-
if (orderBy !== undefined) {
|
|
156
|
-
filteredObjects = filteredObjects.sort((a, b) =>
|
|
157
|
-
StubDatabaseAdapter.compareByOrderBys(orderBy, a, b),
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const offset = querySelectionModifiers.offset;
|
|
162
|
-
if (offset !== undefined) {
|
|
163
|
-
filteredObjects = filteredObjects.slice(offset);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const limit = querySelectionModifiers.limit;
|
|
167
|
-
if (limit !== undefined) {
|
|
168
|
-
filteredObjects = filteredObjects.slice(0, 0 + limit);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return filteredObjects;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
protected fetchManyByRawWhereClauseInternalAsync(
|
|
175
|
-
_queryInterface: any,
|
|
176
|
-
_tableName: string,
|
|
177
|
-
_rawWhereClause: string,
|
|
178
|
-
_bindings: object | any[],
|
|
179
|
-
_querySelectionModifiers: TableQuerySelectionModifiers,
|
|
180
|
-
): Promise<object[]> {
|
|
181
|
-
throw new Error('Raw WHERE clauses not supported for StubDatabaseAdapter');
|
|
84
|
+
tableColumns: readonly string[],
|
|
85
|
+
tableTuple: readonly any[],
|
|
86
|
+
): Promise<object | null> {
|
|
87
|
+
const results = await this.fetchManyWhereInternalAsync(
|
|
88
|
+
queryInterface,
|
|
89
|
+
tableName,
|
|
90
|
+
tableColumns,
|
|
91
|
+
[tableTuple],
|
|
92
|
+
);
|
|
93
|
+
return results[0] ?? null;
|
|
182
94
|
}
|
|
183
95
|
|
|
184
96
|
private generateRandomID(): any {
|
|
@@ -40,7 +40,7 @@ describe.each([true, false])('in transaction %p', (inTransaction) => {
|
|
|
40
40
|
);
|
|
41
41
|
|
|
42
42
|
if (inTransaction) {
|
|
43
|
-
await viewerContext.
|
|
43
|
+
await viewerContext.runInTransactionForDatabaseAdapterFlavorAsync(
|
|
44
44
|
'postgres',
|
|
45
45
|
async (queryContext) => {
|
|
46
46
|
await createOrGetExistingAsync(
|
|
@@ -92,7 +92,7 @@ describe.each([true, false])('in transaction %p', (inTransaction) => {
|
|
|
92
92
|
);
|
|
93
93
|
|
|
94
94
|
if (inTransaction) {
|
|
95
|
-
await viewerContext.
|
|
95
|
+
await viewerContext.runInTransactionForDatabaseAdapterFlavorAsync(
|
|
96
96
|
'postgres',
|
|
97
97
|
async (queryContext) => {
|
|
98
98
|
await createOrGetExistingAsync(
|
|
@@ -146,7 +146,7 @@ describe.each([true, false])('in transaction %p', (inTransaction) => {
|
|
|
146
146
|
);
|
|
147
147
|
|
|
148
148
|
if (inTransaction) {
|
|
149
|
-
await viewerContext.
|
|
149
|
+
await viewerContext.runInTransactionForDatabaseAdapterFlavorAsync(
|
|
150
150
|
'postgres',
|
|
151
151
|
async (queryContext) => {
|
|
152
152
|
await createWithUniqueConstraintRecoveryAsync(
|
|
@@ -204,7 +204,7 @@ describe.each([true, false])('in transaction %p', (inTransaction) => {
|
|
|
204
204
|
);
|
|
205
205
|
|
|
206
206
|
if (inTransaction) {
|
|
207
|
-
await viewerContext.
|
|
207
|
+
await viewerContext.runInTransactionForDatabaseAdapterFlavorAsync(
|
|
208
208
|
'postgres',
|
|
209
209
|
async (queryContext) => {
|
|
210
210
|
await createWithUniqueConstraintRecoveryAsync(
|
|
@@ -261,7 +261,7 @@ describe.each([true, false])('in transaction %p', (inTransaction) => {
|
|
|
261
261
|
|
|
262
262
|
if (inTransaction) {
|
|
263
263
|
await expect(
|
|
264
|
-
viewerContext.
|
|
264
|
+
viewerContext.runInTransactionForDatabaseAdapterFlavorAsync(
|
|
265
265
|
'postgres',
|
|
266
266
|
async (queryContext) => {
|
|
267
267
|
return await createWithUniqueConstraintRecoveryAsync(
|
|
@@ -321,7 +321,7 @@ describe.each([true, false])('in transaction %p', (inTransaction) => {
|
|
|
321
321
|
|
|
322
322
|
if (inTransaction) {
|
|
323
323
|
await expect(
|
|
324
|
-
viewerContext.
|
|
324
|
+
viewerContext.runInTransactionForDatabaseAdapterFlavorAsync(
|
|
325
325
|
'postgres',
|
|
326
326
|
async (queryContext) => {
|
|
327
327
|
return await createWithUniqueConstraintRecoveryAsync(
|
|
@@ -232,7 +232,7 @@ describe(canViewerDeleteAsync, () => {
|
|
|
232
232
|
it('supports running within a transaction', async () => {
|
|
233
233
|
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
234
234
|
const viewerContext = new ViewerContext(companionProvider);
|
|
235
|
-
const canViewerDelete = await viewerContext.
|
|
235
|
+
const canViewerDelete = await viewerContext.runInTransactionForDatabaseAdapterFlavorAsync(
|
|
236
236
|
'postgres',
|
|
237
237
|
async (queryContext) => {
|
|
238
238
|
const testEntity = await SimpleTestDenyUpdateEntity.creator(
|
|
@@ -248,7 +248,7 @@ describe(canViewerDeleteAsync, () => {
|
|
|
248
248
|
);
|
|
249
249
|
expect(canViewerDelete).toBe(true);
|
|
250
250
|
|
|
251
|
-
const canViewerDeleteResult = await viewerContext.
|
|
251
|
+
const canViewerDeleteResult = await viewerContext.runInTransactionForDatabaseAdapterFlavorAsync(
|
|
252
252
|
'postgres',
|
|
253
253
|
async (queryContext) => {
|
|
254
254
|
const testEntity = await SimpleTestDenyUpdateEntity.creator(
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import invariant from 'invariant';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* If the specified key is not already associated with a value in this map,
|
|
5
|
-
* its value using the given mapping function and enters it into this map
|
|
4
|
+
* If the specified key is not already associated with a value in this map, computes
|
|
5
|
+
* its value using the given mapping function and enters it into this map.
|
|
6
6
|
*
|
|
7
7
|
* @param map - map from which to get the key's value or compute and associate
|
|
8
8
|
* @param key - key for which to get the value or with which the computed value is to be associated
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.EntityLoaderUtils = void 0;
|
|
7
|
-
const results_1 = require("@expo/results");
|
|
8
|
-
const nullthrows_1 = __importDefault(require("nullthrows"));
|
|
9
|
-
const entityUtils_1 = require("./entityUtils");
|
|
10
|
-
const SingleFieldHolder_1 = require("./internal/SingleFieldHolder");
|
|
11
|
-
const maps_1 = require("./utils/collections/maps");
|
|
12
|
-
/**
|
|
13
|
-
* Entity loader utilities for things like invalidation, entity construction, and authorization.
|
|
14
|
-
* Methods are exposed publicly since in rare cases they may need to be called manually.
|
|
15
|
-
*/
|
|
16
|
-
class EntityLoaderUtils {
|
|
17
|
-
viewerContext;
|
|
18
|
-
queryContext;
|
|
19
|
-
privacyPolicyEvaluationContext;
|
|
20
|
-
entityConfiguration;
|
|
21
|
-
entityClass;
|
|
22
|
-
entitySelectedFields;
|
|
23
|
-
privacyPolicy;
|
|
24
|
-
dataManager;
|
|
25
|
-
metricsAdapter;
|
|
26
|
-
constructor(viewerContext, queryContext, privacyPolicyEvaluationContext, entityConfiguration, entityClass, entitySelectedFields, privacyPolicy, dataManager, metricsAdapter) {
|
|
27
|
-
this.viewerContext = viewerContext;
|
|
28
|
-
this.queryContext = queryContext;
|
|
29
|
-
this.privacyPolicyEvaluationContext = privacyPolicyEvaluationContext;
|
|
30
|
-
this.entityConfiguration = entityConfiguration;
|
|
31
|
-
this.entityClass = entityClass;
|
|
32
|
-
this.entitySelectedFields = entitySelectedFields;
|
|
33
|
-
this.privacyPolicy = privacyPolicy;
|
|
34
|
-
this.dataManager = dataManager;
|
|
35
|
-
this.metricsAdapter = metricsAdapter;
|
|
36
|
-
}
|
|
37
|
-
getKeyValuePairsFromObjectFields(objectFields) {
|
|
38
|
-
const keys = Object.keys(objectFields);
|
|
39
|
-
const singleFieldKeyValues = [];
|
|
40
|
-
for (const fieldName of keys) {
|
|
41
|
-
const value = objectFields[fieldName];
|
|
42
|
-
if (value !== undefined && value !== null) {
|
|
43
|
-
singleFieldKeyValues.push([
|
|
44
|
-
new SingleFieldHolder_1.SingleFieldHolder(fieldName),
|
|
45
|
-
new SingleFieldHolder_1.SingleFieldValueHolder(value),
|
|
46
|
-
]);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
const compositeFieldKeyValues = [];
|
|
50
|
-
for (const compositeFieldHolder of this.entityConfiguration.compositeFieldInfo.getAllCompositeFieldHolders()) {
|
|
51
|
-
const compositeFieldValueHolder = compositeFieldHolder.extractCompositeFieldValueHolderFromObjectFields(objectFields);
|
|
52
|
-
if (compositeFieldValueHolder) {
|
|
53
|
-
compositeFieldKeyValues.push([compositeFieldHolder, compositeFieldValueHolder]);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return [...singleFieldKeyValues, ...compositeFieldKeyValues];
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Invalidate all caches and local dataloaders for an entity's fields. Exposed primarily for internal use by EntityMutator.
|
|
60
|
-
* @param objectFields - entity data object to be invalidated
|
|
61
|
-
*/
|
|
62
|
-
async invalidateFieldsAsync(objectFields) {
|
|
63
|
-
await this.dataManager.invalidateKeyValuePairsAsync(this.getKeyValuePairsFromObjectFields(objectFields));
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Invalidate all local dataloaders specific to a transaction for an entity's fields. Exposed primarily for internal use by EntityMutator.
|
|
67
|
-
* @param objectFields - entity data object to be invalidated
|
|
68
|
-
*/
|
|
69
|
-
invalidateFieldsForTransaction(queryContext, objectFields) {
|
|
70
|
-
this.dataManager.invalidateKeyValuePairsForTransaction(queryContext, this.getKeyValuePairsFromObjectFields(objectFields));
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Invalidate all caches and local dataloaders for an entity. One potential use case would be to keep the entity
|
|
74
|
-
* framework in sync with changes made to data outside of the framework.
|
|
75
|
-
* @param entity - entity to be invalidated
|
|
76
|
-
*/
|
|
77
|
-
async invalidateEntityAsync(entity) {
|
|
78
|
-
await this.invalidateFieldsAsync(entity.getAllDatabaseFields());
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Invalidate all local dataloaders specific to a transaction for an entity. One potential use case would be to keep the entity
|
|
82
|
-
* framework in sync with changes made to data outside of the framework.
|
|
83
|
-
* @param entity - entity to be invalidated
|
|
84
|
-
*/
|
|
85
|
-
invalidateEntityForTransaction(queryContext, entity) {
|
|
86
|
-
this.invalidateFieldsForTransaction(queryContext, entity.getAllDatabaseFields());
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Construct an entity from a fields object (applying field selection if applicable),
|
|
90
|
-
* checking that the ID field is specified.
|
|
91
|
-
*
|
|
92
|
-
* @param fieldsObject - fields object
|
|
93
|
-
*/
|
|
94
|
-
constructEntity(fieldsObject) {
|
|
95
|
-
const idField = this.entityConfiguration.idField;
|
|
96
|
-
const id = (0, nullthrows_1.default)(fieldsObject[idField], 'must provide ID to create an entity');
|
|
97
|
-
const entitySelectedFields = this.entitySelectedFields ?? Array.from(this.entityConfiguration.schema.keys());
|
|
98
|
-
const selectedFields = (0, entityUtils_1.pick)(fieldsObject, entitySelectedFields);
|
|
99
|
-
return new this.entityClass({
|
|
100
|
-
viewerContext: this.viewerContext,
|
|
101
|
-
id: id,
|
|
102
|
-
databaseFields: fieldsObject,
|
|
103
|
-
selectedFields,
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Construct and authorize entities from fields map, returning error results for entities that fail
|
|
108
|
-
* to construct or fail to authorize.
|
|
109
|
-
*
|
|
110
|
-
* @param map - map from an arbitrary key type to an array of entity field objects
|
|
111
|
-
*/
|
|
112
|
-
async constructAndAuthorizeEntitiesAsync(map) {
|
|
113
|
-
return await (0, maps_1.mapMapAsync)(map, async (fieldObjects) => {
|
|
114
|
-
return await this.constructAndAuthorizeEntitiesArrayAsync(fieldObjects);
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Construct and authorize entities from field objects array, returning error results for entities that fail
|
|
119
|
-
* to construct or fail to authorize.
|
|
120
|
-
*
|
|
121
|
-
* @param fieldObjects - array of field objects
|
|
122
|
-
*/
|
|
123
|
-
async constructAndAuthorizeEntitiesArrayAsync(fieldObjects) {
|
|
124
|
-
const uncheckedEntityResults = this.tryConstructEntities(fieldObjects);
|
|
125
|
-
return await Promise.all(uncheckedEntityResults.map(async (uncheckedEntityResult) => {
|
|
126
|
-
if (!uncheckedEntityResult.ok) {
|
|
127
|
-
return uncheckedEntityResult;
|
|
128
|
-
}
|
|
129
|
-
return await (0, results_1.asyncResult)(this.privacyPolicy.authorizeReadAsync(this.viewerContext, this.queryContext, this.privacyPolicyEvaluationContext, uncheckedEntityResult.value, this.metricsAdapter));
|
|
130
|
-
}));
|
|
131
|
-
}
|
|
132
|
-
tryConstructEntities(fieldsObjects) {
|
|
133
|
-
return fieldsObjects.map((fieldsObject) => {
|
|
134
|
-
try {
|
|
135
|
-
return (0, results_1.result)(this.constructEntity(fieldsObject));
|
|
136
|
-
}
|
|
137
|
-
catch (e) {
|
|
138
|
-
if (!(e instanceof Error)) {
|
|
139
|
-
throw e;
|
|
140
|
-
}
|
|
141
|
-
return (0, results_1.result)(e);
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
exports.EntityLoaderUtils = EntityLoaderUtils;
|
|
147
|
-
//# sourceMappingURL=EntityLoaderUtils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EntityLoaderUtils.js","sourceRoot":"","sources":["../../src/EntityLoaderUtils.ts"],"names":[],"mappings":"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"}
|