From 1bdfbd6b562d1200e4029df0533b5adb2d917831 Mon Sep 17 00:00:00 2001 From: Will Schurman Date: Thu, 11 Apr 2024 09:51:40 -0700 Subject: [PATCH] fix: Revert: require explicit query context specification (#219) This reverts commit 8b0b31fdde5bd565aa527719003ef283a45f55cc. --- .../GenericLocalMemoryCacher-full-test.ts | 42 +- ...tchedRedisCacheAdapter-integration-test.ts | 48 +- ...enericRedisCacher-full-integration-test.ts | 65 +-- .../GenericRedisCacher-integration-test.ts | 10 +- .../src/__integration-tests__/errors-test.ts | 7 +- .../PostgresEntityIntegration-test.ts | 444 ++++-------------- ...PostgresEntityQueryContextProvider-test.ts | 35 +- .../PostgresInvalidSetup-test.ts | 68 +-- .../src/__integration-tests__/errors-test.ts | 71 +-- .../src/__tests__/NoteEntity-test.ts | 10 +- .../entity-example/src/routers/notesRouter.ts | 68 +-- packages/entity-example/src/schema.ts | 36 +- packages/entity-example/src/viewerContexts.ts | 17 +- .../EntityCacheInconsistency-test.ts | 46 +- .../EntityEdgesIntegration-test.ts | 27 +- ...itySelfReferentialEdgesIntegration-test.ts | 34 +- .../entities/ChildEntity.ts | 22 +- .../entities/ParentEntity.ts | 22 +- .../entities/TestViewerContext.ts | 13 - .../LocalMemorySecondaryEntityCache-test.ts | 15 +- ...isSecondaryEntityCache-integration-test.ts | 15 +- packages/entity/src/Entity.ts | 35 +- .../entity/src/EntityAssociationLoader.ts | 34 +- .../entity/src/EntityQueryContextProvider.ts | 2 +- packages/entity/src/ReadonlyEntity.ts | 5 +- packages/entity/src/ViewerContext.ts | 10 +- packages/entity/src/__tests__/Entity-test.ts | 70 ++- .../__tests__/EntityAssociationLoader-test.ts | 254 ++++------ .../__tests__/EntityCommonUseCases-test.ts | 54 +-- .../entity/src/__tests__/EntityEdges-test.ts | 142 ++---- .../EntityLoader-constructor-test.ts | 2 +- .../entity/src/__tests__/EntityLoader-test.ts | 38 +- ...tyMutator-MutationCacheConsistency-test.ts | 35 +- .../src/__tests__/EntityMutator-test.ts | 128 +++-- .../EntitySecondaryCacheLoader-test.ts | 31 +- .../EntitySelfReferentialEdges-test.ts | 162 ++----- .../src/__tests__/ReadonlyEntity-test.ts | 28 +- .../src/__tests__/ViewerContext-test.ts | 5 +- .../TwoEntitySameTableDisjointRows-test.ts | 55 +-- .../TwoEntitySameTableOverlappingRows-test.ts | 52 +- .../entity/src/internal/EntityDataManager.ts | 2 +- .../__tests__/EntityDataManager-test.ts | 22 +- .../src/testfixtures/SimpleTestEntity.ts | 16 +- .../entity/src/testfixtures/TestEntity.ts | 27 +- .../entity/src/testfixtures/TestEntity2.ts | 16 +- .../src/testfixtures/TestViewerContext.ts | 13 +- 46 files changed, 755 insertions(+), 1598 deletions(-) delete mode 100644 packages/entity-full-integration-tests/src/__integration-tests__/entities/TestViewerContext.ts diff --git a/packages/entity-cache-adapter-local-memory/src/__tests__/GenericLocalMemoryCacher-full-test.ts b/packages/entity-cache-adapter-local-memory/src/__tests__/GenericLocalMemoryCacher-full-test.ts index 9778dc8c..dbf552b1 100644 --- a/packages/entity-cache-adapter-local-memory/src/__tests__/GenericLocalMemoryCacher-full-test.ts +++ b/packages/entity-cache-adapter-local-memory/src/__tests__/GenericLocalMemoryCacher-full-test.ts @@ -25,19 +25,13 @@ describe(GenericLocalMemoryCacher, () => { const cacheKeyMaker = genericCacher['makeCacheKey'].bind(genericCacher); const date = new Date(); - const entity1Created = await LocalMemoryTestEntity.creator( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity1Created = await LocalMemoryTestEntity.creator(viewerContext) .setField('name', 'blah') .setField('dateField', date) .enforceCreateAsync(); // loading an entity should put it in cache - const entity1 = await LocalMemoryTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity1 = await LocalMemoryTestEntity.loader(viewerContext) .enforcing() .loadByIDAsync(entity1Created.getID()); @@ -69,10 +63,9 @@ describe(GenericLocalMemoryCacher, () => { // simulate non existent db fetch, should write negative result ('') to cache const nonExistentId = uuidv4(); - const entityNonExistentResult = await LocalMemoryTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).loadByIDAsync(nonExistentId); + const entityNonExistentResult = await LocalMemoryTestEntity.loader(viewerContext).loadByIDAsync( + nonExistentId + ); expect(entityNonExistentResult.ok).toBe(false); const nonExistentCachedResult = await entitySpecificGenericCacher.loadManyAsync([ @@ -84,16 +77,12 @@ describe(GenericLocalMemoryCacher, () => { // load again through entities framework to ensure it reads negative result const entityNonExistentResult2 = await LocalMemoryTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') + viewerContext ).loadByIDAsync(nonExistentId); expect(entityNonExistentResult2.ok).toBe(false); // invalidate from cache to ensure it invalidates correctly - await LocalMemoryTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).invalidateFieldsAsync(entity1.getAllFields()); + await LocalMemoryTestEntity.loader(viewerContext).invalidateFieldsAsync(entity1.getAllFields()); const cachedResultMiss = await entitySpecificGenericCacher.loadManyAsync([ cacheKeyMaker('id', entity1.getID()), ]); @@ -111,19 +100,13 @@ describe(GenericLocalMemoryCacher, () => { const cacheKeyMaker = genericCacher['makeCacheKey'].bind(genericCacher); const date = new Date(); - const entity1Created = await LocalMemoryTestEntity.creator( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity1Created = await LocalMemoryTestEntity.creator(viewerContext) .setField('name', 'blah') .setField('dateField', date) .enforceCreateAsync(); // loading an entity will try to put it in cache but it's a noop cache, so it should be a miss - const entity1 = await LocalMemoryTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity1 = await LocalMemoryTestEntity.loader(viewerContext) .enforcing() .loadByIDAsync(entity1Created.getID()); @@ -150,10 +133,9 @@ describe(GenericLocalMemoryCacher, () => { // a non existent db fetch should try to write negative result ('') but it's a noop cache, so it should be a miss const nonExistentId = uuidv4(); - const entityNonExistentResult = await LocalMemoryTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).loadByIDAsync(nonExistentId); + const entityNonExistentResult = await LocalMemoryTestEntity.loader(viewerContext).loadByIDAsync( + nonExistentId + ); expect(entityNonExistentResult.ok).toBe(false); const nonExistentCachedResult = await entitySpecificGenericCacher.loadManyAsync([ diff --git a/packages/entity-cache-adapter-redis/src/__integration-tests__/BatchedRedisCacheAdapter-integration-test.ts b/packages/entity-cache-adapter-redis/src/__integration-tests__/BatchedRedisCacheAdapter-integration-test.ts index b8152e53..fc11e4c4 100644 --- a/packages/entity-cache-adapter-redis/src/__integration-tests__/BatchedRedisCacheAdapter-integration-test.ts +++ b/packages/entity-cache-adapter-redis/src/__integration-tests__/BatchedRedisCacheAdapter-integration-test.ts @@ -101,10 +101,7 @@ describe(GenericRedisCacher, () => { ]['cacheAdapter']['genericCacher']; const cacheKeyMaker = genericCacher['makeCacheKey'].bind(genericCacher); - const entity1Created = await RedisTestEntity.creator( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity1Created = await RedisTestEntity.creator(viewerContext) .setField('name', 'blah') .enforceCreateAsync(); @@ -120,22 +117,9 @@ describe(GenericRedisCacher, () => { createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext) ); const [entity1, entity2, entity3] = await Promise.all([ - RedisTestEntity.loader( - viewerContext1, - viewerContext1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .enforcing() - .loadByIDAsync(entity1Created.getID()), - RedisTestEntity.loader( - viewerContext2, - viewerContext2.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .enforcing() - .loadByIDAsync(entity1Created.getID()), - RedisTestEntity.loader( - viewerContext3, - viewerContext3.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + RedisTestEntity.loader(viewerContext1).enforcing().loadByIDAsync(entity1Created.getID()), + RedisTestEntity.loader(viewerContext2).enforcing().loadByIDAsync(entity1Created.getID()), + RedisTestEntity.loader(viewerContext3) .enforcing() .loadByFieldEqualingAsync('name', entity1Created.getField('name')), ]); @@ -154,36 +138,28 @@ describe(GenericRedisCacher, () => { }); const cacheKeyEntity1NameField = cacheKeyMaker('name', entity1Created.getField('name')); - await RedisTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + await RedisTestEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('name', entity1Created.getField('name')); await expect(redis.get(cacheKeyEntity1NameField)).resolves.toEqual(cachedJSON); // simulate non existent db fetch, should write negative result ('') to cache const nonExistentId = uuidv4(); - const entityNonExistentResult = await RedisTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).loadByIDAsync(nonExistentId); + const entityNonExistentResult = await RedisTestEntity.loader(viewerContext).loadByIDAsync( + nonExistentId + ); expect(entityNonExistentResult.ok).toBe(false); const cacheKeyNonExistent = cacheKeyMaker('id', nonExistentId); const nonExistentCachedValue = await redis.get(cacheKeyNonExistent); expect(nonExistentCachedValue).toEqual(''); // load again through entities framework to ensure it reads negative result - const entityNonExistentResult2 = await RedisTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).loadByIDAsync(nonExistentId); + const entityNonExistentResult2 = await RedisTestEntity.loader(viewerContext).loadByIDAsync( + nonExistentId + ); expect(entityNonExistentResult2.ok).toBe(false); // invalidate from cache to ensure it invalidates correctly in both caches - await RedisTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).invalidateFieldsAsync(entity1.getAllFields()); + await RedisTestEntity.loader(viewerContext).invalidateFieldsAsync(entity1.getAllFields()); await expect(redis.get(cacheKeyEntity1)).resolves.toBeNull(); await expect(redis.get(cacheKeyEntity1NameField)).resolves.toBeNull(); }); diff --git a/packages/entity-cache-adapter-redis/src/__integration-tests__/GenericRedisCacher-full-integration-test.ts b/packages/entity-cache-adapter-redis/src/__integration-tests__/GenericRedisCacher-full-integration-test.ts index 7f2b6856..8e1d2936 100644 --- a/packages/entity-cache-adapter-redis/src/__integration-tests__/GenericRedisCacher-full-integration-test.ts +++ b/packages/entity-cache-adapter-redis/src/__integration-tests__/GenericRedisCacher-full-integration-test.ts @@ -46,18 +46,12 @@ describe(GenericRedisCacher, () => { ]['cacheAdapter']['genericCacher']; const cacheKeyMaker = genericCacher['makeCacheKey'].bind(genericCacher); - const entity1Created = await RedisTestEntity.creator( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity1Created = await RedisTestEntity.creator(viewerContext) .setField('name', 'blah') .enforceCreateAsync(); // loading an entity should put it in cache - const entity1 = await RedisTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity1 = await RedisTestEntity.loader(viewerContext) .enforcing() .loadByIDAsync(entity1Created.getID()); @@ -73,10 +67,9 @@ describe(GenericRedisCacher, () => { // simulate non existent db fetch, should write negative result ('') to cache const nonExistentId = uuidv4(); - const entityNonExistentResult = await RedisTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).loadByIDAsync(nonExistentId); + const entityNonExistentResult = await RedisTestEntity.loader(viewerContext).loadByIDAsync( + nonExistentId + ); expect(entityNonExistentResult.ok).toBe(false); const nonExistentCachedValue = await (genericRedisCacheContext.redisClient as Redis).get( @@ -85,17 +78,13 @@ describe(GenericRedisCacher, () => { expect(nonExistentCachedValue).toEqual(''); // load again through entities framework to ensure it reads negative result - const entityNonExistentResult2 = await RedisTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).loadByIDAsync(nonExistentId); + const entityNonExistentResult2 = await RedisTestEntity.loader(viewerContext).loadByIDAsync( + nonExistentId + ); expect(entityNonExistentResult2.ok).toBe(false); // invalidate from cache to ensure it invalidates correctly - await RedisTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).invalidateFieldsAsync(entity1.getAllFields()); + await RedisTestEntity.loader(viewerContext).invalidateFieldsAsync(entity1.getAllFields()); const cachedValueNull = await (genericRedisCacheContext.redisClient as Redis).get( cacheKeyMaker('id', entity1.getID()) ); @@ -108,19 +97,11 @@ describe(GenericRedisCacher, () => { ); const date = new Date(); const entity1 = await enforceAsyncResult( - RedisTestEntity.creator( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('dateField', date) - .createAsync() + RedisTestEntity.creator(viewerContext).setField('dateField', date).createAsync() ); expect(entity1.getField('dateField')).toEqual(date); - const entity2 = await RedisTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity2 = await RedisTestEntity.loader(viewerContext) .enforcing() .loadByIDAsync(entity1.getID()); expect(entity2.getField('dateField')).toEqual(date); @@ -129,12 +110,7 @@ describe(GenericRedisCacher, () => { const vc2 = new TestViewerContext( createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext) ); - const entity3 = await RedisTestEntity.loader( - vc2, - vc2.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .enforcing() - .loadByIDAsync(entity1.getID()); + const entity3 = await RedisTestEntity.loader(vc2).enforcing().loadByIDAsync(entity1.getID()); expect(entity3.getField('dateField')).toEqual(date); }); @@ -143,17 +119,9 @@ describe(GenericRedisCacher, () => { createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext) ); const entity1 = await enforceAsyncResult( - RedisTestEntity.creator( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', '') - .createAsync() + RedisTestEntity.creator(viewerContext).setField('name', '').createAsync() ); - const entity2 = await RedisTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity2 = await RedisTestEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('name', ''); expect(entity2?.getID()).toEqual(entity1.getID()); @@ -162,10 +130,7 @@ describe(GenericRedisCacher, () => { const vc2 = new TestViewerContext( createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext) ); - const entity3 = await RedisTestEntity.loader( - vc2, - vc2.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity3 = await RedisTestEntity.loader(vc2) .enforcing() .loadByFieldEqualingAsync('name', ''); expect(entity3?.getID()).toEqual(entity1.getID()); diff --git a/packages/entity-cache-adapter-redis/src/__integration-tests__/GenericRedisCacher-integration-test.ts b/packages/entity-cache-adapter-redis/src/__integration-tests__/GenericRedisCacher-integration-test.ts index 4354002e..13ce64f9 100644 --- a/packages/entity-cache-adapter-redis/src/__integration-tests__/GenericRedisCacher-integration-test.ts +++ b/packages/entity-cache-adapter-redis/src/__integration-tests__/GenericRedisCacher-integration-test.ts @@ -46,10 +46,7 @@ describe(GenericRedisCacher, () => { redisTestEntityConfiguration ); const date = new Date(); - const entity1Created = await RedisTestEntity.creator( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity1Created = await RedisTestEntity.creator(viewerContext) .setField('name', 'blah') .setField('dateField', date) .enforceCreateAsync(); @@ -95,10 +92,7 @@ describe(GenericRedisCacher, () => { redisTestEntityConfiguration ); const date = new Date(); - const entity1Created = await RedisTestEntity.creator( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity1Created = await RedisTestEntity.creator(viewerContext) .setField('name', 'blah') .setField('dateField', date) .enforceCreateAsync(); diff --git a/packages/entity-cache-adapter-redis/src/__integration-tests__/errors-test.ts b/packages/entity-cache-adapter-redis/src/__integration-tests__/errors-test.ts index d972abd6..aeae8155 100644 --- a/packages/entity-cache-adapter-redis/src/__integration-tests__/errors-test.ts +++ b/packages/entity-cache-adapter-redis/src/__integration-tests__/errors-test.ts @@ -40,12 +40,7 @@ describe(GenericRedisCacher, () => { ); await expect( - RedisTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'blah') - .enforceCreateAsync() + RedisTestEntity.creator(vc1).setField('name', 'blah').enforceCreateAsync() ).rejects.toThrow(EntityCacheAdapterTransientError); }); }); diff --git a/packages/entity-database-adapter-knex/src/__integration-tests__/PostgresEntityIntegration-test.ts b/packages/entity-database-adapter-knex/src/__integration-tests__/PostgresEntityIntegration-test.ts index 6b5c6d2b..3af8f407 100644 --- a/packages/entity-database-adapter-knex/src/__integration-tests__/PostgresEntityIntegration-test.ts +++ b/packages/entity-database-adapter-knex/src/__integration-tests__/PostgresEntityIntegration-test.ts @@ -42,34 +42,16 @@ describe('postgres entity integration', () => { it('supports parallel partial updates', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); const entity = await enforceAsyncResult( - PostgresTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'hello') - .createAsync() + PostgresTestEntity.creator(vc).setField('name', 'hello').createAsync() ); // update two different fields at the same time (from the same entity) await Promise.all([ - PostgresTestEntity.updater( - entity, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('hasACat', true) - .updateAsync(), - PostgresTestEntity.updater( - entity, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('hasADog', false) - .updateAsync(), + PostgresTestEntity.updater(entity).setField('hasACat', true).updateAsync(), + PostgresTestEntity.updater(entity).setField('hasADog', false).updateAsync(), ]); - const loadedEntity = await PostgresTestEntity.loader( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const loadedEntity = await PostgresTestEntity.loader(vc) .enforcing() .loadByIDAsync(entity.getID()); @@ -80,49 +62,24 @@ describe('postgres entity integration', () => { describe('empty creates and updates', () => { it('allows empty create', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); - const entity = await enforceAsyncResult( - PostgresTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).createAsync() - ); + const entity = await enforceAsyncResult(PostgresTestEntity.creator(vc).createAsync()); expect(entity.getID()).toBeTruthy(); }); it('throws knex error upon empty update', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); const entity = await enforceAsyncResult( - PostgresTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'hello') - .createAsync() + PostgresTestEntity.creator(vc).setField('name', 'hello').createAsync() ); - await expect( - PostgresTestEntity.updater( - entity, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).updateAsync() - ).rejects.toThrow(); + await expect(PostgresTestEntity.updater(entity).updateAsync()).rejects.toThrow(); }); it('throws error upon empty update for stub database adapter to match behavior', async () => { const vc = new ViewerContext(createUnitTestEntityCompanionProvider()); const entity = await enforceAsyncResult( - PostgresTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'hello') - .createAsync() + PostgresTestEntity.creator(vc).setField('name', 'hello').createAsync() ); - await expect( - PostgresTestEntity.updater( - entity, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).updateAsync() - ).rejects.toThrow(); + await expect(PostgresTestEntity.updater(entity).updateAsync()).rejects.toThrow(); }); }); @@ -131,20 +88,10 @@ describe('postgres entity integration', () => { // put one in the DB const firstEntity = await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'hello') - .createAsync() + PostgresTestEntity.creator(vc1).setField('name', 'hello').createAsync() ); - await enforceAsyncResult( - PostgresTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).loadByIDAsync(firstEntity.getID()) - ); + await enforceAsyncResult(PostgresTestEntity.loader(vc1).loadByIDAsync(firstEntity.getID())); const errorToThrow = new Error('Intentional error'); @@ -160,10 +107,7 @@ describe('postgres entity integration', () => { ).rejects.toEqual(errorToThrow); const entities = await enforceResultsAsync( - PostgresTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ).loadManyByFieldEqualingAsync('name', 'hello') + PostgresTestEntity.loader(vc1).loadManyByFieldEqualingAsync('name', 'hello') ); expect(entities).toHaveLength(1); }); @@ -172,12 +116,7 @@ describe('postgres entity integration', () => { const vc1 = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); const firstEntity = await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'hello') - .createAsync() + PostgresTestEntity.creator(vc1).setField('name', 'hello').createAsync() ); const loadAndUpdateAsync = async (newName: string): Promise<{ error?: Error }> => { @@ -216,10 +155,7 @@ describe('postgres entity integration', () => { const vc1 = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); const entity = await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('stringArray', ['hello', 'world']) .setField('jsonArrayField', ['hello', 'world']) .createAsync() @@ -233,10 +169,7 @@ describe('postgres entity integration', () => { const vc1 = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); const entity = await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('jsonObjectField', { hello: 'world' }) .createAsync() ); @@ -248,18 +181,12 @@ describe('postgres entity integration', () => { const vc1 = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); const entity1 = await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('maybeJsonArrayField', ['hello', 'world']) .createAsync() ); const entity2 = await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('maybeJsonArrayField', { hello: 'world' }) .createAsync() ); @@ -274,32 +201,17 @@ describe('postgres entity integration', () => { const vc1 = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); let entity = await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('bigintField', '72057594037928038') - .createAsync() + PostgresTestEntity.creator(vc1).setField('bigintField', '72057594037928038').createAsync() ); expect(entity.getField('bigintField')).toEqual('72057594037928038'); entity = await enforceAsyncResult( - PostgresTestEntity.updater( - entity, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('bigintField', '10') - .updateAsync() + PostgresTestEntity.updater(entity).setField('bigintField', '10').updateAsync() ); expect(entity.getField('bigintField')).toEqual('10'); entity = await enforceAsyncResult( - PostgresTestEntity.updater( - entity, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('bigintField', '-10') - .updateAsync() + PostgresTestEntity.updater(entity).setField('bigintField', '-10').updateAsync() ); expect(entity.getField('bigintField')).toEqual('-10'); }); @@ -310,10 +222,7 @@ describe('postgres entity integration', () => { const vc1 = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('name', 'hello') .setField('hasACat', false) .setField('hasADog', true) @@ -321,10 +230,7 @@ describe('postgres entity integration', () => { ); await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('name', 'world') .setField('hasACat', false) .setField('hasADog', true) @@ -332,20 +238,14 @@ describe('postgres entity integration', () => { ); await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('name', 'wat') .setField('hasACat', false) .setField('hasADog', false) .createAsync() ); - const results = await PostgresTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const results = await PostgresTestEntity.loader(vc1) .enforcing() .loadManyByFieldEqualityConjunctionAsync([ { @@ -360,10 +260,7 @@ describe('postgres entity integration', () => { expect(results).toHaveLength(2); - const results2 = await PostgresTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const results2 = await PostgresTestEntity.loader(vc1) .enforcing() .loadManyByFieldEqualityConjunctionAsync([ { fieldName: 'hasADog', fieldValues: [true, false] }, @@ -374,37 +271,13 @@ describe('postgres entity integration', () => { it('supports query modifiers', async () => { const vc1 = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); - await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'a') - .createAsync() - ); + await enforceAsyncResult(PostgresTestEntity.creator(vc1).setField('name', 'a').createAsync()); - await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'b') - .createAsync() - ); + await enforceAsyncResult(PostgresTestEntity.creator(vc1).setField('name', 'b').createAsync()); - await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'c') - .createAsync() - ); + await enforceAsyncResult(PostgresTestEntity.creator(vc1).setField('name', 'c').createAsync()); - const results = await PostgresTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const results = await PostgresTestEntity.loader(vc1) .enforcing() .loadManyByFieldEqualityConjunctionAsync([], { limit: 2, @@ -423,55 +296,37 @@ describe('postgres entity integration', () => { it('supports null field values', async () => { const vc1 = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('name', 'a') .setField('hasADog', true) .createAsync() ); await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('name', 'b') .setField('hasADog', true) .createAsync() ); await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('name', null) .setField('hasADog', true) .createAsync() ); await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('name', null) .setField('hasADog', false) .createAsync() ); - const results = await PostgresTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const results = await PostgresTestEntity.loader(vc1) .enforcing() .loadManyByFieldEqualityConjunctionAsync([{ fieldName: 'name', fieldValue: null }]); expect(results).toHaveLength(2); expect(results[0]!.getField('name')).toBeNull(); - const results2 = await PostgresTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const results2 = await PostgresTestEntity.loader(vc1) .enforcing() .loadManyByFieldEqualityConjunctionAsync( [ @@ -496,20 +351,14 @@ describe('postgres entity integration', () => { it('loads by raw where clause', async () => { const vc1 = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('name', 'hello') .setField('hasACat', false) .setField('hasADog', true) .createAsync() ); - const results = await PostgresTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const results = await PostgresTestEntity.loader(vc1) .enforcing() .loadManyByRawWhereClauseAsync('name = ?', ['hello']); @@ -519,10 +368,7 @@ describe('postgres entity integration', () => { it('throws with invalid where clause', async () => { const vc1 = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('name', 'hello') .setField('hasACat', false) .setField('hasADog', true) @@ -530,10 +376,7 @@ describe('postgres entity integration', () => { ); await expect( - PostgresTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.loader(vc1) .enforcing() .loadManyByRawWhereClauseAsync('invalid_column = ?', ['hello']) ).rejects.toThrow(); @@ -543,39 +386,27 @@ describe('postgres entity integration', () => { const vc1 = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('name', 'a') .setField('hasADog', true) .createAsync() ); await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('name', 'b') .setField('hasADog', true) .createAsync() ); await enforceAsyncResult( - PostgresTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTestEntity.creator(vc1) .setField('name', 'c') .setField('hasADog', true) .createAsync() ); - const results = await PostgresTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const results = await PostgresTestEntity.loader(vc1) .enforcing() .loadManyByRawWhereClauseAsync('has_a_dog = ?', [true], { limit: 2, @@ -591,10 +422,7 @@ describe('postgres entity integration', () => { expect(results).toHaveLength(2); expect(results.map((e) => e.getField('name'))).toEqual(['b', 'c']); - const resultsMultipleOrderBy = await PostgresTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const resultsMultipleOrderBy = await PostgresTestEntity.loader(vc1) .enforcing() .loadManyByRawWhereClauseAsync('has_a_dog = ?', [true], { orderBy: [ @@ -612,10 +440,7 @@ describe('postgres entity integration', () => { expect(resultsMultipleOrderBy).toHaveLength(3); expect(resultsMultipleOrderBy.map((e) => e.getField('name'))).toEqual(['c', 'b', 'a']); - const resultsOrderByRaw = await PostgresTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const resultsOrderByRaw = await PostgresTestEntity.loader(vc1) .enforcing() .loadManyByRawWhereClauseAsync('has_a_dog = ?', [true], { orderByRaw: 'has_a_dog ASC, name DESC', @@ -634,86 +459,52 @@ describe('postgres entity integration', () => { ); await expect( - PostgresTriggerTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.creator(vc1) .setField('name', 'beforeCreate') .enforceCreateAsync() ).rejects.toThrowError('name cannot have value beforeCreate'); await expect( - PostgresTriggerTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'beforeCreate') ).resolves.toBeNull(); await expect( - PostgresTriggerTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.creator(vc1) .setField('name', 'afterCreate') .enforceCreateAsync() ).rejects.toThrowError('name cannot have value afterCreate'); await expect( - PostgresTriggerTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'afterCreate') ).resolves.toBeNull(); await expect( - PostgresTriggerTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'beforeAll') - .enforceCreateAsync() + PostgresTriggerTestEntity.creator(vc1).setField('name', 'beforeAll').enforceCreateAsync() ).rejects.toThrowError('name cannot have value beforeAll'); await expect( - PostgresTriggerTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'beforeAll') ).resolves.toBeNull(); await expect( - PostgresTriggerTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'afterAll') - .enforceCreateAsync() + PostgresTriggerTestEntity.creator(vc1).setField('name', 'afterAll').enforceCreateAsync() ).rejects.toThrowError('name cannot have value afterAll'); await expect( - PostgresTriggerTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'afterAll') ).resolves.toBeNull(); await expect( - PostgresTriggerTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.creator(vc1) .setField('name', 'afterCommit') .enforceCreateAsync() ).rejects.toThrowError('name cannot have value afterCommit'); await expect( - PostgresTriggerTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'afterCommit') ).resolves.not.toBeNull(); @@ -726,94 +517,61 @@ describe('postgres entity integration', () => { createKnexIntegrationTestEntityCompanionProvider(knexInstance) ); - const entity = await PostgresTriggerTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity = await PostgresTriggerTestEntity.creator(vc1) .setField('name', 'blah') .enforceCreateAsync(); await expect( - PostgresTriggerTestEntity.updater( - entity, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.updater(entity) .setField('name', 'beforeUpdate') .enforceUpdateAsync() ).rejects.toThrowError('name cannot have value beforeUpdate'); await expect( - PostgresTriggerTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'beforeUpdate') ).resolves.toBeNull(); await expect( - PostgresTriggerTestEntity.updater( - entity, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.updater(entity) .setField('name', 'afterUpdate') .enforceUpdateAsync() ).rejects.toThrowError('name cannot have value afterUpdate'); await expect( - PostgresTriggerTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'afterUpdate') ).resolves.toBeNull(); await expect( - PostgresTriggerTestEntity.updater( - entity, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.updater(entity) .setField('name', 'beforeAll') .enforceUpdateAsync() ).rejects.toThrowError('name cannot have value beforeAll'); await expect( - PostgresTriggerTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'beforeAll') ).resolves.toBeNull(); await expect( - PostgresTriggerTestEntity.updater( - entity, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.updater(entity) .setField('name', 'afterAll') .enforceUpdateAsync() ).rejects.toThrowError('name cannot have value afterAll'); await expect( - PostgresTriggerTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'afterAll') ).resolves.toBeNull(); await expect( - PostgresTriggerTestEntity.updater( - entity, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.updater(entity) .setField('name', 'afterCommit') .enforceUpdateAsync() ).rejects.toThrowError('name cannot have value afterCommit'); await expect( - PostgresTriggerTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'afterCommit') ).resolves.not.toBeNull(); @@ -826,44 +584,26 @@ describe('postgres entity integration', () => { createKnexIntegrationTestEntityCompanionProvider(knexInstance) ); - const entityBeforeDelete = await PostgresTriggerTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entityBeforeDelete = await PostgresTriggerTestEntity.creator(vc1) .setField('name', 'beforeDelete') .enforceCreateAsync(); await expect( - PostgresTriggerTestEntity.enforceDeleteAsync( - entityBeforeDelete, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.enforceDeleteAsync(entityBeforeDelete) ).rejects.toThrowError('name cannot have value beforeDelete'); await expect( - PostgresTriggerTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'beforeDelete') ).resolves.not.toBeNull(); - const entityAfterDelete = await PostgresTriggerTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entityAfterDelete = await PostgresTriggerTestEntity.creator(vc1) .setField('name', 'afterDelete') .enforceCreateAsync(); await expect( - PostgresTriggerTestEntity.enforceDeleteAsync( - entityAfterDelete, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.enforceDeleteAsync(entityAfterDelete) ).rejects.toThrowError('name cannot have value afterDelete'); await expect( - PostgresTriggerTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresTriggerTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'afterDelete') ).resolves.not.toBeNull(); @@ -877,18 +617,12 @@ describe('postgres entity integration', () => { ); await expect( - PostgresValidatorTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresValidatorTestEntity.creator(vc1) .setField('name', 'beforeCreateAndBeforeUpdate') .enforceCreateAsync() ).rejects.toThrowError('name cannot have value beforeCreateAndBeforeUpdate'); await expect( - PostgresValidatorTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresValidatorTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'beforeCreateAndBeforeUpdate') ).resolves.toBeNull(); @@ -900,26 +634,17 @@ describe('postgres entity integration', () => { createKnexIntegrationTestEntityCompanionProvider(knexInstance) ); - const entity = await PostgresValidatorTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entity = await PostgresValidatorTestEntity.creator(vc1) .setField('name', 'blah') .enforceCreateAsync(); await expect( - PostgresValidatorTestEntity.updater( - entity, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresValidatorTestEntity.updater(entity) .setField('name', 'beforeCreateAndBeforeUpdate') .enforceUpdateAsync() ).rejects.toThrowError('name cannot have value beforeCreateAndBeforeUpdate'); await expect( - PostgresValidatorTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresValidatorTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'beforeCreateAndBeforeUpdate') ).resolves.toBeNull(); @@ -931,21 +656,12 @@ describe('postgres entity integration', () => { createKnexIntegrationTestEntityCompanionProvider(knexInstance) ); - const entityToDelete = await PostgresValidatorTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const entityToDelete = await PostgresValidatorTestEntity.creator(vc1) .setField('name', 'shouldBeDeleted') .enforceCreateAsync(); - await PostgresValidatorTestEntity.enforceDeleteAsync( - entityToDelete, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ); + await PostgresValidatorTestEntity.enforceDeleteAsync(entityToDelete); await expect( - PostgresValidatorTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + PostgresValidatorTestEntity.loader(vc1) .enforcing() .loadByFieldEqualingAsync('name', 'shouldBeDeleted') ).resolves.toBeNull(); diff --git a/packages/entity-database-adapter-knex/src/__integration-tests__/PostgresEntityQueryContextProvider-test.ts b/packages/entity-database-adapter-knex/src/__integration-tests__/PostgresEntityQueryContextProvider-test.ts index ceb1e4d5..ca064ba2 100644 --- a/packages/entity-database-adapter-knex/src/__integration-tests__/PostgresEntityQueryContextProvider-test.ts +++ b/packages/entity-database-adapter-knex/src/__integration-tests__/PostgresEntityQueryContextProvider-test.ts @@ -34,20 +34,10 @@ describe(PostgresEntityQueryContextProvider, () => { it('supports nested transactions', async () => { const vc1 = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); - await PostgresUniqueTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'unique') - .enforceCreateAsync(); + await PostgresUniqueTestEntity.creator(vc1).setField('name', 'unique').enforceCreateAsync(); const id = ( - await PostgresUniqueTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'wat') - .enforceCreateAsync() + await PostgresUniqueTestEntity.creator(vc1).setField('name', 'wat').enforceCreateAsync() ).getID(); await vc1.runInTransactionForDatabaseAdaptorFlavorAsync('postgres', async (queryContext) => { @@ -79,12 +69,7 @@ describe(PostgresEntityQueryContextProvider, () => { .enforceUpdateAsync(); }); - const entityLoaded = await PostgresUniqueTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .enforcing() - .loadByIDAsync(id); + const entityLoaded = await PostgresUniqueTestEntity.loader(vc1).enforcing().loadByIDAsync(id); expect(entityLoaded.getField('name')).toEqual('wat3'); }); @@ -92,12 +77,7 @@ describe(PostgresEntityQueryContextProvider, () => { const vc1 = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); const id = ( - await PostgresUniqueTestEntity.creator( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'wat') - .enforceCreateAsync() + await PostgresUniqueTestEntity.creator(vc1).setField('name', 'wat').enforceCreateAsync() ).getID(); await vc1.runInTransactionForDatabaseAdaptorFlavorAsync('postgres', async (queryContext) => { @@ -115,12 +95,7 @@ describe(PostgresEntityQueryContextProvider, () => { }); }); - const entityLoaded = await PostgresUniqueTestEntity.loader( - vc1, - vc1.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .enforcing() - .loadByIDAsync(id); + const entityLoaded = await PostgresUniqueTestEntity.loader(vc1).enforcing().loadByIDAsync(id); expect(entityLoaded.getField('name')).toEqual('wat3'); }); }); diff --git a/packages/entity-database-adapter-knex/src/__integration-tests__/PostgresInvalidSetup-test.ts b/packages/entity-database-adapter-knex/src/__integration-tests__/PostgresInvalidSetup-test.ts index a97b5f58..7edcf546 100644 --- a/packages/entity-database-adapter-knex/src/__integration-tests__/PostgresInvalidSetup-test.ts +++ b/packages/entity-database-adapter-knex/src/__integration-tests__/PostgresInvalidSetup-test.ts @@ -35,86 +35,40 @@ describe('postgres entity integration', () => { it('throws after deletion of multiple rows or no rows', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); const entity1 = await enforceAsyncResult( - InvalidTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('id', 1) - .setField('name', 'hello') - .createAsync() + InvalidTestEntity.creator(vc).setField('id', 1).setField('name', 'hello').createAsync() ); await enforceAsyncResult( - InvalidTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('id', 1) - .setField('name', 'world') - .createAsync() + InvalidTestEntity.creator(vc).setField('id', 1).setField('name', 'world').createAsync() ); - await expect( - InvalidTestEntity.deleteAsync( - entity1, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - ).rejects.toThrowError('Excessive deletions from database adapter delete'); + await expect(InvalidTestEntity.deleteAsync(entity1)).rejects.toThrowError( + 'Excessive deletions from database adapter delete' + ); }); it('throws after update of multiple rows', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); const entity1 = await enforceAsyncResult( - InvalidTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('id', 1) - .setField('name', 'hello') - .createAsync() + InvalidTestEntity.creator(vc).setField('id', 1).setField('name', 'hello').createAsync() ); await enforceAsyncResult( - InvalidTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('id', 1) - .setField('name', 'world') - .createAsync() + InvalidTestEntity.creator(vc).setField('id', 1).setField('name', 'world').createAsync() ); await expect( - InvalidTestEntity.updater( - entity1, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'blah') - .enforceUpdateAsync() + InvalidTestEntity.updater(entity1).setField('name', 'blah').enforceUpdateAsync() ).rejects.toThrowError('Excessive results from database adapter update'); }); it('throws after update of no rows', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); const entity1 = await enforceAsyncResult( - InvalidTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('id', 1) - .setField('name', 'hello') - .createAsync() - ); - await InvalidTestEntity.deleteAsync( - entity1, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') + InvalidTestEntity.creator(vc).setField('id', 1).setField('name', 'hello').createAsync() ); + await InvalidTestEntity.deleteAsync(entity1); await expect( - InvalidTestEntity.updater( - entity1, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .setField('name', 'blah') - .enforceUpdateAsync() + InvalidTestEntity.updater(entity1).setField('name', 'blah').enforceUpdateAsync() ).rejects.toThrowError('Empty results from database adapter update'); }); }); diff --git a/packages/entity-database-adapter-knex/src/__integration-tests__/errors-test.ts b/packages/entity-database-adapter-knex/src/__integration-tests__/errors-test.ts index 0bd6dd91..66205281 100644 --- a/packages/entity-database-adapter-knex/src/__integration-tests__/errors-test.ts +++ b/packages/entity-database-adapter-knex/src/__integration-tests__/errors-test.ts @@ -41,10 +41,7 @@ describe('postgres errors', () => { it('throws EntityDatabaseAdapterTransientError on Knex timeout', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); - await ErrorsTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + await ErrorsTestEntity.creator(vc) .setField('id', 1) .setField('fieldNonNull', 'hello') .enforceCreateAsync(); @@ -63,24 +60,16 @@ describe('postgres errors', () => { const vc2 = new ViewerContext( createKnexIntegrationTestEntityCompanionProvider(shortTimeoutKnexInstance) ); - await expect( - ErrorsTestEntity.loader( - vc2, - vc2.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) - .enforcing() - .loadByIDAsync(1) - ).rejects.toThrow(EntityDatabaseAdapterTransientError); + await expect(ErrorsTestEntity.loader(vc2).enforcing().loadByIDAsync(1)).rejects.toThrow( + EntityDatabaseAdapterTransientError + ); await shortTimeoutKnexInstance.destroy(); }); it('throws EntityDatabaseAdapterNotNullConstraintError when not null is violated', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); await expect( - ErrorsTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + ErrorsTestEntity.creator(vc) .setField('id', 1) .setField('fieldNonNull', null as any) .enforceCreateAsync() @@ -90,10 +79,7 @@ describe('postgres errors', () => { it('throws EntityDatabaseAdapterForeignKeyConstraintError when foreign key is violated', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); await expect( - ErrorsTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + ErrorsTestEntity.creator(vc) .setField('id', 1) .setField('fieldNonNull', 'hello') .setField('fieldForeignKey', 2) @@ -104,19 +90,13 @@ describe('postgres errors', () => { it('throws EntityDatabaseAdapterUniqueConstraintError when primary key unique constraint is violated', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); - await ErrorsTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + await ErrorsTestEntity.creator(vc) .setField('id', 1) .setField('fieldNonNull', 'hello') .enforceCreateAsync(); await expect( - ErrorsTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + ErrorsTestEntity.creator(vc) .setField('id', 1) .setField('fieldNonNull', 'hello') .enforceCreateAsync() @@ -125,20 +105,14 @@ describe('postgres errors', () => { it('throws EntityDatabaseAdapterUniqueConstraintError when unique constraint is violated', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); - await ErrorsTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + await ErrorsTestEntity.creator(vc) .setField('id', 2) .setField('fieldNonNull', 'hello') .setField('fieldUnique', 'hello') .enforceCreateAsync(); await expect( - ErrorsTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + ErrorsTestEntity.creator(vc) .setField('id', 1) .setField('fieldNonNull', 'hello') .setField('fieldUnique', 'hello') @@ -149,10 +123,7 @@ describe('postgres errors', () => { it('throws EntityDatabaseAdapterCheckConstraintError when check constraint is violated', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); await expect( - ErrorsTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + ErrorsTestEntity.creator(vc) .setField('id', 1) .setField('fieldNonNull', 'hello') .setField('checkLessThan5', 2) @@ -160,10 +131,7 @@ describe('postgres errors', () => { ).resolves.toBeTruthy(); await expect( - ErrorsTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + ErrorsTestEntity.creator(vc) .setField('id', 2) .setField('fieldNonNull', 'hello') .setField('checkLessThan5', 10) @@ -174,10 +142,7 @@ describe('postgres errors', () => { it('throws EntityDatabaseAdapterExclusionConstraintError when exclusion constraint is violated', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); await expect( - ErrorsTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + ErrorsTestEntity.creator(vc) .setField('id', 1) .setField('fieldNonNull', 'hello') .setField('fieldExclusion', 'what') @@ -185,10 +150,7 @@ describe('postgres errors', () => { ).resolves.toBeTruthy(); await expect( - ErrorsTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + ErrorsTestEntity.creator(vc) .setField('id', 2) .setField('fieldNonNull', 'hello') .setField('fieldExclusion', 'what') @@ -199,10 +161,7 @@ describe('postgres errors', () => { it('throws EntityDatabaseAdapterUnknownError otherwise', async () => { const vc = new ViewerContext(createKnexIntegrationTestEntityCompanionProvider(knexInstance)); await expect( - ErrorsTestEntity.creator( - vc, - vc.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + ErrorsTestEntity.creator(vc) .setField('id', 1) .setField('fieldNonNull', 'hello') .setField('nonExistentColumn', 'what') diff --git a/packages/entity-example/src/__tests__/NoteEntity-test.ts b/packages/entity-example/src/__tests__/NoteEntity-test.ts index dd5d6745..8c073dee 100644 --- a/packages/entity-example/src/__tests__/NoteEntity-test.ts +++ b/packages/entity-example/src/__tests__/NoteEntity-test.ts @@ -10,20 +10,14 @@ describe(NoteEntity, () => { const userId = uuidv4(); const viewerContext = new UserViewerContext(companionProvider, userId); - const createdEntityResult = await NoteEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ) + const createdEntityResult = await NoteEntity.creator(viewerContext) .setField('userID', userId) .setField('body', 'image') .setField('title', 'page') .createAsync(); expect(createdEntityResult.ok).toBe(true); - const createdEntityResultImpersonate = await NoteEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ) + const createdEntityResultImpersonate = await NoteEntity.creator(viewerContext) .setField('userID', uuidv4()) // a different user .setField('body', 'image') .setField('title', 'page') diff --git a/packages/entity-example/src/routers/notesRouter.ts b/packages/entity-example/src/routers/notesRouter.ts index 0199c157..a5653791 100644 --- a/packages/entity-example/src/routers/notesRouter.ts +++ b/packages/entity-example/src/routers/notesRouter.ts @@ -19,7 +19,7 @@ router.get('/', async (ctx) => { const viewerContext = ctx.state.viewerContext; let notes: readonly NoteEntity[] = []; if (viewerContext.isUserViewerContext()) { - notes = await NoteEntity.loader(viewerContext, viewerContext.getQueryContext()) + notes = await NoteEntity.loader(viewerContext) .enforcing() .loadManyByFieldEqualingAsync('userID', viewerContext.userID); } @@ -30,10 +30,7 @@ router.get('/', async (ctx) => { router.get('/:id', async (ctx) => { const viewerContext = ctx.state.viewerContext; - const noteResult = await NoteEntity.loader( - viewerContext, - viewerContext.getQueryContext() - ).loadByIDAsync(ctx.params['id']!); + const noteResult = await NoteEntity.loader(viewerContext).loadByIDAsync(ctx.params['id']!); if (!noteResult.ok) { ctx.throw(403, noteResult.reason); return; @@ -56,7 +53,7 @@ router.post('/', async (ctx) => { const { title, body } = ctx.request.body as any; - const createResult = await NoteEntity.creator(viewerContext, viewerContext.getQueryContext()) + const createResult = await NoteEntity.creator(viewerContext) .setField('userID', viewerContext.userID) .setField('title', title) .setField('body', body) @@ -75,41 +72,44 @@ router.put('/:id', async (ctx) => { const viewerContext = ctx.state.viewerContext; const { title, body } = ctx.request.body as any; - try { - const updatedNote = await viewerContext.runInTransactionAsync(async (queryContext) => { - const note = await NoteEntity.loader(viewerContext, queryContext) - .enforcing() - .loadByIDAsync(ctx.params['id']!); - - return await NoteEntity.updater(note, queryContext) - .setField('title', title) - .setField('body', body) - .enforceUpdateAsync(); - }); - ctx.body = { - note: updatedNote.getAllFields(), - }; - } catch (e: any) { - ctx.throw(403, e.message); + const noteLoadResult = await NoteEntity.loader(viewerContext).loadByIDAsync(ctx.params['id']!); + if (!noteLoadResult.ok) { + ctx.throw(403, noteLoadResult.reason); + return; + } + + const noteUpdateResult = await NoteEntity.updater(noteLoadResult.value) + .setField('title', title) + .setField('body', body) + .updateAsync(); + if (!noteUpdateResult.ok) { + ctx.throw(403, noteUpdateResult.reason); + return; } + + ctx.body = { + note: noteUpdateResult.value.getAllFields(), + }; }); router.delete('/:id', async (ctx) => { const viewerContext = ctx.state.viewerContext; - try { - await viewerContext.runInTransactionAsync(async (queryContext) => { - const note = await NoteEntity.loader(viewerContext, queryContext) - .enforcing() - .loadByIDAsync(ctx.params['id']!); - await NoteEntity.enforceDeleteAsync(note, queryContext); - }); - ctx.body = { - status: 'ok', - }; - } catch (e: any) { - ctx.throw(403, e.message); + const noteLoadResult = await NoteEntity.loader(viewerContext).loadByIDAsync(ctx.params['id']!); + if (!noteLoadResult.ok) { + ctx.throw(403, noteLoadResult.reason); + return; + } + + const noteDeleteResult = await NoteEntity.deleteAsync(noteLoadResult.value); + if (!noteDeleteResult.ok) { + ctx.throw(403, noteDeleteResult.reason); + return; } + + ctx.body = { + status: 'ok', + }; }); export default router; diff --git a/packages/entity-example/src/schema.ts b/packages/entity-example/src/schema.ts index a4a30b95..c050b210 100644 --- a/packages/entity-example/src/schema.ts +++ b/packages/entity-example/src/schema.ts @@ -46,16 +46,14 @@ export const resolvers: IResolvers = { return viewerContext.userID; }, async noteByID(_root, args, { viewerContext }) { - return await NoteEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDAsync(args.id); + return await NoteEntity.loader(viewerContext).enforcing().loadByIDAsync(args.id); }, } as IObjectTypeResolver, User: { id: (root) => root, async notes(root, _args, { viewerContext }) { - return await NoteEntity.loader(viewerContext, viewerContext.getQueryContext()) + return await NoteEntity.loader(viewerContext) .enforcing() .loadManyByFieldEqualingAsync('userID', root); }, @@ -74,31 +72,27 @@ export const resolvers: IResolvers = { throw new Error('not logged in'); } - return await NoteEntity.creator(viewerContext, viewerContext.getQueryContext()) + return await NoteEntity.creator(viewerContext) .setField('userID', viewerContext.userID) .setField('title', args.note.title) .setField('body', args.note.body) .enforceCreateAsync(); }, async updateNote(_root, args, { viewerContext }) { - return await viewerContext.runInTransactionAsync(async (queryContext) => { - const existingNote = await NoteEntity.loader(viewerContext, queryContext) - .enforcing() - .loadByIDAsync(args.id); - return await NoteEntity.updater(existingNote, queryContext) - .setField('title', args.note.title) - .setField('body', args.note.body) - .enforceUpdateAsync(); - }); + const existingNote = await NoteEntity.loader(viewerContext) + .enforcing() + .loadByIDAsync(args.id); + return await NoteEntity.updater(existingNote) + .setField('title', args.note.title) + .setField('body', args.note.body) + .enforceUpdateAsync(); }, async deleteNote(_root, args, { viewerContext }) { - return await viewerContext.runInTransactionAsync(async (queryContext) => { - const existingNote = await NoteEntity.loader(viewerContext, queryContext) - .enforcing() - .loadByIDAsync(args.id); - await NoteEntity.enforceDeleteAsync(existingNote, queryContext); - return existingNote; - }); + const existingNote = await NoteEntity.loader(viewerContext) + .enforcing() + .loadByIDAsync(args.id); + await NoteEntity.enforceDeleteAsync(existingNote); + return existingNote; }, } as IObjectTypeResolver, }; diff --git a/packages/entity-example/src/viewerContexts.ts b/packages/entity-example/src/viewerContexts.ts index 36af7cc7..f9bb35c9 100644 --- a/packages/entity-example/src/viewerContexts.ts +++ b/packages/entity-example/src/viewerContexts.ts @@ -1,9 +1,4 @@ -import { - ViewerContext, - EntityCompanionProvider, - EntityQueryContext, - EntityTransactionalQueryContext, -} from '@expo/entity'; +import { ViewerContext, EntityCompanionProvider } from '@expo/entity'; /** * A base class for better typing Entities and Privacy Policies specific to this application. @@ -16,16 +11,6 @@ export abstract class ExampleViewerContext extends ViewerContext { isAnonymousViewerContext(): this is AnonymousViewerContext { return this instanceof AnonymousViewerContext; } - - public getQueryContext(): EntityQueryContext { - return super.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres'); - } - - public async runInTransactionAsync( - transactionScope: (queryContext: EntityTransactionalQueryContext) => Promise - ): Promise { - return await super.runInTransactionForDatabaseAdaptorFlavorAsync('postgres', transactionScope); - } } /** diff --git a/packages/entity-full-integration-tests/src/__integration-tests__/EntityCacheInconsistency-test.ts b/packages/entity-full-integration-tests/src/__integration-tests__/EntityCacheInconsistency-test.ts index 6966a9fa..064f06d4 100644 --- a/packages/entity-full-integration-tests/src/__integration-tests__/EntityCacheInconsistency-test.ts +++ b/packages/entity-full-integration-tests/src/__integration-tests__/EntityCacheInconsistency-test.ts @@ -1,5 +1,6 @@ import { EntityPrivacyPolicy, + ViewerContext, AlwaysAllowPrivacyPolicyRule, Entity, EntityCompanionDefinition, @@ -13,7 +14,6 @@ import { knex, Knex } from 'knex'; import nullthrows from 'nullthrows'; import { URL } from 'url'; -import TestViewerContext from './entities/TestViewerContext'; import { createFullIntegrationTestEntityCompanionProvider } from '../testfixtures/createFullIntegrationTestEntityCompanionProvider'; interface TestFields { @@ -25,28 +25,28 @@ interface TestFields { class TestEntityPrivacyPolicy extends EntityPrivacyPolicy< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity > { protected override readonly readRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly createRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly updateRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly deleteRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; } -class TestEntity extends Entity { +class TestEntity extends Entity { static defineCompanionDefinition(): EntityCompanionDefinition< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, TestEntityPrivacyPolicy > { @@ -136,20 +136,18 @@ describe('Entity cache inconsistency', () => { }); test('lots of updates in long-ish running transactions', async () => { - const viewerContext = new TestViewerContext( + const viewerContext = new ViewerContext( createFullIntegrationTestEntityCompanionProvider(knexInstance, genericRedisCacheContext) ); - const entity1 = await TestEntity.creator(viewerContext, viewerContext.getQueryContext()) + const entity1 = await TestEntity.creator(viewerContext) .setField('other_string', 'hello') .setField('third_string', 'initial') .enforceCreateAsync(); // put entities in cache and dataloader - await TestEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDAsync(entity1.getID()); - await TestEntity.loader(viewerContext, viewerContext.getQueryContext()) + await TestEntity.loader(viewerContext).enforcing().loadByIDAsync(entity1.getID()); + await TestEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('other_string', 'hello'); @@ -166,17 +164,15 @@ describe('Entity cache inconsistency', () => { await Promise.all([ // do a load after the transaction below updates the entity but before transaction commits to ensure // that the cache is cleared after the transaction commits rather than in the middle where the changes - // may not be visible by other requests (TestViewerContexts) which would cache the incorrect + // may not be visible by other requests (ViewerContexts) which would cache the incorrect // value during the read-through cache. (async () => { await barrier1; - const viewerContextInternal = new TestViewerContext( + const viewerContextInternal = new ViewerContext( createFullIntegrationTestEntityCompanionProvider(knexInstance, genericRedisCacheContext) ); - await TestEntity.loader(viewerContextInternal, viewerContextInternal.getQueryContext()) - .enforcing() - .loadByIDAsync(entity1.getID()); + await TestEntity.loader(viewerContextInternal).enforcing().loadByIDAsync(entity1.getID()); openBarrier2!(); })(), @@ -196,20 +192,14 @@ describe('Entity cache inconsistency', () => { ]); // ensure cache consistency - const viewerContextLast = new TestViewerContext( + const viewerContextLast = new ViewerContext( createFullIntegrationTestEntityCompanionProvider(knexInstance, genericRedisCacheContext) ); - const loadedById = await TestEntity.loader( - viewerContextLast, - viewerContextLast.getQueryContext() - ) + const loadedById = await TestEntity.loader(viewerContextLast) .enforcing() .loadByIDAsync(entity1.getID()); - const loadedByField = await TestEntity.loader( - viewerContextLast, - viewerContextLast.getQueryContext() - ) + const loadedByField = await TestEntity.loader(viewerContextLast) .enforcing() .loadByFieldEqualingAsync('other_string', 'hello'); diff --git a/packages/entity-full-integration-tests/src/__integration-tests__/EntityEdgesIntegration-test.ts b/packages/entity-full-integration-tests/src/__integration-tests__/EntityEdgesIntegration-test.ts index 771c7714..6eada1a5 100644 --- a/packages/entity-full-integration-tests/src/__integration-tests__/EntityEdgesIntegration-test.ts +++ b/packages/entity-full-integration-tests/src/__integration-tests__/EntityEdgesIntegration-test.ts @@ -1,3 +1,4 @@ +import { ViewerContext } from '@expo/entity'; import { GenericRedisCacheContext } from '@expo/entity-cache-adapter-redis'; import Redis from 'ioredis'; import { knex, Knex } from 'knex'; @@ -6,7 +7,6 @@ import { URL } from 'url'; import ChildEntity from './entities/ChildEntity'; import ParentEntity from './entities/ParentEntity'; -import TestViewerContext from './entities/TestViewerContext'; import { createFullIntegrationTestEntityCompanionProvider } from '../testfixtures/createFullIntegrationTestEntityCompanionProvider'; async function createOrTruncatePostgresTables(knex: Knex): Promise { @@ -75,41 +75,32 @@ describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => { describe('EntityEdgeDeletionBehavior.INVALIDATE_CACHE', () => { it('invalidates the cache', async () => { - const viewerContext = new TestViewerContext( + const viewerContext = new ViewerContext( createFullIntegrationTestEntityCompanionProvider(knexInstance, genericRedisCacheContext) ); - const parent = await ParentEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ).enforceCreateAsync(); - const child = await ChildEntity.creator(viewerContext, viewerContext.getQueryContext()) + const parent = await ParentEntity.creator(viewerContext).enforceCreateAsync(); + const child = await ChildEntity.creator(viewerContext) .setField('parent_id', parent.getID()) .enforceCreateAsync(); await expect( - ParentEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parent.getID()) + ParentEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parent.getID()) ).resolves.not.toBeNull(); await expect( - ChildEntity.loader(viewerContext, viewerContext.getQueryContext()) + ChildEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('parent_id', parent.getID()) ).resolves.not.toBeNull(); - await ParentEntity.enforceDeleteAsync(parent, viewerContext.getQueryContext()); + await ParentEntity.enforceDeleteAsync(parent); await expect( - ParentEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parent.getID()) + ParentEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parent.getID()) ).resolves.toBeNull(); await expect( - ChildEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(child.getID()) + ChildEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(child.getID()) ).resolves.toBeNull(); }); }); diff --git a/packages/entity-full-integration-tests/src/__integration-tests__/EntitySelfReferentialEdgesIntegration-test.ts b/packages/entity-full-integration-tests/src/__integration-tests__/EntitySelfReferentialEdgesIntegration-test.ts index 864bd92a..d0dff765 100644 --- a/packages/entity-full-integration-tests/src/__integration-tests__/EntitySelfReferentialEdgesIntegration-test.ts +++ b/packages/entity-full-integration-tests/src/__integration-tests__/EntitySelfReferentialEdgesIntegration-test.ts @@ -15,7 +15,6 @@ import nullthrows from 'nullthrows'; import { URL } from 'url'; import { v4 as uuidv4 } from 'uuid'; -import TestViewerContext from './entities/TestViewerContext'; import { createFullIntegrationTestEntityCompanionProvider } from '../testfixtures/createFullIntegrationTestEntityCompanionProvider'; interface CategoryFields { @@ -218,53 +217,42 @@ describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => { edgeDeletionBehavior ); - const viewerContext = new TestViewerContext( + const viewerContext = new ViewerContext( createFullIntegrationTestEntityCompanionProvider(knexInstance, genericRedisCacheContext) ); - const category1 = await CategoryEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ).enforceCreateAsync(); - const other1 = await OtherEntity.creator(viewerContext, viewerContext.getQueryContext()) + const category1 = await CategoryEntity.creator(viewerContext).enforceCreateAsync(); + const other1 = await OtherEntity.creator(viewerContext) .setField('parent_category_id', category1.getID()) .enforceCreateAsync(); - await CategoryEntity.updater(category1, viewerContext.getQueryContext()) + await CategoryEntity.updater(category1) .setField('parent_other_id', other1.getID()) .enforceUpdateAsync(); - await CategoryEntity.enforceDeleteAsync(category1, viewerContext.getQueryContext()); + await CategoryEntity.enforceDeleteAsync(category1); if (edgeDeletionBehavior === EntityEdgeDeletionBehavior.SET_NULL) { await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(category1.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(category1.getID()) ).resolves.toBeNull(); - const otherLoaded = await OtherEntity.loader(viewerContext, viewerContext.getQueryContext()) + const otherLoaded = await OtherEntity.loader(viewerContext) .enforcing() .loadByIDNullableAsync(other1.getID()); expect(otherLoaded?.getField('parent_category_id')).toBeNull(); } else if (edgeDeletionBehavior === EntityEdgeDeletionBehavior.SET_NULL_INVALIDATE_CACHE_ONLY) { await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(category1.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(category1.getID()) ).resolves.toBeNull(); - const otherLoaded = await OtherEntity.loader(viewerContext, viewerContext.getQueryContext()) + const otherLoaded = await OtherEntity.loader(viewerContext) .enforcing() .loadByIDNullableAsync(other1.getID()); expect(otherLoaded?.getField('parent_category_id')).toBeNull(); } else { await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(category1.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(category1.getID()) ).resolves.toBeNull(); await expect( - OtherEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(other1.getID()) + OtherEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(other1.getID()) ).resolves.toBeNull(); } }); diff --git a/packages/entity-full-integration-tests/src/__integration-tests__/entities/ChildEntity.ts b/packages/entity-full-integration-tests/src/__integration-tests__/entities/ChildEntity.ts index 53d8a11b..4da93213 100644 --- a/packages/entity-full-integration-tests/src/__integration-tests__/entities/ChildEntity.ts +++ b/packages/entity-full-integration-tests/src/__integration-tests__/entities/ChildEntity.ts @@ -6,42 +6,36 @@ import { EntityEdgeDeletionBehavior, EntityPrivacyPolicy, UUIDField, + ViewerContext, } from '@expo/entity'; import ParentEntity from './ParentEntity'; -import TestViewerContext from './TestViewerContext'; interface ChildFields { id: string; parent_id: string; } -class TestEntityPrivacyPolicy extends EntityPrivacyPolicy< - any, - string, - TestViewerContext, - any, - any -> { +class TestEntityPrivacyPolicy extends EntityPrivacyPolicy { protected override readonly readRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly createRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly updateRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly deleteRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; } -export default class ChildEntity extends Entity { +export default class ChildEntity extends Entity { static defineCompanionDefinition(): EntityCompanionDefinition< ChildFields, string, - TestViewerContext, + ViewerContext, ChildEntity, TestEntityPrivacyPolicy > { diff --git a/packages/entity-full-integration-tests/src/__integration-tests__/entities/ParentEntity.ts b/packages/entity-full-integration-tests/src/__integration-tests__/entities/ParentEntity.ts index 2630ea4a..4c6952d7 100644 --- a/packages/entity-full-integration-tests/src/__integration-tests__/entities/ParentEntity.ts +++ b/packages/entity-full-integration-tests/src/__integration-tests__/entities/ParentEntity.ts @@ -5,41 +5,35 @@ import { EntityConfiguration, EntityPrivacyPolicy, UUIDField, + ViewerContext, } from '@expo/entity'; import ChildEntity from './ChildEntity'; -import TestViewerContext from './TestViewerContext'; interface ParentFields { id: string; } -class TestEntityPrivacyPolicy extends EntityPrivacyPolicy< - any, - string, - TestViewerContext, - any, - any -> { +class TestEntityPrivacyPolicy extends EntityPrivacyPolicy { protected override readonly readRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly createRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly updateRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly deleteRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; } -export default class ParentEntity extends Entity { +export default class ParentEntity extends Entity { static defineCompanionDefinition(): EntityCompanionDefinition< ParentFields, string, - TestViewerContext, + ViewerContext, ParentEntity, TestEntityPrivacyPolicy > { diff --git a/packages/entity-full-integration-tests/src/__integration-tests__/entities/TestViewerContext.ts b/packages/entity-full-integration-tests/src/__integration-tests__/entities/TestViewerContext.ts deleted file mode 100644 index 9482fdf9..00000000 --- a/packages/entity-full-integration-tests/src/__integration-tests__/entities/TestViewerContext.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { EntityQueryContext, EntityTransactionalQueryContext, ViewerContext } from '@expo/entity'; - -export default class TestViewerContext extends ViewerContext { - public getQueryContext(): EntityQueryContext { - return super.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres'); - } - - public async runInTransactionAsync( - transactionScope: (queryContext: EntityTransactionalQueryContext) => Promise - ): Promise { - return await super.runInTransactionForDatabaseAdaptorFlavorAsync('postgres', transactionScope); - } -} diff --git a/packages/entity-secondary-cache-local-memory/src/__tests__/LocalMemorySecondaryEntityCache-test.ts b/packages/entity-secondary-cache-local-memory/src/__tests__/LocalMemorySecondaryEntityCache-test.ts index f63a8546..8637f6ce 100644 --- a/packages/entity-secondary-cache-local-memory/src/__tests__/LocalMemorySecondaryEntityCache-test.ts +++ b/packages/entity-secondary-cache-local-memory/src/__tests__/LocalMemorySecondaryEntityCache-test.ts @@ -172,10 +172,7 @@ describe(LocalMemorySecondaryEntityCache, () => { it('Loads through secondary loader, caches, and invalidates', async () => { const viewerContext = new TestViewerContext(createTestEntityCompanionProvider()); - const createdEntity = await LocalMemoryTestEntity.creator( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const createdEntity = await LocalMemoryTestEntity.creator(viewerContext) .setField('name', 'wat') .enforceCreateAsync(); @@ -184,10 +181,7 @@ describe(LocalMemorySecondaryEntityCache, () => { localMemoryTestEntityConfiguration, GenericLocalMemoryCacher.createLRUCache({}) ), - LocalMemoryTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + LocalMemoryTestEntity.loader(viewerContext) ); const loadParams = { id: createdEntity.getID() }; @@ -223,10 +217,7 @@ describe(LocalMemorySecondaryEntityCache, () => { localMemoryTestEntityConfiguration, GenericLocalMemoryCacher.createLRUCache({}) ), - LocalMemoryTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + LocalMemoryTestEntity.loader(viewerContext) ); const loadParams = { id: FAKE_ID }; diff --git a/packages/entity-secondary-cache-redis/src/__integration-tests__/RedisSecondaryEntityCache-integration-test.ts b/packages/entity-secondary-cache-redis/src/__integration-tests__/RedisSecondaryEntityCache-integration-test.ts index 24cdd877..bcf2ce99 100644 --- a/packages/entity-secondary-cache-redis/src/__integration-tests__/RedisSecondaryEntityCache-integration-test.ts +++ b/packages/entity-secondary-cache-redis/src/__integration-tests__/RedisSecondaryEntityCache-integration-test.ts @@ -79,10 +79,7 @@ describe(RedisSecondaryEntityCache, () => { createRedisIntegrationTestEntityCompanionProvider(genericRedisCacheContext) ); - const createdEntity = await RedisTestEntity.creator( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + const createdEntity = await RedisTestEntity.creator(viewerContext) .setField('name', 'wat') .enforceCreateAsync(); @@ -92,10 +89,7 @@ describe(RedisSecondaryEntityCache, () => { genericRedisCacheContext, (loadParams) => `test-key-${loadParams.id}` ), - RedisTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + RedisTestEntity.loader(viewerContext) ); const loadParams = { id: createdEntity.getID() }; @@ -134,10 +128,7 @@ describe(RedisSecondaryEntityCache, () => { genericRedisCacheContext, (loadParams) => `test-key-${loadParams.id}` ), - RedisTestEntity.loader( - viewerContext, - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres') - ) + RedisTestEntity.loader(viewerContext) ); const loadParams = { id: FAKE_ID }; diff --git a/packages/entity/src/Entity.ts b/packages/entity/src/Entity.ts index 17d47344..280d37fe 100644 --- a/packages/entity/src/Entity.ts +++ b/packages/entity/src/Entity.ts @@ -61,7 +61,10 @@ export default abstract class Entity< TMSelectedFields >, viewerContext: TMViewerContext2, - queryContext: EntityQueryContext + queryContext: EntityQueryContext = viewerContext + .getViewerScopedEntityCompanionForClass(this) + .getQueryContextProvider() + .getQueryContext() ): CreateMutator { return viewerContext .getViewerScopedEntityCompanionForClass(this) @@ -98,7 +101,11 @@ export default abstract class Entity< TMSelectedFields >, existingEntity: TMEntity, - queryContext: EntityQueryContext + queryContext: EntityQueryContext = existingEntity + .getViewerContext() + .getViewerScopedEntityCompanionForClass(this) + .getQueryContextProvider() + .getQueryContext() ): UpdateMutator { return existingEntity .getViewerContext() @@ -135,7 +142,11 @@ export default abstract class Entity< TMSelectedFields >, existingEntity: TMEntity, - queryContext: EntityQueryContext + queryContext: EntityQueryContext = existingEntity + .getViewerContext() + .getViewerScopedEntityCompanionForClass(this) + .getQueryContextProvider() + .getQueryContext() ): Promise> { return existingEntity .getViewerContext() @@ -173,7 +184,11 @@ export default abstract class Entity< TMSelectedFields >, existingEntity: TMEntity, - queryContext: EntityQueryContext + queryContext: EntityQueryContext = existingEntity + .getViewerContext() + .getViewerScopedEntityCompanionForClass(this) + .getQueryContextProvider() + .getQueryContext() ): Promise { return existingEntity .getViewerContext() @@ -222,7 +237,11 @@ export default abstract class Entity< TMSelectedFields >, existingEntity: TMEntity, - queryContext: EntityQueryContext + queryContext: EntityQueryContext = existingEntity + .getViewerContext() + .getViewerScopedEntityCompanionForClass(this) + .getQueryContextProvider() + .getQueryContext() ): Promise { const companion = existingEntity .getViewerContext() @@ -272,7 +291,11 @@ export default abstract class Entity< TMSelectedFields >, existingEntity: TMEntity, - queryContext: EntityQueryContext + queryContext: EntityQueryContext = existingEntity + .getViewerContext() + .getViewerScopedEntityCompanionForClass(this) + .getQueryContextProvider() + .getQueryContext() ): Promise { const companion = existingEntity .getViewerContext() diff --git a/packages/entity/src/EntityAssociationLoader.ts b/packages/entity/src/EntityAssociationLoader.ts index 092266d6..ee42215e 100644 --- a/packages/entity/src/EntityAssociationLoader.ts +++ b/packages/entity/src/EntityAssociationLoader.ts @@ -55,7 +55,11 @@ export default class EntityAssociationLoader< TAssociatedPrivacyPolicy, TAssociatedSelectedFields >, - queryContext: EntityQueryContext + queryContext: EntityQueryContext = this.entity + .getViewerContext() + .getViewerScopedEntityCompanionForClass(associatedEntityClass) + .getQueryContextProvider() + .getQueryContext() ): Promise< Result > { @@ -113,7 +117,11 @@ export default class EntityAssociationLoader< TAssociatedSelectedFields >, associatedEntityFieldContainingThisID: keyof Pick, - queryContext: EntityQueryContext + queryContext: EntityQueryContext = this.entity + .getViewerContext() + .getViewerScopedEntityCompanionForClass(associatedEntityClass) + .getQueryContextProvider() + .getQueryContext() ): Promise[]> { const thisID = this.entity.getID(); const loader = this.entity @@ -163,7 +171,11 @@ export default class EntityAssociationLoader< TAssociatedSelectedFields >, associatedEntityLookupByField: keyof Pick, - queryContext: EntityQueryContext + queryContext: EntityQueryContext = this.entity + .getViewerContext() + .getViewerScopedEntityCompanionForClass(associatedEntityClass) + .getQueryContextProvider() + .getQueryContext() ): Promise | null> { const associatedFieldValue = this.entity.getField(fieldIdentifyingAssociatedEntity); if (!associatedFieldValue) { @@ -216,7 +228,11 @@ export default class EntityAssociationLoader< TAssociatedSelectedFields >, associatedEntityLookupByField: keyof Pick, - queryContext: EntityQueryContext + queryContext: EntityQueryContext = this.entity + .getViewerContext() + .getViewerScopedEntityCompanionForClass(associatedEntityClass) + .getQueryContextProvider() + .getQueryContext() ): Promise[]> { const associatedFieldValue = this.entity.getField(fieldIdentifyingAssociatedEntity); if (!associatedFieldValue) { @@ -265,7 +281,7 @@ export default class EntityAssociationLoader< TSelectedFields2 > ], - queryContext: EntityQueryContext + queryContext?: EntityQueryContext ): Promise | null>; /** @@ -320,7 +336,7 @@ export default class EntityAssociationLoader< TSelectedFields3 > ], - queryContext: EntityQueryContext + queryContext?: EntityQueryContext ): Promise | null>; /** @@ -396,7 +412,7 @@ export default class EntityAssociationLoader< TSelectedFields4 > ], - queryContext: EntityQueryContext + queryContext?: EntityQueryContext ): Promise | null>; /** @@ -407,12 +423,12 @@ export default class EntityAssociationLoader< */ async loadAssociatedEntityThroughAsync( loadDirectives: EntityLoadThroughDirective[], - queryContext: EntityQueryContext + queryContext?: EntityQueryContext ): Promise> | null>; async loadAssociatedEntityThroughAsync( loadDirectives: EntityLoadThroughDirective[], - queryContext: EntityQueryContext + queryContext?: EntityQueryContext ): Promise> | null> { let currentEntity: ReadonlyEntity = this.entity; for (const loadDirective of loadDirectives) { diff --git a/packages/entity/src/EntityQueryContextProvider.ts b/packages/entity/src/EntityQueryContextProvider.ts index 59779d1c..42740fe9 100644 --- a/packages/entity/src/EntityQueryContextProvider.ts +++ b/packages/entity/src/EntityQueryContextProvider.ts @@ -12,7 +12,7 @@ export default abstract class EntityQueryContextProvider { /** * Vend a regular (non-transactional) entity query context. */ - public getNonTransactionalQueryContext(): EntityNonTransactionalQueryContext { + public getQueryContext(): EntityNonTransactionalQueryContext { return new EntityNonTransactionalQueryContext(this.getQueryInterface(), this); } diff --git a/packages/entity/src/ReadonlyEntity.ts b/packages/entity/src/ReadonlyEntity.ts index 61b184bb..dec07d73 100644 --- a/packages/entity/src/ReadonlyEntity.ts +++ b/packages/entity/src/ReadonlyEntity.ts @@ -148,7 +148,10 @@ export default abstract class ReadonlyEntity< TMSelectedFields >, viewerContext: TMViewerContext2, - queryContext: EntityQueryContext + queryContext: EntityQueryContext = viewerContext + .getViewerScopedEntityCompanionForClass(this) + .getQueryContextProvider() + .getQueryContext() ): EntityLoader { return viewerContext .getViewerScopedEntityCompanionForClass(this) diff --git a/packages/entity/src/ViewerContext.ts b/packages/entity/src/ViewerContext.ts index 2cbe6406..3986fd03 100644 --- a/packages/entity/src/ViewerContext.ts +++ b/packages/entity/src/ViewerContext.ts @@ -2,7 +2,7 @@ import { IEntityClass } from './Entity'; import EntityCompanionProvider, { DatabaseAdapterFlavor } from './EntityCompanionProvider'; import EntityPrivacyPolicy from './EntityPrivacyPolicy'; import { - EntityNonTransactionalQueryContext, + EntityQueryContext, EntityTransactionalQueryContext, TransactionConfig, } from './EntityQueryContext'; @@ -67,12 +67,12 @@ export default class ViewerContext { * Get the regular (non-transactional) query context for a database adaptor flavor. * @param databaseAdaptorFlavor - database adaptor flavor */ - getNonTransactionalQueryContextForDatabaseAdaptorFlavor( + getQueryContextForDatabaseAdaptorFlavor( databaseAdaptorFlavor: DatabaseAdapterFlavor - ): EntityNonTransactionalQueryContext { + ): EntityQueryContext { return this.entityCompanionProvider .getQueryContextProviderForDatabaseAdaptorFlavor(databaseAdaptorFlavor) - .getNonTransactionalQueryContext(); + .getQueryContext(); } /** @@ -88,7 +88,7 @@ export default class ViewerContext { ): Promise { return await this.entityCompanionProvider .getQueryContextProviderForDatabaseAdaptorFlavor(databaseAdaptorFlavor) - .getNonTransactionalQueryContext() + .getQueryContext() .runInTransactionIfNotInTransactionAsync(transactionScope, transactionConfig); } } diff --git a/packages/entity/src/__tests__/Entity-test.ts b/packages/entity/src/__tests__/Entity-test.ts index 484ad318..74fde329 100644 --- a/packages/entity/src/__tests__/Entity-test.ts +++ b/packages/entity/src/__tests__/Entity-test.ts @@ -4,27 +4,25 @@ import EntityConfiguration from '../EntityConfiguration'; import { UUIDField } from '../EntityFields'; import { CreateMutator, UpdateMutator } from '../EntityMutator'; import EntityPrivacyPolicy from '../EntityPrivacyPolicy'; +import ViewerContext from '../ViewerContext'; import AlwaysAllowPrivacyPolicyRule from '../rules/AlwaysAllowPrivacyPolicyRule'; import AlwaysDenyPrivacyPolicyRule from '../rules/AlwaysDenyPrivacyPolicyRule'; import SimpleTestEntity from '../testfixtures/SimpleTestEntity'; -import TestViewerContext from '../testfixtures/TestViewerContext'; import { createUnitTestEntityCompanionProvider } from '../utils/testing/createUnitTestEntityCompanionProvider'; describe(Entity, () => { describe('creator', () => { it('creates a new CreateMutator', () => { const companionProvider = createUnitTestEntityCompanionProvider(); - const viewerContext = new TestViewerContext(companionProvider); - expect( - SimpleTestEntity.creator(viewerContext, viewerContext.getQueryContext()) - ).toBeInstanceOf(CreateMutator); + const viewerContext = new ViewerContext(companionProvider); + expect(SimpleTestEntity.creator(viewerContext)).toBeInstanceOf(CreateMutator); }); }); describe('updater', () => { it('creates a new UpdateMutator', () => { const companionProvider = createUnitTestEntityCompanionProvider(); - const viewerContext = new TestViewerContext(companionProvider); + const viewerContext = new ViewerContext(companionProvider); const data = { id: 'what', }; @@ -34,16 +32,14 @@ describe(Entity, () => { databaseFields: data, selectedFields: data, }); - expect(SimpleTestEntity.updater(testEntity, viewerContext.getQueryContext())).toBeInstanceOf( - UpdateMutator - ); + expect(SimpleTestEntity.updater(testEntity)).toBeInstanceOf(UpdateMutator); }); }); describe('canViewerUpdateAsync', () => { it('appropriately executes update privacy policy', async () => { const companionProvider = createUnitTestEntityCompanionProvider(); - const viewerContext = new TestViewerContext(companionProvider); + const viewerContext = new ViewerContext(companionProvider); const data = { id: 'what', }; @@ -53,16 +49,13 @@ describe(Entity, () => { databaseFields: data, selectedFields: data, }); - const canViewerUpdate = await SimpleTestDenyDeleteEntity.canViewerUpdateAsync( - testEntity, - viewerContext.getQueryContext() - ); + const canViewerUpdate = await SimpleTestDenyDeleteEntity.canViewerUpdateAsync(testEntity); expect(canViewerUpdate).toBe(true); }); it('denies when policy denies', async () => { const companionProvider = createUnitTestEntityCompanionProvider(); - const viewerContext = new TestViewerContext(companionProvider); + const viewerContext = new ViewerContext(companionProvider); const data = { id: 'what', }; @@ -72,10 +65,7 @@ describe(Entity, () => { databaseFields: data, selectedFields: data, }); - const canViewerUpdate = await SimpleTestDenyUpdateEntity.canViewerUpdateAsync( - testEntity, - viewerContext.getQueryContext() - ); + const canViewerUpdate = await SimpleTestDenyUpdateEntity.canViewerUpdateAsync(testEntity); expect(canViewerUpdate).toBe(false); }); }); @@ -83,7 +73,7 @@ describe(Entity, () => { describe('canViewerDeleteAsync', () => { it('appropriately executes update privacy policy', async () => { const companionProvider = createUnitTestEntityCompanionProvider(); - const viewerContext = new TestViewerContext(companionProvider); + const viewerContext = new ViewerContext(companionProvider); const data = { id: 'what', }; @@ -93,16 +83,13 @@ describe(Entity, () => { databaseFields: data, selectedFields: data, }); - const canViewerDelete = await SimpleTestDenyUpdateEntity.canViewerDeleteAsync( - testEntity, - viewerContext.getQueryContext() - ); + const canViewerDelete = await SimpleTestDenyUpdateEntity.canViewerDeleteAsync(testEntity); expect(canViewerDelete).toBe(true); }); it('denies when policy denies', async () => { const companionProvider = createUnitTestEntityCompanionProvider(); - const viewerContext = new TestViewerContext(companionProvider); + const viewerContext = new ViewerContext(companionProvider); const data = { id: 'what', }; @@ -112,10 +99,7 @@ describe(Entity, () => { databaseFields: data, selectedFields: data, }); - const canViewerDelete = await SimpleTestDenyDeleteEntity.canViewerDeleteAsync( - testEntity, - viewerContext.getQueryContext() - ); + const canViewerDelete = await SimpleTestDenyDeleteEntity.canViewerDeleteAsync(testEntity); expect(canViewerDelete).toBe(false); }); }); @@ -140,14 +124,14 @@ const testEntityConfiguration = new EntityConfiguration({ class SimpleTestDenyUpdateEntityPrivacyPolicy extends EntityPrivacyPolicy< TestEntityFields, string, - TestViewerContext, + ViewerContext, SimpleTestDenyUpdateEntity > { protected override readonly readRules = [ new AlwaysAllowPrivacyPolicyRule< TestEntityFields, string, - TestViewerContext, + ViewerContext, SimpleTestDenyUpdateEntity >(), ]; @@ -155,7 +139,7 @@ class SimpleTestDenyUpdateEntityPrivacyPolicy extends EntityPrivacyPolicy< new AlwaysAllowPrivacyPolicyRule< TestEntityFields, string, - TestViewerContext, + ViewerContext, SimpleTestDenyUpdateEntity >(), ]; @@ -163,7 +147,7 @@ class SimpleTestDenyUpdateEntityPrivacyPolicy extends EntityPrivacyPolicy< new AlwaysDenyPrivacyPolicyRule< TestEntityFields, string, - TestViewerContext, + ViewerContext, SimpleTestDenyUpdateEntity >(), ]; @@ -171,7 +155,7 @@ class SimpleTestDenyUpdateEntityPrivacyPolicy extends EntityPrivacyPolicy< new AlwaysAllowPrivacyPolicyRule< TestEntityFields, string, - TestViewerContext, + ViewerContext, SimpleTestDenyUpdateEntity >(), ]; @@ -180,14 +164,14 @@ class SimpleTestDenyUpdateEntityPrivacyPolicy extends EntityPrivacyPolicy< class SimpleTestDenyDeleteEntityPrivacyPolicy extends EntityPrivacyPolicy< TestEntityFields, string, - TestViewerContext, + ViewerContext, SimpleTestDenyDeleteEntity > { protected override readonly readRules = [ new AlwaysAllowPrivacyPolicyRule< TestEntityFields, string, - TestViewerContext, + ViewerContext, SimpleTestDenyDeleteEntity >(), ]; @@ -195,7 +179,7 @@ class SimpleTestDenyDeleteEntityPrivacyPolicy extends EntityPrivacyPolicy< new AlwaysAllowPrivacyPolicyRule< TestEntityFields, string, - TestViewerContext, + ViewerContext, SimpleTestDenyDeleteEntity >(), ]; @@ -203,7 +187,7 @@ class SimpleTestDenyDeleteEntityPrivacyPolicy extends EntityPrivacyPolicy< new AlwaysAllowPrivacyPolicyRule< TestEntityFields, string, - TestViewerContext, + ViewerContext, SimpleTestDenyDeleteEntity >(), ]; @@ -211,17 +195,17 @@ class SimpleTestDenyDeleteEntityPrivacyPolicy extends EntityPrivacyPolicy< new AlwaysDenyPrivacyPolicyRule< TestEntityFields, string, - TestViewerContext, + ViewerContext, SimpleTestDenyDeleteEntity >(), ]; } -class SimpleTestDenyUpdateEntity extends Entity { +class SimpleTestDenyUpdateEntity extends Entity { static defineCompanionDefinition(): EntityCompanionDefinition< TestEntityFields, string, - TestViewerContext, + ViewerContext, SimpleTestDenyUpdateEntity, SimpleTestDenyUpdateEntityPrivacyPolicy > { @@ -233,11 +217,11 @@ class SimpleTestDenyUpdateEntity extends Entity { +class SimpleTestDenyDeleteEntity extends Entity { static defineCompanionDefinition(): EntityCompanionDefinition< TestEntityFields, string, - TestViewerContext, + ViewerContext, SimpleTestDenyDeleteEntity, SimpleTestDenyDeleteEntityPrivacyPolicy > { diff --git a/packages/entity/src/__tests__/EntityAssociationLoader-test.ts b/packages/entity/src/__tests__/EntityAssociationLoader-test.ts index aa44680b..f54b1df2 100644 --- a/packages/entity/src/__tests__/EntityAssociationLoader-test.ts +++ b/packages/entity/src/__tests__/EntityAssociationLoader-test.ts @@ -14,24 +14,20 @@ describe(EntityAssociationLoader, () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); const testOtherEntity = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()).createAsync() + TestEntity.creator(viewerContext).createAsync() ); const testEntity = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()) + TestEntity.creator(viewerContext) .setField('stringField', testOtherEntity.getID()) .createAsync() ); const loadedOther = await enforceAsyncResult( - testEntity - .associationLoader() - .loadAssociatedEntityAsync('stringField', TestEntity, viewerContext.getQueryContext()) + testEntity.associationLoader().loadAssociatedEntityAsync('stringField', TestEntity) ); expect(loadedOther.getID()).toEqual(testOtherEntity.getID()); const loadedOther2 = await enforceAsyncResult( - testEntity - .associationLoader() - .loadAssociatedEntityAsync('nullableField', TestEntity, viewerContext.getQueryContext()) + testEntity.associationLoader().loadAssociatedEntityAsync('nullableField', TestEntity) ); expect(loadedOther2).toBeNull(); }); @@ -41,27 +37,15 @@ describe(EntityAssociationLoader, () => { it('loads many associated entities referencing this entity', async () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const testEntity = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()).createAsync() - ); + const testEntity = await enforceAsyncResult(TestEntity.creator(viewerContext).createAsync()); const testOtherEntity1 = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()) - .setField('stringField', testEntity.getID()) - .createAsync() + TestEntity.creator(viewerContext).setField('stringField', testEntity.getID()).createAsync() ); const testOtherEntity2 = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()) - .setField('stringField', testEntity.getID()) - .createAsync() + TestEntity.creator(viewerContext).setField('stringField', testEntity.getID()).createAsync() ); const loaded = await enforceResultsAsync( - testEntity - .associationLoader() - .loadManyAssociatedEntitiesAsync( - TestEntity, - 'stringField', - viewerContext.getQueryContext() - ) + testEntity.associationLoader().loadManyAssociatedEntitiesAsync(TestEntity, 'stringField') ); expect(loaded).toHaveLength(2); expect(loaded.find((e) => e.getID() === testOtherEntity1.getID())).not.toBeUndefined(); @@ -74,21 +58,16 @@ describe(EntityAssociationLoader, () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); const testOtherEntity = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()).createAsync() + TestEntity.creator(viewerContext).createAsync() ); const testEntity = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()) + TestEntity.creator(viewerContext) .setField('stringField', testOtherEntity.getID()) .createAsync() ); const loadedOtherResult = await testEntity .associationLoader() - .loadAssociatedEntityByFieldEqualingAsync( - 'stringField', - TestEntity, - 'customIdField', - viewerContext.getQueryContext() - ); + .loadAssociatedEntityByFieldEqualingAsync('stringField', TestEntity, 'customIdField'); expect(loadedOtherResult?.enforceValue().getID()).toEqual(testOtherEntity.getID()); }); @@ -96,18 +75,11 @@ describe(EntityAssociationLoader, () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); const testEntity = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()) - .setField('stringField', uuidv4()) - .createAsync() + TestEntity.creator(viewerContext).setField('stringField', uuidv4()).createAsync() ); const loadedOtherResult = await testEntity .associationLoader() - .loadAssociatedEntityByFieldEqualingAsync( - 'stringField', - TestEntity, - 'customIdField', - viewerContext.getQueryContext() - ); + .loadAssociatedEntityByFieldEqualingAsync('stringField', TestEntity, 'customIdField'); expect(loadedOtherResult).toBeNull(); }); @@ -115,18 +87,11 @@ describe(EntityAssociationLoader, () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); const testEntity = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()) - .setField('stringField', 'blah') - .createAsync() + TestEntity.creator(viewerContext).setField('stringField', 'blah').createAsync() ); const loadedOtherResult = await testEntity .associationLoader() - .loadAssociatedEntityByFieldEqualingAsync( - 'nullableField', - TestEntity, - 'customIdField', - viewerContext.getQueryContext() - ); + .loadAssociatedEntityByFieldEqualingAsync('nullableField', TestEntity, 'customIdField'); expect(loadedOtherResult).toBeNull(); }); }); @@ -135,18 +100,12 @@ describe(EntityAssociationLoader, () => { it('loads many associated entities by field equaling', async () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const testEntity = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()).createAsync() - ); + const testEntity = await enforceAsyncResult(TestEntity.creator(viewerContext).createAsync()); const testOtherEntity1 = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()) - .setField('stringField', testEntity.getID()) - .createAsync() + TestEntity.creator(viewerContext).setField('stringField', testEntity.getID()).createAsync() ); const testOtherEntity2 = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()) - .setField('stringField', testEntity.getID()) - .createAsync() + TestEntity.creator(viewerContext).setField('stringField', testEntity.getID()).createAsync() ); const loaded = await enforceResultsAsync( testEntity @@ -154,8 +113,7 @@ describe(EntityAssociationLoader, () => { .loadManyAssociatedEntitiesByFieldEqualingAsync( 'customIdField', TestEntity, - 'stringField', - viewerContext.getQueryContext() + 'stringField' ) ); expect(loaded).toHaveLength(2); @@ -166,17 +124,14 @@ describe(EntityAssociationLoader, () => { it('returns empty results when field being queried by is null', async () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const testEntity = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()).createAsync() - ); + const testEntity = await enforceAsyncResult(TestEntity.creator(viewerContext).createAsync()); const loaded = await enforceResultsAsync( testEntity .associationLoader() .loadManyAssociatedEntitiesByFieldEqualingAsync( 'nullableField', TestEntity, - 'stringField', - viewerContext.getQueryContext() + 'stringField' ) ); expect(loaded).toHaveLength(0); @@ -187,68 +142,53 @@ describe(EntityAssociationLoader, () => { it('chain loads associated entities', async () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const testEntity4 = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()).createAsync() - ); + const testEntity4 = await enforceAsyncResult(TestEntity.creator(viewerContext).createAsync()); const testEntity3 = await enforceAsyncResult( - TestEntity2.creator(viewerContext, viewerContext.getQueryContext()) - .setField('foreignKey', testEntity4.getID()) - .createAsync() + TestEntity2.creator(viewerContext).setField('foreignKey', testEntity4.getID()).createAsync() ); const testEntity2 = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()) + TestEntity.creator(viewerContext) .setField('testIndexedField', testEntity3.getID()) .createAsync() ); const testEntity = await enforceAsyncResult( - TestEntity2.creator(viewerContext, viewerContext.getQueryContext()) - .setField('foreignKey', testEntity2.getID()) - .createAsync() + TestEntity2.creator(viewerContext).setField('foreignKey', testEntity2.getID()).createAsync() ); - const loaded2Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync( - [ - { - associatedEntityClass: TestEntity, - fieldIdentifyingAssociatedEntity: 'foreignKey', - }, - ], - viewerContext.getQueryContext() - ); + const loaded2Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([ + { + associatedEntityClass: TestEntity, + fieldIdentifyingAssociatedEntity: 'foreignKey', + }, + ]); expect(loaded2Result?.enforceValue().getID()).toEqual(testEntity2.getID()); - const loaded3Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync( - [ - { - associatedEntityClass: TestEntity, - fieldIdentifyingAssociatedEntity: 'foreignKey', - }, - { - associatedEntityClass: TestEntity2, - fieldIdentifyingAssociatedEntity: 'testIndexedField', - }, - ], - viewerContext.getQueryContext() - ); + const loaded3Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([ + { + associatedEntityClass: TestEntity, + fieldIdentifyingAssociatedEntity: 'foreignKey', + }, + { + associatedEntityClass: TestEntity2, + fieldIdentifyingAssociatedEntity: 'testIndexedField', + }, + ]); expect(loaded3Result?.enforceValue().getID()).toEqual(testEntity3.getID()); - const loaded4Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync( - [ - { - associatedEntityClass: TestEntity, - fieldIdentifyingAssociatedEntity: 'foreignKey', - }, - { - associatedEntityClass: TestEntity2, - fieldIdentifyingAssociatedEntity: 'testIndexedField', - }, - { - associatedEntityClass: TestEntity, - fieldIdentifyingAssociatedEntity: 'foreignKey', - }, - ], - viewerContext.getQueryContext() - ); + const loaded4Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([ + { + associatedEntityClass: TestEntity, + fieldIdentifyingAssociatedEntity: 'foreignKey', + }, + { + associatedEntityClass: TestEntity2, + fieldIdentifyingAssociatedEntity: 'testIndexedField', + }, + { + associatedEntityClass: TestEntity, + fieldIdentifyingAssociatedEntity: 'foreignKey', + }, + ]); expect(loaded4Result?.enforceValue().getID()).toEqual(testEntity4.getID()); }); @@ -257,20 +197,15 @@ describe(EntityAssociationLoader, () => { const viewerContext = new TestViewerContext(companionProvider); const testEntity = await enforceAsyncResult( - TestEntity2.creator(viewerContext, viewerContext.getQueryContext()) - .setField('foreignKey', uuidv4()) - .createAsync() + TestEntity2.creator(viewerContext).setField('foreignKey', uuidv4()).createAsync() ); - const loadResult = await testEntity.associationLoader().loadAssociatedEntityThroughAsync( - [ - { - associatedEntityClass: TestEntity, - fieldIdentifyingAssociatedEntity: 'foreignKey', - }, - ], - viewerContext.getQueryContext() - ); + const loadResult = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([ + { + associatedEntityClass: TestEntity, + fieldIdentifyingAssociatedEntity: 'foreignKey', + }, + ]); expect(loadResult?.ok).toBe(false); }); @@ -280,26 +215,19 @@ describe(EntityAssociationLoader, () => { const fieldValue = uuidv4(); const testEntity2 = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()) - .setField('stringField', fieldValue) - .createAsync() + TestEntity.creator(viewerContext).setField('stringField', fieldValue).createAsync() ); const testEntity = await enforceAsyncResult( - TestEntity2.creator(viewerContext, viewerContext.getQueryContext()) - .setField('foreignKey', fieldValue) - .createAsync() + TestEntity2.creator(viewerContext).setField('foreignKey', fieldValue).createAsync() ); - const loaded2Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync( - [ - { - associatedEntityClass: TestEntity, - fieldIdentifyingAssociatedEntity: 'foreignKey', - associatedEntityLookupByField: 'stringField', - }, - ], - viewerContext.getQueryContext() - ); + const loaded2Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([ + { + associatedEntityClass: TestEntity, + fieldIdentifyingAssociatedEntity: 'foreignKey', + associatedEntityLookupByField: 'stringField', + }, + ]); expect(loaded2Result?.enforceValue().getID()).toEqual(testEntity2.getID()); }); @@ -308,21 +236,16 @@ describe(EntityAssociationLoader, () => { const viewerContext = new TestViewerContext(companionProvider); const testEntity = await enforceAsyncResult( - TestEntity2.creator(viewerContext, viewerContext.getQueryContext()) - .setField('foreignKey', uuidv4()) - .createAsync() + TestEntity2.creator(viewerContext).setField('foreignKey', uuidv4()).createAsync() ); - const loaded2Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync( - [ - { - associatedEntityClass: TestEntity, - fieldIdentifyingAssociatedEntity: 'foreignKey', - associatedEntityLookupByField: 'stringField', - }, - ], - viewerContext.getQueryContext() - ); + const loaded2Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([ + { + associatedEntityClass: TestEntity, + fieldIdentifyingAssociatedEntity: 'foreignKey', + associatedEntityLookupByField: 'stringField', + }, + ]); expect(loaded2Result).toBeNull(); }); @@ -331,20 +254,15 @@ describe(EntityAssociationLoader, () => { const viewerContext = new TestViewerContext(companionProvider); const testEntity = await enforceAsyncResult( - TestEntity.creator(viewerContext, viewerContext.getQueryContext()) - .setField('nullableField', null) - .createAsync() + TestEntity.creator(viewerContext).setField('nullableField', null).createAsync() ); - const loadedResult = await testEntity.associationLoader().loadAssociatedEntityThroughAsync( - [ - { - associatedEntityClass: TestEntity, - fieldIdentifyingAssociatedEntity: 'nullableField', - }, - ], - viewerContext.getQueryContext() - ); + const loadedResult = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([ + { + associatedEntityClass: TestEntity, + fieldIdentifyingAssociatedEntity: 'nullableField', + }, + ]); expect(loadedResult).toBeNull(); }); }); diff --git a/packages/entity/src/__tests__/EntityCommonUseCases-test.ts b/packages/entity/src/__tests__/EntityCommonUseCases-test.ts index a7be860c..2f82ca41 100644 --- a/packages/entity/src/__tests__/EntityCommonUseCases-test.ts +++ b/packages/entity/src/__tests__/EntityCommonUseCases-test.ts @@ -7,15 +7,15 @@ import EntityConfiguration from '../EntityConfiguration'; import { UUIDField } from '../EntityFields'; import EntityPrivacyPolicy, { EntityPrivacyPolicyEvaluationContext } from '../EntityPrivacyPolicy'; import { EntityQueryContext } from '../EntityQueryContext'; +import ViewerContext from '../ViewerContext'; import { enforceResultsAsync } from '../entityUtils'; import EntityNotAuthorizedError from '../errors/EntityNotAuthorizedError'; import AlwaysAllowPrivacyPolicyRule from '../rules/AlwaysAllowPrivacyPolicyRule'; import AlwaysDenyPrivacyPolicyRule from '../rules/AlwaysDenyPrivacyPolicyRule'; import PrivacyPolicyRule, { RuleEvaluationResult } from '../rules/PrivacyPolicyRule'; -import TestViewerContext from '../testfixtures/TestViewerContext'; import { createUnitTestEntityCompanionProvider } from '../utils/testing/createUnitTestEntityCompanionProvider'; -class TestUserViewerContext extends TestViewerContext { +class TestUserViewerContext extends ViewerContext { constructor(entityCompanionProvider: EntityCompanionProvider, private readonly userID: string) { super(entityCompanionProvider); } @@ -82,23 +82,23 @@ class DenyIfNotOwnerPrivacyPolicyRule extends PrivacyPolicyRule< class BlahEntityPrivacyPolicy extends EntityPrivacyPolicy< BlahFields, string, - TestUserViewerContext, + ViewerContext, BlahEntity > { protected override readonly createRules = [ new DenyIfNotOwnerPrivacyPolicyRule(), - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly readRules = [ new DenyIfNotOwnerPrivacyPolicyRule(), - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly updateRules = [ new DenyIfNotOwnerPrivacyPolicyRule(), - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly deleteRules = [ - new AlwaysDenyPrivacyPolicyRule(), + new AlwaysDenyPrivacyPolicyRule(), ]; } @@ -110,21 +110,15 @@ it('runs through a common workflow', async () => { const vc2 = new TestUserViewerContext(entityCompanionProvider, uuidv4()); const blahOwner1 = await enforceAsyncResult( - BlahEntity.creator(vc1, vc1.getQueryContext()) - .setField('ownerID', vc1.getUserID()!) - .createAsync() + BlahEntity.creator(vc1).setField('ownerID', vc1.getUserID()!).createAsync() ); await enforceAsyncResult( - BlahEntity.creator(vc1, vc1.getQueryContext()) - .setField('ownerID', vc1.getUserID()!) - .createAsync() + BlahEntity.creator(vc1).setField('ownerID', vc1.getUserID()!).createAsync() ); const blahOwner2 = await enforceAsyncResult( - BlahEntity.creator(vc2, vc2.getQueryContext()) - .setField('ownerID', vc2.getUserID()!) - .createAsync() + BlahEntity.creator(vc2).setField('ownerID', vc2.getUserID()!).createAsync() ); // sanity check created objects @@ -133,45 +127,33 @@ it('runs through a common workflow', async () => { // check that two people can't read each others data await expect( - enforceAsyncResult( - BlahEntity.loader(vc1, vc1.getQueryContext()).loadByIDAsync(blahOwner2.getID()) - ) + enforceAsyncResult(BlahEntity.loader(vc1).loadByIDAsync(blahOwner2.getID())) ).rejects.toBeInstanceOf(EntityNotAuthorizedError); await expect( - enforceAsyncResult( - BlahEntity.loader(vc2, vc2.getQueryContext()).loadByIDAsync(blahOwner1.getID()) - ) + enforceAsyncResult(BlahEntity.loader(vc2).loadByIDAsync(blahOwner1.getID())) ).rejects.toBeInstanceOf(EntityNotAuthorizedError); // check that all of owner 1's objects can be loaded const results = await enforceResultsAsync( - BlahEntity.loader(vc1, vc1.getQueryContext()).loadManyByFieldEqualingAsync( - 'ownerID', - vc1.getUserID()! - ) + BlahEntity.loader(vc1).loadManyByFieldEqualingAsync('ownerID', vc1.getUserID()!) ); expect(results).toHaveLength(2); // check that two people can't create objects owned by others await expect( enforceAsyncResult( - BlahEntity.creator(vc2, vc2.getQueryContext()) - .setField('ownerID', blahOwner1.getID()) - .createAsync() + BlahEntity.creator(vc2).setField('ownerID', blahOwner1.getID()).createAsync() ) ).rejects.toBeInstanceOf(EntityNotAuthorizedError); // check that empty load many returns nothing - const results2 = await BlahEntity.loader( - vc1, - vc1.getQueryContext() - ).loadManyByFieldEqualingManyAsync('ownerID', []); + const results2 = await BlahEntity.loader(vc1).loadManyByFieldEqualingManyAsync('ownerID', []); for (const value in results2.values) { expect(value).toHaveLength(0); } // check that the user can't delete their own data (as specified by privacy rules) - await expect( - enforceAsyncResult(BlahEntity.deleteAsync(blahOwner2, vc1.getQueryContext())) - ).rejects.toBeInstanceOf(EntityNotAuthorizedError); + await expect(enforceAsyncResult(BlahEntity.deleteAsync(blahOwner2))).rejects.toBeInstanceOf( + EntityNotAuthorizedError + ); }); diff --git a/packages/entity/src/__tests__/EntityEdges-test.ts b/packages/entity/src/__tests__/EntityEdges-test.ts index d035a2e4..b0678bf8 100644 --- a/packages/entity/src/__tests__/EntityEdges-test.ts +++ b/packages/entity/src/__tests__/EntityEdges-test.ts @@ -469,54 +469,36 @@ describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const parent = await ParentEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ).enforceCreateAsync(); - const child = await ChildEntity.creator(viewerContext, viewerContext.getQueryContext()) + const parent = await ParentEntity.creator(viewerContext).enforceCreateAsync(); + const child = await ChildEntity.creator(viewerContext) .setField('parent_id', parent.getID()) .enforceCreateAsync(); - const grandchild = await GrandChildEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ) + const grandchild = await GrandChildEntity.creator(viewerContext) .setField('parent_id', child.getID()) .enforceCreateAsync(); await expect( - ParentEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parent.getID()) + ParentEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parent.getID()) ).resolves.not.toBeNull(); await expect( - ChildEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(child.getID()) + ChildEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(child.getID()) ).resolves.not.toBeNull(); await expect( - GrandChildEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(grandchild.getID()) + GrandChildEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(grandchild.getID()) ).resolves.not.toBeNull(); privacyPolicyEvaluationRecords.shouldRecord = true; - await ParentEntity.enforceDeleteAsync(parent, viewerContext.getQueryContext()); + await ParentEntity.enforceDeleteAsync(parent); privacyPolicyEvaluationRecords.shouldRecord = false; await expect( - ParentEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parent.getID()) + ParentEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parent.getID()) ).resolves.toBeNull(); await expect( - ChildEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(child.getID()) + ChildEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(child.getID()) ).resolves.toBeNull(); await expect( - GrandChildEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(grandchild.getID()) + GrandChildEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(grandchild.getID()) ).resolves.toBeNull(); // two calls for each trigger, one beforeDelete, one afterDelete @@ -605,55 +587,38 @@ describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const parent = await ParentEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ).enforceCreateAsync(); - const child = await ChildEntity.creator(viewerContext, viewerContext.getQueryContext()) + const parent = await ParentEntity.creator(viewerContext).enforceCreateAsync(); + const child = await ChildEntity.creator(viewerContext) .setField('parent_id', parent.getID()) .enforceCreateAsync(); - const grandchild = await GrandChildEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ) + const grandchild = await GrandChildEntity.creator(viewerContext) .setField('parent_id', child.getID()) .enforceCreateAsync(); await expect( - ParentEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parent.getID()) + ParentEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parent.getID()) ).resolves.not.toBeNull(); await expect( - ChildEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(child.getID()) + ChildEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(child.getID()) ).resolves.not.toBeNull(); await expect( - GrandChildEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(grandchild.getID()) + GrandChildEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(grandchild.getID()) ).resolves.not.toBeNull(); privacyPolicyEvaluationRecords.shouldRecord = true; - await ParentEntity.enforceDeleteAsync(parent, viewerContext.getQueryContext()); + await ParentEntity.enforceDeleteAsync(parent); privacyPolicyEvaluationRecords.shouldRecord = false; await expect( - ParentEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parent.getID()) + ParentEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parent.getID()) ).resolves.toBeNull(); - const loadedChild = await ChildEntity.loader(viewerContext, viewerContext.getQueryContext()) + const loadedChild = await ChildEntity.loader(viewerContext) .enforcing() .loadByIDAsync(child.getID()); expect(loadedChild.getField('parent_id')).toBeNull(); - const loadedGrandchild = await GrandChildEntity.loader( - viewerContext, - viewerContext.getQueryContext() - ) + const loadedGrandchild = await GrandChildEntity.loader(viewerContext) .enforcing() .loadByIDAsync(grandchild.getID()); expect(loadedGrandchild.getField('parent_id')).toEqual(loadedChild.getID()); @@ -733,32 +698,24 @@ describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const parent = await ParentEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ).enforceCreateAsync(); - const child = await ChildEntity.creator(viewerContext, viewerContext.getQueryContext()) + const parent = await ParentEntity.creator(viewerContext).enforceCreateAsync(); + const child = await ChildEntity.creator(viewerContext) .setField('parent_id', parent.getID()) .enforceCreateAsync(); - const grandchild = await GrandChildEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ) + const grandchild = await GrandChildEntity.creator(viewerContext) .setField('parent_id', child.getID()) .enforceCreateAsync(); await expect( - ParentEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parent.getID()) + ParentEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parent.getID()) ).resolves.not.toBeNull(); await expect( - ChildEntity.loader(viewerContext, viewerContext.getQueryContext()) + ChildEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('parent_id', parent.getID()) ).resolves.not.toBeNull(); await expect( - GrandChildEntity.loader(viewerContext, viewerContext.getQueryContext()) + GrandChildEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('parent_id', child.getID()) ).resolves.not.toBeNull(); @@ -782,7 +739,7 @@ describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => { expect(grandChildCachedBefore.get(child.getID())?.status).toEqual(CacheStatus.HIT); privacyPolicyEvaluationRecords.shouldRecord = true; - await ParentEntity.enforceDeleteAsync(parent, viewerContext.getQueryContext()); + await ParentEntity.enforceDeleteAsync(parent); privacyPolicyEvaluationRecords.shouldRecord = false; const childCachedAfter = await childCacheAdapter.loadManyAsync('parent_id', [parent.getID()]); @@ -794,20 +751,15 @@ describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => { expect(grandChildCachedAfter.get(child.getID())?.status).toEqual(CacheStatus.HIT); await expect( - ParentEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parent.getID()) + ParentEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parent.getID()) ).resolves.toBeNull(); - const loadedChild = await ChildEntity.loader(viewerContext, viewerContext.getQueryContext()) + const loadedChild = await ChildEntity.loader(viewerContext) .enforcing() .loadByIDAsync(child.getID()); expect(loadedChild).not.toBeNull(); - const loadedGrandchild = await GrandChildEntity.loader( - viewerContext, - viewerContext.getQueryContext() - ) + const loadedGrandchild = await GrandChildEntity.loader(viewerContext) .enforcing() .loadByIDAsync(grandchild.getID()); expect(loadedGrandchild.getField('parent_id')).toEqual(loadedChild.getID()); @@ -879,32 +831,24 @@ describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const parent = await ParentEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ).enforceCreateAsync(); - const child = await ChildEntity.creator(viewerContext, viewerContext.getQueryContext()) + const parent = await ParentEntity.creator(viewerContext).enforceCreateAsync(); + const child = await ChildEntity.creator(viewerContext) .setField('parent_id', parent.getID()) .enforceCreateAsync(); - const grandchild = await GrandChildEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ) + const grandchild = await GrandChildEntity.creator(viewerContext) .setField('parent_id', child.getID()) .enforceCreateAsync(); await expect( - ParentEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parent.getID()) + ParentEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parent.getID()) ).resolves.not.toBeNull(); await expect( - ChildEntity.loader(viewerContext, viewerContext.getQueryContext()) + ChildEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('parent_id', parent.getID()) ).resolves.not.toBeNull(); await expect( - GrandChildEntity.loader(viewerContext, viewerContext.getQueryContext()) + GrandChildEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('parent_id', child.getID()) ).resolves.not.toBeNull(); @@ -928,7 +872,7 @@ describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => { expect(grandChildCachedBefore.get(child.getID())?.status).toEqual(CacheStatus.HIT); privacyPolicyEvaluationRecords.shouldRecord = true; - await ParentEntity.enforceDeleteAsync(parent, viewerContext.getQueryContext()); + await ParentEntity.enforceDeleteAsync(parent); privacyPolicyEvaluationRecords.shouldRecord = false; const childCachedAfter = await childCacheAdapter.loadManyAsync('parent_id', [parent.getID()]); @@ -940,19 +884,13 @@ describe('EntityMutator.processEntityDeletionForInboundEdgesAsync', () => { expect(grandChildCachedAfter.get(child.getID())?.status).toEqual(CacheStatus.MISS); await expect( - ParentEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parent.getID()) + ParentEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parent.getID()) ).resolves.toBeNull(); await expect( - ChildEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(child.getID()) + ChildEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(child.getID()) ).resolves.not.toBeNull(); await expect( - GrandChildEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(grandchild.getID()) + GrandChildEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(grandchild.getID()) ).resolves.not.toBeNull(); // two calls for each trigger, one beforeDelete, one afterDelete diff --git a/packages/entity/src/__tests__/EntityLoader-constructor-test.ts b/packages/entity/src/__tests__/EntityLoader-constructor-test.ts index 0b026b85..ca100c31 100644 --- a/packages/entity/src/__tests__/EntityLoader-constructor-test.ts +++ b/packages/entity/src/__tests__/EntityLoader-constructor-test.ts @@ -123,7 +123,7 @@ describe(EntityLoader, () => { const viewerContext = instance(mock(ViewerContext)); const privacyPolicyEvaluationContext = instance(mock()); const metricsAdapter = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const databaseAdapter = new StubDatabaseAdapter( testEntityConfiguration, diff --git a/packages/entity/src/__tests__/EntityLoader-test.ts b/packages/entity/src/__tests__/EntityLoader-test.ts index 83cdb277..76c6a509 100644 --- a/packages/entity/src/__tests__/EntityLoader-test.ts +++ b/packages/entity/src/__tests__/EntityLoader-test.ts @@ -5,6 +5,7 @@ import { v4 as uuidv4 } from 'uuid'; import { OrderByOrdering } from '../EntityDatabaseAdapter'; import EntityLoader from '../EntityLoader'; import { EntityPrivacyPolicyEvaluationContext } from '../EntityPrivacyPolicy'; +import ViewerContext from '../ViewerContext'; import { enforceResultsAsync } from '../entityUtils'; import EntityDataManager from '../internal/EntityDataManager'; import ReadThroughEntityCache from '../internal/ReadThroughEntityCache'; @@ -14,7 +15,6 @@ import TestEntity, { TestEntityPrivacyPolicy, testEntityConfiguration, } from '../testfixtures/TestEntity'; -import TestViewerContext from '../testfixtures/TestViewerContext'; import { NoCacheStubCacheAdapterProvider } from '../utils/testing/StubCacheAdapter'; import StubDatabaseAdapter from '../utils/testing/StubDatabaseAdapter'; import StubQueryContextProvider from '../utils/testing/StubQueryContextProvider'; @@ -22,10 +22,10 @@ import StubQueryContextProvider from '../utils/testing/StubQueryContextProvider' describe(EntityLoader, () => { it('loads entities', async () => { const dateToInsert = new Date(); - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const privacyPolicyEvaluationContext = instance(mock()); const metricsAdapter = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const id2 = uuidv4(); @@ -117,10 +117,10 @@ describe(EntityLoader, () => { it('loads entities with loadManyByFieldEqualityConjunction', async () => { const privacyPolicy = new TestEntityPrivacyPolicy(); const spiedPrivacyPolicy = spy(privacyPolicy); - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const privacyPolicyEvaluationContext = instance(mock()); const metricsAdapter = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const id2 = uuidv4(); @@ -216,10 +216,10 @@ describe(EntityLoader, () => { it('loads entities with loadFirstByFieldEqualityConjunction', async () => { const privacyPolicy = new TestEntityPrivacyPolicy(); const spiedPrivacyPolicy = spy(privacyPolicy); - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const privacyPolicyEvaluationContext = instance(mock()); const metricsAdapter = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const id2 = uuidv4(); @@ -313,10 +313,10 @@ describe(EntityLoader, () => { const privacyPolicy = new TestEntityPrivacyPolicy(); const spiedPrivacyPolicy = spy(privacyPolicy); - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const privacyPolicyEvaluationContext = instance(mock()); const metricsAdapter = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const databaseAdapter = new StubDatabaseAdapter( @@ -374,10 +374,10 @@ describe(EntityLoader, () => { }); it('invalidates upon invalidate one', async () => { - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const privacyPolicyEvaluationContext = instance(mock()); const metricsAdapter = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const privacyPolicy = instance(mock(TestEntityPrivacyPolicy)); const dataManagerMock = mock>(); const dataManagerInstance = instance(dataManagerMock); @@ -402,10 +402,10 @@ describe(EntityLoader, () => { }); it('invalidates upon invalidate by field', async () => { - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const privacyPolicyEvaluationContext = instance(mock()); const metricsAdapter = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const privacyPolicy = instance(mock(TestEntityPrivacyPolicy)); const dataManagerMock = mock>(); const dataManagerInstance = instance(dataManagerMock); @@ -429,10 +429,10 @@ describe(EntityLoader, () => { }); it('invalidates upon invalidate by entity', async () => { - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const privacyPolicyEvaluationContext = instance(mock()); const metricsAdapter = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const privacyPolicy = instance(mock(TestEntityPrivacyPolicy)); const dataManagerMock = mock>(); const dataManagerInstance = instance(dataManagerMock); @@ -460,10 +460,10 @@ describe(EntityLoader, () => { }); it('returns error result when not allowed', async () => { - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const privacyPolicyEvaluationContext = instance(mock()); const metricsAdapter = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const privacyPolicyMock = mock(TestEntityPrivacyPolicy); const dataManagerMock = mock>(); @@ -506,10 +506,10 @@ describe(EntityLoader, () => { }); it('throws upon database adapter error', async () => { - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const privacyPolicyEvaluationContext = instance(mock()); const metricsAdapter = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const privacyPolicy = instance(mock(TestEntityPrivacyPolicy)); const dataManagerMock = mock>(); diff --git a/packages/entity/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts b/packages/entity/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts index d7c8a6ad..a5589628 100644 --- a/packages/entity/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts +++ b/packages/entity/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts @@ -5,8 +5,8 @@ import { UUIDField } from '../EntityFields'; import { EntityMutationType, EntityTriggerMutationInfo } from '../EntityMutationInfo'; import { EntityNonTransactionalMutationTrigger } from '../EntityMutationTriggerConfiguration'; import EntityPrivacyPolicy from '../EntityPrivacyPolicy'; +import ViewerContext from '../ViewerContext'; import AlwaysAllowPrivacyPolicyRule from '../rules/AlwaysAllowPrivacyPolicyRule'; -import TestViewerContext from '../testfixtures/TestViewerContext'; import { createUnitTestEntityCompanionProvider } from '../utils/testing/createUnitTestEntityCompanionProvider'; type BlahFields = { @@ -16,28 +16,28 @@ type BlahFields = { class BlahEntityPrivacyPolicy extends EntityPrivacyPolicy< BlahFields, string, - TestViewerContext, + ViewerContext, BlahEntity > { protected override readonly createRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly readRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly updateRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly deleteRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; } -class BlahEntity extends Entity { +class BlahEntity extends Entity { static defineCompanionDefinition(): EntityCompanionDefinition< BlahFields, string, - TestViewerContext, + ViewerContext, BlahEntity, BlahEntityPrivacyPolicy > { @@ -66,16 +66,16 @@ class BlahEntity extends Entity { class TestNonTransactionalMutationTrigger extends EntityNonTransactionalMutationTrigger< BlahFields, string, - TestViewerContext, + ViewerContext, BlahEntity > { async executeAsync( - viewerContext: TestViewerContext, + viewerContext: ViewerContext, entity: BlahEntity, - mutationInfo: EntityTriggerMutationInfo + mutationInfo: EntityTriggerMutationInfo ): Promise { if (mutationInfo.type === EntityMutationType.DELETE) { - const entityLoaded = await BlahEntity.loader(viewerContext, viewerContext.getQueryContext()) + const entityLoaded = await BlahEntity.loader(viewerContext) .enforcing() .loadByIDNullableAsync(entity.getID()); if (entityLoaded) { @@ -90,17 +90,14 @@ class TestNonTransactionalMutationTrigger extends EntityNonTransactionalMutation describe('EntityMutator', () => { test('cache consistency with post-commit callbacks', async () => { const companionProvider = createUnitTestEntityCompanionProvider(); - const viewerContext = new TestViewerContext(companionProvider); + const viewerContext = new ViewerContext(companionProvider); // put it in cache - const entity = await BlahEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ).enforceCreateAsync(); - const entityLoaded = await BlahEntity.loader(viewerContext, viewerContext.getQueryContext()) + const entity = await BlahEntity.creator(viewerContext).enforceCreateAsync(); + const entityLoaded = await BlahEntity.loader(viewerContext) .enforcing() .loadByIDAsync(entity.getID()); - await BlahEntity.enforceDeleteAsync(entityLoaded, viewerContext.getQueryContext()); + await BlahEntity.enforceDeleteAsync(entityLoaded); }); }); diff --git a/packages/entity/src/__tests__/EntityMutator-test.ts b/packages/entity/src/__tests__/EntityMutator-test.ts index 9ecb94db..a6b56396 100644 --- a/packages/entity/src/__tests__/EntityMutator-test.ts +++ b/packages/entity/src/__tests__/EntityMutator-test.ts @@ -31,6 +31,7 @@ import EntityMutatorFactory from '../EntityMutatorFactory'; import { EntityPrivacyPolicyEvaluationContext } from '../EntityPrivacyPolicy'; import { EntityTransactionalQueryContext, EntityQueryContext } from '../EntityQueryContext'; import IEntityDatabaseAdapterProvider from '../IEntityDatabaseAdapterProvider'; +import ViewerContext from '../ViewerContext'; import { enforceResultsAsync } from '../entityUtils'; import EntityDataManager from '../internal/EntityDataManager'; import ReadThroughEntityCache from '../internal/ReadThroughEntityCache'; @@ -46,7 +47,6 @@ import TestEntity, { TestEntityPrivacyPolicy, testEntityConfiguration, } from '../testfixtures/TestEntity'; -import TestViewerContext from '../testfixtures/TestViewerContext'; import { NoCacheStubCacheAdapterProvider } from '../utils/testing/StubCacheAdapter'; import StubDatabaseAdapter from '../utils/testing/StubDatabaseAdapter'; import StubQueryContextProvider from '../utils/testing/StubQueryContextProvider'; @@ -54,18 +54,18 @@ import StubQueryContextProvider from '../utils/testing/StubQueryContextProvider' class TestMutationTrigger extends EntityMutationTrigger< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields > { async executeAsync( - _viewerContext: TestViewerContext, + _viewerContext: ViewerContext, _queryContext: EntityQueryContext, _entity: TestEntity, _mutationInfo: EntityTriggerMutationInfo< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields > @@ -75,37 +75,31 @@ class TestMutationTrigger extends EntityMutationTrigger< class TestNonTransactionalMutationTrigger extends EntityNonTransactionalMutationTrigger< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields > { - async executeAsync(_viewerContext: TestViewerContext, _entity: TestEntity): Promise {} + async executeAsync(_viewerContext: ViewerContext, _entity: TestEntity): Promise {} } const setUpMutationValidatorSpies = ( mutationValidators: EntityMutationValidator< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields >[] -): EntityMutationValidator< - TestFields, - string, - TestViewerContext, - TestEntity, - keyof TestFields ->[] => { +): EntityMutationValidator[] => { return mutationValidators.map((validator) => spy(validator)); }; const verifyValidatorCounts = ( - viewerContext: TestViewerContext, + viewerContext: ViewerContext, mutationValidatorSpies: EntityMutationValidator< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields >[], @@ -113,7 +107,7 @@ const verifyValidatorCounts = ( mutationInfo: EntityValidatorMutationInfo< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields > @@ -134,14 +128,14 @@ const setUpMutationTriggerSpies = ( mutationTriggers: EntityMutationTriggerConfiguration< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields > ): EntityMutationTriggerConfiguration< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields > => { @@ -159,11 +153,11 @@ const setUpMutationTriggerSpies = ( }; const verifyTriggerCounts = ( - viewerContext: TestViewerContext, + viewerContext: ViewerContext, mutationTriggerSpies: EntityMutationTriggerConfiguration< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields >, @@ -172,7 +166,7 @@ const verifyTriggerCounts = ( EntityMutationTriggerConfiguration< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields >, @@ -188,7 +182,7 @@ const verifyTriggerCounts = ( mutationInfo: EntityTriggerMutationInfo< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields > @@ -249,7 +243,7 @@ const createEntityMutatorFactory = ( entityLoaderFactory: EntityLoaderFactory< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, TestEntityPrivacyPolicy, keyof TestFields @@ -257,7 +251,7 @@ const createEntityMutatorFactory = ( entityMutatorFactory: EntityMutatorFactory< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, TestEntityPrivacyPolicy >; @@ -265,14 +259,14 @@ const createEntityMutatorFactory = ( mutationValidators: EntityMutationValidator< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields >[]; mutationTriggers: EntityMutationTriggerConfiguration< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields >; @@ -280,14 +274,14 @@ const createEntityMutatorFactory = ( const mutationValidators: EntityMutationValidator< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields >[] = [new TestMutationTrigger()]; const mutationTriggers: EntityMutationTriggerConfiguration< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, keyof TestFields > = { @@ -378,8 +372,8 @@ const createEntityMutatorFactory = ( describe(EntityMutatorFactory, () => { describe('forCreate', () => { it('creates entities', async () => { - const viewerContext = mock(); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const viewerContext = mock(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const id2 = uuidv4(); @@ -409,8 +403,8 @@ describe(EntityMutatorFactory, () => { }); it('checks privacy', async () => { - const viewerContext = mock(); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const viewerContext = mock(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const id2 = uuidv4(); @@ -452,8 +446,8 @@ describe(EntityMutatorFactory, () => { }); it('executes triggers', async () => { - const viewerContext = mock(); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const viewerContext = mock(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const id2 = uuidv4(); @@ -499,8 +493,8 @@ describe(EntityMutatorFactory, () => { }); it('executes validators', async () => { - const viewerContext = mock(); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const viewerContext = mock(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const id2 = uuidv4(); @@ -536,9 +530,9 @@ describe(EntityMutatorFactory, () => { describe('forUpdate', () => { it('updates entities', async () => { - const viewerContext = mock(); + const viewerContext = mock(); const privacyPolicyEvaluationContext = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const id2 = uuidv4(); @@ -585,9 +579,9 @@ describe(EntityMutatorFactory, () => { }); it('checks privacy', async () => { - const viewerContext = mock(); + const viewerContext = mock(); const privacyPolicyEvaluationContext = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const id2 = uuidv4(); @@ -636,9 +630,9 @@ describe(EntityMutatorFactory, () => { }); it('executes triggers', async () => { - const viewerContext = mock(); + const viewerContext = mock(); const privacyPolicyEvaluationContext = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const id2 = uuidv4(); @@ -694,9 +688,9 @@ describe(EntityMutatorFactory, () => { ); }); it('executes validators', async () => { - const viewerContext = mock(); + const viewerContext = mock(); const privacyPolicyEvaluationContext = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const id2 = uuidv4(); @@ -743,9 +737,9 @@ describe(EntityMutatorFactory, () => { describe('forDelete', () => { it('deletes entities', async () => { - const viewerContext = mock(); + const viewerContext = mock(); const privacyPolicyEvaluationContext = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const { entityMutatorFactory, entityLoaderFactory } = createEntityMutatorFactory([ @@ -778,9 +772,9 @@ describe(EntityMutatorFactory, () => { }); it('checks privacy', async () => { - const viewerContext = mock(); + const viewerContext = mock(); const privacyPolicyEvaluationContext = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const { privacyPolicy, entityMutatorFactory, entityLoaderFactory } = @@ -817,9 +811,9 @@ describe(EntityMutatorFactory, () => { }); it('executes triggers', async () => { - const viewerContext = mock(); + const viewerContext = mock(); const privacyPolicyEvaluationContext = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const { mutationTriggers, entityMutatorFactory, entityLoaderFactory } = @@ -860,9 +854,9 @@ describe(EntityMutatorFactory, () => { }); it('does not execute validators', async () => { - const viewerContext = mock(); + const viewerContext = mock(); const privacyPolicyEvaluationContext = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const { mutationValidators, entityMutatorFactory, entityLoaderFactory } = @@ -894,9 +888,9 @@ describe(EntityMutatorFactory, () => { }); it('invalidates cache for fields upon create', async () => { - const viewerContext = mock(); + const viewerContext = mock(); const privacyPolicyEvaluationContext = instance(mock()); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const { entityMutatorFactory, entityLoaderFactory } = createEntityMutatorFactory([ @@ -933,8 +927,8 @@ describe(EntityMutatorFactory, () => { }); it('throws error when field not valid', async () => { - const viewerContext = mock(); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const viewerContext = mock(); + const queryContext = StubQueryContextProvider.getQueryContext(); const id1 = uuidv4(); const { entityMutatorFactory } = createEntityMutatorFactory([ { @@ -969,8 +963,8 @@ describe(EntityMutatorFactory, () => { it('returns error result when not authorized to create', async () => { const entityCompanionProvider = instance(mock(EntityCompanionProvider)); - const viewerContext = instance(mock(TestViewerContext)); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const viewerContext = instance(mock(ViewerContext)); + const queryContext = StubQueryContextProvider.getQueryContext(); const privacyPolicyMock = mock(SimpleTestEntityPrivacyPolicy); const databaseAdapter = instance(mock>()); const metricsAdapter = instance(mock()); @@ -992,7 +986,7 @@ describe(EntityMutatorFactory, () => { EntityLoader< SimpleTestFields, string, - TestViewerContext, + ViewerContext, SimpleTestEntity, SimpleTestEntityPrivacyPolicy, keyof SimpleTestFields @@ -1006,7 +1000,7 @@ describe(EntityMutatorFactory, () => { EntityLoaderFactory< SimpleTestFields, string, - TestViewerContext, + ViewerContext, SimpleTestEntity, SimpleTestEntityPrivacyPolicy, keyof SimpleTestFields @@ -1093,8 +1087,8 @@ describe(EntityMutatorFactory, () => { const entityCompanionProvider = instance(entityCompanionProviderMock); - const viewerContext = instance(mock(TestViewerContext)); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const viewerContext = instance(mock(ViewerContext)); + const queryContext = StubQueryContextProvider.getQueryContext(); const privacyPolicy = instance(mock(SimpleTestEntityPrivacyPolicy)); const databaseAdapterMock = mock>(); const metricsAdapter = instance(mock()); @@ -1116,7 +1110,7 @@ describe(EntityMutatorFactory, () => { EntityLoader< SimpleTestFields, string, - TestViewerContext, + ViewerContext, SimpleTestEntity, SimpleTestEntityPrivacyPolicy, keyof SimpleTestFields @@ -1130,7 +1124,7 @@ describe(EntityMutatorFactory, () => { EntityLoaderFactory< SimpleTestFields, string, - TestViewerContext, + ViewerContext, SimpleTestEntity, SimpleTestEntityPrivacyPolicy, keyof SimpleTestFields @@ -1190,8 +1184,8 @@ describe(EntityMutatorFactory, () => { }); it('records metrics appropriately', async () => { - const viewerContext = mock(); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const viewerContext = mock(); + const queryContext = StubQueryContextProvider.getQueryContext(); const { entityMutatorFactory, metricsAdapter } = createEntityMutatorFactory([]); const spiedMetricsAdapter = spy(metricsAdapter); diff --git a/packages/entity/src/__tests__/EntitySecondaryCacheLoader-test.ts b/packages/entity/src/__tests__/EntitySecondaryCacheLoader-test.ts index ac79b85c..99797ef2 100644 --- a/packages/entity/src/__tests__/EntitySecondaryCacheLoader-test.ts +++ b/packages/entity/src/__tests__/EntitySecondaryCacheLoader-test.ts @@ -2,11 +2,11 @@ import { anyOfClass, anything, deepEqual, instance, mock, spy, verify, when } fr import { EntityNonTransactionalQueryContext } from '../EntityQueryContext'; import EntitySecondaryCacheLoader, { ISecondaryEntityCache } from '../EntitySecondaryCacheLoader'; +import ViewerContext from '../ViewerContext'; import SimpleTestEntity, { SimpleTestEntityPrivacyPolicy, SimpleTestFields, } from '../testfixtures/SimpleTestEntity'; -import TestViewerContext from '../testfixtures/TestViewerContext'; import { createUnitTestEntityCompanionProvider } from '../utils/testing/createUnitTestEntityCompanionProvider'; type TestLoadParams = { id: string }; @@ -15,7 +15,7 @@ class TestSecondaryRedisCacheLoader extends EntitySecondaryCacheLoader< TestLoadParams, SimpleTestFields, string, - TestViewerContext, + ViewerContext, SimpleTestEntity, SimpleTestEntityPrivacyPolicy > { @@ -30,12 +30,9 @@ class TestSecondaryRedisCacheLoader extends EntitySecondaryCacheLoader< describe(EntitySecondaryCacheLoader, () => { describe('loadManyAsync', () => { it('calls into secondary cache with correct params', async () => { - const vc1 = new TestViewerContext(createUnitTestEntityCompanionProvider()); + const vc1 = new ViewerContext(createUnitTestEntityCompanionProvider()); - const createdEntity = await SimpleTestEntity.creator( - vc1, - vc1.getQueryContext() - ).enforceCreateAsync(); + const createdEntity = await SimpleTestEntity.creator(vc1).enforceCreateAsync(); const loadParams = { id: createdEntity.getID() }; const secondaryEntityCacheMock = @@ -47,7 +44,7 @@ describe(EntitySecondaryCacheLoader, () => { const secondaryCacheLoader = new TestSecondaryRedisCacheLoader( secondaryEntityCache, - SimpleTestEntity.loader(vc1, vc1.getQueryContext()) + SimpleTestEntity.loader(vc1) ); await secondaryCacheLoader.loadManyAsync([loadParams]); @@ -58,12 +55,9 @@ describe(EntitySecondaryCacheLoader, () => { }); it('constructs and authorizes entities', async () => { - const vc1 = new TestViewerContext(createUnitTestEntityCompanionProvider()); + const vc1 = new ViewerContext(createUnitTestEntityCompanionProvider()); - const createdEntity = await SimpleTestEntity.creator( - vc1, - vc1.getQueryContext() - ).enforceCreateAsync(); + const createdEntity = await SimpleTestEntity.creator(vc1).enforceCreateAsync(); const loadParams = { id: createdEntity.getID() }; const secondaryEntityCacheMock = @@ -73,7 +67,7 @@ describe(EntitySecondaryCacheLoader, () => { ).thenResolve(new Map([[loadParams, createdEntity.getAllFields()]])); const secondaryEntityCache = instance(secondaryEntityCacheMock); - const loader = SimpleTestEntity.loader(vc1, vc1.getQueryContext()); + const loader = SimpleTestEntity.loader(vc1); const spiedPrivacyPolicy = spy(loader['privacyPolicy']); const secondaryCacheLoader = new TestSecondaryRedisCacheLoader(secondaryEntityCache, loader); @@ -94,18 +88,15 @@ describe(EntitySecondaryCacheLoader, () => { describe('invalidateManyAsync', () => { it('calls invalidate on the secondary cache', async () => { - const vc1 = new TestViewerContext(createUnitTestEntityCompanionProvider()); + const vc1 = new ViewerContext(createUnitTestEntityCompanionProvider()); - const createdEntity = await SimpleTestEntity.creator( - vc1, - vc1.getQueryContext() - ).enforceCreateAsync(); + const createdEntity = await SimpleTestEntity.creator(vc1).enforceCreateAsync(); const loadParams = { id: createdEntity.getID() }; const secondaryEntityCacheMock = mock>(); const secondaryEntityCache = instance(secondaryEntityCacheMock); - const loader = SimpleTestEntity.loader(vc1, vc1.getQueryContext()); + const loader = SimpleTestEntity.loader(vc1); const secondaryCacheLoader = new TestSecondaryRedisCacheLoader(secondaryEntityCache, loader); await secondaryCacheLoader.invalidateManyAsync([loadParams]); diff --git a/packages/entity/src/__tests__/EntitySelfReferentialEdges-test.ts b/packages/entity/src/__tests__/EntitySelfReferentialEdges-test.ts index f46fe75a..8ce828de 100644 --- a/packages/entity/src/__tests__/EntitySelfReferentialEdges-test.ts +++ b/packages/entity/src/__tests__/EntitySelfReferentialEdges-test.ts @@ -87,52 +87,34 @@ describe('EntityEdgeDeletionBehavior.CASCADE_DELETE', () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const parentCategory = await CategoryEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ).enforceCreateAsync(); - const subCategory = await CategoryEntity.creator(viewerContext, viewerContext.getQueryContext()) + const parentCategory = await CategoryEntity.creator(viewerContext).enforceCreateAsync(); + const subCategory = await CategoryEntity.creator(viewerContext) .setField('parent_category_id', parentCategory.getID()) .enforceCreateAsync(); - const subSubCategory = await CategoryEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ) + const subSubCategory = await CategoryEntity.creator(viewerContext) .setField('parent_category_id', subCategory.getID()) .enforceCreateAsync(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parentCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parentCategory.getID()) ).resolves.not.toBeNull(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(subCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(subCategory.getID()) ).resolves.not.toBeNull(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(subSubCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(subSubCategory.getID()) ).resolves.not.toBeNull(); - await CategoryEntity.enforceDeleteAsync(parentCategory, viewerContext.getQueryContext()); + await CategoryEntity.enforceDeleteAsync(parentCategory); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parentCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parentCategory.getID()) ).resolves.toBeNull(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(subCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(subCategory.getID()) ).resolves.toBeNull(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(subSubCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(subSubCategory.getID()) ).resolves.toBeNull(); }); @@ -142,28 +124,21 @@ describe('EntityEdgeDeletionBehavior.CASCADE_DELETE', () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const categoryA = await CategoryEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ).enforceCreateAsync(); - const categoryB = await CategoryEntity.creator(viewerContext, viewerContext.getQueryContext()) + const categoryA = await CategoryEntity.creator(viewerContext).enforceCreateAsync(); + const categoryB = await CategoryEntity.creator(viewerContext) .setField('parent_category_id', categoryA.getID()) .enforceCreateAsync(); - await CategoryEntity.updater(categoryA, viewerContext.getQueryContext()) + await CategoryEntity.updater(categoryA) .setField('parent_category_id', categoryB.getID()) .enforceUpdateAsync(); - await CategoryEntity.enforceDeleteAsync(categoryA, viewerContext.getQueryContext()); + await CategoryEntity.enforceDeleteAsync(categoryA); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(categoryA.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(categoryA.getID()) ).resolves.toBeNull(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(categoryB.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(categoryB.getID()) ).resolves.toBeNull(); }); }); @@ -175,56 +150,36 @@ describe('EntityEdgeDeletionBehavior.SET_NULL', () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const parentCategory = await CategoryEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ).enforceCreateAsync(); - const subCategory = await CategoryEntity.creator(viewerContext, viewerContext.getQueryContext()) + const parentCategory = await CategoryEntity.creator(viewerContext).enforceCreateAsync(); + const subCategory = await CategoryEntity.creator(viewerContext) .setField('parent_category_id', parentCategory.getID()) .enforceCreateAsync(); - const subSubCategory = await CategoryEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ) + const subSubCategory = await CategoryEntity.creator(viewerContext) .setField('parent_category_id', subCategory.getID()) .enforceCreateAsync(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parentCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parentCategory.getID()) ).resolves.not.toBeNull(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(subCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(subCategory.getID()) ).resolves.not.toBeNull(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(subSubCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(subSubCategory.getID()) ).resolves.not.toBeNull(); - await CategoryEntity.enforceDeleteAsync(parentCategory, viewerContext.getQueryContext()); + await CategoryEntity.enforceDeleteAsync(parentCategory); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parentCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parentCategory.getID()) ).resolves.toBeNull(); - const loadedSubCategory = await CategoryEntity.loader( - viewerContext, - viewerContext.getQueryContext() - ) + const loadedSubCategory = await CategoryEntity.loader(viewerContext) .enforcing() .loadByIDAsync(subCategory.getID()); expect(loadedSubCategory.getField('parent_category_id')).toBeNull(); - const loadedSubSubCategory = await CategoryEntity.loader( - viewerContext, - viewerContext.getQueryContext() - ) + const loadedSubSubCategory = await CategoryEntity.loader(viewerContext) .enforcing() .loadByIDAsync(subSubCategory.getID()); expect(loadedSubSubCategory.getField('parent_category_id')).not.toBeNull(); @@ -236,23 +191,17 @@ describe('EntityEdgeDeletionBehavior.SET_NULL', () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const categoryA = await CategoryEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ).enforceCreateAsync(); - const categoryB = await CategoryEntity.creator(viewerContext, viewerContext.getQueryContext()) + const categoryA = await CategoryEntity.creator(viewerContext).enforceCreateAsync(); + const categoryB = await CategoryEntity.creator(viewerContext) .setField('parent_category_id', categoryA.getID()) .enforceCreateAsync(); - await CategoryEntity.updater(categoryA, viewerContext.getQueryContext()) + await CategoryEntity.updater(categoryA) .setField('parent_category_id', categoryB.getID()) .enforceUpdateAsync(); - await CategoryEntity.enforceDeleteAsync(categoryA, viewerContext.getQueryContext()); + await CategoryEntity.enforceDeleteAsync(categoryA); - const loadedCategoryB = await CategoryEntity.loader( - viewerContext, - viewerContext.getQueryContext() - ) + const loadedCategoryB = await CategoryEntity.loader(viewerContext) .enforcing() .loadByIDAsync(categoryB.getID()); expect(loadedCategoryB.getField('parent_category_id')).toBeNull(); @@ -268,32 +217,24 @@ describe('EntityEdgeDeletionBehavior.CASCADE_DELETE_INVALIDATE_CACHE', () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const parentCategory = await CategoryEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ).enforceCreateAsync(); - const subCategory = await CategoryEntity.creator(viewerContext, viewerContext.getQueryContext()) + const parentCategory = await CategoryEntity.creator(viewerContext).enforceCreateAsync(); + const subCategory = await CategoryEntity.creator(viewerContext) .setField('parent_category_id', parentCategory.getID()) .enforceCreateAsync(); - const subSubCategory = await CategoryEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ) + const subSubCategory = await CategoryEntity.creator(viewerContext) .setField('parent_category_id', subCategory.getID()) .enforceCreateAsync(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parentCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parentCategory.getID()) ).resolves.not.toBeNull(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) + CategoryEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('parent_category_id', parentCategory.getID()) ).resolves.not.toBeNull(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) + CategoryEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('parent_category_id', subCategory.getID()) ).resolves.not.toBeNull(); @@ -314,7 +255,7 @@ describe('EntityEdgeDeletionBehavior.CASCADE_DELETE_INVALIDATE_CACHE', () => { ); expect(subSubCategoryCachedBefore.get(subCategory.getID())?.status).toEqual(CacheStatus.HIT); - await CategoryEntity.enforceDeleteAsync(parentCategory, viewerContext.getQueryContext()); + await CategoryEntity.enforceDeleteAsync(parentCategory); const subCategoryCachedAfter = await categoryCacheAdapter.loadManyAsync('parent_category_id', [ parentCategory.getID(), @@ -328,19 +269,13 @@ describe('EntityEdgeDeletionBehavior.CASCADE_DELETE_INVALIDATE_CACHE', () => { expect(subSubCategoryCachedAfter.get(subCategory.getID())?.status).toEqual(CacheStatus.MISS); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(parentCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(parentCategory.getID()) ).resolves.toBeNull(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(subCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(subCategory.getID()) ).resolves.not.toBeNull(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDNullableAsync(subSubCategory.getID()) + CategoryEntity.loader(viewerContext).enforcing().loadByIDNullableAsync(subSubCategory.getID()) ).resolves.not.toBeNull(); }); @@ -352,24 +287,21 @@ describe('EntityEdgeDeletionBehavior.CASCADE_DELETE_INVALIDATE_CACHE', () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new TestViewerContext(companionProvider); - const categoryA = await CategoryEntity.creator( - viewerContext, - viewerContext.getQueryContext() - ).enforceCreateAsync(); - const categoryB = await CategoryEntity.creator(viewerContext, viewerContext.getQueryContext()) + const categoryA = await CategoryEntity.creator(viewerContext).enforceCreateAsync(); + const categoryB = await CategoryEntity.creator(viewerContext) .setField('parent_category_id', categoryA.getID()) .enforceCreateAsync(); - await CategoryEntity.updater(categoryA, viewerContext.getQueryContext()) + await CategoryEntity.updater(categoryA) .setField('parent_category_id', categoryB.getID()) .enforceUpdateAsync(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) + CategoryEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('parent_category_id', categoryA.getID()) ).resolves.not.toBeNull(); await expect( - CategoryEntity.loader(viewerContext, viewerContext.getQueryContext()) + CategoryEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('parent_category_id', categoryB.getID()) ).resolves.not.toBeNull(); @@ -386,7 +318,7 @@ describe('EntityEdgeDeletionBehavior.CASCADE_DELETE_INVALIDATE_CACHE', () => { expect(categoriesCachedBefore.get(categoryA.getID())?.status).toEqual(CacheStatus.HIT); expect(categoriesCachedBefore.get(categoryB.getID())?.status).toEqual(CacheStatus.HIT); - await CategoryEntity.enforceDeleteAsync(categoryA, viewerContext.getQueryContext()); + await CategoryEntity.enforceDeleteAsync(categoryA); const categoriesCachedAfter = await categoryCacheAdapter.loadManyAsync('parent_category_id', [ categoryA.getID(), diff --git a/packages/entity/src/__tests__/ReadonlyEntity-test.ts b/packages/entity/src/__tests__/ReadonlyEntity-test.ts index 7de094c3..bcfa1615 100644 --- a/packages/entity/src/__tests__/ReadonlyEntity-test.ts +++ b/packages/entity/src/__tests__/ReadonlyEntity-test.ts @@ -3,15 +3,15 @@ import { instance, mock } from 'ts-mockito'; import EntityAssociationLoader from '../EntityAssociationLoader'; import EntityLoader from '../EntityLoader'; import ReadonlyEntity from '../ReadonlyEntity'; +import ViewerContext from '../ViewerContext'; import SimpleTestEntity from '../testfixtures/SimpleTestEntity'; import TestEntity from '../testfixtures/TestEntity'; -import TestViewerContext from '../testfixtures/TestViewerContext'; import { createUnitTestEntityCompanionProvider } from '../utils/testing/createUnitTestEntityCompanionProvider'; describe(ReadonlyEntity, () => { describe('getID', () => { it('returns correct value', () => { - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const data = { id: 'what', }; @@ -27,7 +27,7 @@ describe(ReadonlyEntity, () => { describe('toString', () => { it('returns correct value', () => { - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const data = { id: 'what', }; @@ -43,7 +43,7 @@ describe(ReadonlyEntity, () => { describe('getUniqueIdentifier', () => { it('returns a different value for two different entities of the same type', () => { - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const testEntity = new SimpleTestEntity({ viewerContext, id: '1', @@ -68,8 +68,8 @@ describe(ReadonlyEntity, () => { }); it('returns the same value even if different viewer context', () => { - const viewerContext = instance(mock(TestViewerContext)); - const viewerContext2 = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); + const viewerContext2 = instance(mock(ViewerContext)); const data = { id: '1' }; const testEntity = new SimpleTestEntity({ viewerContext, @@ -87,7 +87,7 @@ describe(ReadonlyEntity, () => { }); it('returns a different value for different entities even if same ID', () => { - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const data = { id: '1' }; const testEntity = new SimpleTestEntity({ viewerContext, @@ -114,7 +114,7 @@ describe(ReadonlyEntity, () => { }); it('cannot be created without an ID', () => { - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const dataWithoutID = {}; expect(() => { // eslint-disable-next-line no-new @@ -128,7 +128,7 @@ describe(ReadonlyEntity, () => { }); it('returns correct viewerCo}ntext from instantiation', () => { - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const data = { id: 'what', }; @@ -142,7 +142,7 @@ describe(ReadonlyEntity, () => { }); it('returns correct data for field getters', () => { - const viewerContext = instance(mock(TestViewerContext)); + const viewerContext = instance(mock(ViewerContext)); const data = { id: 'what', }; @@ -159,7 +159,7 @@ describe(ReadonlyEntity, () => { describe('associationLoader', () => { it('returns a new association loader', () => { const companionProvider = createUnitTestEntityCompanionProvider(); - const viewerContext = new TestViewerContext(companionProvider); + const viewerContext = new ViewerContext(companionProvider); const data = { id: 'what', }; @@ -176,10 +176,8 @@ describe(ReadonlyEntity, () => { describe('loader', () => { it('creates a new EntityLoader', async () => { const companionProvider = createUnitTestEntityCompanionProvider(); - const viewerContext = new TestViewerContext(companionProvider); - expect( - SimpleTestEntity.loader(viewerContext, viewerContext.getQueryContext()) - ).toBeInstanceOf(EntityLoader); + const viewerContext = new ViewerContext(companionProvider); + expect(SimpleTestEntity.loader(viewerContext)).toBeInstanceOf(EntityLoader); }); }); }); diff --git a/packages/entity/src/__tests__/ViewerContext-test.ts b/packages/entity/src/__tests__/ViewerContext-test.ts index c8d28514..45fa1ad3 100644 --- a/packages/entity/src/__tests__/ViewerContext-test.ts +++ b/packages/entity/src/__tests__/ViewerContext-test.ts @@ -3,12 +3,11 @@ import ViewerContext from '../ViewerContext'; import { createUnitTestEntityCompanionProvider } from '../utils/testing/createUnitTestEntityCompanionProvider'; describe(ViewerContext, () => { - describe('getNonTransactionalQueryContextForDatabaseAdaptorFlavor', () => { + describe('getQueryContextForDatabaseAdaptorFlavor', () => { it('creates a new regular query context', () => { const companionProvider = createUnitTestEntityCompanionProvider(); const viewerContext = new ViewerContext(companionProvider); - const queryContext = - viewerContext.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres'); + const queryContext = viewerContext.getQueryContextForDatabaseAdaptorFlavor('postgres'); expect(queryContext).toBeInstanceOf(EntityQueryContext); expect(queryContext.isInTransaction()).toBe(false); }); diff --git a/packages/entity/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts b/packages/entity/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts index 00516f8c..cc136089 100644 --- a/packages/entity/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts +++ b/packages/entity/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts @@ -3,22 +3,22 @@ import { EntityCompanionDefinition } from '../../EntityCompanionProvider'; import EntityConfiguration from '../../EntityConfiguration'; import { UUIDField, EnumField, StringField } from '../../EntityFields'; import EntityPrivacyPolicy from '../../EntityPrivacyPolicy'; +import ViewerContext from '../../ViewerContext'; import { successfulResults, failedResults } from '../../entityUtils'; import AlwaysAllowPrivacyPolicyRule from '../../rules/AlwaysAllowPrivacyPolicyRule'; -import TestViewerContext from '../../testfixtures/TestViewerContext'; import { createUnitTestEntityCompanionProvider } from '../../utils/testing/createUnitTestEntityCompanionProvider'; describe('Two entities backed by the same table', () => { test('load by different types', async () => { const companionProvider = createUnitTestEntityCompanionProvider(); - const viewerContext = new TestViewerContext(companionProvider); + const viewerContext = new ViewerContext(companionProvider); - const one = await OneTestEntity.creator(viewerContext, viewerContext.getQueryContext()) + const one = await OneTestEntity.creator(viewerContext) .setField('entity_type', EntityType.ONE) .setField('common_other_field', 'wat') .enforceCreateAsync(); - const two = await TwoTestEntity.creator(viewerContext, viewerContext.getQueryContext()) + const two = await TwoTestEntity.creator(viewerContext) .setField('entity_type', EntityType.TWO) .setField('other_field', 'blah') .setField('common_other_field', 'wat') @@ -28,21 +28,17 @@ describe('Two entities backed by the same table', () => { expect(two).toBeInstanceOf(TwoTestEntity); await expect( - TwoTestEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDAsync(one.getID()) + TwoTestEntity.loader(viewerContext).enforcing().loadByIDAsync(one.getID()) ).rejects.toThrowError('TwoTestEntity must be instantiated with two data'); await expect( - OneTestEntity.loader(viewerContext, viewerContext.getQueryContext()) - .enforcing() - .loadByIDAsync(two.getID()) + OneTestEntity.loader(viewerContext).enforcing().loadByIDAsync(two.getID()) ).rejects.toThrowError('OneTestEntity must be instantiated with one data'); - const manyResults = await OneTestEntity.loader( - viewerContext, - viewerContext.getQueryContext() - ).loadManyByFieldEqualingAsync('common_other_field', 'wat'); + const manyResults = await OneTestEntity.loader(viewerContext).loadManyByFieldEqualingAsync( + 'common_other_field', + 'wat' + ); const successfulManyResults = successfulResults(manyResults); const failedManyResults = failedResults(manyResults); @@ -55,8 +51,7 @@ describe('Two entities backed by the same table', () => { ); const fieldEqualityConjunctionResults = await OneTestEntity.loader( - viewerContext, - viewerContext.getQueryContext() + viewerContext ).loadManyByFieldEqualityConjunctionAsync([ { fieldName: 'common_other_field', @@ -111,30 +106,24 @@ const testEntityConfiguration = new EntityConfiguration({ cacheAdapterFlavor: 'redis', }); -class TestEntityPrivacyPolicy extends EntityPrivacyPolicy< - any, - string, - TestViewerContext, - any, - any -> { +class TestEntityPrivacyPolicy extends EntityPrivacyPolicy { protected override readonly readRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly createRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly updateRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly deleteRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; } -class OneTestEntity extends Entity { +class OneTestEntity extends Entity { constructor(constructorParams: { - viewerContext: TestViewerContext; + viewerContext: ViewerContext; id: string; databaseFields: Readonly; selectedFields: Readonly>; @@ -148,7 +137,7 @@ class OneTestEntity extends Entity { +class TwoTestEntity extends Entity { constructor(constructorParams: { - viewerContext: TestViewerContext; + viewerContext: ViewerContext; id: string; databaseFields: Readonly; selectedFields: Readonly>; @@ -178,7 +167,7 @@ class TwoTestEntity extends Entity { test('mutate through different types and keep consistent cache and dataloader', async () => { const companionProvider = createUnitTestEntityCompanionProvider(); - const viewerContext = new TestViewerContext(companionProvider); + const viewerContext = new ViewerContext(companionProvider); - const entity1 = await OneTestEntity.creator(viewerContext, viewerContext.getQueryContext()) + const entity1 = await OneTestEntity.creator(viewerContext) .setField('fake_field', 'hello') .enforceCreateAsync(); expect(entity1).toBeInstanceOf(OneTestEntity); - const entity2 = await TwoTestEntity.loader(viewerContext, viewerContext.getQueryContext()) + const entity2 = await TwoTestEntity.loader(viewerContext) .enforcing() .loadByIDAsync(entity1.getID()); expect(entity2).toBeInstanceOf(TwoTestEntity); - const updated2 = await TwoTestEntity.updater(entity2, viewerContext.getQueryContext()) + const updated2 = await TwoTestEntity.updater(entity2) .setField('fake_field', 'world') .setField('other_field', 'wat') .enforceUpdateAsync(); @@ -32,7 +32,7 @@ describe('Two entities backed by the same table', () => { fake_field: 'world', }); - const loaded1 = await OneTestEntity.loader(viewerContext, viewerContext.getQueryContext()) + const loaded1 = await OneTestEntity.loader(viewerContext) .enforcing() .loadByIDAsync(entity1.getID()); expect(loaded1.getAllFields()).toMatchObject({ @@ -43,14 +43,14 @@ describe('Two entities backed by the same table', () => { test('cached field that differs between the two to test invalidation', async () => { const companionProvider = createUnitTestEntityCompanionProvider(); - const viewerContext = new TestViewerContext(companionProvider); + const viewerContext = new ViewerContext(companionProvider); - const entity = await TwoTestEntity.creator(viewerContext, viewerContext.getQueryContext()) + const entity = await TwoTestEntity.creator(viewerContext) .setField('fake_field', 'hello') .setField('other_field', 'huh') .enforceCreateAsync(); - const loadedEntity = await TwoTestEntity.loader(viewerContext, viewerContext.getQueryContext()) + const loadedEntity = await TwoTestEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('other_field', 'huh'); expect(loadedEntity?.getAllFields()).toMatchObject({ @@ -59,14 +59,12 @@ describe('Two entities backed by the same table', () => { other_field: 'huh', }); - const loaded1 = await OneTestEntity.loader(viewerContext, viewerContext.getQueryContext()) + const loaded1 = await OneTestEntity.loader(viewerContext) .enforcing() .loadByIDAsync(entity.getID()); - await OneTestEntity.updater(loaded1, viewerContext.getQueryContext()) - .setField('fake_field', 'world') - .enforceUpdateAsync(); + await OneTestEntity.updater(loaded1).setField('fake_field', 'world').enforceUpdateAsync(); - const loaded2 = await TwoTestEntity.loader(viewerContext, viewerContext.getQueryContext()) + const loaded2 = await TwoTestEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('other_field', 'huh'); expect(loaded2?.getAllFields()).toMatchObject({ @@ -75,7 +73,7 @@ describe('Two entities backed by the same table', () => { other_field: 'huh', }); - const loaded22 = await TwoTestEntity.loader(viewerContext, viewerContext.getQueryContext()) + const loaded22 = await TwoTestEntity.loader(viewerContext) .enforcing() .loadByFieldEqualingAsync('fake_field', 'world'); expect(loaded22?.getAllFields()).toMatchObject({ @@ -116,32 +114,26 @@ const testEntityConfiguration = new EntityConfiguration({ cacheAdapterFlavor: 'redis', }); -class TestEntityPrivacyPolicy extends EntityPrivacyPolicy< - any, - string, - TestViewerContext, - any, - any -> { +class TestEntityPrivacyPolicy extends EntityPrivacyPolicy { protected override readonly readRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly createRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly updateRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly deleteRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; } -class OneTestEntity extends Entity { +class OneTestEntity extends Entity { static defineCompanionDefinition(): EntityCompanionDefinition< TestFields, string, - TestViewerContext, + ViewerContext, OneTestEntity, TestEntityPrivacyPolicy, OneTestFields @@ -155,11 +147,11 @@ class OneTestEntity extends Entity { +class TwoTestEntity extends Entity { static defineCompanionDefinition(): EntityCompanionDefinition< TestFields, string, - TestViewerContext, + ViewerContext, TwoTestEntity, TestEntityPrivacyPolicy, TwoTestFields diff --git a/packages/entity/src/internal/EntityDataManager.ts b/packages/entity/src/internal/EntityDataManager.ts index 067c9750..7a513802 100644 --- a/packages/entity/src/internal/EntityDataManager.ts +++ b/packages/entity/src/internal/EntityDataManager.ts @@ -76,7 +76,7 @@ export default class EntityDataManager { entityClassName: this.entityClassName, }); return await this.databaseAdapter.fetchManyWhereAsync( - this.queryContextProvider.getNonTransactionalQueryContext(), + this.queryContextProvider.getQueryContext(), fieldName, fetcherValues ); diff --git a/packages/entity/src/internal/__tests__/EntityDataManager-test.ts b/packages/entity/src/internal/__tests__/EntityDataManager-test.ts index 65ec6b6e..12b79770 100644 --- a/packages/entity/src/internal/__tests__/EntityDataManager-test.ts +++ b/packages/entity/src/internal/__tests__/EntityDataManager-test.ts @@ -78,7 +78,7 @@ describe(EntityDataManager, () => { new NoOpEntityMetricsAdapter(), TestEntity.name ); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const dbSpy = jest.spyOn(databaseAdapter, 'fetchManyWhereAsync'); const cacheSpy = jest.spyOn(entityCache, 'readManyThroughAsync'); @@ -126,7 +126,7 @@ describe(EntityDataManager, () => { new NoOpEntityMetricsAdapter(), TestEntity.name ); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const dbSpy = jest.spyOn(databaseAdapter, 'fetchManyWhereAsync'); const cacheSpy = jest.spyOn(entityCache, 'readManyThroughAsync'); @@ -174,7 +174,7 @@ describe(EntityDataManager, () => { new NoOpEntityMetricsAdapter(), TestEntity.name ); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); // use second data manager to ensure that cache is hit instead of data loader const entityDataManager2 = new EntityDataManager( databaseAdapter, @@ -218,7 +218,7 @@ describe(EntityDataManager, () => { new NoOpEntityMetricsAdapter(), TestEntity.name ); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const dbSpy = jest.spyOn(databaseAdapter, 'fetchManyWhereAsync'); const cacheSpy = jest.spyOn(entityCache, 'readManyThroughAsync'); @@ -254,7 +254,7 @@ describe(EntityDataManager, () => { new NoOpEntityMetricsAdapter(), TestEntity.name ); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const dbSpy = jest.spyOn(databaseAdapter, 'fetchManyWhereAsync'); const cacheSpy = jest.spyOn(entityCache, 'readManyThroughAsync'); @@ -298,7 +298,7 @@ describe(EntityDataManager, () => { new NoOpEntityMetricsAdapter(), TestEntity.name ); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const objectInQuestion = objects.get(testEntityConfiguration.tableName)![1]!; @@ -337,7 +337,7 @@ describe(EntityDataManager, () => { new NoOpEntityMetricsAdapter(), TestEntity.name ); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const objectInQuestion = objects.get(testEntityConfiguration.tableName)![1]!; @@ -415,7 +415,7 @@ describe(EntityDataManager, () => { new NoOpEntityMetricsAdapter(), TestEntity.name ); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); const dbSpy = jest.spyOn(databaseAdapter, 'fetchManyByFieldEqualityConjunctionAsync'); const cacheSpy = jest.spyOn(entityCache, 'readManyThroughAsync'); @@ -461,7 +461,7 @@ describe(EntityDataManager, () => { new NoOpEntityMetricsAdapter(), TestEntity.name ); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); await expect( entityDataManager.loadManyByFieldEqualingAsync(queryContext, 'customIdField', ['2']) @@ -488,7 +488,7 @@ describe(EntityDataManager, () => { metricsAdapter, TestEntity.name ); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); await entityDataManager.loadManyByFieldEqualingAsync(queryContext, 'customIdField', ['1']); verify( @@ -591,7 +591,7 @@ describe(EntityDataManager, () => { new NoOpEntityMetricsAdapter(), TestEntity.name ); - const queryContext = StubQueryContextProvider.getNonTransactionalQueryContext(); + const queryContext = StubQueryContextProvider.getQueryContext(); await expect( entityDataManager.loadManyByFieldEqualingAsync(queryContext, 'nullableField', [null as any]) diff --git a/packages/entity/src/testfixtures/SimpleTestEntity.ts b/packages/entity/src/testfixtures/SimpleTestEntity.ts index 753aca7a..e6992ab3 100644 --- a/packages/entity/src/testfixtures/SimpleTestEntity.ts +++ b/packages/entity/src/testfixtures/SimpleTestEntity.ts @@ -1,9 +1,9 @@ -import TestViewerContext from './TestViewerContext'; import Entity from '../Entity'; import { EntityCompanionDefinition } from '../EntityCompanionProvider'; import EntityConfiguration from '../EntityConfiguration'; import { UUIDField } from '../EntityFields'; import EntityPrivacyPolicy from '../EntityPrivacyPolicy'; +import ViewerContext from '../ViewerContext'; import AlwaysAllowPrivacyPolicyRule from '../rules/AlwaysAllowPrivacyPolicyRule'; export type SimpleTestFields = { @@ -27,7 +27,7 @@ export const simpleTestEntityConfiguration = new EntityConfiguration { @@ -35,7 +35,7 @@ export class SimpleTestEntityPrivacyPolicy extends EntityPrivacyPolicy< new AlwaysAllowPrivacyPolicyRule< SimpleTestFields, string, - TestViewerContext, + ViewerContext, SimpleTestEntity, SimpleTestFieldSelection >(), @@ -44,7 +44,7 @@ export class SimpleTestEntityPrivacyPolicy extends EntityPrivacyPolicy< new AlwaysAllowPrivacyPolicyRule< SimpleTestFields, string, - TestViewerContext, + ViewerContext, SimpleTestEntity, SimpleTestFieldSelection >(), @@ -53,7 +53,7 @@ export class SimpleTestEntityPrivacyPolicy extends EntityPrivacyPolicy< new AlwaysAllowPrivacyPolicyRule< SimpleTestFields, string, - TestViewerContext, + ViewerContext, SimpleTestEntity, SimpleTestFieldSelection >(), @@ -62,7 +62,7 @@ export class SimpleTestEntityPrivacyPolicy extends EntityPrivacyPolicy< new AlwaysAllowPrivacyPolicyRule< SimpleTestFields, string, - TestViewerContext, + ViewerContext, SimpleTestEntity, SimpleTestFieldSelection >(), @@ -72,13 +72,13 @@ export class SimpleTestEntityPrivacyPolicy extends EntityPrivacyPolicy< export default class SimpleTestEntity extends Entity< SimpleTestFields, string, - TestViewerContext, + ViewerContext, SimpleTestFieldSelection > { static defineCompanionDefinition(): EntityCompanionDefinition< SimpleTestFields, string, - TestViewerContext, + ViewerContext, SimpleTestEntity, SimpleTestEntityPrivacyPolicy, SimpleTestFieldSelection diff --git a/packages/entity/src/testfixtures/TestEntity.ts b/packages/entity/src/testfixtures/TestEntity.ts index d47da2a5..5def5fe4 100644 --- a/packages/entity/src/testfixtures/TestEntity.ts +++ b/packages/entity/src/testfixtures/TestEntity.ts @@ -1,11 +1,11 @@ import { result, Result } from '@expo/results'; -import TestViewerContext from './TestViewerContext'; import Entity from '../Entity'; import { EntityCompanionDefinition } from '../EntityCompanionProvider'; import EntityConfiguration from '../EntityConfiguration'; import { UUIDField, StringField, DateField, IntField } from '../EntityFields'; import EntityPrivacyPolicy from '../EntityPrivacyPolicy'; +import ViewerContext from '../ViewerContext'; import AlwaysAllowPrivacyPolicyRule from '../rules/AlwaysAllowPrivacyPolicyRule'; export type TestFields = { @@ -48,28 +48,28 @@ export const testEntityConfiguration = new EntityConfiguration({ export class TestEntityPrivacyPolicy extends EntityPrivacyPolicy< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity > { protected override readonly readRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly createRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly updateRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly deleteRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; } -export default class TestEntity extends Entity { +export default class TestEntity extends Entity { static defineCompanionDefinition(): EntityCompanionDefinition< TestFields, string, - TestViewerContext, + ViewerContext, TestEntity, TestEntityPrivacyPolicy > { @@ -84,10 +84,7 @@ export default class TestEntity extends Entity> { + static async hello(viewerContext: ViewerContext, testValue: string): Promise> { const fields = { customIdField: testValue, testIndexedField: 'hello', @@ -106,15 +103,15 @@ export default class TestEntity extends Entity> { + static async returnError(_viewerContext: ViewerContext): Promise> { return result(new Error('return entity')); } - static async throwError(_viewerContext: TestViewerContext): Promise> { + static async throwError(_viewerContext: ViewerContext): Promise> { throw new Error('threw entity'); } - static async nonResult(_viewerContext: TestViewerContext, testValue: string): Promise { + static async nonResult(_viewerContext: ViewerContext, testValue: string): Promise { return testValue; } } diff --git a/packages/entity/src/testfixtures/TestEntity2.ts b/packages/entity/src/testfixtures/TestEntity2.ts index 541aaed0..be286eed 100644 --- a/packages/entity/src/testfixtures/TestEntity2.ts +++ b/packages/entity/src/testfixtures/TestEntity2.ts @@ -1,9 +1,9 @@ -import TestViewerContext from './TestViewerContext'; import Entity from '../Entity'; import { EntityCompanionDefinition } from '../EntityCompanionProvider'; import EntityConfiguration from '../EntityConfiguration'; import { UUIDField } from '../EntityFields'; import EntityPrivacyPolicy from '../EntityPrivacyPolicy'; +import ViewerContext from '../ViewerContext'; import AlwaysAllowPrivacyPolicyRule from '../rules/AlwaysAllowPrivacyPolicyRule'; export type Test2Fields = { @@ -29,28 +29,28 @@ export const testEntity2Configuration = new EntityConfiguration({ export class TestEntity2PrivacyPolicy extends EntityPrivacyPolicy< Test2Fields, string, - TestViewerContext, + ViewerContext, TestEntity2 > { protected override readonly readRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly createRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly updateRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; protected override readonly deleteRules = [ - new AlwaysAllowPrivacyPolicyRule(), + new AlwaysAllowPrivacyPolicyRule(), ]; } -export default class TestEntity2 extends Entity { +export default class TestEntity2 extends Entity { static defineCompanionDefinition(): EntityCompanionDefinition< Test2Fields, string, - TestViewerContext, + ViewerContext, TestEntity2, TestEntity2PrivacyPolicy > { diff --git a/packages/entity/src/testfixtures/TestViewerContext.ts b/packages/entity/src/testfixtures/TestViewerContext.ts index c0d1580f..2ecf1f1e 100644 --- a/packages/entity/src/testfixtures/TestViewerContext.ts +++ b/packages/entity/src/testfixtures/TestViewerContext.ts @@ -1,14 +1,3 @@ -import { EntityQueryContext, EntityTransactionalQueryContext } from '../EntityQueryContext'; import ViewerContext from '../ViewerContext'; -export default class TestViewerContext extends ViewerContext { - public getQueryContext(): EntityQueryContext { - return super.getNonTransactionalQueryContextForDatabaseAdaptorFlavor('postgres'); - } - - public async runInTransactionAsync( - transactionScope: (queryContext: EntityTransactionalQueryContext) => Promise - ): Promise { - return await super.runInTransactionForDatabaseAdaptorFlavorAsync('postgres', transactionScope); - } -} +export default class TestViewerContext extends ViewerContext {}