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

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.
Files changed (60) hide show
  1. package/build/legacy/{HydrationStreamProvider-D_lqnUNo.d.ts → HydrationStreamProvider-DrbxOdk5.d.cts} +12 -1
  2. package/build/legacy/HydrationStreamProvider-DrbxOdk5.d.cts.map +1 -0
  3. package/build/legacy/{HydrationStreamProvider-D_lqnUNo.d.cts → HydrationStreamProvider-DrbxOdk5.d.ts} +12 -1
  4. package/build/legacy/HydrationStreamProvider-DrbxOdk5.d.ts.map +1 -0
  5. package/build/legacy/HydrationStreamProvider.cjs +15 -7
  6. package/build/legacy/HydrationStreamProvider.cjs.map +1 -1
  7. package/build/legacy/HydrationStreamProvider.d.cts +1 -1
  8. package/build/legacy/HydrationStreamProvider.d.ts +1 -1
  9. package/build/legacy/HydrationStreamProvider.js +15 -7
  10. package/build/legacy/HydrationStreamProvider.js.map +1 -1
  11. package/build/legacy/ReactQueryStreamedHydration.cjs +5 -2
  12. package/build/legacy/ReactQueryStreamedHydration.cjs.map +1 -1
  13. package/build/legacy/ReactQueryStreamedHydration.d.cts +6 -3
  14. package/build/legacy/ReactQueryStreamedHydration.d.cts.map +1 -1
  15. package/build/legacy/ReactQueryStreamedHydration.d.ts +6 -3
  16. package/build/legacy/ReactQueryStreamedHydration.d.ts.map +1 -1
  17. package/build/legacy/ReactQueryStreamedHydration.js +5 -2
  18. package/build/legacy/ReactQueryStreamedHydration.js.map +1 -1
  19. package/build/legacy/htmlescape.cjs +5 -0
  20. package/build/legacy/htmlescape.cjs.map +1 -1
  21. package/build/legacy/htmlescape.d.cts +5 -0
  22. package/build/legacy/htmlescape.d.cts.map +1 -1
  23. package/build/legacy/htmlescape.d.ts +5 -0
  24. package/build/legacy/htmlescape.d.ts.map +1 -1
  25. package/build/legacy/htmlescape.js +5 -0
  26. package/build/legacy/htmlescape.js.map +1 -1
  27. package/build/modern/{HydrationStreamProvider-D_lqnUNo.d.ts → HydrationStreamProvider-DrbxOdk5.d.cts} +12 -1
  28. package/build/modern/HydrationStreamProvider-DrbxOdk5.d.cts.map +1 -0
  29. package/build/modern/{HydrationStreamProvider-D_lqnUNo.d.cts → HydrationStreamProvider-DrbxOdk5.d.ts} +12 -1
  30. package/build/modern/HydrationStreamProvider-DrbxOdk5.d.ts.map +1 -0
  31. package/build/modern/HydrationStreamProvider.cjs +15 -7
  32. package/build/modern/HydrationStreamProvider.cjs.map +1 -1
  33. package/build/modern/HydrationStreamProvider.d.cts +1 -1
  34. package/build/modern/HydrationStreamProvider.d.ts +1 -1
  35. package/build/modern/HydrationStreamProvider.js +15 -7
  36. package/build/modern/HydrationStreamProvider.js.map +1 -1
  37. package/build/modern/ReactQueryStreamedHydration.cjs +5 -2
  38. package/build/modern/ReactQueryStreamedHydration.cjs.map +1 -1
  39. package/build/modern/ReactQueryStreamedHydration.d.cts +6 -3
  40. package/build/modern/ReactQueryStreamedHydration.d.cts.map +1 -1
  41. package/build/modern/ReactQueryStreamedHydration.d.ts +6 -3
  42. package/build/modern/ReactQueryStreamedHydration.d.ts.map +1 -1
  43. package/build/modern/ReactQueryStreamedHydration.js +5 -2
  44. package/build/modern/ReactQueryStreamedHydration.js.map +1 -1
  45. package/build/modern/htmlescape.cjs +5 -0
  46. package/build/modern/htmlescape.cjs.map +1 -1
  47. package/build/modern/htmlescape.d.cts +5 -0
  48. package/build/modern/htmlescape.d.cts.map +1 -1
  49. package/build/modern/htmlescape.d.ts +5 -0
  50. package/build/modern/htmlescape.d.ts.map +1 -1
  51. package/build/modern/htmlescape.js +5 -0
  52. package/build/modern/htmlescape.js.map +1 -1
  53. package/package.json +6 -6
  54. package/src/HydrationStreamProvider.tsx +21 -7
  55. package/src/ReactQueryStreamedHydration.tsx +5 -2
  56. package/src/htmlescape.ts +5 -0
  57. package/build/legacy/HydrationStreamProvider-D_lqnUNo.d.cts.map +0 -1
  58. package/build/legacy/HydrationStreamProvider-D_lqnUNo.d.ts.map +0 -1
  59. package/build/modern/HydrationStreamProvider-D_lqnUNo.d.cts.map +0 -1
  60. package/build/modern/HydrationStreamProvider-D_lqnUNo.d.ts.map +0 -1
@@ -15,7 +15,13 @@ interface HydrationStreamContext<TShape> {
15
15
  push: (...shape: Array<TShape>) => void;
16
16
  };
17
17
  }
18
+ /**
19
+ * The props of the `Provider` returned by `createHydrationStreamProvider`.
20
+ */
18
21
  interface HydrationStreamProviderProps<TShape> {
22
+ /**
23
+ * The children to render inside the stream provider.
24
+ */
19
25
  children: React.ReactNode;
20
26
  /**
21
27
  * Optional transformer to serialize/deserialize the data
@@ -37,6 +43,11 @@ interface HydrationStreamProviderProps<TShape> {
37
43
  */
38
44
  nonce?: string;
39
45
  }
46
+ /**
47
+ * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the
48
+ * client while the page streams in, and the context it shares the stream through.
49
+ * @returns The `Provider` component and its `context`.
50
+ */
40
51
  declare function createHydrationStreamProvider<TShape>(): {
41
52
  Provider: (props: {
42
53
  children: React.ReactNode;
@@ -64,4 +75,4 @@ declare function createHydrationStreamProvider<TShape>(): {
64
75
  };
65
76
  //#endregion
66
77
  export { createHydrationStreamProvider as n, HydrationStreamProviderProps as t };
67
- //# sourceMappingURL=HydrationStreamProvider-D_lqnUNo.d.ts.map
78
+ //# sourceMappingURL=HydrationStreamProvider-DrbxOdk5.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HydrationStreamProvider-DrbxOdk5.d.cts","names":[],"sources":["../../src/HydrationStreamProvider.tsx"],"mappings":";;UASU;EACR,YAAY;EACZ,cAAc;;UAYN,uBAAuB;EAC/B;EACA;;;;;;IAME,UAAU,OAAO,MAAM;;;;;;UAOV,6BAA6B;;;;EAI5C,UAAU,MAAM;;;;;EAKhB,cAAc;;;;;EAKd,YAAY,SAAS,MAAM;;;;;EAK3B,gBAAgB,MAAM;;;;EAItB;;;;;;;iBAQc,8BAA8B;EAgBK,WAAA;IAC/C,UAAU,MAAM;;;;;IAKhB,cAAc;;;;;IAKd,YAAY,SAAS,MAAM;;;;;IAK3B,gBAAgB,MAAM;;;;IAItB;oCACD,IAAA"}
@@ -15,7 +15,13 @@ interface HydrationStreamContext<TShape> {
15
15
  push: (...shape: Array<TShape>) => void;
16
16
  };
17
17
  }
18
+ /**
19
+ * The props of the `Provider` returned by `createHydrationStreamProvider`.
20
+ */
18
21
  interface HydrationStreamProviderProps<TShape> {
22
+ /**
23
+ * The children to render inside the stream provider.
24
+ */
19
25
  children: React.ReactNode;
20
26
  /**
21
27
  * Optional transformer to serialize/deserialize the data
@@ -37,6 +43,11 @@ interface HydrationStreamProviderProps<TShape> {
37
43
  */
38
44
  nonce?: string;
39
45
  }
46
+ /**
47
+ * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the
48
+ * client while the page streams in, and the context it shares the stream through.
49
+ * @returns The `Provider` component and its `context`.
50
+ */
40
51
  declare function createHydrationStreamProvider<TShape>(): {
41
52
  Provider: (props: {
42
53
  children: React.ReactNode;
@@ -64,4 +75,4 @@ declare function createHydrationStreamProvider<TShape>(): {
64
75
  };
65
76
  //#endregion
66
77
  export { createHydrationStreamProvider as n, HydrationStreamProviderProps as t };
67
- //# sourceMappingURL=HydrationStreamProvider-D_lqnUNo.d.cts.map
78
+ //# sourceMappingURL=HydrationStreamProvider-DrbxOdk5.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HydrationStreamProvider-DrbxOdk5.d.ts","names":[],"sources":["../../src/HydrationStreamProvider.tsx"],"mappings":";;UASU;EACR,YAAY;EACZ,cAAc;;UAYN,uBAAuB;EAC/B;EACA;;;;;;IAME,UAAU,OAAO,MAAM;;;;;;UAOV,6BAA6B;;;;EAI5C,UAAU,MAAM;;;;;EAKhB,cAAc;;;;;EAKd,YAAY,SAAS,MAAM;;;;;EAK3B,gBAAgB,MAAM;;;;EAItB;;;;;;;iBAQc,8BAA8B;EAgBK,WAAA;IAC/C,UAAU,MAAM;;;;;IAKhB,cAAc;;;;;IAKd,YAAY,SAAS,MAAM;;;;;IAK3B,gBAAgB,MAAM;;;;IAItB;oCACD,IAAA"}
@@ -8,17 +8,25 @@ 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
+ /**
12
+ * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the
13
+ * client while the page streams in, and the context it shares the stream through.
14
+ * @returns The `Provider` component and its `context`.
15
+ */
11
16
  function createHydrationStreamProvider() {
12
17
  const StreamContext = react.createContext(null);
13
18
  /**
14
-
15
- * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes
16
- * - This means that we might have some new entries in the cache that needs to be flushed
17
- * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`
19
+ * 1. (Happens on server): the callback registered with `useServerInsertedHTML()` is called **on the server** whenever
20
+ * Next.js inserts HTML into the streamed response.
21
+ * - This means that we might have some new entries in the cache that needs to be flushed.
22
+ * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`.
18
23
  * 2. (Happens in browser) In `useEffect()`:
19
- * - 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
20
- * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received
21
- **/
24
+ * - 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.
25
+ * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received.
26
+ * @param props - The `children` to render, the `onEntries`/`onFlush` callbacks, and the optional
27
+ * `transformer` and `nonce`.
28
+ * @returns The `children`, wrapped in the stream context provider.
29
+ */
22
30
  function UseClientHydrationStreamProvider(props) {
23
31
  const id = `__RQ${react.useId()}`;
24
32
  const idJSON = require_htmlescape.htmlEscapeJsonString(JSON.stringify(id));
@@ -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 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
+ {"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\n/**\n * The props of the `Provider` returned by `createHydrationStreamProvider`.\n */\nexport interface HydrationStreamProviderProps<TShape> {\n /**\n * The children to render inside the stream provider.\n */\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\n/**\n * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the\n * client while the page streams in, and the context it shares the stream through.\n * @returns The `Provider` component and its `context`.\n */\nexport function createHydrationStreamProvider<TShape>() {\n const StreamContext = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n * 1. (Happens on server): the callback registered with `useServerInsertedHTML()` is called **on the server** whenever\n * Next.js inserts HTML into the streamed response.\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 * @param props - The `children` to render, the `onEntries`/`onFlush` callbacks, and the optional\n * `transformer` and `nonce`.\n * @returns The `children`, wrapped in the stream context provider.\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":";;;;;;;;;;;;;;;AAqEA,SAAgB,gCAAwC;CACtD,MAAM,gBAAgBA,MAAM,cAC1B,IACF;;;;;;;;;;;;;CAaA,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,2 +1,2 @@
1
- import { n as createHydrationStreamProvider, t as HydrationStreamProviderProps } from "./HydrationStreamProvider-D_lqnUNo.cjs";
1
+ import { n as createHydrationStreamProvider, t as HydrationStreamProviderProps } from "./HydrationStreamProvider-DrbxOdk5.cjs";
2
2
  export { HydrationStreamProviderProps, createHydrationStreamProvider };
@@ -1,2 +1,2 @@
1
- import { n as createHydrationStreamProvider, t as HydrationStreamProviderProps } from "./HydrationStreamProvider-D_lqnUNo.js";
1
+ import { n as createHydrationStreamProvider, t as HydrationStreamProviderProps } from "./HydrationStreamProvider-DrbxOdk5.js";
2
2
  export { HydrationStreamProviderProps, createHydrationStreamProvider };
@@ -5,17 +5,25 @@ 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
+ /**
9
+ * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the
10
+ * client while the page streams in, and the context it shares the stream through.
11
+ * @returns The `Provider` component and its `context`.
12
+ */
8
13
  function createHydrationStreamProvider() {
9
14
  const StreamContext = React.createContext(null);
10
15
  /**
11
-
12
- * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes
13
- * - This means that we might have some new entries in the cache that needs to be flushed
14
- * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`
16
+ * 1. (Happens on server): the callback registered with `useServerInsertedHTML()` is called **on the server** whenever
17
+ * Next.js inserts HTML into the streamed response.
18
+ * - This means that we might have some new entries in the cache that needs to be flushed.
19
+ * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`.
15
20
  * 2. (Happens in browser) In `useEffect()`:
16
- * - 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
17
- * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received
18
- **/
21
+ * - 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.
22
+ * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received.
23
+ * @param props - The `children` to render, the `onEntries`/`onFlush` callbacks, and the optional
24
+ * `transformer` and `nonce`.
25
+ * @returns The `children`, wrapped in the stream context provider.
26
+ */
19
27
  function UseClientHydrationStreamProvider(props) {
20
28
  const id = `__RQ${React.useId()}`;
21
29
  const idJSON = htmlEscapeJsonString(JSON.stringify(id));
@@ -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 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"}
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\n/**\n * The props of the `Provider` returned by `createHydrationStreamProvider`.\n */\nexport interface HydrationStreamProviderProps<TShape> {\n /**\n * The children to render inside the stream provider.\n */\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\n/**\n * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the\n * client while the page streams in, and the context it shares the stream through.\n * @returns The `Provider` component and its `context`.\n */\nexport function createHydrationStreamProvider<TShape>() {\n const StreamContext = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n * 1. (Happens on server): the callback registered with `useServerInsertedHTML()` is called **on the server** whenever\n * Next.js inserts HTML into the streamed response.\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 * @param props - The `children` to render, the `onEntries`/`onFlush` callbacks, and the optional\n * `transformer` and `nonce`.\n * @returns The `children`, wrapped in the stream context provider.\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":";;;;;;;;;;;;AAqEA,SAAgB,gCAAwC;CACtD,MAAM,gBAAgB,MAAM,cAC1B,IACF;;;;;;;;;;;;;CAaA,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"}
@@ -10,8 +10,11 @@ let react_jsx_runtime = require("react/jsx-runtime");
10
10
  const stream = require_HydrationStreamProvider.createHydrationStreamProvider();
11
11
  /**
12
12
  * This component is responsible for:
13
- * - hydrating the query client on the server
14
- * - dehydrating the query client on the server
13
+ * - dehydrating the query client on the server.
14
+ * - hydrating the query client in the browser.
15
+ * @param props - The `children` to render, an optional custom `queryClient`, the `nonce` for the
16
+ * inline script, the hydrate and dehydrate `options`, and the data `transformer`.
17
+ * @returns The `children`, wrapped in the hydration stream provider.
15
18
  */
16
19
  function ReactQueryStreamedHydration(props) {
17
20
  const queryClient = (0, _tanstack_react_query.useQueryClient)(props.queryClient);
@@ -1 +1 @@
1
- {"version":3,"file":"ReactQueryStreamedHydration.cjs","names":["createHydrationStreamProvider","useQueryClient","React","environmentManager","defaultShouldDehydrateQuery","dehydrate"],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"sourcesContent":["'use client'\n\nimport {\n defaultShouldDehydrateQuery,\n dehydrate,\n environmentManager,\n hydrate,\n useQueryClient,\n} from '@tanstack/react-query'\nimport * as React from 'react'\nimport { createHydrationStreamProvider } from './HydrationStreamProvider'\nimport type { HydrationStreamProviderProps } from './HydrationStreamProvider'\nimport type {\n DehydrateOptions,\n DehydratedState,\n HydrateOptions,\n QueryClient,\n} from '@tanstack/react-query'\n\nconst stream = createHydrationStreamProvider<DehydratedState>()\n\n/**\n * This component is responsible for:\n * - hydrating the query client on the server\n * - dehydrating the query client on the server\n */\nexport function ReactQueryStreamedHydration(props: {\n children: React.ReactNode\n queryClient?: QueryClient\n nonce?: string\n options?: {\n hydrate?: HydrateOptions\n dehydrate?: DehydrateOptions\n }\n transformer?: HydrationStreamProviderProps<DehydratedState>['transformer']\n}) {\n const queryClient = useQueryClient(props.queryClient)\n\n /**\n * We need to track which queries were added/updated during the render\n */\n const [trackedKeys] = React.useState(() => new Set<string>())\n\n // <server only>\n if (environmentManager.isServer()) {\n // Do we need to care about unsubscribing? I don't think so to be honest\n queryClient.getQueryCache().subscribe((event) => {\n switch (event.type) {\n case 'added':\n case 'updated':\n // console.log('tracking', event.query.queryHash, 'b/c of a', event.type)\n trackedKeys.add(event.query.queryHash)\n }\n })\n }\n // </server only>\n\n return (\n <stream.Provider\n // Happens on server:\n onFlush={() => {\n /**\n * Dehydrated state of the client where we only include the queries that were added/updated since the last flush\n */\n const shouldDehydrate =\n props.options?.dehydrate?.shouldDehydrateQuery ??\n defaultShouldDehydrateQuery\n\n const dehydratedState = dehydrate(queryClient, {\n ...props.options?.dehydrate,\n shouldDehydrateQuery(query) {\n return trackedKeys.has(query.queryHash) && shouldDehydrate(query)\n },\n })\n trackedKeys.clear()\n\n if (!dehydratedState.queries.length) {\n return []\n }\n\n return [dehydratedState]\n }}\n // Happens in browser:\n onEntries={(entries) => {\n for (const hydratedState of entries) {\n hydrate(queryClient, hydratedState, props.options?.hydrate)\n }\n }}\n // Handle BigInts etc using superjson\n transformer={props.transformer}\n nonce={props.nonce}\n >\n {props.children}\n </stream.Provider>\n )\n}\n"],"mappings":";;;;;;;;;AAmBA,MAAM,SAASA,gCAAAA,8BAA+C;;;;;;AAO9D,SAAgB,4BAA4B,OASzC;CACD,MAAM,eAAA,GAAcC,sBAAAA,eAAAA,CAAe,MAAM,WAAW;;;;CAKpD,MAAM,CAAC,eAAeC,MAAM,+BAAe,IAAI,IAAY,CAAC;CAG5D,IAAIC,sBAAAA,mBAAmB,SAAS,GAE9B,YAAY,cAAc,CAAC,CAAC,WAAW,UAAU;EAC/C,QAAQ,MAAM,MAAd;GACE,KAAK;GACL,KAAK,WAEH,YAAY,IAAI,MAAM,MAAM,SAAS;EACzC;CACF,CAAC;CAIH,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAO,UAAR;EAEE,eAAe;;;;;GAIb,MAAM,oBAAA,iBACJ,MAAM,aAAA,QAAA,mBAAA,KAAA,MAAA,iBAAA,eAAS,eAAA,QAAA,mBAAA,KAAA,IAAA,KAAA,IAAA,eAAW,yBAC1BC,sBAAAA;GAEF,MAAM,mBAAA,GAAkBC,sBAAAA,UAAAA,CAAU,aAAa;IAC7C,IAAA,kBAAG,MAAM,aAAA,QAAA,oBAAA,KAAA,IAAA,KAAA,IAAA,gBAAS;IAClB,qBAAqB,OAAO;KAC1B,OAAO,YAAY,IAAI,MAAM,SAAS,KAAK,gBAAgB,KAAK;IAClE;GACF,CAAC;GACD,YAAY,MAAM;GAElB,IAAI,CAAC,gBAAgB,QAAQ,QAC3B,OAAO,CAAC;GAGV,OAAO,CAAC,eAAe;EACzB;EAEA,YAAY,YAAY;GACtB,KAAK,MAAM,iBAAiB,SAAS;;IACnC,CAAA,GAAA,sBAAA,QAAA,CAAQ,aAAa,gBAAA,kBAAe,MAAM,aAAA,QAAA,oBAAA,KAAA,IAAA,KAAA,IAAA,gBAAS,OAAO;GAC5D;EACF;EAEA,aAAa,MAAM;EACnB,OAAO,MAAM;EAEZ,UAAA,MAAM;CACQ,CAAA;AAErB"}
1
+ {"version":3,"file":"ReactQueryStreamedHydration.cjs","names":["createHydrationStreamProvider","useQueryClient","React","environmentManager","defaultShouldDehydrateQuery","dehydrate"],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"sourcesContent":["'use client'\n\nimport {\n defaultShouldDehydrateQuery,\n dehydrate,\n environmentManager,\n hydrate,\n useQueryClient,\n} from '@tanstack/react-query'\nimport * as React from 'react'\nimport { createHydrationStreamProvider } from './HydrationStreamProvider'\nimport type { HydrationStreamProviderProps } from './HydrationStreamProvider'\nimport type {\n DehydrateOptions,\n DehydratedState,\n HydrateOptions,\n QueryClient,\n} from '@tanstack/react-query'\n\nconst stream = createHydrationStreamProvider<DehydratedState>()\n\n/**\n * This component is responsible for:\n * - dehydrating the query client on the server.\n * - hydrating the query client in the browser.\n * @param props - The `children` to render, an optional custom `queryClient`, the `nonce` for the\n * inline script, the hydrate and dehydrate `options`, and the data `transformer`.\n * @returns The `children`, wrapped in the hydration stream provider.\n */\nexport function ReactQueryStreamedHydration(props: {\n children: React.ReactNode\n queryClient?: QueryClient\n nonce?: string\n options?: {\n hydrate?: HydrateOptions\n dehydrate?: DehydrateOptions\n }\n transformer?: HydrationStreamProviderProps<DehydratedState>['transformer']\n}) {\n const queryClient = useQueryClient(props.queryClient)\n\n /**\n * We need to track which queries were added/updated during the render\n */\n const [trackedKeys] = React.useState(() => new Set<string>())\n\n // <server only>\n if (environmentManager.isServer()) {\n // Do we need to care about unsubscribing? I don't think so to be honest\n queryClient.getQueryCache().subscribe((event) => {\n switch (event.type) {\n case 'added':\n case 'updated':\n // console.log('tracking', event.query.queryHash, 'b/c of a', event.type)\n trackedKeys.add(event.query.queryHash)\n }\n })\n }\n // </server only>\n\n return (\n <stream.Provider\n // Happens on server:\n onFlush={() => {\n /**\n * Dehydrated state of the client where we only include the queries that were added/updated since the last flush\n */\n const shouldDehydrate =\n props.options?.dehydrate?.shouldDehydrateQuery ??\n defaultShouldDehydrateQuery\n\n const dehydratedState = dehydrate(queryClient, {\n ...props.options?.dehydrate,\n shouldDehydrateQuery(query) {\n return trackedKeys.has(query.queryHash) && shouldDehydrate(query)\n },\n })\n trackedKeys.clear()\n\n if (!dehydratedState.queries.length) {\n return []\n }\n\n return [dehydratedState]\n }}\n // Happens in browser:\n onEntries={(entries) => {\n for (const hydratedState of entries) {\n hydrate(queryClient, hydratedState, props.options?.hydrate)\n }\n }}\n // Handle BigInts etc using superjson\n transformer={props.transformer}\n nonce={props.nonce}\n >\n {props.children}\n </stream.Provider>\n )\n}\n"],"mappings":";;;;;;;;;AAmBA,MAAM,SAASA,gCAAAA,8BAA+C;;;;;;;;;AAU9D,SAAgB,4BAA4B,OASzC;CACD,MAAM,eAAA,GAAcC,sBAAAA,eAAAA,CAAe,MAAM,WAAW;;;;CAKpD,MAAM,CAAC,eAAeC,MAAM,+BAAe,IAAI,IAAY,CAAC;CAG5D,IAAIC,sBAAAA,mBAAmB,SAAS,GAE9B,YAAY,cAAc,CAAC,CAAC,WAAW,UAAU;EAC/C,QAAQ,MAAM,MAAd;GACE,KAAK;GACL,KAAK,WAEH,YAAY,IAAI,MAAM,MAAM,SAAS;EACzC;CACF,CAAC;CAIH,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAO,UAAR;EAEE,eAAe;;;;;GAIb,MAAM,oBAAA,iBACJ,MAAM,aAAA,QAAA,mBAAA,KAAA,MAAA,iBAAA,eAAS,eAAA,QAAA,mBAAA,KAAA,IAAA,KAAA,IAAA,eAAW,yBAC1BC,sBAAAA;GAEF,MAAM,mBAAA,GAAkBC,sBAAAA,UAAAA,CAAU,aAAa;IAC7C,IAAA,kBAAG,MAAM,aAAA,QAAA,oBAAA,KAAA,IAAA,KAAA,IAAA,gBAAS;IAClB,qBAAqB,OAAO;KAC1B,OAAO,YAAY,IAAI,MAAM,SAAS,KAAK,gBAAgB,KAAK;IAClE;GACF,CAAC;GACD,YAAY,MAAM;GAElB,IAAI,CAAC,gBAAgB,QAAQ,QAC3B,OAAO,CAAC;GAGV,OAAO,CAAC,eAAe;EACzB;EAEA,YAAY,YAAY;GACtB,KAAK,MAAM,iBAAiB,SAAS;;IACnC,CAAA,GAAA,sBAAA,QAAA,CAAQ,aAAa,gBAAA,kBAAe,MAAM,aAAA,QAAA,oBAAA,KAAA,IAAA,KAAA,IAAA,gBAAS,OAAO;GAC5D;EACF;EAEA,aAAa,MAAM;EACnB,OAAO,MAAM;EAEZ,UAAA,MAAM;CACQ,CAAA;AAErB"}
@@ -1,11 +1,14 @@
1
- import { t as HydrationStreamProviderProps } from "./HydrationStreamProvider-D_lqnUNo.cjs";
1
+ import { t as HydrationStreamProviderProps } from "./HydrationStreamProvider-DrbxOdk5.cjs";
2
2
  import * as React from "react";
3
3
  import { DehydrateOptions, DehydratedState, HydrateOptions, QueryClient } from "@tanstack/react-query";
4
4
  //#region src/ReactQueryStreamedHydration.d.ts
5
5
  /**
6
6
  * This component is responsible for:
7
- * - hydrating the query client on the server
8
- * - dehydrating the query client on the server
7
+ * - dehydrating the query client on the server.
8
+ * - hydrating the query client in the browser.
9
+ * @param props - The `children` to render, an optional custom `queryClient`, the `nonce` for the
10
+ * inline script, the hydrate and dehydrate `options`, and the data `transformer`.
11
+ * @returns The `children`, wrapped in the hydration stream provider.
9
12
  */
10
13
  export declare function ReactQueryStreamedHydration(props: {
11
14
  children: React.ReactNode;
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"ReactQueryStreamedHydration.d.cts","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"mappings":";;;;;;;;;;;;wBA6BgB,4BAA4B;EAC1C,UAAU,MAAM;EAChB,cAAc;EACd;EACA;IACE,UAAU;IACV,YAAY;;EAEd,cAAc,6BAA6B;gCAC5C,IAAA"}
@@ -1,11 +1,14 @@
1
- import { t as HydrationStreamProviderProps } from "./HydrationStreamProvider-D_lqnUNo.js";
1
+ import { t as HydrationStreamProviderProps } from "./HydrationStreamProvider-DrbxOdk5.js";
2
2
  import { DehydrateOptions, DehydratedState, HydrateOptions, QueryClient } from "@tanstack/react-query";
3
3
  import * as React from "react";
4
4
  //#region src/ReactQueryStreamedHydration.d.ts
5
5
  /**
6
6
  * This component is responsible for:
7
- * - hydrating the query client on the server
8
- * - dehydrating the query client on the server
7
+ * - dehydrating the query client on the server.
8
+ * - hydrating the query client in the browser.
9
+ * @param props - The `children` to render, an optional custom `queryClient`, the `nonce` for the
10
+ * inline script, the hydrate and dehydrate `options`, and the data `transformer`.
11
+ * @returns The `children`, wrapped in the hydration stream provider.
9
12
  */
10
13
  export declare function ReactQueryStreamedHydration(props: {
11
14
  children: React.ReactNode;
@@ -1 +1 @@
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
+ {"version":3,"file":"ReactQueryStreamedHydration.d.ts","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"mappings":";;;;;;;;;;;;wBA6BgB,4BAA4B;EAC1C,UAAU,MAAM;EAChB,cAAc;EACd;EACA;IACE,UAAU;IACV,YAAY;;EAEd,cAAc,6BAA6B;gCAC5C,IAAA"}
@@ -7,8 +7,11 @@ import { jsx } from "react/jsx-runtime";
7
7
  const stream = createHydrationStreamProvider();
8
8
  /**
9
9
  * This component is responsible for:
10
- * - hydrating the query client on the server
11
- * - dehydrating the query client on the server
10
+ * - dehydrating the query client on the server.
11
+ * - hydrating the query client in the browser.
12
+ * @param props - The `children` to render, an optional custom `queryClient`, the `nonce` for the
13
+ * inline script, the hydrate and dehydrate `options`, and the data `transformer`.
14
+ * @returns The `children`, wrapped in the hydration stream provider.
12
15
  */
13
16
  function ReactQueryStreamedHydration(props) {
14
17
  const queryClient = useQueryClient(props.queryClient);
@@ -1 +1 @@
1
- {"version":3,"file":"ReactQueryStreamedHydration.js","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"sourcesContent":["'use client'\n\nimport {\n defaultShouldDehydrateQuery,\n dehydrate,\n environmentManager,\n hydrate,\n useQueryClient,\n} from '@tanstack/react-query'\nimport * as React from 'react'\nimport { createHydrationStreamProvider } from './HydrationStreamProvider'\nimport type { HydrationStreamProviderProps } from './HydrationStreamProvider'\nimport type {\n DehydrateOptions,\n DehydratedState,\n HydrateOptions,\n QueryClient,\n} from '@tanstack/react-query'\n\nconst stream = createHydrationStreamProvider<DehydratedState>()\n\n/**\n * This component is responsible for:\n * - hydrating the query client on the server\n * - dehydrating the query client on the server\n */\nexport function ReactQueryStreamedHydration(props: {\n children: React.ReactNode\n queryClient?: QueryClient\n nonce?: string\n options?: {\n hydrate?: HydrateOptions\n dehydrate?: DehydrateOptions\n }\n transformer?: HydrationStreamProviderProps<DehydratedState>['transformer']\n}) {\n const queryClient = useQueryClient(props.queryClient)\n\n /**\n * We need to track which queries were added/updated during the render\n */\n const [trackedKeys] = React.useState(() => new Set<string>())\n\n // <server only>\n if (environmentManager.isServer()) {\n // Do we need to care about unsubscribing? I don't think so to be honest\n queryClient.getQueryCache().subscribe((event) => {\n switch (event.type) {\n case 'added':\n case 'updated':\n // console.log('tracking', event.query.queryHash, 'b/c of a', event.type)\n trackedKeys.add(event.query.queryHash)\n }\n })\n }\n // </server only>\n\n return (\n <stream.Provider\n // Happens on server:\n onFlush={() => {\n /**\n * Dehydrated state of the client where we only include the queries that were added/updated since the last flush\n */\n const shouldDehydrate =\n props.options?.dehydrate?.shouldDehydrateQuery ??\n defaultShouldDehydrateQuery\n\n const dehydratedState = dehydrate(queryClient, {\n ...props.options?.dehydrate,\n shouldDehydrateQuery(query) {\n return trackedKeys.has(query.queryHash) && shouldDehydrate(query)\n },\n })\n trackedKeys.clear()\n\n if (!dehydratedState.queries.length) {\n return []\n }\n\n return [dehydratedState]\n }}\n // Happens in browser:\n onEntries={(entries) => {\n for (const hydratedState of entries) {\n hydrate(queryClient, hydratedState, props.options?.hydrate)\n }\n }}\n // Handle BigInts etc using superjson\n transformer={props.transformer}\n nonce={props.nonce}\n >\n {props.children}\n </stream.Provider>\n )\n}\n"],"mappings":";;;;;;AAmBA,MAAM,SAAS,8BAA+C;;;;;;AAO9D,SAAgB,4BAA4B,OASzC;CACD,MAAM,cAAc,eAAe,MAAM,WAAW;;;;CAKpD,MAAM,CAAC,eAAe,MAAM,+BAAe,IAAI,IAAY,CAAC;CAG5D,IAAI,mBAAmB,SAAS,GAE9B,YAAY,cAAc,CAAC,CAAC,WAAW,UAAU;EAC/C,QAAQ,MAAM,MAAd;GACE,KAAK;GACL,KAAK,WAEH,YAAY,IAAI,MAAM,MAAM,SAAS;EACzC;CACF,CAAC;CAIH,OACE,oBAAC,OAAO,UAAR;EAEE,eAAe;;;;;GAIb,MAAM,oBAAA,iBACJ,MAAM,aAAA,QAAA,mBAAA,KAAA,MAAA,iBAAA,eAAS,eAAA,QAAA,mBAAA,KAAA,IAAA,KAAA,IAAA,eAAW,yBAC1B;GAEF,MAAM,kBAAkB,UAAU,aAAa;IAC7C,IAAA,kBAAG,MAAM,aAAA,QAAA,oBAAA,KAAA,IAAA,KAAA,IAAA,gBAAS;IAClB,qBAAqB,OAAO;KAC1B,OAAO,YAAY,IAAI,MAAM,SAAS,KAAK,gBAAgB,KAAK;IAClE;GACF,CAAC;GACD,YAAY,MAAM;GAElB,IAAI,CAAC,gBAAgB,QAAQ,QAC3B,OAAO,CAAC;GAGV,OAAO,CAAC,eAAe;EACzB;EAEA,YAAY,YAAY;GACtB,KAAK,MAAM,iBAAiB,SAAS;;IACnC,QAAQ,aAAa,gBAAA,kBAAe,MAAM,aAAA,QAAA,oBAAA,KAAA,IAAA,KAAA,IAAA,gBAAS,OAAO;GAC5D;EACF;EAEA,aAAa,MAAM;EACnB,OAAO,MAAM;EAEZ,UAAA,MAAM;CACQ,CAAA;AAErB"}
1
+ {"version":3,"file":"ReactQueryStreamedHydration.js","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"sourcesContent":["'use client'\n\nimport {\n defaultShouldDehydrateQuery,\n dehydrate,\n environmentManager,\n hydrate,\n useQueryClient,\n} from '@tanstack/react-query'\nimport * as React from 'react'\nimport { createHydrationStreamProvider } from './HydrationStreamProvider'\nimport type { HydrationStreamProviderProps } from './HydrationStreamProvider'\nimport type {\n DehydrateOptions,\n DehydratedState,\n HydrateOptions,\n QueryClient,\n} from '@tanstack/react-query'\n\nconst stream = createHydrationStreamProvider<DehydratedState>()\n\n/**\n * This component is responsible for:\n * - dehydrating the query client on the server.\n * - hydrating the query client in the browser.\n * @param props - The `children` to render, an optional custom `queryClient`, the `nonce` for the\n * inline script, the hydrate and dehydrate `options`, and the data `transformer`.\n * @returns The `children`, wrapped in the hydration stream provider.\n */\nexport function ReactQueryStreamedHydration(props: {\n children: React.ReactNode\n queryClient?: QueryClient\n nonce?: string\n options?: {\n hydrate?: HydrateOptions\n dehydrate?: DehydrateOptions\n }\n transformer?: HydrationStreamProviderProps<DehydratedState>['transformer']\n}) {\n const queryClient = useQueryClient(props.queryClient)\n\n /**\n * We need to track which queries were added/updated during the render\n */\n const [trackedKeys] = React.useState(() => new Set<string>())\n\n // <server only>\n if (environmentManager.isServer()) {\n // Do we need to care about unsubscribing? I don't think so to be honest\n queryClient.getQueryCache().subscribe((event) => {\n switch (event.type) {\n case 'added':\n case 'updated':\n // console.log('tracking', event.query.queryHash, 'b/c of a', event.type)\n trackedKeys.add(event.query.queryHash)\n }\n })\n }\n // </server only>\n\n return (\n <stream.Provider\n // Happens on server:\n onFlush={() => {\n /**\n * Dehydrated state of the client where we only include the queries that were added/updated since the last flush\n */\n const shouldDehydrate =\n props.options?.dehydrate?.shouldDehydrateQuery ??\n defaultShouldDehydrateQuery\n\n const dehydratedState = dehydrate(queryClient, {\n ...props.options?.dehydrate,\n shouldDehydrateQuery(query) {\n return trackedKeys.has(query.queryHash) && shouldDehydrate(query)\n },\n })\n trackedKeys.clear()\n\n if (!dehydratedState.queries.length) {\n return []\n }\n\n return [dehydratedState]\n }}\n // Happens in browser:\n onEntries={(entries) => {\n for (const hydratedState of entries) {\n hydrate(queryClient, hydratedState, props.options?.hydrate)\n }\n }}\n // Handle BigInts etc using superjson\n transformer={props.transformer}\n nonce={props.nonce}\n >\n {props.children}\n </stream.Provider>\n )\n}\n"],"mappings":";;;;;;AAmBA,MAAM,SAAS,8BAA+C;;;;;;;;;AAU9D,SAAgB,4BAA4B,OASzC;CACD,MAAM,cAAc,eAAe,MAAM,WAAW;;;;CAKpD,MAAM,CAAC,eAAe,MAAM,+BAAe,IAAI,IAAY,CAAC;CAG5D,IAAI,mBAAmB,SAAS,GAE9B,YAAY,cAAc,CAAC,CAAC,WAAW,UAAU;EAC/C,QAAQ,MAAM,MAAd;GACE,KAAK;GACL,KAAK,WAEH,YAAY,IAAI,MAAM,MAAM,SAAS;EACzC;CACF,CAAC;CAIH,OACE,oBAAC,OAAO,UAAR;EAEE,eAAe;;;;;GAIb,MAAM,oBAAA,iBACJ,MAAM,aAAA,QAAA,mBAAA,KAAA,MAAA,iBAAA,eAAS,eAAA,QAAA,mBAAA,KAAA,IAAA,KAAA,IAAA,eAAW,yBAC1B;GAEF,MAAM,kBAAkB,UAAU,aAAa;IAC7C,IAAA,kBAAG,MAAM,aAAA,QAAA,oBAAA,KAAA,IAAA,KAAA,IAAA,gBAAS;IAClB,qBAAqB,OAAO;KAC1B,OAAO,YAAY,IAAI,MAAM,SAAS,KAAK,gBAAgB,KAAK;IAClE;GACF,CAAC;GACD,YAAY,MAAM;GAElB,IAAI,CAAC,gBAAgB,QAAQ,QAC3B,OAAO,CAAC;GAGV,OAAO,CAAC,eAAe;EACzB;EAEA,YAAY,YAAY;GACtB,KAAK,MAAM,iBAAiB,SAAS;;IACnC,QAAQ,aAAa,gBAAA,kBAAe,MAAM,aAAA,QAAA,oBAAA,KAAA,IAAA,KAAA,IAAA,gBAAS,OAAO;GAC5D;EACF;EAEA,aAAa,MAAM;EACnB,OAAO,MAAM;EAEZ,UAAA,MAAM;CACQ,CAAA;AAErB"}
@@ -8,6 +8,11 @@ const ESCAPE_LOOKUP = {
8
8
  "\u2029": "\\u2029"
9
9
  };
10
10
  const ESCAPE_REGEX = /[&><\u2028\u2029]/g;
11
+ /**
12
+ * Escapes the characters of a JSON string that are unsafe to embed in an HTML `<script>` tag.
13
+ * @param str - The JSON string to escape.
14
+ * @returns The string with `&`, `<`, `>`, U+2028, and U+2029 replaced by `\uXXXX` escapes.
15
+ */
11
16
  function htmlEscapeJsonString(str) {
12
17
  return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]);
13
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"htmlescape.cjs","names":[],"sources":["../../src/htmlescape.ts"],"sourcesContent":["// --------------------------------------------------------------------------------\n//\n// copied from\n// https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/src/server/htmlescape.ts\n// License: https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/license.md\n//\n// --------------------------------------------------------------------------------\n\n// This utility is based on https://github.com/zertosh/htmlescape\n// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE\n\nconst ESCAPE_LOOKUP: Record<string, string> = {\n '&': '\\\\u0026',\n '>': '\\\\u003e',\n '<': '\\\\u003c',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029',\n}\n\nexport const ESCAPE_REGEX = /[&><\\u2028\\u2029]/g\n\nexport function htmlEscapeJsonString(str: string): string {\n return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]!)\n}\n"],"mappings":";;AAWA,MAAM,gBAAwC;CAC5C,KAAK;CACL,KAAK;CACL,KAAK;CACL,UAAU;CACV,UAAU;AACZ;AAEA,MAAa,eAAe;AAE5B,SAAgB,qBAAqB,KAAqB;CACxD,OAAO,IAAI,QAAQ,eAAe,UAAU,cAAc,MAAO;AACnE"}
1
+ {"version":3,"file":"htmlescape.cjs","names":[],"sources":["../../src/htmlescape.ts"],"sourcesContent":["// --------------------------------------------------------------------------------\n//\n// copied from\n// https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/src/server/htmlescape.ts\n// License: https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/license.md\n//\n// --------------------------------------------------------------------------------\n\n// This utility is based on https://github.com/zertosh/htmlescape\n// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE\n\nconst ESCAPE_LOOKUP: Record<string, string> = {\n '&': '\\\\u0026',\n '>': '\\\\u003e',\n '<': '\\\\u003c',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029',\n}\n\nexport const ESCAPE_REGEX = /[&><\\u2028\\u2029]/g\n\n/**\n * Escapes the characters of a JSON string that are unsafe to embed in an HTML `<script>` tag.\n * @param str - The JSON string to escape.\n * @returns The string with `&`, `<`, `>`, U+2028, and U+2029 replaced by `\\uXXXX` escapes.\n */\nexport function htmlEscapeJsonString(str: string): string {\n return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]!)\n}\n"],"mappings":";;AAWA,MAAM,gBAAwC;CAC5C,KAAK;CACL,KAAK;CACL,KAAK;CACL,UAAU;CACV,UAAU;AACZ;AAEA,MAAa,eAAe;;;;;;AAO5B,SAAgB,qBAAqB,KAAqB;CACxD,OAAO,IAAI,QAAQ,eAAe,UAAU,cAAc,MAAO;AACnE"}
@@ -1,5 +1,10 @@
1
1
  //#region src/htmlescape.d.ts
2
2
  export declare const ESCAPE_REGEX: RegExp;
3
+ /**
4
+ * Escapes the characters of a JSON string that are unsafe to embed in an HTML `<script>` tag.
5
+ * @param str - The JSON string to escape.
6
+ * @returns The string with `&`, `<`, `>`, U+2028, and U+2029 replaced by `\uXXXX` escapes.
7
+ */
3
8
  export declare function htmlEscapeJsonString(str: string): string;
4
9
  //#endregion
5
10
  //# sourceMappingURL=htmlescape.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"htmlescape.d.cts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";qBAmBa,cAAY;wBAET,qBAAqB"}
1
+ {"version":3,"file":"htmlescape.d.cts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";qBAmBa,cAAY;;;;;;wBAOT,qBAAqB"}
@@ -1,5 +1,10 @@
1
1
  //#region src/htmlescape.d.ts
2
2
  export declare const ESCAPE_REGEX: RegExp;
3
+ /**
4
+ * Escapes the characters of a JSON string that are unsafe to embed in an HTML `<script>` tag.
5
+ * @param str - The JSON string to escape.
6
+ * @returns The string with `&`, `<`, `>`, U+2028, and U+2029 replaced by `\uXXXX` escapes.
7
+ */
3
8
  export declare function htmlEscapeJsonString(str: string): string;
4
9
  //#endregion
5
10
  //# sourceMappingURL=htmlescape.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"htmlescape.d.ts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";qBAmBa,cAAY;wBAET,qBAAqB"}
1
+ {"version":3,"file":"htmlescape.d.ts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";qBAmBa,cAAY;;;;;;wBAOT,qBAAqB"}
@@ -7,6 +7,11 @@ const ESCAPE_LOOKUP = {
7
7
  "\u2029": "\\u2029"
8
8
  };
9
9
  const ESCAPE_REGEX = /[&><\u2028\u2029]/g;
10
+ /**
11
+ * Escapes the characters of a JSON string that are unsafe to embed in an HTML `<script>` tag.
12
+ * @param str - The JSON string to escape.
13
+ * @returns The string with `&`, `<`, `>`, U+2028, and U+2029 replaced by `\uXXXX` escapes.
14
+ */
10
15
  function htmlEscapeJsonString(str) {
11
16
  return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]);
12
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"htmlescape.js","names":[],"sources":["../../src/htmlescape.ts"],"sourcesContent":["// --------------------------------------------------------------------------------\n//\n// copied from\n// https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/src/server/htmlescape.ts\n// License: https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/license.md\n//\n// --------------------------------------------------------------------------------\n\n// This utility is based on https://github.com/zertosh/htmlescape\n// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE\n\nconst ESCAPE_LOOKUP: Record<string, string> = {\n '&': '\\\\u0026',\n '>': '\\\\u003e',\n '<': '\\\\u003c',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029',\n}\n\nexport const ESCAPE_REGEX = /[&><\\u2028\\u2029]/g\n\nexport function htmlEscapeJsonString(str: string): string {\n return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]!)\n}\n"],"mappings":";AAWA,MAAM,gBAAwC;CAC5C,KAAK;CACL,KAAK;CACL,KAAK;CACL,UAAU;CACV,UAAU;AACZ;AAEA,MAAa,eAAe;AAE5B,SAAgB,qBAAqB,KAAqB;CACxD,OAAO,IAAI,QAAQ,eAAe,UAAU,cAAc,MAAO;AACnE"}
1
+ {"version":3,"file":"htmlescape.js","names":[],"sources":["../../src/htmlescape.ts"],"sourcesContent":["// --------------------------------------------------------------------------------\n//\n// copied from\n// https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/src/server/htmlescape.ts\n// License: https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/license.md\n//\n// --------------------------------------------------------------------------------\n\n// This utility is based on https://github.com/zertosh/htmlescape\n// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE\n\nconst ESCAPE_LOOKUP: Record<string, string> = {\n '&': '\\\\u0026',\n '>': '\\\\u003e',\n '<': '\\\\u003c',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029',\n}\n\nexport const ESCAPE_REGEX = /[&><\\u2028\\u2029]/g\n\n/**\n * Escapes the characters of a JSON string that are unsafe to embed in an HTML `<script>` tag.\n * @param str - The JSON string to escape.\n * @returns The string with `&`, `<`, `>`, U+2028, and U+2029 replaced by `\\uXXXX` escapes.\n */\nexport function htmlEscapeJsonString(str: string): string {\n return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]!)\n}\n"],"mappings":";AAWA,MAAM,gBAAwC;CAC5C,KAAK;CACL,KAAK;CACL,KAAK;CACL,UAAU;CACV,UAAU;AACZ;AAEA,MAAa,eAAe;;;;;;AAO5B,SAAgB,qBAAqB,KAAqB;CACxD,OAAO,IAAI,QAAQ,eAAe,UAAU,cAAc,MAAO;AACnE"}
@@ -15,7 +15,13 @@ interface HydrationStreamContext<TShape> {
15
15
  push: (...shape: Array<TShape>) => void;
16
16
  };
17
17
  }
18
+ /**
19
+ * The props of the `Provider` returned by `createHydrationStreamProvider`.
20
+ */
18
21
  interface HydrationStreamProviderProps<TShape> {
22
+ /**
23
+ * The children to render inside the stream provider.
24
+ */
19
25
  children: React.ReactNode;
20
26
  /**
21
27
  * Optional transformer to serialize/deserialize the data
@@ -37,6 +43,11 @@ interface HydrationStreamProviderProps<TShape> {
37
43
  */
38
44
  nonce?: string;
39
45
  }
46
+ /**
47
+ * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the
48
+ * client while the page streams in, and the context it shares the stream through.
49
+ * @returns The `Provider` component and its `context`.
50
+ */
40
51
  declare function createHydrationStreamProvider<TShape>(): {
41
52
  Provider: (props: {
42
53
  children: React.ReactNode;
@@ -64,4 +75,4 @@ declare function createHydrationStreamProvider<TShape>(): {
64
75
  };
65
76
  //#endregion
66
77
  export { createHydrationStreamProvider as n, HydrationStreamProviderProps as t };
67
- //# sourceMappingURL=HydrationStreamProvider-D_lqnUNo.d.ts.map
78
+ //# sourceMappingURL=HydrationStreamProvider-DrbxOdk5.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HydrationStreamProvider-DrbxOdk5.d.cts","names":[],"sources":["../../src/HydrationStreamProvider.tsx"],"mappings":";;UASU;EACR,YAAY;EACZ,cAAc;;UAYN,uBAAuB;EAC/B;EACA;;;;;;IAME,UAAU,OAAO,MAAM;;;;;;UAOV,6BAA6B;;;;EAI5C,UAAU,MAAM;;;;;EAKhB,cAAc;;;;;EAKd,YAAY,SAAS,MAAM;;;;;EAK3B,gBAAgB,MAAM;;;;EAItB;;;;;;;iBAQc,8BAA8B;EAgBK,WAAA;IAC/C,UAAU,MAAM;;;;;IAKhB,cAAc;;;;;IAKd,YAAY,SAAS,MAAM;;;;;IAK3B,gBAAgB,MAAM;;;;IAItB;oCACD,IAAA"}
@@ -15,7 +15,13 @@ interface HydrationStreamContext<TShape> {
15
15
  push: (...shape: Array<TShape>) => void;
16
16
  };
17
17
  }
18
+ /**
19
+ * The props of the `Provider` returned by `createHydrationStreamProvider`.
20
+ */
18
21
  interface HydrationStreamProviderProps<TShape> {
22
+ /**
23
+ * The children to render inside the stream provider.
24
+ */
19
25
  children: React.ReactNode;
20
26
  /**
21
27
  * Optional transformer to serialize/deserialize the data
@@ -37,6 +43,11 @@ interface HydrationStreamProviderProps<TShape> {
37
43
  */
38
44
  nonce?: string;
39
45
  }
46
+ /**
47
+ * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the
48
+ * client while the page streams in, and the context it shares the stream through.
49
+ * @returns The `Provider` component and its `context`.
50
+ */
40
51
  declare function createHydrationStreamProvider<TShape>(): {
41
52
  Provider: (props: {
42
53
  children: React.ReactNode;
@@ -64,4 +75,4 @@ declare function createHydrationStreamProvider<TShape>(): {
64
75
  };
65
76
  //#endregion
66
77
  export { createHydrationStreamProvider as n, HydrationStreamProviderProps as t };
67
- //# sourceMappingURL=HydrationStreamProvider-D_lqnUNo.d.cts.map
78
+ //# sourceMappingURL=HydrationStreamProvider-DrbxOdk5.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HydrationStreamProvider-DrbxOdk5.d.ts","names":[],"sources":["../../src/HydrationStreamProvider.tsx"],"mappings":";;UASU;EACR,YAAY;EACZ,cAAc;;UAYN,uBAAuB;EAC/B;EACA;;;;;;IAME,UAAU,OAAO,MAAM;;;;;;UAOV,6BAA6B;;;;EAI5C,UAAU,MAAM;;;;;EAKhB,cAAc;;;;;EAKd,YAAY,SAAS,MAAM;;;;;EAK3B,gBAAgB,MAAM;;;;EAItB;;;;;;;iBAQc,8BAA8B;EAgBK,WAAA;IAC/C,UAAU,MAAM;;;;;IAKhB,cAAc;;;;;IAKd,YAAY,SAAS,MAAM;;;;;IAK3B,gBAAgB,MAAM;;;;IAItB;oCACD,IAAA"}
@@ -8,17 +8,25 @@ 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
+ /**
12
+ * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the
13
+ * client while the page streams in, and the context it shares the stream through.
14
+ * @returns The `Provider` component and its `context`.
15
+ */
11
16
  function createHydrationStreamProvider() {
12
17
  const StreamContext = react.createContext(null);
13
18
  /**
14
-
15
- * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes
16
- * - This means that we might have some new entries in the cache that needs to be flushed
17
- * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`
19
+ * 1. (Happens on server): the callback registered with `useServerInsertedHTML()` is called **on the server** whenever
20
+ * Next.js inserts HTML into the streamed response.
21
+ * - This means that we might have some new entries in the cache that needs to be flushed.
22
+ * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`.
18
23
  * 2. (Happens in browser) In `useEffect()`:
19
- * - 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
20
- * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received
21
- **/
24
+ * - 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.
25
+ * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received.
26
+ * @param props - The `children` to render, the `onEntries`/`onFlush` callbacks, and the optional
27
+ * `transformer` and `nonce`.
28
+ * @returns The `children`, wrapped in the stream context provider.
29
+ */
22
30
  function UseClientHydrationStreamProvider(props) {
23
31
  const id = `__RQ${react.useId()}`;
24
32
  const idJSON = require_htmlescape.htmlEscapeJsonString(JSON.stringify(id));
@@ -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 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
+ {"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\n/**\n * The props of the `Provider` returned by `createHydrationStreamProvider`.\n */\nexport interface HydrationStreamProviderProps<TShape> {\n /**\n * The children to render inside the stream provider.\n */\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\n/**\n * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the\n * client while the page streams in, and the context it shares the stream through.\n * @returns The `Provider` component and its `context`.\n */\nexport function createHydrationStreamProvider<TShape>() {\n const StreamContext = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n * 1. (Happens on server): the callback registered with `useServerInsertedHTML()` is called **on the server** whenever\n * Next.js inserts HTML into the streamed response.\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 * @param props - The `children` to render, the `onEntries`/`onFlush` callbacks, and the optional\n * `transformer` and `nonce`.\n * @returns The `children`, wrapped in the stream context provider.\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":";;;;;;;;;;;;;;;AAqEA,SAAgB,gCAAwC;CACtD,MAAM,gBAAgBA,MAAM,cAC1B,IACF;;;;;;;;;;;;;CAaA,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,2 +1,2 @@
1
- import { n as createHydrationStreamProvider, t as HydrationStreamProviderProps } from "./HydrationStreamProvider-D_lqnUNo.cjs";
1
+ import { n as createHydrationStreamProvider, t as HydrationStreamProviderProps } from "./HydrationStreamProvider-DrbxOdk5.cjs";
2
2
  export { HydrationStreamProviderProps, createHydrationStreamProvider };
@@ -1,2 +1,2 @@
1
- import { n as createHydrationStreamProvider, t as HydrationStreamProviderProps } from "./HydrationStreamProvider-D_lqnUNo.js";
1
+ import { n as createHydrationStreamProvider, t as HydrationStreamProviderProps } from "./HydrationStreamProvider-DrbxOdk5.js";
2
2
  export { HydrationStreamProviderProps, createHydrationStreamProvider };
@@ -5,17 +5,25 @@ 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
+ /**
9
+ * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the
10
+ * client while the page streams in, and the context it shares the stream through.
11
+ * @returns The `Provider` component and its `context`.
12
+ */
8
13
  function createHydrationStreamProvider() {
9
14
  const StreamContext = React.createContext(null);
10
15
  /**
11
-
12
- * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes
13
- * - This means that we might have some new entries in the cache that needs to be flushed
14
- * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`
16
+ * 1. (Happens on server): the callback registered with `useServerInsertedHTML()` is called **on the server** whenever
17
+ * Next.js inserts HTML into the streamed response.
18
+ * - This means that we might have some new entries in the cache that needs to be flushed.
19
+ * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`.
15
20
  * 2. (Happens in browser) In `useEffect()`:
16
- * - 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
17
- * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received
18
- **/
21
+ * - 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.
22
+ * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received.
23
+ * @param props - The `children` to render, the `onEntries`/`onFlush` callbacks, and the optional
24
+ * `transformer` and `nonce`.
25
+ * @returns The `children`, wrapped in the stream context provider.
26
+ */
19
27
  function UseClientHydrationStreamProvider(props) {
20
28
  const id = `__RQ${React.useId()}`;
21
29
  const idJSON = htmlEscapeJsonString(JSON.stringify(id));
@@ -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 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"}
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\n/**\n * The props of the `Provider` returned by `createHydrationStreamProvider`.\n */\nexport interface HydrationStreamProviderProps<TShape> {\n /**\n * The children to render inside the stream provider.\n */\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\n/**\n * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the\n * client while the page streams in, and the context it shares the stream through.\n * @returns The `Provider` component and its `context`.\n */\nexport function createHydrationStreamProvider<TShape>() {\n const StreamContext = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n * 1. (Happens on server): the callback registered with `useServerInsertedHTML()` is called **on the server** whenever\n * Next.js inserts HTML into the streamed response.\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 * @param props - The `children` to render, the `onEntries`/`onFlush` callbacks, and the optional\n * `transformer` and `nonce`.\n * @returns The `children`, wrapped in the stream context provider.\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":";;;;;;;;;;;;AAqEA,SAAgB,gCAAwC;CACtD,MAAM,gBAAgB,MAAM,cAC1B,IACF;;;;;;;;;;;;;CAaA,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"}
@@ -10,8 +10,11 @@ let react_jsx_runtime = require("react/jsx-runtime");
10
10
  const stream = require_HydrationStreamProvider.createHydrationStreamProvider();
11
11
  /**
12
12
  * This component is responsible for:
13
- * - hydrating the query client on the server
14
- * - dehydrating the query client on the server
13
+ * - dehydrating the query client on the server.
14
+ * - hydrating the query client in the browser.
15
+ * @param props - The `children` to render, an optional custom `queryClient`, the `nonce` for the
16
+ * inline script, the hydrate and dehydrate `options`, and the data `transformer`.
17
+ * @returns The `children`, wrapped in the hydration stream provider.
15
18
  */
16
19
  function ReactQueryStreamedHydration(props) {
17
20
  const queryClient = (0, _tanstack_react_query.useQueryClient)(props.queryClient);
@@ -1 +1 @@
1
- {"version":3,"file":"ReactQueryStreamedHydration.cjs","names":["createHydrationStreamProvider","useQueryClient","React","environmentManager","defaultShouldDehydrateQuery","dehydrate"],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"sourcesContent":["'use client'\n\nimport {\n defaultShouldDehydrateQuery,\n dehydrate,\n environmentManager,\n hydrate,\n useQueryClient,\n} from '@tanstack/react-query'\nimport * as React from 'react'\nimport { createHydrationStreamProvider } from './HydrationStreamProvider'\nimport type { HydrationStreamProviderProps } from './HydrationStreamProvider'\nimport type {\n DehydrateOptions,\n DehydratedState,\n HydrateOptions,\n QueryClient,\n} from '@tanstack/react-query'\n\nconst stream = createHydrationStreamProvider<DehydratedState>()\n\n/**\n * This component is responsible for:\n * - hydrating the query client on the server\n * - dehydrating the query client on the server\n */\nexport function ReactQueryStreamedHydration(props: {\n children: React.ReactNode\n queryClient?: QueryClient\n nonce?: string\n options?: {\n hydrate?: HydrateOptions\n dehydrate?: DehydrateOptions\n }\n transformer?: HydrationStreamProviderProps<DehydratedState>['transformer']\n}) {\n const queryClient = useQueryClient(props.queryClient)\n\n /**\n * We need to track which queries were added/updated during the render\n */\n const [trackedKeys] = React.useState(() => new Set<string>())\n\n // <server only>\n if (environmentManager.isServer()) {\n // Do we need to care about unsubscribing? I don't think so to be honest\n queryClient.getQueryCache().subscribe((event) => {\n switch (event.type) {\n case 'added':\n case 'updated':\n // console.log('tracking', event.query.queryHash, 'b/c of a', event.type)\n trackedKeys.add(event.query.queryHash)\n }\n })\n }\n // </server only>\n\n return (\n <stream.Provider\n // Happens on server:\n onFlush={() => {\n /**\n * Dehydrated state of the client where we only include the queries that were added/updated since the last flush\n */\n const shouldDehydrate =\n props.options?.dehydrate?.shouldDehydrateQuery ??\n defaultShouldDehydrateQuery\n\n const dehydratedState = dehydrate(queryClient, {\n ...props.options?.dehydrate,\n shouldDehydrateQuery(query) {\n return trackedKeys.has(query.queryHash) && shouldDehydrate(query)\n },\n })\n trackedKeys.clear()\n\n if (!dehydratedState.queries.length) {\n return []\n }\n\n return [dehydratedState]\n }}\n // Happens in browser:\n onEntries={(entries) => {\n for (const hydratedState of entries) {\n hydrate(queryClient, hydratedState, props.options?.hydrate)\n }\n }}\n // Handle BigInts etc using superjson\n transformer={props.transformer}\n nonce={props.nonce}\n >\n {props.children}\n </stream.Provider>\n )\n}\n"],"mappings":";;;;;;;;;AAmBA,MAAM,SAASA,gCAAAA,8BAA+C;;;;;;AAO9D,SAAgB,4BAA4B,OASzC;CACD,MAAM,eAAA,GAAcC,sBAAAA,eAAAA,CAAe,MAAM,WAAW;;;;CAKpD,MAAM,CAAC,eAAeC,MAAM,+BAAe,IAAI,IAAY,CAAC;CAG5D,IAAIC,sBAAAA,mBAAmB,SAAS,GAE9B,YAAY,cAAc,CAAC,CAAC,WAAW,UAAU;EAC/C,QAAQ,MAAM,MAAd;GACE,KAAK;GACL,KAAK,WAEH,YAAY,IAAI,MAAM,MAAM,SAAS;EACzC;CACF,CAAC;CAIH,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAO,UAAR;EAEE,eAAe;;;;GAIb,MAAM,kBACJ,MAAM,SAAS,WAAW,wBAC1BC,sBAAAA;GAEF,MAAM,mBAAA,GAAkBC,sBAAAA,UAAAA,CAAU,aAAa;IAC7C,GAAG,MAAM,SAAS;IAClB,qBAAqB,OAAO;KAC1B,OAAO,YAAY,IAAI,MAAM,SAAS,KAAK,gBAAgB,KAAK;IAClE;GACF,CAAC;GACD,YAAY,MAAM;GAElB,IAAI,CAAC,gBAAgB,QAAQ,QAC3B,OAAO,CAAC;GAGV,OAAO,CAAC,eAAe;EACzB;EAEA,YAAY,YAAY;GACtB,KAAK,MAAM,iBAAiB,SAC1B,CAAA,GAAA,sBAAA,QAAA,CAAQ,aAAa,eAAe,MAAM,SAAS,OAAO;EAE9D;EAEA,aAAa,MAAM;EACnB,OAAO,MAAM;EAEZ,UAAA,MAAM;CACQ,CAAA;AAErB"}
1
+ {"version":3,"file":"ReactQueryStreamedHydration.cjs","names":["createHydrationStreamProvider","useQueryClient","React","environmentManager","defaultShouldDehydrateQuery","dehydrate"],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"sourcesContent":["'use client'\n\nimport {\n defaultShouldDehydrateQuery,\n dehydrate,\n environmentManager,\n hydrate,\n useQueryClient,\n} from '@tanstack/react-query'\nimport * as React from 'react'\nimport { createHydrationStreamProvider } from './HydrationStreamProvider'\nimport type { HydrationStreamProviderProps } from './HydrationStreamProvider'\nimport type {\n DehydrateOptions,\n DehydratedState,\n HydrateOptions,\n QueryClient,\n} from '@tanstack/react-query'\n\nconst stream = createHydrationStreamProvider<DehydratedState>()\n\n/**\n * This component is responsible for:\n * - dehydrating the query client on the server.\n * - hydrating the query client in the browser.\n * @param props - The `children` to render, an optional custom `queryClient`, the `nonce` for the\n * inline script, the hydrate and dehydrate `options`, and the data `transformer`.\n * @returns The `children`, wrapped in the hydration stream provider.\n */\nexport function ReactQueryStreamedHydration(props: {\n children: React.ReactNode\n queryClient?: QueryClient\n nonce?: string\n options?: {\n hydrate?: HydrateOptions\n dehydrate?: DehydrateOptions\n }\n transformer?: HydrationStreamProviderProps<DehydratedState>['transformer']\n}) {\n const queryClient = useQueryClient(props.queryClient)\n\n /**\n * We need to track which queries were added/updated during the render\n */\n const [trackedKeys] = React.useState(() => new Set<string>())\n\n // <server only>\n if (environmentManager.isServer()) {\n // Do we need to care about unsubscribing? I don't think so to be honest\n queryClient.getQueryCache().subscribe((event) => {\n switch (event.type) {\n case 'added':\n case 'updated':\n // console.log('tracking', event.query.queryHash, 'b/c of a', event.type)\n trackedKeys.add(event.query.queryHash)\n }\n })\n }\n // </server only>\n\n return (\n <stream.Provider\n // Happens on server:\n onFlush={() => {\n /**\n * Dehydrated state of the client where we only include the queries that were added/updated since the last flush\n */\n const shouldDehydrate =\n props.options?.dehydrate?.shouldDehydrateQuery ??\n defaultShouldDehydrateQuery\n\n const dehydratedState = dehydrate(queryClient, {\n ...props.options?.dehydrate,\n shouldDehydrateQuery(query) {\n return trackedKeys.has(query.queryHash) && shouldDehydrate(query)\n },\n })\n trackedKeys.clear()\n\n if (!dehydratedState.queries.length) {\n return []\n }\n\n return [dehydratedState]\n }}\n // Happens in browser:\n onEntries={(entries) => {\n for (const hydratedState of entries) {\n hydrate(queryClient, hydratedState, props.options?.hydrate)\n }\n }}\n // Handle BigInts etc using superjson\n transformer={props.transformer}\n nonce={props.nonce}\n >\n {props.children}\n </stream.Provider>\n )\n}\n"],"mappings":";;;;;;;;;AAmBA,MAAM,SAASA,gCAAAA,8BAA+C;;;;;;;;;AAU9D,SAAgB,4BAA4B,OASzC;CACD,MAAM,eAAA,GAAcC,sBAAAA,eAAAA,CAAe,MAAM,WAAW;;;;CAKpD,MAAM,CAAC,eAAeC,MAAM,+BAAe,IAAI,IAAY,CAAC;CAG5D,IAAIC,sBAAAA,mBAAmB,SAAS,GAE9B,YAAY,cAAc,CAAC,CAAC,WAAW,UAAU;EAC/C,QAAQ,MAAM,MAAd;GACE,KAAK;GACL,KAAK,WAEH,YAAY,IAAI,MAAM,MAAM,SAAS;EACzC;CACF,CAAC;CAIH,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAO,UAAR;EAEE,eAAe;;;;GAIb,MAAM,kBACJ,MAAM,SAAS,WAAW,wBAC1BC,sBAAAA;GAEF,MAAM,mBAAA,GAAkBC,sBAAAA,UAAAA,CAAU,aAAa;IAC7C,GAAG,MAAM,SAAS;IAClB,qBAAqB,OAAO;KAC1B,OAAO,YAAY,IAAI,MAAM,SAAS,KAAK,gBAAgB,KAAK;IAClE;GACF,CAAC;GACD,YAAY,MAAM;GAElB,IAAI,CAAC,gBAAgB,QAAQ,QAC3B,OAAO,CAAC;GAGV,OAAO,CAAC,eAAe;EACzB;EAEA,YAAY,YAAY;GACtB,KAAK,MAAM,iBAAiB,SAC1B,CAAA,GAAA,sBAAA,QAAA,CAAQ,aAAa,eAAe,MAAM,SAAS,OAAO;EAE9D;EAEA,aAAa,MAAM;EACnB,OAAO,MAAM;EAEZ,UAAA,MAAM;CACQ,CAAA;AAErB"}
@@ -1,11 +1,14 @@
1
- import { t as HydrationStreamProviderProps } from "./HydrationStreamProvider-D_lqnUNo.cjs";
1
+ import { t as HydrationStreamProviderProps } from "./HydrationStreamProvider-DrbxOdk5.cjs";
2
2
  import * as React from "react";
3
3
  import { DehydrateOptions, DehydratedState, HydrateOptions, QueryClient } from "@tanstack/react-query";
4
4
  //#region src/ReactQueryStreamedHydration.d.ts
5
5
  /**
6
6
  * This component is responsible for:
7
- * - hydrating the query client on the server
8
- * - dehydrating the query client on the server
7
+ * - dehydrating the query client on the server.
8
+ * - hydrating the query client in the browser.
9
+ * @param props - The `children` to render, an optional custom `queryClient`, the `nonce` for the
10
+ * inline script, the hydrate and dehydrate `options`, and the data `transformer`.
11
+ * @returns The `children`, wrapped in the hydration stream provider.
9
12
  */
10
13
  export declare function ReactQueryStreamedHydration(props: {
11
14
  children: React.ReactNode;
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"ReactQueryStreamedHydration.d.cts","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"mappings":";;;;;;;;;;;;wBA6BgB,4BAA4B;EAC1C,UAAU,MAAM;EAChB,cAAc;EACd;EACA;IACE,UAAU;IACV,YAAY;;EAEd,cAAc,6BAA6B;gCAC5C,IAAA"}
@@ -1,11 +1,14 @@
1
- import { t as HydrationStreamProviderProps } from "./HydrationStreamProvider-D_lqnUNo.js";
1
+ import { t as HydrationStreamProviderProps } from "./HydrationStreamProvider-DrbxOdk5.js";
2
2
  import { DehydrateOptions, DehydratedState, HydrateOptions, QueryClient } from "@tanstack/react-query";
3
3
  import * as React from "react";
4
4
  //#region src/ReactQueryStreamedHydration.d.ts
5
5
  /**
6
6
  * This component is responsible for:
7
- * - hydrating the query client on the server
8
- * - dehydrating the query client on the server
7
+ * - dehydrating the query client on the server.
8
+ * - hydrating the query client in the browser.
9
+ * @param props - The `children` to render, an optional custom `queryClient`, the `nonce` for the
10
+ * inline script, the hydrate and dehydrate `options`, and the data `transformer`.
11
+ * @returns The `children`, wrapped in the hydration stream provider.
9
12
  */
10
13
  export declare function ReactQueryStreamedHydration(props: {
11
14
  children: React.ReactNode;
@@ -1 +1 @@
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
+ {"version":3,"file":"ReactQueryStreamedHydration.d.ts","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"mappings":";;;;;;;;;;;;wBA6BgB,4BAA4B;EAC1C,UAAU,MAAM;EAChB,cAAc;EACd;EACA;IACE,UAAU;IACV,YAAY;;EAEd,cAAc,6BAA6B;gCAC5C,IAAA"}
@@ -7,8 +7,11 @@ import { jsx } from "react/jsx-runtime";
7
7
  const stream = createHydrationStreamProvider();
8
8
  /**
9
9
  * This component is responsible for:
10
- * - hydrating the query client on the server
11
- * - dehydrating the query client on the server
10
+ * - dehydrating the query client on the server.
11
+ * - hydrating the query client in the browser.
12
+ * @param props - The `children` to render, an optional custom `queryClient`, the `nonce` for the
13
+ * inline script, the hydrate and dehydrate `options`, and the data `transformer`.
14
+ * @returns The `children`, wrapped in the hydration stream provider.
12
15
  */
13
16
  function ReactQueryStreamedHydration(props) {
14
17
  const queryClient = useQueryClient(props.queryClient);
@@ -1 +1 @@
1
- {"version":3,"file":"ReactQueryStreamedHydration.js","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"sourcesContent":["'use client'\n\nimport {\n defaultShouldDehydrateQuery,\n dehydrate,\n environmentManager,\n hydrate,\n useQueryClient,\n} from '@tanstack/react-query'\nimport * as React from 'react'\nimport { createHydrationStreamProvider } from './HydrationStreamProvider'\nimport type { HydrationStreamProviderProps } from './HydrationStreamProvider'\nimport type {\n DehydrateOptions,\n DehydratedState,\n HydrateOptions,\n QueryClient,\n} from '@tanstack/react-query'\n\nconst stream = createHydrationStreamProvider<DehydratedState>()\n\n/**\n * This component is responsible for:\n * - hydrating the query client on the server\n * - dehydrating the query client on the server\n */\nexport function ReactQueryStreamedHydration(props: {\n children: React.ReactNode\n queryClient?: QueryClient\n nonce?: string\n options?: {\n hydrate?: HydrateOptions\n dehydrate?: DehydrateOptions\n }\n transformer?: HydrationStreamProviderProps<DehydratedState>['transformer']\n}) {\n const queryClient = useQueryClient(props.queryClient)\n\n /**\n * We need to track which queries were added/updated during the render\n */\n const [trackedKeys] = React.useState(() => new Set<string>())\n\n // <server only>\n if (environmentManager.isServer()) {\n // Do we need to care about unsubscribing? I don't think so to be honest\n queryClient.getQueryCache().subscribe((event) => {\n switch (event.type) {\n case 'added':\n case 'updated':\n // console.log('tracking', event.query.queryHash, 'b/c of a', event.type)\n trackedKeys.add(event.query.queryHash)\n }\n })\n }\n // </server only>\n\n return (\n <stream.Provider\n // Happens on server:\n onFlush={() => {\n /**\n * Dehydrated state of the client where we only include the queries that were added/updated since the last flush\n */\n const shouldDehydrate =\n props.options?.dehydrate?.shouldDehydrateQuery ??\n defaultShouldDehydrateQuery\n\n const dehydratedState = dehydrate(queryClient, {\n ...props.options?.dehydrate,\n shouldDehydrateQuery(query) {\n return trackedKeys.has(query.queryHash) && shouldDehydrate(query)\n },\n })\n trackedKeys.clear()\n\n if (!dehydratedState.queries.length) {\n return []\n }\n\n return [dehydratedState]\n }}\n // Happens in browser:\n onEntries={(entries) => {\n for (const hydratedState of entries) {\n hydrate(queryClient, hydratedState, props.options?.hydrate)\n }\n }}\n // Handle BigInts etc using superjson\n transformer={props.transformer}\n nonce={props.nonce}\n >\n {props.children}\n </stream.Provider>\n )\n}\n"],"mappings":";;;;;;AAmBA,MAAM,SAAS,8BAA+C;;;;;;AAO9D,SAAgB,4BAA4B,OASzC;CACD,MAAM,cAAc,eAAe,MAAM,WAAW;;;;CAKpD,MAAM,CAAC,eAAe,MAAM,+BAAe,IAAI,IAAY,CAAC;CAG5D,IAAI,mBAAmB,SAAS,GAE9B,YAAY,cAAc,CAAC,CAAC,WAAW,UAAU;EAC/C,QAAQ,MAAM,MAAd;GACE,KAAK;GACL,KAAK,WAEH,YAAY,IAAI,MAAM,MAAM,SAAS;EACzC;CACF,CAAC;CAIH,OACE,oBAAC,OAAO,UAAR;EAEE,eAAe;;;;GAIb,MAAM,kBACJ,MAAM,SAAS,WAAW,wBAC1B;GAEF,MAAM,kBAAkB,UAAU,aAAa;IAC7C,GAAG,MAAM,SAAS;IAClB,qBAAqB,OAAO;KAC1B,OAAO,YAAY,IAAI,MAAM,SAAS,KAAK,gBAAgB,KAAK;IAClE;GACF,CAAC;GACD,YAAY,MAAM;GAElB,IAAI,CAAC,gBAAgB,QAAQ,QAC3B,OAAO,CAAC;GAGV,OAAO,CAAC,eAAe;EACzB;EAEA,YAAY,YAAY;GACtB,KAAK,MAAM,iBAAiB,SAC1B,QAAQ,aAAa,eAAe,MAAM,SAAS,OAAO;EAE9D;EAEA,aAAa,MAAM;EACnB,OAAO,MAAM;EAEZ,UAAA,MAAM;CACQ,CAAA;AAErB"}
1
+ {"version":3,"file":"ReactQueryStreamedHydration.js","names":[],"sources":["../../src/ReactQueryStreamedHydration.tsx"],"sourcesContent":["'use client'\n\nimport {\n defaultShouldDehydrateQuery,\n dehydrate,\n environmentManager,\n hydrate,\n useQueryClient,\n} from '@tanstack/react-query'\nimport * as React from 'react'\nimport { createHydrationStreamProvider } from './HydrationStreamProvider'\nimport type { HydrationStreamProviderProps } from './HydrationStreamProvider'\nimport type {\n DehydrateOptions,\n DehydratedState,\n HydrateOptions,\n QueryClient,\n} from '@tanstack/react-query'\n\nconst stream = createHydrationStreamProvider<DehydratedState>()\n\n/**\n * This component is responsible for:\n * - dehydrating the query client on the server.\n * - hydrating the query client in the browser.\n * @param props - The `children` to render, an optional custom `queryClient`, the `nonce` for the\n * inline script, the hydrate and dehydrate `options`, and the data `transformer`.\n * @returns The `children`, wrapped in the hydration stream provider.\n */\nexport function ReactQueryStreamedHydration(props: {\n children: React.ReactNode\n queryClient?: QueryClient\n nonce?: string\n options?: {\n hydrate?: HydrateOptions\n dehydrate?: DehydrateOptions\n }\n transformer?: HydrationStreamProviderProps<DehydratedState>['transformer']\n}) {\n const queryClient = useQueryClient(props.queryClient)\n\n /**\n * We need to track which queries were added/updated during the render\n */\n const [trackedKeys] = React.useState(() => new Set<string>())\n\n // <server only>\n if (environmentManager.isServer()) {\n // Do we need to care about unsubscribing? I don't think so to be honest\n queryClient.getQueryCache().subscribe((event) => {\n switch (event.type) {\n case 'added':\n case 'updated':\n // console.log('tracking', event.query.queryHash, 'b/c of a', event.type)\n trackedKeys.add(event.query.queryHash)\n }\n })\n }\n // </server only>\n\n return (\n <stream.Provider\n // Happens on server:\n onFlush={() => {\n /**\n * Dehydrated state of the client where we only include the queries that were added/updated since the last flush\n */\n const shouldDehydrate =\n props.options?.dehydrate?.shouldDehydrateQuery ??\n defaultShouldDehydrateQuery\n\n const dehydratedState = dehydrate(queryClient, {\n ...props.options?.dehydrate,\n shouldDehydrateQuery(query) {\n return trackedKeys.has(query.queryHash) && shouldDehydrate(query)\n },\n })\n trackedKeys.clear()\n\n if (!dehydratedState.queries.length) {\n return []\n }\n\n return [dehydratedState]\n }}\n // Happens in browser:\n onEntries={(entries) => {\n for (const hydratedState of entries) {\n hydrate(queryClient, hydratedState, props.options?.hydrate)\n }\n }}\n // Handle BigInts etc using superjson\n transformer={props.transformer}\n nonce={props.nonce}\n >\n {props.children}\n </stream.Provider>\n )\n}\n"],"mappings":";;;;;;AAmBA,MAAM,SAAS,8BAA+C;;;;;;;;;AAU9D,SAAgB,4BAA4B,OASzC;CACD,MAAM,cAAc,eAAe,MAAM,WAAW;;;;CAKpD,MAAM,CAAC,eAAe,MAAM,+BAAe,IAAI,IAAY,CAAC;CAG5D,IAAI,mBAAmB,SAAS,GAE9B,YAAY,cAAc,CAAC,CAAC,WAAW,UAAU;EAC/C,QAAQ,MAAM,MAAd;GACE,KAAK;GACL,KAAK,WAEH,YAAY,IAAI,MAAM,MAAM,SAAS;EACzC;CACF,CAAC;CAIH,OACE,oBAAC,OAAO,UAAR;EAEE,eAAe;;;;GAIb,MAAM,kBACJ,MAAM,SAAS,WAAW,wBAC1B;GAEF,MAAM,kBAAkB,UAAU,aAAa;IAC7C,GAAG,MAAM,SAAS;IAClB,qBAAqB,OAAO;KAC1B,OAAO,YAAY,IAAI,MAAM,SAAS,KAAK,gBAAgB,KAAK;IAClE;GACF,CAAC;GACD,YAAY,MAAM;GAElB,IAAI,CAAC,gBAAgB,QAAQ,QAC3B,OAAO,CAAC;GAGV,OAAO,CAAC,eAAe;EACzB;EAEA,YAAY,YAAY;GACtB,KAAK,MAAM,iBAAiB,SAC1B,QAAQ,aAAa,eAAe,MAAM,SAAS,OAAO;EAE9D;EAEA,aAAa,MAAM;EACnB,OAAO,MAAM;EAEZ,UAAA,MAAM;CACQ,CAAA;AAErB"}
@@ -8,6 +8,11 @@ const ESCAPE_LOOKUP = {
8
8
  "\u2029": "\\u2029"
9
9
  };
10
10
  const ESCAPE_REGEX = /[&><\u2028\u2029]/g;
11
+ /**
12
+ * Escapes the characters of a JSON string that are unsafe to embed in an HTML `<script>` tag.
13
+ * @param str - The JSON string to escape.
14
+ * @returns The string with `&`, `<`, `>`, U+2028, and U+2029 replaced by `\uXXXX` escapes.
15
+ */
11
16
  function htmlEscapeJsonString(str) {
12
17
  return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]);
13
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"htmlescape.cjs","names":[],"sources":["../../src/htmlescape.ts"],"sourcesContent":["// --------------------------------------------------------------------------------\n//\n// copied from\n// https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/src/server/htmlescape.ts\n// License: https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/license.md\n//\n// --------------------------------------------------------------------------------\n\n// This utility is based on https://github.com/zertosh/htmlescape\n// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE\n\nconst ESCAPE_LOOKUP: Record<string, string> = {\n '&': '\\\\u0026',\n '>': '\\\\u003e',\n '<': '\\\\u003c',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029',\n}\n\nexport const ESCAPE_REGEX = /[&><\\u2028\\u2029]/g\n\nexport function htmlEscapeJsonString(str: string): string {\n return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]!)\n}\n"],"mappings":";;AAWA,MAAM,gBAAwC;CAC5C,KAAK;CACL,KAAK;CACL,KAAK;CACL,UAAU;CACV,UAAU;AACZ;AAEA,MAAa,eAAe;AAE5B,SAAgB,qBAAqB,KAAqB;CACxD,OAAO,IAAI,QAAQ,eAAe,UAAU,cAAc,MAAO;AACnE"}
1
+ {"version":3,"file":"htmlescape.cjs","names":[],"sources":["../../src/htmlescape.ts"],"sourcesContent":["// --------------------------------------------------------------------------------\n//\n// copied from\n// https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/src/server/htmlescape.ts\n// License: https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/license.md\n//\n// --------------------------------------------------------------------------------\n\n// This utility is based on https://github.com/zertosh/htmlescape\n// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE\n\nconst ESCAPE_LOOKUP: Record<string, string> = {\n '&': '\\\\u0026',\n '>': '\\\\u003e',\n '<': '\\\\u003c',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029',\n}\n\nexport const ESCAPE_REGEX = /[&><\\u2028\\u2029]/g\n\n/**\n * Escapes the characters of a JSON string that are unsafe to embed in an HTML `<script>` tag.\n * @param str - The JSON string to escape.\n * @returns The string with `&`, `<`, `>`, U+2028, and U+2029 replaced by `\\uXXXX` escapes.\n */\nexport function htmlEscapeJsonString(str: string): string {\n return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]!)\n}\n"],"mappings":";;AAWA,MAAM,gBAAwC;CAC5C,KAAK;CACL,KAAK;CACL,KAAK;CACL,UAAU;CACV,UAAU;AACZ;AAEA,MAAa,eAAe;;;;;;AAO5B,SAAgB,qBAAqB,KAAqB;CACxD,OAAO,IAAI,QAAQ,eAAe,UAAU,cAAc,MAAO;AACnE"}
@@ -1,5 +1,10 @@
1
1
  //#region src/htmlescape.d.ts
2
2
  export declare const ESCAPE_REGEX: RegExp;
3
+ /**
4
+ * Escapes the characters of a JSON string that are unsafe to embed in an HTML `<script>` tag.
5
+ * @param str - The JSON string to escape.
6
+ * @returns The string with `&`, `<`, `>`, U+2028, and U+2029 replaced by `\uXXXX` escapes.
7
+ */
3
8
  export declare function htmlEscapeJsonString(str: string): string;
4
9
  //#endregion
5
10
  //# sourceMappingURL=htmlescape.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"htmlescape.d.cts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";qBAmBa,cAAY;wBAET,qBAAqB"}
1
+ {"version":3,"file":"htmlescape.d.cts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";qBAmBa,cAAY;;;;;;wBAOT,qBAAqB"}
@@ -1,5 +1,10 @@
1
1
  //#region src/htmlescape.d.ts
2
2
  export declare const ESCAPE_REGEX: RegExp;
3
+ /**
4
+ * Escapes the characters of a JSON string that are unsafe to embed in an HTML `<script>` tag.
5
+ * @param str - The JSON string to escape.
6
+ * @returns The string with `&`, `<`, `>`, U+2028, and U+2029 replaced by `\uXXXX` escapes.
7
+ */
3
8
  export declare function htmlEscapeJsonString(str: string): string;
4
9
  //#endregion
5
10
  //# sourceMappingURL=htmlescape.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"htmlescape.d.ts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";qBAmBa,cAAY;wBAET,qBAAqB"}
1
+ {"version":3,"file":"htmlescape.d.ts","names":[],"sources":["../../src/htmlescape.ts"],"mappings":";qBAmBa,cAAY;;;;;;wBAOT,qBAAqB"}
@@ -7,6 +7,11 @@ const ESCAPE_LOOKUP = {
7
7
  "\u2029": "\\u2029"
8
8
  };
9
9
  const ESCAPE_REGEX = /[&><\u2028\u2029]/g;
10
+ /**
11
+ * Escapes the characters of a JSON string that are unsafe to embed in an HTML `<script>` tag.
12
+ * @param str - The JSON string to escape.
13
+ * @returns The string with `&`, `<`, `>`, U+2028, and U+2029 replaced by `\uXXXX` escapes.
14
+ */
10
15
  function htmlEscapeJsonString(str) {
11
16
  return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]);
12
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"htmlescape.js","names":[],"sources":["../../src/htmlescape.ts"],"sourcesContent":["// --------------------------------------------------------------------------------\n//\n// copied from\n// https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/src/server/htmlescape.ts\n// License: https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/license.md\n//\n// --------------------------------------------------------------------------------\n\n// This utility is based on https://github.com/zertosh/htmlescape\n// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE\n\nconst ESCAPE_LOOKUP: Record<string, string> = {\n '&': '\\\\u0026',\n '>': '\\\\u003e',\n '<': '\\\\u003c',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029',\n}\n\nexport const ESCAPE_REGEX = /[&><\\u2028\\u2029]/g\n\nexport function htmlEscapeJsonString(str: string): string {\n return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]!)\n}\n"],"mappings":";AAWA,MAAM,gBAAwC;CAC5C,KAAK;CACL,KAAK;CACL,KAAK;CACL,UAAU;CACV,UAAU;AACZ;AAEA,MAAa,eAAe;AAE5B,SAAgB,qBAAqB,KAAqB;CACxD,OAAO,IAAI,QAAQ,eAAe,UAAU,cAAc,MAAO;AACnE"}
1
+ {"version":3,"file":"htmlescape.js","names":[],"sources":["../../src/htmlescape.ts"],"sourcesContent":["// --------------------------------------------------------------------------------\n//\n// copied from\n// https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/src/server/htmlescape.ts\n// License: https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/license.md\n//\n// --------------------------------------------------------------------------------\n\n// This utility is based on https://github.com/zertosh/htmlescape\n// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE\n\nconst ESCAPE_LOOKUP: Record<string, string> = {\n '&': '\\\\u0026',\n '>': '\\\\u003e',\n '<': '\\\\u003c',\n '\\u2028': '\\\\u2028',\n '\\u2029': '\\\\u2029',\n}\n\nexport const ESCAPE_REGEX = /[&><\\u2028\\u2029]/g\n\n/**\n * Escapes the characters of a JSON string that are unsafe to embed in an HTML `<script>` tag.\n * @param str - The JSON string to escape.\n * @returns The string with `&`, `<`, `>`, U+2028, and U+2029 replaced by `\\uXXXX` escapes.\n */\nexport function htmlEscapeJsonString(str: string): string {\n return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]!)\n}\n"],"mappings":";AAWA,MAAM,gBAAwC;CAC5C,KAAK;CACL,KAAK;CACL,KAAK;CACL,UAAU;CACV,UAAU;AACZ;AAEA,MAAa,eAAe;;;;;;AAO5B,SAAgB,qBAAqB,KAAqB;CACxD,OAAO,IAAI,QAAQ,eAAe,UAAU,cAAc,MAAO;AACnE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-query-next-experimental",
3
- "version": "5.104.1",
3
+ "version": "5.104.2",
4
4
  "description": "Hydration utils for React Query in the NextJs app directory",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -39,8 +39,8 @@
39
39
  "!src/__tests__"
40
40
  ],
41
41
  "devDependencies": {
42
- "@eslint-react/eslint-plugin": "^5.21.0",
43
- "@tanstack/react-query": "5.104.1",
42
+ "@eslint-react/eslint-plugin": "^5.23.3",
43
+ "@tanstack/react-query": "5.104.2",
44
44
  "@types/react": "^19.2.7",
45
45
  "@vitejs/plugin-react": "^6.1.1",
46
46
  "eslint-plugin-react-hooks": "^7.1.1",
@@ -49,21 +49,21 @@
49
49
  "typescript": "6.0.3"
50
50
  },
51
51
  "peerDependencies": {
52
- "@tanstack/react-query": "^5.104.1",
52
+ "@tanstack/react-query": "^5.104.2",
53
53
  "next": "^13 || ^14 || ^15 || ^16",
54
54
  "react": "^18 || ^19"
55
55
  },
56
56
  "scripts": {
57
57
  "clean": "premove ./build ./coverage ./dist-ts ./.cache/test-types",
58
58
  "compile": "tsc --project tsconfig.json",
59
- "test:eslint": "eslint --concurrency=auto ./src",
59
+ "test:oxlint": "oxlint ./src",
60
60
  "test:types": "npm-run-all --serial test:types:*",
61
- "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js --project tsconfig.legacy.json --outDir .cache/test-types/ts56 --tsBuildInfoFile .cache/test-types/ts56.tsbuildinfo",
62
61
  "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js --project tsconfig.legacy.json --outDir .cache/test-types/ts57 --tsBuildInfoFile .cache/test-types/ts57.tsbuildinfo",
63
62
  "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",
64
63
  "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",
65
64
  "test:types:tscurrent": "tsc --project tsconfig.json --outDir .cache/test-types/tscurrent --tsBuildInfoFile .cache/test-types/tscurrent.tsbuildinfo",
66
65
  "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",
66
+ "test:types:ts71": "node ../../node_modules/typescript71/lib/tsc.js --project tsconfig.legacy.json --outDir .cache/test-types/ts71 --tsBuildInfoFile .cache/test-types/ts71.tsbuildinfo",
67
67
  "test:build": "publint --strict && attw --pack",
68
68
  "build": "tsdown --tsconfig tsconfig.prod.json"
69
69
  }
@@ -33,7 +33,13 @@ interface HydrationStreamContext<TShape> {
33
33
  }
34
34
  }
35
35
 
36
+ /**
37
+ * The props of the `Provider` returned by `createHydrationStreamProvider`.
38
+ */
36
39
  export interface HydrationStreamProviderProps<TShape> {
40
+ /**
41
+ * The children to render inside the stream provider.
42
+ */
37
43
  children: React.ReactNode
38
44
  /**
39
45
  * Optional transformer to serialize/deserialize the data
@@ -56,19 +62,27 @@ export interface HydrationStreamProviderProps<TShape> {
56
62
  nonce?: string
57
63
  }
58
64
 
65
+ /**
66
+ * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the
67
+ * client while the page streams in, and the context it shares the stream through.
68
+ * @returns The `Provider` component and its `context`.
69
+ */
59
70
  export function createHydrationStreamProvider<TShape>() {
60
71
  const StreamContext = React.createContext<HydrationStreamContext<TShape>>(
61
72
  null as any,
62
73
  )
63
74
  /**
64
-
65
- * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes
66
- * - This means that we might have some new entries in the cache that needs to be flushed
67
- * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`
75
+ * 1. (Happens on server): the callback registered with `useServerInsertedHTML()` is called **on the server** whenever
76
+ * Next.js inserts HTML into the streamed response.
77
+ * - This means that we might have some new entries in the cache that needs to be flushed.
78
+ * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`.
68
79
  * 2. (Happens in browser) In `useEffect()`:
69
- * - 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
70
- * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received
71
- **/
80
+ * - 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.
81
+ * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received.
82
+ * @param props - The `children` to render, the `onEntries`/`onFlush` callbacks, and the optional
83
+ * `transformer` and `nonce`.
84
+ * @returns The `children`, wrapped in the stream context provider.
85
+ */
72
86
  function UseClientHydrationStreamProvider(props: {
73
87
  children: React.ReactNode
74
88
  /**
@@ -21,8 +21,11 @@ const stream = createHydrationStreamProvider<DehydratedState>()
21
21
 
22
22
  /**
23
23
  * This component is responsible for:
24
- * - hydrating the query client on the server
25
- * - dehydrating the query client on the server
24
+ * - dehydrating the query client on the server.
25
+ * - hydrating the query client in the browser.
26
+ * @param props - The `children` to render, an optional custom `queryClient`, the `nonce` for the
27
+ * inline script, the hydrate and dehydrate `options`, and the data `transformer`.
28
+ * @returns The `children`, wrapped in the hydration stream provider.
26
29
  */
27
30
  export function ReactQueryStreamedHydration(props: {
28
31
  children: React.ReactNode
package/src/htmlescape.ts CHANGED
@@ -19,6 +19,11 @@ const ESCAPE_LOOKUP: Record<string, string> = {
19
19
 
20
20
  export const ESCAPE_REGEX = /[&><\u2028\u2029]/g
21
21
 
22
+ /**
23
+ * Escapes the characters of a JSON string that are unsafe to embed in an HTML `<script>` tag.
24
+ * @param str - The JSON string to escape.
25
+ * @returns The string with `&`, `<`, `>`, U+2028, and U+2029 replaced by `\uXXXX` escapes.
26
+ */
22
27
  export function htmlEscapeJsonString(str: string): string {
23
28
  return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]!)
24
29
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"HydrationStreamProvider-D_lqnUNo.d.cts","names":[],"sources":["../../src/HydrationStreamProvider.tsx"],"mappings":";;UASU;EACR,YAAY;EACZ,cAAc;;UAYN,uBAAuB;EAC/B;EACA;;;;;;IAME,UAAU,OAAO,MAAM;;;UAIV,6BAA6B;EAC5C,UAAU,MAAM;;;;;EAKhB,cAAc;;;;;EAKd,YAAY,SAAS,MAAM;;;;;EAK3B,gBAAgB,MAAM;;;;EAItB;;iBAGc,8BAA8B;EAaK,WAAA;IAC/C,UAAU,MAAM;;;;;IAKhB,cAAc;;;;;IAKd,YAAY,SAAS,MAAM;;;;;IAK3B,gBAAgB,MAAM;;;;IAItB;oCACD,IAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"HydrationStreamProvider-D_lqnUNo.d.ts","names":[],"sources":["../../src/HydrationStreamProvider.tsx"],"mappings":";;UASU;EACR,YAAY;EACZ,cAAc;;UAYN,uBAAuB;EAC/B;EACA;;;;;;IAME,UAAU,OAAO,MAAM;;;UAIV,6BAA6B;EAC5C,UAAU,MAAM;;;;;EAKhB,cAAc;;;;;EAKd,YAAY,SAAS,MAAM;;;;;EAK3B,gBAAgB,MAAM;;;;EAItB;;iBAGc,8BAA8B;EAaK,WAAA;IAC/C,UAAU,MAAM;;;;;IAKhB,cAAc;;;;;IAKd,YAAY,SAAS,MAAM;;;;;IAK3B,gBAAgB,MAAM;;;;IAItB;oCACD,IAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"HydrationStreamProvider-D_lqnUNo.d.cts","names":[],"sources":["../../src/HydrationStreamProvider.tsx"],"mappings":";;UASU;EACR,YAAY;EACZ,cAAc;;UAYN,uBAAuB;EAC/B;EACA;;;;;;IAME,UAAU,OAAO,MAAM;;;UAIV,6BAA6B;EAC5C,UAAU,MAAM;;;;;EAKhB,cAAc;;;;;EAKd,YAAY,SAAS,MAAM;;;;;EAK3B,gBAAgB,MAAM;;;;EAItB;;iBAGc,8BAA8B;EAaK,WAAA;IAC/C,UAAU,MAAM;;;;;IAKhB,cAAc;;;;;IAKd,YAAY,SAAS,MAAM;;;;;IAK3B,gBAAgB,MAAM;;;;IAItB;oCACD,IAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"HydrationStreamProvider-D_lqnUNo.d.ts","names":[],"sources":["../../src/HydrationStreamProvider.tsx"],"mappings":";;UASU;EACR,YAAY;EACZ,cAAc;;UAYN,uBAAuB;EAC/B;EACA;;;;;;IAME,UAAU,OAAO,MAAM;;;UAIV,6BAA6B;EAC5C,UAAU,MAAM;;;;;EAKhB,cAAc;;;;;EAKd,YAAY,SAAS,MAAM;;;;;EAK3B,gBAAgB,MAAM;;;;EAItB;;iBAGc,8BAA8B;EAaK,WAAA;IAC/C,UAAU,MAAM;;;;;IAKhB,cAAc;;;;;IAKd,YAAY,SAAS,MAAM;;;;;IAK3B,gBAAgB,MAAM;;;;IAItB;oCACD,IAAA"}