@tanstack/react-query-next-experimental 5.101.4 → 5.102.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/build/legacy/HydrationStreamProvider-D_lqnUNo.d.cts +67 -0
  2. package/build/legacy/HydrationStreamProvider-D_lqnUNo.d.cts.map +1 -0
  3. package/build/legacy/HydrationStreamProvider-D_lqnUNo.d.ts +67 -0
  4. package/build/legacy/HydrationStreamProvider-D_lqnUNo.d.ts.map +1 -0
  5. package/build/legacy/HydrationStreamProvider.cjs +73 -114
  6. package/build/legacy/HydrationStreamProvider.cjs.map +1 -1
  7. package/build/legacy/HydrationStreamProvider.d.cts +2 -2
  8. package/build/legacy/HydrationStreamProvider.d.ts +2 -2
  9. package/build/legacy/HydrationStreamProvider.js +67 -77
  10. package/build/legacy/HydrationStreamProvider.js.map +1 -1
  11. package/build/legacy/ReactQueryStreamedHydration.cjs +55 -84
  12. package/build/legacy/ReactQueryStreamedHydration.cjs.map +1 -1
  13. package/build/legacy/ReactQueryStreamedHydration.d.cts +22 -1
  14. package/build/legacy/ReactQueryStreamedHydration.d.cts.map +1 -0
  15. package/build/legacy/ReactQueryStreamedHydration.d.ts +22 -1
  16. package/build/legacy/ReactQueryStreamedHydration.d.ts.map +1 -0
  17. package/build/legacy/ReactQueryStreamedHydration.js +50 -54
  18. package/build/legacy/ReactQueryStreamedHydration.js.map +1 -1
  19. package/build/legacy/htmlescape.cjs +14 -39
  20. package/build/legacy/htmlescape.cjs.map +1 -1
  21. package/build/legacy/htmlescape.d.cts +6 -2
  22. package/build/legacy/htmlescape.d.cts.map +1 -0
  23. package/build/legacy/htmlescape.d.ts +6 -2
  24. package/build/legacy/htmlescape.d.ts.map +1 -0
  25. package/build/legacy/htmlescape.js +12 -13
  26. package/build/legacy/htmlescape.js.map +1 -1
  27. package/build/legacy/index.cjs +3 -31
  28. package/build/legacy/index.d.cts +2 -1
  29. package/build/legacy/index.d.ts +2 -1
  30. package/build/legacy/index.js +1 -5
  31. package/build/legacy/rolldown-runtime-VH7oDXx4.cjs +28 -0
  32. package/build/modern/HydrationStreamProvider-D_lqnUNo.d.cts +67 -0
  33. package/build/modern/HydrationStreamProvider-D_lqnUNo.d.cts.map +1 -0
  34. package/build/modern/HydrationStreamProvider-D_lqnUNo.d.ts +67 -0
  35. package/build/modern/HydrationStreamProvider-D_lqnUNo.d.ts.map +1 -0
  36. package/build/modern/HydrationStreamProvider.cjs +71 -112
  37. package/build/modern/HydrationStreamProvider.cjs.map +1 -1
  38. package/build/modern/HydrationStreamProvider.d.cts +2 -2
  39. package/build/modern/HydrationStreamProvider.d.ts +2 -2
  40. package/build/modern/HydrationStreamProvider.js +65 -75
  41. package/build/modern/HydrationStreamProvider.js.map +1 -1
  42. package/build/modern/ReactQueryStreamedHydration.cjs +51 -82
  43. package/build/modern/ReactQueryStreamedHydration.cjs.map +1 -1
  44. package/build/modern/ReactQueryStreamedHydration.d.cts +22 -1
  45. package/build/modern/ReactQueryStreamedHydration.d.cts.map +1 -0
  46. package/build/modern/ReactQueryStreamedHydration.d.ts +22 -1
  47. package/build/modern/ReactQueryStreamedHydration.d.ts.map +1 -0
  48. package/build/modern/ReactQueryStreamedHydration.js +46 -52
  49. package/build/modern/ReactQueryStreamedHydration.js.map +1 -1
  50. package/build/modern/htmlescape.cjs +14 -39
  51. package/build/modern/htmlescape.cjs.map +1 -1
  52. package/build/modern/htmlescape.d.cts +6 -2
  53. package/build/modern/htmlescape.d.cts.map +1 -0
  54. package/build/modern/htmlescape.d.ts +6 -2
  55. package/build/modern/htmlescape.d.ts.map +1 -0
  56. package/build/modern/htmlescape.js +12 -13
  57. package/build/modern/htmlescape.js.map +1 -1
  58. package/build/modern/index.cjs +3 -31
  59. package/build/modern/index.d.cts +2 -1
  60. package/build/modern/index.d.ts +2 -1
  61. package/build/modern/index.js +1 -5
  62. package/build/modern/rolldown-runtime-VH7oDXx4.cjs +28 -0
  63. package/package.json +5 -7
  64. package/build/legacy/_tsup-dts-rollup.d.cts +0 -96
  65. package/build/legacy/_tsup-dts-rollup.d.ts +0 -96
  66. package/build/legacy/index.cjs.map +0 -1
  67. package/build/legacy/index.js.map +0 -1
  68. package/build/modern/_tsup-dts-rollup.d.cts +0 -96
  69. package/build/modern/_tsup-dts-rollup.d.ts +0 -96
  70. package/build/modern/index.cjs.map +0 -1
  71. package/build/modern/index.js.map +0 -1
@@ -0,0 +1,67 @@
1
+ import * as React from "react";
2
+ //#region src/HydrationStreamProvider.d.ts
3
+ interface DataTransformer {
4
+ serialize: (object: any) => any;
5
+ deserialize: (object: any) => any;
6
+ }
7
+ interface HydrationStreamContext<TShape> {
8
+ id: string;
9
+ stream: {
10
+ /**
11
+ * **Server method**
12
+ * Push a new entry to the stream
13
+ * Will be ignored on the client
14
+ */
15
+ push: (...shape: Array<TShape>) => void;
16
+ };
17
+ }
18
+ interface HydrationStreamProviderProps<TShape> {
19
+ children: React.ReactNode;
20
+ /**
21
+ * Optional transformer to serialize/deserialize the data
22
+ * Example devalue, superjson et al
23
+ */
24
+ transformer?: DataTransformer;
25
+ /**
26
+ * **Client method**
27
+ * Called in the browser when new entries are received
28
+ */
29
+ onEntries: (entries: Array<TShape>) => void;
30
+ /**
31
+ * **Server method**
32
+ * onFlush is called on the server when the cache is flushed
33
+ */
34
+ onFlush?: () => Array<TShape>;
35
+ /**
36
+ * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced
37
+ */
38
+ nonce?: string;
39
+ }
40
+ declare function createHydrationStreamProvider<TShape>(): {
41
+ Provider: (props: {
42
+ children: React.ReactNode;
43
+ /**
44
+ * Optional transformer to serialize/deserialize the data
45
+ * Example devalue, superjson et al
46
+ */
47
+ transformer?: DataTransformer;
48
+ /**
49
+ * **Client method**
50
+ * Called in the browser when new entries are received
51
+ */
52
+ onEntries: (entries: Array<TShape>) => void;
53
+ /**
54
+ * **Server method**
55
+ * onFlush is called on the server when the cache is flushed
56
+ */
57
+ onFlush?: () => Array<TShape>;
58
+ /**
59
+ * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced
60
+ */
61
+ nonce?: string;
62
+ }) => import("react/jsx-runtime").JSX.Element;
63
+ context: React.Context<HydrationStreamContext<TShape>>;
64
+ };
65
+ //#endregion
66
+ export { createHydrationStreamProvider as n, HydrationStreamProviderProps as t };
67
+ //# sourceMappingURL=HydrationStreamProvider-D_lqnUNo.d.cts.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,67 @@
1
+ import * as React from "react";
2
+ //#region src/HydrationStreamProvider.d.ts
3
+ interface DataTransformer {
4
+ serialize: (object: any) => any;
5
+ deserialize: (object: any) => any;
6
+ }
7
+ interface HydrationStreamContext<TShape> {
8
+ id: string;
9
+ stream: {
10
+ /**
11
+ * **Server method**
12
+ * Push a new entry to the stream
13
+ * Will be ignored on the client
14
+ */
15
+ push: (...shape: Array<TShape>) => void;
16
+ };
17
+ }
18
+ interface HydrationStreamProviderProps<TShape> {
19
+ children: React.ReactNode;
20
+ /**
21
+ * Optional transformer to serialize/deserialize the data
22
+ * Example devalue, superjson et al
23
+ */
24
+ transformer?: DataTransformer;
25
+ /**
26
+ * **Client method**
27
+ * Called in the browser when new entries are received
28
+ */
29
+ onEntries: (entries: Array<TShape>) => void;
30
+ /**
31
+ * **Server method**
32
+ * onFlush is called on the server when the cache is flushed
33
+ */
34
+ onFlush?: () => Array<TShape>;
35
+ /**
36
+ * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced
37
+ */
38
+ nonce?: string;
39
+ }
40
+ declare function createHydrationStreamProvider<TShape>(): {
41
+ Provider: (props: {
42
+ children: React.ReactNode;
43
+ /**
44
+ * Optional transformer to serialize/deserialize the data
45
+ * Example devalue, superjson et al
46
+ */
47
+ transformer?: DataTransformer;
48
+ /**
49
+ * **Client method**
50
+ * Called in the browser when new entries are received
51
+ */
52
+ onEntries: (entries: Array<TShape>) => void;
53
+ /**
54
+ * **Server method**
55
+ * onFlush is called on the server when the cache is flushed
56
+ */
57
+ onFlush?: () => Array<TShape>;
58
+ /**
59
+ * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced
60
+ */
61
+ nonce?: string;
62
+ }) => import("react/jsx-runtime").JSX.Element;
63
+ context: React.Context<HydrationStreamContext<TShape>>;
64
+ };
65
+ //#endregion
66
+ export { createHydrationStreamProvider as n, HydrationStreamProviderProps as t };
67
+ //# sourceMappingURL=HydrationStreamProvider-D_lqnUNo.d.ts.map
@@ -0,0 +1 @@
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,118 +1,77 @@
1
- "use strict";
2
1
  "use client";
3
- var __create = Object.create;
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __export = (target, all) => {
10
- for (var name in all)
11
- __defProp(target, name, { get: all[name], enumerable: true });
12
- };
13
- var __copyProps = (to, from, except, desc) => {
14
- if (from && typeof from === "object" || typeof from === "function") {
15
- for (let key of __getOwnPropNames(from))
16
- if (!__hasOwnProp.call(to, key) && key !== except)
17
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
- }
19
- return to;
20
- };
21
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
- // If the importer is in node compatibility mode or this is not an ESM
23
- // file that has been converted to a CommonJS file using a Babel-
24
- // compatible transform (i.e. "__esModule" has not been set), then set
25
- // "default" to the CommonJS "module.exports" for node compatibility.
26
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
- mod
28
- ));
29
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
-
31
- // src/HydrationStreamProvider.tsx
32
- var HydrationStreamProvider_exports = {};
33
- __export(HydrationStreamProvider_exports, {
34
- createHydrationStreamProvider: () => createHydrationStreamProvider
35
- });
36
- module.exports = __toCommonJS(HydrationStreamProvider_exports);
37
- var import_react_query = require("@tanstack/react-query");
38
- var import_navigation = require("next/navigation");
39
- var React = __toESM(require("react"), 1);
40
- var import_htmlescape = require("./htmlescape.cjs");
41
- var import_jsx_runtime = require("react/jsx-runtime");
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
4
+ const require_htmlescape = require("./htmlescape.cjs");
5
+ let _tanstack_react_query = require("@tanstack/react-query");
6
+ let next_navigation_js = require("next/navigation.js");
7
+ let react = require("react");
8
+ react = require_rolldown_runtime.__toESM(react, 1);
9
+ let react_jsx_runtime = require("react/jsx-runtime");
10
+ //#region src/HydrationStreamProvider.tsx
42
11
  function createHydrationStreamProvider() {
43
- const context = React.createContext(
44
- null
45
- );
46
- function UseClientHydrationStreamProvider(props) {
47
- var _a;
48
- const id = `__RQ${React.useId()}`;
49
- const idJSON = (0, import_htmlescape.htmlEscapeJsonString)(JSON.stringify(id));
50
- const [transformer] = React.useState(
51
- () => props.transformer ?? {
52
- // noop
53
- serialize: (obj) => obj,
54
- deserialize: (obj) => obj
55
- }
56
- );
57
- const [stream] = React.useState(() => {
58
- if (!import_react_query.environmentManager.isServer()) {
59
- return {
60
- push() {
61
- }
62
- };
63
- }
64
- return [];
65
- });
66
- const count = React.useRef(0);
67
- (0, import_navigation.useServerInsertedHTML)(() => {
68
- var _a2;
69
- stream.push(...((_a2 = props.onFlush) == null ? void 0 : _a2.call(props)) ?? []);
70
- if (!stream.length) {
71
- return null;
72
- }
73
- const serializedCacheArgs = stream.map((entry) => transformer.serialize(entry)).map((entry) => JSON.stringify(entry)).join(",");
74
- stream.length = 0;
75
- const html = [
76
- `window[${idJSON}] = window[${idJSON}] || [];`,
77
- `window[${idJSON}].push(${(0, import_htmlescape.htmlEscapeJsonString)(serializedCacheArgs)});`
78
- ];
79
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
80
- "script",
81
- {
82
- nonce: props.nonce,
83
- dangerouslySetInnerHTML: {
84
- __html: html.join("")
85
- }
86
- },
87
- count.current++
88
- );
89
- });
90
- if (!import_react_query.environmentManager.isServer()) {
91
- const win = window;
92
- if (!((_a = win[id]) == null ? void 0 : _a.initialized)) {
93
- const onEntries = (...serializedEntries) => {
94
- const entries = serializedEntries.map(
95
- (serialized) => transformer.deserialize(serialized)
96
- );
97
- props.onEntries(entries);
98
- };
99
- const winStream = win[id] ?? [];
100
- onEntries(...winStream);
101
- win[id] = {
102
- initialized: true,
103
- push: onEntries
104
- };
105
- }
106
- }
107
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(context.Provider, { value: { stream, id }, children: props.children });
108
- }
109
- return {
110
- Provider: UseClientHydrationStreamProvider,
111
- context
112
- };
12
+ const context = react.createContext(null);
13
+ /**
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)`
18
+ * 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
+ **/
22
+ function UseClientHydrationStreamProvider(props) {
23
+ const id = `__RQ${react.useId()}`;
24
+ const idJSON = require_htmlescape.htmlEscapeJsonString(JSON.stringify(id));
25
+ const [transformer] = react.useState(() => props.transformer ?? {
26
+ serialize: (obj) => obj,
27
+ deserialize: (obj) => obj
28
+ });
29
+ const [stream] = react.useState(() => {
30
+ if (!_tanstack_react_query.environmentManager.isServer()) return { push() {} };
31
+ return [];
32
+ });
33
+ const count = react.useRef(0);
34
+ (0, next_navigation_js.useServerInsertedHTML)(() => {
35
+ var _props$onFlush;
36
+ stream.push(...((_props$onFlush = props.onFlush) === null || _props$onFlush === void 0 ? void 0 : _props$onFlush.call(props)) ?? []);
37
+ if (!stream.length) return null;
38
+ const serializedCacheArgs = stream.map((entry) => transformer.serialize(entry)).map((entry) => JSON.stringify(entry)).join(",");
39
+ stream.length = 0;
40
+ const html = [`window[${idJSON}] = window[${idJSON}] || [];`, `window[${idJSON}].push(${require_htmlescape.htmlEscapeJsonString(serializedCacheArgs)});`];
41
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("script", {
42
+ nonce: props.nonce,
43
+ dangerouslySetInnerHTML: { __html: html.join("") }
44
+ }, count.current++);
45
+ });
46
+ if (!_tanstack_react_query.environmentManager.isServer()) {
47
+ var _win$id;
48
+ const win = window;
49
+ if (!((_win$id = win[id]) === null || _win$id === void 0 ? void 0 : _win$id.initialized)) {
50
+ const onEntries = (...serializedEntries) => {
51
+ const entries = serializedEntries.map((serialized) => transformer.deserialize(serialized));
52
+ props.onEntries(entries);
53
+ };
54
+ onEntries(...win[id] ?? []);
55
+ win[id] = {
56
+ initialized: true,
57
+ push: onEntries
58
+ };
59
+ }
60
+ }
61
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(context.Provider, {
62
+ value: {
63
+ stream,
64
+ id
65
+ },
66
+ children: props.children
67
+ });
68
+ }
69
+ return {
70
+ Provider: UseClientHydrationStreamProvider,
71
+ context
72
+ };
113
73
  }
114
- // Annotate the CommonJS export names for ESM import in node:
115
- 0 && (module.exports = {
116
- createHydrationStreamProvider
117
- });
74
+ //#endregion
75
+ exports.createHydrationStreamProvider = createHydrationStreamProvider;
76
+
118
77
  //# sourceMappingURL=HydrationStreamProvider.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/HydrationStreamProvider.tsx"],"sourcesContent":["'use client'\n\nimport { environmentManager } from '@tanstack/react-query'\nimport { useServerInsertedHTML } from 'next/navigation'\nimport * as React from 'react'\nimport { htmlEscapeJsonString } from './htmlescape'\n\nconst serializedSymbol = Symbol('serialized')\n\ninterface DataTransformer {\n serialize: (object: any) => any\n deserialize: (object: any) => any\n}\n\ntype Serialized<TData> = unknown & {\n [serializedSymbol]: TData\n}\n\ninterface TypedDataTransformer<TData> {\n serialize: (obj: TData) => Serialized<TData>\n deserialize: (obj: Serialized<TData>) => TData\n}\n\ninterface HydrationStreamContext<TShape> {\n id: string\n stream: {\n /**\n * **Server method**\n * Push a new entry to the stream\n * Will be ignored on the client\n */\n push: (...shape: Array<TShape>) => void\n }\n}\n\nexport interface HydrationStreamProviderProps<TShape> {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n}\n\nexport function createHydrationStreamProvider<TShape>() {\n const context = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n\n * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes\n * - This means that we might have some new entries in the cache that needs to be flushed\n * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`\n * 2. (Happens in browser) In `useEffect()`:\n * - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries\n * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received\n **/\n function UseClientHydrationStreamProvider(props: {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n }) {\n // unique id for the cache provider\n const id = `__RQ${React.useId()}`\n const idJSON = htmlEscapeJsonString(JSON.stringify(id))\n\n const [transformer] = React.useState(\n () =>\n (props.transformer ?? {\n // noop\n serialize: (obj: any) => obj,\n deserialize: (obj: any) => obj,\n }) as unknown as TypedDataTransformer<TShape>,\n )\n\n // <server stuff>\n const [stream] = React.useState<Array<TShape>>(() => {\n if (!environmentManager.isServer()) {\n return {\n push() {\n // no-op on the client\n },\n } as unknown as Array<TShape>\n }\n return []\n })\n const count = React.useRef(0)\n useServerInsertedHTML(() => {\n // This only happens on the server\n stream.push(...(props.onFlush?.() ?? []))\n\n if (!stream.length) {\n return null\n }\n // console.log(`pushing ${stream.length} entries`)\n const serializedCacheArgs = stream\n .map((entry) => transformer.serialize(entry))\n .map((entry) => JSON.stringify(entry))\n .join(',')\n\n // Flush stream\n // eslint-disable-next-line react-hooks/immutability\n stream.length = 0\n\n const html: Array<string> = [\n `window[${idJSON}] = window[${idJSON}] || [];`,\n `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,\n ]\n return (\n <script\n key={count.current++}\n nonce={props.nonce}\n dangerouslySetInnerHTML={{\n __html: html.join(''),\n }}\n />\n )\n })\n // </server stuff>\n\n // <client stuff>\n // Setup and run the onEntries handler on the client only, but do it during\n // the initial render so children have access to the data immediately\n // This is important to avoid the client suspending during the initial render\n // if the data has not yet been hydrated.\n if (!environmentManager.isServer()) {\n const win = window as any\n if (!win[id]?.initialized) {\n // Client: consume cache:\n const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {\n const entries = serializedEntries.map((serialized) =>\n transformer.deserialize(serialized),\n )\n props.onEntries(entries)\n }\n\n const winStream: Array<Serialized<TShape>> = win[id] ?? []\n\n onEntries(...winStream)\n\n // eslint-disable-next-line react-hooks/immutability\n win[id] = {\n initialized: true,\n push: onEntries,\n }\n }\n }\n // </client stuff>\n\n return (\n <context.Provider value={{ stream, id }}>\n {props.children}\n </context.Provider>\n )\n }\n\n return {\n Provider: UseClientHydrationStreamProvider,\n context,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,yBAAmC;AACnC,wBAAsC;AACtC,YAAuB;AACvB,wBAAqC;AAuI7B;AAlFD,SAAS,gCAAwC;AACtD,QAAM,UAAgB;AAAA,IACpB;AAAA,EACF;AAUA,WAAS,iCAAiC,OAqBvC;AA5FL;AA8FI,UAAM,KAAK,OAAa,YAAM,CAAC;AAC/B,UAAM,aAAS,wCAAqB,KAAK,UAAU,EAAE,CAAC;AAEtD,UAAM,CAAC,WAAW,IAAU;AAAA,MAC1B,MACG,MAAM,eAAe;AAAA;AAAA,QAEpB,WAAW,CAAC,QAAa;AAAA,QACzB,aAAa,CAAC,QAAa;AAAA,MAC7B;AAAA,IACJ;AAGA,UAAM,CAAC,MAAM,IAAU,eAAwB,MAAM;AACnD,UAAI,CAAC,sCAAmB,SAAS,GAAG;AAClC,eAAO;AAAA,UACL,OAAO;AAAA,UAEP;AAAA,QACF;AAAA,MACF;AACA,aAAO,CAAC;AAAA,IACV,CAAC;AACD,UAAM,QAAc,aAAO,CAAC;AAC5B,iDAAsB,MAAM;AAtHhC,UAAAA;AAwHM,aAAO,KAAK,KAAIA,MAAA,MAAM,YAAN,gBAAAA,IAAA,gBAAqB,CAAC,CAAE;AAExC,UAAI,CAAC,OAAO,QAAQ;AAClB,eAAO;AAAA,MACT;AAEA,YAAM,sBAAsB,OACzB,IAAI,CAAC,UAAU,YAAY,UAAU,KAAK,CAAC,EAC3C,IAAI,CAAC,UAAU,KAAK,UAAU,KAAK,CAAC,EACpC,KAAK,GAAG;AAIX,aAAO,SAAS;AAEhB,YAAM,OAAsB;AAAA,QAC1B,UAAU,MAAM,cAAc,MAAM;AAAA,QACpC,UAAU,MAAM,cAAU,wCAAqB,mBAAmB,CAAC;AAAA,MACrE;AACA,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,OAAO,MAAM;AAAA,UACb,yBAAyB;AAAA,YACvB,QAAQ,KAAK,KAAK,EAAE;AAAA,UACtB;AAAA;AAAA,QAJK,MAAM;AAAA,MAKb;AAAA,IAEJ,CAAC;AAQD,QAAI,CAAC,sCAAmB,SAAS,GAAG;AAClC,YAAM,MAAM;AACZ,UAAI,GAAC,SAAI,EAAE,MAAN,mBAAS,cAAa;AAEzB,cAAM,YAAY,IAAI,sBAAiD;AACrE,gBAAM,UAAU,kBAAkB;AAAA,YAAI,CAAC,eACrC,YAAY,YAAY,UAAU;AAAA,UACpC;AACA,gBAAM,UAAU,OAAO;AAAA,QACzB;AAEA,cAAM,YAAuC,IAAI,EAAE,KAAK,CAAC;AAEzD,kBAAU,GAAG,SAAS;AAGtB,YAAI,EAAE,IAAI;AAAA,UACR,aAAa;AAAA,UACb,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAGA,WACE,4CAAC,QAAQ,UAAR,EAAiB,OAAO,EAAE,QAAQ,GAAG,GACnC,gBAAM,UACT;AAAA,EAEJ;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,EACF;AACF;","names":["_a"]}
1
+ {"version":3,"file":"HydrationStreamProvider.cjs","names":["React","htmlEscapeJsonString","environmentManager"],"sources":["../../src/HydrationStreamProvider.tsx"],"sourcesContent":["'use client'\n\nimport { environmentManager } from '@tanstack/react-query'\nimport { useServerInsertedHTML } from 'next/navigation'\nimport * as React from 'react'\nimport { htmlEscapeJsonString } from './htmlescape'\n\nconst serializedSymbol = Symbol('serialized')\n\ninterface DataTransformer {\n serialize: (object: any) => any\n deserialize: (object: any) => any\n}\n\ntype Serialized<TData> = unknown & {\n [serializedSymbol]: TData\n}\n\ninterface TypedDataTransformer<TData> {\n serialize: (obj: TData) => Serialized<TData>\n deserialize: (obj: Serialized<TData>) => TData\n}\n\ninterface HydrationStreamContext<TShape> {\n id: string\n stream: {\n /**\n * **Server method**\n * Push a new entry to the stream\n * Will be ignored on the client\n */\n push: (...shape: Array<TShape>) => void\n }\n}\n\nexport interface HydrationStreamProviderProps<TShape> {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n}\n\nexport function createHydrationStreamProvider<TShape>() {\n const context = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n\n * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes\n * - This means that we might have some new entries in the cache that needs to be flushed\n * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`\n * 2. (Happens in browser) In `useEffect()`:\n * - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries\n * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received\n **/\n function UseClientHydrationStreamProvider(props: {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n }) {\n // unique id for the cache provider\n const id = `__RQ${React.useId()}`\n const idJSON = htmlEscapeJsonString(JSON.stringify(id))\n\n const [transformer] = React.useState(\n () =>\n (props.transformer ?? {\n // noop\n serialize: (obj: any) => obj,\n deserialize: (obj: any) => obj,\n }) as unknown as TypedDataTransformer<TShape>,\n )\n\n // <server stuff>\n const [stream] = React.useState<Array<TShape>>(() => {\n if (!environmentManager.isServer()) {\n return {\n push() {\n // no-op on the client\n },\n } as unknown as Array<TShape>\n }\n return []\n })\n const count = React.useRef(0)\n useServerInsertedHTML(() => {\n // This only happens on the server\n stream.push(...(props.onFlush?.() ?? []))\n\n if (!stream.length) {\n return null\n }\n // console.log(`pushing ${stream.length} entries`)\n const serializedCacheArgs = stream\n .map((entry) => transformer.serialize(entry))\n .map((entry) => JSON.stringify(entry))\n .join(',')\n\n // Flush stream\n // eslint-disable-next-line react-hooks/immutability\n stream.length = 0\n\n const html: Array<string> = [\n `window[${idJSON}] = window[${idJSON}] || [];`,\n `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,\n ]\n return (\n <script\n key={count.current++}\n nonce={props.nonce}\n dangerouslySetInnerHTML={{\n __html: html.join(''),\n }}\n />\n )\n })\n // </server stuff>\n\n // <client stuff>\n // Setup and run the onEntries handler on the client only, but do it during\n // the initial render so children have access to the data immediately\n // This is important to avoid the client suspending during the initial render\n // if the data has not yet been hydrated.\n if (!environmentManager.isServer()) {\n const win = window as any\n if (!win[id]?.initialized) {\n // Client: consume cache:\n const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {\n const entries = serializedEntries.map((serialized) =>\n transformer.deserialize(serialized),\n )\n props.onEntries(entries)\n }\n\n const winStream: Array<Serialized<TShape>> = win[id] ?? []\n\n onEntries(...winStream)\n\n // eslint-disable-next-line react-hooks/immutability\n win[id] = {\n initialized: true,\n push: onEntries,\n }\n }\n }\n // </client stuff>\n\n return (\n <context.Provider value={{ stream, id }}>\n {props.children}\n </context.Provider>\n )\n }\n\n return {\n Provider: UseClientHydrationStreamProvider,\n context,\n }\n}\n"],"mappings":";;;;;;;;;;AA0DA,SAAgB,gCAAwC;CACtD,MAAM,UAAUA,MAAM,cACpB,IACF;;;;;;;;;;CAUA,SAAS,iCAAiC,OAqBvC;EAED,MAAM,KAAK,OAAOA,MAAM,MAAM;EAC9B,MAAM,SAASC,mBAAAA,qBAAqB,KAAK,UAAU,EAAE,CAAC;EAEtD,MAAM,CAAC,eAAeD,MAAM,eAEvB,MAAM,eAAe;GAEpB,YAAY,QAAa;GACzB,cAAc,QAAa;EAC7B,CACJ;EAGA,MAAM,CAAC,UAAUA,MAAM,eAA8B;GACnD,IAAI,CAACE,sBAAAA,mBAAmB,SAAS,GAC/B,OAAO,EACL,OAAO,CAEP,EACF;GAEF,OAAO,CAAC;EACV,CAAC;EACD,MAAM,QAAQF,MAAM,OAAO,CAAC;EAC5B,CAAA,GAAA,mBAAA,sBAAA,OAA4B;;GAE1B,OAAO,KAAK,KAAA,iBAAI,MAAM,aAAA,QAAA,mBAAA,KAAA,IAAA,KAAA,IAAA,eAAA,KAAA,KAAU,MAAK,CAAC,CAAE;GAExC,IAAI,CAAC,OAAO,QACV,OAAO;GAGT,MAAM,sBAAsB,OACzB,KAAK,UAAU,YAAY,UAAU,KAAK,CAAC,CAAC,CAC5C,KAAK,UAAU,KAAK,UAAU,KAAK,CAAC,CAAC,CACrC,KAAK,GAAG;GAIX,OAAO,SAAS;GAEhB,MAAM,OAAsB,CAC1B,UAAU,OAAO,aAAa,OAAO,WACrC,UAAU,OAAO,SAASC,mBAAAA,qBAAqB,mBAAmB,EAAE,GACtE;GACA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;IAEE,OAAO,MAAM;IACb,yBAAyB,EACvB,QAAQ,KAAK,KAAK,EAAE,EACtB;GACD,GALM,MAAM,SAKZ;EAEL,CAAC;EAQD,IAAI,CAACC,sBAAAA,mBAAmB,SAAS,GAAG;;GAClC,MAAM,MAAM;GACZ,IAAI,GAAA,UAAC,IAAI,SAAA,QAAA,YAAA,KAAA,IAAA,KAAA,IAAA,QAAK,cAAa;IAEzB,MAAM,aAAa,GAAG,sBAAiD;KACrE,MAAM,UAAU,kBAAkB,KAAK,eACrC,YAAY,YAAY,UAAU,CACpC;KACA,MAAM,UAAU,OAAO;IACzB;IAIA,UAAU,GAFmC,IAAI,OAAO,CAAC,CAEnC;IAGtB,IAAI,MAAM;KACR,aAAa;KACb,MAAM;IACR;GACF;EACF;EAGA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAQ,UAAT;GAAkB,OAAO;IAAE;IAAQ;GAAG;GACnC,UAAA,MAAM;EACS,CAAA;CAEtB;CAEA,OAAO;EACL,UAAU;EACV;CACF;AACF"}
@@ -1,2 +1,2 @@
1
- export { createHydrationStreamProvider } from './_tsup-dts-rollup.cjs';
2
- export { HydrationStreamProviderProps } from './_tsup-dts-rollup.cjs';
1
+ import { n as createHydrationStreamProvider, t as HydrationStreamProviderProps } from "./HydrationStreamProvider-D_lqnUNo.cjs";
2
+ export { HydrationStreamProviderProps, createHydrationStreamProvider };
@@ -1,2 +1,2 @@
1
- export { createHydrationStreamProvider } from './_tsup-dts-rollup.js';
2
- export { HydrationStreamProviderProps } from './_tsup-dts-rollup.js';
1
+ import { n as createHydrationStreamProvider, t as HydrationStreamProviderProps } from "./HydrationStreamProvider-D_lqnUNo.js";
2
+ export { HydrationStreamProviderProps, createHydrationStreamProvider };
@@ -1,84 +1,74 @@
1
1
  "use client";
2
-
3
- // src/HydrationStreamProvider.tsx
2
+ import { htmlEscapeJsonString } from "./htmlescape.js";
4
3
  import { environmentManager } from "@tanstack/react-query";
5
- import { useServerInsertedHTML } from "next/navigation";
4
+ import { useServerInsertedHTML } from "next/navigation.js";
6
5
  import * as React from "react";
7
- import { htmlEscapeJsonString } from "./htmlescape.js";
8
6
  import { jsx } from "react/jsx-runtime";
7
+ //#region src/HydrationStreamProvider.tsx
9
8
  function createHydrationStreamProvider() {
10
- const context = React.createContext(
11
- null
12
- );
13
- function UseClientHydrationStreamProvider(props) {
14
- var _a;
15
- const id = `__RQ${React.useId()}`;
16
- const idJSON = htmlEscapeJsonString(JSON.stringify(id));
17
- const [transformer] = React.useState(
18
- () => props.transformer ?? {
19
- // noop
20
- serialize: (obj) => obj,
21
- deserialize: (obj) => obj
22
- }
23
- );
24
- const [stream] = React.useState(() => {
25
- if (!environmentManager.isServer()) {
26
- return {
27
- push() {
28
- }
29
- };
30
- }
31
- return [];
32
- });
33
- const count = React.useRef(0);
34
- useServerInsertedHTML(() => {
35
- var _a2;
36
- stream.push(...((_a2 = props.onFlush) == null ? void 0 : _a2.call(props)) ?? []);
37
- if (!stream.length) {
38
- return null;
39
- }
40
- const serializedCacheArgs = stream.map((entry) => transformer.serialize(entry)).map((entry) => JSON.stringify(entry)).join(",");
41
- stream.length = 0;
42
- const html = [
43
- `window[${idJSON}] = window[${idJSON}] || [];`,
44
- `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`
45
- ];
46
- return /* @__PURE__ */ jsx(
47
- "script",
48
- {
49
- nonce: props.nonce,
50
- dangerouslySetInnerHTML: {
51
- __html: html.join("")
52
- }
53
- },
54
- count.current++
55
- );
56
- });
57
- if (!environmentManager.isServer()) {
58
- const win = window;
59
- if (!((_a = win[id]) == null ? void 0 : _a.initialized)) {
60
- const onEntries = (...serializedEntries) => {
61
- const entries = serializedEntries.map(
62
- (serialized) => transformer.deserialize(serialized)
63
- );
64
- props.onEntries(entries);
65
- };
66
- const winStream = win[id] ?? [];
67
- onEntries(...winStream);
68
- win[id] = {
69
- initialized: true,
70
- push: onEntries
71
- };
72
- }
73
- }
74
- return /* @__PURE__ */ jsx(context.Provider, { value: { stream, id }, children: props.children });
75
- }
76
- return {
77
- Provider: UseClientHydrationStreamProvider,
78
- context
79
- };
9
+ const context = React.createContext(null);
10
+ /**
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)`
15
+ * 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
+ **/
19
+ function UseClientHydrationStreamProvider(props) {
20
+ const id = `__RQ${React.useId()}`;
21
+ const idJSON = htmlEscapeJsonString(JSON.stringify(id));
22
+ const [transformer] = React.useState(() => props.transformer ?? {
23
+ serialize: (obj) => obj,
24
+ deserialize: (obj) => obj
25
+ });
26
+ const [stream] = React.useState(() => {
27
+ if (!environmentManager.isServer()) return { push() {} };
28
+ return [];
29
+ });
30
+ const count = React.useRef(0);
31
+ useServerInsertedHTML(() => {
32
+ var _props$onFlush;
33
+ stream.push(...((_props$onFlush = props.onFlush) === null || _props$onFlush === void 0 ? void 0 : _props$onFlush.call(props)) ?? []);
34
+ if (!stream.length) return null;
35
+ const serializedCacheArgs = stream.map((entry) => transformer.serialize(entry)).map((entry) => JSON.stringify(entry)).join(",");
36
+ stream.length = 0;
37
+ const html = [`window[${idJSON}] = window[${idJSON}] || [];`, `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`];
38
+ return /* @__PURE__ */ jsx("script", {
39
+ nonce: props.nonce,
40
+ dangerouslySetInnerHTML: { __html: html.join("") }
41
+ }, count.current++);
42
+ });
43
+ if (!environmentManager.isServer()) {
44
+ var _win$id;
45
+ const win = window;
46
+ if (!((_win$id = win[id]) === null || _win$id === void 0 ? void 0 : _win$id.initialized)) {
47
+ const onEntries = (...serializedEntries) => {
48
+ const entries = serializedEntries.map((serialized) => transformer.deserialize(serialized));
49
+ props.onEntries(entries);
50
+ };
51
+ onEntries(...win[id] ?? []);
52
+ win[id] = {
53
+ initialized: true,
54
+ push: onEntries
55
+ };
56
+ }
57
+ }
58
+ return /* @__PURE__ */ jsx(context.Provider, {
59
+ value: {
60
+ stream,
61
+ id
62
+ },
63
+ children: props.children
64
+ });
65
+ }
66
+ return {
67
+ Provider: UseClientHydrationStreamProvider,
68
+ context
69
+ };
80
70
  }
81
- export {
82
- createHydrationStreamProvider
83
- };
71
+ //#endregion
72
+ export { createHydrationStreamProvider };
73
+
84
74
  //# sourceMappingURL=HydrationStreamProvider.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/HydrationStreamProvider.tsx"],"sourcesContent":["'use client'\n\nimport { environmentManager } from '@tanstack/react-query'\nimport { useServerInsertedHTML } from 'next/navigation'\nimport * as React from 'react'\nimport { htmlEscapeJsonString } from './htmlescape'\n\nconst serializedSymbol = Symbol('serialized')\n\ninterface DataTransformer {\n serialize: (object: any) => any\n deserialize: (object: any) => any\n}\n\ntype Serialized<TData> = unknown & {\n [serializedSymbol]: TData\n}\n\ninterface TypedDataTransformer<TData> {\n serialize: (obj: TData) => Serialized<TData>\n deserialize: (obj: Serialized<TData>) => TData\n}\n\ninterface HydrationStreamContext<TShape> {\n id: string\n stream: {\n /**\n * **Server method**\n * Push a new entry to the stream\n * Will be ignored on the client\n */\n push: (...shape: Array<TShape>) => void\n }\n}\n\nexport interface HydrationStreamProviderProps<TShape> {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n}\n\nexport function createHydrationStreamProvider<TShape>() {\n const context = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n\n * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes\n * - This means that we might have some new entries in the cache that needs to be flushed\n * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`\n * 2. (Happens in browser) In `useEffect()`:\n * - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries\n * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received\n **/\n function UseClientHydrationStreamProvider(props: {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n }) {\n // unique id for the cache provider\n const id = `__RQ${React.useId()}`\n const idJSON = htmlEscapeJsonString(JSON.stringify(id))\n\n const [transformer] = React.useState(\n () =>\n (props.transformer ?? {\n // noop\n serialize: (obj: any) => obj,\n deserialize: (obj: any) => obj,\n }) as unknown as TypedDataTransformer<TShape>,\n )\n\n // <server stuff>\n const [stream] = React.useState<Array<TShape>>(() => {\n if (!environmentManager.isServer()) {\n return {\n push() {\n // no-op on the client\n },\n } as unknown as Array<TShape>\n }\n return []\n })\n const count = React.useRef(0)\n useServerInsertedHTML(() => {\n // This only happens on the server\n stream.push(...(props.onFlush?.() ?? []))\n\n if (!stream.length) {\n return null\n }\n // console.log(`pushing ${stream.length} entries`)\n const serializedCacheArgs = stream\n .map((entry) => transformer.serialize(entry))\n .map((entry) => JSON.stringify(entry))\n .join(',')\n\n // Flush stream\n // eslint-disable-next-line react-hooks/immutability\n stream.length = 0\n\n const html: Array<string> = [\n `window[${idJSON}] = window[${idJSON}] || [];`,\n `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,\n ]\n return (\n <script\n key={count.current++}\n nonce={props.nonce}\n dangerouslySetInnerHTML={{\n __html: html.join(''),\n }}\n />\n )\n })\n // </server stuff>\n\n // <client stuff>\n // Setup and run the onEntries handler on the client only, but do it during\n // the initial render so children have access to the data immediately\n // This is important to avoid the client suspending during the initial render\n // if the data has not yet been hydrated.\n if (!environmentManager.isServer()) {\n const win = window as any\n if (!win[id]?.initialized) {\n // Client: consume cache:\n const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {\n const entries = serializedEntries.map((serialized) =>\n transformer.deserialize(serialized),\n )\n props.onEntries(entries)\n }\n\n const winStream: Array<Serialized<TShape>> = win[id] ?? []\n\n onEntries(...winStream)\n\n // eslint-disable-next-line react-hooks/immutability\n win[id] = {\n initialized: true,\n push: onEntries,\n }\n }\n }\n // </client stuff>\n\n return (\n <context.Provider value={{ stream, id }}>\n {props.children}\n </context.Provider>\n )\n }\n\n return {\n Provider: UseClientHydrationStreamProvider,\n context,\n }\n}\n"],"mappings":";;;AAEA,SAAS,0BAA0B;AACnC,SAAS,6BAA6B;AACtC,YAAY,WAAW;AACvB,SAAS,4BAA4B;AAuI7B;AAlFD,SAAS,gCAAwC;AACtD,QAAM,UAAgB;AAAA,IACpB;AAAA,EACF;AAUA,WAAS,iCAAiC,OAqBvC;AA5FL;AA8FI,UAAM,KAAK,OAAa,YAAM,CAAC;AAC/B,UAAM,SAAS,qBAAqB,KAAK,UAAU,EAAE,CAAC;AAEtD,UAAM,CAAC,WAAW,IAAU;AAAA,MAC1B,MACG,MAAM,eAAe;AAAA;AAAA,QAEpB,WAAW,CAAC,QAAa;AAAA,QACzB,aAAa,CAAC,QAAa;AAAA,MAC7B;AAAA,IACJ;AAGA,UAAM,CAAC,MAAM,IAAU,eAAwB,MAAM;AACnD,UAAI,CAAC,mBAAmB,SAAS,GAAG;AAClC,eAAO;AAAA,UACL,OAAO;AAAA,UAEP;AAAA,QACF;AAAA,MACF;AACA,aAAO,CAAC;AAAA,IACV,CAAC;AACD,UAAM,QAAc,aAAO,CAAC;AAC5B,0BAAsB,MAAM;AAtHhC,UAAAA;AAwHM,aAAO,KAAK,KAAIA,MAAA,MAAM,YAAN,gBAAAA,IAAA,gBAAqB,CAAC,CAAE;AAExC,UAAI,CAAC,OAAO,QAAQ;AAClB,eAAO;AAAA,MACT;AAEA,YAAM,sBAAsB,OACzB,IAAI,CAAC,UAAU,YAAY,UAAU,KAAK,CAAC,EAC3C,IAAI,CAAC,UAAU,KAAK,UAAU,KAAK,CAAC,EACpC,KAAK,GAAG;AAIX,aAAO,SAAS;AAEhB,YAAM,OAAsB;AAAA,QAC1B,UAAU,MAAM,cAAc,MAAM;AAAA,QACpC,UAAU,MAAM,UAAU,qBAAqB,mBAAmB,CAAC;AAAA,MACrE;AACA,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,OAAO,MAAM;AAAA,UACb,yBAAyB;AAAA,YACvB,QAAQ,KAAK,KAAK,EAAE;AAAA,UACtB;AAAA;AAAA,QAJK,MAAM;AAAA,MAKb;AAAA,IAEJ,CAAC;AAQD,QAAI,CAAC,mBAAmB,SAAS,GAAG;AAClC,YAAM,MAAM;AACZ,UAAI,GAAC,SAAI,EAAE,MAAN,mBAAS,cAAa;AAEzB,cAAM,YAAY,IAAI,sBAAiD;AACrE,gBAAM,UAAU,kBAAkB;AAAA,YAAI,CAAC,eACrC,YAAY,YAAY,UAAU;AAAA,UACpC;AACA,gBAAM,UAAU,OAAO;AAAA,QACzB;AAEA,cAAM,YAAuC,IAAI,EAAE,KAAK,CAAC;AAEzD,kBAAU,GAAG,SAAS;AAGtB,YAAI,EAAE,IAAI;AAAA,UACR,aAAa;AAAA,UACb,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAGA,WACE,oBAAC,QAAQ,UAAR,EAAiB,OAAO,EAAE,QAAQ,GAAG,GACnC,gBAAM,UACT;AAAA,EAEJ;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,EACF;AACF;","names":["_a"]}
1
+ {"version":3,"file":"HydrationStreamProvider.js","names":[],"sources":["../../src/HydrationStreamProvider.tsx"],"sourcesContent":["'use client'\n\nimport { environmentManager } from '@tanstack/react-query'\nimport { useServerInsertedHTML } from 'next/navigation'\nimport * as React from 'react'\nimport { htmlEscapeJsonString } from './htmlescape'\n\nconst serializedSymbol = Symbol('serialized')\n\ninterface DataTransformer {\n serialize: (object: any) => any\n deserialize: (object: any) => any\n}\n\ntype Serialized<TData> = unknown & {\n [serializedSymbol]: TData\n}\n\ninterface TypedDataTransformer<TData> {\n serialize: (obj: TData) => Serialized<TData>\n deserialize: (obj: Serialized<TData>) => TData\n}\n\ninterface HydrationStreamContext<TShape> {\n id: string\n stream: {\n /**\n * **Server method**\n * Push a new entry to the stream\n * Will be ignored on the client\n */\n push: (...shape: Array<TShape>) => void\n }\n}\n\nexport interface HydrationStreamProviderProps<TShape> {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n}\n\nexport function createHydrationStreamProvider<TShape>() {\n const context = React.createContext<HydrationStreamContext<TShape>>(\n null as any,\n )\n /**\n\n * 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes\n * - This means that we might have some new entries in the cache that needs to be flushed\n * - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`\n * 2. (Happens in browser) In `useEffect()`:\n * - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries\n * - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received\n **/\n function UseClientHydrationStreamProvider(props: {\n children: React.ReactNode\n /**\n * Optional transformer to serialize/deserialize the data\n * Example devalue, superjson et al\n */\n transformer?: DataTransformer\n /**\n * **Client method**\n * Called in the browser when new entries are received\n */\n onEntries: (entries: Array<TShape>) => void\n /**\n * **Server method**\n * onFlush is called on the server when the cache is flushed\n */\n onFlush?: () => Array<TShape>\n /**\n * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced\n */\n nonce?: string\n }) {\n // unique id for the cache provider\n const id = `__RQ${React.useId()}`\n const idJSON = htmlEscapeJsonString(JSON.stringify(id))\n\n const [transformer] = React.useState(\n () =>\n (props.transformer ?? {\n // noop\n serialize: (obj: any) => obj,\n deserialize: (obj: any) => obj,\n }) as unknown as TypedDataTransformer<TShape>,\n )\n\n // <server stuff>\n const [stream] = React.useState<Array<TShape>>(() => {\n if (!environmentManager.isServer()) {\n return {\n push() {\n // no-op on the client\n },\n } as unknown as Array<TShape>\n }\n return []\n })\n const count = React.useRef(0)\n useServerInsertedHTML(() => {\n // This only happens on the server\n stream.push(...(props.onFlush?.() ?? []))\n\n if (!stream.length) {\n return null\n }\n // console.log(`pushing ${stream.length} entries`)\n const serializedCacheArgs = stream\n .map((entry) => transformer.serialize(entry))\n .map((entry) => JSON.stringify(entry))\n .join(',')\n\n // Flush stream\n // eslint-disable-next-line react-hooks/immutability\n stream.length = 0\n\n const html: Array<string> = [\n `window[${idJSON}] = window[${idJSON}] || [];`,\n `window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,\n ]\n return (\n <script\n key={count.current++}\n nonce={props.nonce}\n dangerouslySetInnerHTML={{\n __html: html.join(''),\n }}\n />\n )\n })\n // </server stuff>\n\n // <client stuff>\n // Setup and run the onEntries handler on the client only, but do it during\n // the initial render so children have access to the data immediately\n // This is important to avoid the client suspending during the initial render\n // if the data has not yet been hydrated.\n if (!environmentManager.isServer()) {\n const win = window as any\n if (!win[id]?.initialized) {\n // Client: consume cache:\n const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {\n const entries = serializedEntries.map((serialized) =>\n transformer.deserialize(serialized),\n )\n props.onEntries(entries)\n }\n\n const winStream: Array<Serialized<TShape>> = win[id] ?? []\n\n onEntries(...winStream)\n\n // eslint-disable-next-line react-hooks/immutability\n win[id] = {\n initialized: true,\n push: onEntries,\n }\n }\n }\n // </client stuff>\n\n return (\n <context.Provider value={{ stream, id }}>\n {props.children}\n </context.Provider>\n )\n }\n\n return {\n Provider: UseClientHydrationStreamProvider,\n context,\n }\n}\n"],"mappings":";;;;;;;AA0DA,SAAgB,gCAAwC;CACtD,MAAM,UAAU,MAAM,cACpB,IACF;;;;;;;;;;CAUA,SAAS,iCAAiC,OAqBvC;EAED,MAAM,KAAK,OAAO,MAAM,MAAM;EAC9B,MAAM,SAAS,qBAAqB,KAAK,UAAU,EAAE,CAAC;EAEtD,MAAM,CAAC,eAAe,MAAM,eAEvB,MAAM,eAAe;GAEpB,YAAY,QAAa;GACzB,cAAc,QAAa;EAC7B,CACJ;EAGA,MAAM,CAAC,UAAU,MAAM,eAA8B;GACnD,IAAI,CAAC,mBAAmB,SAAS,GAC/B,OAAO,EACL,OAAO,CAEP,EACF;GAEF,OAAO,CAAC;EACV,CAAC;EACD,MAAM,QAAQ,MAAM,OAAO,CAAC;EAC5B,4BAA4B;;GAE1B,OAAO,KAAK,KAAA,iBAAI,MAAM,aAAA,QAAA,mBAAA,KAAA,IAAA,KAAA,IAAA,eAAA,KAAA,KAAU,MAAK,CAAC,CAAE;GAExC,IAAI,CAAC,OAAO,QACV,OAAO;GAGT,MAAM,sBAAsB,OACzB,KAAK,UAAU,YAAY,UAAU,KAAK,CAAC,CAAC,CAC5C,KAAK,UAAU,KAAK,UAAU,KAAK,CAAC,CAAC,CACrC,KAAK,GAAG;GAIX,OAAO,SAAS;GAEhB,MAAM,OAAsB,CAC1B,UAAU,OAAO,aAAa,OAAO,WACrC,UAAU,OAAO,SAAS,qBAAqB,mBAAmB,EAAE,GACtE;GACA,OACE,oBAAC,UAAD;IAEE,OAAO,MAAM;IACb,yBAAyB,EACvB,QAAQ,KAAK,KAAK,EAAE,EACtB;GACD,GALM,MAAM,SAKZ;EAEL,CAAC;EAQD,IAAI,CAAC,mBAAmB,SAAS,GAAG;;GAClC,MAAM,MAAM;GACZ,IAAI,GAAA,UAAC,IAAI,SAAA,QAAA,YAAA,KAAA,IAAA,KAAA,IAAA,QAAK,cAAa;IAEzB,MAAM,aAAa,GAAG,sBAAiD;KACrE,MAAM,UAAU,kBAAkB,KAAK,eACrC,YAAY,YAAY,UAAU,CACpC;KACA,MAAM,UAAU,OAAO;IACzB;IAIA,UAAU,GAFmC,IAAI,OAAO,CAAC,CAEnC;IAGtB,IAAI,MAAM;KACR,aAAa;KACb,MAAM;IACR;GACF;EACF;EAGA,OACE,oBAAC,QAAQ,UAAT;GAAkB,OAAO;IAAE;IAAQ;GAAG;GACnC,UAAA,MAAM;EACS,CAAA;CAEtB;CAEA,OAAO;EACL,UAAU;EACV;CACF;AACF"}