@absolutejs/absolute 0.19.0-beta.366 → 0.19.0-beta.368
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 +13 -8
- package/dist/angular/browser.js.map +4 -4
- package/dist/angular/components/core/streamingSlotRegistrar.js +4 -3
- package/dist/angular/components/core/streamingSlotRegistry.js +4 -3
- package/dist/angular/index.js +668 -622
- package/dist/angular/index.js.map +8 -8
- package/dist/build.js +24 -579
- package/dist/build.js.map +4 -10
- package/dist/client/index.js +45 -44
- package/dist/client/index.js.map +4 -4
- package/dist/index.js +1322 -1138
- package/dist/index.js.map +28 -22
- package/dist/react/components/browser/index.js +9 -20
- package/dist/react/components/index.js +17 -35
- package/dist/react/components/index.js.map +5 -6
- package/dist/react/index.js +1125 -1095
- package/dist/react/index.js.map +12 -12
- package/dist/react/server.js +3 -574
- package/dist/react/server.js.map +4 -11
- package/dist/src/core/pageHandlers.d.ts +1 -0
- package/dist/src/react/index.d.ts +1 -1
- package/dist/svelte/index.js +1506 -1460
- package/dist/svelte/index.js.map +8 -8
- package/dist/vue/components/index.js +13 -8
- package/dist/vue/components/index.js.map +5 -5
- package/dist/vue/index.js +667 -619
- package/dist/vue/index.js.map +8 -8
- package/package.json +1 -1
- package/dist/src/react/streamingSlotCollection.d.ts +0 -9
package/dist/index.js
CHANGED
|
@@ -78,81 +78,465 @@ var __legacyMetadataTS = (k, v) => {
|
|
|
78
78
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
79
79
|
var __require = import.meta.require;
|
|
80
80
|
|
|
81
|
-
//
|
|
82
|
-
var
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
// src/utils/escapeScriptContent.ts
|
|
82
|
+
var ESCAPE_LOOKUP, ESCAPE_REGEX, escapeScriptContent = (content) => content.replace(ESCAPE_REGEX, (char) => {
|
|
83
|
+
const escaped = ESCAPE_LOOKUP[char];
|
|
84
|
+
return escaped !== undefined ? escaped : char;
|
|
85
|
+
});
|
|
86
|
+
var init_escapeScriptContent = __esm(() => {
|
|
87
|
+
ESCAPE_LOOKUP = {
|
|
88
|
+
"\u2028": "\\u2028",
|
|
89
|
+
"\u2029": "\\u2029",
|
|
90
|
+
"&": "\\u0026",
|
|
91
|
+
"<": "\\u003C",
|
|
92
|
+
">": "\\u003E"
|
|
93
|
+
};
|
|
94
|
+
ESCAPE_REGEX = /[&><\u2028\u2029]/g;
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// src/core/islandPageContext.ts
|
|
98
|
+
var BOOTSTRAP_MANIFEST_KEY = "BootstrapClient", ISLAND_MARKER = 'data-island="true"', MANIFEST_MARKER = "__ABSOLUTE_MANIFEST__", ISLAND_STATE_MARKER = "__ABS_ISLAND_STATE__", CLOSING_HEAD_TAG2 = "</head>", buildIslandsHeadMarkup = (manifest) => {
|
|
99
|
+
const manifestScript = `<script>window.__ABSOLUTE_MANIFEST__ = ${JSON.stringify(manifest)}</script>`;
|
|
100
|
+
const islandStateScript = `<script>window.__ABS_ISLAND_STATE__ = ${JSON.stringify(globalThis.__ABS_ISLAND_STATE__ ?? {})}</script>`;
|
|
101
|
+
const bootstrapPath = manifest[BOOTSTRAP_MANIFEST_KEY];
|
|
102
|
+
const bootstrapScript = bootstrapPath ? `<script type="module" src="${bootstrapPath}"></script>` : "";
|
|
103
|
+
return `${manifestScript}${islandStateScript}${bootstrapScript}`;
|
|
104
|
+
}, injectHeadMarkup = (html, markup) => {
|
|
105
|
+
const closingHeadIndex = html.indexOf("</head>");
|
|
106
|
+
if (closingHeadIndex >= 0) {
|
|
107
|
+
return `${html.slice(0, closingHeadIndex)}${markup}${html.slice(closingHeadIndex)}`;
|
|
85
108
|
}
|
|
86
|
-
|
|
87
|
-
|
|
109
|
+
const openingBodyIndex = html.indexOf("<body");
|
|
110
|
+
if (openingBodyIndex >= 0) {
|
|
111
|
+
const bodyStart = html.indexOf(">", openingBodyIndex);
|
|
112
|
+
if (bodyStart >= 0) {
|
|
113
|
+
return `${html.slice(0, openingBodyIndex)}<head>${markup}</head>${html.slice(openingBodyIndex)}`;
|
|
114
|
+
}
|
|
88
115
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
116
|
+
return `<!DOCTYPE html><html><head>${markup}</head><body>${html}</body></html>`;
|
|
117
|
+
}, streamChunkToString2 = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true }), pipeStreamWithHeadInjection = (stream, markup) => {
|
|
118
|
+
const encoder = new TextEncoder;
|
|
119
|
+
const decoder = new TextDecoder;
|
|
120
|
+
const lookbehind = CLOSING_HEAD_TAG2.length - 1;
|
|
121
|
+
return new ReadableStream({
|
|
122
|
+
async start(controller) {
|
|
123
|
+
const reader = stream.getReader();
|
|
124
|
+
let injected = false;
|
|
125
|
+
let pending = "";
|
|
126
|
+
try {
|
|
127
|
+
for (;; ) {
|
|
128
|
+
const { done, value } = await reader.read();
|
|
129
|
+
if (done)
|
|
130
|
+
break;
|
|
131
|
+
if (!value)
|
|
132
|
+
continue;
|
|
133
|
+
pending += streamChunkToString2(value, decoder);
|
|
134
|
+
if (injected) {
|
|
135
|
+
controller.enqueue(encoder.encode(pending));
|
|
136
|
+
pending = "";
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
const headIndex = pending.indexOf(CLOSING_HEAD_TAG2);
|
|
140
|
+
if (headIndex >= 0) {
|
|
141
|
+
const next = `${pending.slice(0, headIndex)}${markup}${pending.slice(headIndex)}`;
|
|
142
|
+
controller.enqueue(encoder.encode(next));
|
|
143
|
+
pending = "";
|
|
144
|
+
injected = true;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (pending.length > lookbehind) {
|
|
148
|
+
const safeText = pending.slice(0, pending.length - lookbehind);
|
|
149
|
+
controller.enqueue(encoder.encode(safeText));
|
|
150
|
+
pending = pending.slice(-lookbehind);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
pending += decoder.decode();
|
|
154
|
+
if (!injected) {
|
|
155
|
+
pending = injectHeadMarkup(pending, markup);
|
|
156
|
+
}
|
|
157
|
+
if (pending.length > 0) {
|
|
158
|
+
controller.enqueue(encoder.encode(pending));
|
|
159
|
+
}
|
|
160
|
+
controller.close();
|
|
161
|
+
} catch (error) {
|
|
162
|
+
controller.error(error);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}, pipeStreamWithIslandMarkerDetection = (stream, markup) => {
|
|
167
|
+
const encoder = new TextEncoder;
|
|
168
|
+
const decoder = new TextDecoder;
|
|
169
|
+
const lookbehind = Math.max(ISLAND_MARKER.length, 1024);
|
|
170
|
+
return new ReadableStream({
|
|
171
|
+
async start(controller) {
|
|
172
|
+
const reader = stream.getReader();
|
|
173
|
+
let injected = false;
|
|
174
|
+
let pending = "";
|
|
175
|
+
try {
|
|
176
|
+
for (;; ) {
|
|
177
|
+
const { done, value } = await reader.read();
|
|
178
|
+
if (done)
|
|
179
|
+
break;
|
|
180
|
+
if (!value)
|
|
181
|
+
continue;
|
|
182
|
+
pending += streamChunkToString2(value, decoder);
|
|
183
|
+
if (injected) {
|
|
184
|
+
controller.enqueue(encoder.encode(pending));
|
|
185
|
+
pending = "";
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const markerIndex = pending.indexOf(ISLAND_MARKER);
|
|
189
|
+
if (markerIndex >= 0) {
|
|
190
|
+
const tagStart = pending.lastIndexOf("<", markerIndex);
|
|
191
|
+
const injectAt = tagStart >= 0 ? tagStart : markerIndex;
|
|
192
|
+
const next = `${pending.slice(0, injectAt)}${markup}${pending.slice(injectAt)}`;
|
|
193
|
+
controller.enqueue(encoder.encode(next));
|
|
194
|
+
pending = "";
|
|
195
|
+
injected = true;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (pending.length > lookbehind) {
|
|
199
|
+
const safeText = pending.slice(0, pending.length - lookbehind);
|
|
200
|
+
controller.enqueue(encoder.encode(safeText));
|
|
201
|
+
pending = pending.slice(-lookbehind);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
pending += decoder.decode();
|
|
205
|
+
if (pending.length > 0) {
|
|
206
|
+
controller.enqueue(encoder.encode(pending));
|
|
207
|
+
}
|
|
208
|
+
controller.close();
|
|
209
|
+
} catch (error) {
|
|
210
|
+
controller.error(error);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}, htmlContainsIslands = (html) => html.includes(ISLAND_MARKER), injectIslandPageContext = (html, options) => {
|
|
215
|
+
const manifest = globalThis.__absoluteManifest;
|
|
216
|
+
const hasIslands = options?.hasIslands ?? htmlContainsIslands(html);
|
|
217
|
+
if (!manifest || !hasIslands) {
|
|
218
|
+
return html;
|
|
98
219
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return false;
|
|
220
|
+
if (html.includes(MANIFEST_MARKER) || html.includes(ISLAND_STATE_MARKER)) {
|
|
221
|
+
return html;
|
|
102
222
|
}
|
|
103
|
-
|
|
104
|
-
|
|
223
|
+
return injectHeadMarkup(html, buildIslandsHeadMarkup(manifest));
|
|
224
|
+
}, injectIslandPageContextStream = (stream, options) => {
|
|
225
|
+
const manifest = globalThis.__absoluteManifest;
|
|
226
|
+
if (!manifest)
|
|
227
|
+
return stream;
|
|
228
|
+
const markup = buildIslandsHeadMarkup(manifest);
|
|
229
|
+
if (options?.hasIslands === true) {
|
|
230
|
+
return pipeStreamWithHeadInjection(stream, markup);
|
|
105
231
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return "content" in data && typeof data.content === "string" && "messageId" in data && "conversationId" in data;
|
|
109
|
-
case "thinking":
|
|
110
|
-
return "content" in data && typeof data.content === "string" && "messageId" in data && "conversationId" in data;
|
|
111
|
-
case "tool_status":
|
|
112
|
-
return "name" in data && "status" in data && "messageId" in data && "conversationId" in data;
|
|
113
|
-
case "image":
|
|
114
|
-
return "data" in data && typeof data.data === "string" && "format" in data && typeof data.format === "string" && "isPartial" in data && typeof data.isPartial === "boolean" && "messageId" in data && "conversationId" in data;
|
|
115
|
-
case "complete":
|
|
116
|
-
return "messageId" in data && "conversationId" in data;
|
|
117
|
-
case "rag_retrieved":
|
|
118
|
-
return "conversationId" in data && "messageId" in data && "sources" in data && Array.isArray(data.sources);
|
|
119
|
-
case "error":
|
|
120
|
-
return "message" in data && typeof data.message === "string";
|
|
121
|
-
default:
|
|
122
|
-
return false;
|
|
232
|
+
if (options?.hasIslands === false) {
|
|
233
|
+
return stream;
|
|
123
234
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
235
|
+
return pipeStreamWithIslandMarkerDetection(stream, markup);
|
|
236
|
+
}, setCurrentIslandManifest = (manifest) => {
|
|
237
|
+
globalThis.__absoluteManifest = manifest;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
// src/utils/ssrErrorPage.ts
|
|
241
|
+
var ssrErrorPage = (framework, error) => {
|
|
242
|
+
const frameworkColors = {
|
|
243
|
+
angular: "#dd0031",
|
|
244
|
+
html: "#e34c26",
|
|
245
|
+
htmx: "#1a365d",
|
|
246
|
+
react: "#61dafb",
|
|
247
|
+
svelte: "#ff3e00",
|
|
248
|
+
vue: "#42b883"
|
|
249
|
+
};
|
|
250
|
+
const accent = frameworkColors[framework] ?? "#94a3b8";
|
|
251
|
+
const label = framework.charAt(0).toUpperCase() + framework.slice(1);
|
|
252
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
253
|
+
return `<!DOCTYPE html>
|
|
254
|
+
<html>
|
|
255
|
+
<head>
|
|
256
|
+
<meta charset="utf-8">
|
|
257
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
258
|
+
<title>SSR Error - AbsoluteJS</title>
|
|
259
|
+
<style>
|
|
260
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
261
|
+
body{min-height:100vh;background:linear-gradient(135deg,rgba(15,23,42,0.98) 0%,rgba(30,41,59,0.98) 100%);color:#e2e8f0;font-family:"JetBrains Mono","Fira Code",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:14px;line-height:1.6;display:flex;align-items:flex-start;justify-content:center;padding:32px}
|
|
262
|
+
.card{max-width:720px;width:100%;background:rgba(30,41,59,0.6);border:1px solid rgba(71,85,105,0.5);border-radius:16px;box-shadow:0 25px 50px -12px rgba(0,0,0,0.5),0 0 0 1px rgba(255,255,255,0.05);overflow:hidden}
|
|
263
|
+
.header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:20px 24px;background:rgba(15,23,42,0.5);border-bottom:1px solid rgba(71,85,105,0.4)}
|
|
264
|
+
.brand{font-weight:700;font-size:20px;color:#fff;letter-spacing:-0.02em}
|
|
265
|
+
.badge{padding:5px 10px;border-radius:8px;font-size:12px;font-weight:600;background:${accent};color:#fff;opacity:0.95;box-shadow:0 2px 4px rgba(0,0,0,0.2)}
|
|
266
|
+
.kind{color:#94a3b8;font-size:13px;font-weight:500}
|
|
267
|
+
.content{padding:24px}
|
|
268
|
+
.label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.08em;color:#94a3b8;margin-bottom:8px}
|
|
269
|
+
.message{margin:0;padding:16px 20px;background:rgba(239,68,68,0.12);border:1px solid rgba(239,68,68,0.25);border-radius:10px;overflow-x:auto;white-space:pre-wrap;word-break:break-word;color:#fca5a5;font-size:13px;line-height:1.5}
|
|
270
|
+
.hint{margin-top:20px;padding:12px 20px;background:rgba(71,85,105,0.3);border-radius:10px;border:1px solid rgba(71,85,105,0.4);color:#cbd5e1;font-size:13px}
|
|
271
|
+
</style>
|
|
272
|
+
</head>
|
|
273
|
+
<body>
|
|
274
|
+
<div class="card">
|
|
275
|
+
<div class="header">
|
|
276
|
+
<div style="display:flex;align-items:center;gap:12px">
|
|
277
|
+
<span class="brand">AbsoluteJS</span>
|
|
278
|
+
<span class="badge">${label}</span>
|
|
279
|
+
</div>
|
|
280
|
+
<span class="kind">Server Render Error</span>
|
|
281
|
+
</div>
|
|
282
|
+
<div class="content">
|
|
283
|
+
<div class="label">What went wrong</div>
|
|
284
|
+
<pre class="message">${message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</pre>
|
|
285
|
+
<div class="hint">A component threw during server-side rendering. Check the terminal for the full stack trace.</div>
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
288
|
+
</body>
|
|
289
|
+
</html>`;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// src/utils/stringModifiers.ts
|
|
293
|
+
var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9\-_]+/g, "").replace(/[-_]{2,}/g, "-"), toKebab = (str) => normalizeSlug(str).replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), toPascal = (str) => {
|
|
294
|
+
if (!str.includes("-") && !str.includes("_")) {
|
|
295
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
127
296
|
}
|
|
128
|
-
|
|
129
|
-
|
|
297
|
+
return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
|
|
298
|
+
}, toScreamingSnake = (str) => str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase();
|
|
299
|
+
|
|
300
|
+
// src/utils/resolveConvention.ts
|
|
301
|
+
import { basename } from "path";
|
|
302
|
+
var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boolean(value) && typeof value === "object", getMap = () => {
|
|
303
|
+
const value = Reflect.get(globalThis, CONVENTIONS_KEY);
|
|
304
|
+
if (isConventionsMap(value))
|
|
305
|
+
return value;
|
|
306
|
+
const empty = {};
|
|
307
|
+
return empty;
|
|
308
|
+
}, derivePageName = (pagePath) => {
|
|
309
|
+
const base = basename(pagePath);
|
|
310
|
+
const dotIndex = base.indexOf(".");
|
|
311
|
+
const name = dotIndex > 0 ? base.slice(0, dotIndex) : base;
|
|
312
|
+
return toPascal(name);
|
|
313
|
+
}, resolveErrorConventionPath = (framework, pageName) => {
|
|
314
|
+
const conventions = getMap()[framework];
|
|
315
|
+
if (!conventions)
|
|
316
|
+
return;
|
|
317
|
+
return conventions.pages?.[pageName]?.error ?? conventions.defaults?.error;
|
|
318
|
+
}, resolveNotFoundConventionPath = (framework) => getMap()[framework]?.defaults?.notFound, setConventions = (map) => {
|
|
319
|
+
Reflect.set(globalThis, CONVENTIONS_KEY, map);
|
|
320
|
+
}, isDev = () => true, buildErrorProps = (error) => {
|
|
321
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
322
|
+
const stack = isDev() && error instanceof Error ? error.stack : undefined;
|
|
323
|
+
return { error: { message, stack } };
|
|
324
|
+
}, renderReactError = async (conventionPath, errorProps) => {
|
|
325
|
+
const { createElement } = await import("react");
|
|
326
|
+
const { renderToReadableStream } = await import("react-dom/server");
|
|
327
|
+
const mod = await import(conventionPath);
|
|
328
|
+
const [firstKey] = Object.keys(mod);
|
|
329
|
+
const ErrorComponent = mod.default ?? (firstKey ? mod[firstKey] : undefined);
|
|
330
|
+
const element = createElement(ErrorComponent, errorProps);
|
|
331
|
+
const stream = await renderToReadableStream(element);
|
|
332
|
+
return new Response(stream, {
|
|
333
|
+
headers: { "Content-Type": "text/html" },
|
|
334
|
+
status: 500
|
|
335
|
+
});
|
|
336
|
+
}, renderSvelteError = async (conventionPath, errorProps) => {
|
|
337
|
+
const { render } = await import("svelte/server");
|
|
338
|
+
const mod = await import(conventionPath);
|
|
339
|
+
const ErrorComponent = mod.default;
|
|
340
|
+
const { head, body } = render(ErrorComponent, {
|
|
341
|
+
props: errorProps
|
|
342
|
+
});
|
|
343
|
+
const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
|
|
344
|
+
return new Response(html, {
|
|
345
|
+
headers: { "Content-Type": "text/html" },
|
|
346
|
+
status: 500
|
|
347
|
+
});
|
|
348
|
+
}, unescapeVueStyles = (ssrBody) => {
|
|
349
|
+
let styles = "";
|
|
350
|
+
const body = ssrBody.replace(/<style>([\s\S]*?)<\/style>/g, (_, css) => {
|
|
351
|
+
styles += `<style>${css.replace(/"/g, '"').replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</style>`;
|
|
352
|
+
return "";
|
|
353
|
+
});
|
|
354
|
+
return { body, styles };
|
|
355
|
+
}, renderVueError = async (conventionPath, errorProps) => {
|
|
356
|
+
const { createSSRApp, h } = await import("vue");
|
|
357
|
+
const { renderToString } = await import("vue/server-renderer");
|
|
358
|
+
const mod = await import(conventionPath);
|
|
359
|
+
const ErrorComponent = mod.default;
|
|
360
|
+
const app = createSSRApp({
|
|
361
|
+
render: () => h(ErrorComponent, errorProps)
|
|
362
|
+
});
|
|
363
|
+
const rawBody = await renderToString(app);
|
|
364
|
+
const { styles, body } = unescapeVueStyles(rawBody);
|
|
365
|
+
const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
|
|
366
|
+
return new Response(html, {
|
|
367
|
+
headers: { "Content-Type": "text/html" },
|
|
368
|
+
status: 500
|
|
369
|
+
});
|
|
370
|
+
}, renderAngularError = async (conventionPath, errorProps) => {
|
|
371
|
+
const mod = await import(conventionPath);
|
|
372
|
+
const renderError = mod.default ?? mod.renderError;
|
|
373
|
+
if (typeof renderError !== "function")
|
|
374
|
+
return null;
|
|
375
|
+
const html = renderError(errorProps);
|
|
376
|
+
return new Response(html, {
|
|
377
|
+
headers: { "Content-Type": "text/html" },
|
|
378
|
+
status: 500
|
|
379
|
+
});
|
|
380
|
+
}, logConventionRenderError = (framework, label, renderError) => {
|
|
381
|
+
const message = renderError instanceof Error ? renderError.message : "";
|
|
382
|
+
if (message.includes("Cannot find module") || message.includes("Cannot find package") || message.includes("not found in module")) {
|
|
383
|
+
console.error(`[SSR] Convention ${label} page for ${framework} failed: missing framework package. Ensure the ${framework} runtime is installed (e.g. bun add ${framework === "react" ? "react react-dom" : framework}).`);
|
|
384
|
+
return;
|
|
130
385
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
386
|
+
console.error(`[SSR] Failed to render ${framework} convention ${label} page:`, renderError);
|
|
387
|
+
}, ERROR_RENDERERS, renderConventionError = async (framework, pageName, error) => {
|
|
388
|
+
const conventionPath = resolveErrorConventionPath(framework, pageName);
|
|
389
|
+
if (!conventionPath)
|
|
390
|
+
return null;
|
|
391
|
+
const errorProps = buildErrorProps(error);
|
|
392
|
+
const renderer = ERROR_RENDERERS[framework];
|
|
393
|
+
if (!renderer)
|
|
394
|
+
return null;
|
|
395
|
+
try {
|
|
396
|
+
return await renderer(conventionPath, errorProps);
|
|
397
|
+
} catch (renderError) {
|
|
398
|
+
logConventionRenderError(framework, "error", renderError);
|
|
399
|
+
}
|
|
400
|
+
return null;
|
|
401
|
+
}, renderReactNotFound = async (conventionPath) => {
|
|
402
|
+
const { createElement } = await import("react");
|
|
403
|
+
const { renderToReadableStream } = await import("react-dom/server");
|
|
404
|
+
const mod = await import(conventionPath);
|
|
405
|
+
const [nfKey] = Object.keys(mod);
|
|
406
|
+
const NotFoundComponent = mod.default ?? (nfKey ? mod[nfKey] : undefined);
|
|
407
|
+
const element = createElement(NotFoundComponent);
|
|
408
|
+
const stream = await renderToReadableStream(element);
|
|
409
|
+
return new Response(stream, {
|
|
410
|
+
headers: { "Content-Type": "text/html" },
|
|
411
|
+
status: 404
|
|
412
|
+
});
|
|
413
|
+
}, renderSvelteNotFound = async (conventionPath) => {
|
|
414
|
+
const { render } = await import("svelte/server");
|
|
415
|
+
const mod = await import(conventionPath);
|
|
416
|
+
const NotFoundComponent = mod.default;
|
|
417
|
+
const { head, body } = render(NotFoundComponent);
|
|
418
|
+
const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
|
|
419
|
+
return new Response(html, {
|
|
420
|
+
headers: { "Content-Type": "text/html" },
|
|
421
|
+
status: 404
|
|
422
|
+
});
|
|
423
|
+
}, renderVueNotFound = async (conventionPath) => {
|
|
424
|
+
const { createSSRApp, h } = await import("vue");
|
|
425
|
+
const { renderToString } = await import("vue/server-renderer");
|
|
426
|
+
const mod = await import(conventionPath);
|
|
427
|
+
const NotFoundComponent = mod.default;
|
|
428
|
+
const app = createSSRApp({
|
|
429
|
+
render: () => h(NotFoundComponent)
|
|
430
|
+
});
|
|
431
|
+
const rawBody = await renderToString(app);
|
|
432
|
+
const { styles, body } = unescapeVueStyles(rawBody);
|
|
433
|
+
const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
|
|
434
|
+
return new Response(html, {
|
|
435
|
+
headers: { "Content-Type": "text/html" },
|
|
436
|
+
status: 404
|
|
437
|
+
});
|
|
438
|
+
}, renderAngularNotFound = async (conventionPath) => {
|
|
439
|
+
const mod = await import(conventionPath);
|
|
440
|
+
const renderNotFound = mod.default ?? mod.renderNotFound;
|
|
441
|
+
if (typeof renderNotFound !== "function")
|
|
442
|
+
return null;
|
|
443
|
+
const html = renderNotFound();
|
|
444
|
+
return new Response(html, {
|
|
445
|
+
headers: { "Content-Type": "text/html" },
|
|
446
|
+
status: 404
|
|
447
|
+
});
|
|
448
|
+
}, NOT_FOUND_RENDERERS, renderConventionNotFound = async (framework) => {
|
|
449
|
+
const conventionPath = resolveNotFoundConventionPath(framework);
|
|
450
|
+
if (!conventionPath)
|
|
451
|
+
return null;
|
|
452
|
+
const renderer = NOT_FOUND_RENDERERS[framework];
|
|
453
|
+
if (!renderer)
|
|
454
|
+
return null;
|
|
455
|
+
try {
|
|
456
|
+
return await renderer(conventionPath);
|
|
457
|
+
} catch (renderError) {
|
|
458
|
+
logConventionRenderError(framework, "not-found", renderError);
|
|
144
459
|
}
|
|
460
|
+
return null;
|
|
461
|
+
}, NOT_FOUND_PRIORITY, renderFirstNotFound = async () => {
|
|
462
|
+
for (const framework of NOT_FOUND_PRIORITY) {
|
|
463
|
+
if (!getMap()[framework]?.defaults?.notFound)
|
|
464
|
+
continue;
|
|
465
|
+
const response = await renderConventionNotFound(framework);
|
|
466
|
+
if (response)
|
|
467
|
+
return response;
|
|
468
|
+
}
|
|
469
|
+
return null;
|
|
145
470
|
};
|
|
471
|
+
var init_resolveConvention = __esm(() => {
|
|
472
|
+
ERROR_RENDERERS = {
|
|
473
|
+
angular: renderAngularError,
|
|
474
|
+
react: renderReactError,
|
|
475
|
+
svelte: renderSvelteError,
|
|
476
|
+
vue: renderVueError
|
|
477
|
+
};
|
|
478
|
+
NOT_FOUND_RENDERERS = {
|
|
479
|
+
angular: renderAngularNotFound,
|
|
480
|
+
react: renderReactNotFound,
|
|
481
|
+
svelte: renderSvelteNotFound,
|
|
482
|
+
vue: renderVueNotFound
|
|
483
|
+
};
|
|
484
|
+
NOT_FOUND_PRIORITY = [
|
|
485
|
+
"react",
|
|
486
|
+
"svelte",
|
|
487
|
+
"vue",
|
|
488
|
+
"angular"
|
|
489
|
+
];
|
|
490
|
+
});
|
|
146
491
|
|
|
147
|
-
//
|
|
148
|
-
var
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
492
|
+
// src/react/pageHandler.ts
|
|
493
|
+
var ssrDirty = false, buildDirtyResponse = (index, maybeProps) => {
|
|
494
|
+
const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
|
|
495
|
+
const dirtyFlag = "window.__SSR_DIRTY__=true;";
|
|
496
|
+
const refreshSetup = "window.__REFRESH_BUFFER__=[];" + "window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};" + "window.$RefreshSig$=function(){return function(t){return t}};";
|
|
497
|
+
const inlineScript = `${propsScript}${dirtyFlag}${refreshSetup}`;
|
|
498
|
+
const html = `<!DOCTYPE html><html><head></head><body>` + `<script>${inlineScript}</script>` + `<script type="module" src="${index}"></script>` + `</body></html>`;
|
|
499
|
+
return new Response(html, {
|
|
500
|
+
headers: { "Content-Type": "text/html" }
|
|
501
|
+
});
|
|
502
|
+
}, handleReactPageRequest = async (PageComponent, index, ...props) => {
|
|
503
|
+
const [maybeProps] = props;
|
|
504
|
+
if (ssrDirty) {
|
|
505
|
+
return buildDirtyResponse(index, maybeProps);
|
|
506
|
+
}
|
|
507
|
+
try {
|
|
508
|
+
const { createElement } = await import("react");
|
|
509
|
+
const { renderToReadableStream } = await import("react-dom/server");
|
|
510
|
+
const element = maybeProps !== undefined ? createElement(PageComponent, maybeProps) : createElement(PageComponent);
|
|
511
|
+
const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
|
|
512
|
+
const refreshSetup = "window.__REFRESH_BUFFER__=[];window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};window.$RefreshSig$=function(){return function(t){return t}};";
|
|
513
|
+
const stream = await renderToReadableStream(element, {
|
|
514
|
+
bootstrapModules: [index],
|
|
515
|
+
bootstrapScriptContent: propsScript + refreshSetup || undefined,
|
|
516
|
+
onError(error) {
|
|
517
|
+
console.error("[SSR] React streaming error:", error);
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
const htmlStream = injectIslandPageContextStream(stream);
|
|
521
|
+
return new Response(htmlStream, {
|
|
522
|
+
headers: { "Content-Type": "text/html" }
|
|
523
|
+
});
|
|
524
|
+
} catch (error) {
|
|
525
|
+
console.error("[SSR] React render error:", error);
|
|
526
|
+
const pageName = PageComponent.name || PageComponent.displayName || "";
|
|
527
|
+
const conventionResponse = await renderConventionError("react", pageName, error);
|
|
528
|
+
if (conventionResponse)
|
|
529
|
+
return conventionResponse;
|
|
530
|
+
return new Response(ssrErrorPage("react", error), {
|
|
531
|
+
headers: { "Content-Type": "text/html" },
|
|
532
|
+
status: 500
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
}, invalidateReactSsrCache = () => {
|
|
536
|
+
ssrDirty = true;
|
|
537
|
+
};
|
|
538
|
+
var init_pageHandler = __esm(() => {
|
|
539
|
+
init_resolveConvention();
|
|
156
540
|
});
|
|
157
541
|
|
|
158
542
|
// src/core/islandManifest.ts
|
|
@@ -206,6 +590,30 @@ var defineIslandComponent = (component, options) => ({
|
|
|
206
590
|
}, serializeIslandProps = (props) => JSON.stringify(props ?? {});
|
|
207
591
|
var init_islands = () => {};
|
|
208
592
|
|
|
593
|
+
// src/core/islandMarkupAttributes.ts
|
|
594
|
+
var getIslandMarkerAttributes = (props, islandId) => ({
|
|
595
|
+
"data-component": props.component,
|
|
596
|
+
"data-framework": props.framework,
|
|
597
|
+
"data-hydrate": props.hydrate ?? "load",
|
|
598
|
+
"data-island": "true",
|
|
599
|
+
...islandId ? { "data-island-id": islandId } : {},
|
|
600
|
+
"data-props": serializeIslandProps(props.props)
|
|
601
|
+
}), escapeHtmlAttribute = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">"), serializeIslandAttributes = (attributes) => Object.entries(attributes).map(([key, value]) => `${key}="${escapeHtmlAttribute(value)}"`).join(" ");
|
|
602
|
+
var init_islandMarkupAttributes = __esm(() => {
|
|
603
|
+
init_islands();
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
// src/core/currentIslandRegistry.ts
|
|
607
|
+
var requireCurrentIslandRegistry = () => {
|
|
608
|
+
const registry = globalThis.__absoluteIslandRegistry;
|
|
609
|
+
if (!registry) {
|
|
610
|
+
throw new Error("No island registry is active. Configure `islands.registry` in absolute.config.ts before rendering <Island />.");
|
|
611
|
+
}
|
|
612
|
+
return registry;
|
|
613
|
+
}, setCurrentIslandRegistry = (registry) => {
|
|
614
|
+
globalThis.__absoluteIslandRegistry = registry;
|
|
615
|
+
};
|
|
616
|
+
|
|
209
617
|
// src/angular/injectorPatch.ts
|
|
210
618
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
211
619
|
import { dirname, join, resolve } from "path";
|
|
@@ -360,14 +768,6 @@ var init_angularDeps = __esm(() => {
|
|
|
360
768
|
init_resolveAngularPackage();
|
|
361
769
|
});
|
|
362
770
|
|
|
363
|
-
// src/utils/stringModifiers.ts
|
|
364
|
-
var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9\-_]+/g, "").replace(/[-_]{2,}/g, "-"), toKebab = (str) => normalizeSlug(str).replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), toPascal = (str) => {
|
|
365
|
-
if (!str.includes("-") && !str.includes("_")) {
|
|
366
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
367
|
-
}
|
|
368
|
-
return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
|
|
369
|
-
}, toScreamingSnake = (str) => str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase();
|
|
370
|
-
|
|
371
771
|
// src/utils/registerClientScript.ts
|
|
372
772
|
var scriptRegistry, requestCounter = 0, getRequestId = () => `req_${Date.now()}_${++requestCounter}`, ssrContextGetter = null, getSsrContextId = () => ssrContextGetter?.() || Object.getOwnPropertyDescriptor(globalThis, "__absolutejs_requestId")?.value, registerClientScript = (script, requestId) => {
|
|
373
773
|
const id = requestId || getSsrContextId() || getRequestId();
|
|
@@ -741,6 +1141,14 @@ var init_islandSsr = __esm(() => {
|
|
|
741
1141
|
init_islands2();
|
|
742
1142
|
});
|
|
743
1143
|
|
|
1144
|
+
// src/constants.ts
|
|
1145
|
+
var ANGULAR_INIT_TIMEOUT_MS = 500, ANSI_ESCAPE_LENGTH = 3, ASCII_SPACE = 32, BASE_36_RADIX = 36, BUN_BUILD_WARNING_SUPPRESSION = "wildcard sideEffects are not supported yet", BODY_SLICE_LENGTH = 2000, BYTES_PER_KILOBYTE = 1024, CLI_ARGS_OFFSET = 3, CSS_ERROR_RESOLVE_DELAY_MS = 50, CSS_MAX_CHECK_ATTEMPTS = 10, CSS_MAX_PARSE_TIMEOUT_MS = 500, CSS_SHEET_READY_TIMEOUT_MS = 100, DEFAULT_CHUNK_SIZE = 16384, DEFAULT_DEBOUNCE_MS = 15, DEFAULT_PORT = 3000, DEV_SERVER_RESTART_DEBOUNCE_MS = 100, DOM_UPDATE_DELAY_MS = 50, FILE_PROTOCOL_PREFIX_LENGTH = 7, FOCUS_ID_PREFIX_LENGTH = 3, FOCUS_IDX_PREFIX_LENGTH = 4, FOCUS_NAME_PREFIX_LENGTH = 5, HMR_UPDATE_TIMEOUT_MS = 2000, HOOK_SIGNATURE_LENGTH = 12, EXCLUDE_LAST_OFFSET = -1, HOURS_IN_DAY = 24, HOURS_IN_HALF_DAY = 12, MAX_ERROR_LENGTH = 200, MAX_RECONNECT_ATTEMPTS = 60, MILLISECONDS_IN_A_SECOND = 1000, MINUTES_IN_AN_HOUR = 60, SECONDS_IN_A_MINUTE = 60, MILLISECONDS_IN_A_MINUTE, MILLISECONDS_IN_A_DAY, OVERLAY_FADE_DURATION_MS = 150, PING_INTERVAL_MS = 30000, RAF_BATCH_COUNT = 3, RANDOM_ID_END_INDEX = 11, REBUILD_BATCH_DELAY_MS = 10, REBUILD_RELOAD_DELAY_MS = 200, RECONNECT_INITIAL_DELAY_MS = 500, RECONNECT_POLL_INTERVAL_MS = 300, SIGINT_EXIT_CODE = 130, SIGTERM_EXIT_CODE = 143, SVELTE_CSS_LOAD_TIMEOUT_MS = 500, TIME_PRECISION = 2, TWO_THIRDS, UNFOUND_INDEX = -1, WEBSOCKET_NORMAL_CLOSURE = 1000;
|
|
1146
|
+
var init_constants = __esm(() => {
|
|
1147
|
+
MILLISECONDS_IN_A_MINUTE = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE;
|
|
1148
|
+
MILLISECONDS_IN_A_DAY = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE * MINUTES_IN_AN_HOUR * HOURS_IN_DAY;
|
|
1149
|
+
TWO_THIRDS = 2 / 3;
|
|
1150
|
+
});
|
|
1151
|
+
|
|
744
1152
|
// src/svelte/lowerIslandSyntax.ts
|
|
745
1153
|
var ISLAND_TAG_RE, extractBracedExpression = (text, braceStart) => {
|
|
746
1154
|
let depth = 0;
|
|
@@ -815,7 +1223,7 @@ var init_lowerIslandSyntax = __esm(() => {
|
|
|
815
1223
|
|
|
816
1224
|
// src/core/svelteServerModule.ts
|
|
817
1225
|
import { mkdir, readdir } from "fs/promises";
|
|
818
|
-
import { basename, dirname as dirname2, extname, join as join2, relative, resolve as resolve3 } from "path";
|
|
1226
|
+
import { basename as basename2, dirname as dirname2, extname, join as join2, relative, resolve as resolve3 } from "path";
|
|
819
1227
|
var serverCacheRoot, compiledModuleCache, originalSourcePathCache, transpiler, ensureRelativeImportPath = (from, target) => {
|
|
820
1228
|
const importPath = relative(dirname2(from), target).replace(/\\/g, "/");
|
|
821
1229
|
return importPath.startsWith(".") ? importPath : `./${importPath}`;
|
|
@@ -846,7 +1254,7 @@ var serverCacheRoot, compiledModuleCache, originalSourcePathCache, transpiler, e
|
|
|
846
1254
|
return found;
|
|
847
1255
|
}
|
|
848
1256
|
return searchDirectoryLevel(nextStack, targetFileName);
|
|
849
|
-
}, findSourceFileByBasename = async (searchRoot, targetFileName) => searchDirectoryLevel([searchRoot], targetFileName), normalizeBuiltSvelteFileName = (sourcePath) =>
|
|
1257
|
+
}, findSourceFileByBasename = async (searchRoot, targetFileName) => searchDirectoryLevel([searchRoot], targetFileName), normalizeBuiltSvelteFileName = (sourcePath) => basename2(sourcePath).replace(/-[a-z0-9]{6,}(?=\.svelte$)/i, ""), resolveOriginalSourcePath = async (sourcePath) => {
|
|
850
1258
|
const cachedPath = originalSourcePathCache.get(sourcePath);
|
|
851
1259
|
if (cachedPath !== undefined) {
|
|
852
1260
|
return cachedPath;
|
|
@@ -982,19 +1390,6 @@ var init_svelteServerModule = __esm(() => {
|
|
|
982
1390
|
});
|
|
983
1391
|
});
|
|
984
1392
|
|
|
985
|
-
// src/core/islandMarkupAttributes.ts
|
|
986
|
-
var getIslandMarkerAttributes = (props, islandId) => ({
|
|
987
|
-
"data-component": props.component,
|
|
988
|
-
"data-framework": props.framework,
|
|
989
|
-
"data-hydrate": props.hydrate ?? "load",
|
|
990
|
-
"data-island": "true",
|
|
991
|
-
...islandId ? { "data-island-id": islandId } : {},
|
|
992
|
-
"data-props": serializeIslandProps(props.props)
|
|
993
|
-
}), escapeHtmlAttribute = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">"), serializeIslandAttributes = (attributes) => Object.entries(attributes).map(([key, value]) => `${key}="${escapeHtmlAttribute(value)}"`).join(" ");
|
|
994
|
-
var init_islandMarkupAttributes = __esm(() => {
|
|
995
|
-
init_islands();
|
|
996
|
-
});
|
|
997
|
-
|
|
998
1393
|
// src/core/renderIslandMarkup.ts
|
|
999
1394
|
var islandSequence = 0, resolvedServerComponentCache, resolvedServerBuildComponentCache, nextIslandId = () => {
|
|
1000
1395
|
islandSequence += 1;
|
|
@@ -1123,6 +1518,75 @@ var init_renderIslandMarkup = __esm(() => {
|
|
|
1123
1518
|
resolvedServerBuildComponentCache = new Map;
|
|
1124
1519
|
});
|
|
1125
1520
|
|
|
1521
|
+
// types/typeGuards.ts
|
|
1522
|
+
var isValidAIClientMessage = (data) => {
|
|
1523
|
+
if (!data || typeof data !== "object") {
|
|
1524
|
+
return false;
|
|
1525
|
+
}
|
|
1526
|
+
if (!("type" in data) || typeof data.type !== "string") {
|
|
1527
|
+
return false;
|
|
1528
|
+
}
|
|
1529
|
+
switch (data.type) {
|
|
1530
|
+
case "message":
|
|
1531
|
+
return "content" in data && typeof data.content === "string";
|
|
1532
|
+
case "cancel":
|
|
1533
|
+
return "conversationId" in data && typeof data.conversationId === "string";
|
|
1534
|
+
case "branch":
|
|
1535
|
+
return "messageId" in data && typeof data.messageId === "string" && "content" in data && typeof data.content === "string" && "conversationId" in data && typeof data.conversationId === "string";
|
|
1536
|
+
default:
|
|
1537
|
+
return false;
|
|
1538
|
+
}
|
|
1539
|
+
}, isValidAIServerMessage = (data) => {
|
|
1540
|
+
if (!data || typeof data !== "object") {
|
|
1541
|
+
return false;
|
|
1542
|
+
}
|
|
1543
|
+
if (!("type" in data) || typeof data.type !== "string") {
|
|
1544
|
+
return false;
|
|
1545
|
+
}
|
|
1546
|
+
switch (data.type) {
|
|
1547
|
+
case "chunk":
|
|
1548
|
+
return "content" in data && typeof data.content === "string" && "messageId" in data && "conversationId" in data;
|
|
1549
|
+
case "thinking":
|
|
1550
|
+
return "content" in data && typeof data.content === "string" && "messageId" in data && "conversationId" in data;
|
|
1551
|
+
case "tool_status":
|
|
1552
|
+
return "name" in data && "status" in data && "messageId" in data && "conversationId" in data;
|
|
1553
|
+
case "image":
|
|
1554
|
+
return "data" in data && typeof data.data === "string" && "format" in data && typeof data.format === "string" && "isPartial" in data && typeof data.isPartial === "boolean" && "messageId" in data && "conversationId" in data;
|
|
1555
|
+
case "complete":
|
|
1556
|
+
return "messageId" in data && "conversationId" in data;
|
|
1557
|
+
case "rag_retrieved":
|
|
1558
|
+
return "conversationId" in data && "messageId" in data && "sources" in data && Array.isArray(data.sources);
|
|
1559
|
+
case "error":
|
|
1560
|
+
return "message" in data && typeof data.message === "string";
|
|
1561
|
+
default:
|
|
1562
|
+
return false;
|
|
1563
|
+
}
|
|
1564
|
+
}, isValidHMRClientMessage = (data) => {
|
|
1565
|
+
if (!data || typeof data !== "object") {
|
|
1566
|
+
return false;
|
|
1567
|
+
}
|
|
1568
|
+
if (!("type" in data) || typeof data.type !== "string") {
|
|
1569
|
+
return false;
|
|
1570
|
+
}
|
|
1571
|
+
switch (data.type) {
|
|
1572
|
+
case "ping":
|
|
1573
|
+
return true;
|
|
1574
|
+
case "ready":
|
|
1575
|
+
return true;
|
|
1576
|
+
case "request-rebuild":
|
|
1577
|
+
return true;
|
|
1578
|
+
case "hydration-error":
|
|
1579
|
+
return true;
|
|
1580
|
+
case "hmr-timing":
|
|
1581
|
+
return true;
|
|
1582
|
+
default:
|
|
1583
|
+
return false;
|
|
1584
|
+
}
|
|
1585
|
+
};
|
|
1586
|
+
|
|
1587
|
+
// types/websocket.ts
|
|
1588
|
+
var WS_READY_STATE_OPEN = 1;
|
|
1589
|
+
|
|
1126
1590
|
// node_modules/typescript/lib/typescript.js
|
|
1127
1591
|
var require_typescript = __commonJS((exports, module) => {
|
|
1128
1592
|
var __dirname = "/home/alexkahn/abs/absolutejs/node_modules/typescript/lib", __filename = "/home/alexkahn/abs/absolutejs/node_modules/typescript/lib/typescript.js";
|
|
@@ -1416,7 +1880,7 @@ var require_typescript = __commonJS((exports, module) => {
|
|
|
1416
1880
|
codefix: () => ts_codefix_exports,
|
|
1417
1881
|
collapseTextChangeRangesAcrossMultipleVersions: () => collapseTextChangeRangesAcrossMultipleVersions,
|
|
1418
1882
|
collectExternalModuleInfo: () => collectExternalModuleInfo,
|
|
1419
|
-
combine: () =>
|
|
1883
|
+
combine: () => combine2,
|
|
1420
1884
|
combinePaths: () => combinePaths,
|
|
1421
1885
|
commandLineOptionOfCustomType: () => commandLineOptionOfCustomType,
|
|
1422
1886
|
commentPragmas: () => commentPragmas,
|
|
@@ -3991,7 +4455,7 @@ var require_typescript = __commonJS((exports, module) => {
|
|
|
3991
4455
|
to.push(value);
|
|
3992
4456
|
return to;
|
|
3993
4457
|
}
|
|
3994
|
-
function
|
|
4458
|
+
function combine2(xs, ys) {
|
|
3995
4459
|
if (xs === undefined)
|
|
3996
4460
|
return ys;
|
|
3997
4461
|
if (ys === undefined)
|
|
@@ -109092,10 +109556,10 @@ ${lanes.join(`
|
|
|
109092
109556
|
}
|
|
109093
109557
|
function getDefaultLibFilePriority(a) {
|
|
109094
109558
|
if (containsPath(defaultLibraryPath, a.fileName, false)) {
|
|
109095
|
-
const
|
|
109096
|
-
if (
|
|
109559
|
+
const basename3 = getBaseFileName(a.fileName);
|
|
109560
|
+
if (basename3 === "lib.d.ts" || basename3 === "lib.es6.d.ts")
|
|
109097
109561
|
return 0;
|
|
109098
|
-
const name = removeSuffix(removePrefix(
|
|
109562
|
+
const name = removeSuffix(removePrefix(basename3, "lib."), ".d.ts");
|
|
109099
109563
|
const index = libs.indexOf(name);
|
|
109100
109564
|
if (index !== -1)
|
|
109101
109565
|
return index + 1;
|
|
@@ -136199,9 +136663,9 @@ ${newComment.split(`
|
|
|
136199
136663
|
const moduleSpecifier = key.slice(2);
|
|
136200
136664
|
const getDeclarations = useRequire ? getNewRequires : getNewImports;
|
|
136201
136665
|
const declarations = getDeclarations(moduleSpecifier, quotePreference, defaultImport, namedImports && arrayFrom(namedImports.entries(), ([name, [addAsTypeOnly, propertyName]]) => ({ addAsTypeOnly, propertyName, name })), namespaceLikeImport, compilerOptions, preferences);
|
|
136202
|
-
newDeclarations =
|
|
136666
|
+
newDeclarations = combine2(newDeclarations, declarations);
|
|
136203
136667
|
});
|
|
136204
|
-
newDeclarations =
|
|
136668
|
+
newDeclarations = combine2(newDeclarations, getCombinedVerbatimImports());
|
|
136205
136669
|
if (newDeclarations) {
|
|
136206
136670
|
insertImports(changeTracker, sourceFile, newDeclarations, true, preferences);
|
|
136207
136671
|
}
|
|
@@ -136951,11 +137415,11 @@ ${newComment.split(`
|
|
|
136951
137415
|
let statements;
|
|
136952
137416
|
if (defaultImport !== undefined || (namedImports == null ? undefined : namedImports.length)) {
|
|
136953
137417
|
const topLevelTypeOnly = (!defaultImport || needsTypeOnly(defaultImport)) && every(namedImports, needsTypeOnly) || (compilerOptions.verbatimModuleSyntax || preferences.preferTypeOnlyAutoImports) && (defaultImport == null ? undefined : defaultImport.addAsTypeOnly) !== 4 && !some(namedImports, (i) => i.addAsTypeOnly === 4);
|
|
136954
|
-
statements =
|
|
137418
|
+
statements = combine2(statements, makeImport(defaultImport && factory.createIdentifier(defaultImport.name), namedImports == null ? undefined : namedImports.map((namedImport) => factory.createImportSpecifier(!topLevelTypeOnly && shouldUseTypeOnly(namedImport, preferences), namedImport.propertyName === undefined ? undefined : factory.createIdentifier(namedImport.propertyName), factory.createIdentifier(namedImport.name))), moduleSpecifier, quotePreference, topLevelTypeOnly));
|
|
136955
137419
|
}
|
|
136956
137420
|
if (namespaceLikeImport) {
|
|
136957
137421
|
const declaration = namespaceLikeImport.importKind === 3 ? factory.createImportEqualsDeclaration(undefined, shouldUseTypeOnly(namespaceLikeImport, preferences), factory.createIdentifier(namespaceLikeImport.name), factory.createExternalModuleReference(quotedModuleSpecifier)) : factory.createImportDeclaration(undefined, factory.createImportClause(shouldUseTypeOnly(namespaceLikeImport, preferences) ? 156 : undefined, undefined, factory.createNamespaceImport(factory.createIdentifier(namespaceLikeImport.name))), quotedModuleSpecifier, undefined);
|
|
136958
|
-
statements =
|
|
137422
|
+
statements = combine2(statements, declaration);
|
|
136959
137423
|
}
|
|
136960
137424
|
return Debug.checkDefined(statements);
|
|
136961
137425
|
}
|
|
@@ -136968,11 +137432,11 @@ ${newComment.split(`
|
|
|
136968
137432
|
bindingElements.unshift(factory.createBindingElement(undefined, "default", defaultImport.name));
|
|
136969
137433
|
}
|
|
136970
137434
|
const declaration = createConstEqualsRequireDeclaration(factory.createObjectBindingPattern(bindingElements), quotedModuleSpecifier);
|
|
136971
|
-
statements =
|
|
137435
|
+
statements = combine2(statements, declaration);
|
|
136972
137436
|
}
|
|
136973
137437
|
if (namespaceLikeImport) {
|
|
136974
137438
|
const declaration = createConstEqualsRequireDeclaration(namespaceLikeImport.name, quotedModuleSpecifier);
|
|
136975
|
-
statements =
|
|
137439
|
+
statements = combine2(statements, declaration);
|
|
136976
137440
|
}
|
|
136977
137441
|
return Debug.checkDefined(statements);
|
|
136978
137442
|
}
|
|
@@ -141424,7 +141888,7 @@ ${newComment.split(`
|
|
|
141424
141888
|
function createModifiers() {
|
|
141425
141889
|
let modifiers2;
|
|
141426
141890
|
if (modifierFlags) {
|
|
141427
|
-
modifiers2 =
|
|
141891
|
+
modifiers2 = combine2(modifiers2, factory.createModifiersFromModifierFlags(modifierFlags));
|
|
141428
141892
|
}
|
|
141429
141893
|
if (shouldAddOverrideKeyword()) {
|
|
141430
141894
|
modifiers2 = append(modifiers2, factory.createToken(164));
|
|
@@ -157416,7 +157880,7 @@ ${options.prefix}` : `
|
|
|
157416
157880
|
codefix: () => ts_codefix_exports,
|
|
157417
157881
|
collapseTextChangeRangesAcrossMultipleVersions: () => collapseTextChangeRangesAcrossMultipleVersions,
|
|
157418
157882
|
collectExternalModuleInfo: () => collectExternalModuleInfo,
|
|
157419
|
-
combine: () =>
|
|
157883
|
+
combine: () => combine2,
|
|
157420
157884
|
combinePaths: () => combinePaths,
|
|
157421
157885
|
commandLineOptionOfCustomType: () => commandLineOptionOfCustomType,
|
|
157422
157886
|
commentPragmas: () => commentPragmas,
|
|
@@ -161658,8 +162122,8 @@ ${options.prefix}` : `
|
|
|
161658
162122
|
}
|
|
161659
162123
|
};
|
|
161660
162124
|
for (const file of files) {
|
|
161661
|
-
const
|
|
161662
|
-
if (
|
|
162125
|
+
const basename3 = getBaseFileName(file);
|
|
162126
|
+
if (basename3 === "package.json" || basename3 === "bower.json") {
|
|
161663
162127
|
createProjectWatcher(file, "FileWatcher");
|
|
161664
162128
|
continue;
|
|
161665
162129
|
}
|
|
@@ -164536,8 +165000,8 @@ All files are: ${JSON.stringify(names)}`, "Err");
|
|
|
164536
165000
|
const fileOrDirectoryPath = removeIgnoredPath(this.toPath(fileOrDirectory));
|
|
164537
165001
|
if (!fileOrDirectoryPath)
|
|
164538
165002
|
return;
|
|
164539
|
-
const
|
|
164540
|
-
if (((_a = result.affectedModuleSpecifierCacheProjects) == null ? undefined : _a.size) && (
|
|
165003
|
+
const basename3 = getBaseFileName(fileOrDirectoryPath);
|
|
165004
|
+
if (((_a = result.affectedModuleSpecifierCacheProjects) == null ? undefined : _a.size) && (basename3 === "package.json" || basename3 === "node_modules")) {
|
|
164541
165005
|
result.affectedModuleSpecifierCacheProjects.forEach((project) => {
|
|
164542
165006
|
var _a2;
|
|
164543
165007
|
(_a2 = project.getModuleSpecifierCache()) == null || _a2.clear();
|
|
@@ -170061,17 +170525,6 @@ var init_islandEntries = __esm(() => {
|
|
|
170061
170525
|
];
|
|
170062
170526
|
});
|
|
170063
170527
|
|
|
170064
|
-
// src/core/currentIslandRegistry.ts
|
|
170065
|
-
var requireCurrentIslandRegistry = () => {
|
|
170066
|
-
const registry = globalThis.__absoluteIslandRegistry;
|
|
170067
|
-
if (!registry) {
|
|
170068
|
-
throw new Error("No island registry is active. Configure `islands.registry` in absolute.config.ts before rendering <Island />.");
|
|
170069
|
-
}
|
|
170070
|
-
return registry;
|
|
170071
|
-
}, setCurrentIslandRegistry = (registry) => {
|
|
170072
|
-
globalThis.__absoluteIslandRegistry = registry;
|
|
170073
|
-
};
|
|
170074
|
-
|
|
170075
170528
|
// src/build/staticIslandPages.ts
|
|
170076
170529
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
170077
170530
|
var ISLAND_TAG_RE_SOURCE = "<(?:absolute-island|island)\\b([^>]*?)(?:\\/\\>|>(?:[\\s\\S]*?)<\\/(?:absolute-island|island)>)", ATTRIBUTE_RE_SOURCE = `([A-Za-z_:][-A-Za-z0-9_:.]*)\\s*=\\s*(?:"([^"]*)"|'([^']*)')`, islandFrameworks, islandHydrationModes, isRecord4 = (value) => typeof value === "object" && value !== null, isIslandFramework = (value) => islandFrameworks.some((framework) => framework === value), isIslandHydrationMode = (value) => islandHydrationModes.some((mode) => mode === value), parseIslandAttributes = (attributeString) => {
|
|
@@ -170162,149 +170615,6 @@ var init_staticIslandPages = __esm(() => {
|
|
|
170162
170615
|
islandHydrationModes = ["load", "idle", "visible", "none"];
|
|
170163
170616
|
});
|
|
170164
170617
|
|
|
170165
|
-
// src/core/islandPageContext.ts
|
|
170166
|
-
var BOOTSTRAP_MANIFEST_KEY = "BootstrapClient", ISLAND_MARKER = 'data-island="true"', MANIFEST_MARKER = "__ABSOLUTE_MANIFEST__", ISLAND_STATE_MARKER = "__ABS_ISLAND_STATE__", CLOSING_HEAD_TAG = "</head>", buildIslandsHeadMarkup = (manifest) => {
|
|
170167
|
-
const manifestScript = `<script>window.__ABSOLUTE_MANIFEST__ = ${JSON.stringify(manifest)}</script>`;
|
|
170168
|
-
const islandStateScript = `<script>window.__ABS_ISLAND_STATE__ = ${JSON.stringify(globalThis.__ABS_ISLAND_STATE__ ?? {})}</script>`;
|
|
170169
|
-
const bootstrapPath = manifest[BOOTSTRAP_MANIFEST_KEY];
|
|
170170
|
-
const bootstrapScript = bootstrapPath ? `<script type="module" src="${bootstrapPath}"></script>` : "";
|
|
170171
|
-
return `${manifestScript}${islandStateScript}${bootstrapScript}`;
|
|
170172
|
-
}, injectHeadMarkup = (html, markup) => {
|
|
170173
|
-
const closingHeadIndex = html.indexOf("</head>");
|
|
170174
|
-
if (closingHeadIndex >= 0) {
|
|
170175
|
-
return `${html.slice(0, closingHeadIndex)}${markup}${html.slice(closingHeadIndex)}`;
|
|
170176
|
-
}
|
|
170177
|
-
const openingBodyIndex = html.indexOf("<body");
|
|
170178
|
-
if (openingBodyIndex >= 0) {
|
|
170179
|
-
const bodyStart = html.indexOf(">", openingBodyIndex);
|
|
170180
|
-
if (bodyStart >= 0) {
|
|
170181
|
-
return `${html.slice(0, openingBodyIndex)}<head>${markup}</head>${html.slice(openingBodyIndex)}`;
|
|
170182
|
-
}
|
|
170183
|
-
}
|
|
170184
|
-
return `<!DOCTYPE html><html><head>${markup}</head><body>${html}</body></html>`;
|
|
170185
|
-
}, streamChunkToString = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true }), pipeStreamWithHeadInjection = (stream, markup) => {
|
|
170186
|
-
const encoder = new TextEncoder;
|
|
170187
|
-
const decoder = new TextDecoder;
|
|
170188
|
-
const lookbehind = CLOSING_HEAD_TAG.length - 1;
|
|
170189
|
-
return new ReadableStream({
|
|
170190
|
-
async start(controller) {
|
|
170191
|
-
const reader = stream.getReader();
|
|
170192
|
-
let injected = false;
|
|
170193
|
-
let pending = "";
|
|
170194
|
-
try {
|
|
170195
|
-
for (;; ) {
|
|
170196
|
-
const { done, value } = await reader.read();
|
|
170197
|
-
if (done)
|
|
170198
|
-
break;
|
|
170199
|
-
if (!value)
|
|
170200
|
-
continue;
|
|
170201
|
-
pending += streamChunkToString(value, decoder);
|
|
170202
|
-
if (injected) {
|
|
170203
|
-
controller.enqueue(encoder.encode(pending));
|
|
170204
|
-
pending = "";
|
|
170205
|
-
continue;
|
|
170206
|
-
}
|
|
170207
|
-
const headIndex = pending.indexOf(CLOSING_HEAD_TAG);
|
|
170208
|
-
if (headIndex >= 0) {
|
|
170209
|
-
const next = `${pending.slice(0, headIndex)}${markup}${pending.slice(headIndex)}`;
|
|
170210
|
-
controller.enqueue(encoder.encode(next));
|
|
170211
|
-
pending = "";
|
|
170212
|
-
injected = true;
|
|
170213
|
-
continue;
|
|
170214
|
-
}
|
|
170215
|
-
if (pending.length > lookbehind) {
|
|
170216
|
-
const safeText = pending.slice(0, pending.length - lookbehind);
|
|
170217
|
-
controller.enqueue(encoder.encode(safeText));
|
|
170218
|
-
pending = pending.slice(-lookbehind);
|
|
170219
|
-
}
|
|
170220
|
-
}
|
|
170221
|
-
pending += decoder.decode();
|
|
170222
|
-
if (!injected) {
|
|
170223
|
-
pending = injectHeadMarkup(pending, markup);
|
|
170224
|
-
}
|
|
170225
|
-
if (pending.length > 0) {
|
|
170226
|
-
controller.enqueue(encoder.encode(pending));
|
|
170227
|
-
}
|
|
170228
|
-
controller.close();
|
|
170229
|
-
} catch (error) {
|
|
170230
|
-
controller.error(error);
|
|
170231
|
-
}
|
|
170232
|
-
}
|
|
170233
|
-
});
|
|
170234
|
-
}, pipeStreamWithIslandMarkerDetection = (stream, markup) => {
|
|
170235
|
-
const encoder = new TextEncoder;
|
|
170236
|
-
const decoder = new TextDecoder;
|
|
170237
|
-
const lookbehind = Math.max(ISLAND_MARKER.length, 1024);
|
|
170238
|
-
return new ReadableStream({
|
|
170239
|
-
async start(controller) {
|
|
170240
|
-
const reader = stream.getReader();
|
|
170241
|
-
let injected = false;
|
|
170242
|
-
let pending = "";
|
|
170243
|
-
try {
|
|
170244
|
-
for (;; ) {
|
|
170245
|
-
const { done, value } = await reader.read();
|
|
170246
|
-
if (done)
|
|
170247
|
-
break;
|
|
170248
|
-
if (!value)
|
|
170249
|
-
continue;
|
|
170250
|
-
pending += streamChunkToString(value, decoder);
|
|
170251
|
-
if (injected) {
|
|
170252
|
-
controller.enqueue(encoder.encode(pending));
|
|
170253
|
-
pending = "";
|
|
170254
|
-
continue;
|
|
170255
|
-
}
|
|
170256
|
-
const markerIndex = pending.indexOf(ISLAND_MARKER);
|
|
170257
|
-
if (markerIndex >= 0) {
|
|
170258
|
-
const tagStart = pending.lastIndexOf("<", markerIndex);
|
|
170259
|
-
const injectAt = tagStart >= 0 ? tagStart : markerIndex;
|
|
170260
|
-
const next = `${pending.slice(0, injectAt)}${markup}${pending.slice(injectAt)}`;
|
|
170261
|
-
controller.enqueue(encoder.encode(next));
|
|
170262
|
-
pending = "";
|
|
170263
|
-
injected = true;
|
|
170264
|
-
continue;
|
|
170265
|
-
}
|
|
170266
|
-
if (pending.length > lookbehind) {
|
|
170267
|
-
const safeText = pending.slice(0, pending.length - lookbehind);
|
|
170268
|
-
controller.enqueue(encoder.encode(safeText));
|
|
170269
|
-
pending = pending.slice(-lookbehind);
|
|
170270
|
-
}
|
|
170271
|
-
}
|
|
170272
|
-
pending += decoder.decode();
|
|
170273
|
-
if (pending.length > 0) {
|
|
170274
|
-
controller.enqueue(encoder.encode(pending));
|
|
170275
|
-
}
|
|
170276
|
-
controller.close();
|
|
170277
|
-
} catch (error) {
|
|
170278
|
-
controller.error(error);
|
|
170279
|
-
}
|
|
170280
|
-
}
|
|
170281
|
-
});
|
|
170282
|
-
}, htmlContainsIslands = (html) => html.includes(ISLAND_MARKER), injectIslandPageContext = (html, options) => {
|
|
170283
|
-
const manifest = globalThis.__absoluteManifest;
|
|
170284
|
-
const hasIslands = options?.hasIslands ?? htmlContainsIslands(html);
|
|
170285
|
-
if (!manifest || !hasIslands) {
|
|
170286
|
-
return html;
|
|
170287
|
-
}
|
|
170288
|
-
if (html.includes(MANIFEST_MARKER) || html.includes(ISLAND_STATE_MARKER)) {
|
|
170289
|
-
return html;
|
|
170290
|
-
}
|
|
170291
|
-
return injectHeadMarkup(html, buildIslandsHeadMarkup(manifest));
|
|
170292
|
-
}, injectIslandPageContextStream = (stream, options) => {
|
|
170293
|
-
const manifest = globalThis.__absoluteManifest;
|
|
170294
|
-
if (!manifest)
|
|
170295
|
-
return stream;
|
|
170296
|
-
const markup = buildIslandsHeadMarkup(manifest);
|
|
170297
|
-
if (options?.hasIslands === true) {
|
|
170298
|
-
return pipeStreamWithHeadInjection(stream, markup);
|
|
170299
|
-
}
|
|
170300
|
-
if (options?.hasIslands === false) {
|
|
170301
|
-
return stream;
|
|
170302
|
-
}
|
|
170303
|
-
return pipeStreamWithIslandMarkerDetection(stream, markup);
|
|
170304
|
-
}, setCurrentIslandManifest = (manifest) => {
|
|
170305
|
-
globalThis.__absoluteManifest = manifest;
|
|
170306
|
-
};
|
|
170307
|
-
|
|
170308
170618
|
// src/build/scanEntryPoints.ts
|
|
170309
170619
|
import { existsSync as existsSync3 } from "fs";
|
|
170310
170620
|
var {Glob } = globalThis.Bun;
|
|
@@ -170469,198 +170779,6 @@ var init_pageMetadata = __esm(() => {
|
|
|
170469
170779
|
};
|
|
170470
170780
|
});
|
|
170471
170781
|
|
|
170472
|
-
// src/utils/resolveConvention.ts
|
|
170473
|
-
import { basename as basename2 } from "path";
|
|
170474
|
-
var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boolean(value) && typeof value === "object", getMap = () => {
|
|
170475
|
-
const value = Reflect.get(globalThis, CONVENTIONS_KEY);
|
|
170476
|
-
if (isConventionsMap(value))
|
|
170477
|
-
return value;
|
|
170478
|
-
const empty = {};
|
|
170479
|
-
return empty;
|
|
170480
|
-
}, derivePageName = (pagePath) => {
|
|
170481
|
-
const base = basename2(pagePath);
|
|
170482
|
-
const dotIndex = base.indexOf(".");
|
|
170483
|
-
const name = dotIndex > 0 ? base.slice(0, dotIndex) : base;
|
|
170484
|
-
return toPascal(name);
|
|
170485
|
-
}, resolveErrorConventionPath = (framework, pageName) => {
|
|
170486
|
-
const conventions2 = getMap()[framework];
|
|
170487
|
-
if (!conventions2)
|
|
170488
|
-
return;
|
|
170489
|
-
return conventions2.pages?.[pageName]?.error ?? conventions2.defaults?.error;
|
|
170490
|
-
}, resolveNotFoundConventionPath = (framework) => getMap()[framework]?.defaults?.notFound, setConventions = (map) => {
|
|
170491
|
-
Reflect.set(globalThis, CONVENTIONS_KEY, map);
|
|
170492
|
-
}, isDev = () => true, buildErrorProps = (error) => {
|
|
170493
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
170494
|
-
const stack = isDev() && error instanceof Error ? error.stack : undefined;
|
|
170495
|
-
return { error: { message, stack } };
|
|
170496
|
-
}, renderReactError = async (conventionPath, errorProps) => {
|
|
170497
|
-
const { createElement: createElement2 } = await import("react");
|
|
170498
|
-
const { renderToReadableStream } = await import("react-dom/server");
|
|
170499
|
-
const mod = await import(conventionPath);
|
|
170500
|
-
const [firstKey] = Object.keys(mod);
|
|
170501
|
-
const ErrorComponent = mod.default ?? (firstKey ? mod[firstKey] : undefined);
|
|
170502
|
-
const element = createElement2(ErrorComponent, errorProps);
|
|
170503
|
-
const stream = await renderToReadableStream(element);
|
|
170504
|
-
return new Response(stream, {
|
|
170505
|
-
headers: { "Content-Type": "text/html" },
|
|
170506
|
-
status: 500
|
|
170507
|
-
});
|
|
170508
|
-
}, renderSvelteError = async (conventionPath, errorProps) => {
|
|
170509
|
-
const { render } = await import("svelte/server");
|
|
170510
|
-
const mod = await import(conventionPath);
|
|
170511
|
-
const ErrorComponent = mod.default;
|
|
170512
|
-
const { head, body } = render(ErrorComponent, {
|
|
170513
|
-
props: errorProps
|
|
170514
|
-
});
|
|
170515
|
-
const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
|
|
170516
|
-
return new Response(html, {
|
|
170517
|
-
headers: { "Content-Type": "text/html" },
|
|
170518
|
-
status: 500
|
|
170519
|
-
});
|
|
170520
|
-
}, unescapeVueStyles = (ssrBody) => {
|
|
170521
|
-
let styles = "";
|
|
170522
|
-
const body = ssrBody.replace(/<style>([\s\S]*?)<\/style>/g, (_, css) => {
|
|
170523
|
-
styles += `<style>${css.replace(/"/g, '"').replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</style>`;
|
|
170524
|
-
return "";
|
|
170525
|
-
});
|
|
170526
|
-
return { body, styles };
|
|
170527
|
-
}, renderVueError = async (conventionPath, errorProps) => {
|
|
170528
|
-
const { createSSRApp: createSSRApp2, h: h2 } = await import("vue");
|
|
170529
|
-
const { renderToString } = await import("vue/server-renderer");
|
|
170530
|
-
const mod = await import(conventionPath);
|
|
170531
|
-
const ErrorComponent = mod.default;
|
|
170532
|
-
const app = createSSRApp2({
|
|
170533
|
-
render: () => h2(ErrorComponent, errorProps)
|
|
170534
|
-
});
|
|
170535
|
-
const rawBody = await renderToString(app);
|
|
170536
|
-
const { styles, body } = unescapeVueStyles(rawBody);
|
|
170537
|
-
const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
|
|
170538
|
-
return new Response(html, {
|
|
170539
|
-
headers: { "Content-Type": "text/html" },
|
|
170540
|
-
status: 500
|
|
170541
|
-
});
|
|
170542
|
-
}, renderAngularError = async (conventionPath, errorProps) => {
|
|
170543
|
-
const mod = await import(conventionPath);
|
|
170544
|
-
const renderError = mod.default ?? mod.renderError;
|
|
170545
|
-
if (typeof renderError !== "function")
|
|
170546
|
-
return null;
|
|
170547
|
-
const html = renderError(errorProps);
|
|
170548
|
-
return new Response(html, {
|
|
170549
|
-
headers: { "Content-Type": "text/html" },
|
|
170550
|
-
status: 500
|
|
170551
|
-
});
|
|
170552
|
-
}, logConventionRenderError = (framework, label, renderError) => {
|
|
170553
|
-
const message = renderError instanceof Error ? renderError.message : "";
|
|
170554
|
-
if (message.includes("Cannot find module") || message.includes("Cannot find package") || message.includes("not found in module")) {
|
|
170555
|
-
console.error(`[SSR] Convention ${label} page for ${framework} failed: missing framework package. Ensure the ${framework} runtime is installed (e.g. bun add ${framework === "react" ? "react react-dom" : framework}).`);
|
|
170556
|
-
return;
|
|
170557
|
-
}
|
|
170558
|
-
console.error(`[SSR] Failed to render ${framework} convention ${label} page:`, renderError);
|
|
170559
|
-
}, ERROR_RENDERERS, renderConventionError = async (framework, pageName, error) => {
|
|
170560
|
-
const conventionPath = resolveErrorConventionPath(framework, pageName);
|
|
170561
|
-
if (!conventionPath)
|
|
170562
|
-
return null;
|
|
170563
|
-
const errorProps = buildErrorProps(error);
|
|
170564
|
-
const renderer = ERROR_RENDERERS[framework];
|
|
170565
|
-
if (!renderer)
|
|
170566
|
-
return null;
|
|
170567
|
-
try {
|
|
170568
|
-
return await renderer(conventionPath, errorProps);
|
|
170569
|
-
} catch (renderError) {
|
|
170570
|
-
logConventionRenderError(framework, "error", renderError);
|
|
170571
|
-
}
|
|
170572
|
-
return null;
|
|
170573
|
-
}, renderReactNotFound = async (conventionPath) => {
|
|
170574
|
-
const { createElement: createElement2 } = await import("react");
|
|
170575
|
-
const { renderToReadableStream } = await import("react-dom/server");
|
|
170576
|
-
const mod = await import(conventionPath);
|
|
170577
|
-
const [nfKey] = Object.keys(mod);
|
|
170578
|
-
const NotFoundComponent = mod.default ?? (nfKey ? mod[nfKey] : undefined);
|
|
170579
|
-
const element = createElement2(NotFoundComponent);
|
|
170580
|
-
const stream = await renderToReadableStream(element);
|
|
170581
|
-
return new Response(stream, {
|
|
170582
|
-
headers: { "Content-Type": "text/html" },
|
|
170583
|
-
status: 404
|
|
170584
|
-
});
|
|
170585
|
-
}, renderSvelteNotFound = async (conventionPath) => {
|
|
170586
|
-
const { render } = await import("svelte/server");
|
|
170587
|
-
const mod = await import(conventionPath);
|
|
170588
|
-
const NotFoundComponent = mod.default;
|
|
170589
|
-
const { head, body } = render(NotFoundComponent);
|
|
170590
|
-
const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
|
|
170591
|
-
return new Response(html, {
|
|
170592
|
-
headers: { "Content-Type": "text/html" },
|
|
170593
|
-
status: 404
|
|
170594
|
-
});
|
|
170595
|
-
}, renderVueNotFound = async (conventionPath) => {
|
|
170596
|
-
const { createSSRApp: createSSRApp2, h: h2 } = await import("vue");
|
|
170597
|
-
const { renderToString } = await import("vue/server-renderer");
|
|
170598
|
-
const mod = await import(conventionPath);
|
|
170599
|
-
const NotFoundComponent = mod.default;
|
|
170600
|
-
const app = createSSRApp2({
|
|
170601
|
-
render: () => h2(NotFoundComponent)
|
|
170602
|
-
});
|
|
170603
|
-
const rawBody = await renderToString(app);
|
|
170604
|
-
const { styles, body } = unescapeVueStyles(rawBody);
|
|
170605
|
-
const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
|
|
170606
|
-
return new Response(html, {
|
|
170607
|
-
headers: { "Content-Type": "text/html" },
|
|
170608
|
-
status: 404
|
|
170609
|
-
});
|
|
170610
|
-
}, renderAngularNotFound = async (conventionPath) => {
|
|
170611
|
-
const mod = await import(conventionPath);
|
|
170612
|
-
const renderNotFound = mod.default ?? mod.renderNotFound;
|
|
170613
|
-
if (typeof renderNotFound !== "function")
|
|
170614
|
-
return null;
|
|
170615
|
-
const html = renderNotFound();
|
|
170616
|
-
return new Response(html, {
|
|
170617
|
-
headers: { "Content-Type": "text/html" },
|
|
170618
|
-
status: 404
|
|
170619
|
-
});
|
|
170620
|
-
}, NOT_FOUND_RENDERERS, renderConventionNotFound = async (framework) => {
|
|
170621
|
-
const conventionPath = resolveNotFoundConventionPath(framework);
|
|
170622
|
-
if (!conventionPath)
|
|
170623
|
-
return null;
|
|
170624
|
-
const renderer = NOT_FOUND_RENDERERS[framework];
|
|
170625
|
-
if (!renderer)
|
|
170626
|
-
return null;
|
|
170627
|
-
try {
|
|
170628
|
-
return await renderer(conventionPath);
|
|
170629
|
-
} catch (renderError) {
|
|
170630
|
-
logConventionRenderError(framework, "not-found", renderError);
|
|
170631
|
-
}
|
|
170632
|
-
return null;
|
|
170633
|
-
}, NOT_FOUND_PRIORITY, renderFirstNotFound = async () => {
|
|
170634
|
-
for (const framework of NOT_FOUND_PRIORITY) {
|
|
170635
|
-
if (!getMap()[framework]?.defaults?.notFound)
|
|
170636
|
-
continue;
|
|
170637
|
-
const response = await renderConventionNotFound(framework);
|
|
170638
|
-
if (response)
|
|
170639
|
-
return response;
|
|
170640
|
-
}
|
|
170641
|
-
return null;
|
|
170642
|
-
};
|
|
170643
|
-
var init_resolveConvention = __esm(() => {
|
|
170644
|
-
ERROR_RENDERERS = {
|
|
170645
|
-
angular: renderAngularError,
|
|
170646
|
-
react: renderReactError,
|
|
170647
|
-
svelte: renderSvelteError,
|
|
170648
|
-
vue: renderVueError
|
|
170649
|
-
};
|
|
170650
|
-
NOT_FOUND_RENDERERS = {
|
|
170651
|
-
angular: renderAngularNotFound,
|
|
170652
|
-
react: renderReactNotFound,
|
|
170653
|
-
svelte: renderSvelteNotFound,
|
|
170654
|
-
vue: renderVueNotFound
|
|
170655
|
-
};
|
|
170656
|
-
NOT_FOUND_PRIORITY = [
|
|
170657
|
-
"react",
|
|
170658
|
-
"svelte",
|
|
170659
|
-
"vue",
|
|
170660
|
-
"angular"
|
|
170661
|
-
];
|
|
170662
|
-
});
|
|
170663
|
-
|
|
170664
170782
|
// src/utils/getDurationString.ts
|
|
170665
170783
|
var getDurationString = (duration) => {
|
|
170666
170784
|
let durationString;
|
|
@@ -173032,7 +173150,7 @@ ${registrations}
|
|
|
173032
173150
|
({ tsLibDir } = cached);
|
|
173033
173151
|
cached.lastUsed = Date.now();
|
|
173034
173152
|
} else {
|
|
173035
|
-
const tsPath = __require.resolve("typescript");
|
|
173153
|
+
const tsPath = __require.resolve("/home/alexkahn/abs/absolutejs/node_modules/typescript/lib/typescript.js");
|
|
173036
173154
|
const tsRootDir = dirname9(tsPath);
|
|
173037
173155
|
tsLibDir = tsRootDir.endsWith("lib") ? tsRootDir : resolve18(tsRootDir, "lib");
|
|
173038
173156
|
const config = readConfiguration("./tsconfig.json");
|
|
@@ -175820,58 +175938,6 @@ var init_webSocket = __esm(() => {
|
|
|
175820
175938
|
init_logger();
|
|
175821
175939
|
});
|
|
175822
175940
|
|
|
175823
|
-
// src/utils/ssrErrorPage.ts
|
|
175824
|
-
var ssrErrorPage = (framework, error) => {
|
|
175825
|
-
const frameworkColors2 = {
|
|
175826
|
-
angular: "#dd0031",
|
|
175827
|
-
html: "#e34c26",
|
|
175828
|
-
htmx: "#1a365d",
|
|
175829
|
-
react: "#61dafb",
|
|
175830
|
-
svelte: "#ff3e00",
|
|
175831
|
-
vue: "#42b883"
|
|
175832
|
-
};
|
|
175833
|
-
const accent = frameworkColors2[framework] ?? "#94a3b8";
|
|
175834
|
-
const label = framework.charAt(0).toUpperCase() + framework.slice(1);
|
|
175835
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
175836
|
-
return `<!DOCTYPE html>
|
|
175837
|
-
<html>
|
|
175838
|
-
<head>
|
|
175839
|
-
<meta charset="utf-8">
|
|
175840
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
175841
|
-
<title>SSR Error - AbsoluteJS</title>
|
|
175842
|
-
<style>
|
|
175843
|
-
*{margin:0;padding:0;box-sizing:border-box}
|
|
175844
|
-
body{min-height:100vh;background:linear-gradient(135deg,rgba(15,23,42,0.98) 0%,rgba(30,41,59,0.98) 100%);color:#e2e8f0;font-family:"JetBrains Mono","Fira Code",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:14px;line-height:1.6;display:flex;align-items:flex-start;justify-content:center;padding:32px}
|
|
175845
|
-
.card{max-width:720px;width:100%;background:rgba(30,41,59,0.6);border:1px solid rgba(71,85,105,0.5);border-radius:16px;box-shadow:0 25px 50px -12px rgba(0,0,0,0.5),0 0 0 1px rgba(255,255,255,0.05);overflow:hidden}
|
|
175846
|
-
.header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:20px 24px;background:rgba(15,23,42,0.5);border-bottom:1px solid rgba(71,85,105,0.4)}
|
|
175847
|
-
.brand{font-weight:700;font-size:20px;color:#fff;letter-spacing:-0.02em}
|
|
175848
|
-
.badge{padding:5px 10px;border-radius:8px;font-size:12px;font-weight:600;background:${accent};color:#fff;opacity:0.95;box-shadow:0 2px 4px rgba(0,0,0,0.2)}
|
|
175849
|
-
.kind{color:#94a3b8;font-size:13px;font-weight:500}
|
|
175850
|
-
.content{padding:24px}
|
|
175851
|
-
.label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.08em;color:#94a3b8;margin-bottom:8px}
|
|
175852
|
-
.message{margin:0;padding:16px 20px;background:rgba(239,68,68,0.12);border:1px solid rgba(239,68,68,0.25);border-radius:10px;overflow-x:auto;white-space:pre-wrap;word-break:break-word;color:#fca5a5;font-size:13px;line-height:1.5}
|
|
175853
|
-
.hint{margin-top:20px;padding:12px 20px;background:rgba(71,85,105,0.3);border-radius:10px;border:1px solid rgba(71,85,105,0.4);color:#cbd5e1;font-size:13px}
|
|
175854
|
-
</style>
|
|
175855
|
-
</head>
|
|
175856
|
-
<body>
|
|
175857
|
-
<div class="card">
|
|
175858
|
-
<div class="header">
|
|
175859
|
-
<div style="display:flex;align-items:center;gap:12px">
|
|
175860
|
-
<span class="brand">AbsoluteJS</span>
|
|
175861
|
-
<span class="badge">${label}</span>
|
|
175862
|
-
</div>
|
|
175863
|
-
<span class="kind">Server Render Error</span>
|
|
175864
|
-
</div>
|
|
175865
|
-
<div class="content">
|
|
175866
|
-
<div class="label">What went wrong</div>
|
|
175867
|
-
<pre class="message">${message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</pre>
|
|
175868
|
-
<div class="hint">A component threw during server-side rendering. Check the terminal for the full stack trace.</div>
|
|
175869
|
-
</div>
|
|
175870
|
-
</div>
|
|
175871
|
-
</body>
|
|
175872
|
-
</html>`;
|
|
175873
|
-
};
|
|
175874
|
-
|
|
175875
175941
|
// src/angular/lowerServerIslands.ts
|
|
175876
175942
|
var ANGULAR_ISLAND_TAG_RE, ATTRIBUTE_RE, islandFrameworks3, islandHydrationModes3, decodeHtmlAttribute = (value) => value.replaceAll(""", '"').replaceAll(""", '"').replaceAll("'", "'").replaceAll("'", "'").replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">"), isRecord6 = (value) => typeof value === "object" && value !== null, isIslandFramework3 = (value) => islandFrameworks3.some((framework) => framework === value), isIslandHydrate2 = (value) => islandHydrationModes3.some((mode) => mode === value), parseAttributes = (attributeString) => {
|
|
175877
175943
|
const attributes = new Map;
|
|
@@ -176002,13 +176068,13 @@ var escapeHtml = (str) => String(str).replace(/&/g, "&").replace(/</g, "<
|
|
|
176002
176068
|
|
|
176003
176069
|
// src/angular/pageHandler.ts
|
|
176004
176070
|
import { AsyncLocalStorage } from "async_hooks";
|
|
176005
|
-
var
|
|
176071
|
+
var ssrDirty2 = false, lastSelector = "angular-page", isRecord7 = (value) => typeof value === "object" && value !== null, isAngularComponent = (value) => typeof value === "function", compilerImportPromise = null, ensureAngularCompiler = () => {
|
|
176006
176072
|
if (!compilerImportPromise) {
|
|
176007
176073
|
compilerImportPromise = import("@angular/compiler");
|
|
176008
176074
|
}
|
|
176009
176075
|
return compilerImportPromise;
|
|
176010
176076
|
}, readAngularPageModule = (value) => isRecord7(value) ? value : null, invalidateAngularSsrCache = () => {
|
|
176011
|
-
|
|
176077
|
+
ssrDirty2 = true;
|
|
176012
176078
|
clearSelectorCache();
|
|
176013
176079
|
}, angularSsrContext, handleAngularPageRequest = async (_importer, pagePath, indexPath, headTag = "<head></head>", ...props) => {
|
|
176014
176080
|
const requestId = `angular_${Date.now()}_${Math.random().toString(BASE_36_RADIX).substring(2, RANDOM_ID_END_INDEX)}`;
|
|
@@ -176016,7 +176082,7 @@ var ssrDirty = false, lastSelector = "angular-page", isRecord7 = (value) => type
|
|
|
176016
176082
|
await ensureAngularCompiler();
|
|
176017
176083
|
const [maybeProps] = props;
|
|
176018
176084
|
cacheRouteData(pagePath, { headTag, props: maybeProps });
|
|
176019
|
-
if (
|
|
176085
|
+
if (ssrDirty2) {
|
|
176020
176086
|
const script = indexPath ? `<script type="module" src="${indexPath}"></script>` : "";
|
|
176021
176087
|
const html = `<!DOCTYPE html><html>${headTag}<body><${lastSelector}></${lastSelector}>${script}</body></html>`;
|
|
176022
176088
|
return new Response(html, {
|
|
@@ -176065,7 +176131,7 @@ var ssrDirty = false, lastSelector = "angular-page", isRecord7 = (value) => type
|
|
|
176065
176131
|
}
|
|
176066
176132
|
});
|
|
176067
176133
|
};
|
|
176068
|
-
var
|
|
176134
|
+
var init_pageHandler2 = __esm(() => {
|
|
176069
176135
|
init_constants();
|
|
176070
176136
|
init_resolveConvention();
|
|
176071
176137
|
init_registerClientScript();
|
|
@@ -176076,627 +176142,6 @@ var init_pageHandler = __esm(() => {
|
|
|
176076
176142
|
setSsrContextGetter(() => angularSsrContext.getStore());
|
|
176077
176143
|
});
|
|
176078
176144
|
|
|
176079
|
-
// src/client/streamSwap.ts
|
|
176080
|
-
var streamSwapRuntime = () => {
|
|
176081
|
-
if (window.__ABS_SLOT_RUNTIME__ === true)
|
|
176082
|
-
return;
|
|
176083
|
-
window.__ABS_SLOT_RUNTIME__ = true;
|
|
176084
|
-
window.__ABS_SLOT_PENDING__ = window.__ABS_SLOT_PENDING__ ?? {};
|
|
176085
|
-
const pending = window.__ABS_SLOT_PENDING__;
|
|
176086
|
-
const apply = (id, html) => {
|
|
176087
|
-
const node = document.getElementById(`slot-${id}`);
|
|
176088
|
-
if (!node) {
|
|
176089
|
-
pending[id] = html;
|
|
176090
|
-
return;
|
|
176091
|
-
}
|
|
176092
|
-
node.innerHTML = html;
|
|
176093
|
-
delete pending[id];
|
|
176094
|
-
};
|
|
176095
|
-
const flush = () => {
|
|
176096
|
-
for (const id in pending) {
|
|
176097
|
-
if (!Object.prototype.hasOwnProperty.call(pending, id))
|
|
176098
|
-
continue;
|
|
176099
|
-
apply(id, pending[id] ?? "");
|
|
176100
|
-
}
|
|
176101
|
-
};
|
|
176102
|
-
window.__ABS_SLOT_ENQUEUE__ = (id, html) => {
|
|
176103
|
-
apply(id, html);
|
|
176104
|
-
};
|
|
176105
|
-
if (typeof MutationObserver === "function") {
|
|
176106
|
-
const observer = new MutationObserver(flush);
|
|
176107
|
-
const root = document.documentElement ?? document.body ?? document;
|
|
176108
|
-
observer.observe(root, { childList: true, subtree: true });
|
|
176109
|
-
}
|
|
176110
|
-
if (document.readyState === "loading") {
|
|
176111
|
-
document.addEventListener("DOMContentLoaded", flush, { once: true });
|
|
176112
|
-
}
|
|
176113
|
-
flush();
|
|
176114
|
-
}, stripFunctionWrapper = (value) => {
|
|
176115
|
-
const start = value.indexOf("{");
|
|
176116
|
-
const end = value.lastIndexOf("}");
|
|
176117
|
-
if (start < 0 || end <= start)
|
|
176118
|
-
return "";
|
|
176119
|
-
return value.slice(start + 1, end);
|
|
176120
|
-
}, getStreamSwapRuntimeScript = () => `(function(){${stripFunctionWrapper(streamSwapRuntime.toString())}})();`;
|
|
176121
|
-
|
|
176122
|
-
// src/utils/escapeScriptContent.ts
|
|
176123
|
-
var ESCAPE_LOOKUP, ESCAPE_REGEX, escapeScriptContent = (content) => content.replace(ESCAPE_REGEX, (char) => {
|
|
176124
|
-
const escaped = ESCAPE_LOOKUP[char];
|
|
176125
|
-
return escaped !== undefined ? escaped : char;
|
|
176126
|
-
});
|
|
176127
|
-
var init_escapeScriptContent = __esm(() => {
|
|
176128
|
-
ESCAPE_LOOKUP = {
|
|
176129
|
-
"\u2028": "\\u2028",
|
|
176130
|
-
"\u2029": "\\u2029",
|
|
176131
|
-
"&": "\\u0026",
|
|
176132
|
-
"<": "\\u003C",
|
|
176133
|
-
">": "\\u003E"
|
|
176134
|
-
};
|
|
176135
|
-
ESCAPE_REGEX = /[&><\u2028\u2029]/g;
|
|
176136
|
-
});
|
|
176137
|
-
|
|
176138
|
-
// src/utils/streamingSlots.ts
|
|
176139
|
-
var SLOT_ID_PREFIX = "abs-slot-", SLOT_PLACEHOLDER_PREFIX = "slot-", CLOSING_HEAD_TAG2 = "</head>", CLOSING_HEAD_TAG_LENGTH, CLOSING_PAGE_TAG_REGEX, STREAMING_RUNTIME_GLOBAL = "__ABS_SLOT_ENQUEUE__", STREAMING_PENDING_GLOBAL = "__ABS_SLOT_PENDING__", STREAM_TAIL_LOOKBEHIND = 128, STREAMING_SLOT_TIMEOUT_MS = 5000, STREAMING_SLOT_MAX_PER_RESPONSE = 128, STREAMING_SLOT_MAX_HTML_BYTES = 64000, createSlotPlaceholderId = (id) => `${SLOT_PLACEHOLDER_PREFIX}${id}`, createSlotPatchStatement = (id, html) => `(window.${STREAMING_RUNTIME_GLOBAL}||function(i,h){window.${STREAMING_PENDING_GLOBAL}=window.${STREAMING_PENDING_GLOBAL}||{};window.${STREAMING_PENDING_GLOBAL}[i]=h;})(${JSON.stringify(id)},${JSON.stringify(html)});`, createNonceAttr = (nonce) => nonce ? ` nonce="${nonce}"` : "", createStreamingSlotId = () => `${SLOT_ID_PREFIX}${Math.random().toString(36).slice(2, 10)}`, getStreamingSlotsRuntimeScript = () => getStreamSwapRuntimeScript(), renderStreamingSlotsRuntimeTag = (nonce) => `<script${createNonceAttr(nonce)}>${escapeScriptContent(getStreamingSlotsRuntimeScript())}</script>`, renderStreamingSlotPlaceholder = (id, fallbackHtml = "") => `<div id="${createSlotPlaceholderId(id)}" data-absolute-slot="true">${fallbackHtml}</div>`, renderStreamingSlotPatchTag = (id, html, nonce) => `<script${createNonceAttr(nonce)}>${escapeScriptContent(createSlotPatchStatement(id, html))}</script>`, injectHtmlIntoHead = (html, injection) => {
|
|
176140
|
-
const closingHeadIndex = html.indexOf(CLOSING_HEAD_TAG2);
|
|
176141
|
-
if (closingHeadIndex >= 0) {
|
|
176142
|
-
return `${html.slice(0, closingHeadIndex)}${injection}${html.slice(closingHeadIndex)}`;
|
|
176143
|
-
}
|
|
176144
|
-
return `${html}${injection}`;
|
|
176145
|
-
}, toUint8 = (value, encoder) => encoder.encode(value), currentStreamingSlotPolicy, clonePolicy = (policy) => ({
|
|
176146
|
-
...policy
|
|
176147
|
-
}), normalizeSlotBytes = (value, fallback) => {
|
|
176148
|
-
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
176149
|
-
return Math.floor(value);
|
|
176150
|
-
}
|
|
176151
|
-
return fallback;
|
|
176152
|
-
}, normalizeSlotText = (value, fallback) => typeof value === "string" ? value : fallback, normalizeSlotError = (value, fallback) => typeof value === "string" ? value : fallback, hasPolicyValue = (policy, key) => Object.prototype.hasOwnProperty.call(policy, key), applyStreamingSlotPolicyOverrides = (base, overridePolicy = {}) => ({
|
|
176153
|
-
timeoutMs: hasPolicyValue(overridePolicy, "timeoutMs") ? normalizeSlotBytes(overridePolicy.timeoutMs, base.timeoutMs) : base.timeoutMs,
|
|
176154
|
-
fallbackHtml: hasPolicyValue(overridePolicy, "fallbackHtml") ? normalizeSlotText(overridePolicy.fallbackHtml, "") : base.fallbackHtml,
|
|
176155
|
-
errorHtml: hasPolicyValue(overridePolicy, "errorHtml") ? normalizeSlotError(overridePolicy.errorHtml) : base.errorHtml,
|
|
176156
|
-
maxSlotsPerResponse: hasPolicyValue(overridePolicy, "maxSlotsPerResponse") ? normalizeSlotBytes(overridePolicy.maxSlotsPerResponse, base.maxSlotsPerResponse) : base.maxSlotsPerResponse,
|
|
176157
|
-
maxSlotHtmlSizeBytes: hasPolicyValue(overridePolicy, "maxSlotHtmlSizeBytes") ? normalizeSlotBytes(overridePolicy.maxSlotHtmlSizeBytes, base.maxSlotHtmlSizeBytes) : base.maxSlotHtmlSizeBytes,
|
|
176158
|
-
onError: hasPolicyValue(overridePolicy, "onError") ? overridePolicy.onError : base.onError,
|
|
176159
|
-
onSlotMetric: hasPolicyValue(overridePolicy, "onSlotMetric") ? overridePolicy.onSlotMetric : base.onSlotMetric
|
|
176160
|
-
}), createCombinedSlotErrorHandler = (policyOnError, enhancerOnError) => {
|
|
176161
|
-
if (!policyOnError && !enhancerOnError)
|
|
176162
|
-
return;
|
|
176163
|
-
return (error, slot) => {
|
|
176164
|
-
policyOnError?.(error, slot);
|
|
176165
|
-
enhancerOnError?.(error, slot);
|
|
176166
|
-
};
|
|
176167
|
-
}, createCombinedSlotMetricHandler = (policyOnSlotMetric, callOnSlotMetric) => {
|
|
176168
|
-
if (!policyOnSlotMetric && !callOnSlotMetric)
|
|
176169
|
-
return;
|
|
176170
|
-
return (metric) => {
|
|
176171
|
-
policyOnSlotMetric?.(metric);
|
|
176172
|
-
callOnSlotMetric?.(metric);
|
|
176173
|
-
};
|
|
176174
|
-
}, resolveStreamingSlotPolicy = (overridePolicy = {}) => {
|
|
176175
|
-
const base = getStreamingSlotPolicy();
|
|
176176
|
-
return applyStreamingSlotPolicyOverrides(base, overridePolicy);
|
|
176177
|
-
}, getStreamingSlotPolicy = () => clonePolicy(currentStreamingSlotPolicy), setStreamingSlotPolicy = (policy = {}) => {
|
|
176178
|
-
const base = getStreamingSlotPolicy();
|
|
176179
|
-
currentStreamingSlotPolicy = applyStreamingSlotPolicyOverrides(base, policy);
|
|
176180
|
-
}, withStreamingSlotPolicy = async (policy, callback) => {
|
|
176181
|
-
const previous = getStreamingSlotPolicy();
|
|
176182
|
-
setStreamingSlotPolicy(policy);
|
|
176183
|
-
try {
|
|
176184
|
-
return await callback();
|
|
176185
|
-
} finally {
|
|
176186
|
-
currentStreamingSlotPolicy = previous;
|
|
176187
|
-
}
|
|
176188
|
-
}, emitSlotMetric = (metric, onSlotMetric) => {
|
|
176189
|
-
onSlotMetric?.(metric);
|
|
176190
|
-
}, createTimeoutError = (slot, timeoutMs) => {
|
|
176191
|
-
const error = new Error(`Streaming slot "${slot.id}" timed out after ${timeoutMs}ms`);
|
|
176192
|
-
error.__absTimeout = true;
|
|
176193
|
-
return error;
|
|
176194
|
-
}, toStreamingSlot = (slot, policy) => ({
|
|
176195
|
-
errorHtml: slot.errorHtml === undefined ? policy.errorHtml : slot.errorHtml,
|
|
176196
|
-
fallbackHtml: normalizeSlotText(slot.fallbackHtml, policy.fallbackHtml),
|
|
176197
|
-
id: slot.id ?? createStreamingSlotId(),
|
|
176198
|
-
timeoutMs: normalizeSlotBytes(slot.timeoutMs, policy.timeoutMs),
|
|
176199
|
-
resolve: slot.resolve
|
|
176200
|
-
}), prepareSlots = ({
|
|
176201
|
-
policy,
|
|
176202
|
-
slots,
|
|
176203
|
-
onError,
|
|
176204
|
-
onSlotMetric
|
|
176205
|
-
}) => {
|
|
176206
|
-
const preparedSlots = slots.map((slot) => toStreamingSlot(slot, policy));
|
|
176207
|
-
const maxSlotsPerResponse = policy.maxSlotsPerResponse;
|
|
176208
|
-
if (maxSlotsPerResponse === 0) {
|
|
176209
|
-
const error = new Error("Streaming slot limit is set to 0");
|
|
176210
|
-
for (const slot of preparedSlots) {
|
|
176211
|
-
onError?.(error, slot);
|
|
176212
|
-
emitSlotMetric({
|
|
176213
|
-
type: "dropped",
|
|
176214
|
-
slotId: slot.id,
|
|
176215
|
-
reason: "maxSlotsPerResponse is 0"
|
|
176216
|
-
}, onSlotMetric);
|
|
176217
|
-
}
|
|
176218
|
-
return [];
|
|
176219
|
-
}
|
|
176220
|
-
if (preparedSlots.length <= maxSlotsPerResponse) {
|
|
176221
|
-
preparedSlots.forEach((slot) => emitSlotMetric({
|
|
176222
|
-
type: "prepared",
|
|
176223
|
-
slotId: slot.id
|
|
176224
|
-
}, onSlotMetric));
|
|
176225
|
-
return preparedSlots;
|
|
176226
|
-
}
|
|
176227
|
-
const keptSlots = preparedSlots.slice(0, maxSlotsPerResponse);
|
|
176228
|
-
const droppedSlots = preparedSlots.slice(maxSlotsPerResponse);
|
|
176229
|
-
droppedSlots.forEach((slot) => {
|
|
176230
|
-
onError?.(new Error(`Streaming slot "${slot.id}" dropped because ${maxSlotsPerResponse} slots is the configured maximum`), slot);
|
|
176231
|
-
emitSlotMetric({
|
|
176232
|
-
type: "dropped",
|
|
176233
|
-
slotId: slot.id,
|
|
176234
|
-
reason: `maxSlotsPerResponse is ${maxSlotsPerResponse}`
|
|
176235
|
-
}, onSlotMetric);
|
|
176236
|
-
});
|
|
176237
|
-
keptSlots.forEach((slot) => emitSlotMetric({
|
|
176238
|
-
type: "prepared",
|
|
176239
|
-
slotId: slot.id
|
|
176240
|
-
}, onSlotMetric));
|
|
176241
|
-
return keptSlots;
|
|
176242
|
-
}, htmlByteLength = (value, encoder) => encoder.encode(value).length, resolveSlot = async (slot, onError, policy, onSlotMetric) => {
|
|
176243
|
-
const safePolicy = policy ?? getStreamingSlotPolicy();
|
|
176244
|
-
const encoder = new TextEncoder;
|
|
176245
|
-
const start = Date.now();
|
|
176246
|
-
try {
|
|
176247
|
-
const maybeAsyncValue = Promise.resolve(slot.resolve());
|
|
176248
|
-
const resolved = typeof slot.timeoutMs === "number" && slot.timeoutMs > 0 ? await Promise.race([
|
|
176249
|
-
maybeAsyncValue,
|
|
176250
|
-
new Promise((_, reject) => setTimeout(() => {
|
|
176251
|
-
reject(createTimeoutError(slot, slot.timeoutMs ?? 0));
|
|
176252
|
-
}, slot.timeoutMs))
|
|
176253
|
-
]) : await maybeAsyncValue;
|
|
176254
|
-
const html = typeof resolved === "string" ? resolved : `${resolved}`;
|
|
176255
|
-
if (safePolicy.maxSlotHtmlSizeBytes > 0 && htmlByteLength(html, encoder) > safePolicy.maxSlotHtmlSizeBytes) {
|
|
176256
|
-
const bytes2 = htmlByteLength(html, encoder);
|
|
176257
|
-
const error = new Error(`Streaming slot "${slot.id}" exceeded max payload size of ${safePolicy.maxSlotHtmlSizeBytes} bytes`);
|
|
176258
|
-
const durationMs2 = Date.now() - start;
|
|
176259
|
-
onError?.(error, slot);
|
|
176260
|
-
emitSlotMetric({
|
|
176261
|
-
type: "size_exceeded",
|
|
176262
|
-
slotId: slot.id,
|
|
176263
|
-
durationMs: durationMs2,
|
|
176264
|
-
bytes: bytes2,
|
|
176265
|
-
error
|
|
176266
|
-
}, onSlotMetric);
|
|
176267
|
-
const fallbackHtml = typeof slot.errorHtml === "string" ? slot.errorHtml : null;
|
|
176268
|
-
return {
|
|
176269
|
-
html: fallbackHtml,
|
|
176270
|
-
id: slot.id,
|
|
176271
|
-
durationMs: durationMs2,
|
|
176272
|
-
bytes: fallbackHtml === null ? 0 : htmlByteLength(fallbackHtml, encoder)
|
|
176273
|
-
};
|
|
176274
|
-
}
|
|
176275
|
-
const durationMs = Date.now() - start;
|
|
176276
|
-
const bytes = htmlByteLength(html, encoder);
|
|
176277
|
-
emitSlotMetric({
|
|
176278
|
-
type: "resolved",
|
|
176279
|
-
slotId: slot.id,
|
|
176280
|
-
durationMs,
|
|
176281
|
-
bytes
|
|
176282
|
-
}, onSlotMetric);
|
|
176283
|
-
return {
|
|
176284
|
-
html,
|
|
176285
|
-
id: slot.id,
|
|
176286
|
-
durationMs,
|
|
176287
|
-
bytes
|
|
176288
|
-
};
|
|
176289
|
-
} catch (error) {
|
|
176290
|
-
const durationMs = Date.now() - start;
|
|
176291
|
-
onError?.(error, slot);
|
|
176292
|
-
emitSlotMetric({
|
|
176293
|
-
type: error?.__absTimeout === true ? "timeout" : "error",
|
|
176294
|
-
slotId: slot.id,
|
|
176295
|
-
durationMs,
|
|
176296
|
-
error
|
|
176297
|
-
}, onSlotMetric);
|
|
176298
|
-
if (typeof slot.errorHtml === "string") {
|
|
176299
|
-
const html = slot.errorHtml;
|
|
176300
|
-
return {
|
|
176301
|
-
html,
|
|
176302
|
-
id: slot.id,
|
|
176303
|
-
durationMs,
|
|
176304
|
-
bytes: htmlByteLength(html, encoder)
|
|
176305
|
-
};
|
|
176306
|
-
}
|
|
176307
|
-
return {
|
|
176308
|
-
html: null,
|
|
176309
|
-
id: slot.id,
|
|
176310
|
-
durationMs,
|
|
176311
|
-
bytes: 0
|
|
176312
|
-
};
|
|
176313
|
-
}
|
|
176314
|
-
}, nextResolvedSlot = async (pending) => {
|
|
176315
|
-
const wrapped = pending.map((promise) => promise.then((result) => ({
|
|
176316
|
-
original: promise,
|
|
176317
|
-
result
|
|
176318
|
-
})));
|
|
176319
|
-
return Promise.race(wrapped);
|
|
176320
|
-
}, streamChunkToString2 = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true }), streamOutOfOrderSlots = ({
|
|
176321
|
-
footerHtml = "",
|
|
176322
|
-
headerHtml = "",
|
|
176323
|
-
nonce,
|
|
176324
|
-
policy,
|
|
176325
|
-
onSlotMetric,
|
|
176326
|
-
onError,
|
|
176327
|
-
slots
|
|
176328
|
-
}) => {
|
|
176329
|
-
const resolvedPolicy = resolveStreamingSlotPolicy(policy);
|
|
176330
|
-
const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
|
|
176331
|
-
const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
|
|
176332
|
-
const effectivePolicy = {
|
|
176333
|
-
...resolvedPolicy,
|
|
176334
|
-
onSlotMetric: combinedOnSlotMetric
|
|
176335
|
-
};
|
|
176336
|
-
const preparedSlots = prepareSlots({
|
|
176337
|
-
policy: effectivePolicy,
|
|
176338
|
-
slots,
|
|
176339
|
-
onError: combinedOnError,
|
|
176340
|
-
onSlotMetric: combinedOnSlotMetric
|
|
176341
|
-
});
|
|
176342
|
-
const encoder = new TextEncoder;
|
|
176343
|
-
return new ReadableStream({
|
|
176344
|
-
async start(controller) {
|
|
176345
|
-
try {
|
|
176346
|
-
let header = headerHtml;
|
|
176347
|
-
if (preparedSlots.length > 0 && !header.includes(STREAMING_RUNTIME_GLOBAL)) {
|
|
176348
|
-
header = injectHtmlIntoHead(header, renderStreamingSlotsRuntimeTag(nonce));
|
|
176349
|
-
}
|
|
176350
|
-
controller.enqueue(toUint8(header, encoder));
|
|
176351
|
-
const pending = preparedSlots.map((slot) => {
|
|
176352
|
-
const fallback = renderStreamingSlotPlaceholder(slot.id, slot.fallbackHtml ?? "");
|
|
176353
|
-
controller.enqueue(toUint8(fallback, encoder));
|
|
176354
|
-
return resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric);
|
|
176355
|
-
});
|
|
176356
|
-
while (pending.length > 0) {
|
|
176357
|
-
const { original, result } = await nextResolvedSlot(pending);
|
|
176358
|
-
const index = pending.indexOf(original);
|
|
176359
|
-
if (index >= 0)
|
|
176360
|
-
pending.splice(index, 1);
|
|
176361
|
-
if (result.html === null)
|
|
176362
|
-
continue;
|
|
176363
|
-
emitSlotMetric({
|
|
176364
|
-
type: "patched",
|
|
176365
|
-
slotId: result.id,
|
|
176366
|
-
durationMs: result.durationMs,
|
|
176367
|
-
bytes: result.bytes
|
|
176368
|
-
}, combinedOnSlotMetric);
|
|
176369
|
-
controller.enqueue(toUint8(renderStreamingSlotPatchTag(result.id, result.html, nonce), encoder));
|
|
176370
|
-
}
|
|
176371
|
-
if (footerHtml.length > 0) {
|
|
176372
|
-
controller.enqueue(toUint8(footerHtml, encoder));
|
|
176373
|
-
}
|
|
176374
|
-
controller.close();
|
|
176375
|
-
} catch (error) {
|
|
176376
|
-
controller.error(error);
|
|
176377
|
-
}
|
|
176378
|
-
}
|
|
176379
|
-
});
|
|
176380
|
-
}, injectStreamingRuntimeIntoStream = (stream, nonce) => {
|
|
176381
|
-
const runtimeTag = renderStreamingSlotsRuntimeTag(nonce);
|
|
176382
|
-
const encoder = new TextEncoder;
|
|
176383
|
-
const decoder = new TextDecoder;
|
|
176384
|
-
const lookbehind = CLOSING_HEAD_TAG_LENGTH - 1;
|
|
176385
|
-
return new ReadableStream({
|
|
176386
|
-
async start(controller) {
|
|
176387
|
-
const reader = stream.getReader();
|
|
176388
|
-
let injected = false;
|
|
176389
|
-
let pending = "";
|
|
176390
|
-
try {
|
|
176391
|
-
for (;; ) {
|
|
176392
|
-
const { done, value } = await reader.read();
|
|
176393
|
-
if (done)
|
|
176394
|
-
break;
|
|
176395
|
-
if (!value)
|
|
176396
|
-
continue;
|
|
176397
|
-
pending += streamChunkToString2(value, decoder);
|
|
176398
|
-
if (injected) {
|
|
176399
|
-
controller.enqueue(encoder.encode(pending));
|
|
176400
|
-
pending = "";
|
|
176401
|
-
continue;
|
|
176402
|
-
}
|
|
176403
|
-
const headIndex = pending.indexOf(CLOSING_HEAD_TAG2);
|
|
176404
|
-
if (headIndex >= 0) {
|
|
176405
|
-
const withRuntime = `${pending.slice(0, headIndex)}${runtimeTag}${pending.slice(headIndex)}`;
|
|
176406
|
-
controller.enqueue(encoder.encode(withRuntime));
|
|
176407
|
-
pending = "";
|
|
176408
|
-
injected = true;
|
|
176409
|
-
continue;
|
|
176410
|
-
}
|
|
176411
|
-
if (pending.length > lookbehind) {
|
|
176412
|
-
const safeText = pending.slice(0, pending.length - lookbehind);
|
|
176413
|
-
controller.enqueue(encoder.encode(safeText));
|
|
176414
|
-
pending = pending.slice(-lookbehind);
|
|
176415
|
-
}
|
|
176416
|
-
}
|
|
176417
|
-
pending += decoder.decode();
|
|
176418
|
-
if (!injected) {
|
|
176419
|
-
pending = injectHtmlIntoHead(pending, runtimeTag);
|
|
176420
|
-
}
|
|
176421
|
-
if (pending.length > 0) {
|
|
176422
|
-
controller.enqueue(encoder.encode(pending));
|
|
176423
|
-
}
|
|
176424
|
-
controller.close();
|
|
176425
|
-
} catch (error) {
|
|
176426
|
-
controller.error(error);
|
|
176427
|
-
}
|
|
176428
|
-
}
|
|
176429
|
-
});
|
|
176430
|
-
}, appendStreamingSlotPatchesToStream = (stream, slots = [], {
|
|
176431
|
-
injectRuntime = true,
|
|
176432
|
-
nonce,
|
|
176433
|
-
onError,
|
|
176434
|
-
onSlotMetric,
|
|
176435
|
-
policy
|
|
176436
|
-
} = {}) => {
|
|
176437
|
-
const resolvedPolicy = resolveStreamingSlotPolicy(policy);
|
|
176438
|
-
const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
|
|
176439
|
-
const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
|
|
176440
|
-
const effectivePolicy = {
|
|
176441
|
-
...resolvedPolicy,
|
|
176442
|
-
onSlotMetric: combinedOnSlotMetric
|
|
176443
|
-
};
|
|
176444
|
-
const preparedSlots = prepareSlots({
|
|
176445
|
-
policy: effectivePolicy,
|
|
176446
|
-
slots,
|
|
176447
|
-
onError: combinedOnError,
|
|
176448
|
-
onSlotMetric: combinedOnSlotMetric
|
|
176449
|
-
});
|
|
176450
|
-
if (preparedSlots.length === 0)
|
|
176451
|
-
return stream;
|
|
176452
|
-
const source = injectRuntime ? injectStreamingRuntimeIntoStream(stream, nonce) : stream;
|
|
176453
|
-
const encoder = new TextEncoder;
|
|
176454
|
-
const decoder = new TextDecoder;
|
|
176455
|
-
const reader = source.getReader();
|
|
176456
|
-
const pending = preparedSlots.map((slot) => resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric));
|
|
176457
|
-
return new ReadableStream({
|
|
176458
|
-
async start(controller) {
|
|
176459
|
-
let baseDone = false;
|
|
176460
|
-
let baseRead = reader.read();
|
|
176461
|
-
let tail = "";
|
|
176462
|
-
let footer = "";
|
|
176463
|
-
try {
|
|
176464
|
-
while (!baseDone || pending.length > 0) {
|
|
176465
|
-
const racers = [];
|
|
176466
|
-
if (!baseDone) {
|
|
176467
|
-
racers.push(baseRead.then(({ done, value }) => ({
|
|
176468
|
-
done,
|
|
176469
|
-
kind: "base",
|
|
176470
|
-
value
|
|
176471
|
-
})));
|
|
176472
|
-
}
|
|
176473
|
-
if (pending.length > 0) {
|
|
176474
|
-
racers.push(nextResolvedSlot(pending).then((resolved) => ({
|
|
176475
|
-
kind: "slot",
|
|
176476
|
-
...resolved
|
|
176477
|
-
})));
|
|
176478
|
-
}
|
|
176479
|
-
if (racers.length === 0)
|
|
176480
|
-
break;
|
|
176481
|
-
const winner = await Promise.race(racers);
|
|
176482
|
-
if (winner.kind === "base") {
|
|
176483
|
-
if (winner.done) {
|
|
176484
|
-
baseDone = true;
|
|
176485
|
-
tail += decoder.decode();
|
|
176486
|
-
const footerStart = tail.search(CLOSING_PAGE_TAG_REGEX);
|
|
176487
|
-
if (footerStart >= 0) {
|
|
176488
|
-
const content = tail.slice(0, footerStart);
|
|
176489
|
-
footer = tail.slice(footerStart);
|
|
176490
|
-
if (content.length > 0) {
|
|
176491
|
-
controller.enqueue(encoder.encode(content));
|
|
176492
|
-
}
|
|
176493
|
-
} else if (tail.length > 0) {
|
|
176494
|
-
controller.enqueue(encoder.encode(tail));
|
|
176495
|
-
}
|
|
176496
|
-
tail = "";
|
|
176497
|
-
} else if (winner.value) {
|
|
176498
|
-
tail += streamChunkToString2(winner.value, decoder);
|
|
176499
|
-
if (tail.length > STREAM_TAIL_LOOKBEHIND) {
|
|
176500
|
-
const content = tail.slice(0, tail.length - STREAM_TAIL_LOOKBEHIND);
|
|
176501
|
-
controller.enqueue(encoder.encode(content));
|
|
176502
|
-
tail = tail.slice(-STREAM_TAIL_LOOKBEHIND);
|
|
176503
|
-
}
|
|
176504
|
-
baseRead = reader.read();
|
|
176505
|
-
}
|
|
176506
|
-
continue;
|
|
176507
|
-
}
|
|
176508
|
-
const index = pending.indexOf(winner.original);
|
|
176509
|
-
if (index >= 0)
|
|
176510
|
-
pending.splice(index, 1);
|
|
176511
|
-
if (winner.result.html === null)
|
|
176512
|
-
continue;
|
|
176513
|
-
emitSlotMetric({
|
|
176514
|
-
type: "patched",
|
|
176515
|
-
slotId: winner.result.id,
|
|
176516
|
-
durationMs: winner.result.durationMs,
|
|
176517
|
-
bytes: winner.result.bytes
|
|
176518
|
-
}, combinedOnSlotMetric);
|
|
176519
|
-
controller.enqueue(encoder.encode(renderStreamingSlotPatchTag(winner.result.id, winner.result.html, nonce)));
|
|
176520
|
-
}
|
|
176521
|
-
if (footer.length > 0)
|
|
176522
|
-
controller.enqueue(encoder.encode(footer));
|
|
176523
|
-
controller.close();
|
|
176524
|
-
} catch (error) {
|
|
176525
|
-
controller.error(error);
|
|
176526
|
-
}
|
|
176527
|
-
}
|
|
176528
|
-
});
|
|
176529
|
-
};
|
|
176530
|
-
var init_streamingSlots = __esm(() => {
|
|
176531
|
-
init_escapeScriptContent();
|
|
176532
|
-
CLOSING_HEAD_TAG_LENGTH = CLOSING_HEAD_TAG2.length;
|
|
176533
|
-
CLOSING_PAGE_TAG_REGEX = /<\/body>\s*<\/html>\s*$/i;
|
|
176534
|
-
currentStreamingSlotPolicy = {
|
|
176535
|
-
timeoutMs: STREAMING_SLOT_TIMEOUT_MS,
|
|
176536
|
-
fallbackHtml: "",
|
|
176537
|
-
errorHtml: undefined,
|
|
176538
|
-
maxSlotsPerResponse: STREAMING_SLOT_MAX_PER_RESPONSE,
|
|
176539
|
-
maxSlotHtmlSizeBytes: STREAMING_SLOT_MAX_HTML_BYTES
|
|
176540
|
-
};
|
|
176541
|
-
});
|
|
176542
|
-
|
|
176543
|
-
// src/core/streamingSlotRegistrar.ts
|
|
176544
|
-
var registrar = null, setStreamingSlotRegistrar = (nextRegistrar) => {
|
|
176545
|
-
registrar = nextRegistrar;
|
|
176546
|
-
}, registerStreamingSlot = (slot) => {
|
|
176547
|
-
registrar?.(slot);
|
|
176548
|
-
};
|
|
176549
|
-
|
|
176550
|
-
// src/core/streamingSlotRegistry.ts
|
|
176551
|
-
var asyncLocalStorage, isServerRuntime = () => typeof process !== "undefined" && typeof process.versions?.node === "string", ensureAsyncLocalStorage = async () => {
|
|
176552
|
-
if (typeof asyncLocalStorage !== "undefined")
|
|
176553
|
-
return asyncLocalStorage;
|
|
176554
|
-
if (!isServerRuntime()) {
|
|
176555
|
-
asyncLocalStorage = null;
|
|
176556
|
-
return asyncLocalStorage;
|
|
176557
|
-
}
|
|
176558
|
-
const mod = await import("async_hooks");
|
|
176559
|
-
asyncLocalStorage = new mod.AsyncLocalStorage;
|
|
176560
|
-
return asyncLocalStorage;
|
|
176561
|
-
}, registerStreamingSlot2 = (slot) => {
|
|
176562
|
-
if (!asyncLocalStorage)
|
|
176563
|
-
return;
|
|
176564
|
-
const store = asyncLocalStorage.getStore();
|
|
176565
|
-
if (!store)
|
|
176566
|
-
return;
|
|
176567
|
-
store.set(slot.id, slot);
|
|
176568
|
-
}, runWithStreamingSlotRegistry = async (task) => {
|
|
176569
|
-
const storage = await ensureAsyncLocalStorage();
|
|
176570
|
-
if (!storage) {
|
|
176571
|
-
return {
|
|
176572
|
-
result: await task(),
|
|
176573
|
-
slots: []
|
|
176574
|
-
};
|
|
176575
|
-
}
|
|
176576
|
-
return storage.run(new Map, async () => {
|
|
176577
|
-
const result = await task();
|
|
176578
|
-
const store = storage.getStore();
|
|
176579
|
-
return {
|
|
176580
|
-
result,
|
|
176581
|
-
slots: store ? [...store.values()] : []
|
|
176582
|
-
};
|
|
176583
|
-
});
|
|
176584
|
-
};
|
|
176585
|
-
var init_streamingSlotRegistry = __esm(() => {
|
|
176586
|
-
setStreamingSlotRegistrar(registerStreamingSlot2);
|
|
176587
|
-
});
|
|
176588
|
-
|
|
176589
|
-
// src/core/responseEnhancers.ts
|
|
176590
|
-
var toResponse = async (responseLike) => await responseLike, cloneHeaders = (response) => {
|
|
176591
|
-
const headers = new Headers(response.headers);
|
|
176592
|
-
return headers;
|
|
176593
|
-
}, enhanceHtmlResponseWithStreamingSlots = (response, { nonce, onError, streamingSlots = [], policy } = {}) => {
|
|
176594
|
-
if (!response.body || streamingSlots.length === 0) {
|
|
176595
|
-
return response;
|
|
176596
|
-
}
|
|
176597
|
-
const body = appendStreamingSlotPatchesToStream(response.body, streamingSlots, {
|
|
176598
|
-
nonce,
|
|
176599
|
-
onError,
|
|
176600
|
-
policy
|
|
176601
|
-
});
|
|
176602
|
-
return new Response(body, {
|
|
176603
|
-
headers: cloneHeaders(response),
|
|
176604
|
-
status: response.status,
|
|
176605
|
-
statusText: response.statusText
|
|
176606
|
-
});
|
|
176607
|
-
}, withStreamingSlots = async (responseLike, options = {}) => enhanceHtmlResponseWithStreamingSlots(await toResponse(responseLike), options), mergeStreamingSlots = (registered, explicit) => {
|
|
176608
|
-
const merged = new Map;
|
|
176609
|
-
for (const slot of registered)
|
|
176610
|
-
merged.set(slot.id, slot);
|
|
176611
|
-
for (const slot of explicit)
|
|
176612
|
-
merged.set(slot.id, slot);
|
|
176613
|
-
return [...merged.values()];
|
|
176614
|
-
}, withRegisteredStreamingSlots = async (renderResponse, options = {}) => {
|
|
176615
|
-
const { result, slots } = await runWithStreamingSlotRegistry(renderResponse);
|
|
176616
|
-
const explicit = options.streamingSlots ?? [];
|
|
176617
|
-
return withStreamingSlots(result, {
|
|
176618
|
-
...options,
|
|
176619
|
-
streamingSlots: mergeStreamingSlots(slots, explicit)
|
|
176620
|
-
});
|
|
176621
|
-
};
|
|
176622
|
-
var init_responseEnhancers = __esm(() => {
|
|
176623
|
-
init_streamingSlots();
|
|
176624
|
-
init_streamingSlotRegistry();
|
|
176625
|
-
});
|
|
176626
|
-
|
|
176627
|
-
// src/react/streamingSlotCollection.tsx
|
|
176628
|
-
import { createContext, useContext } from "react";
|
|
176629
|
-
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
176630
|
-
var StreamingSlotCollectorContext, StreamingSlotCollectorProvider = ({
|
|
176631
|
-
children,
|
|
176632
|
-
collector
|
|
176633
|
-
}) => /* @__PURE__ */ jsxDEV(StreamingSlotCollectorContext.Provider, {
|
|
176634
|
-
value: collector,
|
|
176635
|
-
children
|
|
176636
|
-
}, undefined, false, undefined, this), useStreamingSlotCollector = () => useContext(StreamingSlotCollectorContext);
|
|
176637
|
-
var init_streamingSlotCollection = __esm(() => {
|
|
176638
|
-
StreamingSlotCollectorContext = createContext(null);
|
|
176639
|
-
});
|
|
176640
|
-
|
|
176641
|
-
// src/react/pageHandler.ts
|
|
176642
|
-
var ssrDirty2 = false, buildDirtyResponse = (index, maybeProps) => {
|
|
176643
|
-
const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
|
|
176644
|
-
const dirtyFlag = "window.__SSR_DIRTY__=true;";
|
|
176645
|
-
const refreshSetup = "window.__REFRESH_BUFFER__=[];" + "window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};" + "window.$RefreshSig$=function(){return function(t){return t}};";
|
|
176646
|
-
const inlineScript = `${propsScript}${dirtyFlag}${refreshSetup}`;
|
|
176647
|
-
const html = `<!DOCTYPE html><html><head></head><body>` + `<script>${inlineScript}</script>` + `<script type="module" src="${index}"></script>` + `</body></html>`;
|
|
176648
|
-
return new Response(html, {
|
|
176649
|
-
headers: { "Content-Type": "text/html" }
|
|
176650
|
-
});
|
|
176651
|
-
}, handleReactPageRequest = async (PageComponent, index, ...props) => {
|
|
176652
|
-
const [maybeProps] = props;
|
|
176653
|
-
if (ssrDirty2) {
|
|
176654
|
-
return buildDirtyResponse(index, maybeProps);
|
|
176655
|
-
}
|
|
176656
|
-
try {
|
|
176657
|
-
const { createElement: createElement2 } = await import("react");
|
|
176658
|
-
const { renderToReadableStream } = await import("react-dom/server");
|
|
176659
|
-
const slotCollector = new Map;
|
|
176660
|
-
const pageElement = maybeProps !== undefined ? createElement2(PageComponent, maybeProps) : createElement2(PageComponent);
|
|
176661
|
-
const element = createElement2(StreamingSlotCollectorProvider, { collector: slotCollector }, pageElement);
|
|
176662
|
-
const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
|
|
176663
|
-
const refreshSetup = "window.__REFRESH_BUFFER__=[];window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};window.$RefreshSig$=function(){return function(t){return t}};";
|
|
176664
|
-
const stream = await renderToReadableStream(element, {
|
|
176665
|
-
bootstrapModules: [index],
|
|
176666
|
-
bootstrapScriptContent: propsScript + refreshSetup || undefined,
|
|
176667
|
-
onError(error) {
|
|
176668
|
-
console.error("[SSR] React streaming error:", error);
|
|
176669
|
-
}
|
|
176670
|
-
});
|
|
176671
|
-
if ("allReady" in stream && stream.allReady instanceof Promise) {
|
|
176672
|
-
await stream.allReady;
|
|
176673
|
-
}
|
|
176674
|
-
const htmlStream = injectIslandPageContextStream(stream);
|
|
176675
|
-
return withStreamingSlots(new Response(htmlStream, {
|
|
176676
|
-
headers: { "Content-Type": "text/html" }
|
|
176677
|
-
}), {
|
|
176678
|
-
streamingSlots: [...slotCollector.values()]
|
|
176679
|
-
});
|
|
176680
|
-
} catch (error) {
|
|
176681
|
-
console.error("[SSR] React render error:", error);
|
|
176682
|
-
const pageName = PageComponent.name || PageComponent.displayName || "";
|
|
176683
|
-
const conventionResponse = await renderConventionError("react", pageName, error);
|
|
176684
|
-
if (conventionResponse)
|
|
176685
|
-
return conventionResponse;
|
|
176686
|
-
return new Response(ssrErrorPage("react", error), {
|
|
176687
|
-
headers: { "Content-Type": "text/html" },
|
|
176688
|
-
status: 500
|
|
176689
|
-
});
|
|
176690
|
-
}
|
|
176691
|
-
}, invalidateReactSsrCache = () => {
|
|
176692
|
-
ssrDirty2 = true;
|
|
176693
|
-
};
|
|
176694
|
-
var init_pageHandler2 = __esm(() => {
|
|
176695
|
-
init_responseEnhancers();
|
|
176696
|
-
init_resolveConvention();
|
|
176697
|
-
init_streamingSlotCollection();
|
|
176698
|
-
});
|
|
176699
|
-
|
|
176700
176145
|
// src/svelte/renderToReadableStream.ts
|
|
176701
176146
|
var exports_renderToReadableStream = {};
|
|
176702
176147
|
__export(exports_renderToReadableStream, {
|
|
@@ -179269,8 +178714,8 @@ var init_rebuildTrigger = __esm(() => {
|
|
|
179269
178714
|
init_assetStore();
|
|
179270
178715
|
init_pathUtils();
|
|
179271
178716
|
init_webSocket();
|
|
179272
|
-
init_pageHandler();
|
|
179273
178717
|
init_pageHandler2();
|
|
178718
|
+
init_pageHandler();
|
|
179274
178719
|
init_pageHandler3();
|
|
179275
178720
|
init_pageHandler4();
|
|
179276
178721
|
moduleServerPromise = Promise.resolve().then(() => (init_moduleServer(), exports_moduleServer));
|
|
@@ -180463,6 +179908,752 @@ var init_devCert = __esm(() => {
|
|
|
180463
179908
|
CERT_PATH = join23(CERT_DIR, "cert.pem");
|
|
180464
179909
|
KEY_PATH = join23(CERT_DIR, "key.pem");
|
|
180465
179910
|
});
|
|
179911
|
+
|
|
179912
|
+
// src/client/streamSwap.ts
|
|
179913
|
+
var streamSwapRuntime = () => {
|
|
179914
|
+
if (window.__ABS_SLOT_RUNTIME__ === true)
|
|
179915
|
+
return;
|
|
179916
|
+
window.__ABS_SLOT_RUNTIME__ = true;
|
|
179917
|
+
window.__ABS_SLOT_PENDING__ = window.__ABS_SLOT_PENDING__ ?? {};
|
|
179918
|
+
const pending = window.__ABS_SLOT_PENDING__;
|
|
179919
|
+
const apply = (id, html) => {
|
|
179920
|
+
const node = document.getElementById(`slot-${id}`);
|
|
179921
|
+
if (!node) {
|
|
179922
|
+
pending[id] = html;
|
|
179923
|
+
return;
|
|
179924
|
+
}
|
|
179925
|
+
node.innerHTML = html;
|
|
179926
|
+
delete pending[id];
|
|
179927
|
+
};
|
|
179928
|
+
const flush = () => {
|
|
179929
|
+
for (const id in pending) {
|
|
179930
|
+
if (!Object.prototype.hasOwnProperty.call(pending, id))
|
|
179931
|
+
continue;
|
|
179932
|
+
apply(id, pending[id] ?? "");
|
|
179933
|
+
}
|
|
179934
|
+
};
|
|
179935
|
+
window.__ABS_SLOT_ENQUEUE__ = (id, html) => {
|
|
179936
|
+
apply(id, html);
|
|
179937
|
+
};
|
|
179938
|
+
if (typeof MutationObserver === "function") {
|
|
179939
|
+
const observer = new MutationObserver(flush);
|
|
179940
|
+
const root = document.documentElement ?? document.body ?? document;
|
|
179941
|
+
observer.observe(root, { childList: true, subtree: true });
|
|
179942
|
+
}
|
|
179943
|
+
if (document.readyState === "loading") {
|
|
179944
|
+
document.addEventListener("DOMContentLoaded", flush, { once: true });
|
|
179945
|
+
}
|
|
179946
|
+
flush();
|
|
179947
|
+
};
|
|
179948
|
+
var stripFunctionWrapper = (value) => {
|
|
179949
|
+
const start = value.indexOf("{");
|
|
179950
|
+
const end = value.lastIndexOf("}");
|
|
179951
|
+
if (start < 0 || end <= start)
|
|
179952
|
+
return "";
|
|
179953
|
+
return value.slice(start + 1, end);
|
|
179954
|
+
};
|
|
179955
|
+
var getStreamSwapRuntimeScript = () => `(function(){${stripFunctionWrapper(streamSwapRuntime.toString())}})();`;
|
|
179956
|
+
|
|
179957
|
+
// src/utils/streamingSlots.ts
|
|
179958
|
+
init_escapeScriptContent();
|
|
179959
|
+
var SLOT_ID_PREFIX = "abs-slot-";
|
|
179960
|
+
var SLOT_PLACEHOLDER_PREFIX = "slot-";
|
|
179961
|
+
var CLOSING_HEAD_TAG = "</head>";
|
|
179962
|
+
var CLOSING_HEAD_TAG_LENGTH = CLOSING_HEAD_TAG.length;
|
|
179963
|
+
var CLOSING_PAGE_TAG_REGEX = /<\/body>\s*<\/html>\s*$/i;
|
|
179964
|
+
var STREAMING_RUNTIME_GLOBAL = "__ABS_SLOT_ENQUEUE__";
|
|
179965
|
+
var STREAMING_PENDING_GLOBAL = "__ABS_SLOT_PENDING__";
|
|
179966
|
+
var STREAM_TAIL_LOOKBEHIND = 128;
|
|
179967
|
+
var STREAMING_SLOT_TIMEOUT_MS = 5000;
|
|
179968
|
+
var STREAMING_SLOT_MAX_PER_RESPONSE = 128;
|
|
179969
|
+
var STREAMING_SLOT_MAX_HTML_BYTES = 64000;
|
|
179970
|
+
var createSlotPlaceholderId = (id) => `${SLOT_PLACEHOLDER_PREFIX}${id}`;
|
|
179971
|
+
var createSlotPatchStatement = (id, html) => `(window.${STREAMING_RUNTIME_GLOBAL}||function(i,h){window.${STREAMING_PENDING_GLOBAL}=window.${STREAMING_PENDING_GLOBAL}||{};window.${STREAMING_PENDING_GLOBAL}[i]=h;})(${JSON.stringify(id)},${JSON.stringify(html)});`;
|
|
179972
|
+
var createNonceAttr = (nonce) => nonce ? ` nonce="${nonce}"` : "";
|
|
179973
|
+
var createStreamingSlotId = () => `${SLOT_ID_PREFIX}${Math.random().toString(36).slice(2, 10)}`;
|
|
179974
|
+
var getStreamingSlotsRuntimeScript = () => getStreamSwapRuntimeScript();
|
|
179975
|
+
var renderStreamingSlotsRuntimeTag = (nonce) => `<script${createNonceAttr(nonce)}>${escapeScriptContent(getStreamingSlotsRuntimeScript())}</script>`;
|
|
179976
|
+
var renderStreamingSlotPlaceholder = (id, fallbackHtml = "") => `<div id="${createSlotPlaceholderId(id)}" data-absolute-slot="true">${fallbackHtml}</div>`;
|
|
179977
|
+
var renderStreamingSlotPatchTag = (id, html, nonce) => `<script${createNonceAttr(nonce)}>${escapeScriptContent(createSlotPatchStatement(id, html))}</script>`;
|
|
179978
|
+
var injectHtmlIntoHead = (html, injection) => {
|
|
179979
|
+
const closingHeadIndex = html.indexOf(CLOSING_HEAD_TAG);
|
|
179980
|
+
if (closingHeadIndex >= 0) {
|
|
179981
|
+
return `${html.slice(0, closingHeadIndex)}${injection}${html.slice(closingHeadIndex)}`;
|
|
179982
|
+
}
|
|
179983
|
+
return `${html}${injection}`;
|
|
179984
|
+
};
|
|
179985
|
+
var toUint8 = (value, encoder) => encoder.encode(value);
|
|
179986
|
+
var currentStreamingSlotPolicy = {
|
|
179987
|
+
timeoutMs: STREAMING_SLOT_TIMEOUT_MS,
|
|
179988
|
+
fallbackHtml: "",
|
|
179989
|
+
errorHtml: undefined,
|
|
179990
|
+
maxSlotsPerResponse: STREAMING_SLOT_MAX_PER_RESPONSE,
|
|
179991
|
+
maxSlotHtmlSizeBytes: STREAMING_SLOT_MAX_HTML_BYTES
|
|
179992
|
+
};
|
|
179993
|
+
var clonePolicy = (policy) => ({
|
|
179994
|
+
...policy
|
|
179995
|
+
});
|
|
179996
|
+
var normalizeSlotBytes = (value, fallback) => {
|
|
179997
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
179998
|
+
return Math.floor(value);
|
|
179999
|
+
}
|
|
180000
|
+
return fallback;
|
|
180001
|
+
};
|
|
180002
|
+
var normalizeSlotText = (value, fallback) => typeof value === "string" ? value : fallback;
|
|
180003
|
+
var normalizeSlotError = (value, fallback) => typeof value === "string" ? value : fallback;
|
|
180004
|
+
var hasPolicyValue = (policy, key) => Object.prototype.hasOwnProperty.call(policy, key);
|
|
180005
|
+
var applyStreamingSlotPolicyOverrides = (base, overridePolicy = {}) => ({
|
|
180006
|
+
timeoutMs: hasPolicyValue(overridePolicy, "timeoutMs") ? normalizeSlotBytes(overridePolicy.timeoutMs, base.timeoutMs) : base.timeoutMs,
|
|
180007
|
+
fallbackHtml: hasPolicyValue(overridePolicy, "fallbackHtml") ? normalizeSlotText(overridePolicy.fallbackHtml, "") : base.fallbackHtml,
|
|
180008
|
+
errorHtml: hasPolicyValue(overridePolicy, "errorHtml") ? normalizeSlotError(overridePolicy.errorHtml) : base.errorHtml,
|
|
180009
|
+
maxSlotsPerResponse: hasPolicyValue(overridePolicy, "maxSlotsPerResponse") ? normalizeSlotBytes(overridePolicy.maxSlotsPerResponse, base.maxSlotsPerResponse) : base.maxSlotsPerResponse,
|
|
180010
|
+
maxSlotHtmlSizeBytes: hasPolicyValue(overridePolicy, "maxSlotHtmlSizeBytes") ? normalizeSlotBytes(overridePolicy.maxSlotHtmlSizeBytes, base.maxSlotHtmlSizeBytes) : base.maxSlotHtmlSizeBytes,
|
|
180011
|
+
onError: hasPolicyValue(overridePolicy, "onError") ? overridePolicy.onError : base.onError,
|
|
180012
|
+
onSlotMetric: hasPolicyValue(overridePolicy, "onSlotMetric") ? overridePolicy.onSlotMetric : base.onSlotMetric
|
|
180013
|
+
});
|
|
180014
|
+
var createCombinedSlotErrorHandler = (policyOnError, enhancerOnError) => {
|
|
180015
|
+
if (!policyOnError && !enhancerOnError)
|
|
180016
|
+
return;
|
|
180017
|
+
return (error, slot) => {
|
|
180018
|
+
policyOnError?.(error, slot);
|
|
180019
|
+
enhancerOnError?.(error, slot);
|
|
180020
|
+
};
|
|
180021
|
+
};
|
|
180022
|
+
var createCombinedSlotMetricHandler = (policyOnSlotMetric, callOnSlotMetric) => {
|
|
180023
|
+
if (!policyOnSlotMetric && !callOnSlotMetric)
|
|
180024
|
+
return;
|
|
180025
|
+
return (metric) => {
|
|
180026
|
+
policyOnSlotMetric?.(metric);
|
|
180027
|
+
callOnSlotMetric?.(metric);
|
|
180028
|
+
};
|
|
180029
|
+
};
|
|
180030
|
+
var resolveStreamingSlotPolicy = (overridePolicy = {}) => {
|
|
180031
|
+
const base = getStreamingSlotPolicy();
|
|
180032
|
+
return applyStreamingSlotPolicyOverrides(base, overridePolicy);
|
|
180033
|
+
};
|
|
180034
|
+
var getStreamingSlotPolicy = () => clonePolicy(currentStreamingSlotPolicy);
|
|
180035
|
+
var setStreamingSlotPolicy = (policy = {}) => {
|
|
180036
|
+
const base = getStreamingSlotPolicy();
|
|
180037
|
+
currentStreamingSlotPolicy = applyStreamingSlotPolicyOverrides(base, policy);
|
|
180038
|
+
};
|
|
180039
|
+
var withStreamingSlotPolicy = async (policy, callback) => {
|
|
180040
|
+
const previous = getStreamingSlotPolicy();
|
|
180041
|
+
setStreamingSlotPolicy(policy);
|
|
180042
|
+
try {
|
|
180043
|
+
return await callback();
|
|
180044
|
+
} finally {
|
|
180045
|
+
currentStreamingSlotPolicy = previous;
|
|
180046
|
+
}
|
|
180047
|
+
};
|
|
180048
|
+
var emitSlotMetric = (metric, onSlotMetric) => {
|
|
180049
|
+
onSlotMetric?.(metric);
|
|
180050
|
+
};
|
|
180051
|
+
var createTimeoutError = (slot, timeoutMs) => {
|
|
180052
|
+
const error = new Error(`Streaming slot "${slot.id}" timed out after ${timeoutMs}ms`);
|
|
180053
|
+
error.__absTimeout = true;
|
|
180054
|
+
return error;
|
|
180055
|
+
};
|
|
180056
|
+
var toStreamingSlot = (slot, policy) => ({
|
|
180057
|
+
errorHtml: slot.errorHtml === undefined ? policy.errorHtml : slot.errorHtml,
|
|
180058
|
+
fallbackHtml: normalizeSlotText(slot.fallbackHtml, policy.fallbackHtml),
|
|
180059
|
+
id: slot.id ?? createStreamingSlotId(),
|
|
180060
|
+
timeoutMs: normalizeSlotBytes(slot.timeoutMs, policy.timeoutMs),
|
|
180061
|
+
resolve: slot.resolve
|
|
180062
|
+
});
|
|
180063
|
+
var prepareSlots = ({
|
|
180064
|
+
policy,
|
|
180065
|
+
slots,
|
|
180066
|
+
onError,
|
|
180067
|
+
onSlotMetric
|
|
180068
|
+
}) => {
|
|
180069
|
+
const preparedSlots = slots.map((slot) => toStreamingSlot(slot, policy));
|
|
180070
|
+
const maxSlotsPerResponse = policy.maxSlotsPerResponse;
|
|
180071
|
+
if (maxSlotsPerResponse === 0) {
|
|
180072
|
+
const error = new Error("Streaming slot limit is set to 0");
|
|
180073
|
+
for (const slot of preparedSlots) {
|
|
180074
|
+
onError?.(error, slot);
|
|
180075
|
+
emitSlotMetric({
|
|
180076
|
+
type: "dropped",
|
|
180077
|
+
slotId: slot.id,
|
|
180078
|
+
reason: "maxSlotsPerResponse is 0"
|
|
180079
|
+
}, onSlotMetric);
|
|
180080
|
+
}
|
|
180081
|
+
return [];
|
|
180082
|
+
}
|
|
180083
|
+
if (preparedSlots.length <= maxSlotsPerResponse) {
|
|
180084
|
+
preparedSlots.forEach((slot) => emitSlotMetric({
|
|
180085
|
+
type: "prepared",
|
|
180086
|
+
slotId: slot.id
|
|
180087
|
+
}, onSlotMetric));
|
|
180088
|
+
return preparedSlots;
|
|
180089
|
+
}
|
|
180090
|
+
const keptSlots = preparedSlots.slice(0, maxSlotsPerResponse);
|
|
180091
|
+
const droppedSlots = preparedSlots.slice(maxSlotsPerResponse);
|
|
180092
|
+
droppedSlots.forEach((slot) => {
|
|
180093
|
+
onError?.(new Error(`Streaming slot "${slot.id}" dropped because ${maxSlotsPerResponse} slots is the configured maximum`), slot);
|
|
180094
|
+
emitSlotMetric({
|
|
180095
|
+
type: "dropped",
|
|
180096
|
+
slotId: slot.id,
|
|
180097
|
+
reason: `maxSlotsPerResponse is ${maxSlotsPerResponse}`
|
|
180098
|
+
}, onSlotMetric);
|
|
180099
|
+
});
|
|
180100
|
+
keptSlots.forEach((slot) => emitSlotMetric({
|
|
180101
|
+
type: "prepared",
|
|
180102
|
+
slotId: slot.id
|
|
180103
|
+
}, onSlotMetric));
|
|
180104
|
+
return keptSlots;
|
|
180105
|
+
};
|
|
180106
|
+
var htmlByteLength = (value, encoder) => encoder.encode(value).length;
|
|
180107
|
+
var resolveSlot = async (slot, onError, policy, onSlotMetric) => {
|
|
180108
|
+
const safePolicy = policy ?? getStreamingSlotPolicy();
|
|
180109
|
+
const encoder = new TextEncoder;
|
|
180110
|
+
const start = Date.now();
|
|
180111
|
+
try {
|
|
180112
|
+
const maybeAsyncValue = Promise.resolve(slot.resolve());
|
|
180113
|
+
const resolved = typeof slot.timeoutMs === "number" && slot.timeoutMs > 0 ? await Promise.race([
|
|
180114
|
+
maybeAsyncValue,
|
|
180115
|
+
new Promise((_, reject) => setTimeout(() => {
|
|
180116
|
+
reject(createTimeoutError(slot, slot.timeoutMs ?? 0));
|
|
180117
|
+
}, slot.timeoutMs))
|
|
180118
|
+
]) : await maybeAsyncValue;
|
|
180119
|
+
const html = typeof resolved === "string" ? resolved : `${resolved}`;
|
|
180120
|
+
if (safePolicy.maxSlotHtmlSizeBytes > 0 && htmlByteLength(html, encoder) > safePolicy.maxSlotHtmlSizeBytes) {
|
|
180121
|
+
const bytes2 = htmlByteLength(html, encoder);
|
|
180122
|
+
const error = new Error(`Streaming slot "${slot.id}" exceeded max payload size of ${safePolicy.maxSlotHtmlSizeBytes} bytes`);
|
|
180123
|
+
const durationMs2 = Date.now() - start;
|
|
180124
|
+
onError?.(error, slot);
|
|
180125
|
+
emitSlotMetric({
|
|
180126
|
+
type: "size_exceeded",
|
|
180127
|
+
slotId: slot.id,
|
|
180128
|
+
durationMs: durationMs2,
|
|
180129
|
+
bytes: bytes2,
|
|
180130
|
+
error
|
|
180131
|
+
}, onSlotMetric);
|
|
180132
|
+
const fallbackHtml = typeof slot.errorHtml === "string" ? slot.errorHtml : null;
|
|
180133
|
+
return {
|
|
180134
|
+
html: fallbackHtml,
|
|
180135
|
+
id: slot.id,
|
|
180136
|
+
durationMs: durationMs2,
|
|
180137
|
+
bytes: fallbackHtml === null ? 0 : htmlByteLength(fallbackHtml, encoder)
|
|
180138
|
+
};
|
|
180139
|
+
}
|
|
180140
|
+
const durationMs = Date.now() - start;
|
|
180141
|
+
const bytes = htmlByteLength(html, encoder);
|
|
180142
|
+
emitSlotMetric({
|
|
180143
|
+
type: "resolved",
|
|
180144
|
+
slotId: slot.id,
|
|
180145
|
+
durationMs,
|
|
180146
|
+
bytes
|
|
180147
|
+
}, onSlotMetric);
|
|
180148
|
+
return {
|
|
180149
|
+
html,
|
|
180150
|
+
id: slot.id,
|
|
180151
|
+
durationMs,
|
|
180152
|
+
bytes
|
|
180153
|
+
};
|
|
180154
|
+
} catch (error) {
|
|
180155
|
+
const durationMs = Date.now() - start;
|
|
180156
|
+
onError?.(error, slot);
|
|
180157
|
+
emitSlotMetric({
|
|
180158
|
+
type: error?.__absTimeout === true ? "timeout" : "error",
|
|
180159
|
+
slotId: slot.id,
|
|
180160
|
+
durationMs,
|
|
180161
|
+
error
|
|
180162
|
+
}, onSlotMetric);
|
|
180163
|
+
if (typeof slot.errorHtml === "string") {
|
|
180164
|
+
const html = slot.errorHtml;
|
|
180165
|
+
return {
|
|
180166
|
+
html,
|
|
180167
|
+
id: slot.id,
|
|
180168
|
+
durationMs,
|
|
180169
|
+
bytes: htmlByteLength(html, encoder)
|
|
180170
|
+
};
|
|
180171
|
+
}
|
|
180172
|
+
return {
|
|
180173
|
+
html: null,
|
|
180174
|
+
id: slot.id,
|
|
180175
|
+
durationMs,
|
|
180176
|
+
bytes: 0
|
|
180177
|
+
};
|
|
180178
|
+
}
|
|
180179
|
+
};
|
|
180180
|
+
var nextResolvedSlot = async (pending) => {
|
|
180181
|
+
const wrapped = pending.map((promise) => promise.then((result) => ({
|
|
180182
|
+
original: promise,
|
|
180183
|
+
result
|
|
180184
|
+
})));
|
|
180185
|
+
return Promise.race(wrapped);
|
|
180186
|
+
};
|
|
180187
|
+
var streamChunkToString = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true });
|
|
180188
|
+
var streamOutOfOrderSlots = ({
|
|
180189
|
+
footerHtml = "",
|
|
180190
|
+
headerHtml = "",
|
|
180191
|
+
nonce,
|
|
180192
|
+
policy,
|
|
180193
|
+
onSlotMetric,
|
|
180194
|
+
onError,
|
|
180195
|
+
slots
|
|
180196
|
+
}) => {
|
|
180197
|
+
const resolvedPolicy = resolveStreamingSlotPolicy(policy);
|
|
180198
|
+
const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
|
|
180199
|
+
const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
|
|
180200
|
+
const effectivePolicy = {
|
|
180201
|
+
...resolvedPolicy,
|
|
180202
|
+
onSlotMetric: combinedOnSlotMetric
|
|
180203
|
+
};
|
|
180204
|
+
const preparedSlots = prepareSlots({
|
|
180205
|
+
policy: effectivePolicy,
|
|
180206
|
+
slots,
|
|
180207
|
+
onError: combinedOnError,
|
|
180208
|
+
onSlotMetric: combinedOnSlotMetric
|
|
180209
|
+
});
|
|
180210
|
+
const encoder = new TextEncoder;
|
|
180211
|
+
return new ReadableStream({
|
|
180212
|
+
async start(controller) {
|
|
180213
|
+
try {
|
|
180214
|
+
let header = headerHtml;
|
|
180215
|
+
if (preparedSlots.length > 0 && !header.includes(STREAMING_RUNTIME_GLOBAL)) {
|
|
180216
|
+
header = injectHtmlIntoHead(header, renderStreamingSlotsRuntimeTag(nonce));
|
|
180217
|
+
}
|
|
180218
|
+
controller.enqueue(toUint8(header, encoder));
|
|
180219
|
+
const pending = preparedSlots.map((slot) => {
|
|
180220
|
+
const fallback = renderStreamingSlotPlaceholder(slot.id, slot.fallbackHtml ?? "");
|
|
180221
|
+
controller.enqueue(toUint8(fallback, encoder));
|
|
180222
|
+
return resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric);
|
|
180223
|
+
});
|
|
180224
|
+
while (pending.length > 0) {
|
|
180225
|
+
const { original, result } = await nextResolvedSlot(pending);
|
|
180226
|
+
const index = pending.indexOf(original);
|
|
180227
|
+
if (index >= 0)
|
|
180228
|
+
pending.splice(index, 1);
|
|
180229
|
+
if (result.html === null)
|
|
180230
|
+
continue;
|
|
180231
|
+
emitSlotMetric({
|
|
180232
|
+
type: "patched",
|
|
180233
|
+
slotId: result.id,
|
|
180234
|
+
durationMs: result.durationMs,
|
|
180235
|
+
bytes: result.bytes
|
|
180236
|
+
}, combinedOnSlotMetric);
|
|
180237
|
+
controller.enqueue(toUint8(renderStreamingSlotPatchTag(result.id, result.html, nonce), encoder));
|
|
180238
|
+
}
|
|
180239
|
+
if (footerHtml.length > 0) {
|
|
180240
|
+
controller.enqueue(toUint8(footerHtml, encoder));
|
|
180241
|
+
}
|
|
180242
|
+
controller.close();
|
|
180243
|
+
} catch (error) {
|
|
180244
|
+
controller.error(error);
|
|
180245
|
+
}
|
|
180246
|
+
}
|
|
180247
|
+
});
|
|
180248
|
+
};
|
|
180249
|
+
var injectStreamingRuntimeIntoStream = (stream, nonce) => {
|
|
180250
|
+
const runtimeTag = renderStreamingSlotsRuntimeTag(nonce);
|
|
180251
|
+
const encoder = new TextEncoder;
|
|
180252
|
+
const decoder = new TextDecoder;
|
|
180253
|
+
const lookbehind = CLOSING_HEAD_TAG_LENGTH - 1;
|
|
180254
|
+
return new ReadableStream({
|
|
180255
|
+
async start(controller) {
|
|
180256
|
+
const reader = stream.getReader();
|
|
180257
|
+
let injected = false;
|
|
180258
|
+
let pending = "";
|
|
180259
|
+
try {
|
|
180260
|
+
for (;; ) {
|
|
180261
|
+
const { done, value } = await reader.read();
|
|
180262
|
+
if (done)
|
|
180263
|
+
break;
|
|
180264
|
+
if (!value)
|
|
180265
|
+
continue;
|
|
180266
|
+
pending += streamChunkToString(value, decoder);
|
|
180267
|
+
if (injected) {
|
|
180268
|
+
controller.enqueue(encoder.encode(pending));
|
|
180269
|
+
pending = "";
|
|
180270
|
+
continue;
|
|
180271
|
+
}
|
|
180272
|
+
const headIndex = pending.indexOf(CLOSING_HEAD_TAG);
|
|
180273
|
+
if (headIndex >= 0) {
|
|
180274
|
+
const withRuntime = `${pending.slice(0, headIndex)}${runtimeTag}${pending.slice(headIndex)}`;
|
|
180275
|
+
controller.enqueue(encoder.encode(withRuntime));
|
|
180276
|
+
pending = "";
|
|
180277
|
+
injected = true;
|
|
180278
|
+
continue;
|
|
180279
|
+
}
|
|
180280
|
+
if (pending.length > lookbehind) {
|
|
180281
|
+
const safeText = pending.slice(0, pending.length - lookbehind);
|
|
180282
|
+
controller.enqueue(encoder.encode(safeText));
|
|
180283
|
+
pending = pending.slice(-lookbehind);
|
|
180284
|
+
}
|
|
180285
|
+
}
|
|
180286
|
+
pending += decoder.decode();
|
|
180287
|
+
if (!injected) {
|
|
180288
|
+
pending = injectHtmlIntoHead(pending, runtimeTag);
|
|
180289
|
+
}
|
|
180290
|
+
if (pending.length > 0) {
|
|
180291
|
+
controller.enqueue(encoder.encode(pending));
|
|
180292
|
+
}
|
|
180293
|
+
controller.close();
|
|
180294
|
+
} catch (error) {
|
|
180295
|
+
controller.error(error);
|
|
180296
|
+
}
|
|
180297
|
+
}
|
|
180298
|
+
});
|
|
180299
|
+
};
|
|
180300
|
+
var appendStreamingSlotPatchesToStream = (stream, slots = [], {
|
|
180301
|
+
injectRuntime = true,
|
|
180302
|
+
nonce,
|
|
180303
|
+
onError,
|
|
180304
|
+
onSlotMetric,
|
|
180305
|
+
policy
|
|
180306
|
+
} = {}) => {
|
|
180307
|
+
const resolvedPolicy = resolveStreamingSlotPolicy(policy);
|
|
180308
|
+
const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
|
|
180309
|
+
const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
|
|
180310
|
+
const effectivePolicy = {
|
|
180311
|
+
...resolvedPolicy,
|
|
180312
|
+
onSlotMetric: combinedOnSlotMetric
|
|
180313
|
+
};
|
|
180314
|
+
const preparedSlots = prepareSlots({
|
|
180315
|
+
policy: effectivePolicy,
|
|
180316
|
+
slots,
|
|
180317
|
+
onError: combinedOnError,
|
|
180318
|
+
onSlotMetric: combinedOnSlotMetric
|
|
180319
|
+
});
|
|
180320
|
+
if (preparedSlots.length === 0)
|
|
180321
|
+
return stream;
|
|
180322
|
+
const source = injectRuntime ? injectStreamingRuntimeIntoStream(stream, nonce) : stream;
|
|
180323
|
+
const encoder = new TextEncoder;
|
|
180324
|
+
const decoder = new TextDecoder;
|
|
180325
|
+
const reader = source.getReader();
|
|
180326
|
+
const pending = preparedSlots.map((slot) => resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric));
|
|
180327
|
+
return new ReadableStream({
|
|
180328
|
+
async start(controller) {
|
|
180329
|
+
let baseDone = false;
|
|
180330
|
+
let baseRead = reader.read();
|
|
180331
|
+
let tail = "";
|
|
180332
|
+
let footer = "";
|
|
180333
|
+
try {
|
|
180334
|
+
while (!baseDone || pending.length > 0) {
|
|
180335
|
+
const racers = [];
|
|
180336
|
+
if (!baseDone) {
|
|
180337
|
+
racers.push(baseRead.then(({ done, value }) => ({
|
|
180338
|
+
done,
|
|
180339
|
+
kind: "base",
|
|
180340
|
+
value
|
|
180341
|
+
})));
|
|
180342
|
+
}
|
|
180343
|
+
if (pending.length > 0) {
|
|
180344
|
+
racers.push(nextResolvedSlot(pending).then((resolved) => ({
|
|
180345
|
+
kind: "slot",
|
|
180346
|
+
...resolved
|
|
180347
|
+
})));
|
|
180348
|
+
}
|
|
180349
|
+
if (racers.length === 0)
|
|
180350
|
+
break;
|
|
180351
|
+
const winner = await Promise.race(racers);
|
|
180352
|
+
if (winner.kind === "base") {
|
|
180353
|
+
if (winner.done) {
|
|
180354
|
+
baseDone = true;
|
|
180355
|
+
tail += decoder.decode();
|
|
180356
|
+
const footerStart = tail.search(CLOSING_PAGE_TAG_REGEX);
|
|
180357
|
+
if (footerStart >= 0) {
|
|
180358
|
+
const content = tail.slice(0, footerStart);
|
|
180359
|
+
footer = tail.slice(footerStart);
|
|
180360
|
+
if (content.length > 0) {
|
|
180361
|
+
controller.enqueue(encoder.encode(content));
|
|
180362
|
+
}
|
|
180363
|
+
} else if (tail.length > 0) {
|
|
180364
|
+
controller.enqueue(encoder.encode(tail));
|
|
180365
|
+
}
|
|
180366
|
+
tail = "";
|
|
180367
|
+
} else if (winner.value) {
|
|
180368
|
+
tail += streamChunkToString(winner.value, decoder);
|
|
180369
|
+
if (tail.length > STREAM_TAIL_LOOKBEHIND) {
|
|
180370
|
+
const content = tail.slice(0, tail.length - STREAM_TAIL_LOOKBEHIND);
|
|
180371
|
+
controller.enqueue(encoder.encode(content));
|
|
180372
|
+
tail = tail.slice(-STREAM_TAIL_LOOKBEHIND);
|
|
180373
|
+
}
|
|
180374
|
+
baseRead = reader.read();
|
|
180375
|
+
}
|
|
180376
|
+
continue;
|
|
180377
|
+
}
|
|
180378
|
+
const index = pending.indexOf(winner.original);
|
|
180379
|
+
if (index >= 0)
|
|
180380
|
+
pending.splice(index, 1);
|
|
180381
|
+
if (winner.result.html === null)
|
|
180382
|
+
continue;
|
|
180383
|
+
emitSlotMetric({
|
|
180384
|
+
type: "patched",
|
|
180385
|
+
slotId: winner.result.id,
|
|
180386
|
+
durationMs: winner.result.durationMs,
|
|
180387
|
+
bytes: winner.result.bytes
|
|
180388
|
+
}, combinedOnSlotMetric);
|
|
180389
|
+
controller.enqueue(encoder.encode(renderStreamingSlotPatchTag(winner.result.id, winner.result.html, nonce)));
|
|
180390
|
+
}
|
|
180391
|
+
if (footer.length > 0)
|
|
180392
|
+
controller.enqueue(encoder.encode(footer));
|
|
180393
|
+
controller.close();
|
|
180394
|
+
} catch (error) {
|
|
180395
|
+
controller.error(error);
|
|
180396
|
+
}
|
|
180397
|
+
}
|
|
180398
|
+
});
|
|
180399
|
+
};
|
|
180400
|
+
|
|
180401
|
+
// src/core/streamingSlotRegistrar.ts
|
|
180402
|
+
var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
|
|
180403
|
+
var getRegistrarGlobal = () => globalThis;
|
|
180404
|
+
var setStreamingSlotRegistrar = (nextRegistrar) => {
|
|
180405
|
+
getRegistrarGlobal()[STREAMING_SLOT_REGISTRAR_KEY] = nextRegistrar;
|
|
180406
|
+
};
|
|
180407
|
+
var registerStreamingSlot = (slot) => {
|
|
180408
|
+
getRegistrarGlobal()[STREAMING_SLOT_REGISTRAR_KEY]?.(slot);
|
|
180409
|
+
};
|
|
180410
|
+
|
|
180411
|
+
// src/core/streamingSlotRegistry.ts
|
|
180412
|
+
var asyncLocalStorage;
|
|
180413
|
+
var isServerRuntime = () => typeof process !== "undefined" && typeof process.versions?.node === "string";
|
|
180414
|
+
var ensureAsyncLocalStorage = async () => {
|
|
180415
|
+
if (typeof asyncLocalStorage !== "undefined")
|
|
180416
|
+
return asyncLocalStorage;
|
|
180417
|
+
if (!isServerRuntime()) {
|
|
180418
|
+
asyncLocalStorage = null;
|
|
180419
|
+
return asyncLocalStorage;
|
|
180420
|
+
}
|
|
180421
|
+
const mod = await import("async_hooks");
|
|
180422
|
+
asyncLocalStorage = new mod.AsyncLocalStorage;
|
|
180423
|
+
return asyncLocalStorage;
|
|
180424
|
+
};
|
|
180425
|
+
var registerStreamingSlot2 = (slot) => {
|
|
180426
|
+
if (!asyncLocalStorage)
|
|
180427
|
+
return;
|
|
180428
|
+
const store = asyncLocalStorage.getStore();
|
|
180429
|
+
if (!store)
|
|
180430
|
+
return;
|
|
180431
|
+
store.set(slot.id, slot);
|
|
180432
|
+
};
|
|
180433
|
+
setStreamingSlotRegistrar(registerStreamingSlot2);
|
|
180434
|
+
var runWithStreamingSlotRegistry = async (task) => {
|
|
180435
|
+
const storage = await ensureAsyncLocalStorage();
|
|
180436
|
+
if (!storage) {
|
|
180437
|
+
return {
|
|
180438
|
+
result: await task(),
|
|
180439
|
+
slots: []
|
|
180440
|
+
};
|
|
180441
|
+
}
|
|
180442
|
+
return storage.run(new Map, async () => {
|
|
180443
|
+
const result = await task();
|
|
180444
|
+
const store = storage.getStore();
|
|
180445
|
+
return {
|
|
180446
|
+
result,
|
|
180447
|
+
slots: store ? [...store.values()] : []
|
|
180448
|
+
};
|
|
180449
|
+
});
|
|
180450
|
+
};
|
|
180451
|
+
|
|
180452
|
+
// src/core/responseEnhancers.ts
|
|
180453
|
+
var toResponse = async (responseLike) => await responseLike;
|
|
180454
|
+
var cloneHeaders = (response) => {
|
|
180455
|
+
const headers = new Headers(response.headers);
|
|
180456
|
+
return headers;
|
|
180457
|
+
};
|
|
180458
|
+
var enhanceHtmlResponseWithStreamingSlots = (response, { nonce, onError, streamingSlots = [], policy } = {}) => {
|
|
180459
|
+
if (!response.body || streamingSlots.length === 0) {
|
|
180460
|
+
return response;
|
|
180461
|
+
}
|
|
180462
|
+
const body = appendStreamingSlotPatchesToStream(response.body, streamingSlots, {
|
|
180463
|
+
nonce,
|
|
180464
|
+
onError,
|
|
180465
|
+
policy
|
|
180466
|
+
});
|
|
180467
|
+
return new Response(body, {
|
|
180468
|
+
headers: cloneHeaders(response),
|
|
180469
|
+
status: response.status,
|
|
180470
|
+
statusText: response.statusText
|
|
180471
|
+
});
|
|
180472
|
+
};
|
|
180473
|
+
var withStreamingSlots = async (responseLike, options = {}) => enhanceHtmlResponseWithStreamingSlots(await toResponse(responseLike), options);
|
|
180474
|
+
var mergeStreamingSlots = (registered, explicit) => {
|
|
180475
|
+
const merged = new Map;
|
|
180476
|
+
for (const slot of registered)
|
|
180477
|
+
merged.set(slot.id, slot);
|
|
180478
|
+
for (const slot of explicit)
|
|
180479
|
+
merged.set(slot.id, slot);
|
|
180480
|
+
return [...merged.values()];
|
|
180481
|
+
};
|
|
180482
|
+
var withRegisteredStreamingSlots = async (renderResponse, options = {}) => {
|
|
180483
|
+
const { result, slots } = await runWithStreamingSlotRegistry(renderResponse);
|
|
180484
|
+
const explicit = options.streamingSlots ?? [];
|
|
180485
|
+
return withStreamingSlots(result, {
|
|
180486
|
+
...options,
|
|
180487
|
+
streamingSlots: mergeStreamingSlots(slots, explicit)
|
|
180488
|
+
});
|
|
180489
|
+
};
|
|
180490
|
+
|
|
180491
|
+
// src/core/wrapPageHandlerWithStreamingSlots.ts
|
|
180492
|
+
var wrapPageHandlerWithStreamingSlots = (handler) => (...args) => withRegisteredStreamingSlots(() => handler(...args));
|
|
180493
|
+
|
|
180494
|
+
// src/react/index.ts
|
|
180495
|
+
init_pageHandler();
|
|
180496
|
+
|
|
180497
|
+
// src/react/Island.tsx
|
|
180498
|
+
init_islandMarkupAttributes();
|
|
180499
|
+
init_renderIslandMarkup();
|
|
180500
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
180501
|
+
var Island = async (props) => {
|
|
180502
|
+
if (typeof window !== "undefined") {
|
|
180503
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
180504
|
+
...getIslandMarkerAttributes(props),
|
|
180505
|
+
suppressHydrationWarning: true
|
|
180506
|
+
}, undefined, false, undefined, this);
|
|
180507
|
+
}
|
|
180508
|
+
const result = await renderIslandResult(requireCurrentIslandRegistry(), props);
|
|
180509
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
180510
|
+
...result.attributes,
|
|
180511
|
+
dangerouslySetInnerHTML: { __html: result.html }
|
|
180512
|
+
}, undefined, false, undefined, this);
|
|
180513
|
+
};
|
|
180514
|
+
// src/react/createIsland.tsx
|
|
180515
|
+
init_islandMarkupAttributes();
|
|
180516
|
+
init_renderIslandMarkup();
|
|
180517
|
+
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
180518
|
+
var createTypedIsland = (registry) => {
|
|
180519
|
+
const Island2 = async (props) => {
|
|
180520
|
+
if (typeof window !== "undefined") {
|
|
180521
|
+
return /* @__PURE__ */ jsxDEV2("div", {
|
|
180522
|
+
...getIslandMarkerAttributes(props),
|
|
180523
|
+
suppressHydrationWarning: true
|
|
180524
|
+
}, undefined, false, undefined, this);
|
|
180525
|
+
}
|
|
180526
|
+
const result = await renderIslandResult(registry, props);
|
|
180527
|
+
return /* @__PURE__ */ jsxDEV2("div", {
|
|
180528
|
+
...result.attributes,
|
|
180529
|
+
dangerouslySetInnerHTML: { __html: result.html }
|
|
180530
|
+
}, undefined, false, undefined, this);
|
|
180531
|
+
};
|
|
180532
|
+
return Island2;
|
|
180533
|
+
};
|
|
180534
|
+
// src/react/hooks/useIslandStore.ts
|
|
180535
|
+
import { useSyncExternalStore } from "react";
|
|
180536
|
+
|
|
180537
|
+
// node_modules/zustand/esm/vanilla.mjs
|
|
180538
|
+
var createStoreImpl = (createState) => {
|
|
180539
|
+
let state;
|
|
180540
|
+
const listeners = /* @__PURE__ */ new Set;
|
|
180541
|
+
const setState = (partial, replace) => {
|
|
180542
|
+
const nextState = typeof partial === "function" ? partial(state) : partial;
|
|
180543
|
+
if (!Object.is(nextState, state)) {
|
|
180544
|
+
const previousState = state;
|
|
180545
|
+
state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
|
|
180546
|
+
listeners.forEach((listener) => listener(state, previousState));
|
|
180547
|
+
}
|
|
180548
|
+
};
|
|
180549
|
+
const getState = () => state;
|
|
180550
|
+
const getInitialState = () => initialState;
|
|
180551
|
+
const subscribe = (listener) => {
|
|
180552
|
+
listeners.add(listener);
|
|
180553
|
+
return () => listeners.delete(listener);
|
|
180554
|
+
};
|
|
180555
|
+
const api = { setState, getState, getInitialState, subscribe };
|
|
180556
|
+
const initialState = state = createState(setState, getState, api);
|
|
180557
|
+
return api;
|
|
180558
|
+
};
|
|
180559
|
+
var createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
|
|
180560
|
+
|
|
180561
|
+
// node_modules/zustand/esm/middleware.mjs
|
|
180562
|
+
function combine(initialState, create) {
|
|
180563
|
+
return (...args) => Object.assign({}, initialState, create(...args));
|
|
180564
|
+
}
|
|
180565
|
+
|
|
180566
|
+
// src/client/islandStore.ts
|
|
180567
|
+
var getIslandStoreSnapshot = () => {
|
|
180568
|
+
globalThis.__ABS_ISLAND_STATE__ ??= {};
|
|
180569
|
+
return globalThis.__ABS_ISLAND_STATE__;
|
|
180570
|
+
};
|
|
180571
|
+
var getIslandStores = () => {
|
|
180572
|
+
globalThis.__ABS_ISLAND_STORES__ ??= new Map;
|
|
180573
|
+
return globalThis.__ABS_ISLAND_STORES__;
|
|
180574
|
+
};
|
|
180575
|
+
var isSerializableValue = (value) => typeof value !== "function" && value !== undefined;
|
|
180576
|
+
var toSerializableState = (state) => Object.fromEntries(Object.entries(state).filter(([, value]) => isSerializableValue(value)));
|
|
180577
|
+
var applySnapshot = (store, snapshot) => {
|
|
180578
|
+
if (!snapshot) {
|
|
180579
|
+
return;
|
|
180580
|
+
}
|
|
180581
|
+
store.setState({
|
|
180582
|
+
...store.getState(),
|
|
180583
|
+
...snapshot
|
|
180584
|
+
});
|
|
180585
|
+
};
|
|
180586
|
+
var getPeerStores = (storeInstances, ownerStore) => [...storeInstances].filter((peer) => peer.store !== ownerStore);
|
|
180587
|
+
var syncIslandSnapshot = (storeId, state, storeInstances, ownerStore) => {
|
|
180588
|
+
const nextSnapshot = toSerializableState(state);
|
|
180589
|
+
getIslandStoreSnapshot()[storeId] = nextSnapshot;
|
|
180590
|
+
for (const peerStore of getPeerStores(storeInstances, ownerStore)) {
|
|
180591
|
+
peerStore.applyExternalSnapshot(nextSnapshot);
|
|
180592
|
+
}
|
|
180593
|
+
};
|
|
180594
|
+
var createIslandStore = (storeId, initialState, createState) => {
|
|
180595
|
+
const store = createStore(combine(initialState, createState));
|
|
180596
|
+
const stores = getIslandStores();
|
|
180597
|
+
const storeInstances = stores.get(storeId) ?? new Set;
|
|
180598
|
+
const initialSnapshot = getIslandStoreSnapshot()[storeId];
|
|
180599
|
+
applySnapshot(store, initialSnapshot);
|
|
180600
|
+
let isApplyingExternalSnapshot = false;
|
|
180601
|
+
const applyExternalSnapshot = (snapshot) => {
|
|
180602
|
+
isApplyingExternalSnapshot = true;
|
|
180603
|
+
applySnapshot(store, snapshot);
|
|
180604
|
+
};
|
|
180605
|
+
storeInstances.add({
|
|
180606
|
+
applyExternalSnapshot,
|
|
180607
|
+
store
|
|
180608
|
+
});
|
|
180609
|
+
stores.set(storeId, storeInstances);
|
|
180610
|
+
syncIslandSnapshot(storeId, store.getState(), storeInstances, store);
|
|
180611
|
+
store.subscribe((state) => {
|
|
180612
|
+
if (isApplyingExternalSnapshot) {
|
|
180613
|
+
isApplyingExternalSnapshot = false;
|
|
180614
|
+
return;
|
|
180615
|
+
}
|
|
180616
|
+
syncIslandSnapshot(storeId, state, storeInstances, store);
|
|
180617
|
+
});
|
|
180618
|
+
return store;
|
|
180619
|
+
};
|
|
180620
|
+
var getIslandStoreServerSnapshot = (store, selector) => selector(store.getInitialState());
|
|
180621
|
+
var applySnapshotToStoreInstances = (storeId, instances, snapshot) => {
|
|
180622
|
+
for (const instance of instances) {
|
|
180623
|
+
instance.applyExternalSnapshot(snapshot[storeId] ?? {});
|
|
180624
|
+
}
|
|
180625
|
+
};
|
|
180626
|
+
var initializeIslandStores = (state) => {
|
|
180627
|
+
const currentSnapshot = getIslandStoreSnapshot();
|
|
180628
|
+
const nextSnapshot = {
|
|
180629
|
+
...state,
|
|
180630
|
+
...currentSnapshot
|
|
180631
|
+
};
|
|
180632
|
+
globalThis.__ABS_ISLAND_STATE__ = nextSnapshot;
|
|
180633
|
+
for (const [storeId, store] of getIslandStores()) {
|
|
180634
|
+
applySnapshotToStoreInstances(storeId, store, nextSnapshot);
|
|
180635
|
+
}
|
|
180636
|
+
};
|
|
180637
|
+
var readIslandStore = (store, selector) => selector(store.getState());
|
|
180638
|
+
var subscribeIslandStore = (store, selector, listener) => {
|
|
180639
|
+
let currentSelection = selector(store.getState());
|
|
180640
|
+
return store.subscribe((state) => {
|
|
180641
|
+
const nextSelection = selector(state);
|
|
180642
|
+
if (Object.is(nextSelection, currentSelection)) {
|
|
180643
|
+
return;
|
|
180644
|
+
}
|
|
180645
|
+
currentSelection = nextSelection;
|
|
180646
|
+
listener(nextSelection);
|
|
180647
|
+
});
|
|
180648
|
+
};
|
|
180649
|
+
|
|
180650
|
+
// src/react/hooks/useIslandStore.ts
|
|
180651
|
+
var useIslandStore = (store, selector) => useSyncExternalStore((listener) => subscribeIslandStore(store, selector, () => {
|
|
180652
|
+
listener();
|
|
180653
|
+
}), () => readIslandStore(store, selector), () => getIslandStoreServerSnapshot(store, selector));
|
|
180654
|
+
|
|
180655
|
+
// src/react/index.ts
|
|
180656
|
+
var handleReactPageRequest2 = wrapPageHandlerWithStreamingSlots(handleReactPageRequest);
|
|
180466
180657
|
// types/client.ts
|
|
180467
180658
|
var hmrState = {
|
|
180468
180659
|
isConnected: false,
|
|
@@ -180764,12 +180955,7 @@ var prepare = async (configOrPath) => {
|
|
|
180764
180955
|
};
|
|
180765
180956
|
|
|
180766
180957
|
// src/core/index.ts
|
|
180767
|
-
init_responseEnhancers();
|
|
180768
180958
|
init_renderIslandMarkup();
|
|
180769
|
-
|
|
180770
|
-
// src/core/wrapPageHandlerWithStreamingSlots.ts
|
|
180771
|
-
init_responseEnhancers();
|
|
180772
|
-
var wrapPageHandlerWithStreamingSlots = (handler) => (...args) => withRegisteredStreamingSlots(() => handler(...args));
|
|
180773
180959
|
// src/plugins/networking.ts
|
|
180774
180960
|
init_constants();
|
|
180775
180961
|
import { argv } from "process";
|
|
@@ -187126,9 +187312,6 @@ var createStreamingSlotMetricSink = ({
|
|
|
187126
187312
|
});
|
|
187127
187313
|
};
|
|
187128
187314
|
};
|
|
187129
|
-
|
|
187130
|
-
// src/utils/index.ts
|
|
187131
|
-
init_streamingSlots();
|
|
187132
187315
|
export {
|
|
187133
187316
|
wrapPageHandlerWithStreamingSlots,
|
|
187134
187317
|
withStreamingSlots,
|
|
@@ -187156,6 +187339,7 @@ export {
|
|
|
187156
187339
|
injectStreamingRuntimeIntoStream,
|
|
187157
187340
|
injectHtmlIntoHead,
|
|
187158
187341
|
hmrState,
|
|
187342
|
+
handleReactPageRequest2 as handleReactPageRequest,
|
|
187159
187343
|
handleHTMXPageRequest,
|
|
187160
187344
|
handleHTMLPageRequest,
|
|
187161
187345
|
getStreamingSlotsRuntimeScript,
|
|
@@ -187232,5 +187416,5 @@ export {
|
|
|
187232
187416
|
ANGULAR_INIT_TIMEOUT_MS
|
|
187233
187417
|
};
|
|
187234
187418
|
|
|
187235
|
-
//# debugId=
|
|
187419
|
+
//# debugId=FC4D790AFD386F0D64756E2164756E21
|
|
187236
187420
|
//# sourceMappingURL=index.js.map
|