@tanstack/react-query-next-experimental 5.103.3 → 5.104.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,13 +3,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
4
4
  const require_htmlescape = require("./htmlescape.cjs");
5
5
  let _tanstack_react_query = require("@tanstack/react-query");
6
- let next_navigation_js = require("next/navigation.js");
6
+ let next_navigation = require("next/navigation");
7
7
  let react = require("react");
8
8
  react = require_rolldown_runtime.__toESM(react, 1);
9
9
  let react_jsx_runtime = require("react/jsx-runtime");
10
10
  //#region src/HydrationStreamProvider.tsx
11
11
  function createHydrationStreamProvider() {
12
- const context = react.createContext(null);
12
+ const StreamContext = react.createContext(null);
13
13
  /**
14
14
 
15
15
  * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes
@@ -30,8 +30,8 @@ function createHydrationStreamProvider() {
30
30
  if (!_tanstack_react_query.environmentManager.isServer()) return { push() {} };
31
31
  return [];
32
32
  });
33
- const count = react.useRef(0);
34
- (0, next_navigation_js.useServerInsertedHTML)(() => {
33
+ const countRef = react.useRef(0);
34
+ (0, next_navigation.useServerInsertedHTML)(() => {
35
35
  var _props$onFlush;
36
36
  stream.push(...((_props$onFlush = props.onFlush) === null || _props$onFlush === void 0 ? void 0 : _props$onFlush.call(props)) ?? []);
37
37
  if (!stream.length) return null;
@@ -41,7 +41,7 @@ function createHydrationStreamProvider() {
41
41
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("script", {
42
42
  nonce: props.nonce,
43
43
  dangerouslySetInnerHTML: { __html: html.join("") }
44
- }, count.current++);
44
+ }, countRef.current++);
45
45
  });
46
46
  if (!_tanstack_react_query.environmentManager.isServer()) {
47
47
  var _win$id;
@@ -58,7 +58,7 @@ function createHydrationStreamProvider() {
58
58
  };
59
59
  }
60
60
  }
61
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(context.Provider, {
61
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StreamContext.Provider, {
62
62
  value: {
63
63
  stream,
64
64
  id
@@ -68,7 +68,7 @@ function createHydrationStreamProvider() {
68
68
  }
69
69
  return {
70
70
  Provider: UseClientHydrationStreamProvider,
71
- context
71
+ context: StreamContext
72
72
  };
73
73
  }
74
74
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"HydrationStreamProvider.cjs","names":["React","htmlEscapeJsonString","environmentManager"],"sources":["../../src/HydrationStreamProvider.tsx"],"sourcesContent":["'use client'\n\nimport { environmentManager } from '@tanstack/react-query'\nimport { useServerInsertedHTML } from 'next/navigation'\nimport * as React from 'react'\nimport { htmlEscapeJsonString } from './htmlescape'\n\nconst serializedSymbol = Symbol('serialized')\n\ninterface DataTransformer {\n serialize: (object: any) => any\n deserialize: (object: any) => any\n}\n\ntype Serialized<TData> = unknown & {\n [serializedSymbol]: TData\n}\n\ninterface TypedDataTransformer<TData> {\n serialize: (obj: TData) => Serialized<TData>\n deserialize: (obj: Serialized<TData>) => TData\n}\n\ninterface HydrationStreamContext<TShape> {\n id: string\n stream: {\n /**\n * **Server method**\n * Push a new entry to the stream\n * Will be ignored on the client\n */\n push: (...shape: Array<TShape>) => void\n }\n}\n\nexport interface HydrationStreamProviderProps<TShape> {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n}\n\nexport function createHydrationStreamProvider<TShape>() {\n const context = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n\n * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes\n * - This means that we might have some new entries in the cache that needs to be flushed\n * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`\n * 2. (Happens in browser) In `useEffect()`:\n * - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries\n * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received\n **/\n function UseClientHydrationStreamProvider(props: {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n }) {\n // unique id for the cache provider\n const id = `__RQ${React.useId()}`\n const idJSON = htmlEscapeJsonString(JSON.stringify(id))\n\n const [transformer] = React.useState(\n () =>\n (props.transformer ?? {\n // noop\n serialize: (obj: any) => obj,\n deserialize: (obj: any) => obj,\n }) as unknown as TypedDataTransformer<TShape>,\n )\n\n // <server stuff>\n const [stream] = React.useState<Array<TShape>>(() => {\n if (!environmentManager.isServer()) {\n return {\n push() {\n // no-op on the client\n },\n } as unknown as Array<TShape>\n }\n return []\n })\n const count = React.useRef(0)\n useServerInsertedHTML(() => {\n // This only happens on the server\n stream.push(...(props.onFlush?.() ?? []))\n\n if (!stream.length) {\n return null\n }\n // console.log(`pushing ${stream.length} entries`)\n const serializedCacheArgs = stream\n .map((entry) => transformer.serialize(entry))\n .map((entry) => JSON.stringify(entry))\n .join(',')\n\n // Flush stream\n // eslint-disable-next-line react-hooks/immutability\n stream.length = 0\n\n const html: Array<string> = [\n `window[${idJSON}] = window[${idJSON}] || [];`,\n `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,\n ]\n return (\n <script\n key={count.current++}\n nonce={props.nonce}\n dangerouslySetInnerHTML={{\n __html: html.join(''),\n }}\n />\n )\n })\n // </server stuff>\n\n // <client stuff>\n // Setup and run the onEntries handler on the client only, but do it during\n // the initial render so children have access to the data immediately\n // This is important to avoid the client suspending during the initial render\n // if the data has not yet been hydrated.\n if (!environmentManager.isServer()) {\n const win = window as any\n if (!win[id]?.initialized) {\n // Client: consume cache:\n const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {\n const entries = serializedEntries.map((serialized) =>\n transformer.deserialize(serialized),\n )\n props.onEntries(entries)\n }\n\n const winStream: Array<Serialized<TShape>> = win[id] ?? []\n\n onEntries(...winStream)\n\n // eslint-disable-next-line react-hooks/immutability\n win[id] = {\n initialized: true,\n push: onEntries,\n }\n }\n }\n // </client stuff>\n\n return (\n <context.Provider value={{ stream, id }}>\n {props.children}\n </context.Provider>\n )\n }\n\n return {\n Provider: UseClientHydrationStreamProvider,\n context,\n }\n}\n"],"mappings":";;;;;;;;;;AA0DA,SAAgB,gCAAwC;CACtD,MAAM,UAAUA,MAAM,cACpB,IACF;;;;;;;;;;CAUA,SAAS,iCAAiC,OAqBvC;EAED,MAAM,KAAK,OAAOA,MAAM,MAAM;EAC9B,MAAM,SAASC,mBAAAA,qBAAqB,KAAK,UAAU,EAAE,CAAC;EAEtD,MAAM,CAAC,eAAeD,MAAM,eAEvB,MAAM,eAAe;GAEpB,YAAY,QAAa;GACzB,cAAc,QAAa;EAC7B,CACJ;EAGA,MAAM,CAAC,UAAUA,MAAM,eAA8B;GACnD,IAAI,CAACE,sBAAAA,mBAAmB,SAAS,GAC/B,OAAO,EACL,OAAO,CAEP,EACF;GAEF,OAAO,CAAC;EACV,CAAC;EACD,MAAM,QAAQF,MAAM,OAAO,CAAC;EAC5B,CAAA,GAAA,mBAAA,sBAAA,OAA4B;;GAE1B,OAAO,KAAK,KAAA,iBAAI,MAAM,aAAA,QAAA,mBAAA,KAAA,IAAA,KAAA,IAAA,eAAA,KAAA,KAAU,MAAK,CAAC,CAAE;GAExC,IAAI,CAAC,OAAO,QACV,OAAO;GAGT,MAAM,sBAAsB,OACzB,KAAK,UAAU,YAAY,UAAU,KAAK,CAAC,CAAC,CAC5C,KAAK,UAAU,KAAK,UAAU,KAAK,CAAC,CAAC,CACrC,KAAK,GAAG;GAIX,OAAO,SAAS;GAEhB,MAAM,OAAsB,CAC1B,UAAU,OAAO,aAAa,OAAO,WACrC,UAAU,OAAO,SAASC,mBAAAA,qBAAqB,mBAAmB,EAAE,GACtE;GACA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;IAEE,OAAO,MAAM;IACb,yBAAyB,EACvB,QAAQ,KAAK,KAAK,EAAE,EACtB;GACD,GALM,MAAM,SAKZ;EAEL,CAAC;EAQD,IAAI,CAACC,sBAAAA,mBAAmB,SAAS,GAAG;;GAClC,MAAM,MAAM;GACZ,IAAI,GAAA,UAAC,IAAI,SAAA,QAAA,YAAA,KAAA,IAAA,KAAA,IAAA,QAAK,cAAa;IAEzB,MAAM,aAAa,GAAG,sBAAiD;KACrE,MAAM,UAAU,kBAAkB,KAAK,eACrC,YAAY,YAAY,UAAU,CACpC;KACA,MAAM,UAAU,OAAO;IACzB;IAIA,UAAU,GAFmC,IAAI,OAAO,CAAC,CAEnC;IAGtB,IAAI,MAAM;KACR,aAAa;KACb,MAAM;IACR;GACF;EACF;EAGA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAQ,UAAT;GAAkB,OAAO;IAAE;IAAQ;GAAG;GACnC,UAAA,MAAM;EACS,CAAA;CAEtB;CAEA,OAAO;EACL,UAAU;EACV;CACF;AACF"}
1
+ {"version":3,"file":"HydrationStreamProvider.cjs","names":["React","htmlEscapeJsonString","environmentManager"],"sources":["../../src/HydrationStreamProvider.tsx"],"sourcesContent":["'use client'\n\nimport { environmentManager } from '@tanstack/react-query'\nimport { useServerInsertedHTML } from 'next/navigation'\nimport * as React from 'react'\nimport { htmlEscapeJsonString } from './htmlescape'\n\nconst serializedSymbol = Symbol('serialized')\n\ninterface DataTransformer {\n serialize: (object: any) => any\n deserialize: (object: any) => any\n}\n\ntype Serialized<TData> = unknown & {\n [serializedSymbol]: TData\n}\n\ninterface TypedDataTransformer<TData> {\n serialize: (obj: TData) => Serialized<TData>\n deserialize: (obj: Serialized<TData>) => TData\n}\n\ninterface HydrationStreamContext<TShape> {\n id: string\n stream: {\n /**\n * **Server method**\n * Push a new entry to the stream\n * Will be ignored on the client\n */\n push: (...shape: Array<TShape>) => void\n }\n}\n\nexport interface HydrationStreamProviderProps<TShape> {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n}\n\nexport function createHydrationStreamProvider<TShape>() {\n const StreamContext = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n\n * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes\n * - This means that we might have some new entries in the cache that needs to be flushed\n * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`\n * 2. (Happens in browser) In `useEffect()`:\n * - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries\n * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received\n **/\n function UseClientHydrationStreamProvider(props: {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n }) {\n // unique id for the cache provider\n const id = `__RQ${React.useId()}`\n const idJSON = htmlEscapeJsonString(JSON.stringify(id))\n\n const [transformer] = React.useState(\n () =>\n (props.transformer ?? {\n // noop\n serialize: (obj: any) => obj,\n deserialize: (obj: any) => obj,\n }) as unknown as TypedDataTransformer<TShape>,\n )\n\n // <server stuff>\n const [stream] = React.useState<Array<TShape>>(() => {\n if (!environmentManager.isServer()) {\n return {\n push() {\n // no-op on the client\n },\n } as unknown as Array<TShape>\n }\n return []\n })\n const countRef = React.useRef(0)\n useServerInsertedHTML(() => {\n // This only happens on the server\n stream.push(...(props.onFlush?.() ?? []))\n\n if (!stream.length) {\n return null\n }\n // console.log(`pushing ${stream.length} entries`)\n const serializedCacheArgs = stream\n .map((entry) => transformer.serialize(entry))\n .map((entry) => JSON.stringify(entry))\n .join(',')\n\n // Flush stream\n stream.length = 0\n\n const html: Array<string> = [\n `window[${idJSON}] = window[${idJSON}] || [];`,\n `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,\n ]\n return (\n <script\n key={countRef.current++}\n nonce={props.nonce}\n dangerouslySetInnerHTML={{\n __html: html.join(''),\n }}\n />\n )\n })\n // </server stuff>\n\n // <client stuff>\n // Setup and run the onEntries handler on the client only, but do it during\n // the initial render so children have access to the data immediately\n // This is important to avoid the client suspending during the initial render\n // if the data has not yet been hydrated.\n if (!environmentManager.isServer()) {\n const win = window as any\n if (!win[id]?.initialized) {\n // Client: consume cache:\n const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {\n const entries = serializedEntries.map((serialized) =>\n transformer.deserialize(serialized),\n )\n props.onEntries(entries)\n }\n\n const winStream: Array<Serialized<TShape>> = win[id] ?? []\n\n onEntries(...winStream)\n\n win[id] = {\n initialized: true,\n push: onEntries,\n }\n }\n }\n // </client stuff>\n\n return (\n <StreamContext.Provider value={{ stream, id }}>\n {props.children}\n </StreamContext.Provider>\n )\n }\n\n return {\n Provider: UseClientHydrationStreamProvider,\n context: StreamContext,\n }\n}\n"],"mappings":";;;;;;;;;;AA0DA,SAAgB,gCAAwC;CACtD,MAAM,gBAAgBA,MAAM,cAC1B,IACF;;;;;;;;;;CAUA,SAAS,iCAAiC,OAqBvC;EAED,MAAM,KAAK,OAAOA,MAAM,MAAM;EAC9B,MAAM,SAASC,mBAAAA,qBAAqB,KAAK,UAAU,EAAE,CAAC;EAEtD,MAAM,CAAC,eAAeD,MAAM,eAEvB,MAAM,eAAe;GAEpB,YAAY,QAAa;GACzB,cAAc,QAAa;EAC7B,CACJ;EAGA,MAAM,CAAC,UAAUA,MAAM,eAA8B;GACnD,IAAI,CAACE,sBAAAA,mBAAmB,SAAS,GAC/B,OAAO,EACL,OAAO,CAEP,EACF;GAEF,OAAO,CAAC;EACV,CAAC;EACD,MAAM,WAAWF,MAAM,OAAO,CAAC;EAC/B,CAAA,GAAA,gBAAA,sBAAA,OAA4B;;GAE1B,OAAO,KAAK,KAAA,iBAAI,MAAM,aAAA,QAAA,mBAAA,KAAA,IAAA,KAAA,IAAA,eAAA,KAAA,KAAU,MAAK,CAAC,CAAE;GAExC,IAAI,CAAC,OAAO,QACV,OAAO;GAGT,MAAM,sBAAsB,OACzB,KAAK,UAAU,YAAY,UAAU,KAAK,CAAC,CAAC,CAC5C,KAAK,UAAU,KAAK,UAAU,KAAK,CAAC,CAAC,CACrC,KAAK,GAAG;GAGX,OAAO,SAAS;GAEhB,MAAM,OAAsB,CAC1B,UAAU,OAAO,aAAa,OAAO,WACrC,UAAU,OAAO,SAASC,mBAAAA,qBAAqB,mBAAmB,EAAE,GACtE;GACA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;IAEE,OAAO,MAAM;IACb,yBAAyB,EACvB,QAAQ,KAAK,KAAK,EAAE,EACtB;GACD,GALM,SAAS,SAKf;EAEL,CAAC;EAQD,IAAI,CAACC,sBAAAA,mBAAmB,SAAS,GAAG;;GAClC,MAAM,MAAM;GACZ,IAAI,GAAA,UAAC,IAAI,SAAA,QAAA,YAAA,KAAA,IAAA,KAAA,IAAA,QAAK,cAAa;IAEzB,MAAM,aAAa,GAAG,sBAAiD;KACrE,MAAM,UAAU,kBAAkB,KAAK,eACrC,YAAY,YAAY,UAAU,CACpC;KACA,MAAM,UAAU,OAAO;IACzB;IAIA,UAAU,GAFmC,IAAI,OAAO,CAAC,CAEnC;IAEtB,IAAI,MAAM;KACR,aAAa;KACb,MAAM;IACR;GACF;EACF;EAGA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,cAAc,UAAf;GAAwB,OAAO;IAAE;IAAQ;GAAG;GACzC,UAAA,MAAM;EACe,CAAA;CAE5B;CAEA,OAAO;EACL,UAAU;EACV,SAAS;CACX;AACF"}
@@ -1,12 +1,12 @@
1
1
  "use client";
2
2
  import { htmlEscapeJsonString } from "./htmlescape.js";
3
3
  import { environmentManager } from "@tanstack/react-query";
4
- import { useServerInsertedHTML } from "next/navigation.js";
4
+ import { useServerInsertedHTML } from "next/navigation";
5
5
  import * as React from "react";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  //#region src/HydrationStreamProvider.tsx
8
8
  function createHydrationStreamProvider() {
9
- const context = React.createContext(null);
9
+ const StreamContext = React.createContext(null);
10
10
  /**
11
11
 
12
12
  * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes
@@ -27,7 +27,7 @@ function createHydrationStreamProvider() {
27
27
  if (!environmentManager.isServer()) return { push() {} };
28
28
  return [];
29
29
  });
30
- const count = React.useRef(0);
30
+ const countRef = React.useRef(0);
31
31
  useServerInsertedHTML(() => {
32
32
  var _props$onFlush;
33
33
  stream.push(...((_props$onFlush = props.onFlush) === null || _props$onFlush === void 0 ? void 0 : _props$onFlush.call(props)) ?? []);
@@ -38,7 +38,7 @@ function createHydrationStreamProvider() {
38
38
  return /* @__PURE__ */ jsx("script", {
39
39
  nonce: props.nonce,
40
40
  dangerouslySetInnerHTML: { __html: html.join("") }
41
- }, count.current++);
41
+ }, countRef.current++);
42
42
  });
43
43
  if (!environmentManager.isServer()) {
44
44
  var _win$id;
@@ -55,7 +55,7 @@ function createHydrationStreamProvider() {
55
55
  };
56
56
  }
57
57
  }
58
- return /* @__PURE__ */ jsx(context.Provider, {
58
+ return /* @__PURE__ */ jsx(StreamContext.Provider, {
59
59
  value: {
60
60
  stream,
61
61
  id
@@ -65,7 +65,7 @@ function createHydrationStreamProvider() {
65
65
  }
66
66
  return {
67
67
  Provider: UseClientHydrationStreamProvider,
68
- context
68
+ context: StreamContext
69
69
  };
70
70
  }
71
71
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"HydrationStreamProvider.js","names":[],"sources":["../../src/HydrationStreamProvider.tsx"],"sourcesContent":["'use client'\n\nimport { environmentManager } from '@tanstack/react-query'\nimport { useServerInsertedHTML } from 'next/navigation'\nimport * as React from 'react'\nimport { htmlEscapeJsonString } from './htmlescape'\n\nconst serializedSymbol = Symbol('serialized')\n\ninterface DataTransformer {\n serialize: (object: any) => any\n deserialize: (object: any) => any\n}\n\ntype Serialized<TData> = unknown & {\n [serializedSymbol]: TData\n}\n\ninterface TypedDataTransformer<TData> {\n serialize: (obj: TData) => Serialized<TData>\n deserialize: (obj: Serialized<TData>) => TData\n}\n\ninterface HydrationStreamContext<TShape> {\n id: string\n stream: {\n /**\n * **Server method**\n * Push a new entry to the stream\n * Will be ignored on the client\n */\n push: (...shape: Array<TShape>) => void\n }\n}\n\nexport interface HydrationStreamProviderProps<TShape> {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n}\n\nexport function createHydrationStreamProvider<TShape>() {\n const context = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n\n * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes\n * - This means that we might have some new entries in the cache that needs to be flushed\n * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`\n * 2. (Happens in browser) In `useEffect()`:\n * - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries\n * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received\n **/\n function UseClientHydrationStreamProvider(props: {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n }) {\n // unique id for the cache provider\n const id = `__RQ${React.useId()}`\n const idJSON = htmlEscapeJsonString(JSON.stringify(id))\n\n const [transformer] = React.useState(\n () =>\n (props.transformer ?? {\n // noop\n serialize: (obj: any) => obj,\n deserialize: (obj: any) => obj,\n }) as unknown as TypedDataTransformer<TShape>,\n )\n\n // <server stuff>\n const [stream] = React.useState<Array<TShape>>(() => {\n if (!environmentManager.isServer()) {\n return {\n push() {\n // no-op on the client\n },\n } as unknown as Array<TShape>\n }\n return []\n })\n const count = React.useRef(0)\n useServerInsertedHTML(() => {\n // This only happens on the server\n stream.push(...(props.onFlush?.() ?? []))\n\n if (!stream.length) {\n return null\n }\n // console.log(`pushing ${stream.length} entries`)\n const serializedCacheArgs = stream\n .map((entry) => transformer.serialize(entry))\n .map((entry) => JSON.stringify(entry))\n .join(',')\n\n // Flush stream\n // eslint-disable-next-line react-hooks/immutability\n stream.length = 0\n\n const html: Array<string> = [\n `window[${idJSON}] = window[${idJSON}] || [];`,\n `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,\n ]\n return (\n <script\n key={count.current++}\n nonce={props.nonce}\n dangerouslySetInnerHTML={{\n __html: html.join(''),\n }}\n />\n )\n })\n // </server stuff>\n\n // <client stuff>\n // Setup and run the onEntries handler on the client only, but do it during\n // the initial render so children have access to the data immediately\n // This is important to avoid the client suspending during the initial render\n // if the data has not yet been hydrated.\n if (!environmentManager.isServer()) {\n const win = window as any\n if (!win[id]?.initialized) {\n // Client: consume cache:\n const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {\n const entries = serializedEntries.map((serialized) =>\n transformer.deserialize(serialized),\n )\n props.onEntries(entries)\n }\n\n const winStream: Array<Serialized<TShape>> = win[id] ?? []\n\n onEntries(...winStream)\n\n // eslint-disable-next-line react-hooks/immutability\n win[id] = {\n initialized: true,\n push: onEntries,\n }\n }\n }\n // </client stuff>\n\n return (\n <context.Provider value={{ stream, id }}>\n {props.children}\n </context.Provider>\n )\n }\n\n return {\n Provider: UseClientHydrationStreamProvider,\n context,\n }\n}\n"],"mappings":";;;;;;;AA0DA,SAAgB,gCAAwC;CACtD,MAAM,UAAU,MAAM,cACpB,IACF;;;;;;;;;;CAUA,SAAS,iCAAiC,OAqBvC;EAED,MAAM,KAAK,OAAO,MAAM,MAAM;EAC9B,MAAM,SAAS,qBAAqB,KAAK,UAAU,EAAE,CAAC;EAEtD,MAAM,CAAC,eAAe,MAAM,eAEvB,MAAM,eAAe;GAEpB,YAAY,QAAa;GACzB,cAAc,QAAa;EAC7B,CACJ;EAGA,MAAM,CAAC,UAAU,MAAM,eAA8B;GACnD,IAAI,CAAC,mBAAmB,SAAS,GAC/B,OAAO,EACL,OAAO,CAEP,EACF;GAEF,OAAO,CAAC;EACV,CAAC;EACD,MAAM,QAAQ,MAAM,OAAO,CAAC;EAC5B,4BAA4B;;GAE1B,OAAO,KAAK,KAAA,iBAAI,MAAM,aAAA,QAAA,mBAAA,KAAA,IAAA,KAAA,IAAA,eAAA,KAAA,KAAU,MAAK,CAAC,CAAE;GAExC,IAAI,CAAC,OAAO,QACV,OAAO;GAGT,MAAM,sBAAsB,OACzB,KAAK,UAAU,YAAY,UAAU,KAAK,CAAC,CAAC,CAC5C,KAAK,UAAU,KAAK,UAAU,KAAK,CAAC,CAAC,CACrC,KAAK,GAAG;GAIX,OAAO,SAAS;GAEhB,MAAM,OAAsB,CAC1B,UAAU,OAAO,aAAa,OAAO,WACrC,UAAU,OAAO,SAAS,qBAAqB,mBAAmB,EAAE,GACtE;GACA,OACE,oBAAC,UAAD;IAEE,OAAO,MAAM;IACb,yBAAyB,EACvB,QAAQ,KAAK,KAAK,EAAE,EACtB;GACD,GALM,MAAM,SAKZ;EAEL,CAAC;EAQD,IAAI,CAAC,mBAAmB,SAAS,GAAG;;GAClC,MAAM,MAAM;GACZ,IAAI,GAAA,UAAC,IAAI,SAAA,QAAA,YAAA,KAAA,IAAA,KAAA,IAAA,QAAK,cAAa;IAEzB,MAAM,aAAa,GAAG,sBAAiD;KACrE,MAAM,UAAU,kBAAkB,KAAK,eACrC,YAAY,YAAY,UAAU,CACpC;KACA,MAAM,UAAU,OAAO;IACzB;IAIA,UAAU,GAFmC,IAAI,OAAO,CAAC,CAEnC;IAGtB,IAAI,MAAM;KACR,aAAa;KACb,MAAM;IACR;GACF;EACF;EAGA,OACE,oBAAC,QAAQ,UAAT;GAAkB,OAAO;IAAE;IAAQ;GAAG;GACnC,UAAA,MAAM;EACS,CAAA;CAEtB;CAEA,OAAO;EACL,UAAU;EACV;CACF;AACF"}
1
+ {"version":3,"file":"HydrationStreamProvider.js","names":[],"sources":["../../src/HydrationStreamProvider.tsx"],"sourcesContent":["'use client'\n\nimport { environmentManager } from '@tanstack/react-query'\nimport { useServerInsertedHTML } from 'next/navigation'\nimport * as React from 'react'\nimport { htmlEscapeJsonString } from './htmlescape'\n\nconst serializedSymbol = Symbol('serialized')\n\ninterface DataTransformer {\n serialize: (object: any) => any\n deserialize: (object: any) => any\n}\n\ntype Serialized<TData> = unknown & {\n [serializedSymbol]: TData\n}\n\ninterface TypedDataTransformer<TData> {\n serialize: (obj: TData) => Serialized<TData>\n deserialize: (obj: Serialized<TData>) => TData\n}\n\ninterface HydrationStreamContext<TShape> {\n id: string\n stream: {\n /**\n * **Server method**\n * Push a new entry to the stream\n * Will be ignored on the client\n */\n push: (...shape: Array<TShape>) => void\n }\n}\n\nexport interface HydrationStreamProviderProps<TShape> {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n}\n\nexport function createHydrationStreamProvider<TShape>() {\n const StreamContext = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n\n * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes\n * - This means that we might have some new entries in the cache that needs to be flushed\n * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`\n * 2. (Happens in browser) In `useEffect()`:\n * - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries\n * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received\n **/\n function UseClientHydrationStreamProvider(props: {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n }) {\n // unique id for the cache provider\n const id = `__RQ${React.useId()}`\n const idJSON = htmlEscapeJsonString(JSON.stringify(id))\n\n const [transformer] = React.useState(\n () =>\n (props.transformer ?? {\n // noop\n serialize: (obj: any) => obj,\n deserialize: (obj: any) => obj,\n }) as unknown as TypedDataTransformer<TShape>,\n )\n\n // <server stuff>\n const [stream] = React.useState<Array<TShape>>(() => {\n if (!environmentManager.isServer()) {\n return {\n push() {\n // no-op on the client\n },\n } as unknown as Array<TShape>\n }\n return []\n })\n const countRef = React.useRef(0)\n useServerInsertedHTML(() => {\n // This only happens on the server\n stream.push(...(props.onFlush?.() ?? []))\n\n if (!stream.length) {\n return null\n }\n // console.log(`pushing ${stream.length} entries`)\n const serializedCacheArgs = stream\n .map((entry) => transformer.serialize(entry))\n .map((entry) => JSON.stringify(entry))\n .join(',')\n\n // Flush stream\n stream.length = 0\n\n const html: Array<string> = [\n `window[${idJSON}] = window[${idJSON}] || [];`,\n `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,\n ]\n return (\n <script\n key={countRef.current++}\n nonce={props.nonce}\n dangerouslySetInnerHTML={{\n __html: html.join(''),\n }}\n />\n )\n })\n // </server stuff>\n\n // <client stuff>\n // Setup and run the onEntries handler on the client only, but do it during\n // the initial render so children have access to the data immediately\n // This is important to avoid the client suspending during the initial render\n // if the data has not yet been hydrated.\n if (!environmentManager.isServer()) {\n const win = window as any\n if (!win[id]?.initialized) {\n // Client: consume cache:\n const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {\n const entries = serializedEntries.map((serialized) =>\n transformer.deserialize(serialized),\n )\n props.onEntries(entries)\n }\n\n const winStream: Array<Serialized<TShape>> = win[id] ?? []\n\n onEntries(...winStream)\n\n win[id] = {\n initialized: true,\n push: onEntries,\n }\n }\n }\n // </client stuff>\n\n return (\n <StreamContext.Provider value={{ stream, id }}>\n {props.children}\n </StreamContext.Provider>\n )\n }\n\n return {\n Provider: UseClientHydrationStreamProvider,\n context: StreamContext,\n }\n}\n"],"mappings":";;;;;;;AA0DA,SAAgB,gCAAwC;CACtD,MAAM,gBAAgB,MAAM,cAC1B,IACF;;;;;;;;;;CAUA,SAAS,iCAAiC,OAqBvC;EAED,MAAM,KAAK,OAAO,MAAM,MAAM;EAC9B,MAAM,SAAS,qBAAqB,KAAK,UAAU,EAAE,CAAC;EAEtD,MAAM,CAAC,eAAe,MAAM,eAEvB,MAAM,eAAe;GAEpB,YAAY,QAAa;GACzB,cAAc,QAAa;EAC7B,CACJ;EAGA,MAAM,CAAC,UAAU,MAAM,eAA8B;GACnD,IAAI,CAAC,mBAAmB,SAAS,GAC/B,OAAO,EACL,OAAO,CAEP,EACF;GAEF,OAAO,CAAC;EACV,CAAC;EACD,MAAM,WAAW,MAAM,OAAO,CAAC;EAC/B,4BAA4B;;GAE1B,OAAO,KAAK,KAAA,iBAAI,MAAM,aAAA,QAAA,mBAAA,KAAA,IAAA,KAAA,IAAA,eAAA,KAAA,KAAU,MAAK,CAAC,CAAE;GAExC,IAAI,CAAC,OAAO,QACV,OAAO;GAGT,MAAM,sBAAsB,OACzB,KAAK,UAAU,YAAY,UAAU,KAAK,CAAC,CAAC,CAC5C,KAAK,UAAU,KAAK,UAAU,KAAK,CAAC,CAAC,CACrC,KAAK,GAAG;GAGX,OAAO,SAAS;GAEhB,MAAM,OAAsB,CAC1B,UAAU,OAAO,aAAa,OAAO,WACrC,UAAU,OAAO,SAAS,qBAAqB,mBAAmB,EAAE,GACtE;GACA,OACE,oBAAC,UAAD;IAEE,OAAO,MAAM;IACb,yBAAyB,EACvB,QAAQ,KAAK,KAAK,EAAE,EACtB;GACD,GALM,SAAS,SAKf;EAEL,CAAC;EAQD,IAAI,CAAC,mBAAmB,SAAS,GAAG;;GAClC,MAAM,MAAM;GACZ,IAAI,GAAA,UAAC,IAAI,SAAA,QAAA,YAAA,KAAA,IAAA,KAAA,IAAA,QAAK,cAAa;IAEzB,MAAM,aAAa,GAAG,sBAAiD;KACrE,MAAM,UAAU,kBAAkB,KAAK,eACrC,YAAY,YAAY,UAAU,CACpC;KACA,MAAM,UAAU,OAAO;IACzB;IAIA,UAAU,GAFmC,IAAI,OAAO,CAAC,CAEnC;IAEtB,IAAI,MAAM;KACR,aAAa;KACb,MAAM;IACR;GACF;EACF;EAGA,OACE,oBAAC,cAAc,UAAf;GAAwB,OAAO;IAAE;IAAQ;GAAG;GACzC,UAAA,MAAM;EACe,CAAA;CAE5B;CAEA,OAAO;EACL,UAAU;EACV,SAAS;CACX;AACF"}
@@ -7,7 +7,7 @@ import { DehydrateOptions, DehydratedState, HydrateOptions, QueryClient } from "
7
7
  * - hydrating the query client on the server
8
8
  * - dehydrating the query client on the server
9
9
  */
10
- declare function ReactQueryStreamedHydration(props: {
10
+ export declare function ReactQueryStreamedHydration(props: {
11
11
  children: React.ReactNode;
12
12
  queryClient?: QueryClient;
13
13
  nonce?: string;
@@ -18,5 +18,4 @@ declare function ReactQueryStreamedHydration(props: {
18
18
  transformer?: HydrationStreamProviderProps<DehydratedState>['transformer'];
19
19
  }): import("react/jsx-runtime").JSX.Element;
20
20
  //#endregion
21
- export { ReactQueryStreamedHydration };
22
21
  //# sourceMappingURL=ReactQueryStreamedHydration.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReactQueryStreamedHydration.d.cts","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"mappings":";;;;;;;;;iBA0BgB,4BAA4B;EAC1C,UAAU,MAAM;EAChB,cAAc;EACd;EACA;IACE,UAAU;IACV,YAAY;;EAEd,cAAc,6BAA6B;gCAC5C,IAAA"}
1
+ {"version":3,"file":"ReactQueryStreamedHydration.d.cts","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"mappings":";;;;;;;;;wBA0BgB,4BAA4B;EAC1C,UAAU,MAAM;EAChB,cAAc;EACd;EACA;IACE,UAAU;IACV,YAAY;;EAEd,cAAc,6BAA6B;gCAC5C,IAAA"}
@@ -7,7 +7,7 @@ import * as React from "react";
7
7
  * - hydrating the query client on the server
8
8
  * - dehydrating the query client on the server
9
9
  */
10
- declare function ReactQueryStreamedHydration(props: {
10
+ export declare function ReactQueryStreamedHydration(props: {
11
11
  children: React.ReactNode;
12
12
  queryClient?: QueryClient;
13
13
  nonce?: string;
@@ -18,5 +18,4 @@ declare function ReactQueryStreamedHydration(props: {
18
18
  transformer?: HydrationStreamProviderProps<DehydratedState>['transformer'];
19
19
  }): import("react/jsx-runtime").JSX.Element;
20
20
  //#endregion
21
- export { ReactQueryStreamedHydration };
22
21
  //# sourceMappingURL=ReactQueryStreamedHydration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReactQueryStreamedHydration.d.ts","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"mappings":";;;;;;;;;iBA0BgB,4BAA4B;EAC1C,UAAU,MAAM;EAChB,cAAc;EACd;EACA;IACE,UAAU;IACV,YAAY;;EAEd,cAAc,6BAA6B;gCAC5C,IAAA"}
1
+ {"version":3,"file":"ReactQueryStreamedHydration.d.ts","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"mappings":";;;;;;;;;wBA0BgB,4BAA4B;EAC1C,UAAU,MAAM;EAChB,cAAc;EACd;EACA;IACE,UAAU;IACV,YAAY;;EAEd,cAAc,6BAA6B;gCAC5C,IAAA"}
@@ -1,6 +1,5 @@
1
1
  //#region src/htmlescape.d.ts
2
- declare const ESCAPE_REGEX: RegExp;
3
- declare function htmlEscapeJsonString(str: string): string;
2
+ export declare const ESCAPE_REGEX: RegExp;
3
+ export declare function htmlEscapeJsonString(str: string): string;
4
4
  //#endregion
5
- export { ESCAPE_REGEX, htmlEscapeJsonString };
6
5
  //# sourceMappingURL=htmlescape.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"htmlescape.d.cts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";cAmBa,cAAY;iBAET,qBAAqB"}
1
+ {"version":3,"file":"htmlescape.d.cts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";qBAmBa,cAAY;wBAET,qBAAqB"}
@@ -1,6 +1,5 @@
1
1
  //#region src/htmlescape.d.ts
2
- declare const ESCAPE_REGEX: RegExp;
3
- declare function htmlEscapeJsonString(str: string): string;
2
+ export declare const ESCAPE_REGEX: RegExp;
3
+ export declare function htmlEscapeJsonString(str: string): string;
4
4
  //#endregion
5
- export { ESCAPE_REGEX, htmlEscapeJsonString };
6
5
  //# sourceMappingURL=htmlescape.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"htmlescape.d.ts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";cAmBa,cAAY;iBAET,qBAAqB"}
1
+ {"version":3,"file":"htmlescape.d.ts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";qBAmBa,cAAY;wBAET,qBAAqB"}
@@ -3,13 +3,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
4
4
  const require_htmlescape = require("./htmlescape.cjs");
5
5
  let _tanstack_react_query = require("@tanstack/react-query");
6
- let next_navigation_js = require("next/navigation.js");
6
+ let next_navigation = require("next/navigation");
7
7
  let react = require("react");
8
8
  react = require_rolldown_runtime.__toESM(react, 1);
9
9
  let react_jsx_runtime = require("react/jsx-runtime");
10
10
  //#region src/HydrationStreamProvider.tsx
11
11
  function createHydrationStreamProvider() {
12
- const context = react.createContext(null);
12
+ const StreamContext = react.createContext(null);
13
13
  /**
14
14
 
15
15
  * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes
@@ -30,8 +30,8 @@ function createHydrationStreamProvider() {
30
30
  if (!_tanstack_react_query.environmentManager.isServer()) return { push() {} };
31
31
  return [];
32
32
  });
33
- const count = react.useRef(0);
34
- (0, next_navigation_js.useServerInsertedHTML)(() => {
33
+ const countRef = react.useRef(0);
34
+ (0, next_navigation.useServerInsertedHTML)(() => {
35
35
  stream.push(...props.onFlush?.() ?? []);
36
36
  if (!stream.length) return null;
37
37
  const serializedCacheArgs = stream.map((entry) => transformer.serialize(entry)).map((entry) => JSON.stringify(entry)).join(",");
@@ -40,7 +40,7 @@ function createHydrationStreamProvider() {
40
40
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("script", {
41
41
  nonce: props.nonce,
42
42
  dangerouslySetInnerHTML: { __html: html.join("") }
43
- }, count.current++);
43
+ }, countRef.current++);
44
44
  });
45
45
  if (!_tanstack_react_query.environmentManager.isServer()) {
46
46
  const win = window;
@@ -56,7 +56,7 @@ function createHydrationStreamProvider() {
56
56
  };
57
57
  }
58
58
  }
59
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(context.Provider, {
59
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StreamContext.Provider, {
60
60
  value: {
61
61
  stream,
62
62
  id
@@ -66,7 +66,7 @@ function createHydrationStreamProvider() {
66
66
  }
67
67
  return {
68
68
  Provider: UseClientHydrationStreamProvider,
69
- context
69
+ context: StreamContext
70
70
  };
71
71
  }
72
72
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"HydrationStreamProvider.cjs","names":["React","htmlEscapeJsonString","environmentManager"],"sources":["../../src/HydrationStreamProvider.tsx"],"sourcesContent":["'use client'\n\nimport { environmentManager } from '@tanstack/react-query'\nimport { useServerInsertedHTML } from 'next/navigation'\nimport * as React from 'react'\nimport { htmlEscapeJsonString } from './htmlescape'\n\nconst serializedSymbol = Symbol('serialized')\n\ninterface DataTransformer {\n serialize: (object: any) => any\n deserialize: (object: any) => any\n}\n\ntype Serialized<TData> = unknown & {\n [serializedSymbol]: TData\n}\n\ninterface TypedDataTransformer<TData> {\n serialize: (obj: TData) => Serialized<TData>\n deserialize: (obj: Serialized<TData>) => TData\n}\n\ninterface HydrationStreamContext<TShape> {\n id: string\n stream: {\n /**\n * **Server method**\n * Push a new entry to the stream\n * Will be ignored on the client\n */\n push: (...shape: Array<TShape>) => void\n }\n}\n\nexport interface HydrationStreamProviderProps<TShape> {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n}\n\nexport function createHydrationStreamProvider<TShape>() {\n const context = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n\n * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes\n * - This means that we might have some new entries in the cache that needs to be flushed\n * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`\n * 2. (Happens in browser) In `useEffect()`:\n * - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries\n * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received\n **/\n function UseClientHydrationStreamProvider(props: {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n }) {\n // unique id for the cache provider\n const id = `__RQ${React.useId()}`\n const idJSON = htmlEscapeJsonString(JSON.stringify(id))\n\n const [transformer] = React.useState(\n () =>\n (props.transformer ?? {\n // noop\n serialize: (obj: any) => obj,\n deserialize: (obj: any) => obj,\n }) as unknown as TypedDataTransformer<TShape>,\n )\n\n // <server stuff>\n const [stream] = React.useState<Array<TShape>>(() => {\n if (!environmentManager.isServer()) {\n return {\n push() {\n // no-op on the client\n },\n } as unknown as Array<TShape>\n }\n return []\n })\n const count = React.useRef(0)\n useServerInsertedHTML(() => {\n // This only happens on the server\n stream.push(...(props.onFlush?.() ?? []))\n\n if (!stream.length) {\n return null\n }\n // console.log(`pushing ${stream.length} entries`)\n const serializedCacheArgs = stream\n .map((entry) => transformer.serialize(entry))\n .map((entry) => JSON.stringify(entry))\n .join(',')\n\n // Flush stream\n // eslint-disable-next-line react-hooks/immutability\n stream.length = 0\n\n const html: Array<string> = [\n `window[${idJSON}] = window[${idJSON}] || [];`,\n `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,\n ]\n return (\n <script\n key={count.current++}\n nonce={props.nonce}\n dangerouslySetInnerHTML={{\n __html: html.join(''),\n }}\n />\n )\n })\n // </server stuff>\n\n // <client stuff>\n // Setup and run the onEntries handler on the client only, but do it during\n // the initial render so children have access to the data immediately\n // This is important to avoid the client suspending during the initial render\n // if the data has not yet been hydrated.\n if (!environmentManager.isServer()) {\n const win = window as any\n if (!win[id]?.initialized) {\n // Client: consume cache:\n const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {\n const entries = serializedEntries.map((serialized) =>\n transformer.deserialize(serialized),\n )\n props.onEntries(entries)\n }\n\n const winStream: Array<Serialized<TShape>> = win[id] ?? []\n\n onEntries(...winStream)\n\n // eslint-disable-next-line react-hooks/immutability\n win[id] = {\n initialized: true,\n push: onEntries,\n }\n }\n }\n // </client stuff>\n\n return (\n <context.Provider value={{ stream, id }}>\n {props.children}\n </context.Provider>\n )\n }\n\n return {\n Provider: UseClientHydrationStreamProvider,\n context,\n }\n}\n"],"mappings":";;;;;;;;;;AA0DA,SAAgB,gCAAwC;CACtD,MAAM,UAAUA,MAAM,cACpB,IACF;;;;;;;;;;CAUA,SAAS,iCAAiC,OAqBvC;EAED,MAAM,KAAK,OAAOA,MAAM,MAAM;EAC9B,MAAM,SAASC,mBAAAA,qBAAqB,KAAK,UAAU,EAAE,CAAC;EAEtD,MAAM,CAAC,eAAeD,MAAM,eAEvB,MAAM,eAAe;GAEpB,YAAY,QAAa;GACzB,cAAc,QAAa;EAC7B,CACJ;EAGA,MAAM,CAAC,UAAUA,MAAM,eAA8B;GACnD,IAAI,CAACE,sBAAAA,mBAAmB,SAAS,GAC/B,OAAO,EACL,OAAO,CAEP,EACF;GAEF,OAAO,CAAC;EACV,CAAC;EACD,MAAM,QAAQF,MAAM,OAAO,CAAC;EAC5B,CAAA,GAAA,mBAAA,sBAAA,OAA4B;GAE1B,OAAO,KAAK,GAAI,MAAM,UAAU,KAAK,CAAC,CAAE;GAExC,IAAI,CAAC,OAAO,QACV,OAAO;GAGT,MAAM,sBAAsB,OACzB,KAAK,UAAU,YAAY,UAAU,KAAK,CAAC,CAAC,CAC5C,KAAK,UAAU,KAAK,UAAU,KAAK,CAAC,CAAC,CACrC,KAAK,GAAG;GAIX,OAAO,SAAS;GAEhB,MAAM,OAAsB,CAC1B,UAAU,OAAO,aAAa,OAAO,WACrC,UAAU,OAAO,SAASC,mBAAAA,qBAAqB,mBAAmB,EAAE,GACtE;GACA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;IAEE,OAAO,MAAM;IACb,yBAAyB,EACvB,QAAQ,KAAK,KAAK,EAAE,EACtB;GACD,GALM,MAAM,SAKZ;EAEL,CAAC;EAQD,IAAI,CAACC,sBAAAA,mBAAmB,SAAS,GAAG;GAClC,MAAM,MAAM;GACZ,IAAI,CAAC,IAAI,GAAG,EAAE,aAAa;IAEzB,MAAM,aAAa,GAAG,sBAAiD;KACrE,MAAM,UAAU,kBAAkB,KAAK,eACrC,YAAY,YAAY,UAAU,CACpC;KACA,MAAM,UAAU,OAAO;IACzB;IAIA,UAAU,GAFmC,IAAI,OAAO,CAAC,CAEnC;IAGtB,IAAI,MAAM;KACR,aAAa;KACb,MAAM;IACR;GACF;EACF;EAGA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAQ,UAAT;GAAkB,OAAO;IAAE;IAAQ;GAAG;GACnC,UAAA,MAAM;EACS,CAAA;CAEtB;CAEA,OAAO;EACL,UAAU;EACV;CACF;AACF"}
1
+ {"version":3,"file":"HydrationStreamProvider.cjs","names":["React","htmlEscapeJsonString","environmentManager"],"sources":["../../src/HydrationStreamProvider.tsx"],"sourcesContent":["'use client'\n\nimport { environmentManager } from '@tanstack/react-query'\nimport { useServerInsertedHTML } from 'next/navigation'\nimport * as React from 'react'\nimport { htmlEscapeJsonString } from './htmlescape'\n\nconst serializedSymbol = Symbol('serialized')\n\ninterface DataTransformer {\n serialize: (object: any) => any\n deserialize: (object: any) => any\n}\n\ntype Serialized<TData> = unknown & {\n [serializedSymbol]: TData\n}\n\ninterface TypedDataTransformer<TData> {\n serialize: (obj: TData) => Serialized<TData>\n deserialize: (obj: Serialized<TData>) => TData\n}\n\ninterface HydrationStreamContext<TShape> {\n id: string\n stream: {\n /**\n * **Server method**\n * Push a new entry to the stream\n * Will be ignored on the client\n */\n push: (...shape: Array<TShape>) => void\n }\n}\n\nexport interface HydrationStreamProviderProps<TShape> {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n}\n\nexport function createHydrationStreamProvider<TShape>() {\n const StreamContext = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n\n * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes\n * - This means that we might have some new entries in the cache that needs to be flushed\n * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`\n * 2. (Happens in browser) In `useEffect()`:\n * - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries\n * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received\n **/\n function UseClientHydrationStreamProvider(props: {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n }) {\n // unique id for the cache provider\n const id = `__RQ${React.useId()}`\n const idJSON = htmlEscapeJsonString(JSON.stringify(id))\n\n const [transformer] = React.useState(\n () =>\n (props.transformer ?? {\n // noop\n serialize: (obj: any) => obj,\n deserialize: (obj: any) => obj,\n }) as unknown as TypedDataTransformer<TShape>,\n )\n\n // <server stuff>\n const [stream] = React.useState<Array<TShape>>(() => {\n if (!environmentManager.isServer()) {\n return {\n push() {\n // no-op on the client\n },\n } as unknown as Array<TShape>\n }\n return []\n })\n const countRef = React.useRef(0)\n useServerInsertedHTML(() => {\n // This only happens on the server\n stream.push(...(props.onFlush?.() ?? []))\n\n if (!stream.length) {\n return null\n }\n // console.log(`pushing ${stream.length} entries`)\n const serializedCacheArgs = stream\n .map((entry) => transformer.serialize(entry))\n .map((entry) => JSON.stringify(entry))\n .join(',')\n\n // Flush stream\n stream.length = 0\n\n const html: Array<string> = [\n `window[${idJSON}] = window[${idJSON}] || [];`,\n `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,\n ]\n return (\n <script\n key={countRef.current++}\n nonce={props.nonce}\n dangerouslySetInnerHTML={{\n __html: html.join(''),\n }}\n />\n )\n })\n // </server stuff>\n\n // <client stuff>\n // Setup and run the onEntries handler on the client only, but do it during\n // the initial render so children have access to the data immediately\n // This is important to avoid the client suspending during the initial render\n // if the data has not yet been hydrated.\n if (!environmentManager.isServer()) {\n const win = window as any\n if (!win[id]?.initialized) {\n // Client: consume cache:\n const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {\n const entries = serializedEntries.map((serialized) =>\n transformer.deserialize(serialized),\n )\n props.onEntries(entries)\n }\n\n const winStream: Array<Serialized<TShape>> = win[id] ?? []\n\n onEntries(...winStream)\n\n win[id] = {\n initialized: true,\n push: onEntries,\n }\n }\n }\n // </client stuff>\n\n return (\n <StreamContext.Provider value={{ stream, id }}>\n {props.children}\n </StreamContext.Provider>\n )\n }\n\n return {\n Provider: UseClientHydrationStreamProvider,\n context: StreamContext,\n }\n}\n"],"mappings":";;;;;;;;;;AA0DA,SAAgB,gCAAwC;CACtD,MAAM,gBAAgBA,MAAM,cAC1B,IACF;;;;;;;;;;CAUA,SAAS,iCAAiC,OAqBvC;EAED,MAAM,KAAK,OAAOA,MAAM,MAAM;EAC9B,MAAM,SAASC,mBAAAA,qBAAqB,KAAK,UAAU,EAAE,CAAC;EAEtD,MAAM,CAAC,eAAeD,MAAM,eAEvB,MAAM,eAAe;GAEpB,YAAY,QAAa;GACzB,cAAc,QAAa;EAC7B,CACJ;EAGA,MAAM,CAAC,UAAUA,MAAM,eAA8B;GACnD,IAAI,CAACE,sBAAAA,mBAAmB,SAAS,GAC/B,OAAO,EACL,OAAO,CAEP,EACF;GAEF,OAAO,CAAC;EACV,CAAC;EACD,MAAM,WAAWF,MAAM,OAAO,CAAC;EAC/B,CAAA,GAAA,gBAAA,sBAAA,OAA4B;GAE1B,OAAO,KAAK,GAAI,MAAM,UAAU,KAAK,CAAC,CAAE;GAExC,IAAI,CAAC,OAAO,QACV,OAAO;GAGT,MAAM,sBAAsB,OACzB,KAAK,UAAU,YAAY,UAAU,KAAK,CAAC,CAAC,CAC5C,KAAK,UAAU,KAAK,UAAU,KAAK,CAAC,CAAC,CACrC,KAAK,GAAG;GAGX,OAAO,SAAS;GAEhB,MAAM,OAAsB,CAC1B,UAAU,OAAO,aAAa,OAAO,WACrC,UAAU,OAAO,SAASC,mBAAAA,qBAAqB,mBAAmB,EAAE,GACtE;GACA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;IAEE,OAAO,MAAM;IACb,yBAAyB,EACvB,QAAQ,KAAK,KAAK,EAAE,EACtB;GACD,GALM,SAAS,SAKf;EAEL,CAAC;EAQD,IAAI,CAACC,sBAAAA,mBAAmB,SAAS,GAAG;GAClC,MAAM,MAAM;GACZ,IAAI,CAAC,IAAI,GAAG,EAAE,aAAa;IAEzB,MAAM,aAAa,GAAG,sBAAiD;KACrE,MAAM,UAAU,kBAAkB,KAAK,eACrC,YAAY,YAAY,UAAU,CACpC;KACA,MAAM,UAAU,OAAO;IACzB;IAIA,UAAU,GAFmC,IAAI,OAAO,CAAC,CAEnC;IAEtB,IAAI,MAAM;KACR,aAAa;KACb,MAAM;IACR;GACF;EACF;EAGA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,cAAc,UAAf;GAAwB,OAAO;IAAE;IAAQ;GAAG;GACzC,UAAA,MAAM;EACe,CAAA;CAE5B;CAEA,OAAO;EACL,UAAU;EACV,SAAS;CACX;AACF"}
@@ -1,12 +1,12 @@
1
1
  "use client";
2
2
  import { htmlEscapeJsonString } from "./htmlescape.js";
3
3
  import { environmentManager } from "@tanstack/react-query";
4
- import { useServerInsertedHTML } from "next/navigation.js";
4
+ import { useServerInsertedHTML } from "next/navigation";
5
5
  import * as React from "react";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  //#region src/HydrationStreamProvider.tsx
8
8
  function createHydrationStreamProvider() {
9
- const context = React.createContext(null);
9
+ const StreamContext = React.createContext(null);
10
10
  /**
11
11
 
12
12
  * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes
@@ -27,7 +27,7 @@ function createHydrationStreamProvider() {
27
27
  if (!environmentManager.isServer()) return { push() {} };
28
28
  return [];
29
29
  });
30
- const count = React.useRef(0);
30
+ const countRef = React.useRef(0);
31
31
  useServerInsertedHTML(() => {
32
32
  stream.push(...props.onFlush?.() ?? []);
33
33
  if (!stream.length) return null;
@@ -37,7 +37,7 @@ function createHydrationStreamProvider() {
37
37
  return /* @__PURE__ */ jsx("script", {
38
38
  nonce: props.nonce,
39
39
  dangerouslySetInnerHTML: { __html: html.join("") }
40
- }, count.current++);
40
+ }, countRef.current++);
41
41
  });
42
42
  if (!environmentManager.isServer()) {
43
43
  const win = window;
@@ -53,7 +53,7 @@ function createHydrationStreamProvider() {
53
53
  };
54
54
  }
55
55
  }
56
- return /* @__PURE__ */ jsx(context.Provider, {
56
+ return /* @__PURE__ */ jsx(StreamContext.Provider, {
57
57
  value: {
58
58
  stream,
59
59
  id
@@ -63,7 +63,7 @@ function createHydrationStreamProvider() {
63
63
  }
64
64
  return {
65
65
  Provider: UseClientHydrationStreamProvider,
66
- context
66
+ context: StreamContext
67
67
  };
68
68
  }
69
69
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"HydrationStreamProvider.js","names":[],"sources":["../../src/HydrationStreamProvider.tsx"],"sourcesContent":["'use client'\n\nimport { environmentManager } from '@tanstack/react-query'\nimport { useServerInsertedHTML } from 'next/navigation'\nimport * as React from 'react'\nimport { htmlEscapeJsonString } from './htmlescape'\n\nconst serializedSymbol = Symbol('serialized')\n\ninterface DataTransformer {\n serialize: (object: any) => any\n deserialize: (object: any) => any\n}\n\ntype Serialized<TData> = unknown & {\n [serializedSymbol]: TData\n}\n\ninterface TypedDataTransformer<TData> {\n serialize: (obj: TData) => Serialized<TData>\n deserialize: (obj: Serialized<TData>) => TData\n}\n\ninterface HydrationStreamContext<TShape> {\n id: string\n stream: {\n /**\n * **Server method**\n * Push a new entry to the stream\n * Will be ignored on the client\n */\n push: (...shape: Array<TShape>) => void\n }\n}\n\nexport interface HydrationStreamProviderProps<TShape> {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n}\n\nexport function createHydrationStreamProvider<TShape>() {\n const context = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n\n * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes\n * - This means that we might have some new entries in the cache that needs to be flushed\n * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`\n * 2. (Happens in browser) In `useEffect()`:\n * - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries\n * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received\n **/\n function UseClientHydrationStreamProvider(props: {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n }) {\n // unique id for the cache provider\n const id = `__RQ${React.useId()}`\n const idJSON = htmlEscapeJsonString(JSON.stringify(id))\n\n const [transformer] = React.useState(\n () =>\n (props.transformer ?? {\n // noop\n serialize: (obj: any) => obj,\n deserialize: (obj: any) => obj,\n }) as unknown as TypedDataTransformer<TShape>,\n )\n\n // <server stuff>\n const [stream] = React.useState<Array<TShape>>(() => {\n if (!environmentManager.isServer()) {\n return {\n push() {\n // no-op on the client\n },\n } as unknown as Array<TShape>\n }\n return []\n })\n const count = React.useRef(0)\n useServerInsertedHTML(() => {\n // This only happens on the server\n stream.push(...(props.onFlush?.() ?? []))\n\n if (!stream.length) {\n return null\n }\n // console.log(`pushing ${stream.length} entries`)\n const serializedCacheArgs = stream\n .map((entry) => transformer.serialize(entry))\n .map((entry) => JSON.stringify(entry))\n .join(',')\n\n // Flush stream\n // eslint-disable-next-line react-hooks/immutability\n stream.length = 0\n\n const html: Array<string> = [\n `window[${idJSON}] = window[${idJSON}] || [];`,\n `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,\n ]\n return (\n <script\n key={count.current++}\n nonce={props.nonce}\n dangerouslySetInnerHTML={{\n __html: html.join(''),\n }}\n />\n )\n })\n // </server stuff>\n\n // <client stuff>\n // Setup and run the onEntries handler on the client only, but do it during\n // the initial render so children have access to the data immediately\n // This is important to avoid the client suspending during the initial render\n // if the data has not yet been hydrated.\n if (!environmentManager.isServer()) {\n const win = window as any\n if (!win[id]?.initialized) {\n // Client: consume cache:\n const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {\n const entries = serializedEntries.map((serialized) =>\n transformer.deserialize(serialized),\n )\n props.onEntries(entries)\n }\n\n const winStream: Array<Serialized<TShape>> = win[id] ?? []\n\n onEntries(...winStream)\n\n // eslint-disable-next-line react-hooks/immutability\n win[id] = {\n initialized: true,\n push: onEntries,\n }\n }\n }\n // </client stuff>\n\n return (\n <context.Provider value={{ stream, id }}>\n {props.children}\n </context.Provider>\n )\n }\n\n return {\n Provider: UseClientHydrationStreamProvider,\n context,\n }\n}\n"],"mappings":";;;;;;;AA0DA,SAAgB,gCAAwC;CACtD,MAAM,UAAU,MAAM,cACpB,IACF;;;;;;;;;;CAUA,SAAS,iCAAiC,OAqBvC;EAED,MAAM,KAAK,OAAO,MAAM,MAAM;EAC9B,MAAM,SAAS,qBAAqB,KAAK,UAAU,EAAE,CAAC;EAEtD,MAAM,CAAC,eAAe,MAAM,eAEvB,MAAM,eAAe;GAEpB,YAAY,QAAa;GACzB,cAAc,QAAa;EAC7B,CACJ;EAGA,MAAM,CAAC,UAAU,MAAM,eAA8B;GACnD,IAAI,CAAC,mBAAmB,SAAS,GAC/B,OAAO,EACL,OAAO,CAEP,EACF;GAEF,OAAO,CAAC;EACV,CAAC;EACD,MAAM,QAAQ,MAAM,OAAO,CAAC;EAC5B,4BAA4B;GAE1B,OAAO,KAAK,GAAI,MAAM,UAAU,KAAK,CAAC,CAAE;GAExC,IAAI,CAAC,OAAO,QACV,OAAO;GAGT,MAAM,sBAAsB,OACzB,KAAK,UAAU,YAAY,UAAU,KAAK,CAAC,CAAC,CAC5C,KAAK,UAAU,KAAK,UAAU,KAAK,CAAC,CAAC,CACrC,KAAK,GAAG;GAIX,OAAO,SAAS;GAEhB,MAAM,OAAsB,CAC1B,UAAU,OAAO,aAAa,OAAO,WACrC,UAAU,OAAO,SAAS,qBAAqB,mBAAmB,EAAE,GACtE;GACA,OACE,oBAAC,UAAD;IAEE,OAAO,MAAM;IACb,yBAAyB,EACvB,QAAQ,KAAK,KAAK,EAAE,EACtB;GACD,GALM,MAAM,SAKZ;EAEL,CAAC;EAQD,IAAI,CAAC,mBAAmB,SAAS,GAAG;GAClC,MAAM,MAAM;GACZ,IAAI,CAAC,IAAI,GAAG,EAAE,aAAa;IAEzB,MAAM,aAAa,GAAG,sBAAiD;KACrE,MAAM,UAAU,kBAAkB,KAAK,eACrC,YAAY,YAAY,UAAU,CACpC;KACA,MAAM,UAAU,OAAO;IACzB;IAIA,UAAU,GAFmC,IAAI,OAAO,CAAC,CAEnC;IAGtB,IAAI,MAAM;KACR,aAAa;KACb,MAAM;IACR;GACF;EACF;EAGA,OACE,oBAAC,QAAQ,UAAT;GAAkB,OAAO;IAAE;IAAQ;GAAG;GACnC,UAAA,MAAM;EACS,CAAA;CAEtB;CAEA,OAAO;EACL,UAAU;EACV;CACF;AACF"}
1
+ {"version":3,"file":"HydrationStreamProvider.js","names":[],"sources":["../../src/HydrationStreamProvider.tsx"],"sourcesContent":["'use client'\n\nimport { environmentManager } from '@tanstack/react-query'\nimport { useServerInsertedHTML } from 'next/navigation'\nimport * as React from 'react'\nimport { htmlEscapeJsonString } from './htmlescape'\n\nconst serializedSymbol = Symbol('serialized')\n\ninterface DataTransformer {\n serialize: (object: any) => any\n deserialize: (object: any) => any\n}\n\ntype Serialized<TData> = unknown & {\n [serializedSymbol]: TData\n}\n\ninterface TypedDataTransformer<TData> {\n serialize: (obj: TData) => Serialized<TData>\n deserialize: (obj: Serialized<TData>) => TData\n}\n\ninterface HydrationStreamContext<TShape> {\n id: string\n stream: {\n /**\n * **Server method**\n * Push a new entry to the stream\n * Will be ignored on the client\n */\n push: (...shape: Array<TShape>) => void\n }\n}\n\nexport interface HydrationStreamProviderProps<TShape> {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n}\n\nexport function createHydrationStreamProvider<TShape>() {\n const StreamContext = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n\n * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes\n * - This means that we might have some new entries in the cache that needs to be flushed\n * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`\n * 2. (Happens in browser) In `useEffect()`:\n * - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries\n * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received\n **/\n function UseClientHydrationStreamProvider(props: {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n }) {\n // unique id for the cache provider\n const id = `__RQ${React.useId()}`\n const idJSON = htmlEscapeJsonString(JSON.stringify(id))\n\n const [transformer] = React.useState(\n () =>\n (props.transformer ?? {\n // noop\n serialize: (obj: any) => obj,\n deserialize: (obj: any) => obj,\n }) as unknown as TypedDataTransformer<TShape>,\n )\n\n // <server stuff>\n const [stream] = React.useState<Array<TShape>>(() => {\n if (!environmentManager.isServer()) {\n return {\n push() {\n // no-op on the client\n },\n } as unknown as Array<TShape>\n }\n return []\n })\n const countRef = React.useRef(0)\n useServerInsertedHTML(() => {\n // This only happens on the server\n stream.push(...(props.onFlush?.() ?? []))\n\n if (!stream.length) {\n return null\n }\n // console.log(`pushing ${stream.length} entries`)\n const serializedCacheArgs = stream\n .map((entry) => transformer.serialize(entry))\n .map((entry) => JSON.stringify(entry))\n .join(',')\n\n // Flush stream\n stream.length = 0\n\n const html: Array<string> = [\n `window[${idJSON}] = window[${idJSON}] || [];`,\n `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,\n ]\n return (\n <script\n key={countRef.current++}\n nonce={props.nonce}\n dangerouslySetInnerHTML={{\n __html: html.join(''),\n }}\n />\n )\n })\n // </server stuff>\n\n // <client stuff>\n // Setup and run the onEntries handler on the client only, but do it during\n // the initial render so children have access to the data immediately\n // This is important to avoid the client suspending during the initial render\n // if the data has not yet been hydrated.\n if (!environmentManager.isServer()) {\n const win = window as any\n if (!win[id]?.initialized) {\n // Client: consume cache:\n const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {\n const entries = serializedEntries.map((serialized) =>\n transformer.deserialize(serialized),\n )\n props.onEntries(entries)\n }\n\n const winStream: Array<Serialized<TShape>> = win[id] ?? []\n\n onEntries(...winStream)\n\n win[id] = {\n initialized: true,\n push: onEntries,\n }\n }\n }\n // </client stuff>\n\n return (\n <StreamContext.Provider value={{ stream, id }}>\n {props.children}\n </StreamContext.Provider>\n )\n }\n\n return {\n Provider: UseClientHydrationStreamProvider,\n context: StreamContext,\n }\n}\n"],"mappings":";;;;;;;AA0DA,SAAgB,gCAAwC;CACtD,MAAM,gBAAgB,MAAM,cAC1B,IACF;;;;;;;;;;CAUA,SAAS,iCAAiC,OAqBvC;EAED,MAAM,KAAK,OAAO,MAAM,MAAM;EAC9B,MAAM,SAAS,qBAAqB,KAAK,UAAU,EAAE,CAAC;EAEtD,MAAM,CAAC,eAAe,MAAM,eAEvB,MAAM,eAAe;GAEpB,YAAY,QAAa;GACzB,cAAc,QAAa;EAC7B,CACJ;EAGA,MAAM,CAAC,UAAU,MAAM,eAA8B;GACnD,IAAI,CAAC,mBAAmB,SAAS,GAC/B,OAAO,EACL,OAAO,CAEP,EACF;GAEF,OAAO,CAAC;EACV,CAAC;EACD,MAAM,WAAW,MAAM,OAAO,CAAC;EAC/B,4BAA4B;GAE1B,OAAO,KAAK,GAAI,MAAM,UAAU,KAAK,CAAC,CAAE;GAExC,IAAI,CAAC,OAAO,QACV,OAAO;GAGT,MAAM,sBAAsB,OACzB,KAAK,UAAU,YAAY,UAAU,KAAK,CAAC,CAAC,CAC5C,KAAK,UAAU,KAAK,UAAU,KAAK,CAAC,CAAC,CACrC,KAAK,GAAG;GAGX,OAAO,SAAS;GAEhB,MAAM,OAAsB,CAC1B,UAAU,OAAO,aAAa,OAAO,WACrC,UAAU,OAAO,SAAS,qBAAqB,mBAAmB,EAAE,GACtE;GACA,OACE,oBAAC,UAAD;IAEE,OAAO,MAAM;IACb,yBAAyB,EACvB,QAAQ,KAAK,KAAK,EAAE,EACtB;GACD,GALM,SAAS,SAKf;EAEL,CAAC;EAQD,IAAI,CAAC,mBAAmB,SAAS,GAAG;GAClC,MAAM,MAAM;GACZ,IAAI,CAAC,IAAI,GAAG,EAAE,aAAa;IAEzB,MAAM,aAAa,GAAG,sBAAiD;KACrE,MAAM,UAAU,kBAAkB,KAAK,eACrC,YAAY,YAAY,UAAU,CACpC;KACA,MAAM,UAAU,OAAO;IACzB;IAIA,UAAU,GAFmC,IAAI,OAAO,CAAC,CAEnC;IAEtB,IAAI,MAAM;KACR,aAAa;KACb,MAAM;IACR;GACF;EACF;EAGA,OACE,oBAAC,cAAc,UAAf;GAAwB,OAAO;IAAE;IAAQ;GAAG;GACzC,UAAA,MAAM;EACe,CAAA;CAE5B;CAEA,OAAO;EACL,UAAU;EACV,SAAS;CACX;AACF"}
@@ -7,7 +7,7 @@ import { DehydrateOptions, DehydratedState, HydrateOptions, QueryClient } from "
7
7
  * - hydrating the query client on the server
8
8
  * - dehydrating the query client on the server
9
9
  */
10
- declare function ReactQueryStreamedHydration(props: {
10
+ export declare function ReactQueryStreamedHydration(props: {
11
11
  children: React.ReactNode;
12
12
  queryClient?: QueryClient;
13
13
  nonce?: string;
@@ -18,5 +18,4 @@ declare function ReactQueryStreamedHydration(props: {
18
18
  transformer?: HydrationStreamProviderProps<DehydratedState>['transformer'];
19
19
  }): import("react/jsx-runtime").JSX.Element;
20
20
  //#endregion
21
- export { ReactQueryStreamedHydration };
22
21
  //# sourceMappingURL=ReactQueryStreamedHydration.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReactQueryStreamedHydration.d.cts","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"mappings":";;;;;;;;;iBA0BgB,4BAA4B;EAC1C,UAAU,MAAM;EAChB,cAAc;EACd;EACA;IACE,UAAU;IACV,YAAY;;EAEd,cAAc,6BAA6B;gCAC5C,IAAA"}
1
+ {"version":3,"file":"ReactQueryStreamedHydration.d.cts","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"mappings":";;;;;;;;;wBA0BgB,4BAA4B;EAC1C,UAAU,MAAM;EAChB,cAAc;EACd;EACA;IACE,UAAU;IACV,YAAY;;EAEd,cAAc,6BAA6B;gCAC5C,IAAA"}
@@ -7,7 +7,7 @@ import * as React from "react";
7
7
  * - hydrating the query client on the server
8
8
  * - dehydrating the query client on the server
9
9
  */
10
- declare function ReactQueryStreamedHydration(props: {
10
+ export declare function ReactQueryStreamedHydration(props: {
11
11
  children: React.ReactNode;
12
12
  queryClient?: QueryClient;
13
13
  nonce?: string;
@@ -18,5 +18,4 @@ declare function ReactQueryStreamedHydration(props: {
18
18
  transformer?: HydrationStreamProviderProps<DehydratedState>['transformer'];
19
19
  }): import("react/jsx-runtime").JSX.Element;
20
20
  //#endregion
21
- export { ReactQueryStreamedHydration };
22
21
  //# sourceMappingURL=ReactQueryStreamedHydration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReactQueryStreamedHydration.d.ts","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"mappings":";;;;;;;;;iBA0BgB,4BAA4B;EAC1C,UAAU,MAAM;EAChB,cAAc;EACd;EACA;IACE,UAAU;IACV,YAAY;;EAEd,cAAc,6BAA6B;gCAC5C,IAAA"}
1
+ {"version":3,"file":"ReactQueryStreamedHydration.d.ts","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"mappings":";;;;;;;;;wBA0BgB,4BAA4B;EAC1C,UAAU,MAAM;EAChB,cAAc;EACd;EACA;IACE,UAAU;IACV,YAAY;;EAEd,cAAc,6BAA6B;gCAC5C,IAAA"}
@@ -1,6 +1,5 @@
1
1
  //#region src/htmlescape.d.ts
2
- declare const ESCAPE_REGEX: RegExp;
3
- declare function htmlEscapeJsonString(str: string): string;
2
+ export declare const ESCAPE_REGEX: RegExp;
3
+ export declare function htmlEscapeJsonString(str: string): string;
4
4
  //#endregion
5
- export { ESCAPE_REGEX, htmlEscapeJsonString };
6
5
  //# sourceMappingURL=htmlescape.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"htmlescape.d.cts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";cAmBa,cAAY;iBAET,qBAAqB"}
1
+ {"version":3,"file":"htmlescape.d.cts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";qBAmBa,cAAY;wBAET,qBAAqB"}
@@ -1,6 +1,5 @@
1
1
  //#region src/htmlescape.d.ts
2
- declare const ESCAPE_REGEX: RegExp;
3
- declare function htmlEscapeJsonString(str: string): string;
2
+ export declare const ESCAPE_REGEX: RegExp;
3
+ export declare function htmlEscapeJsonString(str: string): string;
4
4
  //#endregion
5
- export { ESCAPE_REGEX, htmlEscapeJsonString };
6
5
  //# sourceMappingURL=htmlescape.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"htmlescape.d.ts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";cAmBa,cAAY;iBAET,qBAAqB"}
1
+ {"version":3,"file":"htmlescape.d.ts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";qBAmBa,cAAY;wBAET,qBAAqB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-query-next-experimental",
3
- "version": "5.103.3",
3
+ "version": "5.104.1",
4
4
  "description": "Hydration utils for React Query in the NextJs app directory",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -39,15 +39,17 @@
39
39
  "!src/__tests__"
40
40
  ],
41
41
  "devDependencies": {
42
- "@tanstack/react-query": "5.103.3",
42
+ "@eslint-react/eslint-plugin": "^5.21.0",
43
+ "@tanstack/react-query": "5.104.1",
43
44
  "@types/react": "^19.2.7",
44
- "@vitejs/plugin-react": "^4.3.4",
45
+ "@vitejs/plugin-react": "^6.1.1",
46
+ "eslint-plugin-react-hooks": "^7.1.1",
45
47
  "next": "^16.0.1",
46
- "npm-run-all2": "^9.0.3",
47
- "react": "^19.2.1"
48
+ "react": "^19.2.1",
49
+ "typescript": "6.0.3"
48
50
  },
49
51
  "peerDependencies": {
50
- "@tanstack/react-query": "^5.103.3",
52
+ "@tanstack/react-query": "^5.104.1",
51
53
  "next": "^13 || ^14 || ^15 || ^16",
52
54
  "react": "^18 || ^19"
53
55
  },
@@ -61,7 +63,7 @@
61
63
  "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js --project tsconfig.legacy.json --outDir .cache/test-types/ts58 --tsBuildInfoFile .cache/test-types/ts58.tsbuildinfo",
62
64
  "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js --project tsconfig.legacy.json --outDir .cache/test-types/ts59 --tsBuildInfoFile .cache/test-types/ts59.tsbuildinfo",
63
65
  "test:types:tscurrent": "tsc --project tsconfig.json --outDir .cache/test-types/tscurrent --tsBuildInfoFile .cache/test-types/tscurrent.tsbuildinfo",
64
- "test:types:ts70": "node ../../node_modules/typescript70/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts70 --tsBuildInfoFile .cache/test-types/ts70.tsbuildinfo",
66
+ "test:types:ts70": "node ../../node_modules/typescript70/lib/tsc.js --project tsconfig.legacy.json --outDir .cache/test-types/ts70 --tsBuildInfoFile .cache/test-types/ts70.tsbuildinfo",
65
67
  "test:build": "publint --strict && attw --pack",
66
68
  "build": "tsdown --tsconfig tsconfig.prod.json"
67
69
  }
@@ -57,7 +57,7 @@ export interface HydrationStreamProviderProps<TShape> {
57
57
  }
58
58
 
59
59
  export function createHydrationStreamProvider<TShape>() {
60
- const context = React.createContext<HydrationStreamContext<TShape>>(
60
+ const StreamContext = React.createContext<HydrationStreamContext<TShape>>(
61
61
  null as any,
62
62
  )
63
63
  /**
@@ -115,7 +115,7 @@ export function createHydrationStreamProvider<TShape>() {
115
115
  }
116
116
  return []
117
117
  })
118
- const count = React.useRef(0)
118
+ const countRef = React.useRef(0)
119
119
  useServerInsertedHTML(() => {
120
120
  // This only happens on the server
121
121
  stream.push(...(props.onFlush?.() ?? []))
@@ -130,7 +130,6 @@ export function createHydrationStreamProvider<TShape>() {
130
130
  .join(',')
131
131
 
132
132
  // Flush stream
133
- // eslint-disable-next-line react-hooks/immutability
134
133
  stream.length = 0
135
134
 
136
135
  const html: Array<string> = [
@@ -139,7 +138,7 @@ export function createHydrationStreamProvider<TShape>() {
139
138
  ]
140
139
  return (
141
140
  <script
142
- key={count.current++}
141
+ key={countRef.current++}
143
142
  nonce={props.nonce}
144
143
  dangerouslySetInnerHTML={{
145
144
  __html: html.join(''),
@@ -169,7 +168,6 @@ export function createHydrationStreamProvider<TShape>() {
169
168
 
170
169
  onEntries(...winStream)
171
170
 
172
- // eslint-disable-next-line react-hooks/immutability
173
171
  win[id] = {
174
172
  initialized: true,
175
173
  push: onEntries,
@@ -179,14 +177,14 @@ export function createHydrationStreamProvider<TShape>() {
179
177
  // </client stuff>
180
178
 
181
179
  return (
182
- <context.Provider value={{ stream, id }}>
180
+ <StreamContext.Provider value={{ stream, id }}>
183
181
  {props.children}
184
- </context.Provider>
182
+ </StreamContext.Provider>
185
183
  )
186
184
  }
187
185
 
188
186
  return {
189
187
  Provider: UseClientHydrationStreamProvider,
190
- context,
188
+ context: StreamContext,
191
189
  }
192
190
  }