@expo/entity 0.23.0 → 0.25.1

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 (131) 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/EntityFieldDefinition.d.ts +8 -0
  12. package/build/EntityFieldDefinition.js +5 -0
  13. package/build/EntityFieldDefinition.js.map +1 -1
  14. package/build/EntityFields.d.ts +38 -0
  15. package/build/EntityFields.js +38 -0
  16. package/build/EntityFields.js.map +1 -1
  17. package/build/EntityLoader.d.ts +3 -2
  18. package/build/EntityLoader.js +5 -4
  19. package/build/EntityLoader.js.map +1 -1
  20. package/build/EntityLoaderFactory.d.ts +2 -2
  21. package/build/EntityLoaderFactory.js +2 -2
  22. package/build/EntityLoaderFactory.js.map +1 -1
  23. package/build/EntityMutationInfo.d.ts +12 -3
  24. package/build/EntityMutator.d.ts +5 -4
  25. package/build/EntityMutator.js +31 -24
  26. package/build/EntityMutator.js.map +1 -1
  27. package/build/EntityMutatorFactory.d.ts +4 -4
  28. package/build/EntityMutatorFactory.js +6 -6
  29. package/build/EntityMutatorFactory.js.map +1 -1
  30. package/build/EntityPrivacyPolicy.d.ts +15 -4
  31. package/build/EntityPrivacyPolicy.js +14 -14
  32. package/build/EntityPrivacyPolicy.js.map +1 -1
  33. package/build/GenericSecondaryEntityCache.d.ts +19 -0
  34. package/build/GenericSecondaryEntityCache.js +74 -0
  35. package/build/GenericSecondaryEntityCache.js.map +1 -0
  36. package/build/IEntityGenericCacher.d.ts +11 -0
  37. package/build/IEntityGenericCacher.js +3 -0
  38. package/build/IEntityGenericCacher.js.map +1 -0
  39. package/build/ReadonlyEntity.js +1 -1
  40. package/build/ReadonlyEntity.js.map +1 -1
  41. package/build/ViewerScopedEntityLoaderFactory.d.ts +2 -2
  42. package/build/ViewerScopedEntityLoaderFactory.js +2 -2
  43. package/build/ViewerScopedEntityLoaderFactory.js.map +1 -1
  44. package/build/ViewerScopedEntityMutatorFactory.d.ts +4 -4
  45. package/build/ViewerScopedEntityMutatorFactory.js +6 -6
  46. package/build/ViewerScopedEntityMutatorFactory.js.map +1 -1
  47. package/build/__tests__/ComposedCacheAdapter-test.d.ts +1 -0
  48. package/build/__tests__/ComposedCacheAdapter-test.js +198 -0
  49. package/build/__tests__/ComposedCacheAdapter-test.js.map +1 -0
  50. package/build/__tests__/ComposedSecondaryEntityCache-test.d.ts +1 -0
  51. package/build/__tests__/ComposedSecondaryEntityCache-test.js +65 -0
  52. package/build/__tests__/ComposedSecondaryEntityCache-test.js.map +1 -0
  53. package/build/__tests__/EntityCommonUseCases-test.js +1 -1
  54. package/build/__tests__/EntityCommonUseCases-test.js.map +1 -1
  55. package/build/__tests__/EntityEdges-test.js +260 -37
  56. package/build/__tests__/EntityEdges-test.js.map +1 -1
  57. package/build/__tests__/EntityLoader-constructor-test.js +2 -1
  58. package/build/__tests__/EntityLoader-constructor-test.js.map +1 -1
  59. package/build/__tests__/EntityLoader-test.js +19 -11
  60. package/build/__tests__/EntityLoader-test.js.map +1 -1
  61. package/build/__tests__/EntityMutator-test.js +96 -43
  62. package/build/__tests__/EntityMutator-test.js.map +1 -1
  63. package/build/__tests__/EntityPrivacyPolicy-test.js +23 -12
  64. package/build/__tests__/EntityPrivacyPolicy-test.js.map +1 -1
  65. package/build/__tests__/EntitySecondaryCacheLoader-test.js +1 -1
  66. package/build/__tests__/EntitySecondaryCacheLoader-test.js.map +1 -1
  67. package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js +3 -2
  68. package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js.map +1 -1
  69. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js +3 -2
  70. package/build/__tests__/ViewerScopedEntityMutatorFactory-test.js.map +1 -1
  71. package/build/index.d.ts +4 -0
  72. package/build/index.js +7 -1
  73. package/build/index.js.map +1 -1
  74. package/build/rules/AlwaysAllowPrivacyPolicyRule.d.ts +2 -1
  75. package/build/rules/AlwaysAllowPrivacyPolicyRule.js +1 -1
  76. package/build/rules/AlwaysAllowPrivacyPolicyRule.js.map +1 -1
  77. package/build/rules/AlwaysDenyPrivacyPolicyRule.d.ts +2 -1
  78. package/build/rules/AlwaysDenyPrivacyPolicyRule.js +1 -1
  79. package/build/rules/AlwaysDenyPrivacyPolicyRule.js.map +1 -1
  80. package/build/rules/AlwaysSkipPrivacyPolicyRule.d.ts +2 -1
  81. package/build/rules/AlwaysSkipPrivacyPolicyRule.js +1 -1
  82. package/build/rules/AlwaysSkipPrivacyPolicyRule.js.map +1 -1
  83. package/build/rules/PrivacyPolicyRule.d.ts +2 -1
  84. package/build/rules/PrivacyPolicyRule.js.map +1 -1
  85. package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js +1 -0
  86. package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js.map +1 -1
  87. package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js +1 -0
  88. package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js.map +1 -1
  89. package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js +1 -0
  90. package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js.map +1 -1
  91. package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +2 -0
  92. package/build/utils/testing/PrivacyPolicyRuleTestUtils.js +6 -6
  93. package/build/utils/testing/PrivacyPolicyRuleTestUtils.js.map +1 -1
  94. package/package.json +1 -1
  95. package/src/ComposedEntityCacheAdapter.ts +86 -0
  96. package/src/ComposedSecondaryEntityCache.ts +63 -0
  97. package/src/Entity.ts +6 -4
  98. package/src/EntityAssociationLoader.ts +4 -4
  99. package/src/EntityFieldDefinition.ts +8 -0
  100. package/src/EntityFields.ts +45 -0
  101. package/src/EntityLoader.ts +5 -1
  102. package/src/EntityLoaderFactory.ts +4 -2
  103. package/src/EntityMutationInfo.ts +13 -3
  104. package/src/EntityMutator.ts +44 -21
  105. package/src/EntityMutatorFactory.ts +10 -4
  106. package/src/EntityPrivacyPolicy.ts +31 -1
  107. package/src/GenericSecondaryEntityCache.ts +98 -0
  108. package/src/IEntityGenericCacher.ts +15 -0
  109. package/src/ReadonlyEntity.ts +1 -1
  110. package/src/ViewerScopedEntityLoaderFactory.ts +8 -3
  111. package/src/ViewerScopedEntityMutatorFactory.ts +22 -7
  112. package/src/__tests__/ComposedCacheAdapter-test.ts +280 -0
  113. package/src/__tests__/ComposedSecondaryEntityCache-test.ts +101 -0
  114. package/src/__tests__/EntityCommonUseCases-test.ts +2 -1
  115. package/src/__tests__/EntityEdges-test.ts +286 -45
  116. package/src/__tests__/EntityLoader-constructor-test.ts +3 -1
  117. package/src/__tests__/EntityLoader-test.ts +26 -1
  118. package/src/__tests__/EntityMutator-test.ts +99 -37
  119. package/src/__tests__/EntityPrivacyPolicy-test.ts +66 -7
  120. package/src/__tests__/EntitySecondaryCacheLoader-test.ts +1 -0
  121. package/src/__tests__/ViewerScopedEntityLoaderFactory-test.ts +4 -2
  122. package/src/__tests__/ViewerScopedEntityMutatorFactory-test.ts +6 -2
  123. package/src/index.ts +4 -0
  124. package/src/rules/AlwaysAllowPrivacyPolicyRule.ts +2 -0
  125. package/src/rules/AlwaysDenyPrivacyPolicyRule.ts +2 -0
  126. package/src/rules/AlwaysSkipPrivacyPolicyRule.ts +2 -0
  127. package/src/rules/PrivacyPolicyRule.ts +2 -0
  128. package/src/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.ts +2 -0
  129. package/src/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.ts +2 -0
  130. package/src/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.ts +2 -0
  131. package/src/utils/testing/PrivacyPolicyRuleTestUtils.ts +14 -6
@@ -13,6 +13,7 @@ const AlwaysAllowPrivacyPolicyRule_1 = __importDefault(require("../AlwaysAllowPr
13
13
  {
14
14
  viewerContext: (0, ts_mockito_1.instance)((0, ts_mockito_1.mock)(ViewerContext_1.default)),
15
15
  queryContext: (0, ts_mockito_1.instance)((0, ts_mockito_1.mock)(EntityQueryContext_1.EntityQueryContext)),
16
+ evaluationContext: (0, ts_mockito_1.instance)((0, ts_mockito_1.mock)()),
16
17
  entity: (0, ts_mockito_1.anything)(),
17
18
  },
18
19
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"AlwaysAllowPrivacyPolicyRule-test.js","sourceRoot":"","sources":["../../../src/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.ts"],"names":[],"mappings":";;;;;AAAA,2CAAsD;AAEtD,iEAA8D;AAC9D,wEAAgD;AAChD,+FAA2F;AAC3F,mGAA2E;AAE3E,IAAA,sDAAyB,EAAC,IAAI,sCAA4B,EAAE,EAAE;IAC5D,UAAU,EAAE;QACV;YACE,aAAa,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,EAAC,uBAAa,CAAC,CAAC;YAC5C,YAAY,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,EAAC,uCAAkB,CAAC,CAAC;YAChD,MAAM,EAAE,IAAA,qBAAQ,GAAE;SACnB;KACF;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"AlwaysAllowPrivacyPolicyRule-test.js","sourceRoot":"","sources":["../../../src/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.ts"],"names":[],"mappings":";;;;;AAAA,2CAAsD;AAGtD,iEAA8D;AAC9D,wEAAgD;AAChD,+FAA2F;AAC3F,mGAA2E;AAE3E,IAAA,sDAAyB,EAAC,IAAI,sCAA4B,EAAE,EAAE;IAC5D,UAAU,EAAE;QACV;YACE,aAAa,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,EAAC,uBAAa,CAAC,CAAC;YAC5C,YAAY,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,EAAC,uCAAkB,CAAC,CAAC;YAChD,iBAAiB,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,GAAwC,CAAC;YACzE,MAAM,EAAE,IAAA,qBAAQ,GAAE;SACnB;KACF;CACF,CAAC,CAAC"}
@@ -13,6 +13,7 @@ const AlwaysDenyPrivacyPolicyRule_1 = __importDefault(require("../AlwaysDenyPriv
13
13
  {
14
14
  viewerContext: (0, ts_mockito_1.instance)((0, ts_mockito_1.mock)(ViewerContext_1.default)),
15
15
  queryContext: (0, ts_mockito_1.instance)((0, ts_mockito_1.mock)(EntityQueryContext_1.EntityQueryContext)),
16
+ evaluationContext: (0, ts_mockito_1.instance)((0, ts_mockito_1.mock)()),
16
17
  entity: (0, ts_mockito_1.anything)(),
17
18
  },
18
19
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"AlwaysDenyPrivacyPolicyRule-test.js","sourceRoot":"","sources":["../../../src/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.ts"],"names":[],"mappings":";;;;;AAAA,2CAAsD;AAEtD,iEAA8D;AAC9D,wEAAgD;AAChD,+FAA2F;AAC3F,iGAAyE;AAEzE,IAAA,sDAAyB,EAAC,IAAI,qCAA2B,EAAE,EAAE;IAC3D,SAAS,EAAE;QACT;YACE,aAAa,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,EAAC,uBAAa,CAAC,CAAC;YAC5C,YAAY,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,EAAC,uCAAkB,CAAC,CAAC;YAChD,MAAM,EAAE,IAAA,qBAAQ,GAAE;SACnB;KACF;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"AlwaysDenyPrivacyPolicyRule-test.js","sourceRoot":"","sources":["../../../src/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.ts"],"names":[],"mappings":";;;;;AAAA,2CAAsD;AAGtD,iEAA8D;AAC9D,wEAAgD;AAChD,+FAA2F;AAC3F,iGAAyE;AAEzE,IAAA,sDAAyB,EAAC,IAAI,qCAA2B,EAAE,EAAE;IAC3D,SAAS,EAAE;QACT;YACE,aAAa,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,EAAC,uBAAa,CAAC,CAAC;YAC5C,YAAY,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,EAAC,uCAAkB,CAAC,CAAC;YAChD,iBAAiB,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,GAAwC,CAAC;YACzE,MAAM,EAAE,IAAA,qBAAQ,GAAE;SACnB;KACF;CACF,CAAC,CAAC"}
@@ -13,6 +13,7 @@ const AlwaysSkipPrivacyPolicyRule_1 = __importDefault(require("../AlwaysSkipPriv
13
13
  {
14
14
  viewerContext: (0, ts_mockito_1.instance)((0, ts_mockito_1.mock)(ViewerContext_1.default)),
15
15
  queryContext: (0, ts_mockito_1.instance)((0, ts_mockito_1.mock)(EntityQueryContext_1.EntityQueryContext)),
16
+ evaluationContext: (0, ts_mockito_1.instance)((0, ts_mockito_1.mock)()),
16
17
  entity: (0, ts_mockito_1.anything)(),
17
18
  },
18
19
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"AlwaysSkipPrivacyPolicyRule-test.js","sourceRoot":"","sources":["../../../src/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.ts"],"names":[],"mappings":";;;;;AAAA,2CAAsD;AAEtD,iEAA8D;AAC9D,wEAAgD;AAChD,+FAA2F;AAC3F,iGAAyE;AAEzE,IAAA,sDAAyB,EAAC,IAAI,qCAA2B,EAAE,EAAE;IAC3D,SAAS,EAAE;QACT;YACE,aAAa,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,EAAC,uBAAa,CAAC,CAAC;YAC5C,YAAY,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,EAAC,uCAAkB,CAAC,CAAC;YAChD,MAAM,EAAE,IAAA,qBAAQ,GAAE;SACnB;KACF;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"AlwaysSkipPrivacyPolicyRule-test.js","sourceRoot":"","sources":["../../../src/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.ts"],"names":[],"mappings":";;;;;AAAA,2CAAsD;AAGtD,iEAA8D;AAC9D,wEAAgD;AAChD,+FAA2F;AAC3F,iGAAyE;AAEzE,IAAA,sDAAyB,EAAC,IAAI,qCAA2B,EAAE,EAAE;IAC3D,SAAS,EAAE;QACT;YACE,aAAa,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,EAAC,uBAAa,CAAC,CAAC;YAC5C,YAAY,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,EAAC,uCAAkB,CAAC,CAAC;YAChD,iBAAiB,EAAE,IAAA,qBAAQ,EAAC,IAAA,iBAAI,GAAwC,CAAC;YACzE,MAAM,EAAE,IAAA,qBAAQ,GAAE;SACnB;KACF;CACF,CAAC,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { EntityPrivacyPolicyEvaluationContext } from '../../EntityPrivacyPolicy';
1
2
  import { EntityQueryContext } from '../../EntityQueryContext';
2
3
  import ReadonlyEntity from '../../ReadonlyEntity';
3
4
  import ViewerContext from '../../ViewerContext';
@@ -5,6 +6,7 @@ import PrivacyPolicyRule from '../../rules/PrivacyPolicyRule';
5
6
  export interface Case<TFields, TID extends NonNullable<TFields[TSelectedFields]>, TViewerContext extends ViewerContext, TEntity extends ReadonlyEntity<TFields, TID, TViewerContext, TSelectedFields>, TSelectedFields extends keyof TFields> {
6
7
  viewerContext: TViewerContext;
7
8
  queryContext: EntityQueryContext;
9
+ evaluationContext: EntityPrivacyPolicyEvaluationContext;
8
10
  entity: TEntity;
9
11
  }
10
12
  declare type CaseMap<TFields, TID extends NonNullable<TFields[TSelectedFields]>, TViewerContext extends ViewerContext, TEntity extends ReadonlyEntity<TFields, TID, TViewerContext, TSelectedFields>, TSelectedFields extends keyof TFields> = Map<string, () => Promise<Case<TFields, TID, TViewerContext, TEntity, TSelectedFields>>>;
@@ -10,24 +10,24 @@ const describePrivacyPolicyRuleWithAsyncTestCase = (privacyPolicyRule, { allowCa
10
10
  if (allowCases && allowCases.size > 0) {
11
11
  describe('allow cases', () => {
12
12
  test.each(Array.from(allowCases.keys()))('%p', async (caseKey) => {
13
- const { viewerContext, queryContext, entity } = await allowCases.get(caseKey)();
14
- await expect(privacyPolicyRule.evaluateAsync(viewerContext, queryContext, entity)).resolves.toEqual(PrivacyPolicyRule_1.RuleEvaluationResult.ALLOW);
13
+ const { viewerContext, queryContext, evaluationContext, entity } = await allowCases.get(caseKey)();
14
+ await expect(privacyPolicyRule.evaluateAsync(viewerContext, queryContext, evaluationContext, entity)).resolves.toEqual(PrivacyPolicyRule_1.RuleEvaluationResult.ALLOW);
15
15
  });
16
16
  });
17
17
  }
18
18
  if (skipCases && skipCases.size > 0) {
19
19
  describe('skip cases', () => {
20
20
  test.each(Array.from(skipCases.keys()))('%p', async (caseKey) => {
21
- const { viewerContext, queryContext, entity } = await skipCases.get(caseKey)();
22
- await expect(privacyPolicyRule.evaluateAsync(viewerContext, queryContext, entity)).resolves.toEqual(PrivacyPolicyRule_1.RuleEvaluationResult.SKIP);
21
+ const { viewerContext, queryContext, evaluationContext, entity } = await skipCases.get(caseKey)();
22
+ await expect(privacyPolicyRule.evaluateAsync(viewerContext, queryContext, evaluationContext, entity)).resolves.toEqual(PrivacyPolicyRule_1.RuleEvaluationResult.SKIP);
23
23
  });
24
24
  });
25
25
  }
26
26
  if (denyCases && denyCases.size > 0) {
27
27
  describe('deny cases', () => {
28
28
  test.each(Array.from(denyCases.keys()))('%p', async (caseKey) => {
29
- const { viewerContext, queryContext, entity } = await denyCases.get(caseKey)();
30
- await expect(privacyPolicyRule.evaluateAsync(viewerContext, queryContext, entity)).resolves.toEqual(PrivacyPolicyRule_1.RuleEvaluationResult.DENY);
29
+ const { viewerContext, queryContext, evaluationContext, entity } = await denyCases.get(caseKey)();
30
+ await expect(privacyPolicyRule.evaluateAsync(viewerContext, queryContext, evaluationContext, entity)).resolves.toEqual(PrivacyPolicyRule_1.RuleEvaluationResult.DENY);
31
31
  });
32
32
  });
33
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PrivacyPolicyRuleTestUtils.js","sourceRoot":"","sources":["../../../src/utils/testing/PrivacyPolicyRuleTestUtils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PrivacyPolicyRuleTestUtils.js","sourceRoot":"","sources":["../../../src/utils/testing/PrivacyPolicyRuleTestUtils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/entity",
3
- "version": "0.23.0",
3
+ "version": "0.25.1",
4
4
  "description": "A privacy-first data model",
5
5
  "files": [
6
6
  "build",
@@ -0,0 +1,86 @@
1
+ import nullthrows from 'nullthrows';
2
+
3
+ import EntityCacheAdapter from './EntityCacheAdapter';
4
+ import EntityConfiguration from './EntityConfiguration';
5
+ import { CacheStatus, CacheLoadResult } from './internal/ReadThroughEntityCache';
6
+
7
+ export default class ComposedEntityCacheAdapter<TFields> extends EntityCacheAdapter<TFields> {
8
+ /**
9
+ * A {@link EntityCacheAdapter} that composes other {@link EntityCacheAdapter} instances.
10
+ *
11
+ * @param entityConfiguration - configuration for entity being loaded
12
+ * @param cacheAdapters - list of cache adapters to compose in order of precedence.
13
+ * Earlier cache adapters are read from first and written to (including invalidations) last.
14
+ * Typically, caches closer to the application should be ordered before caches closer to the database.
15
+ */
16
+ constructor(
17
+ entityConfiguration: EntityConfiguration<TFields>,
18
+ private readonly cacheAdapters: EntityCacheAdapter<TFields>[]
19
+ ) {
20
+ super(entityConfiguration);
21
+ }
22
+
23
+ public async loadManyAsync<N extends keyof TFields>(
24
+ fieldName: N,
25
+ fieldValues: readonly NonNullable<TFields[N]>[]
26
+ ): Promise<ReadonlyMap<NonNullable<TFields[N]>, CacheLoadResult<TFields>>> {
27
+ const retMap = new Map<NonNullable<TFields[N]>, CacheLoadResult<TFields>>();
28
+
29
+ let unfulfilledFieldValues = fieldValues;
30
+ for (const cacheAdapter of this.cacheAdapters) {
31
+ const cacheResultsFromAdapter = await cacheAdapter.loadManyAsync(
32
+ fieldName,
33
+ unfulfilledFieldValues
34
+ );
35
+
36
+ const newUnfulfilledFieldValues = [];
37
+ for (const [fieldValue, cacheResult] of cacheResultsFromAdapter) {
38
+ if (cacheResult.status === CacheStatus.MISS) {
39
+ newUnfulfilledFieldValues.push(fieldValue);
40
+ } else {
41
+ retMap.set(fieldValue, cacheResult);
42
+ }
43
+ }
44
+ unfulfilledFieldValues = newUnfulfilledFieldValues;
45
+ }
46
+
47
+ for (const fieldValue of unfulfilledFieldValues) {
48
+ retMap.set(fieldValue, { status: CacheStatus.MISS });
49
+ }
50
+
51
+ return retMap;
52
+ }
53
+
54
+ public async cacheManyAsync<N extends keyof TFields>(
55
+ fieldName: N,
56
+ objectMap: ReadonlyMap<NonNullable<TFields[N]>, Readonly<TFields>>
57
+ ): Promise<void> {
58
+ // write to lower layers first
59
+ for (let i = this.cacheAdapters.length - 1; i >= 0; i--) {
60
+ const cacheAdapter = nullthrows(this.cacheAdapters[i]);
61
+ await cacheAdapter.cacheManyAsync(fieldName, objectMap);
62
+ }
63
+ }
64
+
65
+ public async cacheDBMissesAsync<N extends keyof TFields>(
66
+ fieldName: N,
67
+ fieldValues: readonly NonNullable<TFields[N]>[]
68
+ ): Promise<void> {
69
+ // write to lower layers first
70
+ for (let i = this.cacheAdapters.length - 1; i >= 0; i--) {
71
+ const cacheAdapter = nullthrows(this.cacheAdapters[i]);
72
+ await cacheAdapter.cacheDBMissesAsync(fieldName, fieldValues);
73
+ }
74
+ }
75
+
76
+ public async invalidateManyAsync<N extends keyof TFields>(
77
+ fieldName: N,
78
+ fieldValues: readonly NonNullable<TFields[N]>[]
79
+ ): Promise<void> {
80
+ // delete from lower layers first
81
+ for (let i = this.cacheAdapters.length - 1; i >= 0; i--) {
82
+ const cacheAdapter = nullthrows(this.cacheAdapters[i]);
83
+ await cacheAdapter.invalidateManyAsync(fieldName, fieldValues);
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,63 @@
1
+ import nullthrows from 'nullthrows';
2
+
3
+ import { ISecondaryEntityCache } from './EntitySecondaryCacheLoader';
4
+
5
+ export default class ComposedSecondaryEntityCache<TLoadParams, TFields>
6
+ implements ISecondaryEntityCache<TFields, TLoadParams>
7
+ {
8
+ /**
9
+ * A {@link ISecondaryEntityCache} that composes other {@link ISecondaryEntityCache} instances.
10
+ *
11
+ * @param secondaryEntityCaches - list of caches to compose in order of precedence.
12
+ * Earlier caches are read from first and written to (including invalidations) last.
13
+ * Typically, caches closer to the application should be ordered before caches closer to the database.
14
+ */
15
+ constructor(
16
+ private readonly secondaryEntityCaches: ISecondaryEntityCache<TFields, TLoadParams>[]
17
+ ) {}
18
+
19
+ async loadManyThroughAsync(
20
+ loadParamsArray: readonly Readonly<TLoadParams>[],
21
+ fetcher: (
22
+ fetcherLoadParamsArray: readonly Readonly<TLoadParams>[]
23
+ ) => Promise<ReadonlyMap<Readonly<TLoadParams>, Readonly<TFields> | null>>
24
+ ): Promise<ReadonlyMap<Readonly<TLoadParams>, Readonly<TFields> | null>> {
25
+ return await ComposedSecondaryEntityCache.loadManyThroughRecursivelyAsync(
26
+ this.secondaryEntityCaches,
27
+ loadParamsArray,
28
+ fetcher
29
+ );
30
+ }
31
+
32
+ private static async loadManyThroughRecursivelyAsync<TLoadParams, TFields>(
33
+ secondaryEntityCaches: ISecondaryEntityCache<TFields, TLoadParams>[],
34
+ loadParamsArray: readonly Readonly<TLoadParams>[],
35
+ fetcher: (
36
+ fetcherLoadParamsArray: readonly Readonly<TLoadParams>[]
37
+ ) => Promise<ReadonlyMap<Readonly<TLoadParams>, Readonly<TFields> | null>>
38
+ ): Promise<ReadonlyMap<Readonly<TLoadParams>, Readonly<TFields> | null>> {
39
+ if (secondaryEntityCaches.length === 0) {
40
+ return await fetcher(loadParamsArray);
41
+ }
42
+
43
+ const [firstCache, ...restCaches] = secondaryEntityCaches;
44
+
45
+ return await nullthrows(firstCache).loadManyThroughAsync(
46
+ loadParamsArray,
47
+ (fetcherLoadParamsArray) =>
48
+ ComposedSecondaryEntityCache.loadManyThroughRecursivelyAsync(
49
+ restCaches,
50
+ fetcherLoadParamsArray,
51
+ fetcher
52
+ )
53
+ );
54
+ }
55
+
56
+ async invalidateManyAsync(loadParamsArray: readonly Readonly<TLoadParams>[]): Promise<void> {
57
+ // invalidate lower layers first
58
+ for (let i = this.secondaryEntityCaches.length - 1; i >= 0; i--) {
59
+ const secondaryEntityCache = nullthrows(this.secondaryEntityCaches[i]);
60
+ await secondaryEntityCache.invalidateManyAsync(loadParamsArray);
61
+ }
62
+ }
63
+ }
package/src/Entity.ts CHANGED
@@ -69,7 +69,7 @@ export default abstract class Entity<
69
69
  return viewerContext
70
70
  .getViewerScopedEntityCompanionForClass(this)
71
71
  .getMutatorFactory()
72
- .forCreate(queryContext);
72
+ .forCreate(queryContext, { cascadingDeleteCause: null });
73
73
  }
74
74
 
75
75
  /**
@@ -111,7 +111,7 @@ export default abstract class Entity<
111
111
  .getViewerContext()
112
112
  .getViewerScopedEntityCompanionForClass(this)
113
113
  .getMutatorFactory()
114
- .forUpdate(existingEntity, queryContext);
114
+ .forUpdate(existingEntity, queryContext, { cascadingDeleteCause: null });
115
115
  }
116
116
 
117
117
  /**
@@ -152,7 +152,7 @@ export default abstract class Entity<
152
152
  .getViewerContext()
153
153
  .getViewerScopedEntityCompanionForClass(this)
154
154
  .getMutatorFactory()
155
- .forDelete(existingEntity, queryContext)
155
+ .forDelete(existingEntity, queryContext, { cascadingDeleteCause: null })
156
156
  .deleteAsync();
157
157
  }
158
158
 
@@ -194,7 +194,7 @@ export default abstract class Entity<
194
194
  .getViewerContext()
195
195
  .getViewerScopedEntityCompanionForClass(this)
196
196
  .getMutatorFactory()
197
- .forDelete(existingEntity, queryContext)
197
+ .forDelete(existingEntity, queryContext, { cascadingDeleteCause: null })
198
198
  .enforceDeleteAsync();
199
199
  }
200
200
 
@@ -251,6 +251,7 @@ export default abstract class Entity<
251
251
  privacyPolicy.authorizeUpdateAsync(
252
252
  existingEntity.getViewerContext(),
253
253
  queryContext,
254
+ { cascadingDeleteCause: null },
254
255
  existingEntity,
255
256
  companion.getMetricsAdapter()
256
257
  )
@@ -304,6 +305,7 @@ export default abstract class Entity<
304
305
  privacyPolicy.authorizeDeleteAsync(
305
306
  existingEntity.getViewerContext(),
306
307
  queryContext,
308
+ { cascadingDeleteCause: null },
307
309
  existingEntity,
308
310
  companion.getMetricsAdapter()
309
311
  )
@@ -69,7 +69,7 @@ export default class EntityAssociationLoader<
69
69
  .getViewerContext()
70
70
  .getViewerScopedEntityCompanionForClass(associatedEntityClass)
71
71
  .getLoaderFactory()
72
- .forLoad(queryContext);
72
+ .forLoad(queryContext, { cascadingDeleteCause: null });
73
73
 
74
74
  return (await loader.loadByIDAsync(associatedEntityID as unknown as TAssociatedID)) as Result<
75
75
  null extends TFields[TIdentifyingField] ? TAssociatedEntity | null : TAssociatedEntity
@@ -123,7 +123,7 @@ export default class EntityAssociationLoader<
123
123
  .getViewerContext()
124
124
  .getViewerScopedEntityCompanionForClass(associatedEntityClass)
125
125
  .getLoaderFactory()
126
- .forLoad(queryContext);
126
+ .forLoad(queryContext, { cascadingDeleteCause: null });
127
127
  return await loader.loadManyByFieldEqualingAsync(
128
128
  associatedEntityFieldContainingThisID,
129
129
  thisID as any
@@ -180,7 +180,7 @@ export default class EntityAssociationLoader<
180
180
  .getViewerContext()
181
181
  .getViewerScopedEntityCompanionForClass(associatedEntityClass)
182
182
  .getLoaderFactory()
183
- .forLoad(queryContext);
183
+ .forLoad(queryContext, { cascadingDeleteCause: null });
184
184
  return await loader.loadByFieldEqualingAsync(
185
185
  associatedEntityLookupByField,
186
186
  associatedFieldValue as any
@@ -238,7 +238,7 @@ export default class EntityAssociationLoader<
238
238
  .getViewerContext()
239
239
  .getViewerScopedEntityCompanionForClass(associatedEntityClass)
240
240
  .getLoaderFactory()
241
- .forLoad(queryContext);
241
+ .forLoad(queryContext, { cascadingDeleteCause: null });
242
242
  return await loader.loadManyByFieldEqualingAsync(
243
243
  associatedEntityLookupByField,
244
244
  associatedFieldValue as any
@@ -28,6 +28,9 @@ export enum EntityEdgeDeletionBehavior {
28
28
  SET_NULL,
29
29
  }
30
30
 
31
+ /**
32
+ * Defines an association between entities. An association is primarily used to define cascading deletion behavior.
33
+ */
31
34
  export interface EntityAssociationDefinition<
32
35
  TViewerContext extends ViewerContext,
33
36
  TAssociatedFields,
@@ -83,6 +86,10 @@ export interface EntityAssociationDefinition<
83
86
  edgeDeletionBehavior?: EntityEdgeDeletionBehavior;
84
87
  }
85
88
 
89
+ /**
90
+ * Definition for a field referencing a column in the underlying database. Specifies things like
91
+ * cache behavior and associations, and handles input validation.
92
+ */
86
93
  export abstract class EntityFieldDefinition<T> {
87
94
  readonly columnName: string;
88
95
  readonly cache: boolean;
@@ -93,6 +100,7 @@ export abstract class EntityFieldDefinition<T> {
93
100
  * @param cache - Whether or not to cache loaded instances of the entity by this field. The column name is
94
101
  * used to derive a cache key for the cache entry. If true, this column must be able uniquely
95
102
  * identify the entity.
103
+ * @param association - Defines the association behavior for an entity that this column references.
96
104
  */
97
105
  constructor({
98
106
  columnName,
@@ -2,59 +2,104 @@ import { validate as validateUUID } from 'uuid';
2
2
 
3
3
  import { EntityFieldDefinition } from './EntityFieldDefinition';
4
4
 
5
+ /**
6
+ * {@link EntityFieldDefinition} for a column with a JS string type.
7
+ */
5
8
  export class StringField extends EntityFieldDefinition<string> {
6
9
  protected validateInputValueInternal(value: string): boolean {
7
10
  return typeof value === 'string';
8
11
  }
9
12
  }
13
+
14
+ /**
15
+ * {@link EntityFieldDefinition} for a column with a JS string type.
16
+ * Enforces that the string is a valid UUID.
17
+ */
10
18
  export class UUIDField extends StringField {
11
19
  protected override validateInputValueInternal(value: string): boolean {
12
20
  return validateUUID(value);
13
21
  }
14
22
  }
23
+
24
+ /**
25
+ * {@link EntityFieldDefinition} for a column with a JS Date type.
26
+ */
15
27
  export class DateField extends EntityFieldDefinition<Date> {
16
28
  protected validateInputValueInternal(value: Date): boolean {
17
29
  return value instanceof Date;
18
30
  }
19
31
  }
32
+
33
+ /**
34
+ * {@link EntityFieldDefinition} for a column with a JS boolean type.
35
+ */
20
36
  export class BooleanField extends EntityFieldDefinition<boolean> {
21
37
  protected validateInputValueInternal(value: boolean): boolean {
22
38
  return typeof value === 'boolean';
23
39
  }
24
40
  }
25
41
 
42
+ /**
43
+ * {@link EntityFieldDefinition} for a column with a JS number type.
44
+ * Enforces that the number is an integer.
45
+ */
26
46
  export class IntField extends EntityFieldDefinition<number> {
27
47
  protected validateInputValueInternal(value: number): boolean {
28
48
  return typeof value === 'number' && Number.isInteger(value);
29
49
  }
30
50
  }
31
51
 
52
+ /**
53
+ * {@link EntityFieldDefinition} for a column with a JS number type.
54
+ * Enforces that the number is a float (which includes integers in JS).
55
+ */
32
56
  export class FloatField extends EntityFieldDefinition<number> {
33
57
  protected validateInputValueInternal(value: number): boolean {
34
58
  return typeof value === 'number';
35
59
  }
36
60
  }
37
61
 
62
+ /**
63
+ * {@link EntityFieldDefinition} for a column with a JS string array type.
64
+ * Enforces that every member of the string array is a string.
65
+ */
38
66
  export class StringArrayField extends EntityFieldDefinition<string[]> {
39
67
  protected validateInputValueInternal(value: string[]): boolean {
40
68
  return Array.isArray(value) && value.every((subValue) => typeof subValue === 'string');
41
69
  }
42
70
  }
71
+
72
+ /**
73
+ * {@link EntityFieldDefinition} for a column with a JS JSON object type.
74
+ */
43
75
  export class JSONObjectField extends EntityFieldDefinition<object> {
44
76
  protected validateInputValueInternal(value: object): boolean {
45
77
  return typeof value === 'object' && !Array.isArray(value);
46
78
  }
47
79
  }
80
+
81
+ /**
82
+ * {@link EntityFieldDefinition} for a enum column with a JS string or number type.
83
+ */
48
84
  export class EnumField extends EntityFieldDefinition<string | number> {
49
85
  protected validateInputValueInternal(value: string | number): boolean {
50
86
  return typeof value === 'number' || typeof value === 'string';
51
87
  }
52
88
  }
89
+
90
+ /**
91
+ * {@link EntityFieldDefinition} for a column with a JS JSON array type.
92
+ */
53
93
  export class JSONArrayField extends EntityFieldDefinition<any[]> {
54
94
  protected validateInputValueInternal(value: any[]): boolean {
55
95
  return Array.isArray(value);
56
96
  }
57
97
  }
98
+
99
+ /**
100
+ * {@link EntityFieldDefinition} for a column that may be a JS JSON array type.
101
+ * Does not do any validation.
102
+ */
58
103
  export class MaybeJSONArrayField extends EntityFieldDefinition<any | any[]> {
59
104
  protected validateInputValueInternal(_value: any): boolean {
60
105
  return true;
@@ -9,7 +9,7 @@ import {
9
9
  QuerySelectionModifiers,
10
10
  isSingleValueFieldEqualityCondition,
11
11
  } from './EntityDatabaseAdapter';
12
- import EntityPrivacyPolicy from './EntityPrivacyPolicy';
12
+ import EntityPrivacyPolicy, { EntityPrivacyPolicyEvaluationContext } from './EntityPrivacyPolicy';
13
13
  import { EntityQueryContext } from './EntityQueryContext';
14
14
  import ReadonlyEntity from './ReadonlyEntity';
15
15
  import ViewerContext from './ViewerContext';
@@ -40,6 +40,7 @@ export default class EntityLoader<
40
40
  constructor(
41
41
  private readonly viewerContext: TViewerContext,
42
42
  private readonly queryContext: EntityQueryContext,
43
+ private readonly privacyPolicyEvaluationContext: EntityPrivacyPolicyEvaluationContext,
43
44
  private readonly entityConfiguration: EntityConfiguration<TFields>,
44
45
  private readonly entityClass: IEntityClass<
45
46
  TFields,
@@ -218,6 +219,7 @@ export default class EntityLoader<
218
219
  this.privacyPolicy.authorizeReadAsync(
219
220
  this.viewerContext,
220
221
  this.queryContext,
222
+ this.privacyPolicyEvaluationContext,
221
223
  uncheckedEntityResult.value,
222
224
  this.metricsAdapter
223
225
  )
@@ -272,6 +274,7 @@ export default class EntityLoader<
272
274
  this.privacyPolicy.authorizeReadAsync(
273
275
  this.viewerContext,
274
276
  this.queryContext,
277
+ this.privacyPolicyEvaluationContext,
275
278
  uncheckedEntityResult.value,
276
279
  this.metricsAdapter
277
280
  )
@@ -332,6 +335,7 @@ export default class EntityLoader<
332
335
  this.privacyPolicy.authorizeReadAsync(
333
336
  this.viewerContext,
334
337
  this.queryContext,
338
+ this.privacyPolicyEvaluationContext,
335
339
  uncheckedEntityResult.value,
336
340
  this.metricsAdapter
337
341
  )
@@ -1,7 +1,7 @@
1
1
  import { IEntityClass } from './Entity';
2
2
  import EntityConfiguration from './EntityConfiguration';
3
3
  import EntityLoader from './EntityLoader';
4
- import EntityPrivacyPolicy from './EntityPrivacyPolicy';
4
+ import EntityPrivacyPolicy, { EntityPrivacyPolicyEvaluationContext } from './EntityPrivacyPolicy';
5
5
  import { EntityQueryContext } from './EntityQueryContext';
6
6
  import ReadonlyEntity from './ReadonlyEntity';
7
7
  import ViewerContext from './ViewerContext';
@@ -47,11 +47,13 @@ export default class EntityLoaderFactory<
47
47
  */
48
48
  forLoad(
49
49
  viewerContext: TViewerContext,
50
- queryContext: EntityQueryContext
50
+ queryContext: EntityQueryContext,
51
+ privacyPolicyEvaluationContext: EntityPrivacyPolicyEvaluationContext
51
52
  ): EntityLoader<TFields, TID, TViewerContext, TEntity, TPrivacyPolicy, TSelectedFields> {
52
53
  return new EntityLoader(
53
54
  viewerContext,
54
55
  queryContext,
56
+ privacyPolicyEvaluationContext,
55
57
  this.entityConfiguration,
56
58
  this.entityClass,
57
59
  this.privacyPolicyClass,
@@ -22,9 +22,19 @@ export type EntityValidatorMutationInfo<
22
22
  previousValue: TEntity;
23
23
  };
24
24
 
25
- export type EntityMutationTriggerDeleteCascadeInfo<> = {
25
+ /**
26
+ * Information about a cascading deletion.
27
+ */
28
+ export type EntityCascadingDeletionInfo = {
29
+ /**
30
+ * The entity that is being mutated at this step in the cascaded deletion.
31
+ */
26
32
  entity: Entity<any, any, any, any>;
27
- cascadingDeleteCause: EntityMutationTriggerDeleteCascadeInfo | null;
33
+
34
+ /**
35
+ * The cascade deletion that caused this mutation.
36
+ */
37
+ cascadingDeleteCause: EntityCascadingDeletionInfo | null;
28
38
  };
29
39
 
30
40
  export type EntityTriggerMutationInfo<
@@ -43,5 +53,5 @@ export type EntityTriggerMutationInfo<
43
53
  }
44
54
  | {
45
55
  type: EntityMutationType.DELETE;
46
- cascadingDeleteCause: EntityMutationTriggerDeleteCascadeInfo | null;
56
+ cascadingDeleteCause: EntityCascadingDeletionInfo | null;
47
57
  };