diff --git a/src/cache/inmemory/__tests__/__snapshots__/writeToStore.ts.snap b/src/cache/inmemory/__tests__/__snapshots__/writeToStore.ts.snap index e5b7f49cdcb..894a3eab600 100644 --- a/src/cache/inmemory/__tests__/__snapshots__/writeToStore.ts.snap +++ b/src/cache/inmemory/__tests__/__snapshots__/writeToStore.ts.snap @@ -1,5 +1,39 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`writing to the store "Cache data maybe lost..." warnings should not warn when scalar fields are updated 1`] = ` +Object { + "ROOT_QUERY": Object { + "__typename": "Query", + "currentTime({\\"tz\\":\\"UTC-5\\"})": Object { + "localeString": "9/25/2020, 1:08:33 PM", + }, + "someJSON": Object { + "foos": Array [ + "bar", + "baz", + ], + "oyez": 3, + }, + }, +} +`; + +exports[`writing to the store "Cache data maybe lost..." warnings should not warn when scalar fields are updated 2`] = ` +Object { + "ROOT_QUERY": Object { + "__typename": "Query", + "currentTime({\\"tz\\":\\"UTC-5\\"})": Object { + "msSinceEpoch": 1601053713081, + }, + "someJSON": Object { + "asdf": "middle", + "qwer": "upper", + "zxcv": "lower", + }, + }, +} +`; + exports[`writing to the store user objects should be able to have { __typename: "Mutation" } 1`] = ` Object { "Gene:{\\"id\\":\\"SLC45A2\\"}": Object { diff --git a/src/cache/inmemory/__tests__/writeToStore.ts b/src/cache/inmemory/__tests__/writeToStore.ts index 668f299e29e..dd8b37beb69 100644 --- a/src/cache/inmemory/__tests__/writeToStore.ts +++ b/src/cache/inmemory/__tests__/writeToStore.ts @@ -1582,6 +1582,70 @@ describe('writing to the store', () => { }); }); + describe('"Cache data maybe lost..." warnings', () => { + const { warn } = console; + let warnings: any[][] = []; + + beforeEach(() => { + warnings.length = 0; + console.warn = (...args: any[]) => { + warnings.push(args); + }; + }); + + afterEach(() => { + console.warn = warn; + }); + + it("should not warn when scalar fields are updated", () => { + const cache = new InMemoryCache; + + const query = gql` + query { + someJSON + currentTime(tz: "UTC-5") + } + `; + + expect(warnings).toEqual([]); + + const date = new Date(1601053713081); + + cache.writeQuery({ + query, + data: { + someJSON: { + oyez: 3, + foos: ["bar", "baz"], + }, + currentTime: { + localeString: date.toLocaleString("en-US"), + }, + }, + }); + + expect(cache.extract()).toMatchSnapshot(); + expect(warnings).toEqual([]); + + cache.writeQuery({ + query, + data: { + someJSON: { + qwer: "upper", + asdf: "middle", + zxcv: "lower", + }, + currentTime: { + msSinceEpoch: date.getTime(), + }, + }, + }); + + expect(cache.extract()).toMatchSnapshot(); + expect(warnings).toEqual([]); + }); + }); + describe('writeResultToStore shape checking', () => { const query = gql` query { diff --git a/src/cache/inmemory/writeToStore.ts b/src/cache/inmemory/writeToStore.ts index bb0d8c43864..afef93e9a23 100644 --- a/src/cache/inmemory/writeToStore.ts +++ b/src/cache/inmemory/writeToStore.ts @@ -284,6 +284,15 @@ export class StoreWriter { } if (process.env.NODE_ENV !== "production") { + const hasSelectionSet = (storeFieldName: string) => + fieldsWithSelectionSets.has(fieldNameFromStoreName(storeFieldName)); + const fieldsWithSelectionSets = new Set(); + workSet.forEach(selection => { + if (isField(selection) && selection.selectionSet) { + fieldsWithSelectionSets.add(selection.name.value); + } + }); + const hasMergeFunction = (storeFieldName: string) => { const childTree = mergeTree.map.get(storeFieldName); return Boolean(childTree && childTree.info && childTree.info.merge); @@ -291,8 +300,11 @@ export class StoreWriter { Object.keys(incomingFields).forEach(storeFieldName => { // If a merge function was defined for this field, trust that it - // did the right thing about (not) clobbering data. - if (!hasMergeFunction(storeFieldName)) { + // did the right thing about (not) clobbering data. If the field + // has no selection set, it's a scalar field, so it doesn't need + // a merge function (even if it's an object, like JSON data). + if (hasSelectionSet(storeFieldName) && + !hasMergeFunction(storeFieldName)) { warnAboutDataLoss( entityRef, incomingFields,