diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4f6b5f92e6d..b1a79680132 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,21 @@
`@client` directives.
[@justinmakaila](https://github.com/justinmakaila) in [#3482](https://github.com/apollographql/apollo-client/pull/3482)
+### Apollo Cache In-Memory (1.3.12)
+
+- Avoid using `DepTrackingCache` for optimistic reads.
+ [PR #4521](https://github.com/apollographql/apollo-client/pull/4251)
+
+- When creating an `InMemoryCache` object, it's now possible to disable the
+ result caching behavior introduced in [#3394](https://github.com/apollographql/apollo-client/pull/3394),
+ either for diagnostic purposes or because the benefit of caching repeated
+ reads is not worth the extra memory usage in your application:
+ ```ts
+ new InMemoryCache({
+ resultCaching: false
+ })
+ ```
+ Part of [PR #4521](https://github.com/apollographql/apollo-client/pull/4251).
## Apollo Client (2.4.7)
diff --git a/package.json b/package.json
index 7a21cf20eef..290488a35a1 100644
--- a/package.json
+++ b/package.json
@@ -71,12 +71,10 @@
},
"lint-staged": {
"*.ts*": [
- "prettier --ignore-path \"./config/prettierignore\" --trailing-comma all --single-quote --write",
- "git add"
+ "prettier --ignore-path \"./config/prettierignore\" --trailing-comma all --single-quote --write"
],
"*.js*": [
- "prettier --ignore-path \"./config/prettierignore\" --trailing-comma all --single-quote --write",
- "git add"
+ "prettier --ignore-path \"./config/prettierignore\" --trailing-comma all --single-quote --write"
]
},
"pre-commit": "lint-staged",
diff --git a/packages/apollo-cache-inmemory/package-lock.json b/packages/apollo-cache-inmemory/package-lock.json
index a158d8945c8..268b4dd112e 100644
--- a/packages/apollo-cache-inmemory/package-lock.json
+++ b/packages/apollo-cache-inmemory/package-lock.json
@@ -1,62 +1,43 @@
{
"name": "apollo-cache-inmemory",
- "version": "1.3.11",
+ "version": "1.3.12-beta.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"apollo-cache": {
- "version": "file:../apollo-cache",
+ "version": "1.1.21",
+ "resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.1.21.tgz",
+ "integrity": "sha512-5ErNb78KHtrJNimkDBTEigcvHkIqUmS7QJIk4lpZZ+XLVVgvk2fD+GhD1PLP+s8vHfAKVbO6vdbRxCCjGGrh5w==",
"requires": {
- "apollo-utilities": "file:../apollo-utilities"
- },
- "dependencies": {
- "apollo-utilities": {
- "version": "file:../apollo-utilities",
- "bundled": true,
- "requires": {
- "fast-json-stable-stringify": "^2.0.0",
- "fclone": "^1.0.11"
- },
- "dependencies": {
- "fast-json-stable-stringify": {
- "version": "2.0.0",
- "bundled": true
- },
- "fclone": {
- "version": "1.0.11",
- "bundled": true
- }
- }
- }
+ "apollo-utilities": "^1.0.26"
}
},
"apollo-utilities": {
- "version": "file:../apollo-utilities",
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.26.tgz",
+ "integrity": "sha512-URw7o3phymliqYCYatcird2YRPUU2eWCNvip64U9gQrX56mEfK4m99yBIDCMTpmcvOFsKLii1sIEZsHIs/bvnw==",
"requires": {
"fast-json-stable-stringify": "^2.0.0"
},
"dependencies": {
"fast-json-stable-stringify": {
"version": "2.0.0",
- "bundled": true
- },
- "fclone": {
- "version": "1.0.11",
- "bundled": true
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
}
}
},
"immutable-tuple": {
- "version": "0.4.8",
- "resolved": "https://registry.npmjs.org/immutable-tuple/-/immutable-tuple-0.4.8.tgz",
- "integrity": "sha512-1m29EVSrF+LJJAyVo1v12NsIalVKjyi4HNQVQDBx+LNCIuRXnfeMCHuLao5CyN1m3Sn0T63U5JEkmPArPCipQA=="
+ "version": "0.4.9",
+ "resolved": "https://registry.npmjs.org/immutable-tuple/-/immutable-tuple-0.4.9.tgz",
+ "integrity": "sha512-LWbJPZnidF8eczu7XmcnLBsumuyRBkpwIRPCZxlojouhBo5jEBO4toj6n7hMy6IxHU/c+MqDSWkvaTpPlMQcyA=="
},
"optimism": {
- "version": "0.6.6",
- "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.6.6.tgz",
- "integrity": "sha512-1Y6LY7pYbXP5y6yeXYfXhxJi9hsxYAZWpt7bBp4seAwfcYtaN7tq9wot/pdrhyI809/K4gDm3BcZcEkmwGevjg==",
+ "version": "0.6.8",
+ "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.6.8.tgz",
+ "integrity": "sha512-bN5n1KCxSqwBDnmgDnzMtQTHdL+uea2HYFx1smvtE+w2AMl0Uy31g0aXnP/Nt85OINnMJPRpJyfRQLTCqn5Weg==",
"requires": {
- "immutable-tuple": "^0.4.4"
+ "immutable-tuple": "^0.4.9"
}
}
}
diff --git a/packages/apollo-cache-inmemory/package.json b/packages/apollo-cache-inmemory/package.json
index ecfd2eb9726..9c6a4ccf45f 100644
--- a/packages/apollo-cache-inmemory/package.json
+++ b/packages/apollo-cache-inmemory/package.json
@@ -1,6 +1,6 @@
{
"name": "apollo-cache-inmemory",
- "version": "1.3.11",
+ "version": "1.3.12-beta.1",
"description": "Core abstract of Caching layer for Apollo Client",
"author": "James Baxley ",
"contributors": [
@@ -44,7 +44,7 @@
"dependencies": {
"apollo-cache": "file:../apollo-cache",
"apollo-utilities": "file:../apollo-utilities",
- "optimism": "^0.6.6"
+ "optimism": "^0.6.8"
},
"peerDependencies": {
"graphql": "0.11.7 || ^0.12.0 || ^0.13.0 || ^14.0.0"
diff --git a/packages/apollo-cache-inmemory/src/__tests__/__snapshots__/cache.ts.snap b/packages/apollo-cache-inmemory/src/__tests__/__snapshots__/cache.ts.snap
index 08cc1a7e210..0cd8b06df71 100644
--- a/packages/apollo-cache-inmemory/src/__tests__/__snapshots__/cache.ts.snap
+++ b/packages/apollo-cache-inmemory/src/__tests__/__snapshots__/cache.ts.snap
@@ -1,8 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[
- `Cache writeFragment will write some deeply nested data into the store at any id 1`
-] = `
+exports[`Cache writeFragment will write some deeply nested data into the store at any id (1/2) 1`] = `
Object {
"bar": Object {
"i": 7,
@@ -19,9 +17,7 @@ Object {
}
`;
-exports[
- `Cache writeFragment will write some deeply nested data into the store at any id 2`
-] = `
+exports[`Cache writeFragment will write some deeply nested data into the store at any id (1/2) 2`] = `
Object {
"bar": Object {
"i": 7,
@@ -42,9 +38,7 @@ Object {
}
`;
-exports[
- `Cache writeFragment will write some deeply nested data into the store at any id 3`
-] = `
+exports[`Cache writeFragment will write some deeply nested data into the store at any id (1/2) 3`] = `
Object {
"bar": Object {
"i": 10,
@@ -65,9 +59,7 @@ Object {
}
`;
-exports[
- `Cache writeFragment will write some deeply nested data into the store at any id 4`
-] = `
+exports[`Cache writeFragment will write some deeply nested data into the store at any id (1/2) 4`] = `
Object {
"bar": Object {
"i": 10,
@@ -88,9 +80,7 @@ Object {
}
`;
-exports[
- `Cache writeFragment will write some deeply nested data into the store at any id 5`
-] = `
+exports[`Cache writeFragment will write some deeply nested data into the store at any id (1/2) 5`] = `
Object {
"bar": Object {
"i": 7,
@@ -111,9 +101,129 @@ Object {
}
`;
-exports[
- `Cache writeFragment will write some deeply nested data into the store at any id 6`
-] = `
+exports[`Cache writeFragment will write some deeply nested data into the store at any id (1/2) 6`] = `
+Object {
+ "bar": Object {
+ "i": 10,
+ "j": 11,
+ "k": 12,
+ },
+ "foo": Object {
+ "e": 4,
+ "f": 5,
+ "g": 6,
+ "h": Object {
+ "generated": false,
+ "id": "bar",
+ "type": "id",
+ "typename": "Bar",
+ },
+ },
+}
+`;
+
+exports[`Cache writeFragment will write some deeply nested data into the store at any id (2/2) 1`] = `
+Object {
+ "bar": Object {
+ "i": 7,
+ },
+ "foo": Object {
+ "e": 4,
+ "h": Object {
+ "generated": false,
+ "id": "bar",
+ "type": "id",
+ "typename": undefined,
+ },
+ },
+}
+`;
+
+exports[`Cache writeFragment will write some deeply nested data into the store at any id (2/2) 2`] = `
+Object {
+ "bar": Object {
+ "i": 7,
+ "j": 8,
+ "k": 9,
+ },
+ "foo": Object {
+ "e": 4,
+ "f": 5,
+ "g": 6,
+ "h": Object {
+ "generated": false,
+ "id": "bar",
+ "type": "id",
+ "typename": undefined,
+ },
+ },
+}
+`;
+
+exports[`Cache writeFragment will write some deeply nested data into the store at any id (2/2) 3`] = `
+Object {
+ "bar": Object {
+ "i": 10,
+ "j": 8,
+ "k": 9,
+ },
+ "foo": Object {
+ "e": 4,
+ "f": 5,
+ "g": 6,
+ "h": Object {
+ "generated": false,
+ "id": "bar",
+ "type": "id",
+ "typename": undefined,
+ },
+ },
+}
+`;
+
+exports[`Cache writeFragment will write some deeply nested data into the store at any id (2/2) 4`] = `
+Object {
+ "bar": Object {
+ "i": 10,
+ "j": 11,
+ "k": 12,
+ },
+ "foo": Object {
+ "e": 4,
+ "f": 5,
+ "g": 6,
+ "h": Object {
+ "generated": false,
+ "id": "bar",
+ "type": "id",
+ "typename": undefined,
+ },
+ },
+}
+`;
+
+exports[`Cache writeFragment will write some deeply nested data into the store at any id (2/2) 5`] = `
+Object {
+ "bar": Object {
+ "i": 7,
+ "j": 8,
+ "k": 9,
+ },
+ "foo": Object {
+ "e": 4,
+ "f": 5,
+ "g": 6,
+ "h": Object {
+ "generated": false,
+ "id": "bar",
+ "type": "id",
+ "typename": "Bar",
+ },
+ },
+}
+`;
+
+exports[`Cache writeFragment will write some deeply nested data into the store at any id (2/2) 6`] = `
Object {
"bar": Object {
"i": 10,
diff --git a/packages/apollo-cache-inmemory/src/__tests__/__snapshots__/mapCache.ts.snap b/packages/apollo-cache-inmemory/src/__tests__/__snapshots__/mapCache.ts.snap
index d644838f32c..0ff0bd5d836 100644
--- a/packages/apollo-cache-inmemory/src/__tests__/__snapshots__/mapCache.ts.snap
+++ b/packages/apollo-cache-inmemory/src/__tests__/__snapshots__/mapCache.ts.snap
@@ -1,8 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[
- `MapCache Cache writeFragment will write some deeply nested data into the store at any id 1`
-] = `
+exports[`MapCache Cache writeFragment will write some deeply nested data into the store at any id (1/2) 1`] = `
Object {
"bar": Object {
"i": 7,
@@ -19,9 +17,7 @@ Object {
}
`;
-exports[
- `MapCache Cache writeFragment will write some deeply nested data into the store at any id 2`
-] = `
+exports[`MapCache Cache writeFragment will write some deeply nested data into the store at any id (1/2) 2`] = `
Object {
"bar": Object {
"i": 7,
@@ -42,9 +38,7 @@ Object {
}
`;
-exports[
- `MapCache Cache writeFragment will write some deeply nested data into the store at any id 3`
-] = `
+exports[`MapCache Cache writeFragment will write some deeply nested data into the store at any id (1/2) 3`] = `
Object {
"bar": Object {
"i": 10,
@@ -65,9 +59,7 @@ Object {
}
`;
-exports[
- `MapCache Cache writeFragment will write some deeply nested data into the store at any id 4`
-] = `
+exports[`MapCache Cache writeFragment will write some deeply nested data into the store at any id (1/2) 4`] = `
Object {
"bar": Object {
"i": 10,
@@ -88,9 +80,7 @@ Object {
}
`;
-exports[
- `MapCache Cache writeFragment will write some deeply nested data into the store at any id 5`
-] = `
+exports[`MapCache Cache writeFragment will write some deeply nested data into the store at any id (1/2) 5`] = `
Object {
"bar": Object {
"i": 7,
@@ -111,9 +101,7 @@ Object {
}
`;
-exports[
- `MapCache Cache writeFragment will write some deeply nested data into the store at any id 6`
-] = `
+exports[`MapCache Cache writeFragment will write some deeply nested data into the store at any id (1/2) 6`] = `
Object {
"bar": Object {
"i": 10,
@@ -134,9 +122,129 @@ Object {
}
`;
-exports[
- `MapCache writing to the store throws when trying to write an object without id that was previously queried with id 1`
-] = `
+exports[`MapCache Cache writeFragment will write some deeply nested data into the store at any id (2/2) 1`] = `
+Object {
+ "bar": Object {
+ "i": 7,
+ },
+ "foo": Object {
+ "e": 4,
+ "h": Object {
+ "generated": false,
+ "id": "bar",
+ "type": "id",
+ "typename": undefined,
+ },
+ },
+}
+`;
+
+exports[`MapCache Cache writeFragment will write some deeply nested data into the store at any id (2/2) 2`] = `
+Object {
+ "bar": Object {
+ "i": 7,
+ "j": 8,
+ "k": 9,
+ },
+ "foo": Object {
+ "e": 4,
+ "f": 5,
+ "g": 6,
+ "h": Object {
+ "generated": false,
+ "id": "bar",
+ "type": "id",
+ "typename": undefined,
+ },
+ },
+}
+`;
+
+exports[`MapCache Cache writeFragment will write some deeply nested data into the store at any id (2/2) 3`] = `
+Object {
+ "bar": Object {
+ "i": 10,
+ "j": 8,
+ "k": 9,
+ },
+ "foo": Object {
+ "e": 4,
+ "f": 5,
+ "g": 6,
+ "h": Object {
+ "generated": false,
+ "id": "bar",
+ "type": "id",
+ "typename": undefined,
+ },
+ },
+}
+`;
+
+exports[`MapCache Cache writeFragment will write some deeply nested data into the store at any id (2/2) 4`] = `
+Object {
+ "bar": Object {
+ "i": 10,
+ "j": 11,
+ "k": 12,
+ },
+ "foo": Object {
+ "e": 4,
+ "f": 5,
+ "g": 6,
+ "h": Object {
+ "generated": false,
+ "id": "bar",
+ "type": "id",
+ "typename": undefined,
+ },
+ },
+}
+`;
+
+exports[`MapCache Cache writeFragment will write some deeply nested data into the store at any id (2/2) 5`] = `
+Object {
+ "bar": Object {
+ "i": 7,
+ "j": 8,
+ "k": 9,
+ },
+ "foo": Object {
+ "e": 4,
+ "f": 5,
+ "g": 6,
+ "h": Object {
+ "generated": false,
+ "id": "bar",
+ "type": "id",
+ "typename": "Bar",
+ },
+ },
+}
+`;
+
+exports[`MapCache Cache writeFragment will write some deeply nested data into the store at any id (2/2) 6`] = `
+Object {
+ "bar": Object {
+ "i": 10,
+ "j": 11,
+ "k": 12,
+ },
+ "foo": Object {
+ "e": 4,
+ "f": 5,
+ "g": 6,
+ "h": Object {
+ "generated": false,
+ "id": "bar",
+ "type": "id",
+ "typename": "Bar",
+ },
+ },
+}
+`;
+
+exports[`MapCache writing to the store throws when trying to write an object without id that was previously queried with id 1`] = `
"Error writing result to store for query:
query Failure {
item {
diff --git a/packages/apollo-cache-inmemory/src/__tests__/cache.ts b/packages/apollo-cache-inmemory/src/__tests__/cache.ts
index 0cd4f2cc631..f0cb6e27ed1 100644
--- a/packages/apollo-cache-inmemory/src/__tests__/cache.ts
+++ b/packages/apollo-cache-inmemory/src/__tests__/cache.ts
@@ -3,39 +3,66 @@ import gql, { disableFragmentWarnings } from 'graphql-tag';
import { stripSymbols } from 'apollo-utilities';
import { cloneDeep } from 'lodash';
-import { InMemoryCache, ApolloReducerConfig, NormalizedCache } from '..';
+import { InMemoryCache, InMemoryCacheConfig, NormalizedCache } from '..';
disableFragmentWarnings();
describe('Cache', () => {
- function createCache({
- initialState,
- config,
- }: {
- initialState?: any;
- config?: ApolloReducerConfig;
- } = {}): ApolloCache {
- return new InMemoryCache(
- config || { addTypename: false },
- // XXX this is the old format. The tests need to be updated but since it is mapped down
- ).restore(initialState ? initialState.apollo.data : {});
+ function itWithInitialData(
+ message: string,
+ initialDataForCaches: ({ [key: string]: any })[],
+ callback: (...caches: InMemoryCache[]) => any,
+ ) {
+ const cachesList: InMemoryCache[][] = [
+ initialDataForCaches.map(
+ data => new InMemoryCache({
+ addTypename: false,
+ }).restore(cloneDeep(data))
+ ),
+ initialDataForCaches.map(
+ data => new InMemoryCache({
+ addTypename: false,
+ resultCaching: false,
+ }).restore(cloneDeep(data))
+ ),
+ ];
+
+ cachesList.forEach((caches, i) => {
+ it(message + ` (${i+1}/${cachesList.length})`, () => callback(...caches));
+ });
+ }
+
+ function itWithCacheConfig(
+ message: string,
+ config: InMemoryCacheConfig,
+ callback: (cache: InMemoryCache) => any,
+ ) {
+ const caches = [
+ new InMemoryCache({
+ addTypename: false,
+ ...config,
+ resultCaching: true,
+ }),
+ new InMemoryCache({
+ addTypename: false,
+ ...config,
+ resultCaching: false,
+ }),
+ ];
+
+ caches.forEach((cache, i) => {
+ it(message + ` (${i+1}/${caches.length})`, () => callback(cache));
+ });
}
describe('readQuery', () => {
- it('will read some data from the store', () => {
- const proxy = createCache({
- initialState: {
- apollo: {
- data: {
- ROOT_QUERY: {
- a: 1,
- b: 2,
- c: 3,
- },
- },
- },
- },
- });
+ itWithInitialData('will read some data from the store', [{
+ ROOT_QUERY: {
+ a: 1,
+ b: 2,
+ c: 3,
+ },
+ }], proxy => {
expect(
stripSymbols(
proxy.readQuery({
@@ -74,41 +101,33 @@ describe('Cache', () => {
).toEqual({ a: 1, b: 2, c: 3 });
});
- it('will read some deeply nested data from the store', () => {
- const proxy = createCache({
- initialState: {
- apollo: {
- data: {
- ROOT_QUERY: {
- a: 1,
- b: 2,
- c: 3,
- d: {
- type: 'id',
- id: 'foo',
- generated: false,
- },
- },
- foo: {
- e: 4,
- f: 5,
- g: 6,
- h: {
- type: 'id',
- id: 'bar',
- generated: false,
- },
- },
- bar: {
- i: 7,
- j: 8,
- k: 9,
- },
- },
- },
+ itWithInitialData('will read some deeply nested data from the store', [{
+ ROOT_QUERY: {
+ a: 1,
+ b: 2,
+ c: 3,
+ d: {
+ type: 'id',
+ id: 'foo',
+ generated: false,
},
- });
-
+ },
+ foo: {
+ e: 4,
+ f: 5,
+ g: 6,
+ h: {
+ type: 'id',
+ id: 'bar',
+ generated: false,
+ },
+ },
+ bar: {
+ i: 7,
+ j: 8,
+ k: 9,
+ },
+ }], proxy => {
expect(
stripSymbols(
proxy.readQuery({
@@ -170,20 +189,12 @@ describe('Cache', () => {
});
});
- it('will read some data from the store with variables', () => {
- const proxy = createCache({
- initialState: {
- apollo: {
- data: {
- ROOT_QUERY: {
- 'field({"literal":true,"value":42})': 1,
- 'field({"literal":false,"value":42})': 2,
- },
- },
- },
- },
- });
-
+ itWithInitialData('will read some data from the store with variables', [{
+ ROOT_QUERY: {
+ 'field({"literal":true,"value":42})': 1,
+ 'field({"literal":false,"value":42})': 2,
+ },
+ }], proxy => {
expect(
stripSymbols(
proxy.readQuery({
@@ -202,19 +213,11 @@ describe('Cache', () => {
).toEqual({ a: 1, b: 2 });
});
- it('will read some data from the store with null variables', () => {
- const proxy = createCache({
- initialState: {
- apollo: {
- data: {
- ROOT_QUERY: {
- 'field({"literal":false,"value":null})': 1,
- },
- },
- },
- },
- });
-
+ itWithInitialData('will read some data from the store with null variables', [{
+ ROOT_QUERY: {
+ 'field({"literal":false,"value":null})': 1,
+ },
+ }], proxy => {
expect(
stripSymbols(
proxy.readQuery({
@@ -232,20 +235,12 @@ describe('Cache', () => {
).toEqual({ a: 1 });
});
- it('should not mutate arguments passed in', () => {
- const proxy = createCache({
- initialState: {
- apollo: {
- data: {
- ROOT_QUERY: {
- 'field({"literal":true,"value":42})': 1,
- 'field({"literal":false,"value":42})': 2,
- },
- },
- },
- },
- });
-
+ itWithInitialData('should not mutate arguments passed in', [{
+ ROOT_QUERY: {
+ 'field({"literal":true,"value":42})': 1,
+ 'field({"literal":false,"value":42})': 2,
+ },
+ }], proxy => {
const options = {
query: gql`
query($literal: Boolean, $value: Int) {
@@ -266,9 +261,10 @@ describe('Cache', () => {
});
describe('readFragment', () => {
- it('will throw an error when there is no fragment', () => {
- const proxy = createCache();
-
+ itWithInitialData('will throw an error when there is no fragment', [
+ // Empty data, but still want to test with/without result caching.
+ {},
+ ], proxy => {
expect(() => {
proxy.readFragment({
id: 'x',
@@ -297,9 +293,9 @@ describe('Cache', () => {
);
});
- it('will throw an error when there is more than one fragment but no fragment name', () => {
- const proxy = createCache();
-
+ itWithInitialData('will throw an error when there is more than one fragment but no fragment name', [
+ {},
+ ], proxy => {
expect(() => {
proxy.readFragment({
id: 'x',
@@ -338,44 +334,36 @@ describe('Cache', () => {
);
});
- it('will read some deeply nested data from the store at any id', () => {
- const proxy = createCache({
- initialState: {
- apollo: {
- data: {
- ROOT_QUERY: {
- __typename: 'Type1',
- a: 1,
- b: 2,
- c: 3,
- d: {
- type: 'id',
- id: 'foo',
- generated: false,
- },
- },
- foo: {
- __typename: 'Foo',
- e: 4,
- f: 5,
- g: 6,
- h: {
- type: 'id',
- id: 'bar',
- generated: false,
- },
- },
- bar: {
- __typename: 'Bar',
- i: 7,
- j: 8,
- k: 9,
- },
- },
- },
+ itWithInitialData('will read some deeply nested data from the store at any id', [{
+ ROOT_QUERY: {
+ __typename: 'Type1',
+ a: 1,
+ b: 2,
+ c: 3,
+ d: {
+ type: 'id',
+ id: 'foo',
+ generated: false,
},
- });
-
+ },
+ foo: {
+ __typename: 'Foo',
+ e: 4,
+ f: 5,
+ g: 6,
+ h: {
+ type: 'id',
+ id: 'bar',
+ generated: false,
+ },
+ },
+ bar: {
+ __typename: 'Bar',
+ i: 7,
+ j: 8,
+ k: 9,
+ },
+ }], proxy => {
expect(
stripSymbols(
proxy.readFragment({
@@ -490,21 +478,13 @@ describe('Cache', () => {
).toEqual({ i: 7, j: 8, k: 9 });
});
- it('will read some data from the store with variables', () => {
- const proxy = createCache({
- initialState: {
- apollo: {
- data: {
- foo: {
- __typename: 'Foo',
- 'field({"literal":true,"value":42})': 1,
- 'field({"literal":false,"value":42})': 2,
- },
- },
- },
- },
- });
-
+ itWithInitialData('will read some data from the store with variables', [{
+ foo: {
+ __typename: 'Foo',
+ 'field({"literal":true,"value":42})': 1,
+ 'field({"literal":false,"value":42})': 2,
+ },
+ }], proxy => {
expect(
stripSymbols(
proxy.readFragment({
@@ -524,27 +504,18 @@ describe('Cache', () => {
).toEqual({ a: 1, b: 2 });
});
- it('will return null when an id that can’t be found is provided', () => {
- const client1 = createCache();
- const client2 = createCache({
- initialState: {
- apollo: {
- data: {
- bar: { __typename: 'Bar', a: 1, b: 2, c: 3 },
- },
- },
- },
- });
- const client3 = createCache({
- initialState: {
- apollo: {
- data: {
- foo: { __typename: 'Foo', a: 1, b: 2, c: 3 },
- },
- },
- },
- });
-
+ itWithInitialData('will return null when an id that can’t be found is provided', [
+ // client1
+ {},
+ // client2
+ {
+ bar: { __typename: 'Bar', a: 1, b: 2, c: 3 },
+ },
+ // client3
+ {
+ foo: { __typename: 'Foo', a: 1, b: 2, c: 3 },
+ },
+ ], (client1, client2, client3) => {
expect(
stripSymbols(
client1.readFragment({
@@ -591,9 +562,9 @@ describe('Cache', () => {
});
describe('writeQuery', () => {
- it('will write some data to the store', () => {
- const proxy = createCache();
-
+ itWithInitialData('will write some data to the store', [
+ {}
+ ], proxy => {
proxy.writeQuery({
data: { a: 1 },
query: gql`
@@ -647,9 +618,9 @@ describe('Cache', () => {
});
});
- it('will write some deeply nested data to the store', () => {
- const proxy = createCache();
-
+ itWithInitialData('will write some deeply nested data to the store', [
+ {}
+ ], proxy => {
proxy.writeQuery({
data: { a: 1, d: { e: 4 } },
query: gql`
@@ -767,9 +738,9 @@ describe('Cache', () => {
});
});
- it('will write some data to the store with variables', () => {
- const proxy = createCache();
-
+ itWithInitialData('will write some data to the store with variables', [
+ {},
+ ], proxy => {
proxy.writeQuery({
data: {
a: 1,
@@ -794,9 +765,10 @@ describe('Cache', () => {
},
});
});
- it('will write some data to the store with variables where some are null', () => {
- const proxy = createCache();
+ itWithInitialData('will write some data to the store with variables where some are null', [
+ {}
+ ], proxy => {
proxy.writeQuery({
data: {
a: 1,
@@ -824,9 +796,9 @@ describe('Cache', () => {
});
describe('writeFragment', () => {
- it('will throw an error when there is no fragment', () => {
- const proxy = createCache();
-
+ itWithInitialData('will throw an error when there is no fragment', [
+ {},
+ ], proxy => {
expect(() => {
proxy.writeFragment({
data: {},
@@ -857,9 +829,9 @@ describe('Cache', () => {
);
});
- it('will throw an error when there is more than one fragment but no fragment name', () => {
- const proxy = createCache();
-
+ itWithInitialData('will throw an error when there is more than one fragment but no fragment name', [
+ {}
+ ], proxy => {
expect(() => {
proxy.writeFragment({
data: {},
@@ -900,11 +872,10 @@ describe('Cache', () => {
);
});
- it('will write some deeply nested data into the store at any id', () => {
- const proxy = createCache({
- config: { dataIdFromObject: (o: any) => o.id, addTypename: false },
- });
-
+ itWithCacheConfig('will write some deeply nested data into the store at any id', {
+ dataIdFromObject: (o: any) => o.id,
+ addTypename: false,
+ }, proxy => {
proxy.writeFragment({
data: { __typename: 'Foo', e: 4, h: { id: 'bar', i: 7 } },
id: 'foo',
@@ -1019,10 +990,10 @@ describe('Cache', () => {
expect((proxy as InMemoryCache).extract()).toMatchSnapshot();
});
- it('writes data that can be read back', () => {
- const proxy = createCache({
- config: { addTypename: true },
- });
+
+ itWithCacheConfig('writes data that can be read back', {
+ addTypename: true,
+ }, proxy => {
const readWriteFragment = gql`
fragment aFragment on query {
getSomething {
@@ -1047,11 +1018,9 @@ describe('Cache', () => {
expect(stripSymbols(result)).toEqual(data);
});
- it('will write some data to the store with variables', () => {
- const proxy = createCache({
- config: { addTypename: true },
- });
-
+ itWithCacheConfig('will write some data to the store with variables', {
+ addTypename: true,
+ }, proxy => {
proxy.writeFragment({
data: {
a: 1,
@@ -1082,9 +1051,9 @@ describe('Cache', () => {
});
describe('performTransaction', () => {
- it('will not broadcast mid-transaction', () => {
- const cache = createCache();
-
+ itWithInitialData('will not broadcast mid-transaction', [
+ {},
+ ], cache => {
let numBroadcasts = 0;
const query = gql`
@@ -1130,9 +1099,9 @@ describe('Cache', () => {
});
describe('performOptimisticTransaction', () => {
- it('will only broadcast once', () => {
- const cache = createCache();
-
+ itWithInitialData('will only broadcast once', [
+ {},
+ ], cache => {
let numBroadcasts = 0;
const query = gql`
@@ -1171,7 +1140,7 @@ describe('Cache', () => {
});
expect(numBroadcasts).toEqual(0);
- }, 1);
+ }, 1 as any);
expect(numBroadcasts).toEqual(1);
});
diff --git a/packages/apollo-cache-inmemory/src/inMemoryCache.ts b/packages/apollo-cache-inmemory/src/inMemoryCache.ts
index ce80f6c0b61..41dd5ade92d 100644
--- a/packages/apollo-cache-inmemory/src/inMemoryCache.ts
+++ b/packages/apollo-cache-inmemory/src/inMemoryCache.ts
@@ -21,14 +21,21 @@ import {
import { StoreReader } from './readFromStore';
import { StoreWriter } from './writeToStore';
-import { defaultNormalizedCacheFactory, DepTrackingCache } from './depTrackingCache';
+import { DepTrackingCache } from './depTrackingCache';
import { wrap, CacheKeyNode, OptimisticWrapperFunction } from './optimism';
+import { ObjectCache } from './objectCache';
import { record } from './recordingCache';
-const defaultConfig: ApolloReducerConfig = {
+
+export interface InMemoryCacheConfig extends ApolloReducerConfig {
+ resultCaching?: boolean;
+}
+
+const defaultConfig: InMemoryCacheConfig = {
fragmentMatcher: new HeuristicFragmentMatcher(),
dataIdFromObject: defaultDataIdFromObject,
addTypename: true,
+ resultCaching: true,
};
export function defaultDataIdFromObject(result: any): string | null {
@@ -45,7 +52,7 @@ export function defaultDataIdFromObject(result: any): string | null {
export class InMemoryCache extends ApolloCache {
protected data: NormalizedCache;
- protected config: ApolloReducerConfig;
+ protected config: InMemoryCacheConfig;
protected optimistic: OptimisticStoreItem[] = [];
private watches = new Set();
private addTypename: boolean;
@@ -58,7 +65,7 @@ export class InMemoryCache extends ApolloCache {
// don't forget to turn it back on!
private silenceBroadcast: boolean = false;
- constructor(config: ApolloReducerConfig = {}) {
+ constructor(config: InMemoryCacheConfig = {}) {
super();
this.config = { ...defaultConfig, ...config };
@@ -78,7 +85,9 @@ export class InMemoryCache extends ApolloCache {
}
this.addTypename = this.config.addTypename;
- this.data = defaultNormalizedCacheFactory();
+ this.data = this.config.resultCaching
+ ? new DepTrackingCache()
+ : new ObjectCache();
this.storeReader = new StoreReader(this.cacheKeyRoot);
this.storeWriter = new StoreWriter();
@@ -134,9 +143,10 @@ export class InMemoryCache extends ApolloCache {
return null;
}
- const store = (query.optimistic && this.optimistic.length)
- ? defaultNormalizedCacheFactory(this.extract(true))
- : this.data;
+ const store =
+ query.optimistic && this.optimistic.length
+ ? new ObjectCache(this.extract(true))
+ : this.data;
return this.storeReader.readQueryFromStore({
store,
@@ -164,9 +174,10 @@ export class InMemoryCache extends ApolloCache {
}
public diff(query: Cache.DiffOptions): Cache.DiffResult {
- const store = (query.optimistic && this.optimistic.length)
- ? defaultNormalizedCacheFactory(this.extract(true))
- : this.data;
+ const store =
+ query.optimistic && this.optimistic.length
+ ? new ObjectCache(this.extract(true))
+ : this.data;
return this.storeReader.diffQueryAgainstStore({
store: store,
diff --git a/packages/apollo-cache-inmemory/src/index.ts b/packages/apollo-cache-inmemory/src/index.ts
index 5ef7f2df296..d3e1779cb8b 100644
--- a/packages/apollo-cache-inmemory/src/index.ts
+++ b/packages/apollo-cache-inmemory/src/index.ts
@@ -1,4 +1,9 @@
-export { InMemoryCache, defaultDataIdFromObject } from './inMemoryCache';
+export {
+ InMemoryCache,
+ InMemoryCacheConfig,
+ defaultDataIdFromObject,
+} from './inMemoryCache';
+
export * from './readFromStore';
export * from './writeToStore';
export * from './fragmentMatcher';