@absolutejs/absolute 0.19.0-beta.782 → 0.19.0-beta.784
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/dist/angular/browser.js +57 -9801
- package/dist/angular/browser.js.map +4 -246
- package/dist/angular/index.js +61 -14880
- package/dist/angular/index.js.map +4 -282
- package/dist/angular/server.js +46 -5613
- package/dist/angular/server.js.map +3 -52
- package/dist/build.js +45 -17902
- package/dist/build.js.map +3 -100
- package/dist/chunk-102fp7xe.js +63 -0
- package/dist/chunk-102fp7xe.js.map +10 -0
- package/dist/chunk-11zpfqz6.js +19 -0
- package/dist/chunk-11zpfqz6.js.map +10 -0
- package/dist/chunk-1e9vsfyh.js +100 -0
- package/dist/chunk-1e9vsfyh.js.map +10 -0
- package/dist/chunk-25v9t56f.js +29 -0
- package/dist/chunk-25v9t56f.js.map +11 -0
- package/dist/chunk-2f21eenc.js +21 -0
- package/dist/chunk-2f21eenc.js.map +10 -0
- package/dist/chunk-2ga2znex.js +13 -0
- package/dist/chunk-2ga2znex.js.map +9 -0
- package/dist/chunk-30yrw0f6.js +33 -0
- package/dist/chunk-30yrw0f6.js.map +10 -0
- package/dist/chunk-3c7mpj3m.js +784 -0
- package/dist/chunk-3c7mpj3m.js.map +10 -0
- package/dist/chunk-3g91wb4f.js +358 -0
- package/dist/chunk-3g91wb4f.js.map +10 -0
- package/dist/chunk-3yjzpcne.js +34 -0
- package/dist/chunk-3yjzpcne.js.map +10 -0
- package/dist/chunk-4bq79t8v.js +136 -0
- package/dist/chunk-4bq79t8v.js.map +10 -0
- package/dist/chunk-4d39r92n.js +81 -0
- package/dist/chunk-4d39r92n.js.map +10 -0
- package/dist/chunk-4m75s5xf.js +184 -0
- package/dist/chunk-4m75s5xf.js.map +11 -0
- package/dist/chunk-5003emhv.js +17 -0
- package/dist/chunk-5003emhv.js.map +10 -0
- package/dist/chunk-5fhp1jap.js +9169 -0
- package/dist/chunk-5fhp1jap.js.map +236 -0
- package/dist/chunk-6fkgm9s5.js +569 -0
- package/dist/chunk-6fkgm9s5.js.map +10 -0
- package/dist/chunk-6pdj08z3.js +73 -0
- package/dist/chunk-6pdj08z3.js.map +12 -0
- package/dist/chunk-6qjbrt0k.js +13 -0
- package/dist/chunk-6qjbrt0k.js.map +9 -0
- package/dist/chunk-6sccb4jr.js +14 -0
- package/dist/chunk-6sccb4jr.js.map +9 -0
- package/dist/chunk-73brtyw5.js +16 -0
- package/dist/chunk-73brtyw5.js.map +9 -0
- package/dist/chunk-77cqkarb.js +25 -0
- package/dist/chunk-77cqkarb.js.map +9 -0
- package/dist/chunk-798spvzv.js +50 -0
- package/dist/chunk-798spvzv.js.map +10 -0
- package/dist/chunk-7fw6x3js.js +131 -0
- package/dist/chunk-7fw6x3js.js.map +11 -0
- package/dist/chunk-7kjj42xm.js +11 -0
- package/dist/chunk-7kjj42xm.js.map +10 -0
- package/dist/chunk-851whwc7.js +17 -0
- package/dist/chunk-851whwc7.js.map +10 -0
- package/dist/chunk-85n68sy6.js +103 -0
- package/dist/chunk-85n68sy6.js.map +10 -0
- package/dist/chunk-8feq2qek.js +17 -0
- package/dist/chunk-8feq2qek.js.map +9 -0
- package/dist/chunk-8kcfffry.js +35 -0
- package/dist/chunk-8kcfffry.js.map +10 -0
- package/dist/chunk-93sqk7be.js +139 -0
- package/dist/chunk-93sqk7be.js.map +12 -0
- package/dist/chunk-97572s32.js +262 -0
- package/dist/chunk-97572s32.js.map +12 -0
- package/dist/chunk-9a307ca6.js +1742 -0
- package/dist/chunk-9a307ca6.js.map +11 -0
- package/dist/chunk-9c5tj4k3.js +130 -0
- package/dist/chunk-9c5tj4k3.js.map +10 -0
- package/dist/chunk-9xrsjeem.js +12 -0
- package/dist/chunk-9xrsjeem.js.map +9 -0
- package/dist/chunk-a9mvyp04.js +87 -0
- package/dist/chunk-a9mvyp04.js.map +10 -0
- package/dist/chunk-b3gbnrwe.js +21 -0
- package/dist/chunk-b3gbnrwe.js.map +10 -0
- package/dist/chunk-bmgqm774.js +65 -0
- package/dist/chunk-bmgqm774.js.map +9 -0
- package/dist/chunk-bxfghpma.js +69 -0
- package/dist/chunk-bxfghpma.js.map +10 -0
- package/dist/chunk-c1jfjnka.js +74 -0
- package/dist/chunk-c1jfjnka.js.map +10 -0
- package/dist/chunk-cbkrwmvh.js +80 -0
- package/dist/chunk-cbkrwmvh.js.map +10 -0
- package/dist/chunk-cdxd7sy2.js +71 -0
- package/dist/chunk-cdxd7sy2.js.map +10 -0
- package/dist/chunk-cg95827x.js +21 -0
- package/dist/chunk-cg95827x.js.map +10 -0
- package/dist/chunk-d9c0am65.js +12 -0
- package/dist/chunk-d9c0am65.js.map +10 -0
- package/dist/chunk-daqghmg8.js +12 -0
- package/dist/chunk-daqghmg8.js.map +9 -0
- package/dist/chunk-dr9yqsdb.js +203 -0
- package/dist/chunk-dr9yqsdb.js.map +10 -0
- package/dist/chunk-e8eecyrq.js +244 -0
- package/dist/chunk-e8eecyrq.js.map +10 -0
- package/dist/chunk-ex2hxe0v.js +160 -0
- package/dist/chunk-ex2hxe0v.js.map +11 -0
- package/dist/chunk-ey5hs6x6.js +253 -0
- package/dist/chunk-ey5hs6x6.js.map +11 -0
- package/dist/chunk-fak944et.js +91 -0
- package/dist/chunk-fak944et.js.map +10 -0
- package/dist/chunk-fygx2ymm.js +118 -0
- package/dist/chunk-fygx2ymm.js.map +12 -0
- package/dist/chunk-g15qj669.js +271 -0
- package/dist/chunk-g15qj669.js.map +11 -0
- package/dist/chunk-g3j22qf6.js +51 -0
- package/dist/chunk-g3j22qf6.js.map +9 -0
- package/dist/chunk-gd6wmknh.js +121 -0
- package/dist/chunk-gd6wmknh.js.map +11 -0
- package/dist/chunk-gf0ygptk.js +85 -0
- package/dist/chunk-gf0ygptk.js.map +11 -0
- package/dist/chunk-gq0zxpm0.js +90 -0
- package/dist/chunk-gq0zxpm0.js.map +10 -0
- package/dist/chunk-gytkmthr.js +220 -0
- package/dist/chunk-gytkmthr.js.map +10 -0
- package/dist/chunk-h5bbfn3n.js +28 -0
- package/dist/chunk-h5bbfn3n.js.map +11 -0
- package/dist/chunk-h6mye9r3.js +93 -0
- package/dist/chunk-h6mye9r3.js.map +10 -0
- package/dist/chunk-hcsmxw1v.js +85 -0
- package/dist/chunk-hcsmxw1v.js.map +10 -0
- package/dist/chunk-hep68ja7.js +4444 -0
- package/dist/chunk-hep68ja7.js.map +29 -0
- package/dist/chunk-hhqh49fz.js +149 -0
- package/dist/chunk-hhqh49fz.js.map +10 -0
- package/dist/chunk-hyjs4bqs.js +8 -0
- package/dist/chunk-hyjs4bqs.js.map +10 -0
- package/dist/chunk-hza0n8qm.js +20 -0
- package/dist/chunk-hza0n8qm.js.map +9 -0
- package/dist/chunk-jn91vzkh.js +66 -0
- package/dist/chunk-jn91vzkh.js.map +10 -0
- package/dist/chunk-jwxt8gnp.js +13 -0
- package/dist/chunk-jwxt8gnp.js.map +9 -0
- package/dist/chunk-kk8w9rh5.js +195 -0
- package/dist/chunk-kk8w9rh5.js.map +10 -0
- package/dist/chunk-kndkjsya.js +261 -0
- package/dist/chunk-kndkjsya.js.map +10 -0
- package/dist/chunk-kvq01j35.js +36 -0
- package/dist/chunk-kvq01j35.js.map +10 -0
- package/dist/chunk-mbazhahf.js +60 -0
- package/dist/chunk-mbazhahf.js.map +10 -0
- package/dist/chunk-mgfwq18r.js +15 -0
- package/dist/chunk-mgfwq18r.js.map +9 -0
- package/dist/chunk-mtgf69xn.js +88 -0
- package/dist/chunk-mtgf69xn.js.map +10 -0
- package/dist/chunk-nehhtthw.js +225 -0
- package/dist/chunk-nehhtthw.js.map +10 -0
- package/dist/chunk-nhzf4az4.js +149 -0
- package/dist/chunk-nhzf4az4.js.map +10 -0
- package/dist/chunk-p5504p14.js +16 -0
- package/dist/chunk-p5504p14.js.map +10 -0
- package/dist/chunk-pnscgw95.js +90 -0
- package/dist/chunk-pnscgw95.js.map +10 -0
- package/dist/chunk-pvpp4pvs.js +17 -0
- package/dist/chunk-pvpp4pvs.js.map +10 -0
- package/dist/chunk-qh75agse.js +95 -0
- package/dist/chunk-qh75agse.js.map +10 -0
- package/dist/chunk-qk8kd3hr.js +526 -0
- package/dist/chunk-qk8kd3hr.js.map +12 -0
- package/dist/chunk-qxq2zcty.js +52 -0
- package/dist/chunk-qxq2zcty.js.map +10 -0
- package/dist/chunk-r7jmgqnw.js +114 -0
- package/dist/chunk-r7jmgqnw.js.map +10 -0
- package/dist/chunk-s6defjk2.js +116 -0
- package/dist/chunk-s6defjk2.js.map +10 -0
- package/dist/chunk-sd39p726.js +619 -0
- package/dist/chunk-sd39p726.js.map +10 -0
- package/dist/chunk-smgj0epn.js +18 -0
- package/dist/chunk-smgj0epn.js.map +9 -0
- package/dist/chunk-swrnzs4c.js +63 -0
- package/dist/chunk-swrnzs4c.js.map +10 -0
- package/dist/chunk-t81a331y.js +27 -0
- package/dist/chunk-t81a331y.js.map +10 -0
- package/dist/chunk-tfe3sb44.js +33 -0
- package/dist/chunk-tfe3sb44.js.map +10 -0
- package/dist/chunk-tx9edm1x.js +34 -0
- package/dist/chunk-tx9edm1x.js.map +10 -0
- package/dist/chunk-vkrpm7kc.js +247 -0
- package/dist/chunk-vkrpm7kc.js.map +12 -0
- package/dist/chunk-vvz7dcvq.js +434 -0
- package/dist/chunk-vvz7dcvq.js.map +13 -0
- package/dist/chunk-w3m4m5we.js +4925 -0
- package/dist/chunk-w3m4m5we.js.map +12 -0
- package/dist/chunk-wrxtn9ve.js +18 -0
- package/dist/chunk-wrxtn9ve.js.map +10 -0
- package/dist/chunk-xpkjbmd3.js +428 -0
- package/dist/chunk-xpkjbmd3.js.map +14 -0
- package/dist/chunk-xrmjy8kk.js +454 -0
- package/dist/chunk-xrmjy8kk.js.map +10 -0
- package/dist/chunk-xw0tx842.js +13 -0
- package/dist/chunk-xw0tx842.js.map +9 -0
- package/dist/chunk-xx5b6b9m.js +69 -0
- package/dist/chunk-xx5b6b9m.js.map +10 -0
- package/dist/chunk-xz1kdswj.js +21 -0
- package/dist/chunk-xz1kdswj.js.map +9 -0
- package/dist/chunk-xzvy9hr4.js +377 -0
- package/dist/chunk-xzvy9hr4.js.map +10 -0
- package/dist/chunk-yfqhr31t.js +39 -0
- package/dist/chunk-yfqhr31t.js.map +9 -0
- package/dist/chunk-ygzd5s4z.js +184 -0
- package/dist/chunk-ygzd5s4z.js.map +10 -0
- package/dist/chunk-ywjn0rad.js +14 -0
- package/dist/chunk-ywjn0rad.js.map +9 -0
- package/dist/chunk-z9nvhm6r.js +13 -0
- package/dist/chunk-z9nvhm6r.js.map +9 -0
- package/dist/chunk-zhmvdpk6.js +15 -0
- package/dist/chunk-zhmvdpk6.js.map +9 -0
- package/dist/cli/index.js +6 -3
- package/dist/client/index.js +32 -1112
- package/dist/client/index.js.map +4 -22
- package/dist/core/streamingSlotRegistrar.js +11 -108
- package/dist/core/streamingSlotRegistrar.js.map +3 -4
- package/dist/core/streamingSlotRegistry.js +7 -169
- package/dist/core/streamingSlotRegistry.js.map +3 -5
- package/dist/index.js +537 -19714
- package/dist/index.js.map +3 -117
- package/dist/islands/browser.js +9 -228
- package/dist/islands/browser.js.map +4 -9
- package/dist/islands/index.js +18 -1900
- package/dist/islands/index.js.map +3 -28
- package/dist/react/browser.js +12 -328
- package/dist/react/browser.js.map +4 -12
- package/dist/react/components/index.js +16 -167
- package/dist/react/components/index.js.map +3 -6
- package/dist/react/hooks/index.js +8 -183
- package/dist/react/hooks/index.js.map +3 -7
- package/dist/react/index.js +37 -3619
- package/dist/react/index.js.map +4 -46
- package/dist/react/jsxDevRuntimeCompat.js +2 -61
- package/dist/react/jsxDevRuntimeCompat.js.map +2 -2
- package/dist/react/server.js +18 -1789
- package/dist/react/server.js.map +3 -21
- package/dist/src/build/stylePreprocessor.d.ts +3 -0
- package/dist/src/core/index.d.ts +0 -2
- package/dist/svelte/browser.js +12 -247
- package/dist/svelte/browser.js.map +3 -10
- package/dist/svelte/index.js +38 -3724
- package/dist/svelte/index.js.map +4 -48
- package/dist/svelte/server.js +22 -2701
- package/dist/svelte/server.js.map +3 -27
- package/dist/vue/browser.js +12 -348
- package/dist/vue/browser.js.map +4 -12
- package/dist/vue/components/Image.js +7 -240
- package/dist/vue/components/Image.js.map +3 -6
- package/dist/vue/components/index.js +11 -544
- package/dist/vue/components/index.js.map +3 -9
- package/dist/vue/index.js +53 -4204
- package/dist/vue/index.js.map +4 -51
- package/dist/vue/server.js +18 -1849
- package/dist/vue/server.js.map +3 -21
- package/package.json +7 -7
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import"./chunk-bmgqm774.js";
|
|
3
|
+
|
|
4
|
+
// src/core/prerender.ts
|
|
5
|
+
import { mkdirSync, readFileSync } from "fs";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
var SERVER_OUTPUT_LIMIT = 4000;
|
|
8
|
+
var STARTUP_POLL_INTERVAL_MS = 100;
|
|
9
|
+
var DEFAULT_STARTUP_TIMEOUT_MS = 30000;
|
|
10
|
+
var PRERENDER_BYPASS_HEADER = "X-Absolute-Prerender-Bypass";
|
|
11
|
+
var routeToFilename = (route) => route === "/" ? "index.html" : `${route.slice(1).replace(/\//g, "-")}.html`;
|
|
12
|
+
var writeTimestamp = async (htmlPath) => {
|
|
13
|
+
const metaPath = htmlPath.replace(/\.html$/, ".meta");
|
|
14
|
+
await Bun.write(metaPath, String(Date.now()));
|
|
15
|
+
};
|
|
16
|
+
var readTimestamp = (htmlPath) => {
|
|
17
|
+
const metaPath = htmlPath.replace(/\.html$/, ".meta");
|
|
18
|
+
try {
|
|
19
|
+
const content = readFileSync(metaPath, "utf-8");
|
|
20
|
+
return Number(content) || 0;
|
|
21
|
+
} catch {
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var extractLinks = (html, visited) => {
|
|
26
|
+
const links = [];
|
|
27
|
+
const linkRegex = /href=["'](\/[^"']*?)["']/g;
|
|
28
|
+
let match;
|
|
29
|
+
while ((match = linkRegex.exec(html)) !== null) {
|
|
30
|
+
const href = match[1] ?? "";
|
|
31
|
+
if (!href || href.includes(".") || href.includes("#") || visited.has(href))
|
|
32
|
+
continue;
|
|
33
|
+
links.push(href);
|
|
34
|
+
}
|
|
35
|
+
return links;
|
|
36
|
+
};
|
|
37
|
+
var fetchRoute = async (baseUrl, path) => {
|
|
38
|
+
const res = await fetch(`${baseUrl}${path}`, { redirect: "manual" });
|
|
39
|
+
if (!res.ok)
|
|
40
|
+
return null;
|
|
41
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
42
|
+
if (!contentType.includes("text/html"))
|
|
43
|
+
return null;
|
|
44
|
+
return res.text();
|
|
45
|
+
};
|
|
46
|
+
var crawlRoutes = async (baseUrl) => {
|
|
47
|
+
const visited = new Set;
|
|
48
|
+
const queue = ["/"];
|
|
49
|
+
const routes = [];
|
|
50
|
+
const crawlNextRoute = async () => {
|
|
51
|
+
const path = queue.shift();
|
|
52
|
+
if (!path) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (visited.has(path)) {
|
|
56
|
+
await crawlNextRoute();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
visited.add(path);
|
|
60
|
+
const html = await fetchRoute(baseUrl, path).catch(() => null);
|
|
61
|
+
if (!html) {
|
|
62
|
+
await crawlNextRoute();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
routes.push(path);
|
|
66
|
+
queue.push(...extractLinks(html, visited));
|
|
67
|
+
await crawlNextRoute();
|
|
68
|
+
};
|
|
69
|
+
await crawlNextRoute();
|
|
70
|
+
return routes;
|
|
71
|
+
};
|
|
72
|
+
var rerenderRoute = async (route, port, prerenderDir) => {
|
|
73
|
+
try {
|
|
74
|
+
const res = await fetch(`http://localhost:${port}${route}`, {
|
|
75
|
+
headers: { [PRERENDER_BYPASS_HEADER]: "1" },
|
|
76
|
+
redirect: "manual"
|
|
77
|
+
});
|
|
78
|
+
if (!res.ok)
|
|
79
|
+
return false;
|
|
80
|
+
const html = await res.text();
|
|
81
|
+
const fileName = routeToFilename(route);
|
|
82
|
+
const filePath = join(prerenderDir, fileName);
|
|
83
|
+
await Bun.write(filePath, html);
|
|
84
|
+
await writeTimestamp(filePath);
|
|
85
|
+
return true;
|
|
86
|
+
} catch {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
var prerenderRoute = async (baseUrl, route, prerenderDir, result, log) => {
|
|
91
|
+
const res = await fetch(`${baseUrl}${route}`, {
|
|
92
|
+
redirect: "manual"
|
|
93
|
+
}).catch(() => null);
|
|
94
|
+
if (!res) {
|
|
95
|
+
log?.(` Failed to pre-render ${route}`);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (!res.ok) {
|
|
99
|
+
log?.(` Skipped ${route} (HTTP ${res.status})`);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
103
|
+
if (!contentType.includes("text/html")) {
|
|
104
|
+
log?.(` Skipped ${route} (non-HTML response)`);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const html = await res.text();
|
|
108
|
+
const fileName = routeToFilename(route);
|
|
109
|
+
const filePath = join(prerenderDir, fileName);
|
|
110
|
+
await Bun.write(filePath, html);
|
|
111
|
+
await writeTimestamp(filePath);
|
|
112
|
+
result.routes.set(route, filePath);
|
|
113
|
+
log?.(` Pre-rendered ${route} \u2192 ${fileName} (${html.length} bytes)`);
|
|
114
|
+
};
|
|
115
|
+
var prerender = async (port, outDir, staticConfig, log) => {
|
|
116
|
+
const prerenderDir = join(outDir, "_prerendered");
|
|
117
|
+
mkdirSync(prerenderDir, { recursive: true });
|
|
118
|
+
const baseUrl = `http://localhost:${port}`;
|
|
119
|
+
let routes;
|
|
120
|
+
if (staticConfig.routes === "all") {
|
|
121
|
+
log?.("Crawling routes...");
|
|
122
|
+
routes = await crawlRoutes(baseUrl);
|
|
123
|
+
} else {
|
|
124
|
+
({ routes } = staticConfig);
|
|
125
|
+
}
|
|
126
|
+
const result = {
|
|
127
|
+
dir: prerenderDir,
|
|
128
|
+
routes: new Map
|
|
129
|
+
};
|
|
130
|
+
await routes.reduce((chain, route) => chain.then(() => prerenderRoute(baseUrl, route, prerenderDir, result, log)), Promise.resolve());
|
|
131
|
+
return result;
|
|
132
|
+
};
|
|
133
|
+
var getStartupTimeoutMs = () => {
|
|
134
|
+
const rawTimeout = Bun.env.ABSOLUTE_PRERENDER_STARTUP_TIMEOUT_MS;
|
|
135
|
+
const parsedTimeout = rawTimeout ? Number(rawTimeout) : NaN;
|
|
136
|
+
return Number.isFinite(parsedTimeout) && parsedTimeout > 0 ? parsedTimeout : DEFAULT_STARTUP_TIMEOUT_MS;
|
|
137
|
+
};
|
|
138
|
+
var waitForServerReady = async (port) => {
|
|
139
|
+
const deadline = performance.now() + getStartupTimeoutMs();
|
|
140
|
+
const pollServer = async () => {
|
|
141
|
+
if (performance.now() >= deadline) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
if (await probePrerenderServer(port)) {
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
await Bun.sleep(STARTUP_POLL_INTERVAL_MS);
|
|
148
|
+
return pollServer();
|
|
149
|
+
};
|
|
150
|
+
return pollServer();
|
|
151
|
+
};
|
|
152
|
+
var probePrerenderServer = async (port) => {
|
|
153
|
+
const res = await fetch(`http://localhost:${port}/`).catch(() => null);
|
|
154
|
+
if (!res) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
await res.body?.cancel().catch(() => {
|
|
158
|
+
return;
|
|
159
|
+
});
|
|
160
|
+
return true;
|
|
161
|
+
};
|
|
162
|
+
var captureStreamOutput = (stream, output) => {
|
|
163
|
+
if (!stream)
|
|
164
|
+
return;
|
|
165
|
+
const reader = stream.getReader();
|
|
166
|
+
const decoder = new TextDecoder;
|
|
167
|
+
const read = () => {
|
|
168
|
+
reader.read().then(({ done, value }) => {
|
|
169
|
+
if (done) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
output.push(decoder.decode(value, { stream: true }));
|
|
173
|
+
return read();
|
|
174
|
+
}).catch(() => {});
|
|
175
|
+
};
|
|
176
|
+
read();
|
|
177
|
+
};
|
|
178
|
+
var formatServerOutput = (output) => {
|
|
179
|
+
const text = output.join("").trim();
|
|
180
|
+
if (!text)
|
|
181
|
+
return "";
|
|
182
|
+
return text.length > SERVER_OUTPUT_LIMIT ? text.slice(-SERVER_OUTPUT_LIMIT) : text;
|
|
183
|
+
};
|
|
184
|
+
var createServerStartupError = (output) => {
|
|
185
|
+
const serverOutput = formatServerOutput(output);
|
|
186
|
+
const message = serverOutput ? `Server failed to start for pre-rendering.
|
|
187
|
+
|
|
188
|
+
Server output:
|
|
189
|
+
${serverOutput}` : "Server failed to start for pre-rendering";
|
|
190
|
+
return new Error(message);
|
|
191
|
+
};
|
|
192
|
+
var prerenderWithServer = async (serverBundlePath, port, outDir, staticConfig, env, log) => {
|
|
193
|
+
const serverOutput = [];
|
|
194
|
+
const serverProcess = Bun.spawn(["bun", "run", serverBundlePath], {
|
|
195
|
+
cwd: process.cwd(),
|
|
196
|
+
env: { ...process.env, ...env, PORT: String(port) },
|
|
197
|
+
stderr: "pipe",
|
|
198
|
+
stdout: "pipe"
|
|
199
|
+
});
|
|
200
|
+
captureStreamOutput(serverProcess.stdout, serverOutput);
|
|
201
|
+
captureStreamOutput(serverProcess.stderr, serverOutput);
|
|
202
|
+
const ready = await waitForServerReady(port);
|
|
203
|
+
if (!ready) {
|
|
204
|
+
serverProcess.kill();
|
|
205
|
+
await serverProcess.exited.catch(() => {
|
|
206
|
+
return;
|
|
207
|
+
});
|
|
208
|
+
throw createServerStartupError(serverOutput);
|
|
209
|
+
}
|
|
210
|
+
const result = await prerender(port, outDir, staticConfig, log);
|
|
211
|
+
serverProcess.kill();
|
|
212
|
+
await serverProcess.exited;
|
|
213
|
+
return result;
|
|
214
|
+
};
|
|
215
|
+
export {
|
|
216
|
+
routeToFilename,
|
|
217
|
+
rerenderRoute,
|
|
218
|
+
readTimestamp,
|
|
219
|
+
prerenderWithServer,
|
|
220
|
+
prerender,
|
|
221
|
+
PRERENDER_BYPASS_HEADER
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
//# debugId=5205CCA42BB54FF864756E2164756E21
|
|
225
|
+
//# sourceMappingURL=chunk-nehhtthw.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/core/prerender.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { mkdirSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { StaticConfig } from '../../types/build';\n\nexport type PrerenderResult = {\n\t/** Map of route path → rendered HTML file path on disk */\n\troutes: Map<string, string>;\n\t/** Directory where pre-rendered files are stored */\n\tdir: string;\n};\n\ntype LogFn = (message: string) => void;\n\nconst SERVER_OUTPUT_LIMIT = 4000;\n\n/** Milliseconds between each startup readiness poll */\nconst STARTUP_POLL_INTERVAL_MS = 100;\n\n/** Default maximum time to wait for the prerender server to become ready. */\nconst DEFAULT_STARTUP_TIMEOUT_MS = 30_000;\n\n/** Header used to bypass the prerender cache during ISR re-renders */\nexport const PRERENDER_BYPASS_HEADER = 'X-Absolute-Prerender-Bypass';\n\n/** Convert a URL path to a filename: \"/\" → \"index.html\", \"/vue\" → \"vue.html\" */\nexport const routeToFilename = (route: string) =>\n\troute === '/' ? 'index.html' : `${route.slice(1).replace(/\\//g, '-')}.html`;\n\n/** Write a timestamp file alongside the pre-rendered HTML */\nconst writeTimestamp = async (htmlPath: string) => {\n\tconst metaPath = htmlPath.replace(/\\.html$/, '.meta');\n\tawait Bun.write(metaPath, String(Date.now()));\n};\n\n/** Read the render timestamp for a pre-rendered page. Returns 0 if not found. */\nexport const readTimestamp = (htmlPath: string) => {\n\tconst metaPath = htmlPath.replace(/\\.html$/, '.meta');\n\ttry {\n\t\tconst content = readFileSync(metaPath, 'utf-8');\n\n\t\treturn Number(content) || 0;\n\t} catch {\n\t\treturn 0;\n\t}\n};\n\n/** Extract internal <a href> links from an HTML string */\nconst extractLinks = (html: string, visited: Set<string>) => {\n\tconst links: string[] = [];\n\tconst linkRegex = /href=[\"'](\\/[^\"']*?)[\"']/g;\n\tlet match;\n\twhile ((match = linkRegex.exec(html)) !== null) {\n\t\tconst href = match[1] ?? '';\n\t\tif (\n\t\t\t!href ||\n\t\t\thref.includes('.') ||\n\t\t\thref.includes('#') ||\n\t\t\tvisited.has(href)\n\t\t)\n\t\t\tcontinue;\n\t\tlinks.push(href);\n\t}\n\n\treturn links;\n};\n\n/** Fetch a single route and return its HTML if it's a valid HTML page */\nconst fetchRoute = async (baseUrl: string, path: string) => {\n\tconst res = await fetch(`${baseUrl}${path}`, { redirect: 'manual' });\n\tif (!res.ok) return null;\n\n\tconst contentType = res.headers.get('content-type') ?? '';\n\tif (!contentType.includes('text/html')) return null;\n\n\treturn res.text();\n};\n\n/**\n * Crawl from \"/\" and discover all linked pages by following internal <a href> links.\n */\nconst crawlRoutes = async (baseUrl: string) => {\n\tconst visited = new Set<string>();\n\tconst queue: string[] = ['/'];\n\tconst routes: string[] = [];\n\n\tconst crawlNextRoute = async () => {\n\t\tconst path = queue.shift();\n\t\tif (!path) {\n\t\t\treturn;\n\t\t}\n\t\tif (visited.has(path)) {\n\t\t\tawait crawlNextRoute();\n\n\t\t\treturn;\n\t\t}\n\t\tvisited.add(path);\n\n\t\tconst html = await fetchRoute(baseUrl, path).catch(() => null);\n\t\tif (!html) {\n\t\t\tawait crawlNextRoute();\n\n\t\t\treturn;\n\t\t}\n\n\t\troutes.push(path);\n\t\tqueue.push(...extractLinks(html, visited));\n\t\tawait crawlNextRoute();\n\t};\n\n\tawait crawlNextRoute();\n\n\treturn routes;\n};\n\n/**\n * Re-render a single route by fetching it from the running server\n * with the bypass header so it hits SSR instead of the cache.\n */\nexport const rerenderRoute = async (\n\troute: string,\n\tport: number,\n\tprerenderDir: string\n) => {\n\ttry {\n\t\tconst res = await fetch(`http://localhost:${port}${route}`, {\n\t\t\theaders: { [PRERENDER_BYPASS_HEADER]: '1' },\n\t\t\tredirect: 'manual'\n\t\t});\n\t\tif (!res.ok) return false;\n\n\t\tconst html = await res.text();\n\t\tconst fileName = routeToFilename(route);\n\t\tconst filePath = join(prerenderDir, fileName);\n\t\tawait Bun.write(filePath, html);\n\t\tawait writeTimestamp(filePath);\n\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\n/** Fetch, render, and save a single route during pre-rendering */\nconst prerenderRoute = async (\n\tbaseUrl: string,\n\troute: string,\n\tprerenderDir: string,\n\tresult: PrerenderResult,\n\tlog?: LogFn\n) => {\n\tconst res = await fetch(`${baseUrl}${route}`, {\n\t\tredirect: 'manual'\n\t}).catch(() => null);\n\tif (!res) {\n\t\tlog?.(` Failed to pre-render ${route}`);\n\n\t\treturn;\n\t}\n\tif (!res.ok) {\n\t\tlog?.(` Skipped ${route} (HTTP ${res.status})`);\n\n\t\treturn;\n\t}\n\n\tconst contentType = res.headers.get('content-type') ?? '';\n\tif (!contentType.includes('text/html')) {\n\t\tlog?.(` Skipped ${route} (non-HTML response)`);\n\n\t\treturn;\n\t}\n\n\tconst html = await res.text();\n\tconst fileName = routeToFilename(route);\n\tconst filePath = join(prerenderDir, fileName);\n\tawait Bun.write(filePath, html);\n\tawait writeTimestamp(filePath);\n\tresult.routes.set(route, filePath);\n\n\tlog?.(` Pre-rendered ${route} → ${fileName} (${html.length} bytes)`);\n};\n\n/**\n * Pre-render routes by fetching them from a running server and saving the HTML to disk.\n *\n * Used by both `absolute start` (SSG) and `absolute compile`.\n */\nexport const prerender = async (\n\tport: number,\n\toutDir: string,\n\tstaticConfig: StaticConfig,\n\tlog?: LogFn\n) => {\n\tconst prerenderDir = join(outDir, '_prerendered');\n\tmkdirSync(prerenderDir, { recursive: true });\n\n\tconst baseUrl = `http://localhost:${port}`;\n\n\tlet routes: string[];\n\tif (staticConfig.routes === 'all') {\n\t\tlog?.('Crawling routes...');\n\t\troutes = await crawlRoutes(baseUrl);\n\t} else {\n\t\t({ routes } = staticConfig);\n\t}\n\n\tconst result: PrerenderResult = {\n\t\tdir: prerenderDir,\n\t\troutes: new Map()\n\t};\n\n\tawait routes.reduce(\n\t\t(chain, route) =>\n\t\t\tchain.then(() =>\n\t\t\t\tprerenderRoute(baseUrl, route, prerenderDir, result, log)\n\t\t\t),\n\t\tPromise.resolve()\n\t);\n\n\treturn result;\n};\n\nconst getStartupTimeoutMs = () => {\n\tconst rawTimeout = Bun.env.ABSOLUTE_PRERENDER_STARTUP_TIMEOUT_MS;\n\tconst parsedTimeout = rawTimeout ? Number(rawTimeout) : NaN;\n\n\treturn Number.isFinite(parsedTimeout) && parsedTimeout > 0\n\t\t? parsedTimeout\n\t\t: DEFAULT_STARTUP_TIMEOUT_MS;\n};\n\n/** Poll the server until it responds or startup timeout elapses */\nconst waitForServerReady = async (port: number) => {\n\tconst deadline = performance.now() + getStartupTimeoutMs();\n\tconst pollServer = async () => {\n\t\tif (performance.now() >= deadline) {\n\t\t\treturn false;\n\t\t}\n\t\tif (await probePrerenderServer(port)) {\n\t\t\treturn true;\n\t\t}\n\t\tawait Bun.sleep(STARTUP_POLL_INTERVAL_MS);\n\n\t\treturn pollServer();\n\t};\n\n\treturn pollServer();\n};\n\nconst probePrerenderServer = async (port: number) => {\n\tconst res = await fetch(`http://localhost:${port}/`).catch(() => null);\n\tif (!res) {\n\t\treturn false;\n\t}\n\n\tawait res.body?.cancel().catch(() => undefined);\n\n\treturn true;\n};\n\nconst captureStreamOutput = (\n\tstream: ReadableStream<Uint8Array> | null,\n\toutput: string[]\n) => {\n\tif (!stream) return;\n\n\tconst reader = stream.getReader();\n\tconst decoder = new TextDecoder();\n\tconst read = () => {\n\t\treader\n\t\t\t.read()\n\t\t\t.then(({ done, value }) => {\n\t\t\t\tif (done) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\toutput.push(decoder.decode(value, { stream: true }));\n\n\t\t\t\treturn read();\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\t/* best-effort diagnostics */\n\t\t\t});\n\t};\n\tread();\n};\n\nconst formatServerOutput = (output: string[]) => {\n\tconst text = output.join('').trim();\n\tif (!text) return '';\n\n\treturn text.length > SERVER_OUTPUT_LIMIT\n\t\t? text.slice(-SERVER_OUTPUT_LIMIT)\n\t\t: text;\n};\n\nconst createServerStartupError = (output: string[]) => {\n\tconst serverOutput = formatServerOutput(output);\n\tconst message = serverOutput\n\t\t? `Server failed to start for pre-rendering.\\n\\nServer output:\\n${serverOutput}`\n\t\t: 'Server failed to start for pre-rendering';\n\n\treturn new Error(message);\n};\n\n/**\n * Start the bundled production server, wait for it to be ready, pre-render,\n * then kill it.\n */\nexport const prerenderWithServer = async (\n\tserverBundlePath: string,\n\tport: number,\n\toutDir: string,\n\tstaticConfig: StaticConfig,\n\tenv: Record<string, string>,\n\tlog?: LogFn\n) => {\n\tconst serverOutput: string[] = [];\n\tconst serverProcess = Bun.spawn(['bun', 'run', serverBundlePath], {\n\t\tcwd: process.cwd(),\n\t\tenv: { ...process.env, ...env, PORT: String(port) },\n\t\tstderr: 'pipe',\n\t\tstdout: 'pipe'\n\t});\n\tcaptureStreamOutput(serverProcess.stdout, serverOutput);\n\tcaptureStreamOutput(serverProcess.stderr, serverOutput);\n\n\tconst ready = await waitForServerReady(port);\n\n\tif (!ready) {\n\t\tserverProcess.kill();\n\t\tawait serverProcess.exited.catch(() => undefined);\n\t\tthrow createServerStartupError(serverOutput);\n\t}\n\n\tconst result = await prerender(port, outDir, staticConfig, log);\n\n\tserverProcess.kill();\n\tawait serverProcess.exited;\n\n\treturn result;\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "5205CCA42BB54FF864756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
captureStreamingSlotWarningCallsite,
|
|
4
|
+
runWithStreamingSlotWarningScope,
|
|
5
|
+
ssrErrorPage
|
|
6
|
+
} from "./chunk-gd6wmknh.js";
|
|
7
|
+
import {
|
|
8
|
+
getCurrentRouteRegistrationCallsite
|
|
9
|
+
} from "./chunk-mtgf69xn.js";
|
|
10
|
+
import {
|
|
11
|
+
derivePageName,
|
|
12
|
+
injectIslandPageContextStream,
|
|
13
|
+
renderConventionError,
|
|
14
|
+
withRegisteredStreamingSlots
|
|
15
|
+
} from "./chunk-qk8kd3hr.js";
|
|
16
|
+
import {
|
|
17
|
+
isSsrCacheDirty
|
|
18
|
+
} from "./chunk-d9c0am65.js";
|
|
19
|
+
import {
|
|
20
|
+
EXCLUDE_LAST_OFFSET
|
|
21
|
+
} from "./chunk-qh75agse.js";
|
|
22
|
+
import {
|
|
23
|
+
__require
|
|
24
|
+
} from "./chunk-bmgqm774.js";
|
|
25
|
+
|
|
26
|
+
// src/vue/pageHandler.ts
|
|
27
|
+
import { readdir } from "fs/promises";
|
|
28
|
+
import { basename, dirname } from "path";
|
|
29
|
+
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
30
|
+
var isGenericVueComponent = (value) => typeof value === "function" || isRecord(value);
|
|
31
|
+
var readHasIslands = (value) => {
|
|
32
|
+
if (!isRecord(value))
|
|
33
|
+
return false;
|
|
34
|
+
const hasIslands = value["__ABSOLUTE_PAGE_HAS_ISLANDS__"];
|
|
35
|
+
return typeof hasIslands === "boolean" ? hasIslands : false;
|
|
36
|
+
};
|
|
37
|
+
var readDefaultExport = (value) => isRecord(value) ? value.default : undefined;
|
|
38
|
+
var resolveCurrentGeneratedVueModulePath = async (pagePath) => {
|
|
39
|
+
const pageDirectory = dirname(pagePath);
|
|
40
|
+
const expectedPrefix = `${basename(pagePath, ".js").split(".")[0]}.`;
|
|
41
|
+
try {
|
|
42
|
+
const pageEntries = await readdir(pageDirectory, {
|
|
43
|
+
withFileTypes: true
|
|
44
|
+
});
|
|
45
|
+
const matchingEntry = pageEntries.find((entry) => entry.isFile() && entry.name.endsWith(".js") && (entry.name === `${expectedPrefix.slice(0, EXCLUDE_LAST_OFFSET)}.js` || entry.name.startsWith(expectedPrefix)));
|
|
46
|
+
if (!matchingEntry) {
|
|
47
|
+
return pagePath;
|
|
48
|
+
}
|
|
49
|
+
return `${pageDirectory}/${matchingEntry.name}`;
|
|
50
|
+
} catch {
|
|
51
|
+
return pagePath;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var buildDirtyResponse = (headTag, indexPath, maybeProps) => {
|
|
55
|
+
const propsScript = `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps ?? {})};`;
|
|
56
|
+
const dirtyFlag = "window.__SSR_DIRTY__=true;";
|
|
57
|
+
const html = `<!DOCTYPE html><html>${headTag}<body><div id="root"></div>` + `<script>${propsScript}${dirtyFlag}</script>` + `<script type="module" src="${indexPath}"></script>` + `</body></html>`;
|
|
58
|
+
return new Response(html, {
|
|
59
|
+
headers: { "Content-Type": "text/html" }
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
var primeVueStream = async (stream) => {
|
|
63
|
+
const reader = stream.getReader();
|
|
64
|
+
const firstChunk = await reader.read();
|
|
65
|
+
return { firstChunk, reader };
|
|
66
|
+
};
|
|
67
|
+
var handleVuePageRequest = async (input) => {
|
|
68
|
+
const passedPageComponent = input.Page;
|
|
69
|
+
const resolvedHeadTag = input.headTag ?? "<head></head>";
|
|
70
|
+
const resolvedIndexPath = input.indexPath;
|
|
71
|
+
const resolvedOptions = input;
|
|
72
|
+
const resolvedPagePath = input.pagePath;
|
|
73
|
+
const maybeProps = input.props;
|
|
74
|
+
if (isSsrCacheDirty("vue")) {
|
|
75
|
+
return buildDirtyResponse(resolvedHeadTag, resolvedIndexPath, maybeProps);
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const handlerCallsite = resolvedOptions?.collectStreamingSlots === true ? undefined : getCurrentRouteRegistrationCallsite() ?? captureStreamingSlotWarningCallsite();
|
|
79
|
+
const renderPageResponse = async () => {
|
|
80
|
+
const resolvePageComponent = async () => {
|
|
81
|
+
if (isGenericVueComponent(passedPageComponent)) {
|
|
82
|
+
return {
|
|
83
|
+
component: passedPageComponent,
|
|
84
|
+
hasIslands: readHasIslands(passedPageComponent)
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
const generatedPagePath = await resolveCurrentGeneratedVueModulePath(resolvedPagePath);
|
|
88
|
+
const importedPageModule = await import(generatedPagePath);
|
|
89
|
+
const importedPageComponent = readDefaultExport(importedPageModule) ?? importedPageModule;
|
|
90
|
+
if (!isGenericVueComponent(importedPageComponent)) {
|
|
91
|
+
throw new Error(`Invalid Vue page module: ${generatedPagePath}`);
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
component: importedPageComponent,
|
|
95
|
+
hasIslands: readHasIslands(importedPageModule)
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
const resolvedPage = await resolvePageComponent();
|
|
99
|
+
const { createSSRApp, h } = await import("vue");
|
|
100
|
+
const { renderToWebStream } = await import("vue/server-renderer");
|
|
101
|
+
const app = createSSRApp({
|
|
102
|
+
render: () => h(resolvedPage.component, maybeProps ?? null)
|
|
103
|
+
});
|
|
104
|
+
const bodyStream = renderToWebStream(app);
|
|
105
|
+
const { firstChunk, reader } = await primeVueStream(bodyStream);
|
|
106
|
+
const head = `<!DOCTYPE html><html>${resolvedHeadTag}<body><div id="root">`;
|
|
107
|
+
const tail = `</div><script>window.__INITIAL_PROPS__=${JSON.stringify(maybeProps ?? {})}</script><script type="module" src="${resolvedIndexPath}"></script></body></html>`;
|
|
108
|
+
const stream = new ReadableStream({
|
|
109
|
+
start(controller) {
|
|
110
|
+
controller.enqueue(head);
|
|
111
|
+
if (!firstChunk.done) {
|
|
112
|
+
controller.enqueue(firstChunk.value);
|
|
113
|
+
}
|
|
114
|
+
if (firstChunk.done) {
|
|
115
|
+
controller.enqueue(tail);
|
|
116
|
+
controller.close();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const pumpLoop = () => {
|
|
120
|
+
reader.read().then(({ done, value }) => done ? (controller.enqueue(tail), controller.close()) : (controller.enqueue(value), pumpLoop())).catch((err) => controller.error(err));
|
|
121
|
+
};
|
|
122
|
+
pumpLoop();
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
const htmlStream = injectIslandPageContextStream(stream, {
|
|
126
|
+
hasIslands: resolvedPage.hasIslands
|
|
127
|
+
});
|
|
128
|
+
return new Response(htmlStream, {
|
|
129
|
+
headers: { "Content-Type": "text/html" }
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
return await runWithStreamingSlotWarningScope(() => resolvedOptions?.collectStreamingSlots === true ? withRegisteredStreamingSlots(renderPageResponse, resolvedOptions) : renderPageResponse(), { handlerCallsite });
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error("[SSR] Vue render error:", error);
|
|
135
|
+
const pageName = derivePageName(resolvedPagePath);
|
|
136
|
+
const conventionResponse = await renderConventionError("vue", pageName, error);
|
|
137
|
+
if (conventionResponse)
|
|
138
|
+
return conventionResponse;
|
|
139
|
+
return new Response(ssrErrorPage("vue", error), {
|
|
140
|
+
headers: { "Content-Type": "text/html" },
|
|
141
|
+
status: 500
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
export { handleVuePageRequest };
|
|
147
|
+
|
|
148
|
+
//# debugId=26E5820BE6B0DB1864756E2164756E21
|
|
149
|
+
//# sourceMappingURL=chunk-nhzf4az4.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/vue/pageHandler.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Component as VueComponent } from 'vue';\nimport { readdir } from 'node:fs/promises';\nimport { basename, dirname } from 'node:path';\nimport type { VuePropsOf } from '../../types/vue';\nimport { EXCLUDE_LAST_OFFSET } from '../constants';\nimport { injectIslandPageContextStream } from '../core/islandPageContext';\nimport { getCurrentRouteRegistrationCallsite } from '../core/devRouteRegistrationCallsite';\nimport {\n\ttype StreamingSlotEnhancerOptions,\n\twithRegisteredStreamingSlots\n} from '../core/responseEnhancers';\nimport {\n\tcaptureStreamingSlotWarningCallsite,\n\trunWithStreamingSlotWarningScope\n} from '../core/streamingSlotWarningScope';\nimport { isSsrCacheDirty, markSsrCacheDirty } from '../core/ssrCache';\nimport { ssrErrorPage } from '../utils/ssrErrorPage';\nimport {\n\tderivePageName,\n\trenderConventionError\n} from '../utils/resolveConvention';\n\ntype VuePageRenderOptions = StreamingSlotEnhancerOptions & {\n\tcollectStreamingSlots?: boolean;\n};\nexport type VuePageRequestInput<Component extends VueComponent> =\n\tVuePageRenderOptions & {\n\t\theadTag?: `<head>${string}</head>`;\n\t\tindexPath: string;\n\t\tpagePath: string;\n\t\tPage?: Component;\n\t} & (keyof VuePropsOf<Component> extends never\n\t\t\t? { props?: NoInfer<VuePropsOf<Component>> }\n\t\t\t: { props: NoInfer<VuePropsOf<Component>> });\ntype GenericVueComponent = VueComponent;\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n\ttypeof value === 'object' && value !== null;\n\nconst isGenericVueComponent = (value: unknown): value is GenericVueComponent =>\n\ttypeof value === 'function' || isRecord(value);\n\nconst readHasIslands = (value: unknown) => {\n\tif (!isRecord(value)) return false;\n\tconst hasIslands = value['__ABSOLUTE_PAGE_HAS_ISLANDS__'];\n\n\treturn typeof hasIslands === 'boolean' ? hasIslands : false;\n};\n\nconst readDefaultExport = (value: unknown) =>\n\tisRecord(value) ? value.default : undefined;\n\nconst resolveCurrentGeneratedVueModulePath = async (pagePath: string) => {\n\tconst pageDirectory = dirname(pagePath);\n\tconst expectedPrefix = `${basename(pagePath, '.js').split('.')[0]}.`;\n\n\ttry {\n\t\tconst pageEntries = await readdir(pageDirectory, {\n\t\t\twithFileTypes: true\n\t\t});\n\t\tconst matchingEntry = pageEntries.find(\n\t\t\t(entry) =>\n\t\t\t\tentry.isFile() &&\n\t\t\t\tentry.name.endsWith('.js') &&\n\t\t\t\t(entry.name ===\n\t\t\t\t\t`${expectedPrefix.slice(0, EXCLUDE_LAST_OFFSET)}.js` ||\n\t\t\t\t\tentry.name.startsWith(expectedPrefix))\n\t\t);\n\t\tif (!matchingEntry) {\n\t\t\treturn pagePath;\n\t\t}\n\n\t\treturn `${pageDirectory}/${matchingEntry.name}`;\n\t} catch {\n\t\treturn pagePath;\n\t}\n};\n\nconst buildDirtyResponse = (\n\theadTag: string,\n\tindexPath: string,\n\tmaybeProps: Record<string, unknown> | undefined\n) => {\n\tconst propsScript = `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps ?? {})};`;\n\tconst dirtyFlag = 'window.__SSR_DIRTY__=true;';\n\tconst html =\n\t\t`<!DOCTYPE html><html>${headTag}<body><div id=\"root\"></div>` +\n\t\t`<script>${propsScript}${dirtyFlag}</script>` +\n\t\t`<script type=\"module\" src=\"${indexPath}\"></script>` +\n\t\t`</body></html>`;\n\n\treturn new Response(html, {\n\t\theaders: { 'Content-Type': 'text/html' }\n\t});\n};\n\nconst primeVueStream = async (stream: ReadableStream) => {\n\tconst reader = stream.getReader();\n\tconst firstChunk = await reader.read();\n\n\treturn { firstChunk, reader };\n};\n\nexport const handleVuePageRequest = async <Component extends VueComponent>(\n\tinput: VuePageRequestInput<Component>\n) => {\n\tconst passedPageComponent = input.Page;\n\tconst resolvedHeadTag = input.headTag ?? '<head></head>';\n\tconst resolvedIndexPath = input.indexPath;\n\tconst resolvedOptions = input;\n\tconst resolvedPagePath = input.pagePath;\n\tconst maybeProps = input.props;\n\n\tif (isSsrCacheDirty('vue')) {\n\t\treturn buildDirtyResponse(\n\t\t\tresolvedHeadTag,\n\t\t\tresolvedIndexPath,\n\t\t\tmaybeProps\n\t\t);\n\t}\n\n\ttry {\n\t\tconst handlerCallsite =\n\t\t\tresolvedOptions?.collectStreamingSlots === true\n\t\t\t\t? undefined\n\t\t\t\t: (getCurrentRouteRegistrationCallsite() ??\n\t\t\t\t\tcaptureStreamingSlotWarningCallsite());\n\t\tconst renderPageResponse = async () => {\n\t\t\tconst resolvePageComponent = async () => {\n\t\t\t\tif (isGenericVueComponent(passedPageComponent)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcomponent: passedPageComponent,\n\t\t\t\t\t\thasIslands: readHasIslands(passedPageComponent)\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst generatedPagePath =\n\t\t\t\t\tawait resolveCurrentGeneratedVueModulePath(\n\t\t\t\t\t\tresolvedPagePath\n\t\t\t\t\t);\n\t\t\t\tconst importedPageModule: unknown = await import(\n\t\t\t\t\tgeneratedPagePath\n\t\t\t\t);\n\t\t\t\tconst importedPageComponent =\n\t\t\t\t\treadDefaultExport(importedPageModule) ?? importedPageModule;\n\t\t\t\tif (!isGenericVueComponent(importedPageComponent)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid Vue page module: ${generatedPagePath}`\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcomponent: importedPageComponent,\n\t\t\t\t\thasIslands: readHasIslands(importedPageModule)\n\t\t\t\t};\n\t\t\t};\n\n\t\t\tconst resolvedPage = await resolvePageComponent();\n\t\t\tconst { createSSRApp, h } = await import('vue');\n\t\t\tconst { renderToWebStream } = await import('vue/server-renderer');\n\n\t\t\tconst app = createSSRApp({\n\t\t\t\trender: () => h(resolvedPage.component, maybeProps ?? null)\n\t\t\t});\n\n\t\t\tconst bodyStream = renderToWebStream(app);\n\t\t\tconst { firstChunk, reader } = await primeVueStream(bodyStream);\n\n\t\t\tconst head = `<!DOCTYPE html><html>${resolvedHeadTag}<body><div id=\"root\">`;\n\t\t\tconst tail = `</div><script>window.__INITIAL_PROPS__=${JSON.stringify(\n\t\t\t\tmaybeProps ?? {}\n\t\t\t)}</script><script type=\"module\" src=\"${resolvedIndexPath}\"></script></body></html>`;\n\n\t\t\tconst stream = new ReadableStream({\n\t\t\t\tstart(controller) {\n\t\t\t\t\tcontroller.enqueue(head);\n\t\t\t\t\tif (!firstChunk.done) {\n\t\t\t\t\t\tcontroller.enqueue(firstChunk.value);\n\t\t\t\t\t}\n\t\t\t\t\tif (firstChunk.done) {\n\t\t\t\t\t\tcontroller.enqueue(tail);\n\t\t\t\t\t\tcontroller.close();\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst pumpLoop = () => {\n\t\t\t\t\t\treader\n\t\t\t\t\t\t\t.read()\n\t\t\t\t\t\t\t.then(({ done, value }) =>\n\t\t\t\t\t\t\t\tdone\n\t\t\t\t\t\t\t\t\t? (controller.enqueue(tail),\n\t\t\t\t\t\t\t\t\t\tcontroller.close())\n\t\t\t\t\t\t\t\t\t: (controller.enqueue(value), pumpLoop())\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.catch((err) => controller.error(err));\n\t\t\t\t\t};\n\t\t\t\t\tpumpLoop();\n\t\t\t\t}\n\t\t\t});\n\t\t\tconst htmlStream = injectIslandPageContextStream(stream, {\n\t\t\t\thasIslands: resolvedPage.hasIslands\n\t\t\t});\n\n\t\t\treturn new Response(htmlStream, {\n\t\t\t\theaders: { 'Content-Type': 'text/html' }\n\t\t\t});\n\t\t};\n\n\t\treturn await runWithStreamingSlotWarningScope(\n\t\t\t() =>\n\t\t\t\tresolvedOptions?.collectStreamingSlots === true\n\t\t\t\t\t? withRegisteredStreamingSlots(\n\t\t\t\t\t\t\trenderPageResponse,\n\t\t\t\t\t\t\tresolvedOptions\n\t\t\t\t\t\t)\n\t\t\t\t\t: renderPageResponse(),\n\t\t\t{ handlerCallsite }\n\t\t);\n\t} catch (error) {\n\t\tconsole.error('[SSR] Vue render error:', error);\n\n\t\tconst pageName = derivePageName(resolvedPagePath);\n\t\tconst conventionResponse = await renderConventionError(\n\t\t\t'vue',\n\t\t\tpageName,\n\t\t\terror\n\t\t);\n\t\tif (conventionResponse) return conventionResponse;\n\n\t\treturn new Response(ssrErrorPage('vue', error), {\n\t\t\theaders: { 'Content-Type': 'text/html' },\n\t\t\tstatus: 500\n\t\t});\n\t}\n};\n\nexport const invalidateVueSsrCache = () => {\n\tmarkSsrCacheDirty('vue');\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "26E5820BE6B0DB1864756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/utils/stringModifiers.ts
|
|
3
|
+
var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9\-_]+/g, "").replace(/[-_]{2,}/g, "-");
|
|
4
|
+
var toKebab = (str) => normalizeSlug(str).replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
5
|
+
var toPascal = (str) => {
|
|
6
|
+
if (!str.includes("-") && !str.includes("_")) {
|
|
7
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
8
|
+
}
|
|
9
|
+
return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
|
|
10
|
+
};
|
|
11
|
+
var toScreamingSnake = (str) => str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase();
|
|
12
|
+
|
|
13
|
+
export { toKebab, toPascal, toScreamingSnake };
|
|
14
|
+
|
|
15
|
+
//# debugId=93E61FCF94E3B28D64756E2164756E21
|
|
16
|
+
//# sourceMappingURL=chunk-p5504p14.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/utils/stringModifiers.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"const normalizeSlug = (str: string) =>\n\tstr\n\t\t.trim()\n\t\t.replace(/\\s+/g, '-')\n\t\t.replace(/[^A-Za-z0-9\\-_]+/g, '')\n\t\t.replace(/[-_]{2,}/g, '-');\n\nexport const toKebab = (str: string) =>\n\tnormalizeSlug(str)\n\t\t.replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n\t\t.toLowerCase();\nexport const toPascal = (str: string) => {\n\tif (!str.includes('-') && !str.includes('_')) {\n\t\treturn str.charAt(0).toUpperCase() + str.slice(1);\n\t}\n\n\treturn normalizeSlug(str)\n\t\t.split(/[-_]/)\n\t\t.filter(Boolean)\n\t\t.map(\n\t\t\t(segment) =>\n\t\t\t\tsegment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()\n\t\t)\n\t\t.join('');\n};\nexport const toScreamingSnake = (str: string) =>\n\tstr.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase();\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;AAAA,IAAM,gBAAgB,CAAC,QACtB,IACE,KAAK,EACL,QAAQ,QAAQ,GAAG,EACnB,QAAQ,qBAAqB,EAAE,EAC/B,QAAQ,aAAa,GAAG;AAEpB,IAAM,UAAU,CAAC,QACvB,cAAc,GAAG,EACf,QAAQ,sBAAsB,OAAO,EACrC,YAAY;AACR,IAAM,WAAW,CAAC,QAAgB;AAAA,EACxC,IAAI,CAAC,IAAI,SAAS,GAAG,KAAK,CAAC,IAAI,SAAS,GAAG,GAAG;AAAA,IAC7C,OAAO,IAAI,OAAO,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC;AAAA,EACjD;AAAA,EAEA,OAAO,cAAc,GAAG,EACtB,MAAM,MAAM,EACZ,OAAO,OAAO,EACd,IACA,CAAC,YACA,QAAQ,OAAO,CAAC,EAAE,YAAY,IAAI,QAAQ,MAAM,CAAC,EAAE,YAAY,CACjE,EACC,KAAK,EAAE;AAAA;AAEH,IAAM,mBAAmB,CAAC,QAChC,IAAI,QAAQ,sBAAsB,OAAO,EAAE,YAAY;",
|
|
8
|
+
"debugId": "93E61FCF94E3B28D64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/utils/registerClientScript.ts
|
|
3
|
+
var scriptRegistry = new Map;
|
|
4
|
+
var requestCounter = 0;
|
|
5
|
+
var getRequestId = () => `req_${Date.now()}_${++requestCounter}`;
|
|
6
|
+
var ssrContextGetter = null;
|
|
7
|
+
var getSsrContextId = () => ssrContextGetter?.() || Object.getOwnPropertyDescriptor(globalThis, "__absolutejs_requestId")?.value;
|
|
8
|
+
var registerClientScript = (script, requestId) => {
|
|
9
|
+
const id = requestId || getSsrContextId() || getRequestId();
|
|
10
|
+
if (!scriptRegistry.has(id)) {
|
|
11
|
+
scriptRegistry.set(id, new Set);
|
|
12
|
+
}
|
|
13
|
+
scriptRegistry.get(id)?.add(script);
|
|
14
|
+
return id;
|
|
15
|
+
};
|
|
16
|
+
var setSsrContextGetter = (getter) => {
|
|
17
|
+
ssrContextGetter = getter;
|
|
18
|
+
};
|
|
19
|
+
if (typeof globalThis !== "undefined") {
|
|
20
|
+
Object.assign(globalThis, { registerClientScript });
|
|
21
|
+
}
|
|
22
|
+
var clearAllClientScripts = () => {
|
|
23
|
+
scriptRegistry.clear();
|
|
24
|
+
};
|
|
25
|
+
var generateClientScriptCode = (scripts) => {
|
|
26
|
+
if (scripts.length === 0) {
|
|
27
|
+
return "";
|
|
28
|
+
}
|
|
29
|
+
const scriptCode = scripts.map((script, index) => {
|
|
30
|
+
const funcString = script.toString();
|
|
31
|
+
const bodyMatch = funcString.match(/\{([\s\S]*)\}/);
|
|
32
|
+
if (!bodyMatch || !bodyMatch[1]) {
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
const body = bodyMatch[1].trim();
|
|
36
|
+
return `
|
|
37
|
+
(function() {
|
|
38
|
+
var executed = false;
|
|
39
|
+
function executeScript_${index}() {
|
|
40
|
+
if (executed) return;
|
|
41
|
+
executed = true;
|
|
42
|
+
${body}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
|
46
|
+
executeScript_${index}();
|
|
47
|
+
} else {
|
|
48
|
+
document.addEventListener('DOMContentLoaded', executeScript_${index});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Watch for hydration-added elements
|
|
52
|
+
var observer = new MutationObserver(function() {
|
|
53
|
+
executeScript_${index}();
|
|
54
|
+
if (executed) observer.disconnect();
|
|
55
|
+
});
|
|
56
|
+
if (!executed) {
|
|
57
|
+
observer.observe(document.body || document.documentElement, { childList: true, subtree: true });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Single fallback timeout
|
|
61
|
+
setTimeout(function() {
|
|
62
|
+
executeScript_${index}();
|
|
63
|
+
observer.disconnect();
|
|
64
|
+
}, 1000);
|
|
65
|
+
})();`;
|
|
66
|
+
}).join(`
|
|
67
|
+
`);
|
|
68
|
+
return `<script>
|
|
69
|
+
(function() {
|
|
70
|
+
${scriptCode}
|
|
71
|
+
})();
|
|
72
|
+
</script>`;
|
|
73
|
+
};
|
|
74
|
+
var getAndClearClientScripts = (requestId) => {
|
|
75
|
+
const id = requestId || ssrContextGetter?.();
|
|
76
|
+
if (!id)
|
|
77
|
+
return [];
|
|
78
|
+
const scripts = scriptRegistry.get(id);
|
|
79
|
+
if (!scripts) {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
const scriptArray = Array.from(scripts);
|
|
83
|
+
scriptRegistry.delete(id);
|
|
84
|
+
return scriptArray;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export { getSsrContextId, registerClientScript, setSsrContextGetter, clearAllClientScripts, generateClientScriptCode, getAndClearClientScripts };
|
|
88
|
+
|
|
89
|
+
//# debugId=9DFF481135ABC22A64756E2164756E21
|
|
90
|
+
//# sourceMappingURL=chunk-pnscgw95.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/utils/registerClientScript.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Utility for registering client-side scripts that need to run after Angular SSR hydration.\n *\n * This is necessary because Angular's lifecycle hooks don't always run reliably on the client\n * after SSR hydration, especially for event listeners attached to DOM elements.\n *\n * Usage in Angular components:\n * ```typescript\n * import { registerClientScript } from '@absolutejs/absolute';\n *\n * // Register an event listener script\n * registerClientScript(() => {\n * const element = document.querySelector('.my-element');\n * if (element) {\n * element.addEventListener('click', () => {\n * console.log('Clicked!');\n * });\n * }\n * });\n * ```\n *\n * The script will be automatically injected into the HTML response and executed on the client.\n */\n\n// Request-scoped registry for client scripts\n// Each request gets its own set of scripts to inject\nconst scriptRegistry = new Map<string, Set<() => void>>();\n\n// Generate a unique request ID for tracking scripts per request\nlet requestCounter = 0;\nconst getRequestId = () => `req_${Date.now()}_${++requestCounter}`;\n\n// Allow SSR frameworks to inject a request context getter (e.g. AsyncLocalStorage)\nlet ssrContextGetter: (() => string | undefined) | null = null;\nexport const getSsrContextId = () =>\n\tssrContextGetter?.() ||\n\tObject.getOwnPropertyDescriptor(globalThis, '__absolutejs_requestId')\n\t\t?.value;\nexport const registerClientScript = (\n\tscript: () => void,\n\trequestId?: string\n) => {\n\t// Try to get requestId from explicit arg, then Async Context, then global fallback\n\tconst id = requestId || getSsrContextId() || getRequestId();\n\n\tif (!scriptRegistry.has(id)) {\n\t\tscriptRegistry.set(id, new Set());\n\t}\n\n\tscriptRegistry.get(id)?.add(script);\n\n\treturn id;\n};\nexport const setSsrContextGetter = (getter: () => string | undefined) => {\n\tssrContextGetter = getter;\n};\n\n// Make registerClientScript available globally during SSR for Angular components\n// Using type assertion for globalThis extension\nif (typeof globalThis !== 'undefined') {\n\tObject.assign(globalThis, { registerClientScript });\n}\n\n/**\n * Get all registered scripts for a request and clear them.\n * This is called by the page handler after rendering.\n *\n * @param requestId - The request ID to get scripts for\n * @returns Array of script functions, or empty array if none registered\n */\nexport const clearAllClientScripts = () => {\n\tscriptRegistry.clear();\n};\nexport const generateClientScriptCode = (scripts: (() => void)[]) => {\n\tif (scripts.length === 0) {\n\t\treturn '';\n\t}\n\n\t// Convert functions to strings and wrap in IIFE\n\tconst scriptCode = scripts\n\t\t.map((script, index) => {\n\t\t\t// Get the function body as a string\n\t\t\tconst funcString = script.toString();\n\n\t\t\t// Extract the body (everything between { and })\n\t\t\tconst bodyMatch = funcString.match(/\\{([\\s\\S]*)\\}/);\n\t\t\tif (!bodyMatch || !bodyMatch[1]) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tconst body = bodyMatch[1].trim();\n\n\t\t\t// Wrap in IIFE with MutationObserver for DOM readiness\n\t\t\treturn `\n\t(function() {\n\t\tvar executed = false;\n\t\tfunction executeScript_${index}() {\n\t\t\tif (executed) return;\n\t\t\texecuted = true;\n\t\t\t${body}\n\t\t}\n\n\t\tif (document.readyState === 'complete' || document.readyState === 'interactive') {\n\t\t\texecuteScript_${index}();\n\t\t} else {\n\t\t\tdocument.addEventListener('DOMContentLoaded', executeScript_${index});\n\t\t}\n\n\t\t// Watch for hydration-added elements\n\t\tvar observer = new MutationObserver(function() {\n\t\t\texecuteScript_${index}();\n\t\t\tif (executed) observer.disconnect();\n\t\t});\n\t\tif (!executed) {\n\t\t\tobserver.observe(document.body || document.documentElement, { childList: true, subtree: true });\n\t\t}\n\n\t\t// Single fallback timeout\n\t\tsetTimeout(function() {\n\t\t\texecuteScript_${index}();\n\t\t\tobserver.disconnect();\n\t\t}, 1000);\n\t})();`;\n\t\t})\n\t\t.join('\\n');\n\n\treturn `<script>\n(function() {\n${scriptCode}\n})();\n</script>`;\n};\nexport const getAndClearClientScripts = (requestId?: string) => {\n\tconst id = requestId || ssrContextGetter?.();\n\tif (!id) return [];\n\n\tconst scripts = scriptRegistry.get(id);\n\tif (!scripts) {\n\t\treturn [];\n\t}\n\n\tconst scriptArray = Array.from(scripts);\n\tscriptRegistry.delete(id);\n\n\treturn scriptArray;\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;AA0BA,IAAM,iBAAiB,IAAI;AAG3B,IAAI,iBAAiB;AACrB,IAAM,eAAe,MAAM,OAAO,KAAK,IAAI,KAAK,EAAE;AAGlD,IAAI,mBAAsD;AACnD,IAAM,kBAAkB,MAC9B,mBAAmB,KACnB,OAAO,yBAAyB,YAAY,wBAAwB,GACjE;AACG,IAAM,uBAAuB,CACnC,QACA,cACI;AAAA,EAEJ,MAAM,KAAK,aAAa,gBAAgB,KAAK,aAAa;AAAA,EAE1D,IAAI,CAAC,eAAe,IAAI,EAAE,GAAG;AAAA,IAC5B,eAAe,IAAI,IAAI,IAAI,GAAK;AAAA,EACjC;AAAA,EAEA,eAAe,IAAI,EAAE,GAAG,IAAI,MAAM;AAAA,EAElC,OAAO;AAAA;AAED,IAAM,sBAAsB,CAAC,WAAqC;AAAA,EACxE,mBAAmB;AAAA;AAKpB,IAAI,OAAO,eAAe,aAAa;AAAA,EACtC,OAAO,OAAO,YAAY,EAAE,qBAAqB,CAAC;AACnD;AASO,IAAM,wBAAwB,MAAM;AAAA,EAC1C,eAAe,MAAM;AAAA;AAEf,IAAM,2BAA2B,CAAC,YAA4B;AAAA,EACpE,IAAI,QAAQ,WAAW,GAAG;AAAA,IACzB,OAAO;AAAA,EACR;AAAA,EAGA,MAAM,aAAa,QACjB,IAAI,CAAC,QAAQ,UAAU;AAAA,IAEvB,MAAM,aAAa,OAAO,SAAS;AAAA,IAGnC,MAAM,YAAY,WAAW,MAAM,eAAe;AAAA,IAClD,IAAI,CAAC,aAAa,CAAC,UAAU,IAAI;AAAA,MAChC,OAAO;AAAA,IACR;AAAA,IAEA,MAAM,OAAO,UAAU,GAAG,KAAK;AAAA,IAG/B,OAAO;AAAA;AAAA;AAAA,2BAGiB;AAAA;AAAA;AAAA,KAGtB;AAAA;AAAA;AAAA;AAAA,mBAIc;AAAA;AAAA,iEAE8C;AAAA;AAAA;AAAA;AAAA;AAAA,mBAK9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBASA;AAAA;AAAA;AAAA;AAAA,GAIhB,EACA,KAAK;AAAA,CAAI;AAAA,EAEX,OAAO;AAAA;AAAA,EAEN;AAAA;AAAA;AAAA;AAIK,IAAM,2BAA2B,CAAC,cAAuB;AAAA,EAC/D,MAAM,KAAK,aAAa,mBAAmB;AAAA,EAC3C,IAAI,CAAC;AAAA,IAAI,OAAO,CAAC;AAAA,EAEjB,MAAM,UAAU,eAAe,IAAI,EAAE;AAAA,EACrC,IAAI,CAAC,SAAS;AAAA,IACb,OAAO,CAAC;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,MAAM,KAAK,OAAO;AAAA,EACtC,eAAe,OAAO,EAAE;AAAA,EAExB,OAAO;AAAA;",
|
|
8
|
+
"debugId": "9DFF481135ABC22A64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
getIslandStoreServerSnapshot,
|
|
4
|
+
readIslandStore,
|
|
5
|
+
subscribeIslandStore
|
|
6
|
+
} from "./chunk-fygx2ymm.js";
|
|
7
|
+
|
|
8
|
+
// src/react/hooks/useIslandStore.ts
|
|
9
|
+
import { useSyncExternalStore } from "react";
|
|
10
|
+
var useIslandStore = (store, selector) => useSyncExternalStore((listener) => subscribeIslandStore(store, selector, () => {
|
|
11
|
+
listener();
|
|
12
|
+
}), () => readIslandStore(store, selector), () => getIslandStoreServerSnapshot(store, selector));
|
|
13
|
+
|
|
14
|
+
export { useIslandStore };
|
|
15
|
+
|
|
16
|
+
//# debugId=9AD9EB493DC2966664756E2164756E21
|
|
17
|
+
//# sourceMappingURL=chunk-pvpp4pvs.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/react/hooks/useIslandStore.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { useSyncExternalStore } from 'react';\nimport type { StoreApi } from 'zustand/vanilla';\nimport {\n\tgetIslandStoreServerSnapshot,\n\treadIslandStore,\n\tsubscribeIslandStore,\n\ttype IslandStoreState\n} from '../../client/islandStore';\n\nexport const useIslandStore = <TState extends IslandStoreState, TSelected>(\n\tstore: StoreApi<TState>,\n\tselector: (state: TState) => TSelected\n) =>\n\tuseSyncExternalStore(\n\t\t(listener) =>\n\t\t\tsubscribeIslandStore(store, selector, () => {\n\t\t\t\tlistener();\n\t\t\t}),\n\t\t() => readIslandStore(store, selector),\n\t\t() => getIslandStoreServerSnapshot(store, selector)\n\t);\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;AAAA;AASO,IAAM,iBAAiB,CAC7B,OACA,aAEA,qBACC,CAAC,aACA,qBAAqB,OAAO,UAAU,MAAM;AAAA,EAC3C,SAAS;AAAA,CACT,GACF,MAAM,gBAAgB,OAAO,QAAQ,GACrC,MAAM,6BAA6B,OAAO,QAAQ,CACnD;",
|
|
8
|
+
"debugId": "9AD9EB493DC2966664756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|