@expo/entity 0.24.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/build/ComposedEntityCacheAdapter.d.ts +19 -0
  2. package/build/ComposedEntityCacheAdapter.js +66 -0
  3. package/build/ComposedEntityCacheAdapter.js.map +1 -0
  4. package/build/ComposedSecondaryEntityCache.d.ts +15 -0
  5. package/build/ComposedSecondaryEntityCache.js +37 -0
  6. package/build/ComposedSecondaryEntityCache.js.map +1 -0
  7. package/build/Entity.js +6 -6
  8. package/build/Entity.js.map +1 -1
  9. package/build/EntityAssociationLoader.js +4 -4
  10. package/build/EntityAssociationLoader.js.map +1 -1
  11. package/build/EntityLoader.d.ts +3 -2
  12. package/build/EntityLoader.js +5 -4
  13. package/build/EntityLoader.js.map +1 -1
  14. package/build/EntityLoaderFactory.d.ts +2 -2
  15. package/build/EntityLoaderFactory.js +2 -2
  16. package/build/EntityLoaderFactory.js.map +1 -1
  17. package/build/EntityMutationInfo.d.ts +12 -3
  18. package/build/EntityMutator.d.ts +5 -4
  19. package/build/EntityMutator.js +31 -24
  20. package/build/EntityMutator.js.map +1 -1
  21. package/build/EntityMutatorFactory.d.ts +4 -4
  22. package/build/EntityMutatorFactory.js +6 -6
  23. package/build/EntityMutatorFactory.js.map +1 -1
  24. package/build/EntityPrivacyPolicy.d.ts +15 -4
  25. package/build/EntityPrivacyPolicy.js +14 -14
  26. package/build/EntityPrivacyPolicy.js.map +1 -1
  27. package/build/IEntityGenericCacher.d.ts +2 -2
  28. package/build/ReadonlyEntity.js +1 -1
  29. package/build/ReadonlyEntity.js.map +1 -1
  30. package/build/ViewerScopedEntityLoaderFactory.d.ts +2 -2
  31. package/build/ViewerScopedEntityLoaderFactory.js +2 -2
  32. package/build/ViewerScopedEntityLoaderFactory.js.map +1 -1
  33. package/build/ViewerScopedEntityMutatorFactory.d.ts +4 -4
  34. package/build/ViewerScopedEntityMutatorFactory.js +6 -6
  35. package/build/ViewerScopedEntityMutatorFactory.js.map +1 -1
  36. package/build/__tests__/ComposedCacheAdapter-test.d.ts +1 -0
  37. package/build/__tests__/ComposedCacheAdapter-test.js +198 -0
  38. package/build/__tests__/ComposedCacheAdapter-test.js.map +1 -0
  39. package/build/__tests__/ComposedSecondaryEntityCache-test.d.ts +1 -0
  40. package/build/__tests__/ComposedSecondaryEntityCache-test.js +65 -0
  41. package/build/__tests__/ComposedSecondaryEntityCache-test.js.map +1 -0
  42. package/build/__tests__/EntityCommonUseCases-test.js +1 -1
  43. package/build/__tests__/EntityCommonUseCases-test.js.map +1 -1
  44. package/build/__tests__/EntityEdges-test.js +260 -37
  45. package/build/__tests__/EntityEdges-test.js.map +1 -1
  46. package/build/__tests__/EntityLoader-constructor-test.js +2 -1
  47. package/build/__tests__/EntityLoader-constructor-test.js.map +1 -1
  48. package/build/__tests__/EntityLoader-test.js +19 -11
  49. package/build/__tests__/EntityLoader-test.js.map +1 -1
  50. package/build/__tests__/EntityMutator-test.js +96 -43
  51. package/build/__tests__/EntityMutator-test.js.map +1 -1
  52. package/build/__tests__/EntityPrivacyPolicy-test.js +23 -12
  53. package/build/__tests__/EntityPrivacyPolicy-test.js.map +1 -1
  54. package/build/__tests__/EntitySecondaryCacheLoader-test.js +1 -1
  55. package/build/__tests__/EntitySecondaryCacheLoader-test.js.map +1 -1
  56. package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js +3 -2
  57. package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js.map +1 -1
  58. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js +3 -2
  59. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js.map +1 -1
  60. package/build/rules/AlwaysAllowPrivacyPolicyRule.d.ts +2 -1
  61. package/build/rules/AlwaysAllowPrivacyPolicyRule.js +1 -1
  62. package/build/rules/AlwaysAllowPrivacyPolicyRule.js.map +1 -1
  63. package/build/rules/AlwaysDenyPrivacyPolicyRule.d.ts +2 -1
  64. package/build/rules/AlwaysDenyPrivacyPolicyRule.js +1 -1
  65. package/build/rules/AlwaysDenyPrivacyPolicyRule.js.map +1 -1
  66. package/build/rules/AlwaysSkipPrivacyPolicyRule.d.ts +2 -1
  67. package/build/rules/AlwaysSkipPrivacyPolicyRule.js +1 -1
  68. package/build/rules/AlwaysSkipPrivacyPolicyRule.js.map +1 -1
  69. package/build/rules/PrivacyPolicyRule.d.ts +2 -1
  70. package/build/rules/PrivacyPolicyRule.js.map +1 -1
  71. package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js +1 -0
  72. package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js.map +1 -1
  73. package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js +1 -0
  74. package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js.map +1 -1
  75. package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js +1 -0
  76. package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js.map +1 -1
  77. package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +2 -0
  78. package/build/utils/testing/PrivacyPolicyRuleTestUtils.js +6 -6
  79. package/build/utils/testing/PrivacyPolicyRuleTestUtils.js.map +1 -1
  80. package/package.json +1 -1
  81. package/src/ComposedEntityCacheAdapter.ts +86 -0
  82. package/src/ComposedSecondaryEntityCache.ts +63 -0
  83. package/src/Entity.ts +6 -4
  84. package/src/EntityAssociationLoader.ts +4 -4
  85. package/src/EntityLoader.ts +5 -1
  86. package/src/EntityLoaderFactory.ts +4 -2
  87. package/src/EntityMutationInfo.ts +13 -3
  88. package/src/EntityMutator.ts +44 -21
  89. package/src/EntityMutatorFactory.ts +10 -4
  90. package/src/EntityPrivacyPolicy.ts +31 -1
  91. package/src/IEntityGenericCacher.ts +2 -2
  92. package/src/ReadonlyEntity.ts +1 -1
  93. package/src/ViewerScopedEntityLoaderFactory.ts +8 -3
  94. package/src/ViewerScopedEntityMutatorFactory.ts +22 -7
  95. package/src/__tests__/ComposedCacheAdapter-test.ts +280 -0
  96. package/src/__tests__/ComposedSecondaryEntityCache-test.ts +101 -0
  97. package/src/__tests__/EntityCommonUseCases-test.ts +2 -1
  98. package/src/__tests__/EntityEdges-test.ts +286 -45
  99. package/src/__tests__/EntityLoader-constructor-test.ts +3 -1
  100. package/src/__tests__/EntityLoader-test.ts +26 -1
  101. package/src/__tests__/EntityMutator-test.ts +99 -37
  102. package/src/__tests__/EntityPrivacyPolicy-test.ts +66 -7
  103. package/src/__tests__/EntitySecondaryCacheLoader-test.ts +1 -0
  104. package/src/__tests__/ViewerScopedEntityLoaderFactory-test.ts +4 -2
  105. package/src/__tests__/ViewerScopedEntityMutatorFactory-test.ts +6 -2
  106. package/src/rules/AlwaysAllowPrivacyPolicyRule.ts +2 -0
  107. package/src/rules/AlwaysDenyPrivacyPolicyRule.ts +2 -0
  108. package/src/rules/AlwaysSkipPrivacyPolicyRule.ts +2 -0
  109. package/src/rules/PrivacyPolicyRule.ts +2 -0
  110. package/src/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.ts +2 -0
  111. package/src/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.ts +2 -0
  112. package/src/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.ts +2 -0
  113. package/src/utils/testing/PrivacyPolicyRuleTestUtils.ts +14 -6
@@ -25,6 +25,7 @@ import EntityMutationTriggerConfiguration, {
25
25
  } from '../EntityMutationTriggerConfiguration';
26
26
  import EntityMutationValidator from '../EntityMutationValidator';
27
27
  import EntityMutatorFactory from '../EntityMutatorFactory';
28
+ import { EntityPrivacyPolicyEvaluationContext } from '../EntityPrivacyPolicy';
28
29
  import { EntityTransactionalQueryContext, EntityQueryContext } from '../EntityQueryContext';
29
30
  import ViewerContext from '../ViewerContext';
30
31
  import { enforceResultsAsync } from '../entityUtils';
@@ -340,6 +341,7 @@ describe(EntityMutatorFactory, () => {
340
341
  describe('forCreate', () => {
341
342
  it('creates entities', async () => {
342
343
  const viewerContext = mock<ViewerContext>();
344
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
343
345
  const queryContext = StubQueryContextProvider.getQueryContext();
344
346
 
345
347
  const id1 = uuidv4();
@@ -363,7 +365,7 @@ describe(EntityMutatorFactory, () => {
363
365
  },
364
366
  ]);
365
367
  const newEntity = await entityMutatorFactory
366
- .forCreate(viewerContext, queryContext)
368
+ .forCreate(viewerContext, queryContext, privacyPolicyEvaluationContext)
367
369
  .setField('stringField', 'huh')
368
370
  .enforceCreateAsync();
369
371
  expect(newEntity).toBeTruthy();
@@ -371,6 +373,7 @@ describe(EntityMutatorFactory, () => {
371
373
 
372
374
  it('checks privacy', async () => {
373
375
  const viewerContext = mock<ViewerContext>();
376
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
374
377
  const queryContext = StubQueryContextProvider.getQueryContext();
375
378
 
376
379
  const id1 = uuidv4();
@@ -397,7 +400,7 @@ describe(EntityMutatorFactory, () => {
397
400
  const spiedPrivacyPolicy = spy(privacyPolicy);
398
401
 
399
402
  await entityMutatorFactory
400
- .forCreate(viewerContext, queryContext)
403
+ .forCreate(viewerContext, queryContext, privacyPolicyEvaluationContext)
401
404
  .setField('stringField', 'huh')
402
405
  .enforceCreateAsync();
403
406
 
@@ -405,6 +408,7 @@ describe(EntityMutatorFactory, () => {
405
408
  spiedPrivacyPolicy.authorizeCreateAsync(
406
409
  viewerContext,
407
410
  anyOfClass(EntityTransactionalQueryContext),
411
+ privacyPolicyEvaluationContext,
408
412
  anyOfClass(TestEntity),
409
413
  anything()
410
414
  )
@@ -413,6 +417,7 @@ describe(EntityMutatorFactory, () => {
413
417
 
414
418
  it('executes triggers', async () => {
415
419
  const viewerContext = mock<ViewerContext>();
420
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
416
421
  const queryContext = StubQueryContextProvider.getQueryContext();
417
422
 
418
423
  const id1 = uuidv4();
@@ -439,7 +444,7 @@ describe(EntityMutatorFactory, () => {
439
444
  const triggerSpies = setUpMutationTriggerSpies(mutationTriggers);
440
445
 
441
446
  await entityMutatorFactory
442
- .forCreate(viewerContext, queryContext)
447
+ .forCreate(viewerContext, queryContext, privacyPolicyEvaluationContext)
443
448
  .setField('stringField', 'huh')
444
449
  .enforceCreateAsync();
445
450
 
@@ -460,6 +465,7 @@ describe(EntityMutatorFactory, () => {
460
465
 
461
466
  it('executes validators', async () => {
462
467
  const viewerContext = mock<ViewerContext>();
468
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
463
469
  const queryContext = StubQueryContextProvider.getQueryContext();
464
470
 
465
471
  const id1 = uuidv4();
@@ -486,7 +492,7 @@ describe(EntityMutatorFactory, () => {
486
492
  const validatorSpies = setUpMutationValidatorSpies(mutationValidators);
487
493
 
488
494
  await entityMutatorFactory
489
- .forCreate(viewerContext, queryContext)
495
+ .forCreate(viewerContext, queryContext, privacyPolicyEvaluationContext)
490
496
  .setField('stringField', 'huh')
491
497
  .enforceCreateAsync();
492
498
 
@@ -497,6 +503,7 @@ describe(EntityMutatorFactory, () => {
497
503
  describe('forUpdate', () => {
498
504
  it('updates entities', async () => {
499
505
  const viewerContext = mock<ViewerContext>();
506
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
500
507
  const queryContext = StubQueryContextProvider.getQueryContext();
501
508
 
502
509
  const id1 = uuidv4();
@@ -521,11 +528,13 @@ describe(EntityMutatorFactory, () => {
521
528
  ]);
522
529
 
523
530
  const existingEntity = await enforceAsyncResult(
524
- entityLoaderFactory.forLoad(viewerContext, queryContext).loadByIDAsync(id2)
531
+ entityLoaderFactory
532
+ .forLoad(viewerContext, queryContext, privacyPolicyEvaluationContext)
533
+ .loadByIDAsync(id2)
525
534
  );
526
535
 
527
536
  const updatedEntity = await entityMutatorFactory
528
- .forUpdate(existingEntity, queryContext)
537
+ .forUpdate(existingEntity, queryContext, privacyPolicyEvaluationContext)
529
538
  .setField('stringField', 'huh2')
530
539
  .enforceUpdateAsync();
531
540
 
@@ -534,13 +543,16 @@ describe(EntityMutatorFactory, () => {
534
543
  expect(updatedEntity.getField('stringField')).toEqual('huh2');
535
544
 
536
545
  const reloadedEntity = await enforceAsyncResult(
537
- entityLoaderFactory.forLoad(viewerContext, queryContext).loadByIDAsync(id2)
546
+ entityLoaderFactory
547
+ .forLoad(viewerContext, queryContext, privacyPolicyEvaluationContext)
548
+ .loadByIDAsync(id2)
538
549
  );
539
550
  expect(reloadedEntity.getAllFields()).toMatchObject(updatedEntity.getAllFields());
540
551
  });
541
552
 
542
553
  it('checks privacy', async () => {
543
554
  const viewerContext = mock<ViewerContext>();
555
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
544
556
  const queryContext = StubQueryContextProvider.getQueryContext();
545
557
 
546
558
  const id1 = uuidv4();
@@ -568,11 +580,13 @@ describe(EntityMutatorFactory, () => {
568
580
  const spiedPrivacyPolicy = spy(privacyPolicy);
569
581
 
570
582
  const existingEntity = await enforceAsyncResult(
571
- entityLoaderFactory.forLoad(viewerContext, queryContext).loadByIDAsync(id2)
583
+ entityLoaderFactory
584
+ .forLoad(viewerContext, queryContext, privacyPolicyEvaluationContext)
585
+ .loadByIDAsync(id2)
572
586
  );
573
587
 
574
588
  await entityMutatorFactory
575
- .forUpdate(existingEntity, queryContext)
589
+ .forUpdate(existingEntity, queryContext, privacyPolicyEvaluationContext)
576
590
  .setField('stringField', 'huh2')
577
591
  .enforceUpdateAsync();
578
592
 
@@ -580,6 +594,7 @@ describe(EntityMutatorFactory, () => {
580
594
  spiedPrivacyPolicy.authorizeUpdateAsync(
581
595
  viewerContext,
582
596
  anyOfClass(EntityTransactionalQueryContext),
597
+ privacyPolicyEvaluationContext,
583
598
  anyOfClass(TestEntity),
584
599
  anything()
585
600
  )
@@ -588,6 +603,7 @@ describe(EntityMutatorFactory, () => {
588
603
 
589
604
  it('executes triggers', async () => {
590
605
  const viewerContext = mock<ViewerContext>();
606
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
591
607
  const queryContext = StubQueryContextProvider.getQueryContext();
592
608
 
593
609
  const id1 = uuidv4();
@@ -615,11 +631,13 @@ describe(EntityMutatorFactory, () => {
615
631
  const triggerSpies = setUpMutationTriggerSpies(mutationTriggers);
616
632
 
617
633
  const existingEntity = await enforceAsyncResult(
618
- entityLoaderFactory.forLoad(viewerContext, queryContext).loadByIDAsync(id2)
634
+ entityLoaderFactory
635
+ .forLoad(viewerContext, queryContext, privacyPolicyEvaluationContext)
636
+ .loadByIDAsync(id2)
619
637
  );
620
638
 
621
639
  await entityMutatorFactory
622
- .forUpdate(existingEntity, queryContext)
640
+ .forUpdate(existingEntity, queryContext, privacyPolicyEvaluationContext)
623
641
  .setField('stringField', 'huh2')
624
642
  .enforceUpdateAsync();
625
643
 
@@ -639,6 +657,7 @@ describe(EntityMutatorFactory, () => {
639
657
  });
640
658
  it('executes validators', async () => {
641
659
  const viewerContext = mock<ViewerContext>();
660
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
642
661
  const queryContext = StubQueryContextProvider.getQueryContext();
643
662
 
644
663
  const id1 = uuidv4();
@@ -666,11 +685,13 @@ describe(EntityMutatorFactory, () => {
666
685
  const validatorSpies = setUpMutationValidatorSpies(mutationValidators);
667
686
 
668
687
  const existingEntity = await enforceAsyncResult(
669
- entityLoaderFactory.forLoad(viewerContext, queryContext).loadByIDAsync(id2)
688
+ entityLoaderFactory
689
+ .forLoad(viewerContext, queryContext, privacyPolicyEvaluationContext)
690
+ .loadByIDAsync(id2)
670
691
  );
671
692
 
672
693
  await entityMutatorFactory
673
- .forUpdate(existingEntity, queryContext)
694
+ .forUpdate(existingEntity, queryContext, privacyPolicyEvaluationContext)
674
695
  .setField('stringField', 'huh2')
675
696
  .enforceUpdateAsync();
676
697
 
@@ -684,6 +705,7 @@ describe(EntityMutatorFactory, () => {
684
705
  describe('forDelete', () => {
685
706
  it('deletes entities', async () => {
686
707
  const viewerContext = mock<ViewerContext>();
708
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
687
709
  const queryContext = StubQueryContextProvider.getQueryContext();
688
710
 
689
711
  const id1 = uuidv4();
@@ -699,21 +721,28 @@ describe(EntityMutatorFactory, () => {
699
721
  ]);
700
722
 
701
723
  const existingEntity = await enforceAsyncResult(
702
- entityLoaderFactory.forLoad(viewerContext, queryContext).loadByIDAsync(id1)
724
+ entityLoaderFactory
725
+ .forLoad(viewerContext, queryContext, privacyPolicyEvaluationContext)
726
+ .loadByIDAsync(id1)
703
727
  );
704
728
  expect(existingEntity).toBeTruthy();
705
729
 
706
- await entityMutatorFactory.forDelete(existingEntity, queryContext).enforceDeleteAsync();
730
+ await entityMutatorFactory
731
+ .forDelete(existingEntity, queryContext, privacyPolicyEvaluationContext)
732
+ .enforceDeleteAsync();
707
733
 
708
734
  await expect(
709
735
  enforceAsyncResult(
710
- entityLoaderFactory.forLoad(viewerContext, queryContext).loadByIDAsync(id1)
736
+ entityLoaderFactory
737
+ .forLoad(viewerContext, queryContext, privacyPolicyEvaluationContext)
738
+ .loadByIDAsync(id1)
711
739
  )
712
740
  ).rejects.toBeInstanceOf(Error);
713
741
  });
714
742
 
715
743
  it('checks privacy', async () => {
716
744
  const viewerContext = mock<ViewerContext>();
745
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
717
746
  const queryContext = StubQueryContextProvider.getQueryContext();
718
747
 
719
748
  const id1 = uuidv4();
@@ -732,15 +761,20 @@ describe(EntityMutatorFactory, () => {
732
761
  const spiedPrivacyPolicy = spy(privacyPolicy);
733
762
 
734
763
  const existingEntity = await enforceAsyncResult(
735
- entityLoaderFactory.forLoad(viewerContext, queryContext).loadByIDAsync(id1)
764
+ entityLoaderFactory
765
+ .forLoad(viewerContext, queryContext, privacyPolicyEvaluationContext)
766
+ .loadByIDAsync(id1)
736
767
  );
737
768
 
738
- await entityMutatorFactory.forDelete(existingEntity, queryContext).enforceDeleteAsync();
769
+ await entityMutatorFactory
770
+ .forDelete(existingEntity, queryContext, privacyPolicyEvaluationContext)
771
+ .enforceDeleteAsync();
739
772
 
740
773
  verify(
741
774
  spiedPrivacyPolicy.authorizeDeleteAsync(
742
775
  viewerContext,
743
776
  anyOfClass(EntityTransactionalQueryContext),
777
+ anything(),
744
778
  anyOfClass(TestEntity),
745
779
  anything()
746
780
  )
@@ -749,6 +783,7 @@ describe(EntityMutatorFactory, () => {
749
783
 
750
784
  it('executes triggers', async () => {
751
785
  const viewerContext = mock<ViewerContext>();
786
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
752
787
  const queryContext = StubQueryContextProvider.getQueryContext();
753
788
 
754
789
  const id1 = uuidv4();
@@ -767,10 +802,14 @@ describe(EntityMutatorFactory, () => {
767
802
  const triggerSpies = setUpMutationTriggerSpies(mutationTriggers);
768
803
 
769
804
  const existingEntity = await enforceAsyncResult(
770
- entityLoaderFactory.forLoad(viewerContext, queryContext).loadByIDAsync(id1)
805
+ entityLoaderFactory
806
+ .forLoad(viewerContext, queryContext, privacyPolicyEvaluationContext)
807
+ .loadByIDAsync(id1)
771
808
  );
772
809
 
773
- await entityMutatorFactory.forDelete(existingEntity, queryContext).enforceDeleteAsync();
810
+ await entityMutatorFactory
811
+ .forDelete(existingEntity, queryContext, privacyPolicyEvaluationContext)
812
+ .enforceDeleteAsync();
774
813
 
775
814
  verifyTriggerCounts(
776
815
  viewerContext,
@@ -789,6 +828,7 @@ describe(EntityMutatorFactory, () => {
789
828
 
790
829
  it('does not execute validators', async () => {
791
830
  const viewerContext = mock<ViewerContext>();
831
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
792
832
  const queryContext = StubQueryContextProvider.getQueryContext();
793
833
 
794
834
  const id1 = uuidv4();
@@ -807,10 +847,14 @@ describe(EntityMutatorFactory, () => {
807
847
  const validatorSpies = setUpMutationValidatorSpies(mutationValidators);
808
848
 
809
849
  const existingEntity = await enforceAsyncResult(
810
- entityLoaderFactory.forLoad(viewerContext, queryContext).loadByIDAsync(id1)
850
+ entityLoaderFactory
851
+ .forLoad(viewerContext, queryContext, privacyPolicyEvaluationContext)
852
+ .loadByIDAsync(id1)
811
853
  );
812
854
 
813
- await entityMutatorFactory.forDelete(existingEntity, queryContext).enforceDeleteAsync();
855
+ await entityMutatorFactory
856
+ .forDelete(existingEntity, queryContext, privacyPolicyEvaluationContext)
857
+ .enforceDeleteAsync();
814
858
 
815
859
  verifyValidatorCounts(viewerContext, validatorSpies, 0, {
816
860
  type: EntityMutationType.DELETE as any,
@@ -820,6 +864,7 @@ describe(EntityMutatorFactory, () => {
820
864
 
821
865
  it('invalidates cache for fields upon create', async () => {
822
866
  const viewerContext = mock<ViewerContext>();
867
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
823
868
  const queryContext = StubQueryContextProvider.getQueryContext();
824
869
 
825
870
  const id1 = uuidv4();
@@ -836,21 +881,21 @@ describe(EntityMutatorFactory, () => {
836
881
 
837
882
  const entites1 = await enforceResultsAsync(
838
883
  entityLoaderFactory
839
- .forLoad(viewerContext, queryContext)
884
+ .forLoad(viewerContext, queryContext, privacyPolicyEvaluationContext)
840
885
  .loadManyByFieldEqualingAsync('stringField', 'huh')
841
886
  );
842
887
  expect(entites1).toHaveLength(1);
843
888
 
844
889
  await enforceAsyncResult(
845
890
  entityMutatorFactory
846
- .forCreate(viewerContext, queryContext)
891
+ .forCreate(viewerContext, queryContext, privacyPolicyEvaluationContext)
847
892
  .setField('stringField', 'huh')
848
893
  .createAsync()
849
894
  );
850
895
 
851
896
  const entities2 = await enforceResultsAsync(
852
897
  entityLoaderFactory
853
- .forLoad(viewerContext, queryContext)
898
+ .forLoad(viewerContext, queryContext, privacyPolicyEvaluationContext)
854
899
  .loadManyByFieldEqualingAsync('stringField', 'huh')
855
900
  );
856
901
  expect(entities2).toHaveLength(2);
@@ -858,6 +903,7 @@ describe(EntityMutatorFactory, () => {
858
903
 
859
904
  it('throws error when field not valid', async () => {
860
905
  const viewerContext = mock<ViewerContext>();
906
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
861
907
  const queryContext = StubQueryContextProvider.getQueryContext();
862
908
  const id1 = uuidv4();
863
909
  const { entityMutatorFactory } = createEntityMutatorFactory([
@@ -873,19 +919,19 @@ describe(EntityMutatorFactory, () => {
873
919
 
874
920
  await expect(
875
921
  entityMutatorFactory
876
- .forCreate(viewerContext, queryContext)
922
+ .forCreate(viewerContext, queryContext, privacyPolicyEvaluationContext)
877
923
  .setField('stringField', 10 as any)
878
924
  .createAsync()
879
925
  ).rejects.toThrowError('Entity field not valid: TestEntity (stringField = 10)');
880
926
 
881
927
  const createdEntity = await entityMutatorFactory
882
- .forCreate(viewerContext, queryContext)
928
+ .forCreate(viewerContext, queryContext, privacyPolicyEvaluationContext)
883
929
  .setField('stringField', 'hello')
884
930
  .enforceCreateAsync();
885
931
 
886
932
  await expect(
887
933
  entityMutatorFactory
888
- .forUpdate(createdEntity, queryContext)
934
+ .forUpdate(createdEntity, queryContext, privacyPolicyEvaluationContext)
889
935
  .setField('stringField', 10 as any)
890
936
  .updateAsync()
891
937
  ).rejects.toThrowError('Entity field not valid: TestEntity (stringField = 10)');
@@ -893,6 +939,7 @@ describe(EntityMutatorFactory, () => {
893
939
 
894
940
  it('returns error result when not authorized to create', async () => {
895
941
  const viewerContext = instance(mock(ViewerContext));
942
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
896
943
  const queryContext = StubQueryContextProvider.getQueryContext();
897
944
  const privacyPolicyMock = mock(SimpleTestEntityPrivacyPolicy);
898
945
  const databaseAdapter = instance(mock<EntityDatabaseAdapter<SimpleTestFields>>());
@@ -916,6 +963,7 @@ describe(EntityMutatorFactory, () => {
916
963
  privacyPolicyMock.authorizeCreateAsync(
917
964
  viewerContext,
918
965
  anyOfClass(EntityTransactionalQueryContext),
966
+ anything(),
919
967
  anyOfClass(SimpleTestEntity),
920
968
  anything()
921
969
  )
@@ -924,6 +972,7 @@ describe(EntityMutatorFactory, () => {
924
972
  privacyPolicyMock.authorizeUpdateAsync(
925
973
  viewerContext,
926
974
  anyOfClass(EntityTransactionalQueryContext),
975
+ anything(),
927
976
  anyOfClass(SimpleTestEntity),
928
977
  anything()
929
978
  )
@@ -932,6 +981,7 @@ describe(EntityMutatorFactory, () => {
932
981
  privacyPolicyMock.authorizeDeleteAsync(
933
982
  viewerContext,
934
983
  anyOfClass(EntityTransactionalQueryContext),
984
+ anything(),
935
985
  anyOfClass(SimpleTestEntity),
936
986
  anything()
937
987
  )
@@ -949,7 +999,7 @@ describe(EntityMutatorFactory, () => {
949
999
  );
950
1000
 
951
1001
  const entityCreateResult = await entityMutatorFactory
952
- .forCreate(viewerContext, queryContext)
1002
+ .forCreate(viewerContext, queryContext, privacyPolicyEvaluationContext)
953
1003
  .createAsync();
954
1004
  expect(entityCreateResult.ok).toBe(false);
955
1005
  expect(entityCreateResult.reason).toEqual(rejectionError);
@@ -961,14 +1011,14 @@ describe(EntityMutatorFactory, () => {
961
1011
  });
962
1012
 
963
1013
  const entityUpdateResult = await entityMutatorFactory
964
- .forUpdate(fakeEntity, queryContext)
1014
+ .forUpdate(fakeEntity, queryContext, privacyPolicyEvaluationContext)
965
1015
  .updateAsync();
966
1016
  expect(entityUpdateResult.ok).toBe(false);
967
1017
  expect(entityUpdateResult.reason).toEqual(rejectionError);
968
1018
  expect(entityUpdateResult.value).toBe(undefined);
969
1019
 
970
1020
  const entityDeleteResult = await entityMutatorFactory
971
- .forDelete(fakeEntity, queryContext)
1021
+ .forDelete(fakeEntity, queryContext, privacyPolicyEvaluationContext)
972
1022
  .deleteAsync();
973
1023
  expect(entityDeleteResult.ok).toBe(false);
974
1024
  expect(entityDeleteResult.reason).toEqual(rejectionError);
@@ -977,6 +1027,7 @@ describe(EntityMutatorFactory, () => {
977
1027
 
978
1028
  it('throws error when db adapter throws', async () => {
979
1029
  const viewerContext = instance(mock(ViewerContext));
1030
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
980
1031
  const queryContext = StubQueryContextProvider.getQueryContext();
981
1032
  const privacyPolicy = instance(mock(SimpleTestEntityPrivacyPolicy));
982
1033
  const databaseAdapterMock = mock<EntityDatabaseAdapter<SimpleTestFields>>();
@@ -1032,37 +1083,48 @@ describe(EntityMutatorFactory, () => {
1032
1083
  });
1033
1084
 
1034
1085
  await expect(
1035
- entityMutatorFactory.forCreate(viewerContext, queryContext).createAsync()
1086
+ entityMutatorFactory
1087
+ .forCreate(viewerContext, queryContext, privacyPolicyEvaluationContext)
1088
+ .createAsync()
1036
1089
  ).rejects.toEqual(rejectionError);
1037
1090
  await expect(
1038
- entityMutatorFactory.forUpdate(fakeEntity, queryContext).updateAsync()
1091
+ entityMutatorFactory
1092
+ .forUpdate(fakeEntity, queryContext, privacyPolicyEvaluationContext)
1093
+ .updateAsync()
1039
1094
  ).rejects.toEqual(rejectionError);
1040
1095
  await expect(
1041
- entityMutatorFactory.forDelete(fakeEntity, queryContext).deleteAsync()
1096
+ entityMutatorFactory
1097
+ .forDelete(fakeEntity, queryContext, privacyPolicyEvaluationContext)
1098
+ .deleteAsync()
1042
1099
  ).rejects.toEqual(rejectionError);
1043
1100
  });
1044
1101
 
1045
1102
  it('records metrics appropriately', async () => {
1046
1103
  const viewerContext = mock<ViewerContext>();
1104
+ const privacyPolicyEvaluationContext = instance(mock<EntityPrivacyPolicyEvaluationContext>());
1047
1105
  const queryContext = StubQueryContextProvider.getQueryContext();
1048
1106
  const { entityMutatorFactory, metricsAdapter } = createEntityMutatorFactory([]);
1049
1107
  const spiedMetricsAdapter = spy(metricsAdapter);
1050
1108
 
1051
1109
  const newEntity = await enforceAsyncResult(
1052
1110
  entityMutatorFactory
1053
- .forCreate(viewerContext, queryContext)
1111
+ .forCreate(viewerContext, queryContext, privacyPolicyEvaluationContext)
1054
1112
  .setField('stringField', 'huh')
1055
1113
  .createAsync()
1056
1114
  );
1057
1115
 
1058
1116
  await enforceAsyncResult(
1059
1117
  entityMutatorFactory
1060
- .forUpdate(newEntity, queryContext)
1118
+ .forUpdate(newEntity, queryContext, privacyPolicyEvaluationContext)
1061
1119
  .setField('stringField', 'wat')
1062
1120
  .updateAsync()
1063
1121
  );
1064
1122
 
1065
- await enforceAsyncResult(entityMutatorFactory.forDelete(newEntity, queryContext).deleteAsync());
1123
+ await enforceAsyncResult(
1124
+ entityMutatorFactory
1125
+ .forDelete(newEntity, queryContext, privacyPolicyEvaluationContext)
1126
+ .deleteAsync()
1127
+ );
1066
1128
 
1067
1129
  verify(
1068
1130
  spiedMetricsAdapter.logMutatorMutationEvent(