@expo/entity 0.19.0 → 0.20.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/EntityMutationInfo.d.ts +26 -0
- package/build/EntityMutationInfo.js +10 -0
- package/build/EntityMutationInfo.js.map +1 -0
- package/build/EntityMutationTriggerConfiguration.d.ts +3 -3
- package/build/EntityMutationValidator.d.ts +2 -2
- package/build/EntityMutationValidator.js.map +1 -1
- package/build/EntityMutator.d.ts +4 -15
- package/build/EntityMutator.js +45 -41
- package/build/EntityMutator.js.map +1 -1
- package/build/EntityQueryContext.d.ts +13 -0
- package/build/EntityQueryContext.js +18 -0
- package/build/EntityQueryContext.js.map +1 -1
- package/build/__tests__/EntityEdges-test.js +99 -3
- package/build/__tests__/EntityEdges-test.js.map +1 -1
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.d.ts +1 -0
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js +81 -0
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js.map +1 -0
- package/build/__tests__/EntityMutator-test.js +9 -7
- package/build/__tests__/EntityMutator-test.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/src/EntityMutationInfo.ts +47 -0
- package/src/EntityMutationTriggerConfiguration.ts +3 -3
- package/src/EntityMutationValidator.ts +8 -2
- package/src/EntityMutator.ts +81 -68
- package/src/EntityQueryContext.ts +20 -0
- package/src/__tests__/EntityEdges-test.ts +163 -9
- package/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts +105 -0
- package/src/__tests__/EntityMutator-test.ts +24 -6
- package/src/index.ts +1 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import Entity from '../Entity';
|
|
2
|
+
import { EntityCompanionDefinition } from '../EntityCompanionProvider';
|
|
3
|
+
import EntityConfiguration from '../EntityConfiguration';
|
|
4
|
+
import { UUIDField } from '../EntityFields';
|
|
5
|
+
import { EntityMutationType, EntityTriggerMutationInfo } from '../EntityMutationInfo';
|
|
6
|
+
import { EntityNonTransactionalMutationTrigger } from '../EntityMutationTriggerConfiguration';
|
|
7
|
+
import EntityPrivacyPolicy from '../EntityPrivacyPolicy';
|
|
8
|
+
import ViewerContext from '../ViewerContext';
|
|
9
|
+
import AlwaysAllowPrivacyPolicyRule from '../rules/AlwaysAllowPrivacyPolicyRule';
|
|
10
|
+
import { createUnitTestEntityCompanionProvider } from '../utils/testing/createUnitTestEntityCompanionProvider';
|
|
11
|
+
|
|
12
|
+
type BlahFields = {
|
|
13
|
+
id: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
class BlahEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
17
|
+
BlahFields,
|
|
18
|
+
string,
|
|
19
|
+
ViewerContext,
|
|
20
|
+
BlahEntity
|
|
21
|
+
> {
|
|
22
|
+
protected override readonly createRules = [
|
|
23
|
+
new AlwaysAllowPrivacyPolicyRule<BlahFields, string, ViewerContext, BlahEntity>(),
|
|
24
|
+
];
|
|
25
|
+
protected override readonly readRules = [
|
|
26
|
+
new AlwaysAllowPrivacyPolicyRule<BlahFields, string, ViewerContext, BlahEntity>(),
|
|
27
|
+
];
|
|
28
|
+
protected override readonly updateRules = [
|
|
29
|
+
new AlwaysAllowPrivacyPolicyRule<BlahFields, string, ViewerContext, BlahEntity>(),
|
|
30
|
+
];
|
|
31
|
+
protected override readonly deleteRules = [
|
|
32
|
+
new AlwaysAllowPrivacyPolicyRule<BlahFields, string, ViewerContext, BlahEntity>(),
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
class BlahEntity extends Entity<BlahFields, string, ViewerContext> {
|
|
37
|
+
static getCompanionDefinition(): EntityCompanionDefinition<
|
|
38
|
+
BlahFields,
|
|
39
|
+
string,
|
|
40
|
+
ViewerContext,
|
|
41
|
+
BlahEntity,
|
|
42
|
+
BlahEntityPrivacyPolicy
|
|
43
|
+
> {
|
|
44
|
+
return blahCompanion;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const blahCompanion = new EntityCompanionDefinition({
|
|
49
|
+
entityClass: BlahEntity,
|
|
50
|
+
entityConfiguration: new EntityConfiguration<BlahFields>({
|
|
51
|
+
idField: 'id',
|
|
52
|
+
tableName: 'blah_table',
|
|
53
|
+
schema: {
|
|
54
|
+
id: new UUIDField({
|
|
55
|
+
columnName: 'id',
|
|
56
|
+
cache: true,
|
|
57
|
+
}),
|
|
58
|
+
},
|
|
59
|
+
databaseAdapterFlavor: 'postgres',
|
|
60
|
+
cacheAdapterFlavor: 'redis',
|
|
61
|
+
}),
|
|
62
|
+
privacyPolicyClass: BlahEntityPrivacyPolicy,
|
|
63
|
+
mutationTriggers: () => ({
|
|
64
|
+
afterCommit: [new TestNonTransactionalMutationTrigger()],
|
|
65
|
+
}),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
class TestNonTransactionalMutationTrigger extends EntityNonTransactionalMutationTrigger<
|
|
69
|
+
BlahFields,
|
|
70
|
+
string,
|
|
71
|
+
ViewerContext,
|
|
72
|
+
BlahEntity
|
|
73
|
+
> {
|
|
74
|
+
async executeAsync(
|
|
75
|
+
viewerContext: ViewerContext,
|
|
76
|
+
entity: BlahEntity,
|
|
77
|
+
mutationInfo: EntityTriggerMutationInfo<BlahFields, string, ViewerContext, BlahEntity>
|
|
78
|
+
): Promise<void> {
|
|
79
|
+
if (mutationInfo.type === EntityMutationType.DELETE) {
|
|
80
|
+
const entityLoaded = await BlahEntity.loader(viewerContext)
|
|
81
|
+
.enforcing()
|
|
82
|
+
.loadByIDNullableAsync(entity.getID());
|
|
83
|
+
if (entityLoaded) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
'should not have been able to re-load the entity after delete. this means the cache has not been cleared'
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
describe('EntityMutator', () => {
|
|
93
|
+
test('cache consistency with post-commit callbacks', async () => {
|
|
94
|
+
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
95
|
+
const viewerContext = new ViewerContext(companionProvider);
|
|
96
|
+
|
|
97
|
+
// put it in cache
|
|
98
|
+
const entity = await BlahEntity.creator(viewerContext).enforceCreateAsync();
|
|
99
|
+
const entityLoaded = await BlahEntity.loader(viewerContext)
|
|
100
|
+
.enforcing()
|
|
101
|
+
.loadByIDAsync(entity.getID());
|
|
102
|
+
|
|
103
|
+
await BlahEntity.enforceDeleteAsync(entityLoaded);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -14,12 +14,16 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
14
14
|
|
|
15
15
|
import EntityDatabaseAdapter from '../EntityDatabaseAdapter';
|
|
16
16
|
import EntityLoaderFactory from '../EntityLoaderFactory';
|
|
17
|
+
import {
|
|
18
|
+
EntityMutationType,
|
|
19
|
+
EntityTriggerMutationInfo,
|
|
20
|
+
EntityValidatorMutationInfo,
|
|
21
|
+
} from '../EntityMutationInfo';
|
|
17
22
|
import EntityMutationTriggerConfiguration, {
|
|
18
23
|
EntityMutationTrigger,
|
|
19
24
|
EntityNonTransactionalMutationTrigger,
|
|
20
25
|
} from '../EntityMutationTriggerConfiguration';
|
|
21
26
|
import EntityMutationValidator from '../EntityMutationValidator';
|
|
22
|
-
import { EntityMutationInfo, EntityMutationType } from '../EntityMutator';
|
|
23
27
|
import EntityMutatorFactory from '../EntityMutatorFactory';
|
|
24
28
|
import { EntityTransactionalQueryContext, EntityQueryContext } from '../EntityQueryContext';
|
|
25
29
|
import ViewerContext from '../ViewerContext';
|
|
@@ -53,7 +57,7 @@ class TestMutationTrigger extends EntityMutationTrigger<
|
|
|
53
57
|
_viewerContext: ViewerContext,
|
|
54
58
|
_queryContext: EntityQueryContext,
|
|
55
59
|
_entity: TestEntity,
|
|
56
|
-
_mutationInfo:
|
|
60
|
+
_mutationInfo: EntityTriggerMutationInfo<
|
|
57
61
|
TestFields,
|
|
58
62
|
string,
|
|
59
63
|
ViewerContext,
|
|
@@ -95,7 +99,13 @@ const verifyValidatorCounts = (
|
|
|
95
99
|
keyof TestFields
|
|
96
100
|
>[],
|
|
97
101
|
expectedCalls: number,
|
|
98
|
-
mutationInfo:
|
|
102
|
+
mutationInfo: EntityValidatorMutationInfo<
|
|
103
|
+
TestFields,
|
|
104
|
+
string,
|
|
105
|
+
ViewerContext,
|
|
106
|
+
TestEntity,
|
|
107
|
+
keyof TestFields
|
|
108
|
+
>
|
|
99
109
|
): void => {
|
|
100
110
|
for (const validator of mutationValidatorSpies) {
|
|
101
111
|
verify(
|
|
@@ -164,7 +174,13 @@ const verifyTriggerCounts = (
|
|
|
164
174
|
>,
|
|
165
175
|
boolean
|
|
166
176
|
>,
|
|
167
|
-
mutationInfo:
|
|
177
|
+
mutationInfo: EntityTriggerMutationInfo<
|
|
178
|
+
TestFields,
|
|
179
|
+
string,
|
|
180
|
+
ViewerContext,
|
|
181
|
+
TestEntity,
|
|
182
|
+
keyof TestFields
|
|
183
|
+
>
|
|
168
184
|
): void => {
|
|
169
185
|
Object.keys(executed).forEach((s) => {
|
|
170
186
|
if ((executed as any)[s]) {
|
|
@@ -767,7 +783,7 @@ describe(EntityMutatorFactory, () => {
|
|
|
767
783
|
beforeDelete: true,
|
|
768
784
|
afterDelete: true,
|
|
769
785
|
},
|
|
770
|
-
{ type: EntityMutationType.DELETE }
|
|
786
|
+
{ type: EntityMutationType.DELETE, cascadingDeleteCause: null }
|
|
771
787
|
);
|
|
772
788
|
});
|
|
773
789
|
|
|
@@ -796,7 +812,9 @@ describe(EntityMutatorFactory, () => {
|
|
|
796
812
|
|
|
797
813
|
await entityMutatorFactory.forDelete(existingEntity, queryContext).enforceDeleteAsync();
|
|
798
814
|
|
|
799
|
-
verifyValidatorCounts(viewerContext, validatorSpies, 0, {
|
|
815
|
+
verifyValidatorCounts(viewerContext, validatorSpies, 0, {
|
|
816
|
+
type: EntityMutationType.DELETE as any,
|
|
817
|
+
});
|
|
800
818
|
});
|
|
801
819
|
});
|
|
802
820
|
|
package/src/index.ts
CHANGED
|
@@ -33,6 +33,7 @@ export { default as EntitySecondaryCacheLoader } from './EntitySecondaryCacheLoa
|
|
|
33
33
|
export * from './EntitySecondaryCacheLoader';
|
|
34
34
|
export * from './EntityMutator';
|
|
35
35
|
export { default as EntityMutationValidator } from './EntityMutationValidator';
|
|
36
|
+
export * from './EntityMutationInfo';
|
|
36
37
|
export * from './EntityMutationTriggerConfiguration';
|
|
37
38
|
export { default as EntityMutationTriggerConfiguration } from './EntityMutationTriggerConfiguration';
|
|
38
39
|
export { default as EntityMutatorFactory } from './EntityMutatorFactory';
|