Skip to content

Commit

Permalink
allow to provide underlying storage for ssr exchange
Browse files Browse the repository at this point in the history
  • Loading branch information
schiller-manuel committed Jan 2, 2025
1 parent 25d114d commit aa3bffb
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/fluffy-mirrors-pretend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@urql/core': minor
---

allow to provide underlying storage for ssr exchange
27 changes: 26 additions & 1 deletion packages/core/src/exchanges/ssr.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Client } from '../client';
import { queryOperation, queryResponse } from '../test-utils';
import { ExchangeIO, Operation, OperationResult } from '../types';
import { CombinedError, formatDocument } from '../utils';
import { ssrExchange } from './ssr';
import { SSRDataStorage, ssrExchange } from './ssr';

let forward: ExchangeIO;
let exchangeInput;
Expand Down Expand Up @@ -52,6 +52,31 @@ it('caches query results correctly', () => {
});
});

it('caches query results correctly when storage is provided', () => {
output.mockReturnValueOnce(queryResponse);

const storage: SSRDataStorage = {};
const ssr = ssrExchange({ storage });
const { source: ops$, next } = input;
const exchange = ssr(exchangeInput)(ops$);

publish(exchange);
next(queryOperation);

const data = ssr.extractData();
expect(storage).toEqual(data);

expect(Object.keys(storage)).toEqual(['' + queryOperation.key]);

expect(storage).toEqual({
[queryOperation.key]: {
data: serializedQueryResponse.data,
error: undefined,
hasNext: false,
},
});
});

it('serializes query results quickly', () => {
const result: OperationResult = {
...queryResponse,
Expand Down
12 changes: 11 additions & 1 deletion packages/core/src/exchanges/ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export interface SSRData {
[key: string]: SerializedResult;
}

export interface SSRDataStorage {
[key: string]: SerializedResult | null;
}

/** 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.
Expand Down Expand Up @@ -74,6 +78,11 @@ export interface SSRExchangeParams {
* not serialize this data by default, unless this flag is set.
*/
includeExtensions?: boolean;

/**
* If provided, this will be used as underlying storage for the serialized results.
*/
storage?: SSRDataStorage;
}

/** An `SSRExchange` either in server-side mode, serializing results, or client-side mode, deserializing and replaying results..
Expand Down Expand Up @@ -188,7 +197,8 @@ const revalidated = new Set<number>();
export const ssrExchange = (params: SSRExchangeParams = {}): SSRExchange => {
const staleWhileRevalidate = !!params.staleWhileRevalidate;
const includeExtensions = !!params.includeExtensions;
const data: Record<string, SerializedResult | null> = {};
const data: Record<string, SerializedResult | null> =
params.storage !== undefined ? params.storage : {};

// 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
Expand Down

0 comments on commit aa3bffb

Please sign in to comment.