@lolyjs/core 0.2.0-alpha.15 → 0.2.0-alpha.16
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/README.md +1016 -842
- package/dist/{bootstrap-DgvWWDim.d.mts → bootstrap-BfGTMUkj.d.mts} +12 -0
- package/dist/{bootstrap-DgvWWDim.d.ts → bootstrap-BfGTMUkj.d.ts} +12 -0
- package/dist/cli.cjs +4336 -3067
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +4315 -3046
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +2066 -549
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +9 -79
- package/dist/index.d.ts +9 -79
- package/dist/index.js +2066 -549
- package/dist/index.js.map +1 -1
- package/dist/index.types-BPX6IVAC.d.mts +198 -0
- package/dist/index.types-BPX6IVAC.d.ts +198 -0
- package/dist/react/cache.cjs.map +1 -1
- package/dist/react/cache.d.mts +22 -2
- package/dist/react/cache.d.ts +22 -2
- package/dist/react/cache.js.map +1 -1
- package/dist/react/components.cjs.map +1 -1
- package/dist/react/components.js.map +1 -1
- package/dist/react/hooks.cjs.map +1 -1
- package/dist/react/hooks.js.map +1 -1
- package/dist/react/sockets.cjs.map +1 -1
- package/dist/react/sockets.js.map +1 -1
- package/dist/runtime.cjs +359 -95
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.mts +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +359 -95
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
package/dist/runtime.js
CHANGED
|
@@ -85,22 +85,158 @@ function matchRouteClient(pathWithSearch, routes) {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
// modules/runtime/client/metadata.ts
|
|
88
|
+
function getOrCreateMeta(selector, attributes) {
|
|
89
|
+
let meta = document.querySelector(selector);
|
|
90
|
+
if (!meta) {
|
|
91
|
+
meta = document.createElement("meta");
|
|
92
|
+
if (attributes.name) meta.name = attributes.name;
|
|
93
|
+
if (attributes.property) meta.setAttribute("property", attributes.property);
|
|
94
|
+
if (attributes.httpEquiv) meta.httpEquiv = attributes.httpEquiv;
|
|
95
|
+
document.head.appendChild(meta);
|
|
96
|
+
}
|
|
97
|
+
return meta;
|
|
98
|
+
}
|
|
99
|
+
function getOrCreateLink(rel, href) {
|
|
100
|
+
const selector = `link[rel="${rel}"]`;
|
|
101
|
+
let link = document.querySelector(selector);
|
|
102
|
+
if (!link) {
|
|
103
|
+
link = document.createElement("link");
|
|
104
|
+
link.rel = rel;
|
|
105
|
+
link.href = href;
|
|
106
|
+
document.head.appendChild(link);
|
|
107
|
+
} else {
|
|
108
|
+
link.href = href;
|
|
109
|
+
}
|
|
110
|
+
return link;
|
|
111
|
+
}
|
|
88
112
|
function applyMetadata(md) {
|
|
89
113
|
if (!md) return;
|
|
90
114
|
if (md.title) {
|
|
91
115
|
document.title = md.title;
|
|
92
116
|
}
|
|
93
117
|
if (md.description) {
|
|
94
|
-
|
|
95
|
-
'meta[name="description"]'
|
|
96
|
-
);
|
|
97
|
-
if (!meta) {
|
|
98
|
-
meta = document.createElement("meta");
|
|
99
|
-
meta.name = "description";
|
|
100
|
-
document.head.appendChild(meta);
|
|
101
|
-
}
|
|
118
|
+
const meta = getOrCreateMeta('meta[name="description"]', { name: "description" });
|
|
102
119
|
meta.content = md.description;
|
|
103
120
|
}
|
|
121
|
+
if (md.robots) {
|
|
122
|
+
const meta = getOrCreateMeta('meta[name="robots"]', { name: "robots" });
|
|
123
|
+
meta.content = md.robots;
|
|
124
|
+
}
|
|
125
|
+
if (md.themeColor) {
|
|
126
|
+
const meta = getOrCreateMeta('meta[name="theme-color"]', { name: "theme-color" });
|
|
127
|
+
meta.content = md.themeColor;
|
|
128
|
+
}
|
|
129
|
+
if (md.viewport) {
|
|
130
|
+
const meta = getOrCreateMeta('meta[name="viewport"]', { name: "viewport" });
|
|
131
|
+
meta.content = md.viewport;
|
|
132
|
+
}
|
|
133
|
+
if (md.canonical) {
|
|
134
|
+
getOrCreateLink("canonical", md.canonical);
|
|
135
|
+
}
|
|
136
|
+
if (md.openGraph) {
|
|
137
|
+
const og = md.openGraph;
|
|
138
|
+
if (og.title) {
|
|
139
|
+
const meta = getOrCreateMeta('meta[property="og:title"]', { property: "og:title" });
|
|
140
|
+
meta.content = og.title;
|
|
141
|
+
}
|
|
142
|
+
if (og.description) {
|
|
143
|
+
const meta = getOrCreateMeta('meta[property="og:description"]', { property: "og:description" });
|
|
144
|
+
meta.content = og.description;
|
|
145
|
+
}
|
|
146
|
+
if (og.type) {
|
|
147
|
+
const meta = getOrCreateMeta('meta[property="og:type"]', { property: "og:type" });
|
|
148
|
+
meta.content = og.type;
|
|
149
|
+
}
|
|
150
|
+
if (og.url) {
|
|
151
|
+
const meta = getOrCreateMeta('meta[property="og:url"]', { property: "og:url" });
|
|
152
|
+
meta.content = og.url;
|
|
153
|
+
}
|
|
154
|
+
if (og.image) {
|
|
155
|
+
if (typeof og.image === "string") {
|
|
156
|
+
const meta = getOrCreateMeta('meta[property="og:image"]', { property: "og:image" });
|
|
157
|
+
meta.content = og.image;
|
|
158
|
+
} else {
|
|
159
|
+
const meta = getOrCreateMeta('meta[property="og:image"]', { property: "og:image" });
|
|
160
|
+
meta.content = og.image.url;
|
|
161
|
+
if (og.image.width) {
|
|
162
|
+
const metaWidth = getOrCreateMeta('meta[property="og:image:width"]', { property: "og:image:width" });
|
|
163
|
+
metaWidth.content = String(og.image.width);
|
|
164
|
+
}
|
|
165
|
+
if (og.image.height) {
|
|
166
|
+
const metaHeight = getOrCreateMeta('meta[property="og:image:height"]', { property: "og:image:height" });
|
|
167
|
+
metaHeight.content = String(og.image.height);
|
|
168
|
+
}
|
|
169
|
+
if (og.image.alt) {
|
|
170
|
+
const metaAlt = getOrCreateMeta('meta[property="og:image:alt"]', { property: "og:image:alt" });
|
|
171
|
+
metaAlt.content = og.image.alt;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (og.siteName) {
|
|
176
|
+
const meta = getOrCreateMeta('meta[property="og:site_name"]', { property: "og:site_name" });
|
|
177
|
+
meta.content = og.siteName;
|
|
178
|
+
}
|
|
179
|
+
if (og.locale) {
|
|
180
|
+
const meta = getOrCreateMeta('meta[property="og:locale"]', { property: "og:locale" });
|
|
181
|
+
meta.content = og.locale;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (md.twitter) {
|
|
185
|
+
const twitter = md.twitter;
|
|
186
|
+
if (twitter.card) {
|
|
187
|
+
const meta = getOrCreateMeta('meta[name="twitter:card"]', { name: "twitter:card" });
|
|
188
|
+
meta.content = twitter.card;
|
|
189
|
+
}
|
|
190
|
+
if (twitter.title) {
|
|
191
|
+
const meta = getOrCreateMeta('meta[name="twitter:title"]', { name: "twitter:title" });
|
|
192
|
+
meta.content = twitter.title;
|
|
193
|
+
}
|
|
194
|
+
if (twitter.description) {
|
|
195
|
+
const meta = getOrCreateMeta('meta[name="twitter:description"]', { name: "twitter:description" });
|
|
196
|
+
meta.content = twitter.description;
|
|
197
|
+
}
|
|
198
|
+
if (twitter.image) {
|
|
199
|
+
const meta = getOrCreateMeta('meta[name="twitter:image"]', { name: "twitter:image" });
|
|
200
|
+
meta.content = twitter.image;
|
|
201
|
+
}
|
|
202
|
+
if (twitter.imageAlt) {
|
|
203
|
+
const meta = getOrCreateMeta('meta[name="twitter:image:alt"]', { name: "twitter:image:alt" });
|
|
204
|
+
meta.content = twitter.imageAlt;
|
|
205
|
+
}
|
|
206
|
+
if (twitter.site) {
|
|
207
|
+
const meta = getOrCreateMeta('meta[name="twitter:site"]', { name: "twitter:site" });
|
|
208
|
+
meta.content = twitter.site;
|
|
209
|
+
}
|
|
210
|
+
if (twitter.creator) {
|
|
211
|
+
const meta = getOrCreateMeta('meta[name="twitter:creator"]', { name: "twitter:creator" });
|
|
212
|
+
meta.content = twitter.creator;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (md.metaTags && Array.isArray(md.metaTags)) {
|
|
216
|
+
md.metaTags.forEach((tag) => {
|
|
217
|
+
let selector = "";
|
|
218
|
+
if (tag.name) {
|
|
219
|
+
selector = `meta[name="${tag.name}"]`;
|
|
220
|
+
} else if (tag.property) {
|
|
221
|
+
selector = `meta[property="${tag.property}"]`;
|
|
222
|
+
} else if (tag.httpEquiv) {
|
|
223
|
+
selector = `meta[http-equiv="${tag.httpEquiv}"]`;
|
|
224
|
+
}
|
|
225
|
+
if (selector) {
|
|
226
|
+
const meta = getOrCreateMeta(selector, {
|
|
227
|
+
name: tag.name,
|
|
228
|
+
property: tag.property,
|
|
229
|
+
httpEquiv: tag.httpEquiv
|
|
230
|
+
});
|
|
231
|
+
meta.content = tag.content;
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
if (md.links && Array.isArray(md.links)) {
|
|
236
|
+
md.links.forEach((link) => {
|
|
237
|
+
getOrCreateLink(link.rel, link.href);
|
|
238
|
+
});
|
|
239
|
+
}
|
|
104
240
|
}
|
|
105
241
|
|
|
106
242
|
// modules/runtime/client/AppShell.tsx
|
|
@@ -317,10 +453,15 @@ async function handleErrorRoute(nextUrl, json, errorRoute, setState) {
|
|
|
317
453
|
});
|
|
318
454
|
return true;
|
|
319
455
|
} catch (loadError) {
|
|
320
|
-
console.error(
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
456
|
+
console.error("\n\u274C [client] Error loading error route components:");
|
|
457
|
+
console.error(loadError);
|
|
458
|
+
if (loadError instanceof Error) {
|
|
459
|
+
console.error(` Message: ${loadError.message}`);
|
|
460
|
+
if (loadError.stack) {
|
|
461
|
+
console.error(` Stack: ${loadError.stack.split("\n").slice(0, 3).join("\n ")}`);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
console.error("\u{1F4A1} Falling back to full page reload\n");
|
|
324
465
|
window.location.href = nextUrl;
|
|
325
466
|
return false;
|
|
326
467
|
}
|
|
@@ -425,7 +566,11 @@ async function handleNormalRoute(nextUrl, json, routes, setState) {
|
|
|
425
566
|
searchParams: Object.fromEntries(url.searchParams.entries())
|
|
426
567
|
};
|
|
427
568
|
setRouterData(routerData);
|
|
428
|
-
const
|
|
569
|
+
const prefetched = prefetchedRoutes.get(matched.route);
|
|
570
|
+
const components = prefetched ? await prefetched : await matched.route.load();
|
|
571
|
+
if (!prefetched) {
|
|
572
|
+
prefetchedRoutes.set(matched.route, Promise.resolve(components));
|
|
573
|
+
}
|
|
429
574
|
window.scrollTo({
|
|
430
575
|
top: 0,
|
|
431
576
|
behavior: "smooth"
|
|
@@ -464,7 +609,7 @@ async function navigate(nextUrl, handlers, options) {
|
|
|
464
609
|
}
|
|
465
610
|
}
|
|
466
611
|
if (!ok) {
|
|
467
|
-
if (json
|
|
612
|
+
if (json?.redirect) {
|
|
468
613
|
window.location.href = json.redirect.destination;
|
|
469
614
|
return;
|
|
470
615
|
}
|
|
@@ -485,6 +630,47 @@ async function navigate(nextUrl, handlers, options) {
|
|
|
485
630
|
window.location.href = nextUrl;
|
|
486
631
|
}
|
|
487
632
|
}
|
|
633
|
+
var prefetchedRoutes = /* @__PURE__ */ new WeakMap();
|
|
634
|
+
function prefetchRoute(url, routes, notFoundRoute) {
|
|
635
|
+
const [pathname] = url.split("?");
|
|
636
|
+
const matched = matchRouteClient(pathname, routes);
|
|
637
|
+
if (!matched) {
|
|
638
|
+
if (notFoundRoute) {
|
|
639
|
+
const existing2 = prefetchedRoutes.get(notFoundRoute);
|
|
640
|
+
if (!existing2) {
|
|
641
|
+
const promise = notFoundRoute.load();
|
|
642
|
+
prefetchedRoutes.set(notFoundRoute, promise);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
const existing = prefetchedRoutes.get(matched.route);
|
|
648
|
+
if (!existing) {
|
|
649
|
+
const promise = matched.route.load();
|
|
650
|
+
prefetchedRoutes.set(matched.route, promise);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
function createHoverHandler(routes, notFoundRoute) {
|
|
654
|
+
return function handleHover(ev) {
|
|
655
|
+
try {
|
|
656
|
+
const target = ev.target;
|
|
657
|
+
if (!target) return;
|
|
658
|
+
const anchor = target.closest("a[href]");
|
|
659
|
+
if (!anchor) return;
|
|
660
|
+
const href = anchor.getAttribute("href");
|
|
661
|
+
if (!href) return;
|
|
662
|
+
if (href.startsWith("#")) return;
|
|
663
|
+
const url = new URL(href, window.location.href);
|
|
664
|
+
if (url.origin !== window.location.origin) return;
|
|
665
|
+
if (anchor.target && anchor.target !== "_self") return;
|
|
666
|
+
const nextUrl = url.pathname + url.search;
|
|
667
|
+
const currentUrl = window.location.pathname + window.location.search;
|
|
668
|
+
if (nextUrl === currentUrl) return;
|
|
669
|
+
prefetchRoute(nextUrl, routes, notFoundRoute);
|
|
670
|
+
} catch (error) {
|
|
671
|
+
}
|
|
672
|
+
};
|
|
673
|
+
}
|
|
488
674
|
function createClickHandler(navigate2) {
|
|
489
675
|
return function handleClick(ev) {
|
|
490
676
|
try {
|
|
@@ -595,17 +781,20 @@ function AppShell({
|
|
|
595
781
|
}
|
|
596
782
|
const handleClick = createClickHandler(handleNavigateInternal);
|
|
597
783
|
const handlePopState = createPopStateHandler(handleNavigateInternal);
|
|
784
|
+
const handleHover = createHoverHandler(routes, notFoundRoute);
|
|
598
785
|
window.addEventListener("click", handleClick, false);
|
|
599
786
|
window.addEventListener("popstate", handlePopState, false);
|
|
787
|
+
window.addEventListener("mouseover", handleHover, false);
|
|
600
788
|
return () => {
|
|
601
789
|
isMounted = false;
|
|
602
790
|
window.removeEventListener("click", handleClick, false);
|
|
603
791
|
window.removeEventListener("popstate", handlePopState, false);
|
|
792
|
+
window.removeEventListener("mouseover", handleHover, false);
|
|
604
793
|
};
|
|
605
|
-
}, []);
|
|
794
|
+
}, [routes, notFoundRoute]);
|
|
606
795
|
useEffect(() => {
|
|
607
796
|
const handleDataRefresh = () => {
|
|
608
|
-
const freshData = window
|
|
797
|
+
const freshData = window[WINDOW_DATA_KEY];
|
|
609
798
|
if (!freshData) return;
|
|
610
799
|
const currentPathname = window.location.pathname;
|
|
611
800
|
const freshPathname = freshData.pathname;
|
|
@@ -632,6 +821,91 @@ function AppShell({
|
|
|
632
821
|
return /* @__PURE__ */ jsx2(RouterContext.Provider, { value: { navigate: handleNavigate }, children: /* @__PURE__ */ jsx2(RouterView, { state }, routeKey) });
|
|
633
822
|
}
|
|
634
823
|
|
|
824
|
+
// modules/runtime/client/hot-reload.ts
|
|
825
|
+
function setupHotReload() {
|
|
826
|
+
const nodeEnv = process.env.NODE_ENV || "production";
|
|
827
|
+
const isDev = nodeEnv === "development";
|
|
828
|
+
console.log(`[hot-reload] NODE_ENV: ${nodeEnv}, isDev: ${isDev}`);
|
|
829
|
+
if (!isDev) {
|
|
830
|
+
console.log("[hot-reload] Skipping hot reload setup (not in development mode)");
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
console.log("[hot-reload] Setting up hot reload client...");
|
|
834
|
+
let eventSource = null;
|
|
835
|
+
let reloadTimeout = null;
|
|
836
|
+
let reconnectTimeout = null;
|
|
837
|
+
let reconnectAttempts = 0;
|
|
838
|
+
const MAX_RECONNECT_ATTEMPTS = 10;
|
|
839
|
+
const RECONNECT_DELAY = 1e3;
|
|
840
|
+
const RELOAD_DELAY = 100;
|
|
841
|
+
function connect() {
|
|
842
|
+
try {
|
|
843
|
+
if (eventSource) {
|
|
844
|
+
console.log("[hot-reload] Closing existing EventSource connection");
|
|
845
|
+
eventSource.close();
|
|
846
|
+
}
|
|
847
|
+
const endpoint = "/__fw/hot";
|
|
848
|
+
eventSource = new EventSource(endpoint);
|
|
849
|
+
eventSource.addEventListener("ping", (event) => {
|
|
850
|
+
if ("data" in event) {
|
|
851
|
+
console.log("[hot-reload] \u2705 Connected to hot reload server");
|
|
852
|
+
}
|
|
853
|
+
reconnectAttempts = 0;
|
|
854
|
+
});
|
|
855
|
+
eventSource.addEventListener("message", (event) => {
|
|
856
|
+
const data = event.data;
|
|
857
|
+
if (data && typeof data === "string" && data.startsWith("reload:")) {
|
|
858
|
+
const filePath = data.slice(7);
|
|
859
|
+
console.log(`[hot-reload] \u{1F4DD} File changed: ${filePath}, reloading...`);
|
|
860
|
+
if (reloadTimeout) {
|
|
861
|
+
clearTimeout(reloadTimeout);
|
|
862
|
+
}
|
|
863
|
+
reloadTimeout = setTimeout(() => {
|
|
864
|
+
try {
|
|
865
|
+
window.location.reload();
|
|
866
|
+
} catch (error) {
|
|
867
|
+
console.error("[hot-reload] \u274C Error reloading page:", error);
|
|
868
|
+
setTimeout(() => window.location.reload(), 100);
|
|
869
|
+
}
|
|
870
|
+
}, RELOAD_DELAY);
|
|
871
|
+
}
|
|
872
|
+
});
|
|
873
|
+
eventSource.onopen = () => {
|
|
874
|
+
reconnectAttempts = 0;
|
|
875
|
+
};
|
|
876
|
+
eventSource.onerror = (error) => {
|
|
877
|
+
const states = ["CONNECTING", "OPEN", "CLOSED"];
|
|
878
|
+
const state = states[eventSource?.readyState ?? 0] || "UNKNOWN";
|
|
879
|
+
if (eventSource?.readyState === EventSource.CONNECTING) {
|
|
880
|
+
console.log("[hot-reload] \u23F3 Still connecting...");
|
|
881
|
+
return;
|
|
882
|
+
} else if (eventSource?.readyState === EventSource.OPEN) {
|
|
883
|
+
console.warn("[hot-reload] \u26A0\uFE0F Connection error (but connection is open):", error);
|
|
884
|
+
} else {
|
|
885
|
+
console.warn(`[hot-reload] \u274C Connection closed (readyState: ${state})`);
|
|
886
|
+
if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
|
|
887
|
+
reconnectAttempts++;
|
|
888
|
+
const delay = RECONNECT_DELAY * reconnectAttempts;
|
|
889
|
+
if (reconnectTimeout) {
|
|
890
|
+
clearTimeout(reconnectTimeout);
|
|
891
|
+
}
|
|
892
|
+
reconnectTimeout = setTimeout(() => {
|
|
893
|
+
console.log(`[hot-reload] \u{1F504} Reconnecting... (attempt ${reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`);
|
|
894
|
+
connect();
|
|
895
|
+
}, delay);
|
|
896
|
+
} else {
|
|
897
|
+
console.error("[hot-reload] \u274C Max reconnect attempts reached. Please refresh the page manually.");
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
} catch (error) {
|
|
902
|
+
console.error("[hot-reload] \u274C Failed to create EventSource:", error);
|
|
903
|
+
console.error("[hot-reload] EventSource may not be supported in this browser.");
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
connect();
|
|
907
|
+
}
|
|
908
|
+
|
|
635
909
|
// modules/runtime/client/bootstrap.tsx
|
|
636
910
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
637
911
|
async function loadInitialRoute(initialUrl, initialData, routes, notFoundRoute, errorRoute) {
|
|
@@ -673,101 +947,91 @@ async function loadInitialRoute(initialUrl, initialData, routes, notFoundRoute,
|
|
|
673
947
|
props: initialData?.props ?? {}
|
|
674
948
|
};
|
|
675
949
|
}
|
|
676
|
-
function
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
950
|
+
function initializeRouterData(initialUrl, initialData) {
|
|
951
|
+
let routerData = getRouterData();
|
|
952
|
+
if (!routerData) {
|
|
953
|
+
const url = new URL(initialUrl, window.location.origin);
|
|
954
|
+
routerData = {
|
|
955
|
+
pathname: url.pathname,
|
|
956
|
+
params: initialData?.params || {},
|
|
957
|
+
searchParams: Object.fromEntries(url.searchParams.entries())
|
|
958
|
+
};
|
|
959
|
+
setRouterData(routerData);
|
|
681
960
|
}
|
|
961
|
+
}
|
|
962
|
+
async function hydrateInitialRoute(container, initialUrl, initialData, routes, notFoundRoute, errorRoute) {
|
|
682
963
|
try {
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
console.log("[hot-reload] Reloading page...");
|
|
696
|
-
window.location.reload();
|
|
697
|
-
}, 500);
|
|
698
|
-
}
|
|
699
|
-
});
|
|
700
|
-
eventSource.addEventListener("ping", () => {
|
|
701
|
-
console.log("[hot-reload] \u2713 Connected to hot reload server");
|
|
702
|
-
});
|
|
703
|
-
eventSource.onopen = () => {
|
|
704
|
-
console.log("[hot-reload] \u2713 SSE connection opened");
|
|
705
|
-
};
|
|
706
|
-
eventSource.onerror = (error) => {
|
|
707
|
-
const states = ["CONNECTING", "OPEN", "CLOSED"];
|
|
708
|
-
const state = states[eventSource.readyState] || "UNKNOWN";
|
|
709
|
-
if (eventSource.readyState === EventSource.CONNECTING) {
|
|
710
|
-
console.log("[hot-reload] Connecting...");
|
|
711
|
-
} else if (eventSource.readyState === EventSource.OPEN) {
|
|
712
|
-
console.warn("[hot-reload] Connection error (but connection is open):", error);
|
|
713
|
-
} else {
|
|
714
|
-
console.log("[hot-reload] Connection closed (readyState:", state, ")");
|
|
964
|
+
const initialState = await loadInitialRoute(
|
|
965
|
+
initialUrl,
|
|
966
|
+
initialData,
|
|
967
|
+
routes,
|
|
968
|
+
notFoundRoute,
|
|
969
|
+
errorRoute
|
|
970
|
+
);
|
|
971
|
+
if (initialData?.metadata) {
|
|
972
|
+
try {
|
|
973
|
+
applyMetadata(initialData.metadata);
|
|
974
|
+
} catch (metadataError) {
|
|
975
|
+
console.warn("[client] Error applying metadata:", metadataError);
|
|
715
976
|
}
|
|
716
|
-
}
|
|
977
|
+
}
|
|
978
|
+
hydrateRoot(
|
|
979
|
+
container,
|
|
980
|
+
/* @__PURE__ */ jsx3(
|
|
981
|
+
AppShell,
|
|
982
|
+
{
|
|
983
|
+
initialState,
|
|
984
|
+
routes,
|
|
985
|
+
notFoundRoute,
|
|
986
|
+
errorRoute
|
|
987
|
+
}
|
|
988
|
+
)
|
|
989
|
+
);
|
|
717
990
|
} catch (error) {
|
|
718
|
-
console.
|
|
991
|
+
console.error(
|
|
992
|
+
"[client] Error loading initial route components for",
|
|
993
|
+
initialUrl,
|
|
994
|
+
error
|
|
995
|
+
);
|
|
996
|
+
throw error;
|
|
719
997
|
}
|
|
720
998
|
}
|
|
721
999
|
function bootstrapClient(routes, notFoundRoute, errorRoute = null) {
|
|
722
|
-
console.log("[client] Bootstrap starting, setting up hot reload...");
|
|
723
1000
|
setupHotReload();
|
|
724
|
-
(async
|
|
725
|
-
const container = document.getElementById(APP_CONTAINER_ID);
|
|
726
|
-
const initialData = getWindowData();
|
|
727
|
-
if (!container) {
|
|
728
|
-
console.error(`Container #${APP_CONTAINER_ID} not found for hydration`);
|
|
729
|
-
return;
|
|
730
|
-
}
|
|
731
|
-
const initialUrl = window.location.pathname + window.location.search;
|
|
732
|
-
let routerData = getRouterData();
|
|
733
|
-
if (!routerData) {
|
|
734
|
-
const url = new URL(initialUrl, window.location.origin);
|
|
735
|
-
routerData = {
|
|
736
|
-
pathname: url.pathname,
|
|
737
|
-
params: initialData?.params || {},
|
|
738
|
-
searchParams: Object.fromEntries(url.searchParams.entries())
|
|
739
|
-
};
|
|
740
|
-
setRouterData(routerData);
|
|
741
|
-
}
|
|
1001
|
+
(async () => {
|
|
742
1002
|
try {
|
|
743
|
-
const
|
|
1003
|
+
const container = document.getElementById(APP_CONTAINER_ID);
|
|
1004
|
+
if (!container) {
|
|
1005
|
+
console.error(`
|
|
1006
|
+
\u274C [client] Hydration failed: Container #${APP_CONTAINER_ID} not found`);
|
|
1007
|
+
console.error("\u{1F4A1} This usually means:");
|
|
1008
|
+
console.error(" \u2022 The HTML structure doesn't match what React expects");
|
|
1009
|
+
console.error(" \u2022 The container was removed before hydration");
|
|
1010
|
+
console.error(" \u2022 There's a mismatch between SSR and client HTML\n");
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
1013
|
+
const initialData = getWindowData();
|
|
1014
|
+
const initialUrl = window.location.pathname + window.location.search;
|
|
1015
|
+
initializeRouterData(initialUrl, initialData);
|
|
1016
|
+
await hydrateInitialRoute(
|
|
1017
|
+
container,
|
|
744
1018
|
initialUrl,
|
|
745
1019
|
initialData,
|
|
746
1020
|
routes,
|
|
747
1021
|
notFoundRoute,
|
|
748
1022
|
errorRoute
|
|
749
1023
|
);
|
|
750
|
-
if (initialData?.metadata) {
|
|
751
|
-
applyMetadata(initialData.metadata);
|
|
752
|
-
}
|
|
753
|
-
hydrateRoot(
|
|
754
|
-
container,
|
|
755
|
-
/* @__PURE__ */ jsx3(
|
|
756
|
-
AppShell,
|
|
757
|
-
{
|
|
758
|
-
initialState,
|
|
759
|
-
routes,
|
|
760
|
-
notFoundRoute,
|
|
761
|
-
errorRoute
|
|
762
|
-
}
|
|
763
|
-
)
|
|
764
|
-
);
|
|
765
1024
|
} catch (error) {
|
|
766
|
-
console.error(
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
error
|
|
770
|
-
|
|
1025
|
+
console.error("\n\u274C [client] Fatal error during bootstrap:");
|
|
1026
|
+
console.error(error);
|
|
1027
|
+
if (error instanceof Error) {
|
|
1028
|
+
console.error("\nError details:");
|
|
1029
|
+
console.error(` Message: ${error.message}`);
|
|
1030
|
+
if (error.stack) {
|
|
1031
|
+
console.error(` Stack: ${error.stack}`);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
console.error("\n\u{1F4A1} Attempting page reload to recover...\n");
|
|
771
1035
|
window.location.reload();
|
|
772
1036
|
}
|
|
773
1037
|
})();
|