@absolutejs/absolute 0.19.0-beta.364 → 0.19.0-beta.366

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.
Files changed (60) hide show
  1. package/dist/ai/index.js +108 -2
  2. package/dist/ai/index.js.map +7 -6
  3. package/dist/ai-client/angular/ai/index.js +102 -0
  4. package/dist/ai-client/react/ai/index.js +176 -0
  5. package/dist/ai-client/vue/ai/index.js +172 -0
  6. package/dist/angular/ai/index.js +103 -1
  7. package/dist/angular/ai/index.js.map +5 -3
  8. package/dist/angular/browser.js +8 -12
  9. package/dist/angular/browser.js.map +4 -4
  10. package/dist/angular/index.js +4420 -4465
  11. package/dist/angular/index.js.map +8 -8
  12. package/dist/build.js +578 -23
  13. package/dist/build.js.map +10 -4
  14. package/dist/client/index.js +44 -45
  15. package/dist/client/index.js.map +4 -4
  16. package/dist/index.js +4340 -4363
  17. package/dist/index.js.map +15 -14
  18. package/dist/react/ai/index.js +177 -1
  19. package/dist/react/ai/index.js.map +7 -3
  20. package/dist/react/components/browser/index.js +18 -6
  21. package/dist/react/components/index.js +35 -16
  22. package/dist/react/components/index.js.map +6 -5
  23. package/dist/react/index.js +1774 -1803
  24. package/dist/react/index.js.map +12 -12
  25. package/dist/react/server.js +574 -3
  26. package/dist/react/server.js.map +11 -4
  27. package/dist/src/ai/client/ragClient.d.ts +16 -0
  28. package/dist/src/ai/index.d.ts +2 -1
  29. package/dist/src/ai/rag/chat.d.ts +41 -5
  30. package/dist/src/ai/rag/index.d.ts +1 -1
  31. package/dist/src/ai/rag/types.d.ts +1 -1
  32. package/dist/src/angular/ai/index.d.ts +1 -0
  33. package/dist/src/angular/ai/rag-client.service.d.ts +11 -0
  34. package/dist/src/core/pageHandlers.d.ts +0 -1
  35. package/dist/src/react/ai/index.d.ts +3 -0
  36. package/dist/src/react/ai/useRAGIngest.d.ts +8 -0
  37. package/dist/src/react/ai/useRAGSearch.d.ts +9 -0
  38. package/dist/src/react/ai/useRAGStatus.d.ts +9 -0
  39. package/dist/src/react/index.d.ts +1 -1
  40. package/dist/src/react/streamingSlotCollection.d.ts +9 -0
  41. package/dist/src/svelte/ai/createRAGIngest.d.ts +7 -0
  42. package/dist/src/svelte/ai/createRAGSearch.d.ts +7 -0
  43. package/dist/src/svelte/ai/createRAGStatus.d.ts +8 -0
  44. package/dist/src/svelte/ai/index.d.ts +3 -0
  45. package/dist/src/vue/ai/index.d.ts +3 -0
  46. package/dist/src/vue/ai/useRAGIngest.d.ts +7 -0
  47. package/dist/src/vue/ai/useRAGSearch.d.ts +21 -0
  48. package/dist/src/vue/ai/useRAGStatus.d.ts +8 -0
  49. package/dist/svelte/ai/index.js +171 -1
  50. package/dist/svelte/ai/index.js.map +8 -4
  51. package/dist/svelte/index.js +1881 -1926
  52. package/dist/svelte/index.js.map +8 -8
  53. package/dist/types/ai.d.ts +11 -0
  54. package/dist/vue/ai/index.js +173 -1
  55. package/dist/vue/ai/index.js.map +7 -3
  56. package/dist/vue/components/index.js +8 -12
  57. package/dist/vue/components/index.js.map +5 -5
  58. package/dist/vue/index.js +1929 -1976
  59. package/dist/vue/index.js.map +8 -8
  60. package/package.json +1 -1
@@ -78,24 +78,8 @@ 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
- // 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
81
  // 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) => {
82
+ 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) => {
99
83
  const manifestScript = `<script>window.__ABSOLUTE_MANIFEST__ = ${JSON.stringify(manifest)}</script>`;
100
84
  const islandStateScript = `<script>window.__ABS_ISLAND_STATE__ = ${JSON.stringify(globalThis.__ABS_ISLAND_STATE__ ?? {})}</script>`;
101
85
  const bootstrapPath = manifest[BOOTSTRAP_MANIFEST_KEY];
@@ -114,10 +98,10 @@ var BOOTSTRAP_MANIFEST_KEY = "BootstrapClient", ISLAND_MARKER = 'data-island="tr
114
98
  }
115
99
  }
116
100
  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) => {
101
+ }, streamChunkToString = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true }), pipeStreamWithHeadInjection = (stream, markup) => {
118
102
  const encoder = new TextEncoder;
119
103
  const decoder = new TextDecoder;
120
- const lookbehind = CLOSING_HEAD_TAG2.length - 1;
104
+ const lookbehind = CLOSING_HEAD_TAG.length - 1;
121
105
  return new ReadableStream({
122
106
  async start(controller) {
123
107
  const reader = stream.getReader();
@@ -130,13 +114,13 @@ var BOOTSTRAP_MANIFEST_KEY = "BootstrapClient", ISLAND_MARKER = 'data-island="tr
130
114
  break;
131
115
  if (!value)
132
116
  continue;
133
- pending += streamChunkToString2(value, decoder);
117
+ pending += streamChunkToString(value, decoder);
134
118
  if (injected) {
135
119
  controller.enqueue(encoder.encode(pending));
136
120
  pending = "";
137
121
  continue;
138
122
  }
139
- const headIndex = pending.indexOf(CLOSING_HEAD_TAG2);
123
+ const headIndex = pending.indexOf(CLOSING_HEAD_TAG);
140
124
  if (headIndex >= 0) {
141
125
  const next = `${pending.slice(0, headIndex)}${markup}${pending.slice(headIndex)}`;
142
126
  controller.enqueue(encoder.encode(next));
@@ -179,7 +163,7 @@ var BOOTSTRAP_MANIFEST_KEY = "BootstrapClient", ISLAND_MARKER = 'data-island="tr
179
163
  break;
180
164
  if (!value)
181
165
  continue;
182
- pending += streamChunkToString2(value, decoder);
166
+ pending += streamChunkToString(value, decoder);
183
167
  if (injected) {
184
168
  controller.enqueue(encoder.encode(pending));
185
169
  pending = "";
@@ -237,1867 +221,1857 @@ var BOOTSTRAP_MANIFEST_KEY = "BootstrapClient", ISLAND_MARKER = 'data-island="tr
237
221
  globalThis.__absoluteManifest = manifest;
238
222
  };
239
223
 
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"
224
+ // src/client/streamSwap.ts
225
+ var streamSwapRuntime = () => {
226
+ if (window.__ABS_SLOT_RUNTIME__ === true)
227
+ return;
228
+ window.__ABS_SLOT_RUNTIME__ = true;
229
+ window.__ABS_SLOT_PENDING__ = window.__ABS_SLOT_PENDING__ ?? {};
230
+ const pending = window.__ABS_SLOT_PENDING__;
231
+ const apply = (id, html) => {
232
+ const node = document.getElementById(`slot-${id}`);
233
+ if (!node) {
234
+ pending[id] = html;
235
+ return;
236
+ }
237
+ node.innerHTML = html;
238
+ delete pending[id];
249
239
  };
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);
240
+ const flush = () => {
241
+ for (const id in pending) {
242
+ if (!Object.prototype.hasOwnProperty.call(pending, id))
243
+ continue;
244
+ apply(id, pending[id] ?? "");
245
+ }
246
+ };
247
+ window.__ABS_SLOT_ENQUEUE__ = (id, html) => {
248
+ apply(id, html);
249
+ };
250
+ if (typeof MutationObserver === "function") {
251
+ const observer = new MutationObserver(flush);
252
+ const root = document.documentElement ?? document.body ?? document;
253
+ observer.observe(root, { childList: true, subtree: true });
296
254
  }
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();
255
+ if (document.readyState === "loading") {
256
+ document.addEventListener("DOMContentLoaded", flush, { once: true });
257
+ }
258
+ flush();
259
+ }, stripFunctionWrapper = (value) => {
260
+ const start = value.indexOf("{");
261
+ const end = value.lastIndexOf("}");
262
+ if (start < 0 || end <= start)
263
+ return "";
264
+ return value.slice(start + 1, end);
265
+ }, getStreamSwapRuntimeScript = () => `(function(){${stripFunctionWrapper(streamSwapRuntime.toString())}})();`;
299
266
 
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)
267
+ // src/utils/escapeScriptContent.ts
268
+ var ESCAPE_LOOKUP, ESCAPE_REGEX, escapeScriptContent = (content) => content.replace(ESCAPE_REGEX, (char) => {
269
+ const escaped = ESCAPE_LOOKUP[char];
270
+ return escaped !== undefined ? escaped : char;
271
+ });
272
+ var init_escapeScriptContent = __esm(() => {
273
+ ESCAPE_LOOKUP = {
274
+ "\u2028": "\\u2028",
275
+ "\u2029": "\\u2029",
276
+ "&": "\\u0026",
277
+ "<": "\\u003C",
278
+ ">": "\\u003E"
279
+ };
280
+ ESCAPE_REGEX = /[&><\u2028\u2029]/g;
281
+ });
282
+
283
+ // src/utils/streamingSlots.ts
284
+ 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) => {
285
+ const closingHeadIndex = html.indexOf(CLOSING_HEAD_TAG2);
286
+ if (closingHeadIndex >= 0) {
287
+ return `${html.slice(0, closingHeadIndex)}${injection}${html.slice(closingHeadIndex)}`;
288
+ }
289
+ return `${html}${injection}`;
290
+ }, toUint8 = (value, encoder) => encoder.encode(value), currentStreamingSlotPolicy, clonePolicy = (policy) => ({
291
+ ...policy
292
+ }), normalizeSlotBytes = (value, fallback) => {
293
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
294
+ return Math.floor(value);
295
+ }
296
+ return fallback;
297
+ }, 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 = {}) => ({
298
+ timeoutMs: hasPolicyValue(overridePolicy, "timeoutMs") ? normalizeSlotBytes(overridePolicy.timeoutMs, base.timeoutMs) : base.timeoutMs,
299
+ fallbackHtml: hasPolicyValue(overridePolicy, "fallbackHtml") ? normalizeSlotText(overridePolicy.fallbackHtml, "") : base.fallbackHtml,
300
+ errorHtml: hasPolicyValue(overridePolicy, "errorHtml") ? normalizeSlotError(overridePolicy.errorHtml) : base.errorHtml,
301
+ maxSlotsPerResponse: hasPolicyValue(overridePolicy, "maxSlotsPerResponse") ? normalizeSlotBytes(overridePolicy.maxSlotsPerResponse, base.maxSlotsPerResponse) : base.maxSlotsPerResponse,
302
+ maxSlotHtmlSizeBytes: hasPolicyValue(overridePolicy, "maxSlotHtmlSizeBytes") ? normalizeSlotBytes(overridePolicy.maxSlotHtmlSizeBytes, base.maxSlotHtmlSizeBytes) : base.maxSlotHtmlSizeBytes,
303
+ onError: hasPolicyValue(overridePolicy, "onError") ? overridePolicy.onError : base.onError,
304
+ onSlotMetric: hasPolicyValue(overridePolicy, "onSlotMetric") ? overridePolicy.onSlotMetric : base.onSlotMetric
305
+ }), createCombinedSlotErrorHandler = (policyOnError, enhancerOnError) => {
306
+ if (!policyOnError && !enhancerOnError)
316
307
  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}).`);
308
+ return (error, slot) => {
309
+ policyOnError?.(error, slot);
310
+ enhancerOnError?.(error, slot);
311
+ };
312
+ }, createCombinedSlotMetricHandler = (policyOnSlotMetric, callOnSlotMetric) => {
313
+ if (!policyOnSlotMetric && !callOnSlotMetric)
384
314
  return;
315
+ return (metric) => {
316
+ policyOnSlotMetric?.(metric);
317
+ callOnSlotMetric?.(metric);
318
+ };
319
+ }, resolveStreamingSlotPolicy = (overridePolicy = {}) => {
320
+ const base = getStreamingSlotPolicy();
321
+ return applyStreamingSlotPolicyOverrides(base, overridePolicy);
322
+ }, getStreamingSlotPolicy = () => clonePolicy(currentStreamingSlotPolicy), setStreamingSlotPolicy = (policy = {}) => {
323
+ const base = getStreamingSlotPolicy();
324
+ currentStreamingSlotPolicy = applyStreamingSlotPolicyOverrides(base, policy);
325
+ }, withStreamingSlotPolicy = async (policy, callback) => {
326
+ const previous = getStreamingSlotPolicy();
327
+ setStreamingSlotPolicy(policy);
328
+ try {
329
+ return await callback();
330
+ } finally {
331
+ currentStreamingSlotPolicy = previous;
385
332
  }
386
- console.error(`[SSR] Failed to render ${framework} convention ${label} page:`, renderError);
387
- }, ERROR_RENDERERS, renderConventionError = async (framework, pageName, error) => {
388
- const conventionPath = resolveErrorConventionPath(framework, pageName);
389
- if (!conventionPath)
390
- return null;
391
- const errorProps = buildErrorProps(error);
392
- const renderer = ERROR_RENDERERS[framework];
393
- if (!renderer)
394
- return null;
395
- try {
396
- return await renderer(conventionPath, errorProps);
397
- } catch (renderError) {
398
- logConventionRenderError(framework, "error", renderError);
399
- }
400
- return null;
401
- }, renderReactNotFound = async (conventionPath) => {
402
- const { createElement } = await import("react");
403
- const { renderToReadableStream } = await import("react-dom/server");
404
- const mod = await import(conventionPath);
405
- const [nfKey] = Object.keys(mod);
406
- const NotFoundComponent = mod.default ?? (nfKey ? mod[nfKey] : undefined);
407
- const element = createElement(NotFoundComponent);
408
- const stream = await renderToReadableStream(element);
409
- return new Response(stream, {
410
- headers: { "Content-Type": "text/html" },
411
- status: 404
412
- });
413
- }, renderSvelteNotFound = async (conventionPath) => {
414
- const { render } = await import("svelte/server");
415
- const mod = await import(conventionPath);
416
- const NotFoundComponent = mod.default;
417
- const { head, body } = render(NotFoundComponent);
418
- const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
419
- return new Response(html, {
420
- headers: { "Content-Type": "text/html" },
421
- status: 404
422
- });
423
- }, renderVueNotFound = async (conventionPath) => {
424
- const { createSSRApp, h } = await import("vue");
425
- const { renderToString } = await import("vue/server-renderer");
426
- const mod = await import(conventionPath);
427
- const NotFoundComponent = mod.default;
428
- const app = createSSRApp({
429
- render: () => h(NotFoundComponent)
430
- });
431
- const rawBody = await renderToString(app);
432
- const { styles, body } = unescapeVueStyles(rawBody);
433
- const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
434
- return new Response(html, {
435
- headers: { "Content-Type": "text/html" },
436
- status: 404
437
- });
438
- }, renderAngularNotFound = async (conventionPath) => {
439
- const mod = await import(conventionPath);
440
- const renderNotFound = mod.default ?? mod.renderNotFound;
441
- if (typeof renderNotFound !== "function")
442
- return null;
443
- const html = renderNotFound();
444
- return new Response(html, {
445
- headers: { "Content-Type": "text/html" },
446
- status: 404
447
- });
448
- }, NOT_FOUND_RENDERERS, renderConventionNotFound = async (framework) => {
449
- const conventionPath = resolveNotFoundConventionPath(framework);
450
- if (!conventionPath)
451
- return null;
452
- const renderer = NOT_FOUND_RENDERERS[framework];
453
- if (!renderer)
454
- return null;
455
- try {
456
- return await renderer(conventionPath);
457
- } catch (renderError) {
458
- logConventionRenderError(framework, "not-found", renderError);
333
+ }, emitSlotMetric = (metric, onSlotMetric) => {
334
+ onSlotMetric?.(metric);
335
+ }, createTimeoutError = (slot, timeoutMs) => {
336
+ const error = new Error(`Streaming slot "${slot.id}" timed out after ${timeoutMs}ms`);
337
+ error.__absTimeout = true;
338
+ return error;
339
+ }, toStreamingSlot = (slot, policy) => ({
340
+ errorHtml: slot.errorHtml === undefined ? policy.errorHtml : slot.errorHtml,
341
+ fallbackHtml: normalizeSlotText(slot.fallbackHtml, policy.fallbackHtml),
342
+ id: slot.id ?? createStreamingSlotId(),
343
+ timeoutMs: normalizeSlotBytes(slot.timeoutMs, policy.timeoutMs),
344
+ resolve: slot.resolve
345
+ }), prepareSlots = ({
346
+ policy,
347
+ slots,
348
+ onError,
349
+ onSlotMetric
350
+ }) => {
351
+ const preparedSlots = slots.map((slot) => toStreamingSlot(slot, policy));
352
+ const maxSlotsPerResponse = policy.maxSlotsPerResponse;
353
+ if (maxSlotsPerResponse === 0) {
354
+ const error = new Error("Streaming slot limit is set to 0");
355
+ for (const slot of preparedSlots) {
356
+ onError?.(error, slot);
357
+ emitSlotMetric({
358
+ type: "dropped",
359
+ slotId: slot.id,
360
+ reason: "maxSlotsPerResponse is 0"
361
+ }, onSlotMetric);
362
+ }
363
+ return [];
459
364
  }
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;
365
+ if (preparedSlots.length <= maxSlotsPerResponse) {
366
+ preparedSlots.forEach((slot) => emitSlotMetric({
367
+ type: "prepared",
368
+ slotId: slot.id
369
+ }, onSlotMetric));
370
+ return preparedSlots;
468
371
  }
469
- return null;
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
- });
491
-
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" }
372
+ const keptSlots = preparedSlots.slice(0, maxSlotsPerResponse);
373
+ const droppedSlots = preparedSlots.slice(maxSlotsPerResponse);
374
+ droppedSlots.forEach((slot) => {
375
+ onError?.(new Error(`Streaming slot "${slot.id}" dropped because ${maxSlotsPerResponse} slots is the configured maximum`), slot);
376
+ emitSlotMetric({
377
+ type: "dropped",
378
+ slotId: slot.id,
379
+ reason: `maxSlotsPerResponse is ${maxSlotsPerResponse}`
380
+ }, onSlotMetric);
501
381
  });
502
- }, handleReactPageRequest = async (PageComponent, index, ...props) => {
503
- const [maybeProps] = props;
504
- if (ssrDirty) {
505
- return buildDirtyResponse(index, maybeProps);
506
- }
382
+ keptSlots.forEach((slot) => emitSlotMetric({
383
+ type: "prepared",
384
+ slotId: slot.id
385
+ }, onSlotMetric));
386
+ return keptSlots;
387
+ }, htmlByteLength = (value, encoder) => encoder.encode(value).length, resolveSlot = async (slot, onError, policy, onSlotMetric) => {
388
+ const safePolicy = policy ?? getStreamingSlotPolicy();
389
+ const encoder = new TextEncoder;
390
+ const start = Date.now();
507
391
  try {
508
- const { createElement } = await import("react");
509
- const { renderToReadableStream } = await import("react-dom/server");
510
- const element = maybeProps !== undefined ? createElement(PageComponent, maybeProps) : createElement(PageComponent);
511
- const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
512
- const refreshSetup = "window.__REFRESH_BUFFER__=[];window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};window.$RefreshSig$=function(){return function(t){return t}};";
513
- const stream = await renderToReadableStream(element, {
514
- bootstrapModules: [index],
515
- bootstrapScriptContent: propsScript + refreshSetup || undefined,
516
- onError(error) {
517
- console.error("[SSR] React streaming error:", error);
518
- }
519
- });
520
- const htmlStream = injectIslandPageContextStream(stream);
521
- return new Response(htmlStream, {
522
- headers: { "Content-Type": "text/html" }
523
- });
392
+ const maybeAsyncValue = Promise.resolve(slot.resolve());
393
+ const resolved = typeof slot.timeoutMs === "number" && slot.timeoutMs > 0 ? await Promise.race([
394
+ maybeAsyncValue,
395
+ new Promise((_, reject) => setTimeout(() => {
396
+ reject(createTimeoutError(slot, slot.timeoutMs ?? 0));
397
+ }, slot.timeoutMs))
398
+ ]) : await maybeAsyncValue;
399
+ const html = typeof resolved === "string" ? resolved : `${resolved}`;
400
+ if (safePolicy.maxSlotHtmlSizeBytes > 0 && htmlByteLength(html, encoder) > safePolicy.maxSlotHtmlSizeBytes) {
401
+ const bytes2 = htmlByteLength(html, encoder);
402
+ const error = new Error(`Streaming slot "${slot.id}" exceeded max payload size of ${safePolicy.maxSlotHtmlSizeBytes} bytes`);
403
+ const durationMs2 = Date.now() - start;
404
+ onError?.(error, slot);
405
+ emitSlotMetric({
406
+ type: "size_exceeded",
407
+ slotId: slot.id,
408
+ durationMs: durationMs2,
409
+ bytes: bytes2,
410
+ error
411
+ }, onSlotMetric);
412
+ const fallbackHtml = typeof slot.errorHtml === "string" ? slot.errorHtml : null;
413
+ return {
414
+ html: fallbackHtml,
415
+ id: slot.id,
416
+ durationMs: durationMs2,
417
+ bytes: fallbackHtml === null ? 0 : htmlByteLength(fallbackHtml, encoder)
418
+ };
419
+ }
420
+ const durationMs = Date.now() - start;
421
+ const bytes = htmlByteLength(html, encoder);
422
+ emitSlotMetric({
423
+ type: "resolved",
424
+ slotId: slot.id,
425
+ durationMs,
426
+ bytes
427
+ }, onSlotMetric);
428
+ return {
429
+ html,
430
+ id: slot.id,
431
+ durationMs,
432
+ bytes
433
+ };
524
434
  } catch (error) {
525
- console.error("[SSR] React render error:", error);
526
- const pageName = PageComponent.name || PageComponent.displayName || "";
527
- const conventionResponse = await renderConventionError("react", pageName, error);
528
- if (conventionResponse)
529
- return conventionResponse;
530
- return new Response(ssrErrorPage("react", error), {
531
- headers: { "Content-Type": "text/html" },
532
- status: 500
533
- });
435
+ const durationMs = Date.now() - start;
436
+ onError?.(error, slot);
437
+ emitSlotMetric({
438
+ type: error?.__absTimeout === true ? "timeout" : "error",
439
+ slotId: slot.id,
440
+ durationMs,
441
+ error
442
+ }, onSlotMetric);
443
+ if (typeof slot.errorHtml === "string") {
444
+ const html = slot.errorHtml;
445
+ return {
446
+ html,
447
+ id: slot.id,
448
+ durationMs,
449
+ bytes: htmlByteLength(html, encoder)
450
+ };
451
+ }
452
+ return {
453
+ html: null,
454
+ id: slot.id,
455
+ durationMs,
456
+ bytes: 0
457
+ };
534
458
  }
535
- }, invalidateReactSsrCache = () => {
536
- ssrDirty = true;
537
- };
538
- var init_pageHandler = __esm(() => {
539
- init_resolveConvention();
540
- });
541
-
542
- // src/core/islandManifest.ts
543
- var toIslandFrameworkSegment = (framework) => framework[0]?.toUpperCase() + framework.slice(1), collectFrameworkIslands = (manifest, prefix) => {
544
- const entries = {};
545
- let found = false;
546
- for (const [key, value] of Object.entries(manifest)) {
547
- if (!key.startsWith(prefix))
548
- continue;
549
- const component = key.slice(prefix.length);
550
- if (!component)
551
- continue;
552
- entries[component] = value;
553
- found = true;
554
- }
555
- return found ? entries : undefined;
556
- }, getIslandManifestEntries = (manifest) => {
557
- const islands = {};
558
- const frameworks = ["react", "svelte", "vue", "angular"];
559
- for (const framework of frameworks) {
560
- const prefix = `Island${toIslandFrameworkSegment(framework)}`;
561
- const entries = collectFrameworkIslands(manifest, prefix);
562
- if (entries)
563
- islands[framework] = entries;
564
- }
565
- return islands;
566
- }, getIslandManifestKey = (framework, component) => `Island${toIslandFrameworkSegment(framework)}${component}`;
567
-
568
- // src/core/islands.ts
569
- function getIslandComponent(component) {
570
- if (isIslandComponentDefinition(component)) {
571
- return component.component;
572
- }
573
- return component;
574
- }
575
- var defineIslandComponent = (component, options) => ({
576
- component,
577
- export: options.export,
578
- source: options.source
579
- }), defineIslandRegistry = (registry) => registry, isRecord = (value) => typeof value === "object" && value !== null, getIslandBuildReference = (component) => {
580
- if (!isIslandComponentDefinition(component))
581
- return null;
582
- return {
583
- export: component.export,
584
- source: component.source
585
- };
586
- }, isIslandComponentDefinition = (value) => isRecord(value) && ("component" in value) && ("source" in value) && typeof value.source === "string", parseIslandProps = (rawProps) => {
587
- if (!rawProps)
588
- return {};
589
- return JSON.parse(rawProps);
590
- }, serializeIslandProps = (props) => JSON.stringify(props ?? {});
591
- var init_islands = () => {};
592
-
593
- // src/core/islandMarkupAttributes.ts
594
- var getIslandMarkerAttributes = (props, islandId) => ({
595
- "data-component": props.component,
596
- "data-framework": props.framework,
597
- "data-hydrate": props.hydrate ?? "load",
598
- "data-island": "true",
599
- ...islandId ? { "data-island-id": islandId } : {},
600
- "data-props": serializeIslandProps(props.props)
601
- }), escapeHtmlAttribute = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"), serializeIslandAttributes = (attributes) => Object.entries(attributes).map(([key, value]) => `${key}="${escapeHtmlAttribute(value)}"`).join(" ");
602
- var init_islandMarkupAttributes = __esm(() => {
603
- init_islands();
604
- });
605
-
606
- // src/core/currentIslandRegistry.ts
607
- var requireCurrentIslandRegistry = () => {
608
- const registry = globalThis.__absoluteIslandRegistry;
609
- if (!registry) {
610
- throw new Error("No island registry is active. Configure `islands.registry` in absolute.config.ts before rendering <Island />.");
611
- }
612
- return registry;
613
- }, setCurrentIslandRegistry = (registry) => {
614
- globalThis.__absoluteIslandRegistry = registry;
615
- };
616
-
617
- // src/angular/injectorPatch.ts
618
- import { existsSync, readFileSync, writeFileSync } from "fs";
619
- import { dirname, join, resolve } from "path";
620
- var applyInjectorPatch = (chunkPath, content) => {
621
- if (content.includes('Symbol.for("angular.currentInjector")')) {
622
- return;
623
- }
624
- const original = [
625
- "let _currentInjector = undefined;",
626
- "function getCurrentInjector() {",
627
- " return _currentInjector;",
628
- "}",
629
- "function setCurrentInjector(injector) {",
630
- " const former = _currentInjector;",
631
- " _currentInjector = injector;",
632
- " return former;",
633
- "}"
634
- ].join(`
635
- `);
636
- const replacement = [
637
- 'const _injSym = Symbol.for("angular.currentInjector");',
638
- "if (!globalThis[_injSym]) globalThis[_injSym] = { v: undefined };",
639
- "function getCurrentInjector() {",
640
- " return globalThis[_injSym].v;",
641
- "}",
642
- "function setCurrentInjector(injector) {",
643
- " const former = globalThis[_injSym].v;",
644
- " globalThis[_injSym].v = injector;",
645
- " return former;",
646
- "}"
647
- ].join(`
648
- `);
649
- const patched = content.replace(original, replacement);
650
- if (patched === content) {
651
- return;
652
- }
653
- writeFileSync(chunkPath, patched, "utf-8");
654
- }, resolveAngularCoreDir = () => {
655
- const fromProject = resolve(process.cwd(), "node_modules/@angular/core");
656
- if (existsSync(join(fromProject, "package.json"))) {
657
- return fromProject;
658
- }
659
- return dirname(__require.resolve("@angular/core/package.json"));
660
- }, patchAngularInjectorSingleton = () => {
661
- try {
662
- const coreDir = resolveAngularCoreDir();
663
- const chunkPath = join(coreDir, "fesm2022", "_not_found-chunk.mjs");
664
- const content = readFileSync(chunkPath, "utf-8");
665
- applyInjectorPatch(chunkPath, content);
666
- } catch {}
667
- };
668
- var init_injectorPatch = __esm(() => {
669
- patchAngularInjectorSingleton();
670
- });
671
-
672
- // src/angular/resolveAngularPackage.ts
673
- import { existsSync as existsSync2 } from "fs";
674
- import { resolve as resolve2 } from "path";
675
- var resolveAngularPackage = (specifier) => {
676
- const fromProject = resolve2(process.cwd(), "node_modules", specifier);
677
- if (existsSync2(fromProject)) {
678
- return fromProject;
679
- }
680
- return specifier;
681
- };
682
- var init_resolveAngularPackage = () => {};
683
-
684
- // src/angular/angularPatch.ts
685
- var exports_angularPatch = {};
686
- __export(exports_angularPatch, {
687
- applyPatches: () => applyPatches
688
- });
689
- var ensureHead = (doc) => {
690
- if (!doc || doc.head || !doc.documentElement) {
691
- return;
692
- }
693
- const head = doc.createElement("head");
694
- doc.documentElement.insertBefore(head, doc.documentElement.firstChild);
695
- }, applyPatches = async () => {
696
- const { \u{275}DominoAdapter } = await import(resolveAngularPackage("@angular/platform-server"));
697
- if (!\u{275}DominoAdapter?.prototype) {
698
- console.warn("[Angular Patch] \u0275DominoAdapter not found, skipping patches");
699
- return false;
700
- }
701
- const proto = \u{275}DominoAdapter.prototype;
702
- const origGetBaseHref = proto.getBaseHref;
703
- proto.getBaseHref = function(doc) {
704
- if (!doc || !doc.head || typeof doc.head.children === "undefined") {
705
- return "";
706
- }
707
- return origGetBaseHref.call(this, doc);
708
- };
709
- const origCreateHtmlDocument = proto.createHtmlDocument;
710
- proto.createHtmlDocument = function() {
711
- const doc = origCreateHtmlDocument.call(this);
712
- ensureHead(doc);
713
- return doc;
714
- };
715
- const origGetDefaultDocument = proto.getDefaultDocument;
716
- proto.getDefaultDocument = function() {
717
- const doc = origGetDefaultDocument.call(this);
718
- ensureHead(doc);
719
- return doc;
720
- };
721
- return true;
722
- };
723
- var init_angularPatch = __esm(() => {
724
- init_resolveAngularPackage();
725
- });
726
-
727
- // src/angular/angularDeps.ts
728
- var initDominoAdapter = (platformServer) => {
729
- try {
730
- const DominoAdapter = platformServer.\u{275}DominoAdapter;
731
- DominoAdapter?.makeCurrent?.();
732
- } catch (err) {
733
- console.error("Failed to initialize DominoAdapter:", err);
734
- }
735
- }, loadAngularDeps = async () => {
736
- patchAngularInjectorSingleton();
737
- await import(resolveAngularPackage("@angular/compiler"));
738
- const { applyPatches: applyPatches2 } = await Promise.resolve().then(() => (init_angularPatch(), exports_angularPatch));
739
- await applyPatches2();
740
- const [platformBrowser, platformServer, common, core] = await Promise.all([
741
- import(resolveAngularPackage("@angular/platform-browser")),
742
- import(resolveAngularPackage("@angular/platform-server")),
743
- import(resolveAngularPackage("@angular/common")),
744
- import(resolveAngularPackage("@angular/core"))
745
- ]);
746
- if (false) {}
747
- initDominoAdapter(platformServer);
748
- return {
749
- APP_BASE_HREF: common.APP_BASE_HREF,
750
- bootstrapApplication: platformBrowser.bootstrapApplication,
751
- DomSanitizer: platformBrowser.DomSanitizer,
752
- provideClientHydration: platformBrowser.provideClientHydration,
753
- provideServerRendering: platformServer.provideServerRendering,
754
- provideZonelessChangeDetection: core.provideZonelessChangeDetection,
755
- reflectComponentType: core.reflectComponentType,
756
- renderApplication: platformServer.renderApplication,
757
- Sanitizer: core.Sanitizer,
758
- SecurityContext: core.SecurityContext
759
- };
760
- }, angularDeps = null, getAngularDeps = () => {
761
- if (!angularDeps) {
762
- angularDeps = loadAngularDeps();
763
- }
764
- return angularDeps;
765
- };
766
- var init_angularDeps = __esm(() => {
767
- init_injectorPatch();
768
- init_resolveAngularPackage();
769
- });
770
-
771
- // src/utils/registerClientScript.ts
772
- var scriptRegistry, requestCounter = 0, getRequestId = () => `req_${Date.now()}_${++requestCounter}`, ssrContextGetter = null, getSsrContextId = () => ssrContextGetter?.() || Object.getOwnPropertyDescriptor(globalThis, "__absolutejs_requestId")?.value, registerClientScript = (script, requestId) => {
773
- const id = requestId || getSsrContextId() || getRequestId();
774
- if (!scriptRegistry.has(id)) {
775
- scriptRegistry.set(id, new Set);
776
- }
777
- scriptRegistry.get(id)?.add(script);
778
- return id;
779
- }, setSsrContextGetter = (getter) => {
780
- ssrContextGetter = getter;
781
- }, clearAllClientScripts = () => {
782
- scriptRegistry.clear();
783
- }, generateClientScriptCode = (scripts) => {
784
- if (scripts.length === 0) {
785
- return "";
786
- }
787
- const scriptCode = scripts.map((script, index) => {
788
- const funcString = script.toString();
789
- const bodyMatch = funcString.match(/\{([\s\S]*)\}/);
790
- if (!bodyMatch || !bodyMatch[1]) {
791
- return "";
792
- }
793
- const body = bodyMatch[1].trim();
794
- return `
795
- (function() {
796
- var executed = false;
797
- function executeScript_${index}() {
798
- if (executed) return;
799
- executed = true;
800
- ${body}
801
- }
802
-
803
- if (document.readyState === 'complete' || document.readyState === 'interactive') {
804
- executeScript_${index}();
805
- } else {
806
- document.addEventListener('DOMContentLoaded', executeScript_${index});
807
- }
808
-
809
- // Watch for hydration-added elements
810
- var observer = new MutationObserver(function() {
811
- executeScript_${index}();
812
- if (executed) observer.disconnect();
813
- });
814
- if (!executed) {
815
- observer.observe(document.body || document.documentElement, { childList: true, subtree: true });
816
- }
817
-
818
- // Single fallback timeout
819
- setTimeout(function() {
820
- executeScript_${index}();
821
- observer.disconnect();
822
- }, 1000);
823
- })();`;
824
- }).join(`
825
- `);
826
- return `<script>
827
- (function() {
828
- ${scriptCode}
829
- })();
830
- </script>`;
831
- }, getAndClearClientScripts = (requestId) => {
832
- const id = requestId || ssrContextGetter?.();
833
- if (!id)
834
- return [];
835
- const scripts = scriptRegistry.get(id);
836
- if (!scripts) {
837
- return [];
838
- }
839
- const scriptArray = Array.from(scripts);
840
- scriptRegistry.delete(id);
841
- return scriptArray;
842
- };
843
- var init_registerClientScript = __esm(() => {
844
- scriptRegistry = new Map;
845
- if (typeof globalThis !== "undefined") {
846
- Object.assign(globalThis, { registerClientScript });
847
- }
848
- });
849
-
850
- // src/angular/ssrRender.ts
851
- var routePropsCache, cacheRouteData = (pagePath, data) => {
852
- const cacheKey = pagePath.split("?")[0] ?? pagePath;
853
- routePropsCache.set(cacheKey, data);
854
- }, getCachedRouteData = (pagePath) => routePropsCache.get(pagePath), selectorCache, buildDeps = (ssrResult, baseDeps) => {
855
- if (!ssrResult?.core) {
856
- return baseDeps;
857
- }
858
- const { common, core, platformBrowser, platformServer } = ssrResult;
859
- return {
860
- APP_BASE_HREF: common?.APP_BASE_HREF ?? baseDeps.APP_BASE_HREF,
861
- bootstrapApplication: platformBrowser?.bootstrapApplication ?? baseDeps.bootstrapApplication,
862
- DomSanitizer: platformBrowser?.DomSanitizer ?? baseDeps.DomSanitizer,
863
- provideClientHydration: platformBrowser?.provideClientHydration ?? baseDeps.provideClientHydration,
864
- provideServerRendering: platformServer?.provideServerRendering ?? baseDeps.provideServerRendering,
865
- provideZonelessChangeDetection: core.provideZonelessChangeDetection,
866
- reflectComponentType: core.reflectComponentType,
867
- renderApplication: platformServer?.renderApplication ?? baseDeps.renderApplication,
868
- Sanitizer: core.Sanitizer,
869
- SecurityContext: core.SecurityContext
459
+ }, nextResolvedSlot = async (pending) => {
460
+ const wrapped = pending.map((promise) => promise.then((result) => ({
461
+ original: promise,
462
+ result
463
+ })));
464
+ return Promise.race(wrapped);
465
+ }, streamChunkToString2 = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true }), streamOutOfOrderSlots = ({
466
+ footerHtml = "",
467
+ headerHtml = "",
468
+ nonce,
469
+ policy,
470
+ onSlotMetric,
471
+ onError,
472
+ slots
473
+ }) => {
474
+ const resolvedPolicy = resolveStreamingSlotPolicy(policy);
475
+ const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
476
+ const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
477
+ const effectivePolicy = {
478
+ ...resolvedPolicy,
479
+ onSlotMetric: combinedOnSlotMetric
870
480
  };
871
- }, buildProviders = (deps, sanitizer, maybeProps, tokenMap) => {
872
- const providers = [
873
- deps.provideServerRendering(),
874
- deps.provideClientHydration(),
875
- deps.provideZonelessChangeDetection(),
876
- { provide: deps.APP_BASE_HREF, useValue: "/" },
877
- {
878
- provide: deps.DomSanitizer,
879
- useValue: sanitizer
880
- },
881
- { provide: deps.Sanitizer, useValue: sanitizer }
882
- ];
883
- if (!maybeProps) {
884
- return providers;
885
- }
886
- const propProviders = Object.entries(maybeProps).map(([propName, propValue]) => ({
887
- token: tokenMap.get(toScreamingSnake(propName)),
888
- value: propValue
889
- })).filter((entry) => entry.token).map((entry) => ({ provide: entry.token, useValue: entry.value }));
890
- return [...providers, ...propProviders];
891
- }, clearSelectorCache = () => selectorCache.clear(), isInjectionToken = (value) => {
892
- if (!value || typeof value !== "object") {
893
- return false;
894
- }
895
- return "ngMetadataName" in value && value.ngMetadataName === "InjectionToken";
896
- }, discoverTokens = (pageModule) => new Map(Object.entries(pageModule).filter(([, value]) => isInjectionToken(value))), loadSsrDeps = async (pagePath) => {
897
- const ssrDepsPath = (pagePath.split("?")[0] ?? pagePath).replace(/\.js$/, ".ssr-deps.js");
898
- try {
899
- const ssrDeps = await import(ssrDepsPath);
900
- const result = {
901
- common: ssrDeps.__angularCommon,
902
- core: ssrDeps.__angularCore,
903
- platformBrowser: ssrDeps.__angularPlatformBrowser,
904
- platformServer: ssrDeps.__angularPlatformServer
905
- };
906
- return result;
907
- } catch {
908
- return null;
909
- }
910
- }, resolveSelector = (deps, pagePath, PageComponent) => {
911
- const cached = selectorCache.get(pagePath);
912
- if (cached) {
913
- return cached;
914
- }
915
- const selector = deps.reflectComponentType(PageComponent)?.selector ?? "ng-app";
916
- selectorCache.set(pagePath, selector);
917
- return selector;
918
- }, injectBeforeClose = (html, snippet) => {
919
- if (html.includes("</body>")) {
920
- return html.replace("</body>", `${snippet}</body>`);
921
- }
922
- if (html.includes("</html>")) {
923
- return html.replace("</html>", `${snippet}</html>`);
924
- }
925
- return html + snippet;
926
- }, injectSsrScripts = (html, requestId, indexPath, props) => {
927
- let result = html;
928
- const registeredScripts = getAndClearClientScripts(requestId);
929
- if (registeredScripts.length > 0) {
930
- result = injectBeforeClose(result, generateClientScriptCode(registeredScripts));
931
- }
932
- if (props) {
933
- result = injectBeforeClose(result, `<script>window.__ABS_ANGULAR_PAGE_PROPS__ = ${JSON.stringify(props)};</script>`);
934
- }
935
- if (indexPath) {
936
- result = injectBeforeClose(result, `<script type="module" src="${indexPath}"></script>`);
937
- }
938
- return result;
939
- }, renderAngularApp = async (deps, PageComponent, providers, document2) => {
940
- const bootstrap = (context) => deps.bootstrapApplication(PageComponent, { providers }, context);
941
- return withSuppressedAngularDevLogs(() => deps.renderApplication(bootstrap, {
942
- document: document2,
943
- platformProviders: [],
944
- url: "/"
945
- }));
946
- }, withSuppressedAngularDevLogs = async (render) => {
947
- const origLog = console.log;
948
- console.log = (...args) => {
949
- if (typeof args[0] === "string" && args[0].includes("development mode")) {
950
- return;
481
+ const preparedSlots = prepareSlots({
482
+ policy: effectivePolicy,
483
+ slots,
484
+ onError: combinedOnError,
485
+ onSlotMetric: combinedOnSlotMetric
486
+ });
487
+ const encoder = new TextEncoder;
488
+ return new ReadableStream({
489
+ async start(controller) {
490
+ try {
491
+ let header = headerHtml;
492
+ if (preparedSlots.length > 0 && !header.includes(STREAMING_RUNTIME_GLOBAL)) {
493
+ header = injectHtmlIntoHead(header, renderStreamingSlotsRuntimeTag(nonce));
494
+ }
495
+ controller.enqueue(toUint8(header, encoder));
496
+ const pending = preparedSlots.map((slot) => {
497
+ const fallback = renderStreamingSlotPlaceholder(slot.id, slot.fallbackHtml ?? "");
498
+ controller.enqueue(toUint8(fallback, encoder));
499
+ return resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric);
500
+ });
501
+ while (pending.length > 0) {
502
+ const { original, result } = await nextResolvedSlot(pending);
503
+ const index = pending.indexOf(original);
504
+ if (index >= 0)
505
+ pending.splice(index, 1);
506
+ if (result.html === null)
507
+ continue;
508
+ emitSlotMetric({
509
+ type: "patched",
510
+ slotId: result.id,
511
+ durationMs: result.durationMs,
512
+ bytes: result.bytes
513
+ }, combinedOnSlotMetric);
514
+ controller.enqueue(toUint8(renderStreamingSlotPatchTag(result.id, result.html, nonce), encoder));
515
+ }
516
+ if (footerHtml.length > 0) {
517
+ controller.enqueue(toUint8(footerHtml, encoder));
518
+ }
519
+ controller.close();
520
+ } catch (error) {
521
+ controller.error(error);
522
+ }
951
523
  }
952
- origLog.apply(console, args);
953
- };
954
- try {
955
- return await render();
956
- } finally {
957
- console.log = origLog;
958
- }
959
- };
960
- var init_ssrRender = __esm(() => {
961
- init_registerClientScript();
962
- routePropsCache = new Map;
963
- selectorCache = new Map;
964
- });
965
-
966
- // src/angular/islands.ts
967
- var angularIslandSelector = "abs-angular-island", getAngularIslandSelector = (_islandId) => angularIslandSelector, getSelectorFromRenderedIsland = (rootElement) => {
968
- const firstChild = rootElement.firstElementChild;
969
- if (!(firstChild instanceof HTMLElement)) {
970
- return null;
971
- }
972
- const selector = firstChild.tagName.toLowerCase();
973
- return selector.length > 0 ? selector : null;
974
- }, getClientAngularComponentSelector = (component) => {
975
- const maybeDef = Reflect.get(component, "\u0275cmp");
976
- if (typeof maybeDef !== "object" || maybeDef === null) {
977
- return null;
978
- }
979
- const maybeSelectors = Reflect.get(maybeDef, "selectors");
980
- if (!Array.isArray(maybeSelectors)) {
981
- return null;
982
- }
983
- const [firstSelectorGroup] = maybeSelectors;
984
- if (!Array.isArray(firstSelectorGroup)) {
985
- return null;
986
- }
987
- const [selector] = firstSelectorGroup;
988
- return typeof selector === "string" && selector.length > 0 ? selector : null;
989
- }, createAngularIslandApp = async () => {
990
- const { EnvironmentInjector, provideZonelessChangeDetection } = await import("@angular/core");
991
- const { createApplication } = await import("@angular/platform-browser");
992
- const app = await createApplication({
993
- providers: [provideZonelessChangeDetection()]
994
524
  });
995
- const environmentInjector = app.injector.get(EnvironmentInjector);
996
- return { app, environmentInjector };
997
- }, angularIslandAppPromise = null, getAngularIslandApp = async () => {
998
- if (!angularIslandAppPromise) {
999
- angularIslandAppPromise = createAngularIslandApp();
1000
- }
1001
- return angularIslandAppPromise;
1002
- }, wrapperMetadataCache, requestRenderCache, getRequestRenderCache = () => {
1003
- const requestId = getSsrContextId();
1004
- if (!requestId) {
1005
- return null;
1006
- }
1007
- const cached = requestRenderCache.get(requestId);
1008
- if (cached) {
1009
- return cached;
1010
- }
1011
- const renderCache = new Map;
1012
- requestRenderCache.set(requestId, renderCache);
1013
- return renderCache;
1014
- }, getAngularIslandWrapperKey = (component, _islandId) => {
1015
- const componentName = typeof component.name === "string" && component.name.length > 0 ? component.name : "AngularIsland";
1016
- return `${componentName}:${angularIslandSelector}`;
1017
- }, getIslandRenderCacheKey = (component, props) => {
1018
- const componentName = typeof component.name === "string" && component.name.length > 0 ? component.name : "AngularIsland";
1019
- return `${componentName}:${JSON.stringify(props)}`;
1020
- }, buildAngularIslandWrapperMetadata = async (component, islandId, wrapperKey) => {
1021
- const { Component, InjectionToken, inject } = await import("@angular/core");
1022
- const { NgComponentOutlet } = await import("@angular/common");
1023
- const deps = await getAngularDeps();
1024
- const selector = getAngularIslandSelector(islandId);
1025
- const propsToken = new InjectionToken(`${wrapperKey}:props`);
1026
-
1027
- class AngularIslandWrapperComponent {
1028
- component = component;
1029
- props = inject(propsToken);
1030
- }
1031
- return {
1032
- deps,
1033
- propsToken,
1034
- selector,
1035
- WrapperComponent: Component({
1036
- imports: [NgComponentOutlet, component],
1037
- selector,
1038
- standalone: true,
1039
- template: '<ng-container *ngComponentOutlet="component; inputs: props"></ng-container>'
1040
- })(AngularIslandWrapperComponent)
525
+ }, injectStreamingRuntimeIntoStream = (stream, nonce) => {
526
+ const runtimeTag = renderStreamingSlotsRuntimeTag(nonce);
527
+ const encoder = new TextEncoder;
528
+ const decoder = new TextDecoder;
529
+ const lookbehind = CLOSING_HEAD_TAG_LENGTH - 1;
530
+ return new ReadableStream({
531
+ async start(controller) {
532
+ const reader = stream.getReader();
533
+ let injected = false;
534
+ let pending = "";
535
+ try {
536
+ for (;; ) {
537
+ const { done, value } = await reader.read();
538
+ if (done)
539
+ break;
540
+ if (!value)
541
+ continue;
542
+ pending += streamChunkToString2(value, decoder);
543
+ if (injected) {
544
+ controller.enqueue(encoder.encode(pending));
545
+ pending = "";
546
+ continue;
547
+ }
548
+ const headIndex = pending.indexOf(CLOSING_HEAD_TAG2);
549
+ if (headIndex >= 0) {
550
+ const withRuntime = `${pending.slice(0, headIndex)}${runtimeTag}${pending.slice(headIndex)}`;
551
+ controller.enqueue(encoder.encode(withRuntime));
552
+ pending = "";
553
+ injected = true;
554
+ continue;
555
+ }
556
+ if (pending.length > lookbehind) {
557
+ const safeText = pending.slice(0, pending.length - lookbehind);
558
+ controller.enqueue(encoder.encode(safeText));
559
+ pending = pending.slice(-lookbehind);
560
+ }
561
+ }
562
+ pending += decoder.decode();
563
+ if (!injected) {
564
+ pending = injectHtmlIntoHead(pending, runtimeTag);
565
+ }
566
+ if (pending.length > 0) {
567
+ controller.enqueue(encoder.encode(pending));
568
+ }
569
+ controller.close();
570
+ } catch (error) {
571
+ controller.error(error);
572
+ }
573
+ }
574
+ });
575
+ }, appendStreamingSlotPatchesToStream = (stream, slots = [], {
576
+ injectRuntime = true,
577
+ nonce,
578
+ onError,
579
+ onSlotMetric,
580
+ policy
581
+ } = {}) => {
582
+ const resolvedPolicy = resolveStreamingSlotPolicy(policy);
583
+ const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
584
+ const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
585
+ const effectivePolicy = {
586
+ ...resolvedPolicy,
587
+ onSlotMetric: combinedOnSlotMetric
1041
588
  };
1042
- }, createAngularIslandWrapper = async (component, islandId) => {
1043
- const wrapperKey = getAngularIslandWrapperKey(component, islandId);
1044
- const cached = wrapperMetadataCache.get(wrapperKey);
1045
- if (cached) {
1046
- return cached;
1047
- }
1048
- const metadataPromise = buildAngularIslandWrapperMetadata(component, islandId, wrapperKey);
1049
- wrapperMetadataCache.set(wrapperKey, metadataPromise);
1050
- return metadataPromise;
1051
- }, extractAngularIslandRoot = (html, selector) => {
1052
- const openTag = `<${selector}`;
1053
- const start = html.indexOf(openTag);
1054
- if (start < 0) {
1055
- throw new Error(`Could not find Angular island root "${selector}".`);
1056
- }
1057
- const endTag = `</${selector}>`;
1058
- const end = html.indexOf(endTag, start);
1059
- if (end < 0) {
1060
- throw new Error(`Could not close Angular island root "${selector}".`);
1061
- }
1062
- return html.slice(start, end + endTag.length);
1063
- }, mountAngularIsland = async (component, element, props, islandId) => {
1064
- await import("@angular/compiler");
1065
- const { createComponent, inputBinding } = await import("@angular/core");
1066
- const selector = getAngularIslandSelector(islandId);
1067
- const { app, environmentInjector } = await getAngularIslandApp();
1068
- let rootElement = element.querySelector(selector);
1069
- if (!(rootElement instanceof HTMLElement)) {
1070
- element.innerHTML = `<${selector}></${selector}>`;
1071
- rootElement = element.querySelector(selector);
1072
- }
1073
- if (!(rootElement instanceof HTMLElement))
1074
- return app;
1075
- const componentSelector = getClientAngularComponentSelector(component) ?? getSelectorFromRenderedIsland(rootElement);
1076
- if (!componentSelector)
1077
- return app;
1078
- rootElement.innerHTML = `<${componentSelector}></${componentSelector}>`;
1079
- const hostElement = rootElement.querySelector(componentSelector);
1080
- if (!(hostElement instanceof HTMLElement))
1081
- return app;
1082
- const bindings = Object.entries(props).map(([key, value]) => inputBinding(key, () => value));
1083
- const componentRef = createComponent(component, {
1084
- bindings,
1085
- environmentInjector,
1086
- hostElement
589
+ const preparedSlots = prepareSlots({
590
+ policy: effectivePolicy,
591
+ slots,
592
+ onError: combinedOnError,
593
+ onSlotMetric: combinedOnSlotMetric
1087
594
  });
1088
- app.attachView(componentRef.hostView);
1089
- componentRef.changeDetectorRef.detectChanges();
1090
- window.__ABS_ANGULAR_ISLAND_APPS__ ??= [];
1091
- window.__ABS_ANGULAR_ISLAND_APPS__.push(app);
1092
- return app;
1093
- }, renderAngularIslandToHtml = async (component, props, islandId) => {
1094
- const requestCache = getRequestRenderCache();
1095
- const renderCacheKey = getIslandRenderCacheKey(component, props);
1096
- const cachedHtml = requestCache?.get(renderCacheKey);
1097
- if (cachedHtml) {
1098
- return cachedHtml;
1099
- }
1100
- const { deps, propsToken, selector, WrapperComponent } = await createAngularIslandWrapper(component, islandId);
1101
- const providers = [
1102
- deps.provideServerRendering(),
1103
- deps.provideZonelessChangeDetection(),
1104
- { provide: deps.APP_BASE_HREF, useValue: "/" },
1105
- { provide: propsToken, useValue: props }
1106
- ];
1107
- const document2 = `<!DOCTYPE html><html><body><${selector}></${selector}></body></html>`;
1108
- const html = await withSuppressedAngularDevLogs(() => deps.renderApplication((context) => deps.bootstrapApplication(WrapperComponent, { providers }, context), {
1109
- document: document2,
1110
- platformProviders: [],
1111
- url: "/"
1112
- }));
1113
- const islandHtml = extractAngularIslandRoot(html, selector);
1114
- requestCache?.set(renderCacheKey, islandHtml);
1115
- return islandHtml;
1116
- };
1117
- var init_islands2 = __esm(() => {
1118
- init_angularDeps();
1119
- init_ssrRender();
1120
- init_registerClientScript();
1121
- wrapperMetadataCache = new Map;
1122
- requestRenderCache = new Map;
1123
- });
1124
-
1125
- // src/core/islandSsr.ts
1126
- import { createElement } from "react";
1127
- import { renderToStaticMarkup } from "react-dom/server";
1128
- import { render as renderSvelte } from "svelte/server";
1129
- import { createSSRApp, h } from "vue";
1130
- import { renderToString as renderVueToString } from "vue/server-renderer";
1131
- var renderReactIslandToHtml = (component, props) => renderToStaticMarkup(createElement(component, props)), renderSvelteIslandToHtml = (component, props) => {
1132
- const { body } = renderSvelte(component, { props });
1133
- return body;
1134
- }, renderVueIslandToHtml = (component, props) => {
1135
- const app = createSSRApp({
1136
- render: () => h(component, props)
595
+ if (preparedSlots.length === 0)
596
+ return stream;
597
+ const source = injectRuntime ? injectStreamingRuntimeIntoStream(stream, nonce) : stream;
598
+ const encoder = new TextEncoder;
599
+ const decoder = new TextDecoder;
600
+ const reader = source.getReader();
601
+ const pending = preparedSlots.map((slot) => resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric));
602
+ return new ReadableStream({
603
+ async start(controller) {
604
+ let baseDone = false;
605
+ let baseRead = reader.read();
606
+ let tail = "";
607
+ let footer = "";
608
+ try {
609
+ while (!baseDone || pending.length > 0) {
610
+ const racers = [];
611
+ if (!baseDone) {
612
+ racers.push(baseRead.then(({ done, value }) => ({
613
+ done,
614
+ kind: "base",
615
+ value
616
+ })));
617
+ }
618
+ if (pending.length > 0) {
619
+ racers.push(nextResolvedSlot(pending).then((resolved) => ({
620
+ kind: "slot",
621
+ ...resolved
622
+ })));
623
+ }
624
+ if (racers.length === 0)
625
+ break;
626
+ const winner = await Promise.race(racers);
627
+ if (winner.kind === "base") {
628
+ if (winner.done) {
629
+ baseDone = true;
630
+ tail += decoder.decode();
631
+ const footerStart = tail.search(CLOSING_PAGE_TAG_REGEX);
632
+ if (footerStart >= 0) {
633
+ const content = tail.slice(0, footerStart);
634
+ footer = tail.slice(footerStart);
635
+ if (content.length > 0) {
636
+ controller.enqueue(encoder.encode(content));
637
+ }
638
+ } else if (tail.length > 0) {
639
+ controller.enqueue(encoder.encode(tail));
640
+ }
641
+ tail = "";
642
+ } else if (winner.value) {
643
+ tail += streamChunkToString2(winner.value, decoder);
644
+ if (tail.length > STREAM_TAIL_LOOKBEHIND) {
645
+ const content = tail.slice(0, tail.length - STREAM_TAIL_LOOKBEHIND);
646
+ controller.enqueue(encoder.encode(content));
647
+ tail = tail.slice(-STREAM_TAIL_LOOKBEHIND);
648
+ }
649
+ baseRead = reader.read();
650
+ }
651
+ continue;
652
+ }
653
+ const index = pending.indexOf(winner.original);
654
+ if (index >= 0)
655
+ pending.splice(index, 1);
656
+ if (winner.result.html === null)
657
+ continue;
658
+ emitSlotMetric({
659
+ type: "patched",
660
+ slotId: winner.result.id,
661
+ durationMs: winner.result.durationMs,
662
+ bytes: winner.result.bytes
663
+ }, combinedOnSlotMetric);
664
+ controller.enqueue(encoder.encode(renderStreamingSlotPatchTag(winner.result.id, winner.result.html, nonce)));
665
+ }
666
+ if (footer.length > 0)
667
+ controller.enqueue(encoder.encode(footer));
668
+ controller.close();
669
+ } catch (error) {
670
+ controller.error(error);
671
+ }
672
+ }
1137
673
  });
1138
- return renderVueToString(app);
1139
674
  };
1140
- var init_islandSsr = __esm(() => {
1141
- init_islands2();
675
+ var init_streamingSlots = __esm(() => {
676
+ init_escapeScriptContent();
677
+ CLOSING_HEAD_TAG_LENGTH = CLOSING_HEAD_TAG2.length;
678
+ CLOSING_PAGE_TAG_REGEX = /<\/body>\s*<\/html>\s*$/i;
679
+ currentStreamingSlotPolicy = {
680
+ timeoutMs: STREAMING_SLOT_TIMEOUT_MS,
681
+ fallbackHtml: "",
682
+ errorHtml: undefined,
683
+ maxSlotsPerResponse: STREAMING_SLOT_MAX_PER_RESPONSE,
684
+ maxSlotHtmlSizeBytes: STREAMING_SLOT_MAX_HTML_BYTES
685
+ };
1142
686
  });
1143
687
 
1144
- // src/constants.ts
1145
- var ANGULAR_INIT_TIMEOUT_MS = 500, ANSI_ESCAPE_LENGTH = 3, ASCII_SPACE = 32, BASE_36_RADIX = 36, BUN_BUILD_WARNING_SUPPRESSION = "wildcard sideEffects are not supported yet", BODY_SLICE_LENGTH = 2000, BYTES_PER_KILOBYTE = 1024, CLI_ARGS_OFFSET = 3, CSS_ERROR_RESOLVE_DELAY_MS = 50, CSS_MAX_CHECK_ATTEMPTS = 10, CSS_MAX_PARSE_TIMEOUT_MS = 500, CSS_SHEET_READY_TIMEOUT_MS = 100, DEFAULT_CHUNK_SIZE = 16384, DEFAULT_DEBOUNCE_MS = 15, DEFAULT_PORT = 3000, DEV_SERVER_RESTART_DEBOUNCE_MS = 100, DOM_UPDATE_DELAY_MS = 50, FILE_PROTOCOL_PREFIX_LENGTH = 7, FOCUS_ID_PREFIX_LENGTH = 3, FOCUS_IDX_PREFIX_LENGTH = 4, FOCUS_NAME_PREFIX_LENGTH = 5, HMR_UPDATE_TIMEOUT_MS = 2000, HOOK_SIGNATURE_LENGTH = 12, EXCLUDE_LAST_OFFSET = -1, HOURS_IN_DAY = 24, HOURS_IN_HALF_DAY = 12, MAX_ERROR_LENGTH = 200, MAX_RECONNECT_ATTEMPTS = 60, MILLISECONDS_IN_A_SECOND = 1000, MINUTES_IN_AN_HOUR = 60, SECONDS_IN_A_MINUTE = 60, MILLISECONDS_IN_A_MINUTE, MILLISECONDS_IN_A_DAY, OVERLAY_FADE_DURATION_MS = 150, PING_INTERVAL_MS = 30000, RAF_BATCH_COUNT = 3, RANDOM_ID_END_INDEX = 11, REBUILD_BATCH_DELAY_MS = 10, REBUILD_RELOAD_DELAY_MS = 200, RECONNECT_INITIAL_DELAY_MS = 500, RECONNECT_POLL_INTERVAL_MS = 300, SIGINT_EXIT_CODE = 130, SIGTERM_EXIT_CODE = 143, SVELTE_CSS_LOAD_TIMEOUT_MS = 500, TIME_PRECISION = 2, TWO_THIRDS, UNFOUND_INDEX = -1, WEBSOCKET_NORMAL_CLOSURE = 1000;
1146
- var init_constants = __esm(() => {
1147
- MILLISECONDS_IN_A_MINUTE = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE;
1148
- MILLISECONDS_IN_A_DAY = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE * MINUTES_IN_AN_HOUR * HOURS_IN_DAY;
1149
- TWO_THIRDS = 2 / 3;
1150
- });
688
+ // src/core/streamingSlotRegistrar.ts
689
+ var registrar = null, setStreamingSlotRegistrar = (nextRegistrar) => {
690
+ registrar = nextRegistrar;
691
+ }, registerStreamingSlot = (slot) => {
692
+ registrar?.(slot);
693
+ };
1151
694
 
1152
- // src/svelte/lowerIslandSyntax.ts
1153
- var ISLAND_TAG_RE, extractBracedExpression = (text, braceStart) => {
1154
- let depth = 0;
1155
- for (let index = braceStart;index < text.length; index += 1) {
1156
- const char = text[index];
1157
- if (char === "{")
1158
- depth += 1;
1159
- if (char === "}")
1160
- depth -= 1;
1161
- if (depth === 0) {
1162
- return text.slice(braceStart + 1, index).trim();
1163
- }
1164
- }
1165
- return null;
1166
- }, extractIslandAttribute = (attributeString, name) => {
1167
- const quotedMatch = attributeString.match(new RegExp(`\\b${name}\\s*=\\s*["']([^"']+)["']`));
1168
- if (quotedMatch?.[1]) {
1169
- return { expression: JSON.stringify(quotedMatch[1]), found: true };
1170
- }
1171
- const attributeIndex = attributeString.search(new RegExp(`\\b${name}\\s*=\\s*\\{`));
1172
- if (attributeIndex < 0) {
1173
- return { expression: "", found: false };
1174
- }
1175
- const braceStart = attributeString.indexOf("{", attributeIndex);
1176
- if (braceStart < 0) {
1177
- return { expression: "", found: false };
1178
- }
1179
- const expression = extractBracedExpression(attributeString, braceStart);
1180
- if (expression === null) {
1181
- return { expression: "", found: false };
695
+ // src/core/streamingSlotRegistry.ts
696
+ var asyncLocalStorage, isServerRuntime = () => typeof process !== "undefined" && typeof process.versions?.node === "string", ensureAsyncLocalStorage = async () => {
697
+ if (typeof asyncLocalStorage !== "undefined")
698
+ return asyncLocalStorage;
699
+ if (!isServerRuntime()) {
700
+ asyncLocalStorage = null;
701
+ return asyncLocalStorage;
1182
702
  }
1183
- return { expression, found: true };
1184
- }, lowerSvelteIslandSyntax = (source, _mode = "server") => {
1185
- if (!source.includes("<Island")) {
1186
- return { code: source, transformed: false };
703
+ const mod = await import("async_hooks");
704
+ asyncLocalStorage = new mod.AsyncLocalStorage;
705
+ return asyncLocalStorage;
706
+ }, registerStreamingSlot2 = (slot) => {
707
+ if (!asyncLocalStorage)
708
+ return;
709
+ const store = asyncLocalStorage.getStore();
710
+ if (!store)
711
+ return;
712
+ store.set(slot.id, slot);
713
+ }, runWithStreamingSlotRegistry = async (task) => {
714
+ const storage = await ensureAsyncLocalStorage();
715
+ if (!storage) {
716
+ return {
717
+ result: await task(),
718
+ slots: []
719
+ };
1187
720
  }
1188
- let islandIndex = 0;
1189
- const transformedMarkup = source.replace(ISLAND_TAG_RE, (fullMatch, attributeString) => {
1190
- const framework = extractIslandAttribute(attributeString, "framework");
1191
- const component = extractIslandAttribute(attributeString, "component");
1192
- if (!framework.found || !component.found) {
1193
- return fullMatch;
1194
- }
1195
- const hydrate = extractIslandAttribute(attributeString, "hydrate");
1196
- const props = extractIslandAttribute(attributeString, "props");
1197
- const slotId = `absolute-svelte-island-${islandIndex.toString(BASE_36_RADIX)}`;
1198
- islandIndex += 1;
1199
- const resolveExpression = `await __absoluteResolveIslandHtml(${JSON.stringify(slotId)}, { component: ${component.expression}, framework: ${framework.expression}, hydrate: ${hydrate.found ? hydrate.expression : JSON.stringify("load")}, props: ${props.found ? props.expression : "{}"} })`;
1200
- return `<div data-absolute-island-slot="${slotId}" style="display: contents">{@html ${resolveExpression}}</div>`;
1201
- });
1202
- const importLine = 'import { resolveIslandHtml as __absoluteResolveIslandHtml } from "@absolutejs/absolute/svelte";';
1203
- if (transformedMarkup.includes("<script")) {
721
+ return storage.run(new Map, async () => {
722
+ const result = await task();
723
+ const store = storage.getStore();
1204
724
  return {
1205
- code: transformedMarkup.replace(/<script(\s[^>]*)?>/, (match) => `${match}
1206
- ${importLine}
1207
- `),
1208
- transformed: true
725
+ result,
726
+ slots: store ? [...store.values()] : []
1209
727
  };
728
+ });
729
+ };
730
+ var init_streamingSlotRegistry = __esm(() => {
731
+ setStreamingSlotRegistrar(registerStreamingSlot2);
732
+ });
733
+
734
+ // src/core/responseEnhancers.ts
735
+ var toResponse = async (responseLike) => await responseLike, cloneHeaders = (response) => {
736
+ const headers = new Headers(response.headers);
737
+ return headers;
738
+ }, enhanceHtmlResponseWithStreamingSlots = (response, { nonce, onError, streamingSlots = [], policy } = {}) => {
739
+ if (!response.body || streamingSlots.length === 0) {
740
+ return response;
1210
741
  }
1211
- return {
1212
- code: `<script lang="ts">
1213
- ${importLine}
1214
- </script>
1215
- ${transformedMarkup}`,
1216
- transformed: true
1217
- };
742
+ const body = appendStreamingSlotPatchesToStream(response.body, streamingSlots, {
743
+ nonce,
744
+ onError,
745
+ policy
746
+ });
747
+ return new Response(body, {
748
+ headers: cloneHeaders(response),
749
+ status: response.status,
750
+ statusText: response.statusText
751
+ });
752
+ }, withStreamingSlots = async (responseLike, options = {}) => enhanceHtmlResponseWithStreamingSlots(await toResponse(responseLike), options), mergeStreamingSlots = (registered, explicit) => {
753
+ const merged = new Map;
754
+ for (const slot of registered)
755
+ merged.set(slot.id, slot);
756
+ for (const slot of explicit)
757
+ merged.set(slot.id, slot);
758
+ return [...merged.values()];
759
+ }, withRegisteredStreamingSlots = async (renderResponse, options = {}) => {
760
+ const { result, slots } = await runWithStreamingSlotRegistry(renderResponse);
761
+ const explicit = options.streamingSlots ?? [];
762
+ return withStreamingSlots(result, {
763
+ ...options,
764
+ streamingSlots: mergeStreamingSlots(slots, explicit)
765
+ });
1218
766
  };
1219
- var init_lowerIslandSyntax = __esm(() => {
1220
- init_constants();
1221
- ISLAND_TAG_RE = /<Island\b([\s\S]*?)\/>/g;
767
+ var init_responseEnhancers = __esm(() => {
768
+ init_streamingSlots();
769
+ init_streamingSlotRegistry();
1222
770
  });
1223
771
 
1224
- // src/core/svelteServerModule.ts
1225
- import { mkdir, readdir } from "fs/promises";
1226
- import { basename as basename2, dirname as dirname2, extname, join as join2, relative, resolve as resolve3 } from "path";
1227
- var serverCacheRoot, compiledModuleCache, originalSourcePathCache, transpiler, ensureRelativeImportPath = (from, target) => {
1228
- const importPath = relative(dirname2(from), target).replace(/\\/g, "/");
1229
- return importPath.startsWith(".") ? importPath : `./${importPath}`;
1230
- }, processDirectoryEntries = (entries, dir, targetFileName, stack) => {
1231
- for (const entry of entries) {
1232
- const entryPath = join2(dir, entry.name);
1233
- if (entry.isDirectory())
1234
- stack.push(entryPath);
1235
- if (entry.isFile() && entry.name === targetFileName) {
1236
- return entryPath;
1237
- }
772
+ // src/utils/ssrErrorPage.ts
773
+ var ssrErrorPage = (framework, error) => {
774
+ const frameworkColors = {
775
+ angular: "#dd0031",
776
+ html: "#e34c26",
777
+ htmx: "#1a365d",
778
+ react: "#61dafb",
779
+ svelte: "#ff3e00",
780
+ vue: "#42b883"
781
+ };
782
+ const accent = frameworkColors[framework] ?? "#94a3b8";
783
+ const label = framework.charAt(0).toUpperCase() + framework.slice(1);
784
+ const message = error instanceof Error ? error.message : String(error);
785
+ return `<!DOCTYPE html>
786
+ <html>
787
+ <head>
788
+ <meta charset="utf-8">
789
+ <meta name="viewport" content="width=device-width, initial-scale=1">
790
+ <title>SSR Error - AbsoluteJS</title>
791
+ <style>
792
+ *{margin:0;padding:0;box-sizing:border-box}
793
+ 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}
794
+ .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}
795
+ .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)}
796
+ .brand{font-weight:700;font-size:20px;color:#fff;letter-spacing:-0.02em}
797
+ .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)}
798
+ .kind{color:#94a3b8;font-size:13px;font-weight:500}
799
+ .content{padding:24px}
800
+ .label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.08em;color:#94a3b8;margin-bottom:8px}
801
+ .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}
802
+ .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}
803
+ </style>
804
+ </head>
805
+ <body>
806
+ <div class="card">
807
+ <div class="header">
808
+ <div style="display:flex;align-items:center;gap:12px">
809
+ <span class="brand">AbsoluteJS</span>
810
+ <span class="badge">${label}</span>
811
+ </div>
812
+ <span class="kind">Server Render Error</span>
813
+ </div>
814
+ <div class="content">
815
+ <div class="label">What went wrong</div>
816
+ <pre class="message">${message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")}</pre>
817
+ <div class="hint">A component threw during server-side rendering. Check the terminal for the full stack trace.</div>
818
+ </div>
819
+ </div>
820
+ </body>
821
+ </html>`;
822
+ };
823
+
824
+ // src/utils/stringModifiers.ts
825
+ 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) => {
826
+ if (!str.includes("-") && !str.includes("_")) {
827
+ return str.charAt(0).toUpperCase() + str.slice(1);
1238
828
  }
1239
- return null;
1240
- }, searchDirectoryLevel = async (dirs, targetFileName) => {
1241
- if (dirs.length === 0)
829
+ return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
830
+ }, toScreamingSnake = (str) => str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase();
831
+
832
+ // src/utils/resolveConvention.ts
833
+ import { basename } from "path";
834
+ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boolean(value) && typeof value === "object", getMap = () => {
835
+ const value = Reflect.get(globalThis, CONVENTIONS_KEY);
836
+ if (isConventionsMap(value))
837
+ return value;
838
+ const empty = {};
839
+ return empty;
840
+ }, derivePageName = (pagePath) => {
841
+ const base = basename(pagePath);
842
+ const dotIndex = base.indexOf(".");
843
+ const name = dotIndex > 0 ? base.slice(0, dotIndex) : base;
844
+ return toPascal(name);
845
+ }, resolveErrorConventionPath = (framework, pageName) => {
846
+ const conventions = getMap()[framework];
847
+ if (!conventions)
848
+ return;
849
+ return conventions.pages?.[pageName]?.error ?? conventions.defaults?.error;
850
+ }, resolveNotFoundConventionPath = (framework) => getMap()[framework]?.defaults?.notFound, setConventions = (map) => {
851
+ Reflect.set(globalThis, CONVENTIONS_KEY, map);
852
+ }, isDev = () => true, buildErrorProps = (error) => {
853
+ const message = error instanceof Error ? error.message : String(error);
854
+ const stack = isDev() && error instanceof Error ? error.stack : undefined;
855
+ return { error: { message, stack } };
856
+ }, renderReactError = async (conventionPath, errorProps) => {
857
+ const { createElement } = await import("react");
858
+ const { renderToReadableStream } = await import("react-dom/server");
859
+ const mod = await import(conventionPath);
860
+ const [firstKey] = Object.keys(mod);
861
+ const ErrorComponent = mod.default ?? (firstKey ? mod[firstKey] : undefined);
862
+ const element = createElement(ErrorComponent, errorProps);
863
+ const stream = await renderToReadableStream(element);
864
+ return new Response(stream, {
865
+ headers: { "Content-Type": "text/html" },
866
+ status: 500
867
+ });
868
+ }, renderSvelteError = async (conventionPath, errorProps) => {
869
+ const { render } = await import("svelte/server");
870
+ const mod = await import(conventionPath);
871
+ const ErrorComponent = mod.default;
872
+ const { head, body } = render(ErrorComponent, {
873
+ props: errorProps
874
+ });
875
+ const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
876
+ return new Response(html, {
877
+ headers: { "Content-Type": "text/html" },
878
+ status: 500
879
+ });
880
+ }, unescapeVueStyles = (ssrBody) => {
881
+ let styles = "";
882
+ const body = ssrBody.replace(/<style>([\s\S]*?)<\/style>/g, (_, css) => {
883
+ styles += `<style>${css.replace(/&quot;/g, '"').replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">")}</style>`;
884
+ return "";
885
+ });
886
+ return { body, styles };
887
+ }, renderVueError = async (conventionPath, errorProps) => {
888
+ const { createSSRApp, h } = await import("vue");
889
+ const { renderToString } = await import("vue/server-renderer");
890
+ const mod = await import(conventionPath);
891
+ const ErrorComponent = mod.default;
892
+ const app = createSSRApp({
893
+ render: () => h(ErrorComponent, errorProps)
894
+ });
895
+ const rawBody = await renderToString(app);
896
+ const { styles, body } = unescapeVueStyles(rawBody);
897
+ const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
898
+ return new Response(html, {
899
+ headers: { "Content-Type": "text/html" },
900
+ status: 500
901
+ });
902
+ }, renderAngularError = async (conventionPath, errorProps) => {
903
+ const mod = await import(conventionPath);
904
+ const renderError = mod.default ?? mod.renderError;
905
+ if (typeof renderError !== "function")
1242
906
  return null;
1243
- const nextStack = [];
1244
- const dirEntries = await Promise.all(dirs.map(async (dir) => ({
1245
- dir,
1246
- entries: await readdir(dir, {
1247
- encoding: "utf-8",
1248
- withFileTypes: true
1249
- })
1250
- })));
1251
- for (const { dir, entries } of dirEntries) {
1252
- const found = processDirectoryEntries(entries, dir, targetFileName, nextStack);
1253
- if (found)
1254
- return found;
1255
- }
1256
- return searchDirectoryLevel(nextStack, targetFileName);
1257
- }, findSourceFileByBasename = async (searchRoot, targetFileName) => searchDirectoryLevel([searchRoot], targetFileName), normalizeBuiltSvelteFileName = (sourcePath) => basename2(sourcePath).replace(/-[a-z0-9]{6,}(?=\.svelte$)/i, ""), resolveOriginalSourcePath = async (sourcePath) => {
1258
- const cachedPath = originalSourcePathCache.get(sourcePath);
1259
- if (cachedPath !== undefined) {
1260
- return cachedPath;
1261
- }
1262
- if (!sourcePath.includes(`${join2(process.cwd(), "build")}${process.platform === "win32" ? "" : "/"}`) && !sourcePath.includes("/build/")) {
1263
- originalSourcePathCache.set(sourcePath, sourcePath);
1264
- return sourcePath;
907
+ const html = renderError(errorProps);
908
+ return new Response(html, {
909
+ headers: { "Content-Type": "text/html" },
910
+ status: 500
911
+ });
912
+ }, logConventionRenderError = (framework, label, renderError) => {
913
+ const message = renderError instanceof Error ? renderError.message : "";
914
+ if (message.includes("Cannot find module") || message.includes("Cannot find package") || message.includes("not found in module")) {
915
+ 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}).`);
916
+ return;
1265
917
  }
1266
- const resolvedSourcePath = await findSourceFileByBasename(join2(process.cwd(), "src"), normalizeBuiltSvelteFileName(sourcePath));
1267
- const nextPath = resolvedSourcePath ?? sourcePath;
1268
- originalSourcePathCache.set(sourcePath, nextPath);
1269
- return nextPath;
1270
- }, resolveRelativeModule = async (spec, from) => {
1271
- if (!spec.startsWith(".")) {
918
+ console.error(`[SSR] Failed to render ${framework} convention ${label} page:`, renderError);
919
+ }, ERROR_RENDERERS, renderConventionError = async (framework, pageName, error) => {
920
+ const conventionPath = resolveErrorConventionPath(framework, pageName);
921
+ if (!conventionPath)
1272
922
  return null;
1273
- }
1274
- const basePath = resolve3(dirname2(from), spec);
1275
- const candidates = [
1276
- basePath,
1277
- `${basePath}.ts`,
1278
- `${basePath}.js`,
1279
- `${basePath}.mjs`,
1280
- `${basePath}.cjs`,
1281
- `${basePath}.json`,
1282
- join2(basePath, "index.ts"),
1283
- join2(basePath, "index.js"),
1284
- join2(basePath, "index.mjs"),
1285
- join2(basePath, "index.cjs"),
1286
- join2(basePath, "index.json")
1287
- ];
1288
- const existResults = await Promise.all(candidates.map((candidate) => Bun.file(candidate).exists()));
1289
- const foundIndex = existResults.indexOf(true);
1290
- return foundIndex >= 0 ? candidates[foundIndex] ?? null : null;
1291
- }, getCachedModulePath = (sourcePath) => {
1292
- const relativeSourcePath = relative(process.cwd(), sourcePath).replace(/\\/g, "/");
1293
- const normalizedSourcePath = relativeSourcePath.startsWith("..") ? sourcePath.replace(/[:\\/]/g, "_") : relativeSourcePath;
1294
- return join2(serverCacheRoot, `${normalizedSourcePath}.server.js`);
1295
- }, resolveSvelteImport = async (spec, from) => {
1296
- if (spec.startsWith("/")) {
1297
- return spec;
1298
- }
1299
- if (!spec.startsWith(".")) {
923
+ const errorProps = buildErrorProps(error);
924
+ const renderer = ERROR_RENDERERS[framework];
925
+ if (!renderer)
1300
926
  return null;
1301
- }
1302
- const explicitPath = resolve3(dirname2(from), spec);
1303
- if (extname(explicitPath) === ".svelte") {
1304
- return explicitPath;
1305
- }
1306
- const candidate = `${explicitPath}.svelte`;
1307
- if (await Bun.file(candidate).exists() === true) {
1308
- return candidate;
927
+ try {
928
+ return await renderer(conventionPath, errorProps);
929
+ } catch (renderError) {
930
+ logConventionRenderError(framework, "error", renderError);
1309
931
  }
1310
932
  return null;
1311
- }, writeIfChanged = async (path, content) => {
1312
- const targetFile = Bun.file(path);
1313
- const exists = await targetFile.exists();
1314
- if (exists) {
1315
- const currentContent = await targetFile.text();
1316
- if (currentContent === content) {
1317
- return;
1318
- }
1319
- }
1320
- await Bun.write(path, content);
1321
- }, compileSvelteServerModule = async (sourcePath) => {
1322
- const cachedModulePath = compiledModuleCache.get(sourcePath);
1323
- if (cachedModulePath) {
1324
- return cachedModulePath;
1325
- }
1326
- const resolutionSourcePath = await resolveOriginalSourcePath(sourcePath);
1327
- const source = await Bun.file(sourcePath).text();
1328
- const { compile, preprocess } = await import("svelte/compiler");
1329
- const loweredSource = lowerSvelteIslandSyntax(source, "server");
1330
- const preprocessed = await preprocess(loweredSource.code, {});
1331
- let transpiled = sourcePath.endsWith(".ts") || sourcePath.endsWith(".svelte.ts") ? transpiler.transformSync(preprocessed.code) : preprocessed.code;
1332
- const childImportSpecs = Array.from(transpiled.matchAll(/from\s+['"]([^'"]+)['"]/g)).map((match) => match[1]).filter((value) => value !== undefined);
1333
- const resolvedChildModules = await Promise.all(childImportSpecs.map((spec) => resolveSvelteImport(spec, resolutionSourcePath)));
1334
- const resolvedModuleImports = await Promise.all(childImportSpecs.map((spec) => resolveRelativeModule(spec, resolutionSourcePath)));
1335
- const childModulePaths = new Map;
1336
- const rewrittenModulePaths = new Map;
1337
- const compiledChildren = await Promise.all(childImportSpecs.map(async (spec, index) => {
1338
- const resolvedChild = resolvedChildModules[index];
1339
- if (!spec || !resolvedChild)
1340
- return null;
1341
- return {
1342
- compiledPath: await compileSvelteServerModule(resolvedChild),
1343
- spec
1344
- };
1345
- }));
1346
- for (const result of compiledChildren) {
1347
- if (result)
1348
- childModulePaths.set(result.spec, result.compiledPath);
1349
- }
1350
- for (let index = 0;index < childImportSpecs.length; index += 1) {
1351
- const spec = childImportSpecs[index];
1352
- const resolvedModuleImport = resolvedModuleImports[index];
1353
- if (!spec || !resolvedModuleImport)
1354
- continue;
1355
- if (resolvedChildModules[index])
1356
- continue;
1357
- rewrittenModulePaths.set(spec, ensureRelativeImportPath(getCachedModulePath(sourcePath), resolvedModuleImport));
1358
- }
1359
- for (const [spec, resolvedModuleImport] of rewrittenModulePaths) {
1360
- transpiled = transpiled.replaceAll(spec, resolvedModuleImport);
1361
- }
1362
- let compiledCode = compile(transpiled, {
1363
- css: "injected",
1364
- experimental: {
1365
- async: loweredSource.transformed
1366
- },
1367
- filename: resolutionSourcePath,
1368
- generate: "server"
1369
- }).js.code;
1370
- for (const [spec, compiledChildPath] of childModulePaths) {
1371
- compiledCode = compiledCode.replaceAll(spec, ensureRelativeImportPath(getCachedModulePath(sourcePath), compiledChildPath));
1372
- }
1373
- for (const [spec, resolvedModuleImport] of rewrittenModulePaths) {
1374
- compiledCode = compiledCode.replaceAll(spec, resolvedModuleImport);
1375
- }
1376
- const compiledModulePath = getCachedModulePath(sourcePath);
1377
- await mkdir(dirname2(compiledModulePath), { recursive: true });
1378
- await writeIfChanged(compiledModulePath, compiledCode);
1379
- compiledModuleCache.set(sourcePath, compiledModulePath);
1380
- return compiledModulePath;
1381
- };
1382
- var init_svelteServerModule = __esm(() => {
1383
- init_lowerIslandSyntax();
1384
- serverCacheRoot = join2(process.cwd(), ".absolutejs", "islands", "svelte");
1385
- compiledModuleCache = new Map;
1386
- originalSourcePathCache = new Map;
1387
- transpiler = new Bun.Transpiler({
1388
- loader: "ts",
1389
- target: "browser"
933
+ }, renderReactNotFound = async (conventionPath) => {
934
+ const { createElement } = await import("react");
935
+ const { renderToReadableStream } = await import("react-dom/server");
936
+ const mod = await import(conventionPath);
937
+ const [nfKey] = Object.keys(mod);
938
+ const NotFoundComponent = mod.default ?? (nfKey ? mod[nfKey] : undefined);
939
+ const element = createElement(NotFoundComponent);
940
+ const stream = await renderToReadableStream(element);
941
+ return new Response(stream, {
942
+ headers: { "Content-Type": "text/html" },
943
+ status: 404
1390
944
  });
1391
- });
1392
-
1393
- // src/core/renderIslandMarkup.ts
1394
- var islandSequence = 0, resolvedServerComponentCache, resolvedServerBuildComponentCache, nextIslandId = () => {
1395
- islandSequence += 1;
1396
- return `island-${islandSequence}`;
1397
- }, isRecord2 = (value) => typeof value === "object" && value !== null, isReactServerIslandComponent = (value) => typeof value === "function", isSvelteServerIslandComponent = (value) => typeof value === "function", isVueServerIslandComponent = (value) => typeof value === "function" || isRecord2(value), isAngularServerIslandComponent = (value) => typeof value === "function", resolveBuildReferencePath = (source, registryPath) => {
1398
- if (source.startsWith("file://"))
1399
- return new URL(source).pathname;
1400
- if (source.startsWith("."))
1401
- return new URL(source, registryPath).pathname;
1402
- return source;
1403
- }, loadAndCompileServerBuildComponent = async (buildReferencePath) => {
1404
- const compiledModulePath = await compileSvelteServerModule(buildReferencePath);
1405
- const loadedModule = await import(compiledModulePath);
1406
- return "default" in loadedModule ? loadedModule.default : loadedModule;
1407
- }, loadServerBuildComponent = async (buildReferencePath) => {
1408
- const cachedBuildComponent = resolvedServerBuildComponentCache.get(buildReferencePath);
1409
- if (cachedBuildComponent) {
1410
- return cachedBuildComponent;
1411
- }
1412
- const loadPromise = loadAndCompileServerBuildComponent(buildReferencePath);
1413
- resolvedServerBuildComponentCache.set(buildReferencePath, loadPromise);
1414
- return loadPromise;
1415
- }, loadServerImportComponent = async (resolvedComponent) => {
1416
- const resolvedModulePath = resolvedComponent.startsWith(".") ? new URL(resolvedComponent, import.meta.url).pathname : resolvedComponent;
1417
- const importTarget = resolvedModulePath.endsWith(".svelte") ? await compileSvelteServerModule(resolvedModulePath) : resolvedModulePath;
1418
- const loadedModule = await import(importTarget);
1419
- return "default" in loadedModule ? loadedModule.default : loadedModule;
1420
- }, resolveIslandComponent = async (component) => {
1421
- const buildReference = getIslandBuildReference(component);
1422
- const buildReferencePath = buildReference?.source ? resolveBuildReferencePath(buildReference.source, import.meta.url) : null;
1423
- if (buildReferencePath?.endsWith(".svelte")) {
1424
- return loadServerBuildComponent(buildReferencePath);
1425
- }
1426
- const resolvedComponent = getIslandComponent(component);
1427
- if (typeof resolvedComponent !== "string") {
1428
- return resolvedComponent;
1429
- }
1430
- return loadServerImportComponent(resolvedComponent);
1431
- }, resolveServerIslandComponent = async (component) => {
1432
- const cachedResolvedComponent = resolvedServerComponentCache.get(component);
1433
- if (cachedResolvedComponent) {
1434
- return cachedResolvedComponent;
1435
- }
1436
- const resolutionPromise = resolveIslandComponent(component);
1437
- resolvedServerComponentCache.set(component, resolutionPromise);
1438
- return resolutionPromise;
1439
- }, resolveReactServerIslandComponent = async (component) => {
1440
- const resolvedComponent = await resolveServerIslandComponent(component);
1441
- if (!isReactServerIslandComponent(resolvedComponent)) {
1442
- throw new Error("Resolved React island is not a valid React component.");
1443
- }
1444
- return resolvedComponent;
1445
- }, resolveSvelteServerIslandComponent = async (component) => {
1446
- const resolvedComponent = await resolveServerIslandComponent(component);
1447
- if (!isSvelteServerIslandComponent(resolvedComponent)) {
1448
- throw new Error("Resolved Svelte island is not a valid Svelte component.");
945
+ }, renderSvelteNotFound = async (conventionPath) => {
946
+ const { render } = await import("svelte/server");
947
+ const mod = await import(conventionPath);
948
+ const NotFoundComponent = mod.default;
949
+ const { head, body } = render(NotFoundComponent);
950
+ const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
951
+ return new Response(html, {
952
+ headers: { "Content-Type": "text/html" },
953
+ status: 404
954
+ });
955
+ }, renderVueNotFound = async (conventionPath) => {
956
+ const { createSSRApp, h } = await import("vue");
957
+ const { renderToString } = await import("vue/server-renderer");
958
+ const mod = await import(conventionPath);
959
+ const NotFoundComponent = mod.default;
960
+ const app = createSSRApp({
961
+ render: () => h(NotFoundComponent)
962
+ });
963
+ const rawBody = await renderToString(app);
964
+ const { styles, body } = unescapeVueStyles(rawBody);
965
+ const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
966
+ return new Response(html, {
967
+ headers: { "Content-Type": "text/html" },
968
+ status: 404
969
+ });
970
+ }, renderAngularNotFound = async (conventionPath) => {
971
+ const mod = await import(conventionPath);
972
+ const renderNotFound = mod.default ?? mod.renderNotFound;
973
+ if (typeof renderNotFound !== "function")
974
+ return null;
975
+ const html = renderNotFound();
976
+ return new Response(html, {
977
+ headers: { "Content-Type": "text/html" },
978
+ status: 404
979
+ });
980
+ }, NOT_FOUND_RENDERERS, renderConventionNotFound = async (framework) => {
981
+ const conventionPath = resolveNotFoundConventionPath(framework);
982
+ if (!conventionPath)
983
+ return null;
984
+ const renderer = NOT_FOUND_RENDERERS[framework];
985
+ if (!renderer)
986
+ return null;
987
+ try {
988
+ return await renderer(conventionPath);
989
+ } catch (renderError) {
990
+ logConventionRenderError(framework, "not-found", renderError);
1449
991
  }
1450
- return resolvedComponent;
1451
- }, resolveVueServerIslandComponent = async (component) => {
1452
- const resolvedComponent = await resolveServerIslandComponent(component);
1453
- if (!isVueServerIslandComponent(resolvedComponent)) {
1454
- throw new Error("Resolved Vue island is not a valid Vue component.");
992
+ return null;
993
+ }, NOT_FOUND_PRIORITY, renderFirstNotFound = async () => {
994
+ for (const framework of NOT_FOUND_PRIORITY) {
995
+ if (!getMap()[framework]?.defaults?.notFound)
996
+ continue;
997
+ const response = await renderConventionNotFound(framework);
998
+ if (response)
999
+ return response;
1455
1000
  }
1456
- return resolvedComponent;
1457
- }, resolveAngularServerIslandComponent = async (component) => {
1458
- const resolvedComponent = await resolveServerIslandComponent(component);
1459
- if (!isAngularServerIslandComponent(resolvedComponent)) {
1460
- throw new Error("Resolved Angular island is not a valid Angular component.");
1001
+ return null;
1002
+ };
1003
+ var init_resolveConvention = __esm(() => {
1004
+ ERROR_RENDERERS = {
1005
+ angular: renderAngularError,
1006
+ react: renderReactError,
1007
+ svelte: renderSvelteError,
1008
+ vue: renderVueError
1009
+ };
1010
+ NOT_FOUND_RENDERERS = {
1011
+ angular: renderAngularNotFound,
1012
+ react: renderReactNotFound,
1013
+ svelte: renderSvelteNotFound,
1014
+ vue: renderVueNotFound
1015
+ };
1016
+ NOT_FOUND_PRIORITY = [
1017
+ "react",
1018
+ "svelte",
1019
+ "vue",
1020
+ "angular"
1021
+ ];
1022
+ });
1023
+
1024
+ // src/react/streamingSlotCollection.tsx
1025
+ import { createContext, useContext } from "react";
1026
+ import { jsxDEV } from "react/jsx-dev-runtime";
1027
+ var StreamingSlotCollectorContext, StreamingSlotCollectorProvider = ({
1028
+ children,
1029
+ collector
1030
+ }) => /* @__PURE__ */ jsxDEV(StreamingSlotCollectorContext.Provider, {
1031
+ value: collector,
1032
+ children
1033
+ }, undefined, false, undefined, this), useStreamingSlotCollector = () => useContext(StreamingSlotCollectorContext);
1034
+ var init_streamingSlotCollection = __esm(() => {
1035
+ StreamingSlotCollectorContext = createContext(null);
1036
+ });
1037
+
1038
+ // src/react/pageHandler.ts
1039
+ var ssrDirty = false, buildDirtyResponse = (index, maybeProps) => {
1040
+ const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
1041
+ const dirtyFlag = "window.__SSR_DIRTY__=true;";
1042
+ const refreshSetup = "window.__REFRESH_BUFFER__=[];" + "window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};" + "window.$RefreshSig$=function(){return function(t){return t}};";
1043
+ const inlineScript = `${propsScript}${dirtyFlag}${refreshSetup}`;
1044
+ const html = `<!DOCTYPE html><html><head></head><body>` + `<script>${inlineScript}</script>` + `<script type="module" src="${index}"></script>` + `</body></html>`;
1045
+ return new Response(html, {
1046
+ headers: { "Content-Type": "text/html" }
1047
+ });
1048
+ }, handleReactPageRequest = async (PageComponent, index, ...props) => {
1049
+ const [maybeProps] = props;
1050
+ if (ssrDirty) {
1051
+ return buildDirtyResponse(index, maybeProps);
1461
1052
  }
1462
- return resolvedComponent;
1463
- }, renderIslandMarkup = async (registry, props) => {
1464
- const result = await renderIslandResult(registry, props);
1465
- return `<div ${serializeIslandAttributes(result.attributes)}>${result.html}</div>`;
1466
- }, renderIslandResult = async (registry, props) => {
1467
- const islandId = nextIslandId();
1468
- const attributes = getIslandMarkerAttributes(props);
1469
- if (props.framework === "react") {
1470
- const entry = registry.react?.[props.component];
1471
- if (!entry) {
1472
- throw new Error(`Island component "${props.component}" is not registered for framework "react".`);
1053
+ try {
1054
+ const { createElement } = await import("react");
1055
+ const { renderToReadableStream } = await import("react-dom/server");
1056
+ const slotCollector = new Map;
1057
+ const pageElement = maybeProps !== undefined ? createElement(PageComponent, maybeProps) : createElement(PageComponent);
1058
+ const element = createElement(StreamingSlotCollectorProvider, { collector: slotCollector }, pageElement);
1059
+ const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
1060
+ const refreshSetup = "window.__REFRESH_BUFFER__=[];window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};window.$RefreshSig$=function(){return function(t){return t}};";
1061
+ const stream = await renderToReadableStream(element, {
1062
+ bootstrapModules: [index],
1063
+ bootstrapScriptContent: propsScript + refreshSetup || undefined,
1064
+ onError(error) {
1065
+ console.error("[SSR] React streaming error:", error);
1066
+ }
1067
+ });
1068
+ if ("allReady" in stream && stream.allReady instanceof Promise) {
1069
+ await stream.allReady;
1473
1070
  }
1474
- const component = await resolveReactServerIslandComponent(entry);
1475
- const html = renderReactIslandToHtml(component, props.props);
1476
- return { attributes, html };
1071
+ const htmlStream = injectIslandPageContextStream(stream);
1072
+ return withStreamingSlots(new Response(htmlStream, {
1073
+ headers: { "Content-Type": "text/html" }
1074
+ }), {
1075
+ streamingSlots: [...slotCollector.values()]
1076
+ });
1077
+ } catch (error) {
1078
+ console.error("[SSR] React render error:", error);
1079
+ const pageName = PageComponent.name || PageComponent.displayName || "";
1080
+ const conventionResponse = await renderConventionError("react", pageName, error);
1081
+ if (conventionResponse)
1082
+ return conventionResponse;
1083
+ return new Response(ssrErrorPage("react", error), {
1084
+ headers: { "Content-Type": "text/html" },
1085
+ status: 500
1086
+ });
1477
1087
  }
1478
- if (props.framework === "svelte") {
1479
- const entry = registry.svelte?.[props.component];
1480
- if (!entry) {
1481
- throw new Error(`Island component "${props.component}" is not registered for framework "svelte".`);
1482
- }
1483
- const component = await resolveSvelteServerIslandComponent(entry);
1484
- const html = renderSvelteIslandToHtml(component, props.props);
1485
- return { attributes, html };
1088
+ }, invalidateReactSsrCache = () => {
1089
+ ssrDirty = true;
1090
+ };
1091
+ var init_pageHandler = __esm(() => {
1092
+ init_responseEnhancers();
1093
+ init_resolveConvention();
1094
+ init_streamingSlotCollection();
1095
+ });
1096
+
1097
+ // src/core/islandManifest.ts
1098
+ var toIslandFrameworkSegment = (framework) => framework[0]?.toUpperCase() + framework.slice(1), collectFrameworkIslands = (manifest, prefix) => {
1099
+ const entries = {};
1100
+ let found = false;
1101
+ for (const [key, value] of Object.entries(manifest)) {
1102
+ if (!key.startsWith(prefix))
1103
+ continue;
1104
+ const component = key.slice(prefix.length);
1105
+ if (!component)
1106
+ continue;
1107
+ entries[component] = value;
1108
+ found = true;
1486
1109
  }
1487
- if (props.framework === "vue") {
1488
- const entry = registry.vue?.[props.component];
1489
- if (!entry) {
1490
- throw new Error(`Island component "${props.component}" is not registered for framework "vue".`);
1491
- }
1492
- const component = await resolveVueServerIslandComponent(entry);
1493
- const html = await renderVueIslandToHtml(component, props.props);
1494
- return { attributes, html };
1110
+ return found ? entries : undefined;
1111
+ }, getIslandManifestEntries = (manifest) => {
1112
+ const islands = {};
1113
+ const frameworks = ["react", "svelte", "vue", "angular"];
1114
+ for (const framework of frameworks) {
1115
+ const prefix = `Island${toIslandFrameworkSegment(framework)}`;
1116
+ const entries = collectFrameworkIslands(manifest, prefix);
1117
+ if (entries)
1118
+ islands[framework] = entries;
1495
1119
  }
1496
- if (props.framework === "angular") {
1497
- const entry = registry.angular?.[props.component];
1498
- if (!entry) {
1499
- throw new Error(`Island component "${props.component}" is not registered for framework "angular".`);
1500
- }
1501
- const component = await resolveAngularServerIslandComponent(entry);
1502
- const html = await renderAngularIslandToHtml(component, props.props, islandId);
1503
- return {
1504
- attributes: {
1505
- ...getIslandMarkerAttributes(props, islandId)
1506
- },
1507
- html
1508
- };
1120
+ return islands;
1121
+ }, getIslandManifestKey = (framework, component) => `Island${toIslandFrameworkSegment(framework)}${component}`;
1122
+
1123
+ // src/core/islands.ts
1124
+ function getIslandComponent(component) {
1125
+ if (isIslandComponentDefinition(component)) {
1126
+ return component.component;
1509
1127
  }
1510
- throw new Error(`Framework "${props.framework}" is not implemented in this prototype.`);
1511
- };
1512
- var init_renderIslandMarkup = __esm(() => {
1513
- init_islandSsr();
1514
- init_svelteServerModule();
1515
- init_islandMarkupAttributes();
1128
+ return component;
1129
+ }
1130
+ var defineIslandComponent = (component, options) => ({
1131
+ component,
1132
+ export: options.export,
1133
+ source: options.source
1134
+ }), defineIslandRegistry = (registry) => registry, isRecord = (value) => typeof value === "object" && value !== null, getIslandBuildReference = (component) => {
1135
+ if (!isIslandComponentDefinition(component))
1136
+ return null;
1137
+ return {
1138
+ export: component.export,
1139
+ source: component.source
1140
+ };
1141
+ }, isIslandComponentDefinition = (value) => isRecord(value) && ("component" in value) && ("source" in value) && typeof value.source === "string", parseIslandProps = (rawProps) => {
1142
+ if (!rawProps)
1143
+ return {};
1144
+ return JSON.parse(rawProps);
1145
+ }, serializeIslandProps = (props) => JSON.stringify(props ?? {});
1146
+ var init_islands = () => {};
1147
+
1148
+ // src/core/islandMarkupAttributes.ts
1149
+ var getIslandMarkerAttributes = (props, islandId) => ({
1150
+ "data-component": props.component,
1151
+ "data-framework": props.framework,
1152
+ "data-hydrate": props.hydrate ?? "load",
1153
+ "data-island": "true",
1154
+ ...islandId ? { "data-island-id": islandId } : {},
1155
+ "data-props": serializeIslandProps(props.props)
1156
+ }), escapeHtmlAttribute = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"), serializeIslandAttributes = (attributes) => Object.entries(attributes).map(([key, value]) => `${key}="${escapeHtmlAttribute(value)}"`).join(" ");
1157
+ var init_islandMarkupAttributes = __esm(() => {
1516
1158
  init_islands();
1517
- resolvedServerComponentCache = new Map;
1518
- resolvedServerBuildComponentCache = new Map;
1519
1159
  });
1520
1160
 
1521
- // src/client/streamSwap.ts
1522
- var streamSwapRuntime = () => {
1523
- if (window.__ABS_SLOT_RUNTIME__ === true)
1161
+ // src/core/currentIslandRegistry.ts
1162
+ var requireCurrentIslandRegistry = () => {
1163
+ const registry = globalThis.__absoluteIslandRegistry;
1164
+ if (!registry) {
1165
+ throw new Error("No island registry is active. Configure `islands.registry` in absolute.config.ts before rendering <Island />.");
1166
+ }
1167
+ return registry;
1168
+ }, setCurrentIslandRegistry = (registry) => {
1169
+ globalThis.__absoluteIslandRegistry = registry;
1170
+ };
1171
+
1172
+ // src/angular/injectorPatch.ts
1173
+ import { existsSync, readFileSync, writeFileSync } from "fs";
1174
+ import { dirname, join, resolve } from "path";
1175
+ var applyInjectorPatch = (chunkPath, content) => {
1176
+ if (content.includes('Symbol.for("angular.currentInjector")')) {
1524
1177
  return;
1525
- window.__ABS_SLOT_RUNTIME__ = true;
1526
- window.__ABS_SLOT_PENDING__ = window.__ABS_SLOT_PENDING__ ?? {};
1527
- const pending = window.__ABS_SLOT_PENDING__;
1528
- const apply = (id, html) => {
1529
- const node = document.getElementById(`slot-${id}`);
1530
- if (!node) {
1531
- pending[id] = html;
1532
- return;
1533
- }
1534
- node.innerHTML = html;
1535
- delete pending[id];
1536
- };
1537
- const flush = () => {
1538
- for (const id in pending) {
1539
- if (!Object.prototype.hasOwnProperty.call(pending, id))
1540
- continue;
1541
- apply(id, pending[id] ?? "");
1542
- }
1543
- };
1544
- window.__ABS_SLOT_ENQUEUE__ = (id, html) => {
1545
- apply(id, html);
1546
- };
1547
- if (typeof MutationObserver === "function") {
1548
- const observer = new MutationObserver(flush);
1549
- const root = document.documentElement ?? document.body ?? document;
1550
- observer.observe(root, { childList: true, subtree: true });
1551
1178
  }
1552
- if (document.readyState === "loading") {
1553
- document.addEventListener("DOMContentLoaded", flush, { once: true });
1179
+ const original = [
1180
+ "let _currentInjector = undefined;",
1181
+ "function getCurrentInjector() {",
1182
+ " return _currentInjector;",
1183
+ "}",
1184
+ "function setCurrentInjector(injector) {",
1185
+ " const former = _currentInjector;",
1186
+ " _currentInjector = injector;",
1187
+ " return former;",
1188
+ "}"
1189
+ ].join(`
1190
+ `);
1191
+ const replacement = [
1192
+ 'const _injSym = Symbol.for("angular.currentInjector");',
1193
+ "if (!globalThis[_injSym]) globalThis[_injSym] = { v: undefined };",
1194
+ "function getCurrentInjector() {",
1195
+ " return globalThis[_injSym].v;",
1196
+ "}",
1197
+ "function setCurrentInjector(injector) {",
1198
+ " const former = globalThis[_injSym].v;",
1199
+ " globalThis[_injSym].v = injector;",
1200
+ " return former;",
1201
+ "}"
1202
+ ].join(`
1203
+ `);
1204
+ const patched = content.replace(original, replacement);
1205
+ if (patched === content) {
1206
+ return;
1554
1207
  }
1555
- flush();
1556
- };
1557
- var stripFunctionWrapper = (value) => {
1558
- const start = value.indexOf("{");
1559
- const end = value.lastIndexOf("}");
1560
- if (start < 0 || end <= start)
1561
- return "";
1562
- return value.slice(start + 1, end);
1563
- };
1564
- var getStreamSwapRuntimeScript = () => `(function(){${stripFunctionWrapper(streamSwapRuntime.toString())}})();`;
1565
-
1566
- // src/utils/streamingSlots.ts
1567
- init_escapeScriptContent();
1568
- var SLOT_ID_PREFIX = "abs-slot-";
1569
- var SLOT_PLACEHOLDER_PREFIX = "slot-";
1570
- var CLOSING_HEAD_TAG = "</head>";
1571
- var CLOSING_HEAD_TAG_LENGTH = CLOSING_HEAD_TAG.length;
1572
- var CLOSING_PAGE_TAG_REGEX = /<\/body>\s*<\/html>\s*$/i;
1573
- var STREAMING_RUNTIME_GLOBAL = "__ABS_SLOT_ENQUEUE__";
1574
- var STREAMING_PENDING_GLOBAL = "__ABS_SLOT_PENDING__";
1575
- var STREAM_TAIL_LOOKBEHIND = 128;
1576
- var STREAMING_SLOT_TIMEOUT_MS = 5000;
1577
- var STREAMING_SLOT_MAX_PER_RESPONSE = 128;
1578
- var STREAMING_SLOT_MAX_HTML_BYTES = 64000;
1579
- var createSlotPlaceholderId = (id) => `${SLOT_PLACEHOLDER_PREFIX}${id}`;
1580
- 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)});`;
1581
- var createNonceAttr = (nonce) => nonce ? ` nonce="${nonce}"` : "";
1582
- var createStreamingSlotId = () => `${SLOT_ID_PREFIX}${Math.random().toString(36).slice(2, 10)}`;
1583
- var getStreamingSlotsRuntimeScript = () => getStreamSwapRuntimeScript();
1584
- var renderStreamingSlotsRuntimeTag = (nonce) => `<script${createNonceAttr(nonce)}>${escapeScriptContent(getStreamingSlotsRuntimeScript())}</script>`;
1585
- var renderStreamingSlotPlaceholder = (id, fallbackHtml = "") => `<div id="${createSlotPlaceholderId(id)}" data-absolute-slot="true">${fallbackHtml}</div>`;
1586
- var renderStreamingSlotPatchTag = (id, html, nonce) => `<script${createNonceAttr(nonce)}>${escapeScriptContent(createSlotPatchStatement(id, html))}</script>`;
1587
- var injectHtmlIntoHead = (html, injection) => {
1588
- const closingHeadIndex = html.indexOf(CLOSING_HEAD_TAG);
1589
- if (closingHeadIndex >= 0) {
1590
- return `${html.slice(0, closingHeadIndex)}${injection}${html.slice(closingHeadIndex)}`;
1208
+ writeFileSync(chunkPath, patched, "utf-8");
1209
+ }, resolveAngularCoreDir = () => {
1210
+ const fromProject = resolve(process.cwd(), "node_modules/@angular/core");
1211
+ if (existsSync(join(fromProject, "package.json"))) {
1212
+ return fromProject;
1591
1213
  }
1592
- return `${html}${injection}`;
1593
- };
1594
- var toUint8 = (value, encoder) => encoder.encode(value);
1595
- var currentStreamingSlotPolicy = {
1596
- timeoutMs: STREAMING_SLOT_TIMEOUT_MS,
1597
- fallbackHtml: "",
1598
- errorHtml: undefined,
1599
- maxSlotsPerResponse: STREAMING_SLOT_MAX_PER_RESPONSE,
1600
- maxSlotHtmlSizeBytes: STREAMING_SLOT_MAX_HTML_BYTES
1214
+ return dirname(__require.resolve("@angular/core/package.json"));
1215
+ }, patchAngularInjectorSingleton = () => {
1216
+ try {
1217
+ const coreDir = resolveAngularCoreDir();
1218
+ const chunkPath = join(coreDir, "fesm2022", "_not_found-chunk.mjs");
1219
+ const content = readFileSync(chunkPath, "utf-8");
1220
+ applyInjectorPatch(chunkPath, content);
1221
+ } catch {}
1601
1222
  };
1602
- var clonePolicy = (policy) => ({
1603
- ...policy
1223
+ var init_injectorPatch = __esm(() => {
1224
+ patchAngularInjectorSingleton();
1604
1225
  });
1605
- var normalizeSlotBytes = (value, fallback) => {
1606
- if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
1607
- return Math.floor(value);
1226
+
1227
+ // src/angular/resolveAngularPackage.ts
1228
+ import { existsSync as existsSync2 } from "fs";
1229
+ import { resolve as resolve2 } from "path";
1230
+ var resolveAngularPackage = (specifier) => {
1231
+ const fromProject = resolve2(process.cwd(), "node_modules", specifier);
1232
+ if (existsSync2(fromProject)) {
1233
+ return fromProject;
1608
1234
  }
1609
- return fallback;
1235
+ return specifier;
1610
1236
  };
1611
- var normalizeSlotText = (value, fallback) => typeof value === "string" ? value : fallback;
1612
- var normalizeSlotError = (value, fallback) => typeof value === "string" ? value : fallback;
1613
- var hasPolicyValue = (policy, key) => Object.prototype.hasOwnProperty.call(policy, key);
1614
- var applyStreamingSlotPolicyOverrides = (base, overridePolicy = {}) => ({
1615
- timeoutMs: hasPolicyValue(overridePolicy, "timeoutMs") ? normalizeSlotBytes(overridePolicy.timeoutMs, base.timeoutMs) : base.timeoutMs,
1616
- fallbackHtml: hasPolicyValue(overridePolicy, "fallbackHtml") ? normalizeSlotText(overridePolicy.fallbackHtml, "") : base.fallbackHtml,
1617
- errorHtml: hasPolicyValue(overridePolicy, "errorHtml") ? normalizeSlotError(overridePolicy.errorHtml) : base.errorHtml,
1618
- maxSlotsPerResponse: hasPolicyValue(overridePolicy, "maxSlotsPerResponse") ? normalizeSlotBytes(overridePolicy.maxSlotsPerResponse, base.maxSlotsPerResponse) : base.maxSlotsPerResponse,
1619
- maxSlotHtmlSizeBytes: hasPolicyValue(overridePolicy, "maxSlotHtmlSizeBytes") ? normalizeSlotBytes(overridePolicy.maxSlotHtmlSizeBytes, base.maxSlotHtmlSizeBytes) : base.maxSlotHtmlSizeBytes,
1620
- onError: hasPolicyValue(overridePolicy, "onError") ? overridePolicy.onError : base.onError,
1621
- onSlotMetric: hasPolicyValue(overridePolicy, "onSlotMetric") ? overridePolicy.onSlotMetric : base.onSlotMetric
1237
+ var init_resolveAngularPackage = () => {};
1238
+
1239
+ // src/angular/angularPatch.ts
1240
+ var exports_angularPatch = {};
1241
+ __export(exports_angularPatch, {
1242
+ applyPatches: () => applyPatches
1622
1243
  });
1623
- var createCombinedSlotErrorHandler = (policyOnError, enhancerOnError) => {
1624
- if (!policyOnError && !enhancerOnError)
1244
+ var ensureHead = (doc) => {
1245
+ if (!doc || doc.head || !doc.documentElement) {
1625
1246
  return;
1626
- return (error, slot) => {
1627
- policyOnError?.(error, slot);
1628
- enhancerOnError?.(error, slot);
1247
+ }
1248
+ const head = doc.createElement("head");
1249
+ doc.documentElement.insertBefore(head, doc.documentElement.firstChild);
1250
+ }, applyPatches = async () => {
1251
+ const { \u{275}DominoAdapter } = await import(resolveAngularPackage("@angular/platform-server"));
1252
+ if (!\u{275}DominoAdapter?.prototype) {
1253
+ console.warn("[Angular Patch] \u0275DominoAdapter not found, skipping patches");
1254
+ return false;
1255
+ }
1256
+ const proto = \u{275}DominoAdapter.prototype;
1257
+ const origGetBaseHref = proto.getBaseHref;
1258
+ proto.getBaseHref = function(doc) {
1259
+ if (!doc || !doc.head || typeof doc.head.children === "undefined") {
1260
+ return "";
1261
+ }
1262
+ return origGetBaseHref.call(this, doc);
1629
1263
  };
1630
- };
1631
- var createCombinedSlotMetricHandler = (policyOnSlotMetric, callOnSlotMetric) => {
1632
- if (!policyOnSlotMetric && !callOnSlotMetric)
1633
- return;
1634
- return (metric) => {
1635
- policyOnSlotMetric?.(metric);
1636
- callOnSlotMetric?.(metric);
1264
+ const origCreateHtmlDocument = proto.createHtmlDocument;
1265
+ proto.createHtmlDocument = function() {
1266
+ const doc = origCreateHtmlDocument.call(this);
1267
+ ensureHead(doc);
1268
+ return doc;
1637
1269
  };
1270
+ const origGetDefaultDocument = proto.getDefaultDocument;
1271
+ proto.getDefaultDocument = function() {
1272
+ const doc = origGetDefaultDocument.call(this);
1273
+ ensureHead(doc);
1274
+ return doc;
1275
+ };
1276
+ return true;
1638
1277
  };
1639
- var resolveStreamingSlotPolicy = (overridePolicy = {}) => {
1640
- const base = getStreamingSlotPolicy();
1641
- return applyStreamingSlotPolicyOverrides(base, overridePolicy);
1642
- };
1643
- var getStreamingSlotPolicy = () => clonePolicy(currentStreamingSlotPolicy);
1644
- var setStreamingSlotPolicy = (policy = {}) => {
1645
- const base = getStreamingSlotPolicy();
1646
- currentStreamingSlotPolicy = applyStreamingSlotPolicyOverrides(base, policy);
1647
- };
1648
- var withStreamingSlotPolicy = async (policy, callback) => {
1649
- const previous = getStreamingSlotPolicy();
1650
- setStreamingSlotPolicy(policy);
1278
+ var init_angularPatch = __esm(() => {
1279
+ init_resolveAngularPackage();
1280
+ });
1281
+
1282
+ // src/angular/angularDeps.ts
1283
+ var initDominoAdapter = (platformServer) => {
1651
1284
  try {
1652
- return await callback();
1653
- } finally {
1654
- currentStreamingSlotPolicy = previous;
1285
+ const DominoAdapter = platformServer.\u{275}DominoAdapter;
1286
+ DominoAdapter?.makeCurrent?.();
1287
+ } catch (err) {
1288
+ console.error("Failed to initialize DominoAdapter:", err);
1655
1289
  }
1290
+ }, loadAngularDeps = async () => {
1291
+ patchAngularInjectorSingleton();
1292
+ await import(resolveAngularPackage("@angular/compiler"));
1293
+ const { applyPatches: applyPatches2 } = await Promise.resolve().then(() => (init_angularPatch(), exports_angularPatch));
1294
+ await applyPatches2();
1295
+ const [platformBrowser, platformServer, common, core] = await Promise.all([
1296
+ import(resolveAngularPackage("@angular/platform-browser")),
1297
+ import(resolveAngularPackage("@angular/platform-server")),
1298
+ import(resolveAngularPackage("@angular/common")),
1299
+ import(resolveAngularPackage("@angular/core"))
1300
+ ]);
1301
+ if (false) {}
1302
+ initDominoAdapter(platformServer);
1303
+ return {
1304
+ APP_BASE_HREF: common.APP_BASE_HREF,
1305
+ bootstrapApplication: platformBrowser.bootstrapApplication,
1306
+ DomSanitizer: platformBrowser.DomSanitizer,
1307
+ provideClientHydration: platformBrowser.provideClientHydration,
1308
+ provideServerRendering: platformServer.provideServerRendering,
1309
+ provideZonelessChangeDetection: core.provideZonelessChangeDetection,
1310
+ reflectComponentType: core.reflectComponentType,
1311
+ renderApplication: platformServer.renderApplication,
1312
+ Sanitizer: core.Sanitizer,
1313
+ SecurityContext: core.SecurityContext
1314
+ };
1315
+ }, angularDeps = null, getAngularDeps = () => {
1316
+ if (!angularDeps) {
1317
+ angularDeps = loadAngularDeps();
1318
+ }
1319
+ return angularDeps;
1656
1320
  };
1657
- var emitSlotMetric = (metric, onSlotMetric) => {
1658
- onSlotMetric?.(metric);
1659
- };
1660
- var createTimeoutError = (slot, timeoutMs) => {
1661
- const error = new Error(`Streaming slot "${slot.id}" timed out after ${timeoutMs}ms`);
1662
- error.__absTimeout = true;
1663
- return error;
1664
- };
1665
- var toStreamingSlot = (slot, policy) => ({
1666
- errorHtml: slot.errorHtml === undefined ? policy.errorHtml : slot.errorHtml,
1667
- fallbackHtml: normalizeSlotText(slot.fallbackHtml, policy.fallbackHtml),
1668
- id: slot.id ?? createStreamingSlotId(),
1669
- timeoutMs: normalizeSlotBytes(slot.timeoutMs, policy.timeoutMs),
1670
- resolve: slot.resolve
1321
+ var init_angularDeps = __esm(() => {
1322
+ init_injectorPatch();
1323
+ init_resolveAngularPackage();
1671
1324
  });
1672
- var prepareSlots = ({
1673
- policy,
1674
- slots,
1675
- onError,
1676
- onSlotMetric
1677
- }) => {
1678
- const preparedSlots = slots.map((slot) => toStreamingSlot(slot, policy));
1679
- const maxSlotsPerResponse = policy.maxSlotsPerResponse;
1680
- if (maxSlotsPerResponse === 0) {
1681
- const error = new Error("Streaming slot limit is set to 0");
1682
- for (const slot of preparedSlots) {
1683
- onError?.(error, slot);
1684
- emitSlotMetric({
1685
- type: "dropped",
1686
- slotId: slot.id,
1687
- reason: "maxSlotsPerResponse is 0"
1688
- }, onSlotMetric);
1325
+
1326
+ // src/utils/registerClientScript.ts
1327
+ var scriptRegistry, requestCounter = 0, getRequestId = () => `req_${Date.now()}_${++requestCounter}`, ssrContextGetter = null, getSsrContextId = () => ssrContextGetter?.() || Object.getOwnPropertyDescriptor(globalThis, "__absolutejs_requestId")?.value, registerClientScript = (script, requestId) => {
1328
+ const id = requestId || getSsrContextId() || getRequestId();
1329
+ if (!scriptRegistry.has(id)) {
1330
+ scriptRegistry.set(id, new Set);
1331
+ }
1332
+ scriptRegistry.get(id)?.add(script);
1333
+ return id;
1334
+ }, setSsrContextGetter = (getter) => {
1335
+ ssrContextGetter = getter;
1336
+ }, clearAllClientScripts = () => {
1337
+ scriptRegistry.clear();
1338
+ }, generateClientScriptCode = (scripts) => {
1339
+ if (scripts.length === 0) {
1340
+ return "";
1341
+ }
1342
+ const scriptCode = scripts.map((script, index) => {
1343
+ const funcString = script.toString();
1344
+ const bodyMatch = funcString.match(/\{([\s\S]*)\}/);
1345
+ if (!bodyMatch || !bodyMatch[1]) {
1346
+ return "";
1689
1347
  }
1348
+ const body = bodyMatch[1].trim();
1349
+ return `
1350
+ (function() {
1351
+ var executed = false;
1352
+ function executeScript_${index}() {
1353
+ if (executed) return;
1354
+ executed = true;
1355
+ ${body}
1356
+ }
1357
+
1358
+ if (document.readyState === 'complete' || document.readyState === 'interactive') {
1359
+ executeScript_${index}();
1360
+ } else {
1361
+ document.addEventListener('DOMContentLoaded', executeScript_${index});
1362
+ }
1363
+
1364
+ // Watch for hydration-added elements
1365
+ var observer = new MutationObserver(function() {
1366
+ executeScript_${index}();
1367
+ if (executed) observer.disconnect();
1368
+ });
1369
+ if (!executed) {
1370
+ observer.observe(document.body || document.documentElement, { childList: true, subtree: true });
1371
+ }
1372
+
1373
+ // Single fallback timeout
1374
+ setTimeout(function() {
1375
+ executeScript_${index}();
1376
+ observer.disconnect();
1377
+ }, 1000);
1378
+ })();`;
1379
+ }).join(`
1380
+ `);
1381
+ return `<script>
1382
+ (function() {
1383
+ ${scriptCode}
1384
+ })();
1385
+ </script>`;
1386
+ }, getAndClearClientScripts = (requestId) => {
1387
+ const id = requestId || ssrContextGetter?.();
1388
+ if (!id)
1389
+ return [];
1390
+ const scripts = scriptRegistry.get(id);
1391
+ if (!scripts) {
1690
1392
  return [];
1691
1393
  }
1692
- if (preparedSlots.length <= maxSlotsPerResponse) {
1693
- preparedSlots.forEach((slot) => emitSlotMetric({
1694
- type: "prepared",
1695
- slotId: slot.id
1696
- }, onSlotMetric));
1697
- return preparedSlots;
1698
- }
1699
- const keptSlots = preparedSlots.slice(0, maxSlotsPerResponse);
1700
- const droppedSlots = preparedSlots.slice(maxSlotsPerResponse);
1701
- droppedSlots.forEach((slot) => {
1702
- onError?.(new Error(`Streaming slot "${slot.id}" dropped because ${maxSlotsPerResponse} slots is the configured maximum`), slot);
1703
- emitSlotMetric({
1704
- type: "dropped",
1705
- slotId: slot.id,
1706
- reason: `maxSlotsPerResponse is ${maxSlotsPerResponse}`
1707
- }, onSlotMetric);
1708
- });
1709
- keptSlots.forEach((slot) => emitSlotMetric({
1710
- type: "prepared",
1711
- slotId: slot.id
1712
- }, onSlotMetric));
1713
- return keptSlots;
1394
+ const scriptArray = Array.from(scripts);
1395
+ scriptRegistry.delete(id);
1396
+ return scriptArray;
1714
1397
  };
1715
- var htmlByteLength = (value, encoder) => encoder.encode(value).length;
1716
- var resolveSlot = async (slot, onError, policy, onSlotMetric) => {
1717
- const safePolicy = policy ?? getStreamingSlotPolicy();
1718
- const encoder = new TextEncoder;
1719
- const start = Date.now();
1398
+ var init_registerClientScript = __esm(() => {
1399
+ scriptRegistry = new Map;
1400
+ if (typeof globalThis !== "undefined") {
1401
+ Object.assign(globalThis, { registerClientScript });
1402
+ }
1403
+ });
1404
+
1405
+ // src/angular/ssrRender.ts
1406
+ var routePropsCache, cacheRouteData = (pagePath, data) => {
1407
+ const cacheKey = pagePath.split("?")[0] ?? pagePath;
1408
+ routePropsCache.set(cacheKey, data);
1409
+ }, getCachedRouteData = (pagePath) => routePropsCache.get(pagePath), selectorCache, buildDeps = (ssrResult, baseDeps) => {
1410
+ if (!ssrResult?.core) {
1411
+ return baseDeps;
1412
+ }
1413
+ const { common, core, platformBrowser, platformServer } = ssrResult;
1414
+ return {
1415
+ APP_BASE_HREF: common?.APP_BASE_HREF ?? baseDeps.APP_BASE_HREF,
1416
+ bootstrapApplication: platformBrowser?.bootstrapApplication ?? baseDeps.bootstrapApplication,
1417
+ DomSanitizer: platformBrowser?.DomSanitizer ?? baseDeps.DomSanitizer,
1418
+ provideClientHydration: platformBrowser?.provideClientHydration ?? baseDeps.provideClientHydration,
1419
+ provideServerRendering: platformServer?.provideServerRendering ?? baseDeps.provideServerRendering,
1420
+ provideZonelessChangeDetection: core.provideZonelessChangeDetection,
1421
+ reflectComponentType: core.reflectComponentType,
1422
+ renderApplication: platformServer?.renderApplication ?? baseDeps.renderApplication,
1423
+ Sanitizer: core.Sanitizer,
1424
+ SecurityContext: core.SecurityContext
1425
+ };
1426
+ }, buildProviders = (deps, sanitizer, maybeProps, tokenMap) => {
1427
+ const providers = [
1428
+ deps.provideServerRendering(),
1429
+ deps.provideClientHydration(),
1430
+ deps.provideZonelessChangeDetection(),
1431
+ { provide: deps.APP_BASE_HREF, useValue: "/" },
1432
+ {
1433
+ provide: deps.DomSanitizer,
1434
+ useValue: sanitizer
1435
+ },
1436
+ { provide: deps.Sanitizer, useValue: sanitizer }
1437
+ ];
1438
+ if (!maybeProps) {
1439
+ return providers;
1440
+ }
1441
+ const propProviders = Object.entries(maybeProps).map(([propName, propValue]) => ({
1442
+ token: tokenMap.get(toScreamingSnake(propName)),
1443
+ value: propValue
1444
+ })).filter((entry) => entry.token).map((entry) => ({ provide: entry.token, useValue: entry.value }));
1445
+ return [...providers, ...propProviders];
1446
+ }, clearSelectorCache = () => selectorCache.clear(), isInjectionToken = (value) => {
1447
+ if (!value || typeof value !== "object") {
1448
+ return false;
1449
+ }
1450
+ return "ngMetadataName" in value && value.ngMetadataName === "InjectionToken";
1451
+ }, discoverTokens = (pageModule) => new Map(Object.entries(pageModule).filter(([, value]) => isInjectionToken(value))), loadSsrDeps = async (pagePath) => {
1452
+ const ssrDepsPath = (pagePath.split("?")[0] ?? pagePath).replace(/\.js$/, ".ssr-deps.js");
1720
1453
  try {
1721
- const maybeAsyncValue = Promise.resolve(slot.resolve());
1722
- const resolved = typeof slot.timeoutMs === "number" && slot.timeoutMs > 0 ? await Promise.race([
1723
- maybeAsyncValue,
1724
- new Promise((_, reject) => setTimeout(() => {
1725
- reject(createTimeoutError(slot, slot.timeoutMs ?? 0));
1726
- }, slot.timeoutMs))
1727
- ]) : await maybeAsyncValue;
1728
- const html = typeof resolved === "string" ? resolved : `${resolved}`;
1729
- if (safePolicy.maxSlotHtmlSizeBytes > 0 && htmlByteLength(html, encoder) > safePolicy.maxSlotHtmlSizeBytes) {
1730
- const bytes2 = htmlByteLength(html, encoder);
1731
- const error = new Error(`Streaming slot "${slot.id}" exceeded max payload size of ${safePolicy.maxSlotHtmlSizeBytes} bytes`);
1732
- const durationMs2 = Date.now() - start;
1733
- onError?.(error, slot);
1734
- emitSlotMetric({
1735
- type: "size_exceeded",
1736
- slotId: slot.id,
1737
- durationMs: durationMs2,
1738
- bytes: bytes2,
1739
- error
1740
- }, onSlotMetric);
1741
- const fallbackHtml = typeof slot.errorHtml === "string" ? slot.errorHtml : null;
1742
- return {
1743
- html: fallbackHtml,
1744
- id: slot.id,
1745
- durationMs: durationMs2,
1746
- bytes: fallbackHtml === null ? 0 : htmlByteLength(fallbackHtml, encoder)
1747
- };
1748
- }
1749
- const durationMs = Date.now() - start;
1750
- const bytes = htmlByteLength(html, encoder);
1751
- emitSlotMetric({
1752
- type: "resolved",
1753
- slotId: slot.id,
1754
- durationMs,
1755
- bytes
1756
- }, onSlotMetric);
1757
- return {
1758
- html,
1759
- id: slot.id,
1760
- durationMs,
1761
- bytes
1762
- };
1763
- } catch (error) {
1764
- const durationMs = Date.now() - start;
1765
- onError?.(error, slot);
1766
- emitSlotMetric({
1767
- type: error?.__absTimeout === true ? "timeout" : "error",
1768
- slotId: slot.id,
1769
- durationMs,
1770
- error
1771
- }, onSlotMetric);
1772
- if (typeof slot.errorHtml === "string") {
1773
- const html = slot.errorHtml;
1774
- return {
1775
- html,
1776
- id: slot.id,
1777
- durationMs,
1778
- bytes: htmlByteLength(html, encoder)
1779
- };
1780
- }
1781
- return {
1782
- html: null,
1783
- id: slot.id,
1784
- durationMs,
1785
- bytes: 0
1454
+ const ssrDeps = await import(ssrDepsPath);
1455
+ const result = {
1456
+ common: ssrDeps.__angularCommon,
1457
+ core: ssrDeps.__angularCore,
1458
+ platformBrowser: ssrDeps.__angularPlatformBrowser,
1459
+ platformServer: ssrDeps.__angularPlatformServer
1786
1460
  };
1461
+ return result;
1462
+ } catch {
1463
+ return null;
1787
1464
  }
1788
- };
1789
- var nextResolvedSlot = async (pending) => {
1790
- const wrapped = pending.map((promise) => promise.then((result) => ({
1791
- original: promise,
1792
- result
1793
- })));
1794
- return Promise.race(wrapped);
1795
- };
1796
- var streamChunkToString = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true });
1797
- var streamOutOfOrderSlots = ({
1798
- footerHtml = "",
1799
- headerHtml = "",
1800
- nonce,
1801
- policy,
1802
- onSlotMetric,
1803
- onError,
1804
- slots
1805
- }) => {
1806
- const resolvedPolicy = resolveStreamingSlotPolicy(policy);
1807
- const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
1808
- const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
1809
- const effectivePolicy = {
1810
- ...resolvedPolicy,
1811
- onSlotMetric: combinedOnSlotMetric
1812
- };
1813
- const preparedSlots = prepareSlots({
1814
- policy: effectivePolicy,
1815
- slots,
1816
- onError: combinedOnError,
1817
- onSlotMetric: combinedOnSlotMetric
1818
- });
1819
- const encoder = new TextEncoder;
1820
- return new ReadableStream({
1821
- async start(controller) {
1822
- try {
1823
- let header = headerHtml;
1824
- if (preparedSlots.length > 0 && !header.includes(STREAMING_RUNTIME_GLOBAL)) {
1825
- header = injectHtmlIntoHead(header, renderStreamingSlotsRuntimeTag(nonce));
1826
- }
1827
- controller.enqueue(toUint8(header, encoder));
1828
- const pending = preparedSlots.map((slot) => {
1829
- const fallback = renderStreamingSlotPlaceholder(slot.id, slot.fallbackHtml ?? "");
1830
- controller.enqueue(toUint8(fallback, encoder));
1831
- return resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric);
1832
- });
1833
- while (pending.length > 0) {
1834
- const { original, result } = await nextResolvedSlot(pending);
1835
- const index = pending.indexOf(original);
1836
- if (index >= 0)
1837
- pending.splice(index, 1);
1838
- if (result.html === null)
1839
- continue;
1840
- emitSlotMetric({
1841
- type: "patched",
1842
- slotId: result.id,
1843
- durationMs: result.durationMs,
1844
- bytes: result.bytes
1845
- }, combinedOnSlotMetric);
1846
- controller.enqueue(toUint8(renderStreamingSlotPatchTag(result.id, result.html, nonce), encoder));
1847
- }
1848
- if (footerHtml.length > 0) {
1849
- controller.enqueue(toUint8(footerHtml, encoder));
1850
- }
1851
- controller.close();
1852
- } catch (error) {
1853
- controller.error(error);
1854
- }
1465
+ }, resolveSelector = (deps, pagePath, PageComponent) => {
1466
+ const cached = selectorCache.get(pagePath);
1467
+ if (cached) {
1468
+ return cached;
1469
+ }
1470
+ const selector = deps.reflectComponentType(PageComponent)?.selector ?? "ng-app";
1471
+ selectorCache.set(pagePath, selector);
1472
+ return selector;
1473
+ }, injectBeforeClose = (html, snippet) => {
1474
+ if (html.includes("</body>")) {
1475
+ return html.replace("</body>", `${snippet}</body>`);
1476
+ }
1477
+ if (html.includes("</html>")) {
1478
+ return html.replace("</html>", `${snippet}</html>`);
1479
+ }
1480
+ return html + snippet;
1481
+ }, injectSsrScripts = (html, requestId, indexPath, props) => {
1482
+ let result = html;
1483
+ const registeredScripts = getAndClearClientScripts(requestId);
1484
+ if (registeredScripts.length > 0) {
1485
+ result = injectBeforeClose(result, generateClientScriptCode(registeredScripts));
1486
+ }
1487
+ if (props) {
1488
+ result = injectBeforeClose(result, `<script>window.__ABS_ANGULAR_PAGE_PROPS__ = ${JSON.stringify(props)};</script>`);
1489
+ }
1490
+ if (indexPath) {
1491
+ result = injectBeforeClose(result, `<script type="module" src="${indexPath}"></script>`);
1492
+ }
1493
+ return result;
1494
+ }, renderAngularApp = async (deps, PageComponent, providers, document2) => {
1495
+ const bootstrap = (context) => deps.bootstrapApplication(PageComponent, { providers }, context);
1496
+ return withSuppressedAngularDevLogs(() => deps.renderApplication(bootstrap, {
1497
+ document: document2,
1498
+ platformProviders: [],
1499
+ url: "/"
1500
+ }));
1501
+ }, withSuppressedAngularDevLogs = async (render) => {
1502
+ const origLog = console.log;
1503
+ console.log = (...args) => {
1504
+ if (typeof args[0] === "string" && args[0].includes("development mode")) {
1505
+ return;
1855
1506
  }
1856
- });
1507
+ origLog.apply(console, args);
1508
+ };
1509
+ try {
1510
+ return await render();
1511
+ } finally {
1512
+ console.log = origLog;
1513
+ }
1857
1514
  };
1858
- var injectStreamingRuntimeIntoStream = (stream, nonce) => {
1859
- const runtimeTag = renderStreamingSlotsRuntimeTag(nonce);
1860
- const encoder = new TextEncoder;
1861
- const decoder = new TextDecoder;
1862
- const lookbehind = CLOSING_HEAD_TAG_LENGTH - 1;
1863
- return new ReadableStream({
1864
- async start(controller) {
1865
- const reader = stream.getReader();
1866
- let injected = false;
1867
- let pending = "";
1868
- try {
1869
- for (;; ) {
1870
- const { done, value } = await reader.read();
1871
- if (done)
1872
- break;
1873
- if (!value)
1874
- continue;
1875
- pending += streamChunkToString(value, decoder);
1876
- if (injected) {
1877
- controller.enqueue(encoder.encode(pending));
1878
- pending = "";
1879
- continue;
1880
- }
1881
- const headIndex = pending.indexOf(CLOSING_HEAD_TAG);
1882
- if (headIndex >= 0) {
1883
- const withRuntime = `${pending.slice(0, headIndex)}${runtimeTag}${pending.slice(headIndex)}`;
1884
- controller.enqueue(encoder.encode(withRuntime));
1885
- pending = "";
1886
- injected = true;
1887
- continue;
1888
- }
1889
- if (pending.length > lookbehind) {
1890
- const safeText = pending.slice(0, pending.length - lookbehind);
1891
- controller.enqueue(encoder.encode(safeText));
1892
- pending = pending.slice(-lookbehind);
1893
- }
1894
- }
1895
- pending += decoder.decode();
1896
- if (!injected) {
1897
- pending = injectHtmlIntoHead(pending, runtimeTag);
1898
- }
1899
- if (pending.length > 0) {
1900
- controller.enqueue(encoder.encode(pending));
1901
- }
1902
- controller.close();
1903
- } catch (error) {
1904
- controller.error(error);
1905
- }
1906
- }
1515
+ var init_ssrRender = __esm(() => {
1516
+ init_registerClientScript();
1517
+ routePropsCache = new Map;
1518
+ selectorCache = new Map;
1519
+ });
1520
+
1521
+ // src/angular/islands.ts
1522
+ var angularIslandSelector = "abs-angular-island", getAngularIslandSelector = (_islandId) => angularIslandSelector, getSelectorFromRenderedIsland = (rootElement) => {
1523
+ const firstChild = rootElement.firstElementChild;
1524
+ if (!(firstChild instanceof HTMLElement)) {
1525
+ return null;
1526
+ }
1527
+ const selector = firstChild.tagName.toLowerCase();
1528
+ return selector.length > 0 ? selector : null;
1529
+ }, getClientAngularComponentSelector = (component) => {
1530
+ const maybeDef = Reflect.get(component, "\u0275cmp");
1531
+ if (typeof maybeDef !== "object" || maybeDef === null) {
1532
+ return null;
1533
+ }
1534
+ const maybeSelectors = Reflect.get(maybeDef, "selectors");
1535
+ if (!Array.isArray(maybeSelectors)) {
1536
+ return null;
1537
+ }
1538
+ const [firstSelectorGroup] = maybeSelectors;
1539
+ if (!Array.isArray(firstSelectorGroup)) {
1540
+ return null;
1541
+ }
1542
+ const [selector] = firstSelectorGroup;
1543
+ return typeof selector === "string" && selector.length > 0 ? selector : null;
1544
+ }, createAngularIslandApp = async () => {
1545
+ const { EnvironmentInjector, provideZonelessChangeDetection } = await import("@angular/core");
1546
+ const { createApplication } = await import("@angular/platform-browser");
1547
+ const app = await createApplication({
1548
+ providers: [provideZonelessChangeDetection()]
1907
1549
  });
1908
- };
1909
- var appendStreamingSlotPatchesToStream = (stream, slots = [], {
1910
- injectRuntime = true,
1911
- nonce,
1912
- onError,
1913
- onSlotMetric,
1914
- policy
1915
- } = {}) => {
1916
- const resolvedPolicy = resolveStreamingSlotPolicy(policy);
1917
- const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
1918
- const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
1919
- const effectivePolicy = {
1920
- ...resolvedPolicy,
1921
- onSlotMetric: combinedOnSlotMetric
1550
+ const environmentInjector = app.injector.get(EnvironmentInjector);
1551
+ return { app, environmentInjector };
1552
+ }, angularIslandAppPromise = null, getAngularIslandApp = async () => {
1553
+ if (!angularIslandAppPromise) {
1554
+ angularIslandAppPromise = createAngularIslandApp();
1555
+ }
1556
+ return angularIslandAppPromise;
1557
+ }, wrapperMetadataCache, requestRenderCache, getRequestRenderCache = () => {
1558
+ const requestId = getSsrContextId();
1559
+ if (!requestId) {
1560
+ return null;
1561
+ }
1562
+ const cached = requestRenderCache.get(requestId);
1563
+ if (cached) {
1564
+ return cached;
1565
+ }
1566
+ const renderCache = new Map;
1567
+ requestRenderCache.set(requestId, renderCache);
1568
+ return renderCache;
1569
+ }, getAngularIslandWrapperKey = (component, _islandId) => {
1570
+ const componentName = typeof component.name === "string" && component.name.length > 0 ? component.name : "AngularIsland";
1571
+ return `${componentName}:${angularIslandSelector}`;
1572
+ }, getIslandRenderCacheKey = (component, props) => {
1573
+ const componentName = typeof component.name === "string" && component.name.length > 0 ? component.name : "AngularIsland";
1574
+ return `${componentName}:${JSON.stringify(props)}`;
1575
+ }, buildAngularIslandWrapperMetadata = async (component, islandId, wrapperKey) => {
1576
+ const { Component, InjectionToken, inject } = await import("@angular/core");
1577
+ const { NgComponentOutlet } = await import("@angular/common");
1578
+ const deps = await getAngularDeps();
1579
+ const selector = getAngularIslandSelector(islandId);
1580
+ const propsToken = new InjectionToken(`${wrapperKey}:props`);
1581
+
1582
+ class AngularIslandWrapperComponent {
1583
+ component = component;
1584
+ props = inject(propsToken);
1585
+ }
1586
+ return {
1587
+ deps,
1588
+ propsToken,
1589
+ selector,
1590
+ WrapperComponent: Component({
1591
+ imports: [NgComponentOutlet, component],
1592
+ selector,
1593
+ standalone: true,
1594
+ template: '<ng-container *ngComponentOutlet="component; inputs: props"></ng-container>'
1595
+ })(AngularIslandWrapperComponent)
1922
1596
  };
1923
- const preparedSlots = prepareSlots({
1924
- policy: effectivePolicy,
1925
- slots,
1926
- onError: combinedOnError,
1927
- onSlotMetric: combinedOnSlotMetric
1928
- });
1929
- if (preparedSlots.length === 0)
1930
- return stream;
1931
- const source = injectRuntime ? injectStreamingRuntimeIntoStream(stream, nonce) : stream;
1932
- const encoder = new TextEncoder;
1933
- const decoder = new TextDecoder;
1934
- const reader = source.getReader();
1935
- const pending = preparedSlots.map((slot) => resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric));
1936
- return new ReadableStream({
1937
- async start(controller) {
1938
- let baseDone = false;
1939
- let baseRead = reader.read();
1940
- let tail = "";
1941
- let footer = "";
1942
- try {
1943
- while (!baseDone || pending.length > 0) {
1944
- const racers = [];
1945
- if (!baseDone) {
1946
- racers.push(baseRead.then(({ done, value }) => ({
1947
- done,
1948
- kind: "base",
1949
- value
1950
- })));
1951
- }
1952
- if (pending.length > 0) {
1953
- racers.push(nextResolvedSlot(pending).then((resolved) => ({
1954
- kind: "slot",
1955
- ...resolved
1956
- })));
1957
- }
1958
- if (racers.length === 0)
1959
- break;
1960
- const winner = await Promise.race(racers);
1961
- if (winner.kind === "base") {
1962
- if (winner.done) {
1963
- baseDone = true;
1964
- tail += decoder.decode();
1965
- const footerStart = tail.search(CLOSING_PAGE_TAG_REGEX);
1966
- if (footerStart >= 0) {
1967
- const content = tail.slice(0, footerStart);
1968
- footer = tail.slice(footerStart);
1969
- if (content.length > 0) {
1970
- controller.enqueue(encoder.encode(content));
1971
- }
1972
- } else if (tail.length > 0) {
1973
- controller.enqueue(encoder.encode(tail));
1974
- }
1975
- tail = "";
1976
- } else if (winner.value) {
1977
- tail += streamChunkToString(winner.value, decoder);
1978
- if (tail.length > STREAM_TAIL_LOOKBEHIND) {
1979
- const content = tail.slice(0, tail.length - STREAM_TAIL_LOOKBEHIND);
1980
- controller.enqueue(encoder.encode(content));
1981
- tail = tail.slice(-STREAM_TAIL_LOOKBEHIND);
1982
- }
1983
- baseRead = reader.read();
1984
- }
1985
- continue;
1986
- }
1987
- const index = pending.indexOf(winner.original);
1988
- if (index >= 0)
1989
- pending.splice(index, 1);
1990
- if (winner.result.html === null)
1991
- continue;
1992
- emitSlotMetric({
1993
- type: "patched",
1994
- slotId: winner.result.id,
1995
- durationMs: winner.result.durationMs,
1996
- bytes: winner.result.bytes
1997
- }, combinedOnSlotMetric);
1998
- controller.enqueue(encoder.encode(renderStreamingSlotPatchTag(winner.result.id, winner.result.html, nonce)));
1999
- }
2000
- if (footer.length > 0)
2001
- controller.enqueue(encoder.encode(footer));
2002
- controller.close();
2003
- } catch (error) {
2004
- controller.error(error);
2005
- }
2006
- }
1597
+ }, createAngularIslandWrapper = async (component, islandId) => {
1598
+ const wrapperKey = getAngularIslandWrapperKey(component, islandId);
1599
+ const cached = wrapperMetadataCache.get(wrapperKey);
1600
+ if (cached) {
1601
+ return cached;
1602
+ }
1603
+ const metadataPromise = buildAngularIslandWrapperMetadata(component, islandId, wrapperKey);
1604
+ wrapperMetadataCache.set(wrapperKey, metadataPromise);
1605
+ return metadataPromise;
1606
+ }, extractAngularIslandRoot = (html, selector) => {
1607
+ const openTag = `<${selector}`;
1608
+ const start = html.indexOf(openTag);
1609
+ if (start < 0) {
1610
+ throw new Error(`Could not find Angular island root "${selector}".`);
1611
+ }
1612
+ const endTag = `</${selector}>`;
1613
+ const end = html.indexOf(endTag, start);
1614
+ if (end < 0) {
1615
+ throw new Error(`Could not close Angular island root "${selector}".`);
1616
+ }
1617
+ return html.slice(start, end + endTag.length);
1618
+ }, mountAngularIsland = async (component, element, props, islandId) => {
1619
+ await import("@angular/compiler");
1620
+ const { createComponent, inputBinding } = await import("@angular/core");
1621
+ const selector = getAngularIslandSelector(islandId);
1622
+ const { app, environmentInjector } = await getAngularIslandApp();
1623
+ let rootElement = element.querySelector(selector);
1624
+ if (!(rootElement instanceof HTMLElement)) {
1625
+ element.innerHTML = `<${selector}></${selector}>`;
1626
+ rootElement = element.querySelector(selector);
1627
+ }
1628
+ if (!(rootElement instanceof HTMLElement))
1629
+ return app;
1630
+ const componentSelector = getClientAngularComponentSelector(component) ?? getSelectorFromRenderedIsland(rootElement);
1631
+ if (!componentSelector)
1632
+ return app;
1633
+ rootElement.innerHTML = `<${componentSelector}></${componentSelector}>`;
1634
+ const hostElement = rootElement.querySelector(componentSelector);
1635
+ if (!(hostElement instanceof HTMLElement))
1636
+ return app;
1637
+ const bindings = Object.entries(props).map(([key, value]) => inputBinding(key, () => value));
1638
+ const componentRef = createComponent(component, {
1639
+ bindings,
1640
+ environmentInjector,
1641
+ hostElement
2007
1642
  });
1643
+ app.attachView(componentRef.hostView);
1644
+ componentRef.changeDetectorRef.detectChanges();
1645
+ window.__ABS_ANGULAR_ISLAND_APPS__ ??= [];
1646
+ window.__ABS_ANGULAR_ISLAND_APPS__.push(app);
1647
+ return app;
1648
+ }, renderAngularIslandToHtml = async (component, props, islandId) => {
1649
+ const requestCache = getRequestRenderCache();
1650
+ const renderCacheKey = getIslandRenderCacheKey(component, props);
1651
+ const cachedHtml = requestCache?.get(renderCacheKey);
1652
+ if (cachedHtml) {
1653
+ return cachedHtml;
1654
+ }
1655
+ const { deps, propsToken, selector, WrapperComponent } = await createAngularIslandWrapper(component, islandId);
1656
+ const providers = [
1657
+ deps.provideServerRendering(),
1658
+ deps.provideZonelessChangeDetection(),
1659
+ { provide: deps.APP_BASE_HREF, useValue: "/" },
1660
+ { provide: propsToken, useValue: props }
1661
+ ];
1662
+ const document2 = `<!DOCTYPE html><html><body><${selector}></${selector}></body></html>`;
1663
+ const html = await withSuppressedAngularDevLogs(() => deps.renderApplication((context) => deps.bootstrapApplication(WrapperComponent, { providers }, context), {
1664
+ document: document2,
1665
+ platformProviders: [],
1666
+ url: "/"
1667
+ }));
1668
+ const islandHtml = extractAngularIslandRoot(html, selector);
1669
+ requestCache?.set(renderCacheKey, islandHtml);
1670
+ return islandHtml;
2008
1671
  };
1672
+ var init_islands2 = __esm(() => {
1673
+ init_angularDeps();
1674
+ init_ssrRender();
1675
+ init_registerClientScript();
1676
+ wrapperMetadataCache = new Map;
1677
+ requestRenderCache = new Map;
1678
+ });
2009
1679
 
2010
- // src/core/streamingSlotRegistrar.ts
2011
- var registrar = null;
2012
- var setStreamingSlotRegistrar = (nextRegistrar) => {
2013
- registrar = nextRegistrar;
1680
+ // src/core/islandSsr.ts
1681
+ import { createElement } from "react";
1682
+ import { renderToStaticMarkup } from "react-dom/server";
1683
+ import { render as renderSvelte } from "svelte/server";
1684
+ import { createSSRApp, h } from "vue";
1685
+ import { renderToString as renderVueToString } from "vue/server-renderer";
1686
+ var renderReactIslandToHtml = (component, props) => renderToStaticMarkup(createElement(component, props)), renderSvelteIslandToHtml = (component, props) => {
1687
+ const { body } = renderSvelte(component, { props });
1688
+ return body;
1689
+ }, renderVueIslandToHtml = (component, props) => {
1690
+ const app = createSSRApp({
1691
+ render: () => h(component, props)
1692
+ });
1693
+ return renderVueToString(app);
2014
1694
  };
2015
- var registerStreamingSlot = (slot) => {
2016
- registrar?.(slot);
1695
+ var init_islandSsr = __esm(() => {
1696
+ init_islands2();
1697
+ });
1698
+
1699
+ // src/constants.ts
1700
+ 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;
1701
+ var init_constants = __esm(() => {
1702
+ MILLISECONDS_IN_A_MINUTE = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE;
1703
+ MILLISECONDS_IN_A_DAY = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE * MINUTES_IN_AN_HOUR * HOURS_IN_DAY;
1704
+ TWO_THIRDS = 2 / 3;
1705
+ });
1706
+
1707
+ // src/svelte/lowerIslandSyntax.ts
1708
+ var ISLAND_TAG_RE, extractBracedExpression = (text, braceStart) => {
1709
+ let depth = 0;
1710
+ for (let index = braceStart;index < text.length; index += 1) {
1711
+ const char = text[index];
1712
+ if (char === "{")
1713
+ depth += 1;
1714
+ if (char === "}")
1715
+ depth -= 1;
1716
+ if (depth === 0) {
1717
+ return text.slice(braceStart + 1, index).trim();
1718
+ }
1719
+ }
1720
+ return null;
1721
+ }, extractIslandAttribute = (attributeString, name) => {
1722
+ const quotedMatch = attributeString.match(new RegExp(`\\b${name}\\s*=\\s*["']([^"']+)["']`));
1723
+ if (quotedMatch?.[1]) {
1724
+ return { expression: JSON.stringify(quotedMatch[1]), found: true };
1725
+ }
1726
+ const attributeIndex = attributeString.search(new RegExp(`\\b${name}\\s*=\\s*\\{`));
1727
+ if (attributeIndex < 0) {
1728
+ return { expression: "", found: false };
1729
+ }
1730
+ const braceStart = attributeString.indexOf("{", attributeIndex);
1731
+ if (braceStart < 0) {
1732
+ return { expression: "", found: false };
1733
+ }
1734
+ const expression = extractBracedExpression(attributeString, braceStart);
1735
+ if (expression === null) {
1736
+ return { expression: "", found: false };
1737
+ }
1738
+ return { expression, found: true };
1739
+ }, lowerSvelteIslandSyntax = (source, _mode = "server") => {
1740
+ if (!source.includes("<Island")) {
1741
+ return { code: source, transformed: false };
1742
+ }
1743
+ let islandIndex = 0;
1744
+ const transformedMarkup = source.replace(ISLAND_TAG_RE, (fullMatch, attributeString) => {
1745
+ const framework = extractIslandAttribute(attributeString, "framework");
1746
+ const component = extractIslandAttribute(attributeString, "component");
1747
+ if (!framework.found || !component.found) {
1748
+ return fullMatch;
1749
+ }
1750
+ const hydrate = extractIslandAttribute(attributeString, "hydrate");
1751
+ const props = extractIslandAttribute(attributeString, "props");
1752
+ const slotId = `absolute-svelte-island-${islandIndex.toString(BASE_36_RADIX)}`;
1753
+ islandIndex += 1;
1754
+ const resolveExpression = `await __absoluteResolveIslandHtml(${JSON.stringify(slotId)}, { component: ${component.expression}, framework: ${framework.expression}, hydrate: ${hydrate.found ? hydrate.expression : JSON.stringify("load")}, props: ${props.found ? props.expression : "{}"} })`;
1755
+ return `<div data-absolute-island-slot="${slotId}" style="display: contents">{@html ${resolveExpression}}</div>`;
1756
+ });
1757
+ const importLine = 'import { resolveIslandHtml as __absoluteResolveIslandHtml } from "@absolutejs/absolute/svelte";';
1758
+ if (transformedMarkup.includes("<script")) {
1759
+ return {
1760
+ code: transformedMarkup.replace(/<script(\s[^>]*)?>/, (match) => `${match}
1761
+ ${importLine}
1762
+ `),
1763
+ transformed: true
1764
+ };
1765
+ }
1766
+ return {
1767
+ code: `<script lang="ts">
1768
+ ${importLine}
1769
+ </script>
1770
+ ${transformedMarkup}`,
1771
+ transformed: true
1772
+ };
2017
1773
  };
1774
+ var init_lowerIslandSyntax = __esm(() => {
1775
+ init_constants();
1776
+ ISLAND_TAG_RE = /<Island\b([\s\S]*?)\/>/g;
1777
+ });
2018
1778
 
2019
- // src/core/streamingSlotRegistry.ts
2020
- var asyncLocalStorage;
2021
- var isServerRuntime = () => typeof process !== "undefined" && typeof process.versions?.node === "string";
2022
- var ensureAsyncLocalStorage = async () => {
2023
- if (typeof asyncLocalStorage !== "undefined")
2024
- return asyncLocalStorage;
2025
- if (!isServerRuntime()) {
2026
- asyncLocalStorage = null;
2027
- return asyncLocalStorage;
1779
+ // src/core/svelteServerModule.ts
1780
+ import { mkdir, readdir } from "fs/promises";
1781
+ import { basename as basename2, dirname as dirname2, extname, join as join2, relative, resolve as resolve3 } from "path";
1782
+ var serverCacheRoot, compiledModuleCache, originalSourcePathCache, transpiler, ensureRelativeImportPath = (from, target) => {
1783
+ const importPath = relative(dirname2(from), target).replace(/\\/g, "/");
1784
+ return importPath.startsWith(".") ? importPath : `./${importPath}`;
1785
+ }, processDirectoryEntries = (entries, dir, targetFileName, stack) => {
1786
+ for (const entry of entries) {
1787
+ const entryPath = join2(dir, entry.name);
1788
+ if (entry.isDirectory())
1789
+ stack.push(entryPath);
1790
+ if (entry.isFile() && entry.name === targetFileName) {
1791
+ return entryPath;
1792
+ }
1793
+ }
1794
+ return null;
1795
+ }, searchDirectoryLevel = async (dirs, targetFileName) => {
1796
+ if (dirs.length === 0)
1797
+ return null;
1798
+ const nextStack = [];
1799
+ const dirEntries = await Promise.all(dirs.map(async (dir) => ({
1800
+ dir,
1801
+ entries: await readdir(dir, {
1802
+ encoding: "utf-8",
1803
+ withFileTypes: true
1804
+ })
1805
+ })));
1806
+ for (const { dir, entries } of dirEntries) {
1807
+ const found = processDirectoryEntries(entries, dir, targetFileName, nextStack);
1808
+ if (found)
1809
+ return found;
1810
+ }
1811
+ return searchDirectoryLevel(nextStack, targetFileName);
1812
+ }, findSourceFileByBasename = async (searchRoot, targetFileName) => searchDirectoryLevel([searchRoot], targetFileName), normalizeBuiltSvelteFileName = (sourcePath) => basename2(sourcePath).replace(/-[a-z0-9]{6,}(?=\.svelte$)/i, ""), resolveOriginalSourcePath = async (sourcePath) => {
1813
+ const cachedPath = originalSourcePathCache.get(sourcePath);
1814
+ if (cachedPath !== undefined) {
1815
+ return cachedPath;
1816
+ }
1817
+ if (!sourcePath.includes(`${join2(process.cwd(), "build")}${process.platform === "win32" ? "" : "/"}`) && !sourcePath.includes("/build/")) {
1818
+ originalSourcePathCache.set(sourcePath, sourcePath);
1819
+ return sourcePath;
1820
+ }
1821
+ const resolvedSourcePath = await findSourceFileByBasename(join2(process.cwd(), "src"), normalizeBuiltSvelteFileName(sourcePath));
1822
+ const nextPath = resolvedSourcePath ?? sourcePath;
1823
+ originalSourcePathCache.set(sourcePath, nextPath);
1824
+ return nextPath;
1825
+ }, resolveRelativeModule = async (spec, from) => {
1826
+ if (!spec.startsWith(".")) {
1827
+ return null;
1828
+ }
1829
+ const basePath = resolve3(dirname2(from), spec);
1830
+ const candidates = [
1831
+ basePath,
1832
+ `${basePath}.ts`,
1833
+ `${basePath}.js`,
1834
+ `${basePath}.mjs`,
1835
+ `${basePath}.cjs`,
1836
+ `${basePath}.json`,
1837
+ join2(basePath, "index.ts"),
1838
+ join2(basePath, "index.js"),
1839
+ join2(basePath, "index.mjs"),
1840
+ join2(basePath, "index.cjs"),
1841
+ join2(basePath, "index.json")
1842
+ ];
1843
+ const existResults = await Promise.all(candidates.map((candidate) => Bun.file(candidate).exists()));
1844
+ const foundIndex = existResults.indexOf(true);
1845
+ return foundIndex >= 0 ? candidates[foundIndex] ?? null : null;
1846
+ }, getCachedModulePath = (sourcePath) => {
1847
+ const relativeSourcePath = relative(process.cwd(), sourcePath).replace(/\\/g, "/");
1848
+ const normalizedSourcePath = relativeSourcePath.startsWith("..") ? sourcePath.replace(/[:\\/]/g, "_") : relativeSourcePath;
1849
+ return join2(serverCacheRoot, `${normalizedSourcePath}.server.js`);
1850
+ }, resolveSvelteImport = async (spec, from) => {
1851
+ if (spec.startsWith("/")) {
1852
+ return spec;
1853
+ }
1854
+ if (!spec.startsWith(".")) {
1855
+ return null;
1856
+ }
1857
+ const explicitPath = resolve3(dirname2(from), spec);
1858
+ if (extname(explicitPath) === ".svelte") {
1859
+ return explicitPath;
1860
+ }
1861
+ const candidate = `${explicitPath}.svelte`;
1862
+ if (await Bun.file(candidate).exists() === true) {
1863
+ return candidate;
1864
+ }
1865
+ return null;
1866
+ }, writeIfChanged = async (path, content) => {
1867
+ const targetFile = Bun.file(path);
1868
+ const exists = await targetFile.exists();
1869
+ if (exists) {
1870
+ const currentContent = await targetFile.text();
1871
+ if (currentContent === content) {
1872
+ return;
1873
+ }
2028
1874
  }
2029
- const mod = await import("async_hooks");
2030
- asyncLocalStorage = new mod.AsyncLocalStorage;
2031
- return asyncLocalStorage;
2032
- };
2033
- var registerStreamingSlot2 = (slot) => {
2034
- if (!asyncLocalStorage)
2035
- return;
2036
- const store = asyncLocalStorage.getStore();
2037
- if (!store)
2038
- return;
2039
- store.set(slot.id, slot);
2040
- };
2041
- setStreamingSlotRegistrar(registerStreamingSlot2);
2042
- var runWithStreamingSlotRegistry = async (task) => {
2043
- const storage = await ensureAsyncLocalStorage();
2044
- if (!storage) {
2045
- return {
2046
- result: await task(),
2047
- slots: []
2048
- };
1875
+ await Bun.write(path, content);
1876
+ }, compileSvelteServerModule = async (sourcePath) => {
1877
+ const cachedModulePath = compiledModuleCache.get(sourcePath);
1878
+ if (cachedModulePath) {
1879
+ return cachedModulePath;
2049
1880
  }
2050
- return storage.run(new Map, async () => {
2051
- const result = await task();
2052
- const store = storage.getStore();
1881
+ const resolutionSourcePath = await resolveOriginalSourcePath(sourcePath);
1882
+ const source = await Bun.file(sourcePath).text();
1883
+ const { compile, preprocess } = await import("svelte/compiler");
1884
+ const loweredSource = lowerSvelteIslandSyntax(source, "server");
1885
+ const preprocessed = await preprocess(loweredSource.code, {});
1886
+ let transpiled = sourcePath.endsWith(".ts") || sourcePath.endsWith(".svelte.ts") ? transpiler.transformSync(preprocessed.code) : preprocessed.code;
1887
+ const childImportSpecs = Array.from(transpiled.matchAll(/from\s+['"]([^'"]+)['"]/g)).map((match) => match[1]).filter((value) => value !== undefined);
1888
+ const resolvedChildModules = await Promise.all(childImportSpecs.map((spec) => resolveSvelteImport(spec, resolutionSourcePath)));
1889
+ const resolvedModuleImports = await Promise.all(childImportSpecs.map((spec) => resolveRelativeModule(spec, resolutionSourcePath)));
1890
+ const childModulePaths = new Map;
1891
+ const rewrittenModulePaths = new Map;
1892
+ const compiledChildren = await Promise.all(childImportSpecs.map(async (spec, index) => {
1893
+ const resolvedChild = resolvedChildModules[index];
1894
+ if (!spec || !resolvedChild)
1895
+ return null;
2053
1896
  return {
2054
- result,
2055
- slots: store ? [...store.values()] : []
1897
+ compiledPath: await compileSvelteServerModule(resolvedChild),
1898
+ spec
2056
1899
  };
2057
- });
2058
- };
2059
-
2060
- // src/core/responseEnhancers.ts
2061
- var toResponse = async (responseLike) => await responseLike;
2062
- var cloneHeaders = (response) => {
2063
- const headers = new Headers(response.headers);
2064
- return headers;
2065
- };
2066
- var enhanceHtmlResponseWithStreamingSlots = (response, { nonce, onError, streamingSlots = [], policy } = {}) => {
2067
- if (!response.body || streamingSlots.length === 0) {
2068
- return response;
1900
+ }));
1901
+ for (const result of compiledChildren) {
1902
+ if (result)
1903
+ childModulePaths.set(result.spec, result.compiledPath);
2069
1904
  }
2070
- const body = appendStreamingSlotPatchesToStream(response.body, streamingSlots, {
2071
- nonce,
2072
- onError,
2073
- policy
2074
- });
2075
- return new Response(body, {
2076
- headers: cloneHeaders(response),
2077
- status: response.status,
2078
- statusText: response.statusText
2079
- });
2080
- };
2081
- var withStreamingSlots = async (responseLike, options = {}) => enhanceHtmlResponseWithStreamingSlots(await toResponse(responseLike), options);
2082
- var mergeStreamingSlots = (registered, explicit) => {
2083
- const merged = new Map;
2084
- for (const slot of registered)
2085
- merged.set(slot.id, slot);
2086
- for (const slot of explicit)
2087
- merged.set(slot.id, slot);
2088
- return [...merged.values()];
1905
+ for (let index = 0;index < childImportSpecs.length; index += 1) {
1906
+ const spec = childImportSpecs[index];
1907
+ const resolvedModuleImport = resolvedModuleImports[index];
1908
+ if (!spec || !resolvedModuleImport)
1909
+ continue;
1910
+ if (resolvedChildModules[index])
1911
+ continue;
1912
+ rewrittenModulePaths.set(spec, ensureRelativeImportPath(getCachedModulePath(sourcePath), resolvedModuleImport));
1913
+ }
1914
+ for (const [spec, resolvedModuleImport] of rewrittenModulePaths) {
1915
+ transpiled = transpiled.replaceAll(spec, resolvedModuleImport);
1916
+ }
1917
+ let compiledCode = compile(transpiled, {
1918
+ css: "injected",
1919
+ experimental: {
1920
+ async: loweredSource.transformed
1921
+ },
1922
+ filename: resolutionSourcePath,
1923
+ generate: "server"
1924
+ }).js.code;
1925
+ for (const [spec, compiledChildPath] of childModulePaths) {
1926
+ compiledCode = compiledCode.replaceAll(spec, ensureRelativeImportPath(getCachedModulePath(sourcePath), compiledChildPath));
1927
+ }
1928
+ for (const [spec, resolvedModuleImport] of rewrittenModulePaths) {
1929
+ compiledCode = compiledCode.replaceAll(spec, resolvedModuleImport);
1930
+ }
1931
+ const compiledModulePath = getCachedModulePath(sourcePath);
1932
+ await mkdir(dirname2(compiledModulePath), { recursive: true });
1933
+ await writeIfChanged(compiledModulePath, compiledCode);
1934
+ compiledModuleCache.set(sourcePath, compiledModulePath);
1935
+ return compiledModulePath;
2089
1936
  };
2090
- var withRegisteredStreamingSlots = async (renderResponse, options = {}) => {
2091
- const { result, slots } = await runWithStreamingSlotRegistry(renderResponse);
2092
- const explicit = options.streamingSlots ?? [];
2093
- return withStreamingSlots(result, {
2094
- ...options,
2095
- streamingSlots: mergeStreamingSlots(slots, explicit)
1937
+ var init_svelteServerModule = __esm(() => {
1938
+ init_lowerIslandSyntax();
1939
+ serverCacheRoot = join2(process.cwd(), ".absolutejs", "islands", "svelte");
1940
+ compiledModuleCache = new Map;
1941
+ originalSourcePathCache = new Map;
1942
+ transpiler = new Bun.Transpiler({
1943
+ loader: "ts",
1944
+ target: "browser"
2096
1945
  });
2097
- };
1946
+ });
2098
1947
 
2099
- // src/core/wrapPageHandlerWithStreamingSlots.ts
2100
- var wrapPageHandlerWithStreamingSlots = (handler) => (...args) => withRegisteredStreamingSlots(() => handler(...args));
1948
+ // src/core/renderIslandMarkup.ts
1949
+ var islandSequence = 0, resolvedServerComponentCache, resolvedServerBuildComponentCache, nextIslandId = () => {
1950
+ islandSequence += 1;
1951
+ return `island-${islandSequence}`;
1952
+ }, isRecord2 = (value) => typeof value === "object" && value !== null, isReactServerIslandComponent = (value) => typeof value === "function", isSvelteServerIslandComponent = (value) => typeof value === "function", isVueServerIslandComponent = (value) => typeof value === "function" || isRecord2(value), isAngularServerIslandComponent = (value) => typeof value === "function", resolveBuildReferencePath = (source, registryPath) => {
1953
+ if (source.startsWith("file://"))
1954
+ return new URL(source).pathname;
1955
+ if (source.startsWith("."))
1956
+ return new URL(source, registryPath).pathname;
1957
+ return source;
1958
+ }, loadAndCompileServerBuildComponent = async (buildReferencePath) => {
1959
+ const compiledModulePath = await compileSvelteServerModule(buildReferencePath);
1960
+ const loadedModule = await import(compiledModulePath);
1961
+ return "default" in loadedModule ? loadedModule.default : loadedModule;
1962
+ }, loadServerBuildComponent = async (buildReferencePath) => {
1963
+ const cachedBuildComponent = resolvedServerBuildComponentCache.get(buildReferencePath);
1964
+ if (cachedBuildComponent) {
1965
+ return cachedBuildComponent;
1966
+ }
1967
+ const loadPromise = loadAndCompileServerBuildComponent(buildReferencePath);
1968
+ resolvedServerBuildComponentCache.set(buildReferencePath, loadPromise);
1969
+ return loadPromise;
1970
+ }, loadServerImportComponent = async (resolvedComponent) => {
1971
+ const resolvedModulePath = resolvedComponent.startsWith(".") ? new URL(resolvedComponent, import.meta.url).pathname : resolvedComponent;
1972
+ const importTarget = resolvedModulePath.endsWith(".svelte") ? await compileSvelteServerModule(resolvedModulePath) : resolvedModulePath;
1973
+ const loadedModule = await import(importTarget);
1974
+ return "default" in loadedModule ? loadedModule.default : loadedModule;
1975
+ }, resolveIslandComponent = async (component) => {
1976
+ const buildReference = getIslandBuildReference(component);
1977
+ const buildReferencePath = buildReference?.source ? resolveBuildReferencePath(buildReference.source, import.meta.url) : null;
1978
+ if (buildReferencePath?.endsWith(".svelte")) {
1979
+ return loadServerBuildComponent(buildReferencePath);
1980
+ }
1981
+ const resolvedComponent = getIslandComponent(component);
1982
+ if (typeof resolvedComponent !== "string") {
1983
+ return resolvedComponent;
1984
+ }
1985
+ return loadServerImportComponent(resolvedComponent);
1986
+ }, resolveServerIslandComponent = async (component) => {
1987
+ const cachedResolvedComponent = resolvedServerComponentCache.get(component);
1988
+ if (cachedResolvedComponent) {
1989
+ return cachedResolvedComponent;
1990
+ }
1991
+ const resolutionPromise = resolveIslandComponent(component);
1992
+ resolvedServerComponentCache.set(component, resolutionPromise);
1993
+ return resolutionPromise;
1994
+ }, resolveReactServerIslandComponent = async (component) => {
1995
+ const resolvedComponent = await resolveServerIslandComponent(component);
1996
+ if (!isReactServerIslandComponent(resolvedComponent)) {
1997
+ throw new Error("Resolved React island is not a valid React component.");
1998
+ }
1999
+ return resolvedComponent;
2000
+ }, resolveSvelteServerIslandComponent = async (component) => {
2001
+ const resolvedComponent = await resolveServerIslandComponent(component);
2002
+ if (!isSvelteServerIslandComponent(resolvedComponent)) {
2003
+ throw new Error("Resolved Svelte island is not a valid Svelte component.");
2004
+ }
2005
+ return resolvedComponent;
2006
+ }, resolveVueServerIslandComponent = async (component) => {
2007
+ const resolvedComponent = await resolveServerIslandComponent(component);
2008
+ if (!isVueServerIslandComponent(resolvedComponent)) {
2009
+ throw new Error("Resolved Vue island is not a valid Vue component.");
2010
+ }
2011
+ return resolvedComponent;
2012
+ }, resolveAngularServerIslandComponent = async (component) => {
2013
+ const resolvedComponent = await resolveServerIslandComponent(component);
2014
+ if (!isAngularServerIslandComponent(resolvedComponent)) {
2015
+ throw new Error("Resolved Angular island is not a valid Angular component.");
2016
+ }
2017
+ return resolvedComponent;
2018
+ }, renderIslandMarkup = async (registry, props) => {
2019
+ const result = await renderIslandResult(registry, props);
2020
+ return `<div ${serializeIslandAttributes(result.attributes)}>${result.html}</div>`;
2021
+ }, renderIslandResult = async (registry, props) => {
2022
+ const islandId = nextIslandId();
2023
+ const attributes = getIslandMarkerAttributes(props);
2024
+ if (props.framework === "react") {
2025
+ const entry = registry.react?.[props.component];
2026
+ if (!entry) {
2027
+ throw new Error(`Island component "${props.component}" is not registered for framework "react".`);
2028
+ }
2029
+ const component = await resolveReactServerIslandComponent(entry);
2030
+ const html = renderReactIslandToHtml(component, props.props);
2031
+ return { attributes, html };
2032
+ }
2033
+ if (props.framework === "svelte") {
2034
+ const entry = registry.svelte?.[props.component];
2035
+ if (!entry) {
2036
+ throw new Error(`Island component "${props.component}" is not registered for framework "svelte".`);
2037
+ }
2038
+ const component = await resolveSvelteServerIslandComponent(entry);
2039
+ const html = renderSvelteIslandToHtml(component, props.props);
2040
+ return { attributes, html };
2041
+ }
2042
+ if (props.framework === "vue") {
2043
+ const entry = registry.vue?.[props.component];
2044
+ if (!entry) {
2045
+ throw new Error(`Island component "${props.component}" is not registered for framework "vue".`);
2046
+ }
2047
+ const component = await resolveVueServerIslandComponent(entry);
2048
+ const html = await renderVueIslandToHtml(component, props.props);
2049
+ return { attributes, html };
2050
+ }
2051
+ if (props.framework === "angular") {
2052
+ const entry = registry.angular?.[props.component];
2053
+ if (!entry) {
2054
+ throw new Error(`Island component "${props.component}" is not registered for framework "angular".`);
2055
+ }
2056
+ const component = await resolveAngularServerIslandComponent(entry);
2057
+ const html = await renderAngularIslandToHtml(component, props.props, islandId);
2058
+ return {
2059
+ attributes: {
2060
+ ...getIslandMarkerAttributes(props, islandId)
2061
+ },
2062
+ html
2063
+ };
2064
+ }
2065
+ throw new Error(`Framework "${props.framework}" is not implemented in this prototype.`);
2066
+ };
2067
+ var init_renderIslandMarkup = __esm(() => {
2068
+ init_islandSsr();
2069
+ init_svelteServerModule();
2070
+ init_islandMarkupAttributes();
2071
+ init_islands();
2072
+ resolvedServerComponentCache = new Map;
2073
+ resolvedServerBuildComponentCache = new Map;
2074
+ });
2101
2075
 
2102
2076
  // src/react/index.ts
2103
2077
  init_pageHandler();
@@ -2105,16 +2079,16 @@ init_pageHandler();
2105
2079
  // src/react/Island.tsx
2106
2080
  init_islandMarkupAttributes();
2107
2081
  init_renderIslandMarkup();
2108
- import { jsxDEV } from "react/jsx-dev-runtime";
2082
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
2109
2083
  var Island = async (props) => {
2110
2084
  if (typeof window !== "undefined") {
2111
- return /* @__PURE__ */ jsxDEV("div", {
2085
+ return /* @__PURE__ */ jsxDEV2("div", {
2112
2086
  ...getIslandMarkerAttributes(props),
2113
2087
  suppressHydrationWarning: true
2114
2088
  }, undefined, false, undefined, this);
2115
2089
  }
2116
2090
  const result = await renderIslandResult(requireCurrentIslandRegistry(), props);
2117
- return /* @__PURE__ */ jsxDEV("div", {
2091
+ return /* @__PURE__ */ jsxDEV2("div", {
2118
2092
  ...result.attributes,
2119
2093
  dangerouslySetInnerHTML: { __html: result.html }
2120
2094
  }, undefined, false, undefined, this);
@@ -2122,17 +2096,17 @@ var Island = async (props) => {
2122
2096
  // src/react/createIsland.tsx
2123
2097
  init_islandMarkupAttributes();
2124
2098
  init_renderIslandMarkup();
2125
- import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
2099
+ import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
2126
2100
  var createTypedIsland = (registry) => {
2127
2101
  const Island2 = async (props) => {
2128
2102
  if (typeof window !== "undefined") {
2129
- return /* @__PURE__ */ jsxDEV2("div", {
2103
+ return /* @__PURE__ */ jsxDEV3("div", {
2130
2104
  ...getIslandMarkerAttributes(props),
2131
2105
  suppressHydrationWarning: true
2132
2106
  }, undefined, false, undefined, this);
2133
2107
  }
2134
2108
  const result = await renderIslandResult(registry, props);
2135
- return /* @__PURE__ */ jsxDEV2("div", {
2109
+ return /* @__PURE__ */ jsxDEV3("div", {
2136
2110
  ...result.attributes,
2137
2111
  dangerouslySetInnerHTML: { __html: result.html }
2138
2112
  }, undefined, false, undefined, this);
@@ -2259,15 +2233,12 @@ var subscribeIslandStore = (store, selector, listener) => {
2259
2233
  var useIslandStore = (store, selector) => useSyncExternalStore((listener) => subscribeIslandStore(store, selector, () => {
2260
2234
  listener();
2261
2235
  }), () => readIslandStore(store, selector), () => getIslandStoreServerSnapshot(store, selector));
2262
-
2263
- // src/react/index.ts
2264
- var handleReactPageRequest2 = wrapPageHandlerWithStreamingSlots(handleReactPageRequest);
2265
2236
  export {
2266
2237
  useIslandStore,
2267
- handleReactPageRequest2 as handleReactPageRequest,
2238
+ handleReactPageRequest,
2268
2239
  createTypedIsland,
2269
2240
  Island
2270
2241
  };
2271
2242
 
2272
- //# debugId=570A0BC29167FAF664756E2164756E21
2243
+ //# debugId=15AFCB77217FB62264756E2164756E21
2273
2244
  //# sourceMappingURL=index.js.map