From f20bf938e75acf8c40f71662a882a58c1b0a0931 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 4 Aug 2025 16:39:22 -0600 Subject: [PATCH 1/4] Use JSON.stringify directly and don't wrap in class --- src/__tests__/__snapshots__/exports.ts.snap | 3 --- src/core/index.ts | 2 -- src/link/batch-http/batchHttpLink.ts | 3 +-- src/link/http/BaseHttpLink.ts | 3 +-- src/link/http/__tests__/HttpLink.ts | 19 ++++------------ .../http/__tests__/serializeFetchParameter.ts | 17 -------------- src/link/http/index.ts | 2 -- src/link/http/rewriteURIForGET.ts | 11 ++-------- src/link/http/serializeFetchParameter.ts | 22 ------------------- src/utilities/subscriptions/relay/index.ts | 3 +-- 10 files changed, 9 insertions(+), 76 deletions(-) delete mode 100644 src/link/http/__tests__/serializeFetchParameter.ts delete mode 100644 src/link/http/serializeFetchParameter.ts diff --git a/src/__tests__/__snapshots__/exports.ts.snap b/src/__tests__/__snapshots__/exports.ts.snap index 7238d428751..43841e8f502 100644 --- a/src/__tests__/__snapshots__/exports.ts.snap +++ b/src/__tests__/__snapshots__/exports.ts.snap @@ -43,7 +43,6 @@ Array [ "selectHttpOptionsAndBody", "selectHttpOptionsAndBodyInternal", "selectURI", - "serializeFetchParameter", "setLogVerbosity", "split", "version", @@ -110,7 +109,6 @@ Array [ "selectHttpOptionsAndBody", "selectHttpOptionsAndBodyInternal", "selectURI", - "serializeFetchParameter", "setLogVerbosity", "split", "version", @@ -210,7 +208,6 @@ Array [ "selectHttpOptionsAndBody", "selectHttpOptionsAndBodyInternal", "selectURI", - "serializeFetchParameter", ] `; diff --git a/src/core/index.ts b/src/core/index.ts index 8a3ec1ca63c..431c2ded247 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -133,9 +133,7 @@ export { // TODO remove: needed by @apollo/client/link/batch-http but not public selectHttpOptionsAndBodyInternal, selectURI, - serializeFetchParameter, } from "@apollo/client/link/http"; -export type { ClientParseError } from "@apollo/client/link/http"; /* Masking */ export type { diff --git a/src/link/batch-http/batchHttpLink.ts b/src/link/batch-http/batchHttpLink.ts index 26a5fe928f8..c3501f9e9b6 100644 --- a/src/link/batch-http/batchHttpLink.ts +++ b/src/link/batch-http/batchHttpLink.ts @@ -12,7 +12,6 @@ import { parseAndCheckHttpResponse, selectHttpOptionsAndBodyInternal, selectURI, - serializeFetchParameter, } from "@apollo/client/link/http"; import { filterOperationVariables } from "@apollo/client/link/utils"; import { __DEV__ } from "@apollo/client/utilities/environment"; @@ -132,7 +131,7 @@ export class BaseBatchHttpLink extends ApolloLink { } try { - (options as any).body = serializeFetchParameter(loadedBody, "Payload"); + (options as any).body = JSON.stringify(loadedBody); } catch (parseError) { return throwError(() => parseError); } diff --git a/src/link/http/BaseHttpLink.ts b/src/link/http/BaseHttpLink.ts index fab3dab639b..94ca367dc1b 100644 --- a/src/link/http/BaseHttpLink.ts +++ b/src/link/http/BaseHttpLink.ts @@ -23,7 +23,6 @@ import { selectHttpOptionsAndBodyInternal, } from "./selectHttpOptionsAndBody.js"; import { selectURI } from "./selectURI.js"; -import { serializeFetchParameter } from "./serializeFetchParameter.js"; const backupFetch = maybe(() => fetch); @@ -108,7 +107,7 @@ export class BaseHttpLink extends ApolloLink { } chosenURI = newURI; } else { - options.body = serializeFetchParameter(body, "Payload"); + options.body = JSON.stringify(body); } // Prefer linkOptions.fetch (preferredFetch) if provided, and otherwise // fall back to the *current* global window.fetch function (see issue diff --git a/src/link/http/__tests__/HttpLink.ts b/src/link/http/__tests__/HttpLink.ts index 4508c1f6cbb..3999e09f92b 100644 --- a/src/link/http/__tests__/HttpLink.ts +++ b/src/link/http/__tests__/HttpLink.ts @@ -32,8 +32,6 @@ import { wait, } from "@apollo/client/testing/internal"; -import type { ClientParseError } from "../serializeFetchParameter.js"; - import { voidFetchDuringEachTest } from "./helpers.js"; const sampleQuery = gql` @@ -395,10 +393,7 @@ describe("HttpLink", () => { const error = await stream.takeError(); - expect(error.message).toMatch(/Variables map is not serializable/); - expect(error.parseError.message).toMatch( - /Converting circular structure to JSON/ - ); + expect(error.message).toMatch(/Converting circular structure to JSON/); }); it("throws for GET if the extensions can't be stringified", async () => { @@ -421,10 +416,7 @@ describe("HttpLink", () => { const error = await stream.takeError(); - expect(error.message).toMatch(/Extensions map is not serializable/); - expect(error.parseError.message).toMatch( - /Converting circular structure to JSON/ - ); + expect(error.message).toMatch(/Converting circular structure to JSON/); }); it("does not need any constructor arguments", () => { @@ -1115,12 +1107,9 @@ describe("HttpLink", () => { const observable = execute(link, { query: sampleQuery, variables }); const stream = new ObservableStream(observable); - const error: ClientParseError = await stream.takeError(); + const error = await stream.takeError(); - expect(error.message).toMatch(/Payload is not serializable/); - expect(error.parseError.message).toMatch( - /Converting circular structure to JSON/ - ); + expect(error.message).toMatch(/Converting circular structure to JSON/); }); describe("AbortController", () => { diff --git a/src/link/http/__tests__/serializeFetchParameter.ts b/src/link/http/__tests__/serializeFetchParameter.ts deleted file mode 100644 index 3f9da18aece..00000000000 --- a/src/link/http/__tests__/serializeFetchParameter.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { serializeFetchParameter } from "@apollo/client/link/http"; - -describe("serializeFetchParameter", () => { - it("throws a parse error on an unparsable body", () => { - const b = {}; - const a = { b }; - (b as any).a = a; - - expect(() => serializeFetchParameter(b, "Label")).toThrow(/Label/); - }); - - it("returns a correctly parsed body", () => { - const body = { no: "thing" }; - - expect(serializeFetchParameter(body, "Label")).toEqual('{"no":"thing"}'); - }); -}); diff --git a/src/link/http/index.ts b/src/link/http/index.ts index d0604076e79..a1f7b60690c 100644 --- a/src/link/http/index.ts +++ b/src/link/http/index.ts @@ -1,6 +1,4 @@ export { parseAndCheckHttpResponse } from "./parseAndCheckHttpResponse.js"; -export type { ClientParseError } from "./serializeFetchParameter.js"; -export { serializeFetchParameter } from "./serializeFetchParameter.js"; export { defaultPrinter, fallbackHttpConfig, diff --git a/src/link/http/rewriteURIForGET.ts b/src/link/http/rewriteURIForGET.ts index 0627082e3e2..1469abe983d 100644 --- a/src/link/http/rewriteURIForGET.ts +++ b/src/link/http/rewriteURIForGET.ts @@ -1,5 +1,4 @@ import type { HttpLink } from "./HttpLink.js"; -import { serializeFetchParameter } from "./serializeFetchParameter.js"; // For GET operations, returns the given URI rewritten with parameters, or a // parse error. @@ -20,10 +19,7 @@ export function rewriteURIForGET(chosenURI: string, body: HttpLink.Body) { if (body.variables) { let serializedVariables; try { - serializedVariables = serializeFetchParameter( - body.variables, - "Variables map" - ); + serializedVariables = JSON.stringify(body.variables); } catch (parseError) { return { parseError }; } @@ -32,10 +28,7 @@ export function rewriteURIForGET(chosenURI: string, body: HttpLink.Body) { if (body.extensions) { let serializedExtensions; try { - serializedExtensions = serializeFetchParameter( - body.extensions, - "Extensions map" - ); + serializedExtensions = JSON.stringify(body.extensions); } catch (parseError) { return { parseError }; } diff --git a/src/link/http/serializeFetchParameter.ts b/src/link/http/serializeFetchParameter.ts deleted file mode 100644 index 964c443766d..00000000000 --- a/src/link/http/serializeFetchParameter.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { InvariantError } from "@apollo/client/utilities/invariant"; -import { newInvariantError } from "@apollo/client/utilities/invariant"; - -export type ClientParseError = InvariantError & { - parseError: Error; -}; - -export const serializeFetchParameter = (p: any, label: string) => { - let serialized; - try { - serialized = JSON.stringify(p); - } catch (e: any) { - const parseError = newInvariantError( - `Network request failed. %s is not serializable: %s`, - label, - e.message - ) as ClientParseError; - parseError.parseError = e; - throw parseError; - } - return serialized; -}; diff --git a/src/utilities/subscriptions/relay/index.ts b/src/utilities/subscriptions/relay/index.ts index c006cc1fbe3..f17533e5072 100644 --- a/src/utilities/subscriptions/relay/index.ts +++ b/src/utilities/subscriptions/relay/index.ts @@ -2,7 +2,6 @@ import type { GraphQLResponse, RequestParameters } from "relay-runtime"; import { Observable } from "relay-runtime"; import type { OperationVariables } from "@apollo/client"; -import { serializeFetchParameter } from "@apollo/client"; import type { HttpLink } from "@apollo/client/link/http"; import { maybe } from "@apollo/client/utilities/internal/globals"; @@ -35,7 +34,7 @@ export function createFetchMultipartSubscription( return Observable.create((sink) => { try { - options.body = serializeFetchParameter(body, "Payload"); + options.body = JSON.stringify(body); } catch (parseError) { sink.error(parseError as Error); } From 6fbe75f7d34e4b0692bf1bdc6ee5e36353038c04 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 4 Aug 2025 16:41:04 -0600 Subject: [PATCH 2/4] Add changeset --- .changeset/friendly-news-drive.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/friendly-news-drive.md diff --git a/.changeset/friendly-news-drive.md b/.changeset/friendly-news-drive.md new file mode 100644 index 00000000000..434b76ecb68 --- /dev/null +++ b/.changeset/friendly-news-drive.md @@ -0,0 +1,5 @@ +--- +"@apollo/client": major +--- + +The `serializeFetchParameter` helper is no longer exported and `JSON.stringify` is used directly. As such, the `ClientParseError` type has also been removed in favor of throwing any JSON serialize errors directly. From 78660ed8a45328688834b9561154bd99eb9499d3 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 4 Aug 2025 16:42:41 -0600 Subject: [PATCH 3/4] chores --- .api-reports/api-report-core.api.md | 6 ------ .api-reports/api-report-link_http.api.md | 9 --------- .api-reports/api-report.api.md | 15 --------------- .size-limits.json | 8 ++++---- 4 files changed, 4 insertions(+), 34 deletions(-) diff --git a/.api-reports/api-report-core.api.md b/.api-reports/api-report-core.api.md index 6a0a6495a88..b51775b5f8f 100644 --- a/.api-reports/api-report-core.api.md +++ b/.api-reports/api-report-core.api.md @@ -12,7 +12,6 @@ import type { ApplyHKTImplementationWithDefault } from '@apollo/client/utilities import { Cache as Cache_2 } from '@apollo/client/cache'; import { checkFetcher } from '@apollo/client/link/http'; import type { ClientAwarenessLink } from '@apollo/client/link/client-awareness'; -import { ClientParseError } from '@apollo/client/link/http'; import { CombinedGraphQLErrors } from '@apollo/client/errors'; import { CombinedProtocolErrors } from '@apollo/client/errors'; import { concat } from '@apollo/client/link'; @@ -88,7 +87,6 @@ import { rewriteURIForGET } from '@apollo/client/link/http'; import { selectHttpOptionsAndBody } from '@apollo/client/link/http'; import { selectHttpOptionsAndBodyInternal } from '@apollo/client/link/http'; import { selectURI } from '@apollo/client/link/http'; -import { serializeFetchParameter } from '@apollo/client/link/http'; import { ServerError } from '@apollo/client/errors'; import { ServerParseError } from '@apollo/client/errors'; import { setVerbosity as setLogVerbosity } from '@apollo/client/utilities/invariant'; @@ -388,8 +386,6 @@ export { Cache_2 as Cache } export { checkFetcher } -export { ClientParseError } - export { CombinedGraphQLErrors } export { CombinedProtocolErrors } @@ -1031,8 +1027,6 @@ export { selectHttpOptionsAndBodyInternal } export { selectURI } -export { serializeFetchParameter } - export { ServerError } export { ServerParseError } diff --git a/.api-reports/api-report-link_http.api.md b/.api-reports/api-report-link_http.api.md index 11346eeb050..f5434e67405 100644 --- a/.api-reports/api-report-link_http.api.md +++ b/.api-reports/api-report-link_http.api.md @@ -7,7 +7,6 @@ import { ApolloLink } from '@apollo/client/link'; import type { ASTNode } from 'graphql'; import { ClientAwarenessLink } from '@apollo/client/link/client-awareness'; -import type { InvariantError } from '@apollo/client/utilities/invariant'; import type { print as print_2 } from '@apollo/client/utilities'; // @public (undocumented) @@ -18,11 +17,6 @@ export class BaseHttpLink extends ApolloLink { // @public (undocumented) export const checkFetcher: (fetcher: typeof fetch | undefined) => void; -// @public (undocumented) -export type ClientParseError = InvariantError & { - parseError: Error; -}; - // @public @deprecated (undocumented) export const createHttpLink: (linkOptions?: HttpLink.Options & ClientAwarenessLink.Options) => HttpLink; @@ -140,9 +134,6 @@ export function selectHttpOptionsAndBodyInternal(operation: ApolloLink.Operation // @public (undocumented) export const selectURI: (operation: ApolloLink.Operation, fallbackURI?: string | ((operation: ApolloLink.Operation) => string)) => any; -// @public (undocumented) -export const serializeFetchParameter: (p: any, label: string) => string; - // (No @packageDocumentation comment for this package) ``` diff --git a/.api-reports/api-report.api.md b/.api-reports/api-report.api.md index a4fecc6d549..a60d192a005 100644 --- a/.api-reports/api-report.api.md +++ b/.api-reports/api-report.api.md @@ -679,13 +679,6 @@ class ClientAwarenessLink extends ApolloLink { constructor(constructorOptions?: ClientAwarenessLink.Options); } -// Warning: (ae-forgotten-export) The symbol "InvariantError" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -export type ClientParseError = InvariantError & { - parseError: Error; -}; - // Warning: (ae-forgotten-export) The symbol "Prettify" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "MergeUnions" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "ExtractByMatchingTypeNames" needs to be exported by the entry point index.d.ts @@ -1566,11 +1559,6 @@ interface InvalidateModifier { // @public (undocumented) const _invalidateModifier: unique symbol; -// @public (undocumented) -class InvariantError extends Error { - constructor(message?: string); -} - // @internal @deprecated (undocumented) type IsAny = 0 extends 1 & T ? true : false; @@ -2545,9 +2533,6 @@ export function selectHttpOptionsAndBodyInternal(operation: ApolloLink.Operation // @public (undocumented) export const selectURI: (operation: ApolloLink.Operation, fallbackURI?: string | ((operation: ApolloLink.Operation) => string)) => any; -// @public (undocumented) -export const serializeFetchParameter: (p: any, label: string) => string; - // @public (undocumented) export namespace ServerError { // (undocumented) diff --git a/.size-limits.json b/.size-limits.json index 170e634388d..bb29577b883 100644 --- a/.size-limits.json +++ b/.size-limits.json @@ -1,6 +1,6 @@ { - "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (CJS)": 43862, - "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production) (CJS)": 38777, - "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\"": 33487, - "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production)": 27626 + "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (CJS)": 43708, + "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production) (CJS)": 38584, + "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\"": 33364, + "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production)": 27561 } From ffa09b88b44c92e5362a9b6ebfa770c0d3e49a65 Mon Sep 17 00:00:00 2001 From: jerelmiller <565661+jerelmiller@users.noreply.github.com> Date: Tue, 5 Aug 2025 14:54:19 +0000 Subject: [PATCH 4/4] Clean up Prettier, Size-limit, and Api-Extractor --- .size-limits.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.size-limits.json b/.size-limits.json index bb29577b883..86a6a779747 100644 --- a/.size-limits.json +++ b/.size-limits.json @@ -1,6 +1,6 @@ { - "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (CJS)": 43708, - "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production) (CJS)": 38584, - "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\"": 33364, - "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production)": 27561 + "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (CJS)": 43798, + "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production) (CJS)": 38629, + "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\"": 33543, + "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production)": 27562 }