From 3a5307b89cd6e712d9812c39dc836829bd8fcd53 Mon Sep 17 00:00:00 2001 From: Bozhidar Hristov Date: Fri, 7 Mar 2025 19:34:30 +0200 Subject: [PATCH 1/3] Allow SSR exchange to use custom serializer --- packages/core/src/exchanges/ssr.ts | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/core/src/exchanges/ssr.ts b/packages/core/src/exchanges/ssr.ts index 6716a54fb9..c928214609 100644 --- a/packages/core/src/exchanges/ssr.ts +++ b/packages/core/src/exchanges/ssr.ts @@ -36,6 +36,9 @@ export interface SSRData { [key: string]: SerializedResult; } +export type Serializer = (data: any) => string +export type Deserializer = (serialized: string) => any + /** Options for the `ssrExchange` allowing it to either operate on the server- or client-side. */ export interface SSRExchangeParams { /** Indicates to the {@link SSRExchange} whether it's currently in server-side or client-side mode. @@ -74,6 +77,10 @@ export interface SSRExchangeParams { * not serialize this data by default, unless this flag is set. */ includeExtensions?: boolean; + + serialize?: Serializer; + + deserialize?: Deserializer; } /** An `SSRExchange` either in server-side mode, serializing results, or client-side mode, deserializing and replaying results.. @@ -106,18 +113,19 @@ export interface SSRExchange extends Exchange { /** Serialize an OperationResult to plain JSON */ const serializeResult = ( result: OperationResult, - includeExtensions: boolean + includeExtensions: boolean, + serializer: Serializer, ): SerializedResult => { const serialized: SerializedResult = { hasNext: result.hasNext, }; if (result.data !== undefined) { - serialized.data = JSON.stringify(result.data); + serialized.data = serializer(result.data); } if (includeExtensions && result.extensions !== undefined) { - serialized.extensions = JSON.stringify(result.extensions); + serialized.extensions = serializer(result.extensions); } if (result.error) { @@ -147,13 +155,14 @@ const serializeResult = ( const deserializeResult = ( operation: Operation, result: SerializedResult, - includeExtensions: boolean + includeExtensions: boolean, + deserializer: Deserializer, ): OperationResult => ({ operation, - data: result.data ? JSON.parse(result.data) : undefined, + data: result.data ? deserializer(result.data) : undefined, extensions: includeExtensions && result.extensions - ? JSON.parse(result.extensions) + ? deserializer(result.extensions) : undefined, error: result.error ? new CombinedError({ @@ -189,6 +198,8 @@ export const ssrExchange = (params: SSRExchangeParams = {}): SSRExchange => { const staleWhileRevalidate = !!params.staleWhileRevalidate; const includeExtensions = !!params.includeExtensions; const data: Record = {}; + const serializer: Serializer = params.serialize ?? JSON.stringify + const deserializer: Deserializer = params.deserialize ?? JSON.parse // On the client-side, we delete results from the cache as they're resolved // this is delayed so that concurrent queries don't delete each other's data @@ -245,7 +256,8 @@ export const ssrExchange = (params: SSRExchangeParams = {}): SSRExchange => { const cachedResult = deserializeResult( op, serialized, - includeExtensions + includeExtensions, + deserializer ); if (staleWhileRevalidate && !revalidated.has(op.key)) { @@ -271,7 +283,7 @@ export const ssrExchange = (params: SSRExchangeParams = {}): SSRExchange => { tap((result: OperationResult) => { const { operation } = result; if (operation.kind !== 'mutation') { - const serialized = serializeResult(result, includeExtensions); + const serialized = serializeResult(result, includeExtensions, serializer); data[operation.key] = serialized; } }) From 7d363b19d5dce273125581ba8cd2008452014b64 Mon Sep 17 00:00:00 2001 From: Bozhidar Hristov Date: Fri, 7 Mar 2025 19:41:03 +0200 Subject: [PATCH 2/3] Allow SSR exchange to use custom serializer --- packages/core/src/exchanges/ssr.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/core/src/exchanges/ssr.ts b/packages/core/src/exchanges/ssr.ts index c928214609..5c0de2d28a 100644 --- a/packages/core/src/exchanges/ssr.ts +++ b/packages/core/src/exchanges/ssr.ts @@ -36,8 +36,8 @@ export interface SSRData { [key: string]: SerializedResult; } -export type Serializer = (data: any) => string -export type Deserializer = (serialized: string) => any +export type Serializer = (data: any) => string; +export type Deserializer = (serialized: string) => any; /** Options for the `ssrExchange` allowing it to either operate on the server- or client-side. */ export interface SSRExchangeParams { @@ -114,7 +114,7 @@ export interface SSRExchange extends Exchange { const serializeResult = ( result: OperationResult, includeExtensions: boolean, - serializer: Serializer, + serializer: Serializer ): SerializedResult => { const serialized: SerializedResult = { hasNext: result.hasNext, @@ -156,7 +156,7 @@ const deserializeResult = ( operation: Operation, result: SerializedResult, includeExtensions: boolean, - deserializer: Deserializer, + deserializer: Deserializer ): OperationResult => ({ operation, data: result.data ? deserializer(result.data) : undefined, @@ -198,8 +198,8 @@ export const ssrExchange = (params: SSRExchangeParams = {}): SSRExchange => { const staleWhileRevalidate = !!params.staleWhileRevalidate; const includeExtensions = !!params.includeExtensions; const data: Record = {}; - const serializer: Serializer = params.serialize ?? JSON.stringify - const deserializer: Deserializer = params.deserialize ?? JSON.parse + const serializer: Serializer = params.serialize ? params.serialize : JSON.stringify; + const deserializer: Deserializer = params.deserialize ? params.deserialize : JSON.parse; // On the client-side, we delete results from the cache as they're resolved // this is delayed so that concurrent queries don't delete each other's data @@ -283,8 +283,11 @@ export const ssrExchange = (params: SSRExchangeParams = {}): SSRExchange => { tap((result: OperationResult) => { const { operation } = result; if (operation.kind !== 'mutation') { - const serialized = serializeResult(result, includeExtensions, serializer); - data[operation.key] = serialized; + data[operation.key] = serializeResult( + result, + includeExtensions, + serializer + ); } }) ); From 07f28a9e20ded16dfc4cd87dc55aaa4b39903d59 Mon Sep 17 00:00:00 2001 From: Bozhidar Hristov Date: Fri, 7 Mar 2025 19:50:15 +0200 Subject: [PATCH 3/3] Allow SSR exchange to use custom serializer --- packages/core/src/exchanges/ssr.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/core/src/exchanges/ssr.ts b/packages/core/src/exchanges/ssr.ts index 5c0de2d28a..55bd95d292 100644 --- a/packages/core/src/exchanges/ssr.ts +++ b/packages/core/src/exchanges/ssr.ts @@ -198,8 +198,12 @@ export const ssrExchange = (params: SSRExchangeParams = {}): SSRExchange => { const staleWhileRevalidate = !!params.staleWhileRevalidate; const includeExtensions = !!params.includeExtensions; const data: Record = {}; - const serializer: Serializer = params.serialize ? params.serialize : JSON.stringify; - const deserializer: Deserializer = params.deserialize ? params.deserialize : JSON.parse; + const serializer: Serializer = params.serialize + ? params.serialize + : JSON.stringify; + const deserializer: Deserializer = params.deserialize + ? params.deserialize + : JSON.parse; // On the client-side, we delete results from the cache as they're resolved // this is delayed so that concurrent queries don't delete each other's data