diff --git a/src/cache/inmemory/__tests__/diffAgainstStore.ts b/src/cache/inmemory/__tests__/diffAgainstStore.ts index ced01a858b7..d3ea1fb7aa5 100644 --- a/src/cache/inmemory/__tests__/diffAgainstStore.ts +++ b/src/cache/inmemory/__tests__/diffAgainstStore.ts @@ -1,7 +1,7 @@ import gql, { disableFragmentWarnings } from 'graphql-tag'; import { Reference, makeReference, isReference } from '../../../utilities/graphql/storeUtils'; -import { defaultNormalizedCacheFactory } from '../entityCache'; +import { defaultNormalizedCacheFactory } from '../entityStore'; import { StoreReader } from '../readFromStore'; import { StoreWriter } from '../writeToStore'; import { defaultDataIdFromObject } from '../policies'; diff --git a/src/cache/inmemory/__tests__/entityCache.ts b/src/cache/inmemory/__tests__/entityStore.ts similarity index 96% rename from src/cache/inmemory/__tests__/entityCache.ts rename to src/cache/inmemory/__tests__/entityStore.ts index eda02e0357a..f64d1c4f53c 100644 --- a/src/cache/inmemory/__tests__/entityCache.ts +++ b/src/cache/inmemory/__tests__/entityStore.ts @@ -1,22 +1,22 @@ import gql from 'graphql-tag'; -import { EntityCache, supportsResultCaching } from '../entityCache'; +import { EntityStore, supportsResultCaching } from '../entityStore'; import { InMemoryCache } from '../inMemoryCache'; -describe('EntityCache', () => { +describe('EntityStore', () => { it('should support result caching if so configured', () => { - const cacheWithResultCaching = new EntityCache.Root({ + const storeWithResultCaching = new EntityStore.Root({ resultCaching: true, }); - const cacheWithoutResultCaching = new EntityCache.Root({ + const storeWithoutResultCaching = new EntityStore.Root({ resultCaching: false, }); expect(supportsResultCaching({ some: "arbitrary object " })).toBe(false); - expect(supportsResultCaching(cacheWithResultCaching)).toBe(true); - expect(supportsResultCaching(cacheWithoutResultCaching)).toBe(false); + expect(supportsResultCaching(storeWithResultCaching)).toBe(true); + expect(supportsResultCaching(storeWithoutResultCaching)).toBe(false); - const layerWithCaching = cacheWithResultCaching.addLayer("with caching", () => {}); + const layerWithCaching = storeWithResultCaching.addLayer("with caching", () => {}); expect(supportsResultCaching(layerWithCaching)).toBe(true); const anotherLayer = layerWithCaching.addLayer("another layer", () => {}); expect(supportsResultCaching(anotherLayer)).toBe(true); @@ -24,13 +24,13 @@ describe('EntityCache', () => { anotherLayer .removeLayer("with caching") .removeLayer("another layer") - ).toBe(cacheWithResultCaching); - expect(supportsResultCaching(cacheWithResultCaching)).toBe(true); + ).toBe(storeWithResultCaching); + expect(supportsResultCaching(storeWithResultCaching)).toBe(true); - const layerWithoutCaching = cacheWithoutResultCaching.addLayer("with caching", () => {}); + const layerWithoutCaching = storeWithoutResultCaching.addLayer("with caching", () => {}); expect(supportsResultCaching(layerWithoutCaching)).toBe(false); - expect(layerWithoutCaching.removeLayer("with caching")).toBe(cacheWithoutResultCaching); - expect(supportsResultCaching(cacheWithoutResultCaching)).toBe(false); + expect(layerWithoutCaching.removeLayer("with caching")).toBe(storeWithoutResultCaching); + expect(supportsResultCaching(storeWithoutResultCaching)).toBe(false); }); function newBookAuthorCache() { diff --git a/src/cache/inmemory/__tests__/readFromStore.ts b/src/cache/inmemory/__tests__/readFromStore.ts index 8ac5a6934a7..3fa359b5bca 100644 --- a/src/cache/inmemory/__tests__/readFromStore.ts +++ b/src/cache/inmemory/__tests__/readFromStore.ts @@ -5,7 +5,7 @@ import { stripSymbols } from '../../../utilities/testing/stripSymbols'; import { StoreObject } from '../types'; import { StoreReader } from '../readFromStore'; import { makeReference } from '../../../utilities/graphql/storeUtils'; -import { defaultNormalizedCacheFactory } from '../entityCache'; +import { defaultNormalizedCacheFactory } from '../entityStore'; import { withError } from './diffAgainstStore'; import { Policies } from '../policies'; diff --git a/src/cache/inmemory/__tests__/recordingCache.ts b/src/cache/inmemory/__tests__/recordingCache.ts index f270b54f4b3..cf75417078d 100644 --- a/src/cache/inmemory/__tests__/recordingCache.ts +++ b/src/cache/inmemory/__tests__/recordingCache.ts @@ -1,8 +1,8 @@ import { NormalizedCacheObject } from '../types'; -import { EntityCache } from '../entityCache'; +import { EntityStore } from '../entityStore'; -describe('OptimisticCacheLayer', () => { - function makeLayer(root: EntityCache) { +describe('Optimistic EntityStore layering', () => { + function makeLayer(root: EntityStore) { return root.addLayer('whatever', () => {}); } @@ -16,31 +16,31 @@ describe('OptimisticCacheLayer', () => { Human: { __typename: 'Human', name: 'John' }, }; - const underlyingCache = new EntityCache.Root({ seed: data }); + const underlyingStore = new EntityStore.Root({ seed: data }); - let cache = makeLayer(underlyingCache); + let store = makeLayer(underlyingStore); beforeEach(() => { - cache = makeLayer(underlyingCache); + store = makeLayer(underlyingStore); }); it('should passthrough values if not defined in recording', () => { - expect(cache.get('Human')).toBe(data.Human); - expect(cache.get('Animal')).toBe(data.Animal); + expect(store.get('Human')).toBe(data.Human); + expect(store.get('Animal')).toBe(data.Animal); }); it('should return values defined during recording', () => { - cache.merge('Human', dataToRecord.Human); - expect(cache.get('Human')).toEqual(dataToRecord.Human); - expect(underlyingCache.get('Human')).toBe(data.Human); + store.merge('Human', dataToRecord.Human); + expect(store.get('Human')).toEqual(dataToRecord.Human); + expect(underlyingStore.get('Human')).toBe(data.Human); }); it('should return undefined for values deleted during recording', () => { - expect(cache.get('Animal')).toBe(data.Animal); + expect(store.get('Animal')).toBe(data.Animal); // delete should be registered in the recording: - cache.delete('Animal'); - expect(cache.get('Animal')).toBeUndefined(); - expect(cache.toObject()).toHaveProperty('Animal'); - expect(underlyingCache.get('Animal')).toBe(data.Animal); + store.delete('Animal'); + expect(store.get('Animal')).toBeUndefined(); + expect(store.toObject()).toHaveProperty('Animal'); + expect(underlyingStore.get('Animal')).toBe(data.Animal); }); }); @@ -54,15 +54,15 @@ describe('OptimisticCacheLayer', () => { Human: { __typename: 'Human', name: 'John' }, }; - const underlyingCache = new EntityCache.Root({ seed: data }); - let cache = makeLayer(underlyingCache); + const underlyingStore = new EntityStore.Root({ seed: data }); + let store = makeLayer(underlyingStore); let recording: NormalizedCacheObject; beforeEach(() => { - cache = makeLayer(underlyingCache); - cache.merge('Human', dataToRecord.Human); - cache.delete('Animal'); - recording = cache.toObject(); + store = makeLayer(underlyingStore); + store.merge('Human', dataToRecord.Human); + store.delete('Animal'); + recording = store.toObject(); }); it('should contain the property indicating deletion', () => { @@ -77,7 +77,7 @@ describe('OptimisticCacheLayer', () => { }); it('should keep the original data unaffected', () => { - expect(underlyingCache.toObject()).toEqual(data); + expect(underlyingStore.toObject()).toEqual(data); }); }); }); diff --git a/src/cache/inmemory/__tests__/roundtrip.ts b/src/cache/inmemory/__tests__/roundtrip.ts index ff47a5558b6..5face167fa0 100644 --- a/src/cache/inmemory/__tests__/roundtrip.ts +++ b/src/cache/inmemory/__tests__/roundtrip.ts @@ -3,7 +3,7 @@ import gql from 'graphql-tag'; import { withError } from './diffAgainstStore'; import { withWarning } from './writeToStore'; -import { EntityCache } from '../entityCache'; +import { EntityStore } from '../entityStore'; import { StoreReader } from '../readFromStore'; import { StoreWriter } from '../writeToStore'; import { Policies } from '../policies'; @@ -42,7 +42,7 @@ function storeRoundtrip(query: DocumentNode, result: any, variables = {}) { // Make sure the result is identical if we haven't written anything new // to the store. https://github.com/apollographql/apollo-client/pull/3394 - expect(store).toBeInstanceOf(EntityCache); + expect(store).toBeInstanceOf(EntityStore); expect(reader.readQueryFromStore(readOptions)).toBe(reconstructedResult); const immutableResult = reader.readQueryFromStore(readOptions); diff --git a/src/cache/inmemory/__tests__/writeToStore.ts b/src/cache/inmemory/__tests__/writeToStore.ts index 6b02e7ada5f..45beebaa19a 100644 --- a/src/cache/inmemory/__tests__/writeToStore.ts +++ b/src/cache/inmemory/__tests__/writeToStore.ts @@ -16,7 +16,7 @@ import { import { addTypenameToDocument } from '../../../utilities/graphql/transform'; import { cloneDeep } from '../../../utilities/common/cloneDeep'; import { StoreWriter } from '../writeToStore'; -import { defaultNormalizedCacheFactory } from '../entityCache'; +import { defaultNormalizedCacheFactory } from '../entityStore'; import { InMemoryCache } from '../inMemoryCache'; import { Policies } from '../policies'; diff --git a/src/cache/inmemory/entityCache.ts b/src/cache/inmemory/entityStore.ts similarity index 89% rename from src/cache/inmemory/entityCache.ts rename to src/cache/inmemory/entityStore.ts index 0fd6b29d902..1b52ef56cad 100644 --- a/src/cache/inmemory/entityCache.ts +++ b/src/cache/inmemory/entityStore.ts @@ -21,13 +21,13 @@ function makeDepKey(dataId: string, fieldName?: string) { return JSON.stringify(parts); } -function depend(store: EntityCache, dataId: string, fieldName?: string) { +function depend(store: EntityStore, dataId: string, fieldName?: string) { if (store.depend) { store.depend(makeDepKey(dataId, fieldName)); } } -function dirty(store: EntityCache, dataId: string, fieldName?: string) { +function dirty(store: EntityStore, dataId: string, fieldName?: string) { if (store.depend) { store.depend.dirty(makeDepKey(dataId)); if (typeof fieldName === "string") { @@ -36,24 +36,24 @@ function dirty(store: EntityCache, dataId: string, fieldName?: string) { } } -export abstract class EntityCache implements NormalizedCache { +export abstract class EntityStore implements NormalizedCache { protected data: NormalizedCacheObject = Object.create(null); // It seems like this property ought to be protected rather than public, // but TypeScript doesn't realize it's inherited from a shared base // class by both Root and Layer classes, so Layer methods are forbidden - // from accessing the .depend property of an arbitrary EntityCache + // from accessing the .depend property of an arbitrary EntityStore // instance, because it might be a Root instance (and vice-versa). public readonly depend: DependType = null; public abstract addLayer( layerId: string, - replay: (layer: EntityCache) => any, - ): EntityCache; + replay: (layer: EntityStore) => any, + ): EntityStore; - public abstract removeLayer(layerId: string): EntityCache; + public abstract removeLayer(layerId: string): EntityStore; - // Although the EntityCache class is abstract, it contains concrete + // Although the EntityStore class is abstract, it contains concrete // implementations of the various NormalizedCache interface methods that // are inherited by the Root and Layer subclasses. @@ -107,7 +107,7 @@ export abstract class EntityCache implements NormalizedCache { delete this.refs[dataId]; // Note that we do not delete the this.rootIds[dataId] retainment // count for this ID, since an object with the same ID could appear in - // the cache again, and should not have to be retained again. + // the store again, and should not have to be retained again. // delete this.rootIds[dataId]; if (this.depend && storeObject) { @@ -162,9 +162,9 @@ export abstract class EntityCache implements NormalizedCache { } // The goal of garbage collection is to remove IDs from the Root layer of the - // cache that are no longer reachable starting from any IDs that have been + // store that are no longer reachable starting from any IDs that have been // explicitly retained (see retain and release, above). Returns an array of - // dataId strings that were removed from the cache. + // dataId strings that were removed from the store. public gc() { const ids = this.getRootIdSet(); const snapshot = this.toObject(); @@ -175,13 +175,13 @@ export abstract class EntityCache implements NormalizedCache { // were not previously contained by the Set. Object.keys(this.findChildRefIds(id)).forEach(ids.add, ids); // By removing IDs from the snapshot object here, we protect them from - // getting removed from the root cache layer below. + // getting removed from the root store layer below. delete snapshot[id]; } }); const idsToRemove = Object.keys(snapshot); if (idsToRemove.length) { - let root: EntityCache = this; + let root: EntityStore = this; while (root instanceof Layer) root = root.parent; idsToRemove.forEach(root.delete, root); } @@ -197,7 +197,7 @@ export abstract class EntityCache implements NormalizedCache { if (!hasOwn.call(this.refs, dataId)) { const found = this.refs[dataId] = Object.create(null); const workSet = new Set([this.data[dataId]]); - // Within the cache, only arrays and objects can contain child entity + // Within the store, only arrays and objects can contain child entity // references, so we can prune the traversal using this predicate: const canTraverse = (obj: any) => obj !== null && typeof obj === 'object'; workSet.forEach(obj => { @@ -216,9 +216,9 @@ export abstract class EntityCache implements NormalizedCache { } } -export namespace EntityCache { - // Refer to this class as EntityCache.Root outside this namespace. - export class Root extends EntityCache { +export namespace EntityStore { + // Refer to this class as EntityStore.Root outside this namespace. + export class Root extends EntityStore { // Although each Root instance gets its own unique this.depend // function, any Layer instances created by calling addLayer need to // share a single distinct dependency function. Since this shared @@ -244,8 +244,8 @@ export namespace EntityCache { public addLayer( layerId: string, - replay: (layer: EntityCache) => any, - ): EntityCache { + replay: (layer: EntityStore) => any, + ): EntityStore { // The replay function will be called in the Layer constructor. return new Layer(layerId, this, replay, this.sharedLayerDepend); } @@ -258,12 +258,12 @@ export namespace EntityCache { } // Not exported, since all Layer instances are created by the addLayer method -// of the EntityCache.Root class. -class Layer extends EntityCache { +// of the EntityStore.Root class. +class Layer extends EntityStore { constructor( public readonly id: string, - public readonly parent: Layer | EntityCache.Root, - public readonly replay: (layer: EntityCache) => any, + public readonly parent: Layer | EntityStore.Root, + public readonly replay: (layer: EntityStore) => any, public readonly depend: DependType, ) { super(); @@ -272,12 +272,12 @@ class Layer extends EntityCache { public addLayer( layerId: string, - replay: (layer: EntityCache) => any, - ): EntityCache { + replay: (layer: EntityStore) => any, + ): EntityStore { return new Layer(layerId, this, replay, this.depend); } - public removeLayer(layerId: string): EntityCache { + public removeLayer(layerId: string): EntityStore { // Remove all instances of the given id, not just the first one. const parent = this.parent.removeLayer(layerId); @@ -362,7 +362,7 @@ class Layer extends EntityCache { } } -const storeObjectReconciler: ReconcilerFunction<[EntityCache]> = function ( +const storeObjectReconciler: ReconcilerFunction<[EntityStore]> = function ( existingObject, incomingObject, property, @@ -386,7 +386,7 @@ const storeObjectReconciler: ReconcilerFunction<[EntityCache]> = function ( const iType = getTypenameFromStoreObject(store, incoming); // If both objects have a typename and the typename is different, let the // incoming object win. The typename can change when a different subtype - // of a union or interface is written to the cache. + // of a union or interface is written to the store. if ( typeof eType === 'string' && typeof iType === 'string' && @@ -415,13 +415,13 @@ const storeObjectReconciler: ReconcilerFunction<[EntityCache]> = function ( return incoming; } -export function supportsResultCaching(store: any): store is EntityCache { +export function supportsResultCaching(store: any): store is EntityStore { // When result caching is disabled, store.depend will be null. - return !!(store instanceof EntityCache && store.depend); + return !!(store instanceof EntityStore && store.depend); } export function defaultNormalizedCacheFactory( seed?: NormalizedCacheObject, ): NormalizedCache { - return new EntityCache.Root({ resultCaching: true, seed }); + return new EntityStore.Root({ resultCaching: true, seed }); } diff --git a/src/cache/inmemory/inMemoryCache.ts b/src/cache/inmemory/inMemoryCache.ts index 4b21c7dae2c..88712a3ea76 100644 --- a/src/cache/inmemory/inMemoryCache.ts +++ b/src/cache/inmemory/inMemoryCache.ts @@ -15,7 +15,7 @@ import { } from './types'; import { StoreReader } from './readFromStore'; import { StoreWriter } from './writeToStore'; -import { EntityCache, supportsResultCaching } from './entityCache'; +import { EntityStore, supportsResultCaching } from './entityStore'; import { defaultDataIdFromObject, PossibleTypesMap, @@ -37,8 +37,8 @@ const defaultConfig: InMemoryCacheConfig = { }; export class InMemoryCache extends ApolloCache { - private data: EntityCache; - private optimisticData: EntityCache; + private data: EntityStore; + private optimisticData: EntityStore; protected config: InMemoryCacheConfig; private watches = new Set(); @@ -68,7 +68,7 @@ export class InMemoryCache extends ApolloCache { // Passing { resultCaching: false } in the InMemoryCache constructor options // will completely disable dependency tracking, which will improve memory // usage but worsen the performance of repeated reads. - this.data = new EntityCache.Root({ + this.data = new EntityStore.Root({ resultCaching: this.config.resultCaching, }); @@ -230,7 +230,7 @@ export class InMemoryCache extends ApolloCache { // from duplicating this implementation in recordOptimisticTransaction. optimisticId?: string, ) { - const perform = (layer?: EntityCache) => { + const perform = (layer?: EntityStore) => { const proxy: InMemoryCache = Object.create(this); proxy.silenceBroadcast = true; if (layer) { diff --git a/src/cache/inmemory/readFromStore.ts b/src/cache/inmemory/readFromStore.ts index 876edcaf9c8..7c0e3e0deab 100644 --- a/src/cache/inmemory/readFromStore.ts +++ b/src/cache/inmemory/readFromStore.ts @@ -36,7 +36,7 @@ import { StoreObject, NormalizedCache, } from './types'; -import { supportsResultCaching } from './entityCache'; +import { supportsResultCaching } from './entityStore'; import { getTypenameFromStoreObject } from './helpers'; import { Policies } from './policies'; diff --git a/src/cache/inmemory/writeToStore.ts b/src/cache/inmemory/writeToStore.ts index 017ededd1e3..0721a3dea94 100644 --- a/src/cache/inmemory/writeToStore.ts +++ b/src/cache/inmemory/writeToStore.ts @@ -25,7 +25,7 @@ import { DeepMerger } from '../../utilities/common/mergeDeep'; import { shouldInclude } from '../../utilities/graphql/directives'; import { cloneDeep } from '../../utilities/common/cloneDeep'; -import { defaultNormalizedCacheFactory } from './entityCache'; +import { defaultNormalizedCacheFactory } from './entityStore'; import { NormalizedCache, StoreObject } from './types'; import { Policies, StoreValueMergeFunction } from './policies';