@fluixi/core 1.0.0-alpha.100
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.
- package/LICENSE +21 -0
- package/README.md +334 -0
- package/dist/cdn/core.global.js +2 -0
- package/dist/cli/generate.cjs +5639 -0
- package/dist/cli/generate.d.ts +7 -0
- package/dist/cli/generate.d.ts.map +1 -0
- package/dist/cli/generate.js +2580 -0
- package/dist/cli/generate.mjs +5644 -0
- package/dist/cli/index.cjs +5639 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +2580 -0
- package/dist/cli/index.mjs +5644 -0
- package/dist/cli/run.cjs +64 -0
- package/dist/cli/run.d.ts +3 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +62 -0
- package/dist/cli/run.mjs +40 -0
- package/dist/fluixi.d.ts +5 -0
- package/dist/src/cdn/chunk-RKBFEFZP.mjs +987 -0
- package/dist/src/cdn/core.cjs +1592 -0
- package/dist/src/cdn/core.d.ts +16 -0
- package/dist/src/cdn/core.d.ts.map +1 -0
- package/dist/src/cdn/core.js +15 -0
- package/dist/src/cdn/core.mjs +714 -0
- package/dist/src/cdn/router-V2THK27H.mjs +74 -0
- package/dist/src/index.cjs +1711 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +11 -0
- package/dist/src/index.mjs +1833 -0
- package/dist/src/jsx-dev-runtime.cjs +26 -0
- package/dist/src/jsx-dev-runtime.d.ts +2 -0
- package/dist/src/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/src/jsx-dev-runtime.js +1 -0
- package/dist/src/jsx-dev-runtime.mjs +24 -0
- package/dist/src/jsx-runtime.cjs +26 -0
- package/dist/src/jsx-runtime.d.ts +7 -0
- package/dist/src/jsx-runtime.d.ts.map +1 -0
- package/dist/src/jsx-runtime.js +8 -0
- package/dist/src/jsx-runtime.mjs +24 -0
- package/dist/src/lib/client/chunk-FDOPDB6Z.mjs +53 -0
- package/dist/src/lib/client/index.cjs +1210 -0
- package/dist/src/lib/client/index.d.ts +51 -0
- package/dist/src/lib/client/index.d.ts.map +1 -0
- package/dist/src/lib/client/index.js +174 -0
- package/dist/src/lib/client/index.mjs +293 -0
- package/dist/src/lib/client/router-4PTBPZLQ.mjs +891 -0
- package/dist/src/lib/context/context.cjs +81 -0
- package/dist/src/lib/context/context.d.ts +73 -0
- package/dist/src/lib/context/context.d.ts.map +1 -0
- package/dist/src/lib/context/context.js +93 -0
- package/dist/src/lib/context/context.mjs +64 -0
- package/dist/src/lib/context/index.cjs +83 -0
- package/dist/src/lib/context/index.d.ts +3 -0
- package/dist/src/lib/context/index.d.ts.map +1 -0
- package/dist/src/lib/context/index.js +1 -0
- package/dist/src/lib/context/index.mjs +64 -0
- package/dist/src/lib/control-flow.cjs +35 -0
- package/dist/src/lib/control-flow.d.ts +4 -0
- package/dist/src/lib/control-flow.d.ts.map +1 -0
- package/dist/src/lib/control-flow.js +1 -0
- package/dist/src/lib/control-flow.mjs +25 -0
- package/dist/src/lib/core.cjs +1710 -0
- package/dist/src/lib/core.d.ts +91 -0
- package/dist/src/lib/core.d.ts.map +1 -0
- package/dist/src/lib/core.js +158 -0
- package/dist/src/lib/core.mjs +1833 -0
- package/dist/src/lib/env/index.cjs +44 -0
- package/dist/src/lib/env/index.d.ts +26 -0
- package/dist/src/lib/env/index.d.ts.map +1 -0
- package/dist/src/lib/env/index.js +31 -0
- package/dist/src/lib/env/index.mjs +23 -0
- package/dist/src/lib/i18n/index.cjs +123 -0
- package/dist/src/lib/i18n/index.d.ts +110 -0
- package/dist/src/lib/i18n/index.d.ts.map +1 -0
- package/dist/src/lib/i18n/index.js +164 -0
- package/dist/src/lib/i18n/index.mjs +103 -0
- package/dist/src/lib/index.cjs +598 -0
- package/dist/src/lib/index.d.ts +81 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +130 -0
- package/dist/src/lib/index.mjs +688 -0
- package/dist/src/lib/isomorphic.cjs +90 -0
- package/dist/src/lib/isomorphic.d.ts +114 -0
- package/dist/src/lib/isomorphic.d.ts.map +1 -0
- package/dist/src/lib/isomorphic.js +132 -0
- package/dist/src/lib/isomorphic.mjs +69 -0
- package/dist/src/lib/jsx-runtime/index.cjs +21 -0
- package/dist/src/lib/jsx-runtime/index.d.ts +13 -0
- package/dist/src/lib/jsx-runtime/index.d.ts.map +1 -0
- package/dist/src/lib/jsx-runtime/index.js +13 -0
- package/dist/src/lib/jsx-runtime/index.mjs +4 -0
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.cjs +21 -0
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.d.ts +2 -0
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.js +1 -0
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.mjs +4 -0
- package/dist/src/lib/plugins/fluixi-routes-plugin.cjs +302 -0
- package/dist/src/lib/plugins/fluixi-routes-plugin.d.ts +35 -0
- package/dist/src/lib/plugins/fluixi-routes-plugin.d.ts.map +1 -0
- package/dist/src/lib/plugins/fluixi-routes-plugin.js +118 -0
- package/dist/src/lib/plugins/fluixi-routes-plugin.mjs +271 -0
- package/dist/src/lib/plugins/index.cjs +311 -0
- package/dist/src/lib/plugins/index.d.ts +6 -0
- package/dist/src/lib/plugins/index.d.ts.map +1 -0
- package/dist/src/lib/plugins/index.js +7 -0
- package/dist/src/lib/plugins/index.mjs +279 -0
- package/dist/src/lib/plugins/route-codegen.cjs +73 -0
- package/dist/src/lib/plugins/route-codegen.d.ts +12 -0
- package/dist/src/lib/plugins/route-codegen.d.ts.map +1 -0
- package/dist/src/lib/plugins/route-codegen.js +80 -0
- package/dist/src/lib/plugins/route-codegen.mjs +52 -0
- package/dist/src/lib/plugins/route-scanner.cjs +189 -0
- package/dist/src/lib/plugins/route-scanner.d.ts +38 -0
- package/dist/src/lib/plugins/route-scanner.d.ts.map +1 -0
- package/dist/src/lib/plugins/route-scanner.js +215 -0
- package/dist/src/lib/plugins/route-scanner.mjs +158 -0
- package/dist/src/lib/plugins/vite.cjs +27 -0
- package/dist/src/lib/plugins/vite.d.ts +3 -0
- package/dist/src/lib/plugins/vite.d.ts.map +1 -0
- package/dist/src/lib/plugins/vite.js +1 -0
- package/dist/src/lib/plugins/vite.mjs +6 -0
- package/dist/src/lib/render/await.cjs +38 -0
- package/dist/src/lib/render/await.d.ts +26 -0
- package/dist/src/lib/render/await.d.ts.map +1 -0
- package/dist/src/lib/render/await.js +45 -0
- package/dist/src/lib/render/await.mjs +17 -0
- package/dist/src/lib/render/component.cjs +221 -0
- package/dist/src/lib/render/component.d.ts +296 -0
- package/dist/src/lib/render/component.d.ts.map +1 -0
- package/dist/src/lib/render/component.js +514 -0
- package/dist/src/lib/render/component.mjs +214 -0
- package/dist/src/lib/render/deferred.cjs +175 -0
- package/dist/src/lib/render/deferred.d.ts +36 -0
- package/dist/src/lib/render/deferred.d.ts.map +1 -0
- package/dist/src/lib/render/deferred.js +141 -0
- package/dist/src/lib/render/deferred.mjs +158 -0
- package/dist/src/lib/render/index.cjs +573 -0
- package/dist/src/lib/render/index.d.ts +98 -0
- package/dist/src/lib/render/index.d.ts.map +1 -0
- package/dist/src/lib/render/index.js +180 -0
- package/dist/src/lib/render/index.mjs +590 -0
- package/dist/src/lib/render/lazy.cjs +67 -0
- package/dist/src/lib/render/lazy.d.ts +49 -0
- package/dist/src/lib/render/lazy.d.ts.map +1 -0
- package/dist/src/lib/render/lazy.js +105 -0
- package/dist/src/lib/render/lazy.mjs +50 -0
- package/dist/src/lib/render/suspense.cjs +141 -0
- package/dist/src/lib/render/suspense.d.ts +65 -0
- package/dist/src/lib/render/suspense.d.ts.map +1 -0
- package/dist/src/lib/render/suspense.js +196 -0
- package/dist/src/lib/render/suspense.mjs +136 -0
- package/dist/src/lib/render/versions.cjs +35 -0
- package/dist/src/lib/render/versions.d.ts +2 -0
- package/dist/src/lib/render/versions.d.ts.map +1 -0
- package/dist/src/lib/render/versions.js +21 -0
- package/dist/src/lib/render/versions.mjs +14 -0
- package/dist/src/lib/router/data.cjs +228 -0
- package/dist/src/lib/router/data.d.ts +142 -0
- package/dist/src/lib/router/data.d.ts.map +1 -0
- package/dist/src/lib/router/data.js +258 -0
- package/dist/src/lib/router/data.mjs +214 -0
- package/dist/src/lib/router/index.cjs +921 -0
- package/dist/src/lib/router/index.d.ts +274 -0
- package/dist/src/lib/router/index.d.ts.map +1 -0
- package/dist/src/lib/router/index.js +904 -0
- package/dist/src/lib/router/index.mjs +938 -0
- package/dist/src/lib/router/scroll.cjs +79 -0
- package/dist/src/lib/router/scroll.d.ts +19 -0
- package/dist/src/lib/router/scroll.d.ts.map +1 -0
- package/dist/src/lib/router/scroll.js +68 -0
- package/dist/src/lib/router/scroll.mjs +58 -0
- package/dist/src/lib/router/transition.cjs +75 -0
- package/dist/src/lib/router/transition.d.ts +81 -0
- package/dist/src/lib/router/transition.d.ts.map +1 -0
- package/dist/src/lib/router/transition.js +136 -0
- package/dist/src/lib/router/transition.mjs +54 -0
- package/dist/src/lib/server/hydration.cjs +169 -0
- package/dist/src/lib/server/hydration.d.ts +198 -0
- package/dist/src/lib/server/hydration.d.ts.map +1 -0
- package/dist/src/lib/server/hydration.js +345 -0
- package/dist/src/lib/server/hydration.mjs +148 -0
- package/dist/src/lib/server/index.cjs +406 -0
- package/dist/src/lib/server/index.d.ts +115 -0
- package/dist/src/lib/server/index.d.ts.map +1 -0
- package/dist/src/lib/server/index.js +164 -0
- package/dist/src/lib/server/index.mjs +384 -0
- package/dist/src/lib/server/reactive.cjs +197 -0
- package/dist/src/lib/server/reactive.d.ts +239 -0
- package/dist/src/lib/server/reactive.d.ts.map +1 -0
- package/dist/src/lib/server/reactive.js +413 -0
- package/dist/src/lib/server/reactive.mjs +176 -0
- package/dist/src/lib/storage/cache.cjs +51 -0
- package/dist/src/lib/storage/cache.d.ts +18 -0
- package/dist/src/lib/storage/cache.d.ts.map +1 -0
- package/dist/src/lib/storage/cache.js +42 -0
- package/dist/src/lib/storage/cache.mjs +30 -0
- package/dist/src/lib/storage/index.cjs +246 -0
- package/dist/src/lib/storage/index.d.ts +83 -0
- package/dist/src/lib/storage/index.d.ts.map +1 -0
- package/dist/src/lib/storage/index.js +179 -0
- package/dist/src/lib/storage/index.mjs +231 -0
- package/dist/src/lib/storage/persisted.cjs +91 -0
- package/dist/src/lib/storage/persisted.d.ts +53 -0
- package/dist/src/lib/storage/persisted.d.ts.map +1 -0
- package/dist/src/lib/storage/persisted.js +75 -0
- package/dist/src/lib/storage/persisted.mjs +70 -0
- package/dist/src/lib/theme/color-scheme.cjs +281 -0
- package/dist/src/lib/theme/color-scheme.d.ts +61 -0
- package/dist/src/lib/theme/color-scheme.d.ts.map +1 -0
- package/dist/src/lib/theme/color-scheme.js +120 -0
- package/dist/src/lib/theme/color-scheme.mjs +265 -0
- package/dist/src/lib/theme/index.cjs +267 -0
- package/dist/src/lib/theme/index.d.ts +78 -0
- package/dist/src/lib/theme/index.d.ts.map +1 -0
- package/dist/src/lib/theme/index.js +135 -0
- package/dist/src/lib/theme/index.mjs +251 -0
- package/dist/src/lib/theme/provider.cjs +346 -0
- package/dist/src/lib/theme/provider.d.ts +34 -0
- package/dist/src/lib/theme/provider.d.ts.map +1 -0
- package/dist/src/lib/theme/provider.js +60 -0
- package/dist/src/lib/theme/provider.mjs +332 -0
- package/dist/src/lib/utils/index.cjs +209 -0
- package/dist/src/lib/utils/index.d.ts +286 -0
- package/dist/src/lib/utils/index.d.ts.map +1 -0
- package/dist/src/lib/utils/index.js +434 -0
- package/dist/src/lib/utils/index.mjs +188 -0
- package/dist/src/routes.cjs +37 -0
- package/dist/src/routes.d.ts +22 -0
- package/dist/src/routes.d.ts.map +1 -0
- package/dist/src/routes.js +20 -0
- package/dist/src/routes.mjs +17 -0
- package/dist/src/server.cjs +405 -0
- package/dist/src/server.d.ts +63 -0
- package/dist/src/server.d.ts.map +1 -0
- package/dist/src/server.js +62 -0
- package/dist/src/server.mjs +382 -0
- package/dist/src/utils.cjs +21 -0
- package/dist/src/utils.d.ts +10 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +9 -0
- package/dist/src/utils.mjs +4 -0
- package/dist/src/version.generated.cjs +26 -0
- package/dist/src/version.generated.d.ts +3 -0
- package/dist/src/version.generated.d.ts.map +1 -0
- package/dist/src/version.generated.js +3 -0
- package/dist/src/version.generated.mjs +5 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/package.json +164 -0
- package/src/index.ts +19 -0
- package/types/fluixi.d.ts +5 -0
- package/types/vinxi.d.ts +50 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/lib/server/hydration.ts
|
|
21
|
+
var hydration_exports = {};
|
|
22
|
+
__export(hydration_exports, {
|
|
23
|
+
cleanupHydration: () => cleanupHydration,
|
|
24
|
+
clearHydrationData: () => clearHydrationData,
|
|
25
|
+
clearHydrationDataKey: () => clearHydrationDataKey,
|
|
26
|
+
createHydratableResource: () => createHydratableResource,
|
|
27
|
+
deserializeHydrationData: () => deserializeHydrationData,
|
|
28
|
+
generateMarkerID: () => generateMarkerID,
|
|
29
|
+
getHydrationData: () => getHydrationData,
|
|
30
|
+
hasHydrationData: () => hasHydrationData,
|
|
31
|
+
hydrationMarker: () => hydrationMarker,
|
|
32
|
+
hydrationMarkerEnd: () => hydrationMarkerEnd,
|
|
33
|
+
hydrationMarkerStart: () => hydrationMarkerStart,
|
|
34
|
+
isClientEnvironment: () => isClientEnvironment,
|
|
35
|
+
isHydrating: () => isHydrating,
|
|
36
|
+
isServerEnvironment: () => isServerEnvironment,
|
|
37
|
+
serializeHydrationData: () => serializeHydrationData,
|
|
38
|
+
setHydrating: () => setHydrating,
|
|
39
|
+
setHydrationData: () => setHydrationData,
|
|
40
|
+
useHydrationData: () => useHydrationData
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(hydration_exports);
|
|
43
|
+
var import_dom = require("@fluixi/dom");
|
|
44
|
+
var hydrating = false;
|
|
45
|
+
var hydrationDataMap = /* @__PURE__ */ new Map();
|
|
46
|
+
var markerCounter = 0;
|
|
47
|
+
function isHydrating() {
|
|
48
|
+
return hydrating;
|
|
49
|
+
}
|
|
50
|
+
function setHydrating(state) {
|
|
51
|
+
hydrating = state;
|
|
52
|
+
}
|
|
53
|
+
function setHydrationData(key, data) {
|
|
54
|
+
hydrationDataMap.set(key, data);
|
|
55
|
+
}
|
|
56
|
+
function getHydrationData(key) {
|
|
57
|
+
return hydrationDataMap.get(key);
|
|
58
|
+
}
|
|
59
|
+
function hasHydrationData(key) {
|
|
60
|
+
return hydrationDataMap.has(key);
|
|
61
|
+
}
|
|
62
|
+
function clearHydrationData() {
|
|
63
|
+
hydrationDataMap.clear();
|
|
64
|
+
}
|
|
65
|
+
function clearHydrationDataKey(key) {
|
|
66
|
+
hydrationDataMap.delete(key);
|
|
67
|
+
}
|
|
68
|
+
function serializeHydrationData() {
|
|
69
|
+
if (hydrationDataMap.size === 0) {
|
|
70
|
+
return "";
|
|
71
|
+
}
|
|
72
|
+
const data = Object.fromEntries(hydrationDataMap);
|
|
73
|
+
const json = JSON.stringify(data);
|
|
74
|
+
return `<script type="application/json" id="__FLUIXI_HYDRATION__">${json}<\/script>`;
|
|
75
|
+
}
|
|
76
|
+
function deserializeHydrationData() {
|
|
77
|
+
if (typeof window === "undefined") {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
const script = document.getElementById("__FLUIXI_HYDRATION__");
|
|
81
|
+
if (!script || script.getAttribute("type") !== "application/json") {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const json = script.textContent || "{}";
|
|
86
|
+
const data = JSON.parse(json);
|
|
87
|
+
for (const [key, value] of Object.entries(data)) {
|
|
88
|
+
hydrationDataMap.set(key, value);
|
|
89
|
+
}
|
|
90
|
+
return true;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error("Failed to deserialize hydration data:", error);
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function generateMarkerID() {
|
|
97
|
+
return `h${markerCounter++}`;
|
|
98
|
+
}
|
|
99
|
+
function hydrationMarker(id) {
|
|
100
|
+
return `<!--#${id}-->`;
|
|
101
|
+
}
|
|
102
|
+
function hydrationMarkerStart(id) {
|
|
103
|
+
return `<!--#${id}-->`;
|
|
104
|
+
}
|
|
105
|
+
function hydrationMarkerEnd(id) {
|
|
106
|
+
return `<!--/${id}-->`;
|
|
107
|
+
}
|
|
108
|
+
function createHydratableResource(key, fetcher) {
|
|
109
|
+
return async () => {
|
|
110
|
+
if (isHydrating() || typeof window !== "undefined") {
|
|
111
|
+
const cached = getHydrationData(key);
|
|
112
|
+
if (cached !== void 0) {
|
|
113
|
+
return cached;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const data = await fetcher();
|
|
117
|
+
if (typeof window === "undefined") {
|
|
118
|
+
setHydrationData(key, data);
|
|
119
|
+
}
|
|
120
|
+
return data;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function useHydrationData(key, value) {
|
|
124
|
+
const hydrationData = getHydrationData(key);
|
|
125
|
+
if (hydrationData !== void 0) {
|
|
126
|
+
return hydrationData;
|
|
127
|
+
}
|
|
128
|
+
const computedValue = typeof value === "function" ? value() : value;
|
|
129
|
+
if (typeof window === "undefined") {
|
|
130
|
+
setHydrationData(key, computedValue);
|
|
131
|
+
}
|
|
132
|
+
return computedValue;
|
|
133
|
+
}
|
|
134
|
+
function cleanupHydration() {
|
|
135
|
+
if (typeof window === "undefined") {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const script = document.getElementById("__FLUIXI_HYDRATION__");
|
|
139
|
+
if (script) {
|
|
140
|
+
script.remove();
|
|
141
|
+
}
|
|
142
|
+
const walker = document.createTreeWalker(
|
|
143
|
+
document.body,
|
|
144
|
+
NodeFilter.SHOW_COMMENT,
|
|
145
|
+
null
|
|
146
|
+
);
|
|
147
|
+
const comments = [];
|
|
148
|
+
let node;
|
|
149
|
+
while (node = walker.nextNode()) {
|
|
150
|
+
const comment = node;
|
|
151
|
+
const text = comment.nodeValue || "";
|
|
152
|
+
if (text.startsWith("#") || text.startsWith("/")) {
|
|
153
|
+
comments.push(comment);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
comments.forEach((comment) => comment.remove());
|
|
157
|
+
clearHydrationData();
|
|
158
|
+
}
|
|
159
|
+
if (typeof window !== "undefined") {
|
|
160
|
+
window.addEventListener("load", () => {
|
|
161
|
+
setTimeout(cleanupHydration, 100);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
function isServerEnvironment() {
|
|
165
|
+
return (0, import_dom.isServer)();
|
|
166
|
+
}
|
|
167
|
+
function isClientEnvironment() {
|
|
168
|
+
return !(0, import_dom.isServer)();
|
|
169
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @fluixi/core/server/hydration
|
|
3
|
+
*
|
|
4
|
+
* Hydration:
|
|
5
|
+
* - DOM reused (no recreation)
|
|
6
|
+
* - No component execution (components ran on server)
|
|
7
|
+
* - Bindings reattached
|
|
8
|
+
* - Structural markers required
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Hydration data structure
|
|
12
|
+
*/
|
|
13
|
+
export interface HydrationData {
|
|
14
|
+
[key: string]: any;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check if currently hydrating
|
|
18
|
+
*
|
|
19
|
+
* During hydration, DOM is reused, not recreated
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import { isHydrating } from '@fluixi/core/server';
|
|
24
|
+
*
|
|
25
|
+
* if (isHydrating()) {
|
|
26
|
+
* // Reuse existing DOM
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function isHydrating(): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Set hydration state
|
|
33
|
+
*
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
export declare function setHydrating(state: boolean): void;
|
|
37
|
+
/**
|
|
38
|
+
* Store data for hydration
|
|
39
|
+
*
|
|
40
|
+
* On server, store data to serialize into HTML
|
|
41
|
+
* On client during hydration, this data is reused
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* import { setHydrationData } from '@fluixi/core/server';
|
|
46
|
+
*
|
|
47
|
+
* // On server
|
|
48
|
+
* setHydrationData('user', { id: 1, name: 'Alice' });
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function setHydrationData(key: string, data: any): void;
|
|
52
|
+
/**
|
|
53
|
+
* Get hydration data
|
|
54
|
+
*
|
|
55
|
+
* On client, retrieve data stored on server
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* import { getHydrationData } from '@fluixi/core/server';
|
|
60
|
+
*
|
|
61
|
+
* // On client
|
|
62
|
+
* const user = getHydrationData('user');
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare function getHydrationData(key: string): any;
|
|
66
|
+
/**
|
|
67
|
+
* Check if hydration data exists
|
|
68
|
+
*/
|
|
69
|
+
export declare function hasHydrationData(key: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Clear all hydration data
|
|
72
|
+
*
|
|
73
|
+
* @internal
|
|
74
|
+
*/
|
|
75
|
+
export declare function clearHydrationData(): void;
|
|
76
|
+
/**
|
|
77
|
+
* Clear specific hydration data
|
|
78
|
+
*/
|
|
79
|
+
export declare function clearHydrationDataKey(key: string): void;
|
|
80
|
+
/**
|
|
81
|
+
* Serialize hydration data to script tag
|
|
82
|
+
*
|
|
83
|
+
* Embed data in HTML for client hydration
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* import { serializeHydrationData } from '@fluixi/core/server';
|
|
88
|
+
*
|
|
89
|
+
* const html = await renderToString(() => App());
|
|
90
|
+
* const script = serializeHydrationData();
|
|
91
|
+
* return html + script;
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function serializeHydrationData(): string;
|
|
95
|
+
/**
|
|
96
|
+
* Deserialize hydration data from DOM
|
|
97
|
+
*
|
|
98
|
+
* On client, load data from script tag
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* import { deserializeHydrationData } from '@fluixi/core/server';
|
|
103
|
+
*
|
|
104
|
+
* // On client startup
|
|
105
|
+
* if (deserializeHydrationData()) {
|
|
106
|
+
* console.log('Hydration data loaded');
|
|
107
|
+
* }
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
export declare function deserializeHydrationData(): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Generate unique hydration marker ID
|
|
113
|
+
*
|
|
114
|
+
* @internal
|
|
115
|
+
*/
|
|
116
|
+
export declare function generateMarkerID(): string;
|
|
117
|
+
/**
|
|
118
|
+
* Create hydration marker
|
|
119
|
+
*
|
|
120
|
+
* Structural markers required for hydration points
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* import { hydrationMarker } from '@fluixi/core/server';
|
|
125
|
+
*
|
|
126
|
+
* const marker = hydrationMarker('component-1');
|
|
127
|
+
* // Returns: <!--h:component-1-->
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export declare function hydrationMarker(id: string): string;
|
|
131
|
+
/**
|
|
132
|
+
* Create start hydration marker
|
|
133
|
+
*/
|
|
134
|
+
export declare function hydrationMarkerStart(id: string): string;
|
|
135
|
+
/**
|
|
136
|
+
* Create end hydration marker
|
|
137
|
+
*/
|
|
138
|
+
export declare function hydrationMarkerEnd(id: string): string;
|
|
139
|
+
/**
|
|
140
|
+
* Create hydration-friendly resource
|
|
141
|
+
*
|
|
142
|
+
* Resources loaded on server are serialized
|
|
143
|
+
* On client, reused during hydration (no re-fetch)
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* import { createHydratableResource } from '@fluixi/core/server';
|
|
148
|
+
*
|
|
149
|
+
* const loadUser = createHydratableResource('user', async () => {
|
|
150
|
+
* const res = await fetch('/api/user');
|
|
151
|
+
* return res.json();
|
|
152
|
+
* });
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
export declare function createHydratableResource<T>(key: string, fetcher: () => Promise<T>): () => Promise<T>;
|
|
156
|
+
/**
|
|
157
|
+
* Use hydration data in component
|
|
158
|
+
*
|
|
159
|
+
* Components use hydration data to restore state
|
|
160
|
+
* without re-execution
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```typescript
|
|
164
|
+
* import { useHydrationData } from '@fluixi/core/server';
|
|
165
|
+
*
|
|
166
|
+
* const MyComponent = () => {
|
|
167
|
+
* const data = useHydrationData('my-data', { initial: true });
|
|
168
|
+
* return html`<div>${JSON.stringify(data)}</div>`;
|
|
169
|
+
* };
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
export declare function useHydrationData<T>(key: string, value: T | (() => T)): T;
|
|
173
|
+
/**
|
|
174
|
+
* Cleanup hydration artifacts from DOM
|
|
175
|
+
*
|
|
176
|
+
* After hydration, remove markers and serialized data
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* import { cleanupHydration } from '@fluixi/core/server';
|
|
181
|
+
*
|
|
182
|
+
* // After hydration completes
|
|
183
|
+
* cleanupHydration();
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
export declare function cleanupHydration(): void;
|
|
187
|
+
/**
|
|
188
|
+
* Whether this is a server render.
|
|
189
|
+
*
|
|
190
|
+
* Defers to `@fluixi/dom`, which keeps the flag on a realm singleton that
|
|
191
|
+
* `renderToString` sets. A local `typeof window` test disagrees with it inside a jsdom
|
|
192
|
+
* process, which is where server rendering is usually tested, and `router/data.ts`
|
|
193
|
+
* branches on this to decide whether a loader may touch the client.
|
|
194
|
+
*/
|
|
195
|
+
export declare function isServerEnvironment(): boolean;
|
|
196
|
+
/** Whether this is running in a browser, the negation of a server render. */
|
|
197
|
+
export declare function isClientEnvironment(): boolean;
|
|
198
|
+
//# sourceMappingURL=hydration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hydration.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/hydration.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AA2BD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAEjD;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI,CAE7D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAEjD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEvD;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAS/C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAuBlD;AAMD;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAErD;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACxB,MAAM,OAAO,CAAC,CAAC,CAAC,CAoBlB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAiBxE;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAiCvC;AAgBD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED,6EAA6E;AAC7E,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C"}
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @fluixi/core/server/hydration
|
|
3
|
+
*
|
|
4
|
+
* Hydration:
|
|
5
|
+
* - DOM reused (no recreation)
|
|
6
|
+
* - No component execution (components ran on server)
|
|
7
|
+
* - Bindings reattached
|
|
8
|
+
* - Structural markers required
|
|
9
|
+
*/
|
|
10
|
+
import { isServer as domIsServer } from '@fluixi/dom';
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// STATE
|
|
13
|
+
// ============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Global hydration flag
|
|
16
|
+
* Indicates if we're currently hydrating
|
|
17
|
+
*/
|
|
18
|
+
let hydrating = false;
|
|
19
|
+
/**
|
|
20
|
+
* Hydration data registry
|
|
21
|
+
* Stores data serialized on server and consumed on client
|
|
22
|
+
*/
|
|
23
|
+
const hydrationDataMap = new Map();
|
|
24
|
+
/**
|
|
25
|
+
* Hydration marker counter for unique IDs
|
|
26
|
+
*/
|
|
27
|
+
let markerCounter = 0;
|
|
28
|
+
// ============================================================================
|
|
29
|
+
// HYDRATION STATE
|
|
30
|
+
// ============================================================================
|
|
31
|
+
/**
|
|
32
|
+
* Check if currently hydrating
|
|
33
|
+
*
|
|
34
|
+
* During hydration, DOM is reused, not recreated
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* import { isHydrating } from '@fluixi/core/server';
|
|
39
|
+
*
|
|
40
|
+
* if (isHydrating()) {
|
|
41
|
+
* // Reuse existing DOM
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export function isHydrating() {
|
|
46
|
+
return hydrating;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Set hydration state
|
|
50
|
+
*
|
|
51
|
+
* @internal
|
|
52
|
+
*/
|
|
53
|
+
export function setHydrating(state) {
|
|
54
|
+
hydrating = state;
|
|
55
|
+
}
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// HYDRATION DATA MANAGEMENT
|
|
58
|
+
// ============================================================================
|
|
59
|
+
/**
|
|
60
|
+
* Store data for hydration
|
|
61
|
+
*
|
|
62
|
+
* On server, store data to serialize into HTML
|
|
63
|
+
* On client during hydration, this data is reused
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* import { setHydrationData } from '@fluixi/core/server';
|
|
68
|
+
*
|
|
69
|
+
* // On server
|
|
70
|
+
* setHydrationData('user', { id: 1, name: 'Alice' });
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export function setHydrationData(key, data) {
|
|
74
|
+
hydrationDataMap.set(key, data);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get hydration data
|
|
78
|
+
*
|
|
79
|
+
* On client, retrieve data stored on server
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* import { getHydrationData } from '@fluixi/core/server';
|
|
84
|
+
*
|
|
85
|
+
* // On client
|
|
86
|
+
* const user = getHydrationData('user');
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export function getHydrationData(key) {
|
|
90
|
+
return hydrationDataMap.get(key);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if hydration data exists
|
|
94
|
+
*/
|
|
95
|
+
export function hasHydrationData(key) {
|
|
96
|
+
return hydrationDataMap.has(key);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Clear all hydration data
|
|
100
|
+
*
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
103
|
+
export function clearHydrationData() {
|
|
104
|
+
hydrationDataMap.clear();
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Clear specific hydration data
|
|
108
|
+
*/
|
|
109
|
+
export function clearHydrationDataKey(key) {
|
|
110
|
+
hydrationDataMap.delete(key);
|
|
111
|
+
}
|
|
112
|
+
// ============================================================================
|
|
113
|
+
// SERIALIZATION
|
|
114
|
+
// ============================================================================
|
|
115
|
+
/**
|
|
116
|
+
* Serialize hydration data to script tag
|
|
117
|
+
*
|
|
118
|
+
* Embed data in HTML for client hydration
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```typescript
|
|
122
|
+
* import { serializeHydrationData } from '@fluixi/core/server';
|
|
123
|
+
*
|
|
124
|
+
* const html = await renderToString(() => App());
|
|
125
|
+
* const script = serializeHydrationData();
|
|
126
|
+
* return html + script;
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export function serializeHydrationData() {
|
|
130
|
+
if (hydrationDataMap.size === 0) {
|
|
131
|
+
return '';
|
|
132
|
+
}
|
|
133
|
+
const data = Object.fromEntries(hydrationDataMap);
|
|
134
|
+
const json = JSON.stringify(data);
|
|
135
|
+
return `<script type="application/json" id="__FLUIXI_HYDRATION__">${json}</script>`;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Deserialize hydration data from DOM
|
|
139
|
+
*
|
|
140
|
+
* On client, load data from script tag
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* import { deserializeHydrationData } from '@fluixi/core/server';
|
|
145
|
+
*
|
|
146
|
+
* // On client startup
|
|
147
|
+
* if (deserializeHydrationData()) {
|
|
148
|
+
* console.log('Hydration data loaded');
|
|
149
|
+
* }
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
export function deserializeHydrationData() {
|
|
153
|
+
if (typeof window === 'undefined') {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
const script = document.getElementById('__FLUIXI_HYDRATION__');
|
|
157
|
+
if (!script || script.getAttribute('type') !== 'application/json') {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
const json = script.textContent || '{}';
|
|
162
|
+
const data = JSON.parse(json);
|
|
163
|
+
for (const [key, value] of Object.entries(data)) {
|
|
164
|
+
hydrationDataMap.set(key, value);
|
|
165
|
+
}
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
console.error('Failed to deserialize hydration data:', error);
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// ============================================================================
|
|
174
|
+
// HYDRATION MARKERS
|
|
175
|
+
// ============================================================================
|
|
176
|
+
/**
|
|
177
|
+
* Generate unique hydration marker ID
|
|
178
|
+
*
|
|
179
|
+
* @internal
|
|
180
|
+
*/
|
|
181
|
+
export function generateMarkerID() {
|
|
182
|
+
return `h${markerCounter++}`;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Create hydration marker
|
|
186
|
+
*
|
|
187
|
+
* Structural markers required for hydration points
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```typescript
|
|
191
|
+
* import { hydrationMarker } from '@fluixi/core/server';
|
|
192
|
+
*
|
|
193
|
+
* const marker = hydrationMarker('component-1');
|
|
194
|
+
* // Returns: <!--h:component-1-->
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
export function hydrationMarker(id) {
|
|
198
|
+
return `<!--#${id}-->`;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Create start hydration marker
|
|
202
|
+
*/
|
|
203
|
+
export function hydrationMarkerStart(id) {
|
|
204
|
+
return `<!--#${id}-->`;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Create end hydration marker
|
|
208
|
+
*/
|
|
209
|
+
export function hydrationMarkerEnd(id) {
|
|
210
|
+
return `<!--/${id}-->`;
|
|
211
|
+
}
|
|
212
|
+
// ============================================================================
|
|
213
|
+
// RESOURCE HYDRATION
|
|
214
|
+
// ============================================================================
|
|
215
|
+
/**
|
|
216
|
+
* Create hydration-friendly resource
|
|
217
|
+
*
|
|
218
|
+
* Resources loaded on server are serialized
|
|
219
|
+
* On client, reused during hydration (no re-fetch)
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```typescript
|
|
223
|
+
* import { createHydratableResource } from '@fluixi/core/server';
|
|
224
|
+
*
|
|
225
|
+
* const loadUser = createHydratableResource('user', async () => {
|
|
226
|
+
* const res = await fetch('/api/user');
|
|
227
|
+
* return res.json();
|
|
228
|
+
* });
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
export function createHydratableResource(key, fetcher) {
|
|
232
|
+
return async () => {
|
|
233
|
+
// During hydration or on client, check for cached data
|
|
234
|
+
if (isHydrating() || typeof window !== 'undefined') {
|
|
235
|
+
const cached = getHydrationData(key);
|
|
236
|
+
if (cached !== undefined) {
|
|
237
|
+
return cached;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
// Server or no cache: fetch data
|
|
241
|
+
const data = await fetcher();
|
|
242
|
+
// On server, store for serialization
|
|
243
|
+
if (typeof window === 'undefined') {
|
|
244
|
+
setHydrationData(key, data);
|
|
245
|
+
}
|
|
246
|
+
return data;
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Use hydration data in component
|
|
251
|
+
*
|
|
252
|
+
* Components use hydration data to restore state
|
|
253
|
+
* without re-execution
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```typescript
|
|
257
|
+
* import { useHydrationData } from '@fluixi/core/server';
|
|
258
|
+
*
|
|
259
|
+
* const MyComponent = () => {
|
|
260
|
+
* const data = useHydrationData('my-data', { initial: true });
|
|
261
|
+
* return html`<div>${JSON.stringify(data)}</div>`;
|
|
262
|
+
* };
|
|
263
|
+
* ```
|
|
264
|
+
*/
|
|
265
|
+
export function useHydrationData(key, value) {
|
|
266
|
+
// Check for hydration data first
|
|
267
|
+
const hydrationData = getHydrationData(key);
|
|
268
|
+
if (hydrationData !== undefined) {
|
|
269
|
+
return hydrationData;
|
|
270
|
+
}
|
|
271
|
+
// Compute or use provided value
|
|
272
|
+
const computedValue = typeof value === 'function' ? value() : value;
|
|
273
|
+
// On server, store for serialization
|
|
274
|
+
if (typeof window === 'undefined') {
|
|
275
|
+
setHydrationData(key, computedValue);
|
|
276
|
+
}
|
|
277
|
+
return computedValue;
|
|
278
|
+
}
|
|
279
|
+
// ============================================================================
|
|
280
|
+
// CLEANUP
|
|
281
|
+
// ============================================================================
|
|
282
|
+
/**
|
|
283
|
+
* Cleanup hydration artifacts from DOM
|
|
284
|
+
*
|
|
285
|
+
* After hydration, remove markers and serialized data
|
|
286
|
+
*
|
|
287
|
+
* @example
|
|
288
|
+
* ```typescript
|
|
289
|
+
* import { cleanupHydration } from '@fluixi/core/server';
|
|
290
|
+
*
|
|
291
|
+
* // After hydration completes
|
|
292
|
+
* cleanupHydration();
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
export function cleanupHydration() {
|
|
296
|
+
if (typeof window === 'undefined') {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
// Remove hydration data script
|
|
300
|
+
const script = document.getElementById('__FLUIXI_HYDRATION__');
|
|
301
|
+
if (script) {
|
|
302
|
+
script.remove();
|
|
303
|
+
}
|
|
304
|
+
// Remove hydration markers (comments)
|
|
305
|
+
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_COMMENT, null);
|
|
306
|
+
const comments = [];
|
|
307
|
+
let node;
|
|
308
|
+
while ((node = walker.nextNode())) {
|
|
309
|
+
const comment = node;
|
|
310
|
+
const text = comment.nodeValue || '';
|
|
311
|
+
if (text.startsWith('#') || text.startsWith('/')) {
|
|
312
|
+
comments.push(comment);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
comments.forEach((comment) => comment.remove());
|
|
316
|
+
// Clear hydration data from memory
|
|
317
|
+
clearHydrationData();
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Auto-cleanup hydration on page load (client-side)
|
|
321
|
+
*/
|
|
322
|
+
if (typeof window !== 'undefined') {
|
|
323
|
+
window.addEventListener('load', () => {
|
|
324
|
+
// Delay cleanup to ensure hydration is complete
|
|
325
|
+
setTimeout(cleanupHydration, 100);
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
// ============================================================================
|
|
329
|
+
// ENVIRONMENT HELPERS
|
|
330
|
+
// ============================================================================
|
|
331
|
+
/**
|
|
332
|
+
* Whether this is a server render.
|
|
333
|
+
*
|
|
334
|
+
* Defers to `@fluixi/dom`, which keeps the flag on a realm singleton that
|
|
335
|
+
* `renderToString` sets. A local `typeof window` test disagrees with it inside a jsdom
|
|
336
|
+
* process, which is where server rendering is usually tested, and `router/data.ts`
|
|
337
|
+
* branches on this to decide whether a loader may touch the client.
|
|
338
|
+
*/
|
|
339
|
+
export function isServerEnvironment() {
|
|
340
|
+
return domIsServer();
|
|
341
|
+
}
|
|
342
|
+
/** Whether this is running in a browser, the negation of a server render. */
|
|
343
|
+
export function isClientEnvironment() {
|
|
344
|
+
return !domIsServer();
|
|
345
|
+
}
|