@absolutejs/absolute 0.19.0-beta.367 → 0.19.0-beta.369

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/index.js CHANGED
@@ -78,81 +78,468 @@ 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
- // types/typeGuards.ts
82
- var isValidAIClientMessage = (data) => {
83
- if (!data || typeof data !== "object") {
84
- return false;
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
- if (!("type" in data) || typeof data.type !== "string") {
87
- return false;
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
- switch (data.type) {
90
- case "message":
91
- return "content" in data && typeof data.content === "string";
92
- case "cancel":
93
- return "conversationId" in data && typeof data.conversationId === "string";
94
- case "branch":
95
- return "messageId" in data && typeof data.messageId === "string" && "content" in data && typeof data.content === "string" && "conversationId" in data && typeof data.conversationId === "string";
96
- default:
97
- return false;
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
- }, isValidAIServerMessage = (data) => {
100
- if (!data || typeof data !== "object") {
101
- return false;
220
+ if (html.includes(MANIFEST_MARKER) || html.includes(ISLAND_STATE_MARKER)) {
221
+ return html;
102
222
  }
103
- if (!("type" in data) || typeof data.type !== "string") {
104
- return false;
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
- switch (data.type) {
107
- case "chunk":
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
- }, isValidHMRClientMessage = (data) => {
125
- if (!data || typeof data !== "object") {
126
- return false;
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")}</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
- if (!("type" in data) || typeof data.type !== "string") {
129
- return false;
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(/&quot;/g, '"').replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/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
- switch (data.type) {
132
- case "ping":
133
- return true;
134
- case "ready":
135
- return true;
136
- case "request-rebuild":
137
- return true;
138
- case "hydration-error":
139
- return true;
140
- case "hmr-timing":
141
- return true;
142
- default:
143
- return false;
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);
144
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);
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
- // types/websocket.ts
148
- var WS_READY_STATE_OPEN = 1;
149
-
150
- // src/constants.ts
151
- 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;
152
- var init_constants = __esm(() => {
153
- MILLISECONDS_IN_A_MINUTE = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE;
154
- MILLISECONDS_IN_A_DAY = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE * MINUTES_IN_AN_HOUR * HOURS_IN_DAY;
155
- TWO_THIRDS = 2 / 3;
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
+ if ("allReady" in stream && stream.allReady instanceof Promise) {
521
+ await stream.allReady;
522
+ }
523
+ const htmlStream = injectIslandPageContextStream(stream);
524
+ return new Response(htmlStream, {
525
+ headers: { "Content-Type": "text/html" }
526
+ });
527
+ } catch (error) {
528
+ console.error("[SSR] React render error:", error);
529
+ const pageName = PageComponent.name || PageComponent.displayName || "";
530
+ const conventionResponse = await renderConventionError("react", pageName, error);
531
+ if (conventionResponse)
532
+ return conventionResponse;
533
+ return new Response(ssrErrorPage("react", error), {
534
+ headers: { "Content-Type": "text/html" },
535
+ status: 500
536
+ });
537
+ }
538
+ }, invalidateReactSsrCache = () => {
539
+ ssrDirty = true;
540
+ };
541
+ var init_pageHandler = __esm(() => {
542
+ init_resolveConvention();
156
543
  });
157
544
 
158
545
  // src/core/islandManifest.ts
@@ -206,6 +593,30 @@ var defineIslandComponent = (component, options) => ({
206
593
  }, serializeIslandProps = (props) => JSON.stringify(props ?? {});
207
594
  var init_islands = () => {};
208
595
 
596
+ // src/core/islandMarkupAttributes.ts
597
+ var getIslandMarkerAttributes = (props, islandId) => ({
598
+ "data-component": props.component,
599
+ "data-framework": props.framework,
600
+ "data-hydrate": props.hydrate ?? "load",
601
+ "data-island": "true",
602
+ ...islandId ? { "data-island-id": islandId } : {},
603
+ "data-props": serializeIslandProps(props.props)
604
+ }), escapeHtmlAttribute = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"), serializeIslandAttributes = (attributes) => Object.entries(attributes).map(([key, value]) => `${key}="${escapeHtmlAttribute(value)}"`).join(" ");
605
+ var init_islandMarkupAttributes = __esm(() => {
606
+ init_islands();
607
+ });
608
+
609
+ // src/core/currentIslandRegistry.ts
610
+ var requireCurrentIslandRegistry = () => {
611
+ const registry = globalThis.__absoluteIslandRegistry;
612
+ if (!registry) {
613
+ throw new Error("No island registry is active. Configure `islands.registry` in absolute.config.ts before rendering <Island />.");
614
+ }
615
+ return registry;
616
+ }, setCurrentIslandRegistry = (registry) => {
617
+ globalThis.__absoluteIslandRegistry = registry;
618
+ };
619
+
209
620
  // src/angular/injectorPatch.ts
210
621
  import { existsSync, readFileSync, writeFileSync } from "fs";
211
622
  import { dirname, join, resolve } from "path";
@@ -360,14 +771,6 @@ var init_angularDeps = __esm(() => {
360
771
  init_resolveAngularPackage();
361
772
  });
362
773
 
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
774
  // src/utils/registerClientScript.ts
372
775
  var scriptRegistry, requestCounter = 0, getRequestId = () => `req_${Date.now()}_${++requestCounter}`, ssrContextGetter = null, getSsrContextId = () => ssrContextGetter?.() || Object.getOwnPropertyDescriptor(globalThis, "__absolutejs_requestId")?.value, registerClientScript = (script, requestId) => {
373
776
  const id = requestId || getSsrContextId() || getRequestId();
@@ -741,6 +1144,14 @@ var init_islandSsr = __esm(() => {
741
1144
  init_islands2();
742
1145
  });
743
1146
 
1147
+ // src/constants.ts
1148
+ 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;
1149
+ var init_constants = __esm(() => {
1150
+ MILLISECONDS_IN_A_MINUTE = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE;
1151
+ MILLISECONDS_IN_A_DAY = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE * MINUTES_IN_AN_HOUR * HOURS_IN_DAY;
1152
+ TWO_THIRDS = 2 / 3;
1153
+ });
1154
+
744
1155
  // src/svelte/lowerIslandSyntax.ts
745
1156
  var ISLAND_TAG_RE, extractBracedExpression = (text, braceStart) => {
746
1157
  let depth = 0;
@@ -815,7 +1226,7 @@ var init_lowerIslandSyntax = __esm(() => {
815
1226
 
816
1227
  // src/core/svelteServerModule.ts
817
1228
  import { mkdir, readdir } from "fs/promises";
818
- import { basename, dirname as dirname2, extname, join as join2, relative, resolve as resolve3 } from "path";
1229
+ import { basename as basename2, dirname as dirname2, extname, join as join2, relative, resolve as resolve3 } from "path";
819
1230
  var serverCacheRoot, compiledModuleCache, originalSourcePathCache, transpiler, ensureRelativeImportPath = (from, target) => {
820
1231
  const importPath = relative(dirname2(from), target).replace(/\\/g, "/");
821
1232
  return importPath.startsWith(".") ? importPath : `./${importPath}`;
@@ -846,7 +1257,7 @@ var serverCacheRoot, compiledModuleCache, originalSourcePathCache, transpiler, e
846
1257
  return found;
847
1258
  }
848
1259
  return searchDirectoryLevel(nextStack, targetFileName);
849
- }, findSourceFileByBasename = async (searchRoot, targetFileName) => searchDirectoryLevel([searchRoot], targetFileName), normalizeBuiltSvelteFileName = (sourcePath) => basename(sourcePath).replace(/-[a-z0-9]{6,}(?=\.svelte$)/i, ""), resolveOriginalSourcePath = async (sourcePath) => {
1260
+ }, findSourceFileByBasename = async (searchRoot, targetFileName) => searchDirectoryLevel([searchRoot], targetFileName), normalizeBuiltSvelteFileName = (sourcePath) => basename2(sourcePath).replace(/-[a-z0-9]{6,}(?=\.svelte$)/i, ""), resolveOriginalSourcePath = async (sourcePath) => {
850
1261
  const cachedPath = originalSourcePathCache.get(sourcePath);
851
1262
  if (cachedPath !== undefined) {
852
1263
  return cachedPath;
@@ -982,19 +1393,6 @@ var init_svelteServerModule = __esm(() => {
982
1393
  });
983
1394
  });
984
1395
 
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("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"), serializeIslandAttributes = (attributes) => Object.entries(attributes).map(([key, value]) => `${key}="${escapeHtmlAttribute(value)}"`).join(" ");
994
- var init_islandMarkupAttributes = __esm(() => {
995
- init_islands();
996
- });
997
-
998
1396
  // src/core/renderIslandMarkup.ts
999
1397
  var islandSequence = 0, resolvedServerComponentCache, resolvedServerBuildComponentCache, nextIslandId = () => {
1000
1398
  islandSequence += 1;
@@ -1123,6 +1521,75 @@ var init_renderIslandMarkup = __esm(() => {
1123
1521
  resolvedServerBuildComponentCache = new Map;
1124
1522
  });
1125
1523
 
1524
+ // types/typeGuards.ts
1525
+ var isValidAIClientMessage = (data) => {
1526
+ if (!data || typeof data !== "object") {
1527
+ return false;
1528
+ }
1529
+ if (!("type" in data) || typeof data.type !== "string") {
1530
+ return false;
1531
+ }
1532
+ switch (data.type) {
1533
+ case "message":
1534
+ return "content" in data && typeof data.content === "string";
1535
+ case "cancel":
1536
+ return "conversationId" in data && typeof data.conversationId === "string";
1537
+ case "branch":
1538
+ return "messageId" in data && typeof data.messageId === "string" && "content" in data && typeof data.content === "string" && "conversationId" in data && typeof data.conversationId === "string";
1539
+ default:
1540
+ return false;
1541
+ }
1542
+ }, isValidAIServerMessage = (data) => {
1543
+ if (!data || typeof data !== "object") {
1544
+ return false;
1545
+ }
1546
+ if (!("type" in data) || typeof data.type !== "string") {
1547
+ return false;
1548
+ }
1549
+ switch (data.type) {
1550
+ case "chunk":
1551
+ return "content" in data && typeof data.content === "string" && "messageId" in data && "conversationId" in data;
1552
+ case "thinking":
1553
+ return "content" in data && typeof data.content === "string" && "messageId" in data && "conversationId" in data;
1554
+ case "tool_status":
1555
+ return "name" in data && "status" in data && "messageId" in data && "conversationId" in data;
1556
+ case "image":
1557
+ 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;
1558
+ case "complete":
1559
+ return "messageId" in data && "conversationId" in data;
1560
+ case "rag_retrieved":
1561
+ return "conversationId" in data && "messageId" in data && "sources" in data && Array.isArray(data.sources);
1562
+ case "error":
1563
+ return "message" in data && typeof data.message === "string";
1564
+ default:
1565
+ return false;
1566
+ }
1567
+ }, isValidHMRClientMessage = (data) => {
1568
+ if (!data || typeof data !== "object") {
1569
+ return false;
1570
+ }
1571
+ if (!("type" in data) || typeof data.type !== "string") {
1572
+ return false;
1573
+ }
1574
+ switch (data.type) {
1575
+ case "ping":
1576
+ return true;
1577
+ case "ready":
1578
+ return true;
1579
+ case "request-rebuild":
1580
+ return true;
1581
+ case "hydration-error":
1582
+ return true;
1583
+ case "hmr-timing":
1584
+ return true;
1585
+ default:
1586
+ return false;
1587
+ }
1588
+ };
1589
+
1590
+ // types/websocket.ts
1591
+ var WS_READY_STATE_OPEN = 1;
1592
+
1126
1593
  // node_modules/typescript/lib/typescript.js
1127
1594
  var require_typescript = __commonJS((exports, module) => {
1128
1595
  var __dirname = "/home/alexkahn/abs/absolutejs/node_modules/typescript/lib", __filename = "/home/alexkahn/abs/absolutejs/node_modules/typescript/lib/typescript.js";
@@ -1416,7 +1883,7 @@ var require_typescript = __commonJS((exports, module) => {
1416
1883
  codefix: () => ts_codefix_exports,
1417
1884
  collapseTextChangeRangesAcrossMultipleVersions: () => collapseTextChangeRangesAcrossMultipleVersions,
1418
1885
  collectExternalModuleInfo: () => collectExternalModuleInfo,
1419
- combine: () => combine,
1886
+ combine: () => combine2,
1420
1887
  combinePaths: () => combinePaths,
1421
1888
  commandLineOptionOfCustomType: () => commandLineOptionOfCustomType,
1422
1889
  commentPragmas: () => commentPragmas,
@@ -3991,7 +4458,7 @@ var require_typescript = __commonJS((exports, module) => {
3991
4458
  to.push(value);
3992
4459
  return to;
3993
4460
  }
3994
- function combine(xs, ys) {
4461
+ function combine2(xs, ys) {
3995
4462
  if (xs === undefined)
3996
4463
  return ys;
3997
4464
  if (ys === undefined)
@@ -109092,10 +109559,10 @@ ${lanes.join(`
109092
109559
  }
109093
109560
  function getDefaultLibFilePriority(a) {
109094
109561
  if (containsPath(defaultLibraryPath, a.fileName, false)) {
109095
- const basename2 = getBaseFileName(a.fileName);
109096
- if (basename2 === "lib.d.ts" || basename2 === "lib.es6.d.ts")
109562
+ const basename3 = getBaseFileName(a.fileName);
109563
+ if (basename3 === "lib.d.ts" || basename3 === "lib.es6.d.ts")
109097
109564
  return 0;
109098
- const name = removeSuffix(removePrefix(basename2, "lib."), ".d.ts");
109565
+ const name = removeSuffix(removePrefix(basename3, "lib."), ".d.ts");
109099
109566
  const index = libs.indexOf(name);
109100
109567
  if (index !== -1)
109101
109568
  return index + 1;
@@ -136199,9 +136666,9 @@ ${newComment.split(`
136199
136666
  const moduleSpecifier = key.slice(2);
136200
136667
  const getDeclarations = useRequire ? getNewRequires : getNewImports;
136201
136668
  const declarations = getDeclarations(moduleSpecifier, quotePreference, defaultImport, namedImports && arrayFrom(namedImports.entries(), ([name, [addAsTypeOnly, propertyName]]) => ({ addAsTypeOnly, propertyName, name })), namespaceLikeImport, compilerOptions, preferences);
136202
- newDeclarations = combine(newDeclarations, declarations);
136669
+ newDeclarations = combine2(newDeclarations, declarations);
136203
136670
  });
136204
- newDeclarations = combine(newDeclarations, getCombinedVerbatimImports());
136671
+ newDeclarations = combine2(newDeclarations, getCombinedVerbatimImports());
136205
136672
  if (newDeclarations) {
136206
136673
  insertImports(changeTracker, sourceFile, newDeclarations, true, preferences);
136207
136674
  }
@@ -136951,11 +137418,11 @@ ${newComment.split(`
136951
137418
  let statements;
136952
137419
  if (defaultImport !== undefined || (namedImports == null ? undefined : namedImports.length)) {
136953
137420
  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 = combine(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));
137421
+ 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
137422
  }
136956
137423
  if (namespaceLikeImport) {
136957
137424
  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 = combine(statements, declaration);
137425
+ statements = combine2(statements, declaration);
136959
137426
  }
136960
137427
  return Debug.checkDefined(statements);
136961
137428
  }
@@ -136968,11 +137435,11 @@ ${newComment.split(`
136968
137435
  bindingElements.unshift(factory.createBindingElement(undefined, "default", defaultImport.name));
136969
137436
  }
136970
137437
  const declaration = createConstEqualsRequireDeclaration(factory.createObjectBindingPattern(bindingElements), quotedModuleSpecifier);
136971
- statements = combine(statements, declaration);
137438
+ statements = combine2(statements, declaration);
136972
137439
  }
136973
137440
  if (namespaceLikeImport) {
136974
137441
  const declaration = createConstEqualsRequireDeclaration(namespaceLikeImport.name, quotedModuleSpecifier);
136975
- statements = combine(statements, declaration);
137442
+ statements = combine2(statements, declaration);
136976
137443
  }
136977
137444
  return Debug.checkDefined(statements);
136978
137445
  }
@@ -141424,7 +141891,7 @@ ${newComment.split(`
141424
141891
  function createModifiers() {
141425
141892
  let modifiers2;
141426
141893
  if (modifierFlags) {
141427
- modifiers2 = combine(modifiers2, factory.createModifiersFromModifierFlags(modifierFlags));
141894
+ modifiers2 = combine2(modifiers2, factory.createModifiersFromModifierFlags(modifierFlags));
141428
141895
  }
141429
141896
  if (shouldAddOverrideKeyword()) {
141430
141897
  modifiers2 = append(modifiers2, factory.createToken(164));
@@ -157416,7 +157883,7 @@ ${options.prefix}` : `
157416
157883
  codefix: () => ts_codefix_exports,
157417
157884
  collapseTextChangeRangesAcrossMultipleVersions: () => collapseTextChangeRangesAcrossMultipleVersions,
157418
157885
  collectExternalModuleInfo: () => collectExternalModuleInfo,
157419
- combine: () => combine,
157886
+ combine: () => combine2,
157420
157887
  combinePaths: () => combinePaths,
157421
157888
  commandLineOptionOfCustomType: () => commandLineOptionOfCustomType,
157422
157889
  commentPragmas: () => commentPragmas,
@@ -161658,8 +162125,8 @@ ${options.prefix}` : `
161658
162125
  }
161659
162126
  };
161660
162127
  for (const file of files) {
161661
- const basename2 = getBaseFileName(file);
161662
- if (basename2 === "package.json" || basename2 === "bower.json") {
162128
+ const basename3 = getBaseFileName(file);
162129
+ if (basename3 === "package.json" || basename3 === "bower.json") {
161663
162130
  createProjectWatcher(file, "FileWatcher");
161664
162131
  continue;
161665
162132
  }
@@ -164536,8 +165003,8 @@ All files are: ${JSON.stringify(names)}`, "Err");
164536
165003
  const fileOrDirectoryPath = removeIgnoredPath(this.toPath(fileOrDirectory));
164537
165004
  if (!fileOrDirectoryPath)
164538
165005
  return;
164539
- const basename2 = getBaseFileName(fileOrDirectoryPath);
164540
- if (((_a = result.affectedModuleSpecifierCacheProjects) == null ? undefined : _a.size) && (basename2 === "package.json" || basename2 === "node_modules")) {
165006
+ const basename3 = getBaseFileName(fileOrDirectoryPath);
165007
+ if (((_a = result.affectedModuleSpecifierCacheProjects) == null ? undefined : _a.size) && (basename3 === "package.json" || basename3 === "node_modules")) {
164541
165008
  result.affectedModuleSpecifierCacheProjects.forEach((project) => {
164542
165009
  var _a2;
164543
165010
  (_a2 = project.getModuleSpecifierCache()) == null || _a2.clear();
@@ -170061,17 +170528,6 @@ var init_islandEntries = __esm(() => {
170061
170528
  ];
170062
170529
  });
170063
170530
 
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
170531
  // src/build/staticIslandPages.ts
170076
170532
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
170077
170533
  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,1014 +170618,6 @@ var init_staticIslandPages = __esm(() => {
170162
170618
  islandHydrationModes = ["load", "idle", "visible", "none"];
170163
170619
  });
170164
170620
 
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
- // src/client/streamSwap.ts
170309
- var streamSwapRuntime = () => {
170310
- if (window.__ABS_SLOT_RUNTIME__ === true)
170311
- return;
170312
- window.__ABS_SLOT_RUNTIME__ = true;
170313
- window.__ABS_SLOT_PENDING__ = window.__ABS_SLOT_PENDING__ ?? {};
170314
- const pending = window.__ABS_SLOT_PENDING__;
170315
- const apply = (id, html) => {
170316
- const node = document.getElementById(`slot-${id}`);
170317
- if (!node) {
170318
- pending[id] = html;
170319
- return;
170320
- }
170321
- node.innerHTML = html;
170322
- delete pending[id];
170323
- };
170324
- const flush = () => {
170325
- for (const id in pending) {
170326
- if (!Object.prototype.hasOwnProperty.call(pending, id))
170327
- continue;
170328
- apply(id, pending[id] ?? "");
170329
- }
170330
- };
170331
- window.__ABS_SLOT_ENQUEUE__ = (id, html) => {
170332
- apply(id, html);
170333
- };
170334
- if (typeof MutationObserver === "function") {
170335
- const observer = new MutationObserver(flush);
170336
- const root = document.documentElement ?? document.body ?? document;
170337
- observer.observe(root, { childList: true, subtree: true });
170338
- }
170339
- if (document.readyState === "loading") {
170340
- document.addEventListener("DOMContentLoaded", flush, { once: true });
170341
- }
170342
- flush();
170343
- }, stripFunctionWrapper = (value) => {
170344
- const start = value.indexOf("{");
170345
- const end = value.lastIndexOf("}");
170346
- if (start < 0 || end <= start)
170347
- return "";
170348
- return value.slice(start + 1, end);
170349
- }, getStreamSwapRuntimeScript = () => `(function(){${stripFunctionWrapper(streamSwapRuntime.toString())}})();`;
170350
-
170351
- // src/utils/escapeScriptContent.ts
170352
- var ESCAPE_LOOKUP, ESCAPE_REGEX, escapeScriptContent = (content) => content.replace(ESCAPE_REGEX, (char) => {
170353
- const escaped = ESCAPE_LOOKUP[char];
170354
- return escaped !== undefined ? escaped : char;
170355
- });
170356
- var init_escapeScriptContent = __esm(() => {
170357
- ESCAPE_LOOKUP = {
170358
- "\u2028": "\\u2028",
170359
- "\u2029": "\\u2029",
170360
- "&": "\\u0026",
170361
- "<": "\\u003C",
170362
- ">": "\\u003E"
170363
- };
170364
- ESCAPE_REGEX = /[&><\u2028\u2029]/g;
170365
- });
170366
-
170367
- // src/utils/streamingSlots.ts
170368
- 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) => {
170369
- const closingHeadIndex = html.indexOf(CLOSING_HEAD_TAG2);
170370
- if (closingHeadIndex >= 0) {
170371
- return `${html.slice(0, closingHeadIndex)}${injection}${html.slice(closingHeadIndex)}`;
170372
- }
170373
- return `${html}${injection}`;
170374
- }, toUint8 = (value, encoder) => encoder.encode(value), currentStreamingSlotPolicy, clonePolicy = (policy) => ({
170375
- ...policy
170376
- }), normalizeSlotBytes = (value, fallback) => {
170377
- if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
170378
- return Math.floor(value);
170379
- }
170380
- return fallback;
170381
- }, 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 = {}) => ({
170382
- timeoutMs: hasPolicyValue(overridePolicy, "timeoutMs") ? normalizeSlotBytes(overridePolicy.timeoutMs, base.timeoutMs) : base.timeoutMs,
170383
- fallbackHtml: hasPolicyValue(overridePolicy, "fallbackHtml") ? normalizeSlotText(overridePolicy.fallbackHtml, "") : base.fallbackHtml,
170384
- errorHtml: hasPolicyValue(overridePolicy, "errorHtml") ? normalizeSlotError(overridePolicy.errorHtml) : base.errorHtml,
170385
- maxSlotsPerResponse: hasPolicyValue(overridePolicy, "maxSlotsPerResponse") ? normalizeSlotBytes(overridePolicy.maxSlotsPerResponse, base.maxSlotsPerResponse) : base.maxSlotsPerResponse,
170386
- maxSlotHtmlSizeBytes: hasPolicyValue(overridePolicy, "maxSlotHtmlSizeBytes") ? normalizeSlotBytes(overridePolicy.maxSlotHtmlSizeBytes, base.maxSlotHtmlSizeBytes) : base.maxSlotHtmlSizeBytes,
170387
- onError: hasPolicyValue(overridePolicy, "onError") ? overridePolicy.onError : base.onError,
170388
- onSlotMetric: hasPolicyValue(overridePolicy, "onSlotMetric") ? overridePolicy.onSlotMetric : base.onSlotMetric
170389
- }), createCombinedSlotErrorHandler = (policyOnError, enhancerOnError) => {
170390
- if (!policyOnError && !enhancerOnError)
170391
- return;
170392
- return (error, slot) => {
170393
- policyOnError?.(error, slot);
170394
- enhancerOnError?.(error, slot);
170395
- };
170396
- }, createCombinedSlotMetricHandler = (policyOnSlotMetric, callOnSlotMetric) => {
170397
- if (!policyOnSlotMetric && !callOnSlotMetric)
170398
- return;
170399
- return (metric) => {
170400
- policyOnSlotMetric?.(metric);
170401
- callOnSlotMetric?.(metric);
170402
- };
170403
- }, resolveStreamingSlotPolicy = (overridePolicy = {}) => {
170404
- const base = getStreamingSlotPolicy();
170405
- return applyStreamingSlotPolicyOverrides(base, overridePolicy);
170406
- }, getStreamingSlotPolicy = () => clonePolicy(currentStreamingSlotPolicy), setStreamingSlotPolicy = (policy = {}) => {
170407
- const base = getStreamingSlotPolicy();
170408
- currentStreamingSlotPolicy = applyStreamingSlotPolicyOverrides(base, policy);
170409
- }, withStreamingSlotPolicy = async (policy, callback) => {
170410
- const previous = getStreamingSlotPolicy();
170411
- setStreamingSlotPolicy(policy);
170412
- try {
170413
- return await callback();
170414
- } finally {
170415
- currentStreamingSlotPolicy = previous;
170416
- }
170417
- }, emitSlotMetric = (metric, onSlotMetric) => {
170418
- onSlotMetric?.(metric);
170419
- }, createTimeoutError = (slot, timeoutMs) => {
170420
- const error = new Error(`Streaming slot "${slot.id}" timed out after ${timeoutMs}ms`);
170421
- error.__absTimeout = true;
170422
- return error;
170423
- }, toStreamingSlot = (slot, policy) => ({
170424
- errorHtml: slot.errorHtml === undefined ? policy.errorHtml : slot.errorHtml,
170425
- fallbackHtml: normalizeSlotText(slot.fallbackHtml, policy.fallbackHtml),
170426
- id: slot.id ?? createStreamingSlotId(),
170427
- timeoutMs: normalizeSlotBytes(slot.timeoutMs, policy.timeoutMs),
170428
- resolve: slot.resolve
170429
- }), prepareSlots = ({
170430
- policy,
170431
- slots,
170432
- onError,
170433
- onSlotMetric
170434
- }) => {
170435
- const preparedSlots = slots.map((slot) => toStreamingSlot(slot, policy));
170436
- const maxSlotsPerResponse = policy.maxSlotsPerResponse;
170437
- if (maxSlotsPerResponse === 0) {
170438
- const error = new Error("Streaming slot limit is set to 0");
170439
- for (const slot of preparedSlots) {
170440
- onError?.(error, slot);
170441
- emitSlotMetric({
170442
- type: "dropped",
170443
- slotId: slot.id,
170444
- reason: "maxSlotsPerResponse is 0"
170445
- }, onSlotMetric);
170446
- }
170447
- return [];
170448
- }
170449
- if (preparedSlots.length <= maxSlotsPerResponse) {
170450
- preparedSlots.forEach((slot) => emitSlotMetric({
170451
- type: "prepared",
170452
- slotId: slot.id
170453
- }, onSlotMetric));
170454
- return preparedSlots;
170455
- }
170456
- const keptSlots = preparedSlots.slice(0, maxSlotsPerResponse);
170457
- const droppedSlots = preparedSlots.slice(maxSlotsPerResponse);
170458
- droppedSlots.forEach((slot) => {
170459
- onError?.(new Error(`Streaming slot "${slot.id}" dropped because ${maxSlotsPerResponse} slots is the configured maximum`), slot);
170460
- emitSlotMetric({
170461
- type: "dropped",
170462
- slotId: slot.id,
170463
- reason: `maxSlotsPerResponse is ${maxSlotsPerResponse}`
170464
- }, onSlotMetric);
170465
- });
170466
- keptSlots.forEach((slot) => emitSlotMetric({
170467
- type: "prepared",
170468
- slotId: slot.id
170469
- }, onSlotMetric));
170470
- return keptSlots;
170471
- }, htmlByteLength = (value, encoder) => encoder.encode(value).length, resolveSlot = async (slot, onError, policy, onSlotMetric) => {
170472
- const safePolicy = policy ?? getStreamingSlotPolicy();
170473
- const encoder = new TextEncoder;
170474
- const start = Date.now();
170475
- try {
170476
- const maybeAsyncValue = Promise.resolve(slot.resolve());
170477
- const resolved = typeof slot.timeoutMs === "number" && slot.timeoutMs > 0 ? await Promise.race([
170478
- maybeAsyncValue,
170479
- new Promise((_, reject) => setTimeout(() => {
170480
- reject(createTimeoutError(slot, slot.timeoutMs ?? 0));
170481
- }, slot.timeoutMs))
170482
- ]) : await maybeAsyncValue;
170483
- const html = typeof resolved === "string" ? resolved : `${resolved}`;
170484
- if (safePolicy.maxSlotHtmlSizeBytes > 0 && htmlByteLength(html, encoder) > safePolicy.maxSlotHtmlSizeBytes) {
170485
- const bytes2 = htmlByteLength(html, encoder);
170486
- const error = new Error(`Streaming slot "${slot.id}" exceeded max payload size of ${safePolicy.maxSlotHtmlSizeBytes} bytes`);
170487
- const durationMs2 = Date.now() - start;
170488
- onError?.(error, slot);
170489
- emitSlotMetric({
170490
- type: "size_exceeded",
170491
- slotId: slot.id,
170492
- durationMs: durationMs2,
170493
- bytes: bytes2,
170494
- error
170495
- }, onSlotMetric);
170496
- const fallbackHtml = typeof slot.errorHtml === "string" ? slot.errorHtml : null;
170497
- return {
170498
- html: fallbackHtml,
170499
- id: slot.id,
170500
- durationMs: durationMs2,
170501
- bytes: fallbackHtml === null ? 0 : htmlByteLength(fallbackHtml, encoder)
170502
- };
170503
- }
170504
- const durationMs = Date.now() - start;
170505
- const bytes = htmlByteLength(html, encoder);
170506
- emitSlotMetric({
170507
- type: "resolved",
170508
- slotId: slot.id,
170509
- durationMs,
170510
- bytes
170511
- }, onSlotMetric);
170512
- return {
170513
- html,
170514
- id: slot.id,
170515
- durationMs,
170516
- bytes
170517
- };
170518
- } catch (error) {
170519
- const durationMs = Date.now() - start;
170520
- onError?.(error, slot);
170521
- emitSlotMetric({
170522
- type: error?.__absTimeout === true ? "timeout" : "error",
170523
- slotId: slot.id,
170524
- durationMs,
170525
- error
170526
- }, onSlotMetric);
170527
- if (typeof slot.errorHtml === "string") {
170528
- const html = slot.errorHtml;
170529
- return {
170530
- html,
170531
- id: slot.id,
170532
- durationMs,
170533
- bytes: htmlByteLength(html, encoder)
170534
- };
170535
- }
170536
- return {
170537
- html: null,
170538
- id: slot.id,
170539
- durationMs,
170540
- bytes: 0
170541
- };
170542
- }
170543
- }, nextResolvedSlot = async (pending) => {
170544
- const wrapped = pending.map((promise) => promise.then((result) => ({
170545
- original: promise,
170546
- result
170547
- })));
170548
- return Promise.race(wrapped);
170549
- }, streamChunkToString2 = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true }), streamOutOfOrderSlots = ({
170550
- footerHtml = "",
170551
- headerHtml = "",
170552
- nonce,
170553
- policy,
170554
- onSlotMetric,
170555
- onError,
170556
- slots
170557
- }) => {
170558
- const resolvedPolicy = resolveStreamingSlotPolicy(policy);
170559
- const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
170560
- const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
170561
- const effectivePolicy = {
170562
- ...resolvedPolicy,
170563
- onSlotMetric: combinedOnSlotMetric
170564
- };
170565
- const preparedSlots = prepareSlots({
170566
- policy: effectivePolicy,
170567
- slots,
170568
- onError: combinedOnError,
170569
- onSlotMetric: combinedOnSlotMetric
170570
- });
170571
- const encoder = new TextEncoder;
170572
- return new ReadableStream({
170573
- async start(controller) {
170574
- try {
170575
- let header = headerHtml;
170576
- if (preparedSlots.length > 0 && !header.includes(STREAMING_RUNTIME_GLOBAL)) {
170577
- header = injectHtmlIntoHead(header, renderStreamingSlotsRuntimeTag(nonce));
170578
- }
170579
- controller.enqueue(toUint8(header, encoder));
170580
- const pending = preparedSlots.map((slot) => {
170581
- const fallback = renderStreamingSlotPlaceholder(slot.id, slot.fallbackHtml ?? "");
170582
- controller.enqueue(toUint8(fallback, encoder));
170583
- return resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric);
170584
- });
170585
- while (pending.length > 0) {
170586
- const { original, result } = await nextResolvedSlot(pending);
170587
- const index = pending.indexOf(original);
170588
- if (index >= 0)
170589
- pending.splice(index, 1);
170590
- if (result.html === null)
170591
- continue;
170592
- emitSlotMetric({
170593
- type: "patched",
170594
- slotId: result.id,
170595
- durationMs: result.durationMs,
170596
- bytes: result.bytes
170597
- }, combinedOnSlotMetric);
170598
- controller.enqueue(toUint8(renderStreamingSlotPatchTag(result.id, result.html, nonce), encoder));
170599
- }
170600
- if (footerHtml.length > 0) {
170601
- controller.enqueue(toUint8(footerHtml, encoder));
170602
- }
170603
- controller.close();
170604
- } catch (error) {
170605
- controller.error(error);
170606
- }
170607
- }
170608
- });
170609
- }, injectStreamingRuntimeIntoStream = (stream, nonce) => {
170610
- const runtimeTag = renderStreamingSlotsRuntimeTag(nonce);
170611
- const encoder = new TextEncoder;
170612
- const decoder = new TextDecoder;
170613
- const lookbehind = CLOSING_HEAD_TAG_LENGTH - 1;
170614
- return new ReadableStream({
170615
- async start(controller) {
170616
- const reader = stream.getReader();
170617
- let injected = false;
170618
- let pending = "";
170619
- try {
170620
- for (;; ) {
170621
- const { done, value } = await reader.read();
170622
- if (done)
170623
- break;
170624
- if (!value)
170625
- continue;
170626
- pending += streamChunkToString2(value, decoder);
170627
- if (injected) {
170628
- controller.enqueue(encoder.encode(pending));
170629
- pending = "";
170630
- continue;
170631
- }
170632
- const headIndex = pending.indexOf(CLOSING_HEAD_TAG2);
170633
- if (headIndex >= 0) {
170634
- const withRuntime = `${pending.slice(0, headIndex)}${runtimeTag}${pending.slice(headIndex)}`;
170635
- controller.enqueue(encoder.encode(withRuntime));
170636
- pending = "";
170637
- injected = true;
170638
- continue;
170639
- }
170640
- if (pending.length > lookbehind) {
170641
- const safeText = pending.slice(0, pending.length - lookbehind);
170642
- controller.enqueue(encoder.encode(safeText));
170643
- pending = pending.slice(-lookbehind);
170644
- }
170645
- }
170646
- pending += decoder.decode();
170647
- if (!injected) {
170648
- pending = injectHtmlIntoHead(pending, runtimeTag);
170649
- }
170650
- if (pending.length > 0) {
170651
- controller.enqueue(encoder.encode(pending));
170652
- }
170653
- controller.close();
170654
- } catch (error) {
170655
- controller.error(error);
170656
- }
170657
- }
170658
- });
170659
- }, appendStreamingSlotPatchesToStream = (stream, slots = [], {
170660
- injectRuntime = true,
170661
- nonce,
170662
- onError,
170663
- onSlotMetric,
170664
- policy
170665
- } = {}) => {
170666
- const resolvedPolicy = resolveStreamingSlotPolicy(policy);
170667
- const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
170668
- const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
170669
- const effectivePolicy = {
170670
- ...resolvedPolicy,
170671
- onSlotMetric: combinedOnSlotMetric
170672
- };
170673
- const preparedSlots = prepareSlots({
170674
- policy: effectivePolicy,
170675
- slots,
170676
- onError: combinedOnError,
170677
- onSlotMetric: combinedOnSlotMetric
170678
- });
170679
- if (preparedSlots.length === 0)
170680
- return stream;
170681
- const source = injectRuntime ? injectStreamingRuntimeIntoStream(stream, nonce) : stream;
170682
- const encoder = new TextEncoder;
170683
- const decoder = new TextDecoder;
170684
- const reader = source.getReader();
170685
- const pending = preparedSlots.map((slot) => resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric));
170686
- return new ReadableStream({
170687
- async start(controller) {
170688
- let baseDone = false;
170689
- let baseRead = reader.read();
170690
- let tail = "";
170691
- let footer = "";
170692
- try {
170693
- while (!baseDone || pending.length > 0) {
170694
- const racers = [];
170695
- if (!baseDone) {
170696
- racers.push(baseRead.then(({ done, value }) => ({
170697
- done,
170698
- kind: "base",
170699
- value
170700
- })));
170701
- }
170702
- if (pending.length > 0) {
170703
- racers.push(nextResolvedSlot(pending).then((resolved) => ({
170704
- kind: "slot",
170705
- ...resolved
170706
- })));
170707
- }
170708
- if (racers.length === 0)
170709
- break;
170710
- const winner = await Promise.race(racers);
170711
- if (winner.kind === "base") {
170712
- if (winner.done) {
170713
- baseDone = true;
170714
- tail += decoder.decode();
170715
- const footerStart = tail.search(CLOSING_PAGE_TAG_REGEX);
170716
- if (footerStart >= 0) {
170717
- const content = tail.slice(0, footerStart);
170718
- footer = tail.slice(footerStart);
170719
- if (content.length > 0) {
170720
- controller.enqueue(encoder.encode(content));
170721
- }
170722
- } else if (tail.length > 0) {
170723
- controller.enqueue(encoder.encode(tail));
170724
- }
170725
- tail = "";
170726
- } else if (winner.value) {
170727
- tail += streamChunkToString2(winner.value, decoder);
170728
- if (tail.length > STREAM_TAIL_LOOKBEHIND) {
170729
- const content = tail.slice(0, tail.length - STREAM_TAIL_LOOKBEHIND);
170730
- controller.enqueue(encoder.encode(content));
170731
- tail = tail.slice(-STREAM_TAIL_LOOKBEHIND);
170732
- }
170733
- baseRead = reader.read();
170734
- }
170735
- continue;
170736
- }
170737
- const index = pending.indexOf(winner.original);
170738
- if (index >= 0)
170739
- pending.splice(index, 1);
170740
- if (winner.result.html === null)
170741
- continue;
170742
- emitSlotMetric({
170743
- type: "patched",
170744
- slotId: winner.result.id,
170745
- durationMs: winner.result.durationMs,
170746
- bytes: winner.result.bytes
170747
- }, combinedOnSlotMetric);
170748
- controller.enqueue(encoder.encode(renderStreamingSlotPatchTag(winner.result.id, winner.result.html, nonce)));
170749
- }
170750
- if (footer.length > 0)
170751
- controller.enqueue(encoder.encode(footer));
170752
- controller.close();
170753
- } catch (error) {
170754
- controller.error(error);
170755
- }
170756
- }
170757
- });
170758
- };
170759
- var init_streamingSlots = __esm(() => {
170760
- init_escapeScriptContent();
170761
- CLOSING_HEAD_TAG_LENGTH = CLOSING_HEAD_TAG2.length;
170762
- CLOSING_PAGE_TAG_REGEX = /<\/body>\s*<\/html>\s*$/i;
170763
- currentStreamingSlotPolicy = {
170764
- timeoutMs: STREAMING_SLOT_TIMEOUT_MS,
170765
- fallbackHtml: "",
170766
- errorHtml: undefined,
170767
- maxSlotsPerResponse: STREAMING_SLOT_MAX_PER_RESPONSE,
170768
- maxSlotHtmlSizeBytes: STREAMING_SLOT_MAX_HTML_BYTES
170769
- };
170770
- });
170771
-
170772
- // src/core/streamingSlotRegistrar.ts
170773
- var registrar = null, setStreamingSlotRegistrar = (nextRegistrar) => {
170774
- registrar = nextRegistrar;
170775
- }, registerStreamingSlot = (slot) => {
170776
- registrar?.(slot);
170777
- };
170778
-
170779
- // src/core/streamingSlotRegistry.ts
170780
- var asyncLocalStorage, isServerRuntime = () => typeof process !== "undefined" && typeof process.versions?.node === "string", ensureAsyncLocalStorage = async () => {
170781
- if (typeof asyncLocalStorage !== "undefined")
170782
- return asyncLocalStorage;
170783
- if (!isServerRuntime()) {
170784
- asyncLocalStorage = null;
170785
- return asyncLocalStorage;
170786
- }
170787
- const mod = await import("async_hooks");
170788
- asyncLocalStorage = new mod.AsyncLocalStorage;
170789
- return asyncLocalStorage;
170790
- }, registerStreamingSlot2 = (slot) => {
170791
- if (!asyncLocalStorage)
170792
- return;
170793
- const store = asyncLocalStorage.getStore();
170794
- if (!store)
170795
- return;
170796
- store.set(slot.id, slot);
170797
- }, runWithStreamingSlotRegistry = async (task) => {
170798
- const storage = await ensureAsyncLocalStorage();
170799
- if (!storage) {
170800
- return {
170801
- result: await task(),
170802
- slots: []
170803
- };
170804
- }
170805
- return storage.run(new Map, async () => {
170806
- const result = await task();
170807
- const store = storage.getStore();
170808
- return {
170809
- result,
170810
- slots: store ? [...store.values()] : []
170811
- };
170812
- });
170813
- };
170814
- var init_streamingSlotRegistry = __esm(() => {
170815
- setStreamingSlotRegistrar(registerStreamingSlot2);
170816
- });
170817
-
170818
- // src/core/responseEnhancers.ts
170819
- var toResponse = async (responseLike) => await responseLike, cloneHeaders = (response) => {
170820
- const headers = new Headers(response.headers);
170821
- return headers;
170822
- }, enhanceHtmlResponseWithStreamingSlots = (response, { nonce, onError, streamingSlots = [], policy } = {}) => {
170823
- if (!response.body || streamingSlots.length === 0) {
170824
- return response;
170825
- }
170826
- const body = appendStreamingSlotPatchesToStream(response.body, streamingSlots, {
170827
- nonce,
170828
- onError,
170829
- policy
170830
- });
170831
- return new Response(body, {
170832
- headers: cloneHeaders(response),
170833
- status: response.status,
170834
- statusText: response.statusText
170835
- });
170836
- }, withStreamingSlots = async (responseLike, options = {}) => enhanceHtmlResponseWithStreamingSlots(await toResponse(responseLike), options), mergeStreamingSlots = (registered, explicit) => {
170837
- const merged = new Map;
170838
- for (const slot of registered)
170839
- merged.set(slot.id, slot);
170840
- for (const slot of explicit)
170841
- merged.set(slot.id, slot);
170842
- return [...merged.values()];
170843
- }, withRegisteredStreamingSlots = async (renderResponse, options = {}) => {
170844
- const { result, slots } = await runWithStreamingSlotRegistry(renderResponse);
170845
- const explicit = options.streamingSlots ?? [];
170846
- return withStreamingSlots(result, {
170847
- ...options,
170848
- streamingSlots: mergeStreamingSlots(slots, explicit)
170849
- });
170850
- };
170851
- var init_responseEnhancers = __esm(() => {
170852
- init_streamingSlots();
170853
- init_streamingSlotRegistry();
170854
- });
170855
-
170856
- // src/utils/ssrErrorPage.ts
170857
- var ssrErrorPage = (framework, error) => {
170858
- const frameworkColors = {
170859
- angular: "#dd0031",
170860
- html: "#e34c26",
170861
- htmx: "#1a365d",
170862
- react: "#61dafb",
170863
- svelte: "#ff3e00",
170864
- vue: "#42b883"
170865
- };
170866
- const accent = frameworkColors[framework] ?? "#94a3b8";
170867
- const label = framework.charAt(0).toUpperCase() + framework.slice(1);
170868
- const message = error instanceof Error ? error.message : String(error);
170869
- return `<!DOCTYPE html>
170870
- <html>
170871
- <head>
170872
- <meta charset="utf-8">
170873
- <meta name="viewport" content="width=device-width, initial-scale=1">
170874
- <title>SSR Error - AbsoluteJS</title>
170875
- <style>
170876
- *{margin:0;padding:0;box-sizing:border-box}
170877
- 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}
170878
- .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}
170879
- .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)}
170880
- .brand{font-weight:700;font-size:20px;color:#fff;letter-spacing:-0.02em}
170881
- .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)}
170882
- .kind{color:#94a3b8;font-size:13px;font-weight:500}
170883
- .content{padding:24px}
170884
- .label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.08em;color:#94a3b8;margin-bottom:8px}
170885
- .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}
170886
- .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}
170887
- </style>
170888
- </head>
170889
- <body>
170890
- <div class="card">
170891
- <div class="header">
170892
- <div style="display:flex;align-items:center;gap:12px">
170893
- <span class="brand">AbsoluteJS</span>
170894
- <span class="badge">${label}</span>
170895
- </div>
170896
- <span class="kind">Server Render Error</span>
170897
- </div>
170898
- <div class="content">
170899
- <div class="label">What went wrong</div>
170900
- <pre class="message">${message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")}</pre>
170901
- <div class="hint">A component threw during server-side rendering. Check the terminal for the full stack trace.</div>
170902
- </div>
170903
- </div>
170904
- </body>
170905
- </html>`;
170906
- };
170907
-
170908
- // src/utils/resolveConvention.ts
170909
- import { basename as basename2 } from "path";
170910
- var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boolean(value) && typeof value === "object", getMap = () => {
170911
- const value = Reflect.get(globalThis, CONVENTIONS_KEY);
170912
- if (isConventionsMap(value))
170913
- return value;
170914
- const empty = {};
170915
- return empty;
170916
- }, derivePageName = (pagePath) => {
170917
- const base = basename2(pagePath);
170918
- const dotIndex = base.indexOf(".");
170919
- const name = dotIndex > 0 ? base.slice(0, dotIndex) : base;
170920
- return toPascal(name);
170921
- }, resolveErrorConventionPath = (framework, pageName) => {
170922
- const conventions2 = getMap()[framework];
170923
- if (!conventions2)
170924
- return;
170925
- return conventions2.pages?.[pageName]?.error ?? conventions2.defaults?.error;
170926
- }, resolveNotFoundConventionPath = (framework) => getMap()[framework]?.defaults?.notFound, setConventions = (map) => {
170927
- Reflect.set(globalThis, CONVENTIONS_KEY, map);
170928
- }, isDev = () => true, buildErrorProps = (error) => {
170929
- const message = error instanceof Error ? error.message : String(error);
170930
- const stack = isDev() && error instanceof Error ? error.stack : undefined;
170931
- return { error: { message, stack } };
170932
- }, renderReactError = async (conventionPath, errorProps) => {
170933
- const { createElement: createElement2 } = await import("react");
170934
- const { renderToReadableStream } = await import("react-dom/server");
170935
- const mod = await import(conventionPath);
170936
- const [firstKey] = Object.keys(mod);
170937
- const ErrorComponent = mod.default ?? (firstKey ? mod[firstKey] : undefined);
170938
- const element = createElement2(ErrorComponent, errorProps);
170939
- const stream = await renderToReadableStream(element);
170940
- return new Response(stream, {
170941
- headers: { "Content-Type": "text/html" },
170942
- status: 500
170943
- });
170944
- }, renderSvelteError = async (conventionPath, errorProps) => {
170945
- const { render } = await import("svelte/server");
170946
- const mod = await import(conventionPath);
170947
- const ErrorComponent = mod.default;
170948
- const { head, body } = render(ErrorComponent, {
170949
- props: errorProps
170950
- });
170951
- const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
170952
- return new Response(html, {
170953
- headers: { "Content-Type": "text/html" },
170954
- status: 500
170955
- });
170956
- }, unescapeVueStyles = (ssrBody) => {
170957
- let styles = "";
170958
- const body = ssrBody.replace(/<style>([\s\S]*?)<\/style>/g, (_, css) => {
170959
- styles += `<style>${css.replace(/&quot;/g, '"').replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">")}</style>`;
170960
- return "";
170961
- });
170962
- return { body, styles };
170963
- }, renderVueError = async (conventionPath, errorProps) => {
170964
- const { createSSRApp: createSSRApp2, h: h2 } = await import("vue");
170965
- const { renderToString } = await import("vue/server-renderer");
170966
- const mod = await import(conventionPath);
170967
- const ErrorComponent = mod.default;
170968
- const app = createSSRApp2({
170969
- render: () => h2(ErrorComponent, errorProps)
170970
- });
170971
- const rawBody = await renderToString(app);
170972
- const { styles, body } = unescapeVueStyles(rawBody);
170973
- const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
170974
- return new Response(html, {
170975
- headers: { "Content-Type": "text/html" },
170976
- status: 500
170977
- });
170978
- }, renderAngularError = async (conventionPath, errorProps) => {
170979
- const mod = await import(conventionPath);
170980
- const renderError = mod.default ?? mod.renderError;
170981
- if (typeof renderError !== "function")
170982
- return null;
170983
- const html = renderError(errorProps);
170984
- return new Response(html, {
170985
- headers: { "Content-Type": "text/html" },
170986
- status: 500
170987
- });
170988
- }, logConventionRenderError = (framework, label, renderError) => {
170989
- const message = renderError instanceof Error ? renderError.message : "";
170990
- if (message.includes("Cannot find module") || message.includes("Cannot find package") || message.includes("not found in module")) {
170991
- 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}).`);
170992
- return;
170993
- }
170994
- console.error(`[SSR] Failed to render ${framework} convention ${label} page:`, renderError);
170995
- }, ERROR_RENDERERS, renderConventionError = async (framework, pageName, error) => {
170996
- const conventionPath = resolveErrorConventionPath(framework, pageName);
170997
- if (!conventionPath)
170998
- return null;
170999
- const errorProps = buildErrorProps(error);
171000
- const renderer = ERROR_RENDERERS[framework];
171001
- if (!renderer)
171002
- return null;
171003
- try {
171004
- return await renderer(conventionPath, errorProps);
171005
- } catch (renderError) {
171006
- logConventionRenderError(framework, "error", renderError);
171007
- }
171008
- return null;
171009
- }, renderReactNotFound = async (conventionPath) => {
171010
- const { createElement: createElement2 } = await import("react");
171011
- const { renderToReadableStream } = await import("react-dom/server");
171012
- const mod = await import(conventionPath);
171013
- const [nfKey] = Object.keys(mod);
171014
- const NotFoundComponent = mod.default ?? (nfKey ? mod[nfKey] : undefined);
171015
- const element = createElement2(NotFoundComponent);
171016
- const stream = await renderToReadableStream(element);
171017
- return new Response(stream, {
171018
- headers: { "Content-Type": "text/html" },
171019
- status: 404
171020
- });
171021
- }, renderSvelteNotFound = async (conventionPath) => {
171022
- const { render } = await import("svelte/server");
171023
- const mod = await import(conventionPath);
171024
- const NotFoundComponent = mod.default;
171025
- const { head, body } = render(NotFoundComponent);
171026
- const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
171027
- return new Response(html, {
171028
- headers: { "Content-Type": "text/html" },
171029
- status: 404
171030
- });
171031
- }, renderVueNotFound = async (conventionPath) => {
171032
- const { createSSRApp: createSSRApp2, h: h2 } = await import("vue");
171033
- const { renderToString } = await import("vue/server-renderer");
171034
- const mod = await import(conventionPath);
171035
- const NotFoundComponent = mod.default;
171036
- const app = createSSRApp2({
171037
- render: () => h2(NotFoundComponent)
171038
- });
171039
- const rawBody = await renderToString(app);
171040
- const { styles, body } = unescapeVueStyles(rawBody);
171041
- const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
171042
- return new Response(html, {
171043
- headers: { "Content-Type": "text/html" },
171044
- status: 404
171045
- });
171046
- }, renderAngularNotFound = async (conventionPath) => {
171047
- const mod = await import(conventionPath);
171048
- const renderNotFound = mod.default ?? mod.renderNotFound;
171049
- if (typeof renderNotFound !== "function")
171050
- return null;
171051
- const html = renderNotFound();
171052
- return new Response(html, {
171053
- headers: { "Content-Type": "text/html" },
171054
- status: 404
171055
- });
171056
- }, NOT_FOUND_RENDERERS, renderConventionNotFound = async (framework) => {
171057
- const conventionPath = resolveNotFoundConventionPath(framework);
171058
- if (!conventionPath)
171059
- return null;
171060
- const renderer = NOT_FOUND_RENDERERS[framework];
171061
- if (!renderer)
171062
- return null;
171063
- try {
171064
- return await renderer(conventionPath);
171065
- } catch (renderError) {
171066
- logConventionRenderError(framework, "not-found", renderError);
171067
- }
171068
- return null;
171069
- }, NOT_FOUND_PRIORITY, renderFirstNotFound = async () => {
171070
- for (const framework of NOT_FOUND_PRIORITY) {
171071
- if (!getMap()[framework]?.defaults?.notFound)
171072
- continue;
171073
- const response = await renderConventionNotFound(framework);
171074
- if (response)
171075
- return response;
171076
- }
171077
- return null;
171078
- };
171079
- var init_resolveConvention = __esm(() => {
171080
- ERROR_RENDERERS = {
171081
- angular: renderAngularError,
171082
- react: renderReactError,
171083
- svelte: renderSvelteError,
171084
- vue: renderVueError
171085
- };
171086
- NOT_FOUND_RENDERERS = {
171087
- angular: renderAngularNotFound,
171088
- react: renderReactNotFound,
171089
- svelte: renderSvelteNotFound,
171090
- vue: renderVueNotFound
171091
- };
171092
- NOT_FOUND_PRIORITY = [
171093
- "react",
171094
- "svelte",
171095
- "vue",
171096
- "angular"
171097
- ];
171098
- });
171099
-
171100
- // src/react/streamingSlotCollection.tsx
171101
- import { createContext, useContext } from "react";
171102
- import { jsxDEV } from "react/jsx-dev-runtime";
171103
- var StreamingSlotCollectorContext, StreamingSlotCollectorProvider = ({
171104
- children,
171105
- collector
171106
- }) => /* @__PURE__ */ jsxDEV(StreamingSlotCollectorContext.Provider, {
171107
- value: collector,
171108
- children
171109
- }, undefined, false, undefined, this), useStreamingSlotCollector = () => useContext(StreamingSlotCollectorContext);
171110
- var init_streamingSlotCollection = __esm(() => {
171111
- StreamingSlotCollectorContext = createContext(null);
171112
- });
171113
-
171114
- // src/react/pageHandler.ts
171115
- var ssrDirty = false, buildDirtyResponse = (index, maybeProps) => {
171116
- const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
171117
- const dirtyFlag = "window.__SSR_DIRTY__=true;";
171118
- const refreshSetup = "window.__REFRESH_BUFFER__=[];" + "window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};" + "window.$RefreshSig$=function(){return function(t){return t}};";
171119
- const inlineScript = `${propsScript}${dirtyFlag}${refreshSetup}`;
171120
- const html = `<!DOCTYPE html><html><head></head><body>` + `<script>${inlineScript}</script>` + `<script type="module" src="${index}"></script>` + `</body></html>`;
171121
- return new Response(html, {
171122
- headers: { "Content-Type": "text/html" }
171123
- });
171124
- }, handleReactPageRequest = async (PageComponent, index, ...props) => {
171125
- const [maybeProps] = props;
171126
- if (ssrDirty) {
171127
- return buildDirtyResponse(index, maybeProps);
171128
- }
171129
- try {
171130
- const { createElement: createElement2 } = await import("react");
171131
- const { renderToReadableStream } = await import("react-dom/server");
171132
- const slotCollector = new Map;
171133
- const pageElement = maybeProps !== undefined ? createElement2(PageComponent, maybeProps) : createElement2(PageComponent);
171134
- const element = createElement2(StreamingSlotCollectorProvider, { collector: slotCollector }, pageElement);
171135
- const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
171136
- const refreshSetup = "window.__REFRESH_BUFFER__=[];window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};window.$RefreshSig$=function(){return function(t){return t}};";
171137
- const stream = await renderToReadableStream(element, {
171138
- bootstrapModules: [index],
171139
- bootstrapScriptContent: propsScript + refreshSetup || undefined,
171140
- onError(error) {
171141
- console.error("[SSR] React streaming error:", error);
171142
- }
171143
- });
171144
- if ("allReady" in stream && stream.allReady instanceof Promise) {
171145
- await stream.allReady;
171146
- }
171147
- const htmlStream = injectIslandPageContextStream(stream);
171148
- return withStreamingSlots(new Response(htmlStream, {
171149
- headers: { "Content-Type": "text/html" }
171150
- }), {
171151
- streamingSlots: [...slotCollector.values()]
171152
- });
171153
- } catch (error) {
171154
- console.error("[SSR] React render error:", error);
171155
- const pageName = PageComponent.name || PageComponent.displayName || "";
171156
- const conventionResponse = await renderConventionError("react", pageName, error);
171157
- if (conventionResponse)
171158
- return conventionResponse;
171159
- return new Response(ssrErrorPage("react", error), {
171160
- headers: { "Content-Type": "text/html" },
171161
- status: 500
171162
- });
171163
- }
171164
- }, invalidateReactSsrCache = () => {
171165
- ssrDirty = true;
171166
- };
171167
- var init_pageHandler = __esm(() => {
171168
- init_responseEnhancers();
171169
- init_resolveConvention();
171170
- init_streamingSlotCollection();
171171
- });
171172
-
171173
170621
  // src/build/scanEntryPoints.ts
171174
170622
  import { existsSync as existsSync3 } from "fs";
171175
170623
  var {Glob } = globalThis.Bun;
@@ -173705,7 +173153,7 @@ ${registrations}
173705
173153
  ({ tsLibDir } = cached);
173706
173154
  cached.lastUsed = Date.now();
173707
173155
  } else {
173708
- const tsPath = __require.resolve("/home/alexkahn/abs/absolutejs/node_modules/typescript/lib/typescript.js");
173156
+ const tsPath = __require.resolve("typescript");
173709
173157
  const tsRootDir = dirname9(tsPath);
173710
173158
  tsLibDir = tsRootDir.endsWith("lib") ? tsRootDir : resolve18(tsRootDir, "lib");
173711
173159
  const config = readConfiguration("./tsconfig.json");
@@ -180463,6 +179911,752 @@ var init_devCert = __esm(() => {
180463
179911
  CERT_PATH = join23(CERT_DIR, "cert.pem");
180464
179912
  KEY_PATH = join23(CERT_DIR, "key.pem");
180465
179913
  });
179914
+
179915
+ // src/client/streamSwap.ts
179916
+ var streamSwapRuntime = () => {
179917
+ if (window.__ABS_SLOT_RUNTIME__ === true)
179918
+ return;
179919
+ window.__ABS_SLOT_RUNTIME__ = true;
179920
+ window.__ABS_SLOT_PENDING__ = window.__ABS_SLOT_PENDING__ ?? {};
179921
+ const pending = window.__ABS_SLOT_PENDING__;
179922
+ const apply = (id, html) => {
179923
+ const node = document.getElementById(`slot-${id}`);
179924
+ if (!node) {
179925
+ pending[id] = html;
179926
+ return;
179927
+ }
179928
+ node.innerHTML = html;
179929
+ delete pending[id];
179930
+ };
179931
+ const flush = () => {
179932
+ for (const id in pending) {
179933
+ if (!Object.prototype.hasOwnProperty.call(pending, id))
179934
+ continue;
179935
+ apply(id, pending[id] ?? "");
179936
+ }
179937
+ };
179938
+ window.__ABS_SLOT_ENQUEUE__ = (id, html) => {
179939
+ apply(id, html);
179940
+ };
179941
+ if (typeof MutationObserver === "function") {
179942
+ const observer = new MutationObserver(flush);
179943
+ const root = document.documentElement ?? document.body ?? document;
179944
+ observer.observe(root, { childList: true, subtree: true });
179945
+ }
179946
+ if (document.readyState === "loading") {
179947
+ document.addEventListener("DOMContentLoaded", flush, { once: true });
179948
+ }
179949
+ flush();
179950
+ };
179951
+ var stripFunctionWrapper = (value) => {
179952
+ const start = value.indexOf("{");
179953
+ const end = value.lastIndexOf("}");
179954
+ if (start < 0 || end <= start)
179955
+ return "";
179956
+ return value.slice(start + 1, end);
179957
+ };
179958
+ var getStreamSwapRuntimeScript = () => `(function(){${stripFunctionWrapper(streamSwapRuntime.toString())}})();`;
179959
+
179960
+ // src/utils/streamingSlots.ts
179961
+ init_escapeScriptContent();
179962
+ var SLOT_ID_PREFIX = "abs-slot-";
179963
+ var SLOT_PLACEHOLDER_PREFIX = "slot-";
179964
+ var CLOSING_HEAD_TAG = "</head>";
179965
+ var CLOSING_HEAD_TAG_LENGTH = CLOSING_HEAD_TAG.length;
179966
+ var CLOSING_PAGE_TAG_REGEX = /<\/body>\s*<\/html>\s*$/i;
179967
+ var STREAMING_RUNTIME_GLOBAL = "__ABS_SLOT_ENQUEUE__";
179968
+ var STREAMING_PENDING_GLOBAL = "__ABS_SLOT_PENDING__";
179969
+ var STREAM_TAIL_LOOKBEHIND = 128;
179970
+ var STREAMING_SLOT_TIMEOUT_MS = 5000;
179971
+ var STREAMING_SLOT_MAX_PER_RESPONSE = 128;
179972
+ var STREAMING_SLOT_MAX_HTML_BYTES = 64000;
179973
+ var createSlotPlaceholderId = (id) => `${SLOT_PLACEHOLDER_PREFIX}${id}`;
179974
+ 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)});`;
179975
+ var createNonceAttr = (nonce) => nonce ? ` nonce="${nonce}"` : "";
179976
+ var createStreamingSlotId = () => `${SLOT_ID_PREFIX}${Math.random().toString(36).slice(2, 10)}`;
179977
+ var getStreamingSlotsRuntimeScript = () => getStreamSwapRuntimeScript();
179978
+ var renderStreamingSlotsRuntimeTag = (nonce) => `<script${createNonceAttr(nonce)}>${escapeScriptContent(getStreamingSlotsRuntimeScript())}</script>`;
179979
+ var renderStreamingSlotPlaceholder = (id, fallbackHtml = "") => `<div id="${createSlotPlaceholderId(id)}" data-absolute-slot="true">${fallbackHtml}</div>`;
179980
+ var renderStreamingSlotPatchTag = (id, html, nonce) => `<script${createNonceAttr(nonce)}>${escapeScriptContent(createSlotPatchStatement(id, html))}</script>`;
179981
+ var injectHtmlIntoHead = (html, injection) => {
179982
+ const closingHeadIndex = html.indexOf(CLOSING_HEAD_TAG);
179983
+ if (closingHeadIndex >= 0) {
179984
+ return `${html.slice(0, closingHeadIndex)}${injection}${html.slice(closingHeadIndex)}`;
179985
+ }
179986
+ return `${html}${injection}`;
179987
+ };
179988
+ var toUint8 = (value, encoder) => encoder.encode(value);
179989
+ var currentStreamingSlotPolicy = {
179990
+ timeoutMs: STREAMING_SLOT_TIMEOUT_MS,
179991
+ fallbackHtml: "",
179992
+ errorHtml: undefined,
179993
+ maxSlotsPerResponse: STREAMING_SLOT_MAX_PER_RESPONSE,
179994
+ maxSlotHtmlSizeBytes: STREAMING_SLOT_MAX_HTML_BYTES
179995
+ };
179996
+ var clonePolicy = (policy) => ({
179997
+ ...policy
179998
+ });
179999
+ var normalizeSlotBytes = (value, fallback) => {
180000
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
180001
+ return Math.floor(value);
180002
+ }
180003
+ return fallback;
180004
+ };
180005
+ var normalizeSlotText = (value, fallback) => typeof value === "string" ? value : fallback;
180006
+ var normalizeSlotError = (value, fallback) => typeof value === "string" ? value : fallback;
180007
+ var hasPolicyValue = (policy, key) => Object.prototype.hasOwnProperty.call(policy, key);
180008
+ var applyStreamingSlotPolicyOverrides = (base, overridePolicy = {}) => ({
180009
+ timeoutMs: hasPolicyValue(overridePolicy, "timeoutMs") ? normalizeSlotBytes(overridePolicy.timeoutMs, base.timeoutMs) : base.timeoutMs,
180010
+ fallbackHtml: hasPolicyValue(overridePolicy, "fallbackHtml") ? normalizeSlotText(overridePolicy.fallbackHtml, "") : base.fallbackHtml,
180011
+ errorHtml: hasPolicyValue(overridePolicy, "errorHtml") ? normalizeSlotError(overridePolicy.errorHtml) : base.errorHtml,
180012
+ maxSlotsPerResponse: hasPolicyValue(overridePolicy, "maxSlotsPerResponse") ? normalizeSlotBytes(overridePolicy.maxSlotsPerResponse, base.maxSlotsPerResponse) : base.maxSlotsPerResponse,
180013
+ maxSlotHtmlSizeBytes: hasPolicyValue(overridePolicy, "maxSlotHtmlSizeBytes") ? normalizeSlotBytes(overridePolicy.maxSlotHtmlSizeBytes, base.maxSlotHtmlSizeBytes) : base.maxSlotHtmlSizeBytes,
180014
+ onError: hasPolicyValue(overridePolicy, "onError") ? overridePolicy.onError : base.onError,
180015
+ onSlotMetric: hasPolicyValue(overridePolicy, "onSlotMetric") ? overridePolicy.onSlotMetric : base.onSlotMetric
180016
+ });
180017
+ var createCombinedSlotErrorHandler = (policyOnError, enhancerOnError) => {
180018
+ if (!policyOnError && !enhancerOnError)
180019
+ return;
180020
+ return (error, slot) => {
180021
+ policyOnError?.(error, slot);
180022
+ enhancerOnError?.(error, slot);
180023
+ };
180024
+ };
180025
+ var createCombinedSlotMetricHandler = (policyOnSlotMetric, callOnSlotMetric) => {
180026
+ if (!policyOnSlotMetric && !callOnSlotMetric)
180027
+ return;
180028
+ return (metric) => {
180029
+ policyOnSlotMetric?.(metric);
180030
+ callOnSlotMetric?.(metric);
180031
+ };
180032
+ };
180033
+ var resolveStreamingSlotPolicy = (overridePolicy = {}) => {
180034
+ const base = getStreamingSlotPolicy();
180035
+ return applyStreamingSlotPolicyOverrides(base, overridePolicy);
180036
+ };
180037
+ var getStreamingSlotPolicy = () => clonePolicy(currentStreamingSlotPolicy);
180038
+ var setStreamingSlotPolicy = (policy = {}) => {
180039
+ const base = getStreamingSlotPolicy();
180040
+ currentStreamingSlotPolicy = applyStreamingSlotPolicyOverrides(base, policy);
180041
+ };
180042
+ var withStreamingSlotPolicy = async (policy, callback) => {
180043
+ const previous = getStreamingSlotPolicy();
180044
+ setStreamingSlotPolicy(policy);
180045
+ try {
180046
+ return await callback();
180047
+ } finally {
180048
+ currentStreamingSlotPolicy = previous;
180049
+ }
180050
+ };
180051
+ var emitSlotMetric = (metric, onSlotMetric) => {
180052
+ onSlotMetric?.(metric);
180053
+ };
180054
+ var createTimeoutError = (slot, timeoutMs) => {
180055
+ const error = new Error(`Streaming slot "${slot.id}" timed out after ${timeoutMs}ms`);
180056
+ error.__absTimeout = true;
180057
+ return error;
180058
+ };
180059
+ var toStreamingSlot = (slot, policy) => ({
180060
+ errorHtml: slot.errorHtml === undefined ? policy.errorHtml : slot.errorHtml,
180061
+ fallbackHtml: normalizeSlotText(slot.fallbackHtml, policy.fallbackHtml),
180062
+ id: slot.id ?? createStreamingSlotId(),
180063
+ timeoutMs: normalizeSlotBytes(slot.timeoutMs, policy.timeoutMs),
180064
+ resolve: slot.resolve
180065
+ });
180066
+ var prepareSlots = ({
180067
+ policy,
180068
+ slots,
180069
+ onError,
180070
+ onSlotMetric
180071
+ }) => {
180072
+ const preparedSlots = slots.map((slot) => toStreamingSlot(slot, policy));
180073
+ const maxSlotsPerResponse = policy.maxSlotsPerResponse;
180074
+ if (maxSlotsPerResponse === 0) {
180075
+ const error = new Error("Streaming slot limit is set to 0");
180076
+ for (const slot of preparedSlots) {
180077
+ onError?.(error, slot);
180078
+ emitSlotMetric({
180079
+ type: "dropped",
180080
+ slotId: slot.id,
180081
+ reason: "maxSlotsPerResponse is 0"
180082
+ }, onSlotMetric);
180083
+ }
180084
+ return [];
180085
+ }
180086
+ if (preparedSlots.length <= maxSlotsPerResponse) {
180087
+ preparedSlots.forEach((slot) => emitSlotMetric({
180088
+ type: "prepared",
180089
+ slotId: slot.id
180090
+ }, onSlotMetric));
180091
+ return preparedSlots;
180092
+ }
180093
+ const keptSlots = preparedSlots.slice(0, maxSlotsPerResponse);
180094
+ const droppedSlots = preparedSlots.slice(maxSlotsPerResponse);
180095
+ droppedSlots.forEach((slot) => {
180096
+ onError?.(new Error(`Streaming slot "${slot.id}" dropped because ${maxSlotsPerResponse} slots is the configured maximum`), slot);
180097
+ emitSlotMetric({
180098
+ type: "dropped",
180099
+ slotId: slot.id,
180100
+ reason: `maxSlotsPerResponse is ${maxSlotsPerResponse}`
180101
+ }, onSlotMetric);
180102
+ });
180103
+ keptSlots.forEach((slot) => emitSlotMetric({
180104
+ type: "prepared",
180105
+ slotId: slot.id
180106
+ }, onSlotMetric));
180107
+ return keptSlots;
180108
+ };
180109
+ var htmlByteLength = (value, encoder) => encoder.encode(value).length;
180110
+ var resolveSlot = async (slot, onError, policy, onSlotMetric) => {
180111
+ const safePolicy = policy ?? getStreamingSlotPolicy();
180112
+ const encoder = new TextEncoder;
180113
+ const start = Date.now();
180114
+ try {
180115
+ const maybeAsyncValue = Promise.resolve(slot.resolve());
180116
+ const resolved = typeof slot.timeoutMs === "number" && slot.timeoutMs > 0 ? await Promise.race([
180117
+ maybeAsyncValue,
180118
+ new Promise((_, reject) => setTimeout(() => {
180119
+ reject(createTimeoutError(slot, slot.timeoutMs ?? 0));
180120
+ }, slot.timeoutMs))
180121
+ ]) : await maybeAsyncValue;
180122
+ const html = typeof resolved === "string" ? resolved : `${resolved}`;
180123
+ if (safePolicy.maxSlotHtmlSizeBytes > 0 && htmlByteLength(html, encoder) > safePolicy.maxSlotHtmlSizeBytes) {
180124
+ const bytes2 = htmlByteLength(html, encoder);
180125
+ const error = new Error(`Streaming slot "${slot.id}" exceeded max payload size of ${safePolicy.maxSlotHtmlSizeBytes} bytes`);
180126
+ const durationMs2 = Date.now() - start;
180127
+ onError?.(error, slot);
180128
+ emitSlotMetric({
180129
+ type: "size_exceeded",
180130
+ slotId: slot.id,
180131
+ durationMs: durationMs2,
180132
+ bytes: bytes2,
180133
+ error
180134
+ }, onSlotMetric);
180135
+ const fallbackHtml = typeof slot.errorHtml === "string" ? slot.errorHtml : null;
180136
+ return {
180137
+ html: fallbackHtml,
180138
+ id: slot.id,
180139
+ durationMs: durationMs2,
180140
+ bytes: fallbackHtml === null ? 0 : htmlByteLength(fallbackHtml, encoder)
180141
+ };
180142
+ }
180143
+ const durationMs = Date.now() - start;
180144
+ const bytes = htmlByteLength(html, encoder);
180145
+ emitSlotMetric({
180146
+ type: "resolved",
180147
+ slotId: slot.id,
180148
+ durationMs,
180149
+ bytes
180150
+ }, onSlotMetric);
180151
+ return {
180152
+ html,
180153
+ id: slot.id,
180154
+ durationMs,
180155
+ bytes
180156
+ };
180157
+ } catch (error) {
180158
+ const durationMs = Date.now() - start;
180159
+ onError?.(error, slot);
180160
+ emitSlotMetric({
180161
+ type: error?.__absTimeout === true ? "timeout" : "error",
180162
+ slotId: slot.id,
180163
+ durationMs,
180164
+ error
180165
+ }, onSlotMetric);
180166
+ if (typeof slot.errorHtml === "string") {
180167
+ const html = slot.errorHtml;
180168
+ return {
180169
+ html,
180170
+ id: slot.id,
180171
+ durationMs,
180172
+ bytes: htmlByteLength(html, encoder)
180173
+ };
180174
+ }
180175
+ return {
180176
+ html: null,
180177
+ id: slot.id,
180178
+ durationMs,
180179
+ bytes: 0
180180
+ };
180181
+ }
180182
+ };
180183
+ var nextResolvedSlot = async (pending) => {
180184
+ const wrapped = pending.map((promise) => promise.then((result) => ({
180185
+ original: promise,
180186
+ result
180187
+ })));
180188
+ return Promise.race(wrapped);
180189
+ };
180190
+ var streamChunkToString = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true });
180191
+ var streamOutOfOrderSlots = ({
180192
+ footerHtml = "",
180193
+ headerHtml = "",
180194
+ nonce,
180195
+ policy,
180196
+ onSlotMetric,
180197
+ onError,
180198
+ slots
180199
+ }) => {
180200
+ const resolvedPolicy = resolveStreamingSlotPolicy(policy);
180201
+ const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
180202
+ const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
180203
+ const effectivePolicy = {
180204
+ ...resolvedPolicy,
180205
+ onSlotMetric: combinedOnSlotMetric
180206
+ };
180207
+ const preparedSlots = prepareSlots({
180208
+ policy: effectivePolicy,
180209
+ slots,
180210
+ onError: combinedOnError,
180211
+ onSlotMetric: combinedOnSlotMetric
180212
+ });
180213
+ const encoder = new TextEncoder;
180214
+ return new ReadableStream({
180215
+ async start(controller) {
180216
+ try {
180217
+ let header = headerHtml;
180218
+ if (preparedSlots.length > 0 && !header.includes(STREAMING_RUNTIME_GLOBAL)) {
180219
+ header = injectHtmlIntoHead(header, renderStreamingSlotsRuntimeTag(nonce));
180220
+ }
180221
+ controller.enqueue(toUint8(header, encoder));
180222
+ const pending = preparedSlots.map((slot) => {
180223
+ const fallback = renderStreamingSlotPlaceholder(slot.id, slot.fallbackHtml ?? "");
180224
+ controller.enqueue(toUint8(fallback, encoder));
180225
+ return resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric);
180226
+ });
180227
+ while (pending.length > 0) {
180228
+ const { original, result } = await nextResolvedSlot(pending);
180229
+ const index = pending.indexOf(original);
180230
+ if (index >= 0)
180231
+ pending.splice(index, 1);
180232
+ if (result.html === null)
180233
+ continue;
180234
+ emitSlotMetric({
180235
+ type: "patched",
180236
+ slotId: result.id,
180237
+ durationMs: result.durationMs,
180238
+ bytes: result.bytes
180239
+ }, combinedOnSlotMetric);
180240
+ controller.enqueue(toUint8(renderStreamingSlotPatchTag(result.id, result.html, nonce), encoder));
180241
+ }
180242
+ if (footerHtml.length > 0) {
180243
+ controller.enqueue(toUint8(footerHtml, encoder));
180244
+ }
180245
+ controller.close();
180246
+ } catch (error) {
180247
+ controller.error(error);
180248
+ }
180249
+ }
180250
+ });
180251
+ };
180252
+ var injectStreamingRuntimeIntoStream = (stream, nonce) => {
180253
+ const runtimeTag = renderStreamingSlotsRuntimeTag(nonce);
180254
+ const encoder = new TextEncoder;
180255
+ const decoder = new TextDecoder;
180256
+ const lookbehind = CLOSING_HEAD_TAG_LENGTH - 1;
180257
+ return new ReadableStream({
180258
+ async start(controller) {
180259
+ const reader = stream.getReader();
180260
+ let injected = false;
180261
+ let pending = "";
180262
+ try {
180263
+ for (;; ) {
180264
+ const { done, value } = await reader.read();
180265
+ if (done)
180266
+ break;
180267
+ if (!value)
180268
+ continue;
180269
+ pending += streamChunkToString(value, decoder);
180270
+ if (injected) {
180271
+ controller.enqueue(encoder.encode(pending));
180272
+ pending = "";
180273
+ continue;
180274
+ }
180275
+ const headIndex = pending.indexOf(CLOSING_HEAD_TAG);
180276
+ if (headIndex >= 0) {
180277
+ const withRuntime = `${pending.slice(0, headIndex)}${runtimeTag}${pending.slice(headIndex)}`;
180278
+ controller.enqueue(encoder.encode(withRuntime));
180279
+ pending = "";
180280
+ injected = true;
180281
+ continue;
180282
+ }
180283
+ if (pending.length > lookbehind) {
180284
+ const safeText = pending.slice(0, pending.length - lookbehind);
180285
+ controller.enqueue(encoder.encode(safeText));
180286
+ pending = pending.slice(-lookbehind);
180287
+ }
180288
+ }
180289
+ pending += decoder.decode();
180290
+ if (!injected) {
180291
+ pending = injectHtmlIntoHead(pending, runtimeTag);
180292
+ }
180293
+ if (pending.length > 0) {
180294
+ controller.enqueue(encoder.encode(pending));
180295
+ }
180296
+ controller.close();
180297
+ } catch (error) {
180298
+ controller.error(error);
180299
+ }
180300
+ }
180301
+ });
180302
+ };
180303
+ var appendStreamingSlotPatchesToStream = (stream, slots = [], {
180304
+ injectRuntime = true,
180305
+ nonce,
180306
+ onError,
180307
+ onSlotMetric,
180308
+ policy
180309
+ } = {}) => {
180310
+ const resolvedPolicy = resolveStreamingSlotPolicy(policy);
180311
+ const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
180312
+ const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
180313
+ const effectivePolicy = {
180314
+ ...resolvedPolicy,
180315
+ onSlotMetric: combinedOnSlotMetric
180316
+ };
180317
+ const preparedSlots = prepareSlots({
180318
+ policy: effectivePolicy,
180319
+ slots,
180320
+ onError: combinedOnError,
180321
+ onSlotMetric: combinedOnSlotMetric
180322
+ });
180323
+ if (preparedSlots.length === 0)
180324
+ return stream;
180325
+ const source = injectRuntime ? injectStreamingRuntimeIntoStream(stream, nonce) : stream;
180326
+ const encoder = new TextEncoder;
180327
+ const decoder = new TextDecoder;
180328
+ const reader = source.getReader();
180329
+ const pending = preparedSlots.map((slot) => resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric));
180330
+ return new ReadableStream({
180331
+ async start(controller) {
180332
+ let baseDone = false;
180333
+ let baseRead = reader.read();
180334
+ let tail = "";
180335
+ let footer = "";
180336
+ try {
180337
+ while (!baseDone || pending.length > 0) {
180338
+ const racers = [];
180339
+ if (!baseDone) {
180340
+ racers.push(baseRead.then(({ done, value }) => ({
180341
+ done,
180342
+ kind: "base",
180343
+ value
180344
+ })));
180345
+ }
180346
+ if (pending.length > 0) {
180347
+ racers.push(nextResolvedSlot(pending).then((resolved) => ({
180348
+ kind: "slot",
180349
+ ...resolved
180350
+ })));
180351
+ }
180352
+ if (racers.length === 0)
180353
+ break;
180354
+ const winner = await Promise.race(racers);
180355
+ if (winner.kind === "base") {
180356
+ if (winner.done) {
180357
+ baseDone = true;
180358
+ tail += decoder.decode();
180359
+ const footerStart = tail.search(CLOSING_PAGE_TAG_REGEX);
180360
+ if (footerStart >= 0) {
180361
+ const content = tail.slice(0, footerStart);
180362
+ footer = tail.slice(footerStart);
180363
+ if (content.length > 0) {
180364
+ controller.enqueue(encoder.encode(content));
180365
+ }
180366
+ } else if (tail.length > 0) {
180367
+ controller.enqueue(encoder.encode(tail));
180368
+ }
180369
+ tail = "";
180370
+ } else if (winner.value) {
180371
+ tail += streamChunkToString(winner.value, decoder);
180372
+ if (tail.length > STREAM_TAIL_LOOKBEHIND) {
180373
+ const content = tail.slice(0, tail.length - STREAM_TAIL_LOOKBEHIND);
180374
+ controller.enqueue(encoder.encode(content));
180375
+ tail = tail.slice(-STREAM_TAIL_LOOKBEHIND);
180376
+ }
180377
+ baseRead = reader.read();
180378
+ }
180379
+ continue;
180380
+ }
180381
+ const index = pending.indexOf(winner.original);
180382
+ if (index >= 0)
180383
+ pending.splice(index, 1);
180384
+ if (winner.result.html === null)
180385
+ continue;
180386
+ emitSlotMetric({
180387
+ type: "patched",
180388
+ slotId: winner.result.id,
180389
+ durationMs: winner.result.durationMs,
180390
+ bytes: winner.result.bytes
180391
+ }, combinedOnSlotMetric);
180392
+ controller.enqueue(encoder.encode(renderStreamingSlotPatchTag(winner.result.id, winner.result.html, nonce)));
180393
+ }
180394
+ if (footer.length > 0)
180395
+ controller.enqueue(encoder.encode(footer));
180396
+ controller.close();
180397
+ } catch (error) {
180398
+ controller.error(error);
180399
+ }
180400
+ }
180401
+ });
180402
+ };
180403
+
180404
+ // src/core/streamingSlotRegistrar.ts
180405
+ var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
180406
+ var getRegistrarGlobal = () => globalThis;
180407
+ var setStreamingSlotRegistrar = (nextRegistrar) => {
180408
+ getRegistrarGlobal()[STREAMING_SLOT_REGISTRAR_KEY] = nextRegistrar;
180409
+ };
180410
+ var registerStreamingSlot = (slot) => {
180411
+ getRegistrarGlobal()[STREAMING_SLOT_REGISTRAR_KEY]?.(slot);
180412
+ };
180413
+
180414
+ // src/core/streamingSlotRegistry.ts
180415
+ var asyncLocalStorage;
180416
+ var isServerRuntime = () => typeof process !== "undefined" && typeof process.versions?.node === "string";
180417
+ var ensureAsyncLocalStorage = async () => {
180418
+ if (typeof asyncLocalStorage !== "undefined")
180419
+ return asyncLocalStorage;
180420
+ if (!isServerRuntime()) {
180421
+ asyncLocalStorage = null;
180422
+ return asyncLocalStorage;
180423
+ }
180424
+ const mod = await import("async_hooks");
180425
+ asyncLocalStorage = new mod.AsyncLocalStorage;
180426
+ return asyncLocalStorage;
180427
+ };
180428
+ var registerStreamingSlot2 = (slot) => {
180429
+ if (!asyncLocalStorage)
180430
+ return;
180431
+ const store = asyncLocalStorage.getStore();
180432
+ if (!store)
180433
+ return;
180434
+ store.set(slot.id, slot);
180435
+ };
180436
+ setStreamingSlotRegistrar(registerStreamingSlot2);
180437
+ var runWithStreamingSlotRegistry = async (task) => {
180438
+ const storage = await ensureAsyncLocalStorage();
180439
+ if (!storage) {
180440
+ return {
180441
+ result: await task(),
180442
+ slots: []
180443
+ };
180444
+ }
180445
+ return storage.run(new Map, async () => {
180446
+ const result = await task();
180447
+ const store = storage.getStore();
180448
+ return {
180449
+ result,
180450
+ slots: store ? [...store.values()] : []
180451
+ };
180452
+ });
180453
+ };
180454
+
180455
+ // src/core/responseEnhancers.ts
180456
+ var toResponse = async (responseLike) => await responseLike;
180457
+ var cloneHeaders = (response) => {
180458
+ const headers = new Headers(response.headers);
180459
+ return headers;
180460
+ };
180461
+ var enhanceHtmlResponseWithStreamingSlots = (response, { nonce, onError, streamingSlots = [], policy } = {}) => {
180462
+ if (!response.body || streamingSlots.length === 0) {
180463
+ return response;
180464
+ }
180465
+ const body = appendStreamingSlotPatchesToStream(response.body, streamingSlots, {
180466
+ nonce,
180467
+ onError,
180468
+ policy
180469
+ });
180470
+ return new Response(body, {
180471
+ headers: cloneHeaders(response),
180472
+ status: response.status,
180473
+ statusText: response.statusText
180474
+ });
180475
+ };
180476
+ var withStreamingSlots = async (responseLike, options = {}) => enhanceHtmlResponseWithStreamingSlots(await toResponse(responseLike), options);
180477
+ var mergeStreamingSlots = (registered, explicit) => {
180478
+ const merged = new Map;
180479
+ for (const slot of registered)
180480
+ merged.set(slot.id, slot);
180481
+ for (const slot of explicit)
180482
+ merged.set(slot.id, slot);
180483
+ return [...merged.values()];
180484
+ };
180485
+ var withRegisteredStreamingSlots = async (renderResponse, options = {}) => {
180486
+ const { result, slots } = await runWithStreamingSlotRegistry(renderResponse);
180487
+ const explicit = options.streamingSlots ?? [];
180488
+ return withStreamingSlots(result, {
180489
+ ...options,
180490
+ streamingSlots: mergeStreamingSlots(slots, explicit)
180491
+ });
180492
+ };
180493
+
180494
+ // src/core/wrapPageHandlerWithStreamingSlots.ts
180495
+ var wrapPageHandlerWithStreamingSlots = (handler) => (...args) => withRegisteredStreamingSlots(() => handler(...args));
180496
+
180497
+ // src/react/index.ts
180498
+ init_pageHandler();
180499
+
180500
+ // src/react/Island.tsx
180501
+ init_islandMarkupAttributes();
180502
+ init_renderIslandMarkup();
180503
+ import { jsxDEV } from "react/jsx-dev-runtime";
180504
+ var Island = async (props) => {
180505
+ if (typeof window !== "undefined") {
180506
+ return /* @__PURE__ */ jsxDEV("div", {
180507
+ ...getIslandMarkerAttributes(props),
180508
+ suppressHydrationWarning: true
180509
+ }, undefined, false, undefined, this);
180510
+ }
180511
+ const result = await renderIslandResult(requireCurrentIslandRegistry(), props);
180512
+ return /* @__PURE__ */ jsxDEV("div", {
180513
+ ...result.attributes,
180514
+ dangerouslySetInnerHTML: { __html: result.html }
180515
+ }, undefined, false, undefined, this);
180516
+ };
180517
+ // src/react/createIsland.tsx
180518
+ init_islandMarkupAttributes();
180519
+ init_renderIslandMarkup();
180520
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
180521
+ var createTypedIsland = (registry) => {
180522
+ const Island2 = async (props) => {
180523
+ if (typeof window !== "undefined") {
180524
+ return /* @__PURE__ */ jsxDEV2("div", {
180525
+ ...getIslandMarkerAttributes(props),
180526
+ suppressHydrationWarning: true
180527
+ }, undefined, false, undefined, this);
180528
+ }
180529
+ const result = await renderIslandResult(registry, props);
180530
+ return /* @__PURE__ */ jsxDEV2("div", {
180531
+ ...result.attributes,
180532
+ dangerouslySetInnerHTML: { __html: result.html }
180533
+ }, undefined, false, undefined, this);
180534
+ };
180535
+ return Island2;
180536
+ };
180537
+ // src/react/hooks/useIslandStore.ts
180538
+ import { useSyncExternalStore } from "react";
180539
+
180540
+ // node_modules/zustand/esm/vanilla.mjs
180541
+ var createStoreImpl = (createState) => {
180542
+ let state;
180543
+ const listeners = /* @__PURE__ */ new Set;
180544
+ const setState = (partial, replace) => {
180545
+ const nextState = typeof partial === "function" ? partial(state) : partial;
180546
+ if (!Object.is(nextState, state)) {
180547
+ const previousState = state;
180548
+ state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
180549
+ listeners.forEach((listener) => listener(state, previousState));
180550
+ }
180551
+ };
180552
+ const getState = () => state;
180553
+ const getInitialState = () => initialState;
180554
+ const subscribe = (listener) => {
180555
+ listeners.add(listener);
180556
+ return () => listeners.delete(listener);
180557
+ };
180558
+ const api = { setState, getState, getInitialState, subscribe };
180559
+ const initialState = state = createState(setState, getState, api);
180560
+ return api;
180561
+ };
180562
+ var createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
180563
+
180564
+ // node_modules/zustand/esm/middleware.mjs
180565
+ function combine(initialState, create) {
180566
+ return (...args) => Object.assign({}, initialState, create(...args));
180567
+ }
180568
+
180569
+ // src/client/islandStore.ts
180570
+ var getIslandStoreSnapshot = () => {
180571
+ globalThis.__ABS_ISLAND_STATE__ ??= {};
180572
+ return globalThis.__ABS_ISLAND_STATE__;
180573
+ };
180574
+ var getIslandStores = () => {
180575
+ globalThis.__ABS_ISLAND_STORES__ ??= new Map;
180576
+ return globalThis.__ABS_ISLAND_STORES__;
180577
+ };
180578
+ var isSerializableValue = (value) => typeof value !== "function" && value !== undefined;
180579
+ var toSerializableState = (state) => Object.fromEntries(Object.entries(state).filter(([, value]) => isSerializableValue(value)));
180580
+ var applySnapshot = (store, snapshot) => {
180581
+ if (!snapshot) {
180582
+ return;
180583
+ }
180584
+ store.setState({
180585
+ ...store.getState(),
180586
+ ...snapshot
180587
+ });
180588
+ };
180589
+ var getPeerStores = (storeInstances, ownerStore) => [...storeInstances].filter((peer) => peer.store !== ownerStore);
180590
+ var syncIslandSnapshot = (storeId, state, storeInstances, ownerStore) => {
180591
+ const nextSnapshot = toSerializableState(state);
180592
+ getIslandStoreSnapshot()[storeId] = nextSnapshot;
180593
+ for (const peerStore of getPeerStores(storeInstances, ownerStore)) {
180594
+ peerStore.applyExternalSnapshot(nextSnapshot);
180595
+ }
180596
+ };
180597
+ var createIslandStore = (storeId, initialState, createState) => {
180598
+ const store = createStore(combine(initialState, createState));
180599
+ const stores = getIslandStores();
180600
+ const storeInstances = stores.get(storeId) ?? new Set;
180601
+ const initialSnapshot = getIslandStoreSnapshot()[storeId];
180602
+ applySnapshot(store, initialSnapshot);
180603
+ let isApplyingExternalSnapshot = false;
180604
+ const applyExternalSnapshot = (snapshot) => {
180605
+ isApplyingExternalSnapshot = true;
180606
+ applySnapshot(store, snapshot);
180607
+ };
180608
+ storeInstances.add({
180609
+ applyExternalSnapshot,
180610
+ store
180611
+ });
180612
+ stores.set(storeId, storeInstances);
180613
+ syncIslandSnapshot(storeId, store.getState(), storeInstances, store);
180614
+ store.subscribe((state) => {
180615
+ if (isApplyingExternalSnapshot) {
180616
+ isApplyingExternalSnapshot = false;
180617
+ return;
180618
+ }
180619
+ syncIslandSnapshot(storeId, state, storeInstances, store);
180620
+ });
180621
+ return store;
180622
+ };
180623
+ var getIslandStoreServerSnapshot = (store, selector) => selector(store.getInitialState());
180624
+ var applySnapshotToStoreInstances = (storeId, instances, snapshot) => {
180625
+ for (const instance of instances) {
180626
+ instance.applyExternalSnapshot(snapshot[storeId] ?? {});
180627
+ }
180628
+ };
180629
+ var initializeIslandStores = (state) => {
180630
+ const currentSnapshot = getIslandStoreSnapshot();
180631
+ const nextSnapshot = {
180632
+ ...state,
180633
+ ...currentSnapshot
180634
+ };
180635
+ globalThis.__ABS_ISLAND_STATE__ = nextSnapshot;
180636
+ for (const [storeId, store] of getIslandStores()) {
180637
+ applySnapshotToStoreInstances(storeId, store, nextSnapshot);
180638
+ }
180639
+ };
180640
+ var readIslandStore = (store, selector) => selector(store.getState());
180641
+ var subscribeIslandStore = (store, selector, listener) => {
180642
+ let currentSelection = selector(store.getState());
180643
+ return store.subscribe((state) => {
180644
+ const nextSelection = selector(state);
180645
+ if (Object.is(nextSelection, currentSelection)) {
180646
+ return;
180647
+ }
180648
+ currentSelection = nextSelection;
180649
+ listener(nextSelection);
180650
+ });
180651
+ };
180652
+
180653
+ // src/react/hooks/useIslandStore.ts
180654
+ var useIslandStore = (store, selector) => useSyncExternalStore((listener) => subscribeIslandStore(store, selector, () => {
180655
+ listener();
180656
+ }), () => readIslandStore(store, selector), () => getIslandStoreServerSnapshot(store, selector));
180657
+
180658
+ // src/react/index.ts
180659
+ var handleReactPageRequest2 = wrapPageHandlerWithStreamingSlots(handleReactPageRequest);
180466
180660
  // types/client.ts
180467
180661
  var hmrState = {
180468
180662
  isConnected: false,
@@ -180488,7 +180682,6 @@ init_islands();
180488
180682
 
180489
180683
  // src/core/pageHandlers.ts
180490
180684
  init_staticIslandPages();
180491
- init_pageHandler();
180492
180685
  var {file } = globalThis.Bun;
180493
180686
  var handleStaticPageRequest = async (pagePath) => {
180494
180687
  const html = await file(pagePath).text();
@@ -180765,12 +180958,7 @@ var prepare = async (configOrPath) => {
180765
180958
  };
180766
180959
 
180767
180960
  // src/core/index.ts
180768
- init_responseEnhancers();
180769
180961
  init_renderIslandMarkup();
180770
-
180771
- // src/core/wrapPageHandlerWithStreamingSlots.ts
180772
- init_responseEnhancers();
180773
- var wrapPageHandlerWithStreamingSlots = (handler) => (...args) => withRegisteredStreamingSlots(() => handler(...args));
180774
180962
  // src/plugins/networking.ts
180775
180963
  init_constants();
180776
180964
  import { argv } from "process";
@@ -187127,9 +187315,6 @@ var createStreamingSlotMetricSink = ({
187127
187315
  });
187128
187316
  };
187129
187317
  };
187130
-
187131
- // src/utils/index.ts
187132
- init_streamingSlots();
187133
187318
  export {
187134
187319
  wrapPageHandlerWithStreamingSlots,
187135
187320
  withStreamingSlots,
@@ -187157,7 +187342,7 @@ export {
187157
187342
  injectStreamingRuntimeIntoStream,
187158
187343
  injectHtmlIntoHead,
187159
187344
  hmrState,
187160
- handleReactPageRequest,
187345
+ handleReactPageRequest2 as handleReactPageRequest,
187161
187346
  handleHTMXPageRequest,
187162
187347
  handleHTMLPageRequest,
187163
187348
  getStreamingSlotsRuntimeScript,
@@ -187234,5 +187419,5 @@ export {
187234
187419
  ANGULAR_INIT_TIMEOUT_MS
187235
187420
  };
187236
187421
 
187237
- //# debugId=48812244A0B17F5E64756E2164756E21
187422
+ //# debugId=C88BAB0C6BD3F8AB64756E2164756E21
187238
187423
  //# sourceMappingURL=index.js.map