From 3bd46d3a5b2805f256f974d03c502bdcb782eb6c Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 8 Nov 2024 12:45:34 -0700 Subject: [PATCH 01/14] Reenable failing test --- src/__tests__/dataMasking.ts | 117 ++++++++++++++++------------------- 1 file changed, 55 insertions(+), 62 deletions(-) diff --git a/src/__tests__/dataMasking.ts b/src/__tests__/dataMasking.ts index f8bcd12ceb0..8af6327ecbb 100644 --- a/src/__tests__/dataMasking.ts +++ b/src/__tests__/dataMasking.ts @@ -3112,79 +3112,72 @@ describe("client.watchFragment", () => { }); }); - // FIXME: This broke with the changes in https://github.com/apollographql/apollo-client/pull/12114 - // which ensure masking works with deferred payloads. Instead of fixing with - // #12114, it will be fixed with https://github.com/apollographql/apollo-client/issues/12043 - // which will fix overagressive warnings. - test.failing( - "warns when accessing an unmasked field on a watched fragment while using @unmask with mode: 'migrate'", - async () => { - using consoleSpy = spyOnConsole("warn"); - - type ProfileFieldsFragment = { - __typename: "User"; - age: number; - name: string; - } & { " $fragmentName": "UserFieldsFragment" }; + test("warns when accessing an unmasked field on a watched fragment while using @unmask with mode: 'migrate'", async () => { + using consoleSpy = spyOnConsole("warn"); - type UserFieldsFragment = { - __typename: "User"; - id: number; - name: string; - /** @deprecated */ - age: number; - } & { " $fragmentName": "UserFieldsFragment" } & { - " $fragmentRefs": { ProfileFieldsFragment: ProfileFieldsFragment }; - }; + type ProfileFieldsFragment = { + __typename: "User"; + age: number; + name: string; + } & { " $fragmentName": "UserFieldsFragment" }; - const fragment: MaskedDocumentNode = gql` - fragment UserFields on User { - id - name - ...ProfileFields @unmask(mode: "migrate") - } + type UserFieldsFragment = { + __typename: "User"; + id: number; + name: string; + /** @deprecated */ + age: number; + } & { " $fragmentName": "UserFieldsFragment" } & { + " $fragmentRefs": { ProfileFieldsFragment: ProfileFieldsFragment }; + }; - fragment ProfileFields on User { - age - name - } - `; + const fragment: MaskedDocumentNode = gql` + fragment UserFields on User { + id + name + ...ProfileFields @unmask(mode: "migrate") + } - const client = new ApolloClient({ - dataMasking: true, - cache: new InMemoryCache(), - }); + fragment ProfileFields on User { + age + name + } + `; - const observable = client.watchFragment({ - fragment, - fragmentName: "UserFields", - from: { __typename: "User", id: 1 }, - }); - const stream = new ObservableStream(observable); + const client = new ApolloClient({ + dataMasking: true, + cache: new InMemoryCache(), + }); - { - const { data } = await stream.takeNext(); - data.__typename; - data.id; - data.name; + const observable = client.watchFragment({ + fragment, + fragmentName: "UserFields", + from: { __typename: "User", id: 1 }, + }); + const stream = new ObservableStream(observable); - expect(consoleSpy.warn).not.toHaveBeenCalled(); + { + const { data } = await stream.takeNext(); + data.__typename; + data.id; + data.name; - data.age; + expect(consoleSpy.warn).not.toHaveBeenCalled(); - expect(consoleSpy.warn).toHaveBeenCalledTimes(1); - expect(consoleSpy.warn).toHaveBeenCalledWith( - "Accessing unmasked field on %s at path '%s'. This field will not be available when masking is enabled. Please read the field from the fragment instead.", - "fragment 'UserFields'", - "age" - ); + data.age; - // Ensure we only warn once - data.age; - expect(consoleSpy.warn).toHaveBeenCalledTimes(1); - } + expect(consoleSpy.warn).toHaveBeenCalledTimes(1); + expect(consoleSpy.warn).toHaveBeenCalledWith( + "Accessing unmasked field on %s at path '%s'. This field will not be available when masking is enabled. Please read the field from the fragment instead.", + "fragment 'UserFields'", + "age" + ); + + // Ensure we only warn once + data.age; + expect(consoleSpy.warn).toHaveBeenCalledTimes(1); } - ); + }); test("can lookup unmasked fragments from the fragment registry in watched fragments", async () => { const fragments = createFragmentRegistry(); From 8070ae179627c054591d85edc77e9b017e14d367 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 8 Nov 2024 12:45:46 -0700 Subject: [PATCH 02/14] Don't add accessor warnings for fields with undefined value --- src/core/masking.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/masking.ts b/src/core/masking.ts index 3991940a23c..1c342b28132 100644 --- a/src/core/masking.ts +++ b/src/core/masking.ts @@ -370,6 +370,10 @@ function addAccessorWarning( path: string, context: MaskingContext ) { + if (value === void 0) { + return; + } + let getValue = () => { if (context.disableWarnings) { return value; From ac909c293d227849d1cdd680dd153a6373c05208 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 8 Nov 2024 12:52:16 -0700 Subject: [PATCH 03/14] Return early if passing an empty object to maskFragment --- src/core/masking.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/core/masking.ts b/src/core/masking.ts index 1c342b28132..ef6988454b0 100644 --- a/src/core/masking.ts +++ b/src/core/masking.ts @@ -11,6 +11,7 @@ import { import type { FragmentMap } from "../utilities/index.js"; import type { ApolloCache, DocumentNode, TypedDocumentNode } from "./index.js"; import { invariant } from "../utilities/globals/index.js"; +import { equal } from "@wry/equality"; interface MaskingContext { operationType: "query" | "mutation" | "subscription" | "fragment"; @@ -110,6 +111,13 @@ export function maskFragment( return data; } + if (equal(data, {})) { + // Return early and skip the masking algorithm if we don't have any data + // yet. This can happen when cache.diff returns an empty object which is + // used from watchFragment. + return data; + } + const context: MaskingContext = { operationType: "fragment", operationName: fragment.name.value, From dedcbec2741654331eddd4dd6c3fa8da678fdf4e Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 8 Nov 2024 12:52:33 -0700 Subject: [PATCH 04/14] Add comment about undefined value for accessor warning --- src/core/masking.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/masking.ts b/src/core/masking.ts index ef6988454b0..209c878b37d 100644 --- a/src/core/masking.ts +++ b/src/core/masking.ts @@ -378,6 +378,11 @@ function addAccessorWarning( path: string, context: MaskingContext ) { + // In order to preserve the original shape of the data as much as possible, we + // want to skip adding a property with warning to the final result when the + // value is missing, otherwise our final result will contain additional + // properties that our original result did not have. This could happen with a + // deferred payload for example. if (value === void 0) { return; } From 819475fc574ed46d8fb5f01ade6c5de930ec68d2 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 8 Nov 2024 12:54:31 -0700 Subject: [PATCH 05/14] Adjust test that checks for warnings to ensure there is data --- src/__tests__/dataMasking.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/__tests__/dataMasking.ts b/src/__tests__/dataMasking.ts index 8af6327ecbb..f2e998d27f1 100644 --- a/src/__tests__/dataMasking.ts +++ b/src/__tests__/dataMasking.ts @@ -3149,6 +3149,18 @@ describe("client.watchFragment", () => { cache: new InMemoryCache(), }); + client.writeFragment({ + id: client.cache.identify({ __typename: "User", id: 1 }), + fragment, + fragmentName: "UserFields", + data: { + __typename: "User", + id: 1, + age: 30, + name: "Test User", + }, + }); + const observable = client.watchFragment({ fragment, fragmentName: "UserFields", From d8298e468094f76c5927a35541864060ea0d1fbf Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 8 Nov 2024 13:02:23 -0700 Subject: [PATCH 06/14] Use a slot to determine when to disable warnings --- src/core/masking.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/core/masking.ts b/src/core/masking.ts index 209c878b37d..a6d288b9653 100644 --- a/src/core/masking.ts +++ b/src/core/masking.ts @@ -12,6 +12,7 @@ import type { FragmentMap } from "../utilities/index.js"; import type { ApolloCache, DocumentNode, TypedDocumentNode } from "./index.js"; import { invariant } from "../utilities/globals/index.js"; import { equal } from "@wry/equality"; +import { Slot } from "optimism"; interface MaskingContext { operationType: "query" | "mutation" | "subscription" | "fragment"; @@ -21,6 +22,10 @@ interface MaskingContext { disableWarnings?: boolean; } +// Contextual slot that allows us to disable accessor warnings on fields when in +// migrate mode. +export const disableWarningsSlot = new Slot(); + export function maskOperation( data: TData, document: DocumentNode | TypedDocumentNode, @@ -60,9 +65,7 @@ export function maskOperation( ); if (Object.isFrozen(data)) { - context.disableWarnings = true; - maybeDeepFreeze(masked); - context.disableWarnings = false; + disableWarningsSlot.withValue(true, maybeDeepFreeze, [masked]); } return changed ? masked : data; @@ -132,9 +135,7 @@ export function maskFragment( ); if (Object.isFrozen(data)) { - context.disableWarnings = true; - maybeDeepFreeze(masked); - context.disableWarnings = false; + disableWarningsSlot.withValue(true, maybeDeepFreeze, [masked]); } return changed ? masked : data; @@ -388,7 +389,7 @@ function addAccessorWarning( } let getValue = () => { - if (context.disableWarnings) { + if (disableWarningsSlot.getValue()) { return value; } From 01d0212c191c734df3e2a5535db0a8b24f67f1ff Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 8 Nov 2024 13:10:58 -0700 Subject: [PATCH 07/14] Ensure cache.identify does not trigger masked field access warning --- src/__tests__/dataMasking.ts | 67 ++++++++++++++++++++++++++++++++++ src/cache/inmemory/policies.ts | 5 ++- 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/__tests__/dataMasking.ts b/src/__tests__/dataMasking.ts index f2e998d27f1..dfe2988c0f3 100644 --- a/src/__tests__/dataMasking.ts +++ b/src/__tests__/dataMasking.ts @@ -1143,6 +1143,73 @@ describe("client.watchQuery", () => { } }); + // https://github.com/apollographql/apollo-client/issues/12043 + test("does not warn when passing @unmask(mode: 'migrate') object to cache.identify", async () => { + using consoleSpy = spyOnConsole("warn"); + + type UserFieldsFragment = { + age: number; + } & { " $fragmentName"?: "UserFieldsFragment" }; + + interface Query { + currentUser: { + __typename: "User"; + id: number; + name: string; + /** @deprecated */ + age: number; + } & { " $fragmentRefs"?: { UserFieldsFragment: UserFieldsFragment } }; + } + + const query: MaskedDocumentNode = gql` + query UnmaskedQuery { + currentUser { + id + name + ...UserFields @unmask(mode: "migrate") + } + } + + fragment UserFields on User { + age + name + } + `; + + const mocks = [ + { + request: { query }, + result: { + data: { + currentUser: { + __typename: "User", + id: 1, + name: "Test User", + age: 34, + }, + }, + }, + delay: 20, + }, + ]; + + const client = new ApolloClient({ + dataMasking: true, + cache: new InMemoryCache(), + link: new MockLink(mocks), + }); + + const observable = client.watchQuery({ query }); + const stream = new ObservableStream(observable); + + const { data } = await stream.takeNext(); + + const id = client.cache.identify(data.currentUser); + + expect(consoleSpy.warn).not.toHaveBeenCalled(); + expect(id).toEqual("User:1"); + }); + test("reads fragment by passing parent object to `from`", async () => { type UserFieldsFragment = { age: number; diff --git a/src/cache/inmemory/policies.ts b/src/cache/inmemory/policies.ts index 3c68f35eb9d..a9fdf925126 100644 --- a/src/cache/inmemory/policies.ts +++ b/src/cache/inmemory/policies.ts @@ -52,6 +52,7 @@ import { keyArgsFnFromSpecifier, keyFieldsFnFromSpecifier, } from "./key-extractor.js"; +import { disableWarningsSlot } from "../../core/masking.js"; export type TypePolicies = { [__typename: string]: TypePolicy; @@ -392,7 +393,9 @@ export class Policies { const policy = typename && this.getTypePolicy(typename); let keyFn = (policy && policy.keyFn) || this.config.dataIdFromObject; while (keyFn) { - const specifierOrId = keyFn({ ...object, ...storeObject }, context); + const specifierOrId = disableWarningsSlot.withValue(true, () => { + return keyFn!({ ...object, ...storeObject }, context); + }); if (isArray(specifierOrId)) { keyFn = keyFieldsFnFromSpecifier(specifierOrId); } else { From 706c8910880de76f23a5db2876c1b2da95c14737 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 8 Nov 2024 13:23:44 -0700 Subject: [PATCH 08/14] Rename variable --- src/core/__tests__/masking.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/__tests__/masking.test.ts b/src/core/__tests__/masking.test.ts index 27063e7be1d..c3b99a79dcb 100644 --- a/src/core/__tests__/masking.test.ts +++ b/src/core/__tests__/masking.test.ts @@ -2244,7 +2244,7 @@ describe("maskFragment", () => { test("warns when accessing unmasked fields when using `@unmask` directive with mode 'migrate'", () => { using _ = spyOnConsole("warn"); - const query = gql` + const fragment = gql` fragment UnmaskedFragment on User { id name @@ -2265,7 +2265,7 @@ describe("maskFragment", () => { age: 30, }, }), - query, + fragment, new InMemoryCache(), "UnmaskedFragment" ); From 53e910925b04e2795d976b643609982aae4788a5 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 8 Nov 2024 13:24:18 -0700 Subject: [PATCH 09/14] Fix incorrect test --- src/core/__tests__/masking.test.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/core/__tests__/masking.test.ts b/src/core/__tests__/masking.test.ts index c3b99a79dcb..fbd1f99a760 100644 --- a/src/core/__tests__/masking.test.ts +++ b/src/core/__tests__/masking.test.ts @@ -2258,12 +2258,10 @@ describe("maskFragment", () => { const data = maskFragment( deepFreeze({ - currentUser: { - __typename: "User", - id: 1, - name: "Test User", - age: 30, - }, + __typename: "User", + id: 1, + name: "Test User", + age: 30, }), fragment, new InMemoryCache(), From afd18c3da6c5ac9cbfa934651fc267a10b4f8267 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 8 Nov 2024 13:25:21 -0700 Subject: [PATCH 10/14] Add additional test check --- src/core/__tests__/masking.test.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/core/__tests__/masking.test.ts b/src/core/__tests__/masking.test.ts index fbd1f99a760..84f5389e928 100644 --- a/src/core/__tests__/masking.test.ts +++ b/src/core/__tests__/masking.test.ts @@ -2268,6 +2268,12 @@ describe("maskFragment", () => { "UnmaskedFragment" ); + data.__typename; + data.id; + data.name; + + expect(console.warn).not.toHaveBeenCalled(); + data.age; expect(console.warn).toHaveBeenCalledTimes(1); From 1b235943fe502124744b48c668c6015e3dd38cd4 Mon Sep 17 00:00:00 2001 From: jerelmiller Date: Fri, 8 Nov 2024 20:37:13 +0000 Subject: [PATCH 11/14] Clean up Prettier, Size-limit, and Api-Extractor --- .api-reports/api-report-cache.api.md | 6 +++--- .api-reports/api-report-core.api.md | 6 +++--- .api-reports/api-report-utilities.api.md | 10 +++++----- .api-reports/api-report.api.md | 6 +++--- .size-limits.json | 4 ++-- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.api-reports/api-report-cache.api.md b/.api-reports/api-report-cache.api.md index b539bec11c8..243e585f909 100644 --- a/.api-reports/api-report-cache.api.md +++ b/.api-reports/api-report-cache.api.md @@ -1109,9 +1109,9 @@ interface WriteContext extends ReadMergeModifyContext { // Warnings were encountered during analysis: // // src/cache/core/cache.ts:92:7 - (ae-forgotten-export) The symbol "MaybeMasked" needs to be exported by the entry point index.d.ts -// src/cache/inmemory/policies.ts:92:3 - (ae-forgotten-export) The symbol "FragmentMap" needs to be exported by the entry point index.d.ts -// src/cache/inmemory/policies.ts:161:3 - (ae-forgotten-export) The symbol "KeySpecifier" needs to be exported by the entry point index.d.ts -// src/cache/inmemory/policies.ts:161:3 - (ae-forgotten-export) The symbol "KeyArgsFunction" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:93:3 - (ae-forgotten-export) The symbol "FragmentMap" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:162:3 - (ae-forgotten-export) The symbol "KeySpecifier" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:162:3 - (ae-forgotten-export) The symbol "KeyArgsFunction" needs to be exported by the entry point index.d.ts // src/cache/inmemory/types.ts:139:3 - (ae-forgotten-export) The symbol "KeyFieldsFunction" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/.api-reports/api-report-core.api.md b/.api-reports/api-report-core.api.md index fe19a8ee4fd..3a31996bbd3 100644 --- a/.api-reports/api-report-core.api.md +++ b/.api-reports/api-report-core.api.md @@ -2432,9 +2432,9 @@ interface WriteContext extends ReadMergeModifyContext { // Warnings were encountered during analysis: // -// src/cache/inmemory/policies.ts:92:3 - (ae-forgotten-export) The symbol "FragmentMap" needs to be exported by the entry point index.d.ts -// src/cache/inmemory/policies.ts:161:3 - (ae-forgotten-export) The symbol "KeySpecifier" needs to be exported by the entry point index.d.ts -// src/cache/inmemory/policies.ts:161:3 - (ae-forgotten-export) The symbol "KeyArgsFunction" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:93:3 - (ae-forgotten-export) The symbol "FragmentMap" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:162:3 - (ae-forgotten-export) The symbol "KeySpecifier" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:162:3 - (ae-forgotten-export) The symbol "KeyArgsFunction" needs to be exported by the entry point index.d.ts // src/cache/inmemory/types.ts:139:3 - (ae-forgotten-export) The symbol "KeyFieldsFunction" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:120:5 - (ae-forgotten-export) The symbol "QueryManager" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:121:5 - (ae-forgotten-export) The symbol "QueryInfo" needs to be exported by the entry point index.d.ts diff --git a/.api-reports/api-report-utilities.api.md b/.api-reports/api-report-utilities.api.md index 451fe8a5d66..32893220155 100644 --- a/.api-reports/api-report-utilities.api.md +++ b/.api-reports/api-report-utilities.api.md @@ -2792,11 +2792,11 @@ interface WriteContext extends ReadMergeModifyContext { // Warnings were encountered during analysis: // // src/cache/core/types/DataProxy.ts:147:7 - (ae-forgotten-export) The symbol "MissingFieldError" needs to be exported by the entry point index.d.ts -// src/cache/inmemory/policies.ts:57:3 - (ae-forgotten-export) The symbol "TypePolicy" needs to be exported by the entry point index.d.ts -// src/cache/inmemory/policies.ts:161:3 - (ae-forgotten-export) The symbol "KeySpecifier" needs to be exported by the entry point index.d.ts -// src/cache/inmemory/policies.ts:161:3 - (ae-forgotten-export) The symbol "KeyArgsFunction" needs to be exported by the entry point index.d.ts -// src/cache/inmemory/policies.ts:162:3 - (ae-forgotten-export) The symbol "FieldReadFunction" needs to be exported by the entry point index.d.ts -// src/cache/inmemory/policies.ts:163:3 - (ae-forgotten-export) The symbol "FieldMergeFunction" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:58:3 - (ae-forgotten-export) The symbol "TypePolicy" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:162:3 - (ae-forgotten-export) The symbol "KeySpecifier" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:162:3 - (ae-forgotten-export) The symbol "KeyArgsFunction" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:163:3 - (ae-forgotten-export) The symbol "FieldReadFunction" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:164:3 - (ae-forgotten-export) The symbol "FieldMergeFunction" needs to be exported by the entry point index.d.ts // src/cache/inmemory/types.ts:139:3 - (ae-forgotten-export) The symbol "KeyFieldsFunction" needs to be exported by the entry point index.d.ts // src/cache/inmemory/writeToStore.ts:65:7 - (ae-forgotten-export) The symbol "MergeTree" needs to be exported by the entry point index.d.ts // src/core/LocalState.ts:71:3 - (ae-forgotten-export) The symbol "ApolloClient" needs to be exported by the entry point index.d.ts diff --git a/.api-reports/api-report.api.md b/.api-reports/api-report.api.md index e94c5e35783..0a2c8f55e31 100644 --- a/.api-reports/api-report.api.md +++ b/.api-reports/api-report.api.md @@ -3143,9 +3143,9 @@ interface WriteContext extends ReadMergeModifyContext { // Warnings were encountered during analysis: // -// src/cache/inmemory/policies.ts:92:3 - (ae-forgotten-export) The symbol "FragmentMap" needs to be exported by the entry point index.d.ts -// src/cache/inmemory/policies.ts:161:3 - (ae-forgotten-export) The symbol "KeySpecifier" needs to be exported by the entry point index.d.ts -// src/cache/inmemory/policies.ts:161:3 - (ae-forgotten-export) The symbol "KeyArgsFunction" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:93:3 - (ae-forgotten-export) The symbol "FragmentMap" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:162:3 - (ae-forgotten-export) The symbol "KeySpecifier" needs to be exported by the entry point index.d.ts +// src/cache/inmemory/policies.ts:162:3 - (ae-forgotten-export) The symbol "KeyArgsFunction" needs to be exported by the entry point index.d.ts // src/cache/inmemory/types.ts:139:3 - (ae-forgotten-export) The symbol "KeyFieldsFunction" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:120:5 - (ae-forgotten-export) The symbol "QueryManager" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:121:5 - (ae-forgotten-export) The symbol "QueryInfo" needs to be exported by the entry point index.d.ts diff --git a/.size-limits.json b/.size-limits.json index 1a3c2258651..8d2b7665bb4 100644 --- a/.size-limits.json +++ b/.size-limits.json @@ -1,4 +1,4 @@ { - "dist/apollo-client.min.cjs": 41506, - "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 34257 + "dist/apollo-client.min.cjs": 41516, + "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 34299 } From a8303d1833b0f5c63718a89cc16cd431630a70e2 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 8 Nov 2024 13:53:20 -0700 Subject: [PATCH 12/14] Add changeset --- .changeset/early-bobcats-eat.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/early-bobcats-eat.md diff --git a/.changeset/early-bobcats-eat.md b/.changeset/early-bobcats-eat.md new file mode 100644 index 00000000000..64907a4bda9 --- /dev/null +++ b/.changeset/early-bobcats-eat.md @@ -0,0 +1,5 @@ +--- +"@apollo/client": patch +--- + +Prevent field accessor warnings when using `@unmask(mode: "migrate")` on objects that are passed into `cache.identify`. From 0a6a3fbc16b2e81a3d3fa30b07b5c68dbd58acc2 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 11 Nov 2024 09:40:53 -0700 Subject: [PATCH 13/14] Wrap slot around while loop --- src/cache/inmemory/policies.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/cache/inmemory/policies.ts b/src/cache/inmemory/policies.ts index a9fdf925126..774c167cd11 100644 --- a/src/cache/inmemory/policies.ts +++ b/src/cache/inmemory/policies.ts @@ -392,17 +392,18 @@ export class Policies { const policy = typename && this.getTypePolicy(typename); let keyFn = (policy && policy.keyFn) || this.config.dataIdFromObject; - while (keyFn) { - const specifierOrId = disableWarningsSlot.withValue(true, () => { - return keyFn!({ ...object, ...storeObject }, context); - }); - if (isArray(specifierOrId)) { - keyFn = keyFieldsFnFromSpecifier(specifierOrId); - } else { - id = specifierOrId; - break; + + disableWarningsSlot.withValue(true, () => { + while (keyFn) { + const specifierOrId = keyFn({ ...object, ...storeObject }, context); + if (isArray(specifierOrId)) { + keyFn = keyFieldsFnFromSpecifier(specifierOrId); + } else { + id = specifierOrId; + break; + } } - } + }); id = id ? String(id) : void 0; return context.keyObject ? [id, context.keyObject] : [id]; From c57ea5154f7544197d58ea3e78ee541ff4a40116 Mon Sep 17 00:00:00 2001 From: jerelmiller Date: Mon, 11 Nov 2024 16:43:17 +0000 Subject: [PATCH 14/14] Clean up Prettier, Size-limit, and Api-Extractor --- .size-limits.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.size-limits.json b/.size-limits.json index 8d2b7665bb4..0a00c26d167 100644 --- a/.size-limits.json +++ b/.size-limits.json @@ -1,4 +1,4 @@ { "dist/apollo-client.min.cjs": 41516, - "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 34299 + "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 34296 }