@absolutejs/absolute 0.19.0-beta.317 → 0.19.0-beta.319

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -203,1389 +203,9 @@ var defineIslandRegistry = (registry) => registry, defineIslandComponent = (comp
203
203
  };
204
204
  var init_islands = () => {};
205
205
 
206
- // src/core/islandPageContext.ts
207
- var BOOTSTRAP_MANIFEST_KEY = "BootstrapClient", ISLAND_MARKER = 'data-island="true"', MANIFEST_MARKER = "__ABSOLUTE_MANIFEST__", ISLAND_STATE_MARKER = "__ABS_ISLAND_STATE__", buildIslandsHeadMarkup = (manifest) => {
208
- const manifestScript = `<script>window.__ABSOLUTE_MANIFEST__ = ${JSON.stringify(manifest)}</script>`;
209
- const islandStateScript = "<script>window.__ABS_ISLAND_STATE__ = window.__ABS_ISLAND_STATE__ ?? {}</script>";
210
- const bootstrapPath = manifest[BOOTSTRAP_MANIFEST_KEY];
211
- const bootstrapScript = bootstrapPath ? `<script type="module" src="${bootstrapPath}"></script>` : "";
212
- return `${manifestScript}${islandStateScript}${bootstrapScript}`;
213
- }, injectHeadMarkup = (html, markup) => {
214
- const closingHeadIndex = html.indexOf("</head>");
215
- if (closingHeadIndex >= 0) {
216
- return `${html.slice(0, closingHeadIndex)}${markup}${html.slice(closingHeadIndex)}`;
217
- }
218
- const openingBodyIndex = html.indexOf("<body");
219
- if (openingBodyIndex >= 0) {
220
- const bodyStart = html.indexOf(">", openingBodyIndex);
221
- if (bodyStart >= 0) {
222
- return `${html.slice(0, openingBodyIndex)}<head>${markup}</head>${html.slice(openingBodyIndex)}`;
223
- }
224
- }
225
- return `<!DOCTYPE html><html><head>${markup}</head><body>${html}</body></html>`;
226
- }, setCurrentIslandManifest = (manifest) => {
227
- globalThis.__absoluteManifest = manifest;
228
- }, htmlContainsIslands = (html) => html.includes(ISLAND_MARKER), injectIslandPageContext = (html, options) => {
229
- const manifest = globalThis.__absoluteManifest;
230
- const hasIslands = options?.hasIslands ?? htmlContainsIslands(html);
231
- if (!manifest || !hasIslands) {
232
- return html;
233
- }
234
- if (html.includes(MANIFEST_MARKER) || html.includes(ISLAND_STATE_MARKER)) {
235
- return html;
236
- }
237
- return injectHeadMarkup(html, buildIslandsHeadMarkup(manifest));
238
- };
239
-
240
- // src/utils/ssrErrorPage.ts
241
- var ssrErrorPage = (framework, error) => {
242
- const frameworkColors = {
243
- angular: "#dd0031",
244
- html: "#e34c26",
245
- htmx: "#1a365d",
246
- react: "#61dafb",
247
- svelte: "#ff3e00",
248
- vue: "#42b883"
249
- };
250
- const accent = frameworkColors[framework] ?? "#94a3b8";
251
- const label = framework.charAt(0).toUpperCase() + framework.slice(1);
252
- const message = error instanceof Error ? error.message : String(error);
253
- return `<!DOCTYPE html>
254
- <html>
255
- <head>
256
- <meta charset="utf-8">
257
- <meta name="viewport" content="width=device-width, initial-scale=1">
258
- <title>SSR Error - AbsoluteJS</title>
259
- <style>
260
- *{margin:0;padding:0;box-sizing:border-box}
261
- body{min-height:100vh;background:linear-gradient(135deg,rgba(15,23,42,0.98) 0%,rgba(30,41,59,0.98) 100%);color:#e2e8f0;font-family:"JetBrains Mono","Fira Code",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:14px;line-height:1.6;display:flex;align-items:flex-start;justify-content:center;padding:32px}
262
- .card{max-width:720px;width:100%;background:rgba(30,41,59,0.6);border:1px solid rgba(71,85,105,0.5);border-radius:16px;box-shadow:0 25px 50px -12px rgba(0,0,0,0.5),0 0 0 1px rgba(255,255,255,0.05);overflow:hidden}
263
- .header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:20px 24px;background:rgba(15,23,42,0.5);border-bottom:1px solid rgba(71,85,105,0.4)}
264
- .brand{font-weight:700;font-size:20px;color:#fff;letter-spacing:-0.02em}
265
- .badge{padding:5px 10px;border-radius:8px;font-size:12px;font-weight:600;background:${accent};color:#fff;opacity:0.95;box-shadow:0 2px 4px rgba(0,0,0,0.2)}
266
- .kind{color:#94a3b8;font-size:13px;font-weight:500}
267
- .content{padding:24px}
268
- .label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.08em;color:#94a3b8;margin-bottom:8px}
269
- .message{margin:0;padding:16px 20px;background:rgba(239,68,68,0.12);border:1px solid rgba(239,68,68,0.25);border-radius:10px;overflow-x:auto;white-space:pre-wrap;word-break:break-word;color:#fca5a5;font-size:13px;line-height:1.5}
270
- .hint{margin-top:20px;padding:12px 20px;background:rgba(71,85,105,0.3);border-radius:10px;border:1px solid rgba(71,85,105,0.4);color:#cbd5e1;font-size:13px}
271
- </style>
272
- </head>
273
- <body>
274
- <div class="card">
275
- <div class="header">
276
- <div style="display:flex;align-items:center;gap:12px">
277
- <span class="brand">AbsoluteJS</span>
278
- <span class="badge">${label}</span>
279
- </div>
280
- <span class="kind">Server Render Error</span>
281
- </div>
282
- <div class="content">
283
- <div class="label">What went wrong</div>
284
- <pre class="message">${message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")}</pre>
285
- <div class="hint">A component threw during server-side rendering. Check the terminal for the full stack trace.</div>
286
- </div>
287
- </div>
288
- </body>
289
- </html>`;
290
- };
291
-
292
- // src/utils/stringModifiers.ts
293
- var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9\-_]+/g, "").replace(/[-_]{2,}/g, "-"), toKebab = (str) => normalizeSlug(str).replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), toPascal = (str) => {
294
- if (!str.includes("-") && !str.includes("_")) {
295
- return str.charAt(0).toUpperCase() + str.slice(1);
296
- }
297
- return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
298
- }, toScreamingSnake = (str) => str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase();
299
-
300
- // src/utils/resolveConvention.ts
301
- import { basename } from "path";
302
- var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boolean(value) && typeof value === "object", getMap = () => {
303
- const value = Reflect.get(globalThis, CONVENTIONS_KEY);
304
- if (isConventionsMap(value))
305
- return value;
306
- const empty = {};
307
- return empty;
308
- }, derivePageName = (pagePath) => {
309
- const base = basename(pagePath);
310
- const dotIndex = base.indexOf(".");
311
- const name = dotIndex > 0 ? base.slice(0, dotIndex) : base;
312
- return toPascal(name);
313
- }, resolveErrorConventionPath = (framework, pageName) => {
314
- const conventions2 = getMap()[framework];
315
- if (!conventions2)
316
- return;
317
- return conventions2.pages?.[pageName]?.error ?? conventions2.defaults?.error;
318
- }, resolveNotFoundConventionPath = (framework) => getMap()[framework]?.defaults?.notFound, setConventions = (map) => {
319
- Reflect.set(globalThis, CONVENTIONS_KEY, map);
320
- }, isDev = () => true, buildErrorProps = (error) => {
321
- const message = error instanceof Error ? error.message : String(error);
322
- const stack = isDev() && error instanceof Error ? error.stack : undefined;
323
- return { error: { message, stack } };
324
- }, renderReactError = async (conventionPath, errorProps) => {
325
- const { createElement } = await import("react");
326
- const { renderToReadableStream } = await import("react-dom/server");
327
- const mod = await import(conventionPath);
328
- const [firstKey] = Object.keys(mod);
329
- const ErrorComponent = mod.default ?? (firstKey ? mod[firstKey] : undefined);
330
- const element = createElement(ErrorComponent, errorProps);
331
- const stream = await renderToReadableStream(element);
332
- return new Response(stream, {
333
- headers: { "Content-Type": "text/html" },
334
- status: 500
335
- });
336
- }, renderSvelteError = async (conventionPath, errorProps) => {
337
- const { render } = await import("svelte/server");
338
- const mod = await import(conventionPath);
339
- const ErrorComponent = mod.default;
340
- const { head, body } = render(ErrorComponent, {
341
- props: errorProps
342
- });
343
- const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
344
- return new Response(html, {
345
- headers: { "Content-Type": "text/html" },
346
- status: 500
347
- });
348
- }, unescapeVueStyles = (ssrBody) => {
349
- let styles = "";
350
- const body = ssrBody.replace(/<style>([\s\S]*?)<\/style>/g, (_, css) => {
351
- styles += `<style>${css.replace(/&quot;/g, '"').replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">")}</style>`;
352
- return "";
353
- });
354
- return { body, styles };
355
- }, renderVueError = async (conventionPath, errorProps) => {
356
- const { createSSRApp, h } = await import("vue");
357
- const { renderToString } = await import("vue/server-renderer");
358
- const mod = await import(conventionPath);
359
- const ErrorComponent = mod.default;
360
- const app = createSSRApp({
361
- render: () => h(ErrorComponent, errorProps)
362
- });
363
- const rawBody = await renderToString(app);
364
- const { styles, body } = unescapeVueStyles(rawBody);
365
- const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
366
- return new Response(html, {
367
- headers: { "Content-Type": "text/html" },
368
- status: 500
369
- });
370
- }, renderAngularError = async (conventionPath, errorProps) => {
371
- const mod = await import(conventionPath);
372
- const renderError = mod.default ?? mod.renderError;
373
- if (typeof renderError !== "function")
374
- return null;
375
- const html = renderError(errorProps);
376
- return new Response(html, {
377
- headers: { "Content-Type": "text/html" },
378
- status: 500
379
- });
380
- }, logConventionRenderError = (framework, label, renderError) => {
381
- const message = renderError instanceof Error ? renderError.message : "";
382
- if (message.includes("Cannot find module") || message.includes("Cannot find package") || message.includes("not found in module")) {
383
- console.error(`[SSR] Convention ${label} page for ${framework} failed: missing framework package. Ensure the ${framework} runtime is installed (e.g. bun add ${framework === "react" ? "react react-dom" : framework}).`);
384
- return;
385
- }
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);
459
- }
460
- return null;
461
- }, NOT_FOUND_PRIORITY, renderFirstNotFound = async () => {
462
- for (const framework of NOT_FOUND_PRIORITY) {
463
- if (!getMap()[framework]?.defaults?.notFound)
464
- continue;
465
- const response = await renderConventionNotFound(framework);
466
- if (response)
467
- return response;
468
- }
469
- return null;
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" }
501
- });
502
- }, handleReactPageRequest = async (PageComponent, index, ...props) => {
503
- const [maybeProps] = props;
504
- if (ssrDirty) {
505
- return buildDirtyResponse(index, maybeProps);
506
- }
507
- try {
508
- const { createElement } = await import("react");
509
- const { renderToReadableStream } = await import("react-dom/server");
510
- const element = maybeProps !== undefined ? createElement(PageComponent, maybeProps) : createElement(PageComponent);
511
- const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
512
- const refreshSetup = "window.__REFRESH_BUFFER__=[];window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};window.$RefreshSig$=function(){return function(t){return t}};";
513
- const stream = await renderToReadableStream(element, {
514
- bootstrapModules: [index],
515
- bootstrapScriptContent: propsScript + refreshSetup || undefined,
516
- onError(error) {
517
- console.error("[SSR] React streaming error:", error);
518
- }
519
- });
520
- const html = injectIslandPageContext(await new Response(stream).text());
521
- return new Response(html, {
522
- headers: { "Content-Type": "text/html" }
523
- });
524
- } catch (error) {
525
- console.error("[SSR] React render error:", error);
526
- const pageName = PageComponent.name || PageComponent.displayName || "";
527
- const conventionResponse = await renderConventionError("react", pageName, error);
528
- if (conventionResponse)
529
- return conventionResponse;
530
- return new Response(ssrErrorPage("react", error), {
531
- headers: { "Content-Type": "text/html" },
532
- status: 500
533
- });
534
- }
535
- }, invalidateReactSsrCache = () => {
536
- ssrDirty = true;
537
- };
538
- var init_pageHandler = __esm(() => {
539
- init_resolveConvention();
540
- });
541
-
542
- // src/core/currentIslandRegistry.ts
543
- var setCurrentIslandRegistry = (registry) => {
544
- globalThis.__absoluteIslandRegistry = registry;
545
- }, requireCurrentIslandRegistry = () => {
546
- const registry = globalThis.__absoluteIslandRegistry;
547
- if (!registry) {
548
- throw new Error("No island registry is active. Configure `islands.registry` in absolute.config.ts before rendering <Island />.");
549
- }
550
- return registry;
551
- };
552
-
553
- // src/build/islandEntries.ts
554
- import {
555
- mkdirSync,
556
- rmSync,
557
- writeFileSync
558
- } from "fs";
559
- import { dirname, extname, join, relative, resolve as resolve3 } from "path";
560
- var frameworks, isRecord3 = (value) => typeof value === "object" && value !== null, resolveRegistryExport2 = (mod) => {
561
- if (isRecord3(mod.islandRegistry))
562
- return mod.islandRegistry;
563
- if (isRecord3(mod.default))
564
- return mod.default;
565
- throw new Error("Island registry module must export `islandRegistry` or a default registry object.");
566
- }, normalizeImportPath = (wrapperPath, targetPath) => {
567
- const importPath = relative(dirname(wrapperPath), targetPath).replace(/\\/g, "/");
568
- return importPath.startsWith(".") ? importPath : `./${importPath}`;
569
- }, isIdentifier = (value) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value), resolveIslandSourcePath = (registryPath, sourcePath) => {
570
- if (sourcePath.startsWith("file://")) {
571
- return new URL(sourcePath).pathname;
572
- }
573
- return resolve3(dirname(registryPath), sourcePath);
574
- }, createRegistryImportCode = (wrapperPath, registryPath, hasNamedExport) => {
575
- const normalizedPath = normalizeImportPath(wrapperPath, registryPath);
576
- if (hasNamedExport) {
577
- return {
578
- importStatement: `import { islandRegistry as __absoluteIslandRegistry } from ${JSON.stringify(normalizedPath)};`,
579
- registryReference: "__absoluteIslandRegistry"
580
- };
581
- }
582
- return {
583
- importStatement: `import __absoluteIslandRegistry from ${JSON.stringify(normalizedPath)};`,
584
- registryReference: "__absoluteIslandRegistry"
585
- };
586
- }, createDirectEntrySource = (wrapperPath, importPath, exportName) => {
587
- const normalizedImportPath = normalizeImportPath(wrapperPath, importPath);
588
- if (!exportName || exportName === "default") {
589
- return `export { default } from ${JSON.stringify(normalizedImportPath)};
590
- `;
591
- }
592
- return `export { ${exportName} as default } from ${JSON.stringify(normalizedImportPath)};
593
- `;
594
- }, createRegistryEntrySource = (wrapperPath, registryPath, hasNamedExport, framework, component) => {
595
- const { importStatement, registryReference } = createRegistryImportCode(wrapperPath, registryPath, hasNamedExport);
596
- const frameworkAccess = isIdentifier(framework) ? `${registryReference}.${framework}` : `${registryReference}[${JSON.stringify(framework)}]`;
597
- const componentAccess = isIdentifier(component) ? `${frameworkAccess}.${component}` : `${frameworkAccess}[${JSON.stringify(component)}]`;
598
- return `${importStatement}
599
-
600
- const component = ${componentAccess};
601
-
602
- export default component;
603
- `;
604
- }, shouldUseCompiledClientPath = (framework, sourcePath) => {
605
- if (framework === "svelte") {
606
- return /\.svelte(?:\.(?:ts|js))?$/.test(sourcePath);
607
- }
608
- if (framework === "vue") {
609
- return extname(sourcePath) === ".vue";
610
- }
611
- return false;
612
- }, loadIslandRegistryBuildInfo = async (registryPath) => {
613
- const resolvedRegistryPath = resolve3(registryPath);
614
- const registryModule = await import(resolvedRegistryPath);
615
- const registry = resolveRegistryExport2(registryModule);
616
- const definitions = [];
617
- for (const framework of frameworks) {
618
- const frameworkRegistry = registry[framework];
619
- if (!isRecord3(frameworkRegistry))
620
- continue;
621
- for (const [component, value] of Object.entries(frameworkRegistry)) {
622
- definitions.push({
623
- buildReference: getIslandBuildReference(value),
624
- component,
625
- framework
626
- });
627
- }
628
- }
629
- return {
630
- definitions,
631
- hasNamedExport: isRecord3(registryModule.islandRegistry),
632
- registry,
633
- resolvedRegistryPath
634
- };
635
- }, collectIslandFrameworkSources = (buildInfo) => {
636
- const sources = {};
637
- for (const definition of buildInfo.definitions) {
638
- const buildReference = definition.buildReference;
639
- if (!buildReference)
640
- continue;
641
- const resolvedSourcePath = resolveIslandSourcePath(buildInfo.resolvedRegistryPath, buildReference.source);
642
- if (!shouldUseCompiledClientPath(definition.framework, resolvedSourcePath)) {
643
- continue;
644
- }
645
- const frameworkSources = sources[definition.framework] ?? [];
646
- if (!frameworkSources.includes(resolvedSourcePath)) {
647
- frameworkSources.push(resolvedSourcePath);
648
- }
649
- sources[definition.framework] = frameworkSources;
650
- }
651
- return sources;
652
- }, generateIslandEntryPoints = async ({
653
- buildInfo,
654
- buildPath,
655
- clientPathMaps = {}
656
- }) => {
657
- const generatedRoot = join(buildPath, "_island_entries");
658
- rmSync(generatedRoot, { force: true, recursive: true });
659
- const entries = [];
660
- for (const definition of buildInfo.definitions) {
661
- const entryPath = join(generatedRoot, "islands", definition.framework, `${definition.component}.ts`);
662
- const buildReference = definition.buildReference;
663
- const source = buildReference ? resolveIslandSourcePath(buildInfo.resolvedRegistryPath, buildReference.source) : null;
664
- const compiledSourcePath = source && shouldUseCompiledClientPath(definition.framework, source) ? clientPathMaps[definition.framework]?.get(source) : undefined;
665
- const entrySource = source && (compiledSourcePath || !shouldUseCompiledClientPath(definition.framework, source)) ? createDirectEntrySource(entryPath, compiledSourcePath ?? source, compiledSourcePath ? undefined : buildReference?.export) : createRegistryEntrySource(entryPath, buildInfo.resolvedRegistryPath, buildInfo.hasNamedExport, definition.framework, definition.component);
666
- mkdirSync(dirname(entryPath), { recursive: true });
667
- writeFileSync(entryPath, entrySource);
668
- entries.push({
669
- component: definition.component,
670
- entryPath,
671
- framework: definition.framework
672
- });
673
- }
674
- return {
675
- entries,
676
- generatedRoot
677
- };
678
- };
679
- var init_islandEntries = __esm(() => {
680
- init_islands();
681
- frameworks = [
682
- "react",
683
- "svelte",
684
- "vue",
685
- "angular"
686
- ];
687
- });
688
-
689
- // src/build/scanEntryPoints.ts
690
- import { existsSync } from "fs";
691
- var {Glob } = globalThis.Bun;
692
- var scanEntryPoints = async (dir, pattern) => {
693
- if (!existsSync(dir))
694
- return [];
695
- const entryPaths = [];
696
- const glob = new Glob(pattern);
697
- for await (const file2 of glob.scan({ absolute: true, cwd: dir })) {
698
- entryPaths.push(file2);
699
- }
700
- return entryPaths;
701
- };
702
- var init_scanEntryPoints = () => {};
703
-
704
- // src/islands/sourceMetadata.ts
705
- var islandFrameworks, islandHydrationModes, isIslandFramework = (value) => islandFrameworks.some((framework) => framework === value), isIslandHydrate = (value) => islandHydrationModes.some((hydrate) => hydrate === value), parseIslandTagAttributes = (attributeString) => {
706
- const frameworkMatch = attributeString.match(/\bframework\s*=\s*["']([^"']+)["']/);
707
- const componentMatch = attributeString.match(/\bcomponent\s*=\s*["']([^"']+)["']/);
708
- const hydrateMatch = attributeString.match(/\bhydrate\s*=\s*["']([^"']+)["']/);
709
- const framework = frameworkMatch?.[1];
710
- const component = componentMatch?.[1];
711
- if (!framework || !component) {
712
- return null;
713
- }
714
- if (!isIslandFramework(framework)) {
715
- return null;
716
- }
717
- const hydrateCandidate = hydrateMatch?.[1];
718
- return {
719
- component,
720
- framework,
721
- hydrate: hydrateCandidate && isIslandHydrate(hydrateCandidate) ? hydrateCandidate : undefined
722
- };
723
- }, normalizeUsage = (usage) => `${usage.framework}:${usage.component}:${usage.hydrate ?? ""}`, addUsage = (usageMap, usage) => {
724
- if (!usage)
725
- return;
726
- usageMap.set(normalizeUsage(usage), usage);
727
- }, extractIslandUsagesFromSource = (source) => {
728
- const usageMap = new Map;
729
- const islandTagRegex = /<Island\b([\s\S]*?)(?:\/>|>(?:[\s\S]*?)<\/Island>)/g;
730
- let islandTagMatch = islandTagRegex.exec(source);
731
- while (islandTagMatch) {
732
- addUsage(usageMap, parseIslandTagAttributes(islandTagMatch[1] ?? ""));
733
- islandTagMatch = islandTagRegex.exec(source);
734
- }
735
- const staticRenderCallRegex = /renderIsland\s*\(\s*\{[\s\S]*?\bframework\s*:\s*['"]([^'"]+)['"][\s\S]*?\bcomponent\s*:\s*['"]([^'"]+)['"](?:[\s\S]*?\bhydrate\s*:\s*['"]([^'"]+)['"])?[\s\S]*?\}\s*\)/g;
736
- let renderMatch = staticRenderCallRegex.exec(source);
737
- while (renderMatch) {
738
- const framework = renderMatch[1];
739
- const component = renderMatch[2];
740
- const hydrate = renderMatch[3];
741
- if (!framework || !component || !isIslandFramework(framework)) {
742
- renderMatch = staticRenderCallRegex.exec(source);
743
- continue;
744
- }
745
- addUsage(usageMap, {
746
- component,
747
- framework,
748
- hydrate: hydrate && isIslandHydrate(hydrate) ? hydrate : undefined
749
- });
750
- renderMatch = staticRenderCallRegex.exec(source);
751
- }
752
- return [...usageMap.values()];
753
- }, buildIslandMetadataExports = (source) => {
754
- const usages = extractIslandUsagesFromSource(source);
755
- const serialized = JSON.stringify(usages);
756
- return `
757
- export const __ABSOLUTE_PAGE_ISLANDS__ = ${serialized};
758
- export const __ABSOLUTE_PAGE_HAS_ISLANDS__ = ${usages.length > 0};
759
- `;
760
- };
761
- var init_sourceMetadata = __esm(() => {
762
- islandFrameworks = [
763
- "react",
764
- "svelte",
765
- "vue",
766
- "angular"
767
- ];
768
- islandHydrationModes = [
769
- "load",
770
- "idle",
771
- "visible",
772
- "none"
773
- ];
774
- });
775
-
776
- // src/islands/pageMetadata.ts
777
- import { readFileSync } from "fs";
778
- import { dirname as dirname2, resolve as resolve4 } from "path";
779
- var pagePatterns, getPageDirs = (config) => [
780
- { dir: config.angularDirectory, framework: "angular" },
781
- { dir: config.reactDirectory, framework: "react" },
782
- { dir: config.svelteDirectory, framework: "svelte" },
783
- { dir: config.vueDirectory, framework: "vue" },
784
- { dir: config.htmlDirectory, framework: "html" },
785
- { dir: config.htmxDirectory, framework: "htmx" }
786
- ].filter((entry) => typeof entry.dir === "string" && entry.dir.length > 0), buildIslandSourceLookup = async (config) => {
787
- const registryPath = config.islands?.registry;
788
- if (!registryPath) {
789
- return new Map;
790
- }
791
- const buildInfo = await loadIslandRegistryBuildInfo(registryPath);
792
- const lookup = new Map;
793
- for (const definition of buildInfo.definitions) {
794
- const source = definition.buildReference?.source;
795
- if (!source)
796
- continue;
797
- const resolvedSource = source.startsWith("file://") ? new URL(source).pathname : resolve4(dirname2(buildInfo.resolvedRegistryPath), source);
798
- lookup.set(`${definition.framework}:${definition.component}`, resolve4(resolvedSource));
799
- }
800
- return lookup;
801
- }, loadPageIslandMetadata = async (config) => {
802
- const pageMetadata = new Map;
803
- const islandSourceLookup = await buildIslandSourceLookup(config);
804
- for (const entry of getPageDirs(config)) {
805
- const pattern = pagePatterns[entry.framework];
806
- if (!pattern)
807
- continue;
808
- const files = await scanEntryPoints(resolve4(entry.dir), pattern);
809
- for (const filePath of files) {
810
- const source = readFileSync(filePath, "utf-8");
811
- const islands = extractIslandUsagesFromSource(source);
812
- pageMetadata.set(resolve4(filePath), {
813
- islands: islands.map((usage) => {
814
- const sourcePath = islandSourceLookup.get(`${usage.framework}:${usage.component}`);
815
- return sourcePath ? {
816
- ...usage,
817
- source: sourcePath
818
- } : usage;
819
- }),
820
- pagePath: resolve4(filePath)
821
- });
822
- }
823
- }
824
- return pageMetadata;
825
- }, setCurrentPageIslandMetadata = (metadata2) => {
826
- globalThis.__absolutePageIslandMetadata = metadata2;
827
- }, getCurrentPageIslandMetadata = () => globalThis.__absolutePageIslandMetadata ?? new Map, getPagesUsingIslandSource = (sourcePath) => {
828
- const target = resolve4(sourcePath);
829
- const matches = [];
830
- for (const metadata2 of getCurrentPageIslandMetadata().values()) {
831
- const usesTarget = metadata2.islands.some((usage) => {
832
- const candidate = usage.source;
833
- return candidate ? resolve4(candidate) === target : false;
834
- });
835
- if (usesTarget) {
836
- matches.push(metadata2.pagePath);
837
- }
838
- }
839
- return matches;
840
- };
841
- var init_pageMetadata = __esm(() => {
842
- init_islandEntries();
843
- init_scanEntryPoints();
844
- init_sourceMetadata();
845
- pagePatterns = {
846
- angular: "pages/**/*.{ts,js}",
847
- html: "pages/**/*.html",
848
- htmx: "pages/**/*.html",
849
- react: "pages/**/*.{ts,tsx,js,jsx}",
850
- svelte: "pages/**/*.svelte",
851
- vue: "pages/**/*.vue"
852
- };
853
- });
854
-
855
- // src/build/generateIslandBindings.ts
856
- var exports_generateIslandBindings = {};
857
- __export(exports_generateIslandBindings, {
858
- generateIslandBindings: () => generateIslandBindings
859
- });
860
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
861
- import { dirname as dirname3, resolve as resolve5 } from "path";
862
- var ensureDir = (filePath) => {
863
- mkdirSync2(dirname3(filePath), { recursive: true });
864
- }, writeIfChanged = (filePath, content) => {
865
- ensureDir(filePath);
866
- writeFileSync2(filePath, content);
867
- }, removeIfExists = (filePath) => {
868
- if (existsSync2(filePath)) {
869
- rmSync2(filePath, { force: true });
870
- }
871
- }, generateIslandBindings = (projectRoot, config) => {
872
- const registryPath = config.islands?.registry;
873
- if (!registryPath) {
874
- return;
875
- }
876
- const resolvedRegistryPath = resolve5(projectRoot, registryPath);
877
- removeIfExists(resolve5(dirname3(resolvedRegistryPath), "absolute-islands.d.ts"));
878
- if (config.reactDirectory) {
879
- const compatTarget = resolve5(config.reactDirectory, "generated", "absolute-react.ts");
880
- removeIfExists(resolve5(config.reactDirectory, "generated", "Island.tsx"));
881
- removeIfExists(resolve5(config.reactDirectory, "generated", "absolute-react.d.ts"));
882
- writeIfChanged(compatTarget, `export * from "@absolutejs/absolute/react";
883
- `);
884
- }
885
- if (config.vueDirectory) {
886
- const compatTarget = resolve5(config.vueDirectory, "generated", "absolute-vue.ts");
887
- removeIfExists(resolve5(config.vueDirectory, "generated", "Island.ts"));
888
- removeIfExists(resolve5(config.vueDirectory, "generated", "absolute-vue.d.ts"));
889
- writeIfChanged(compatTarget, `export * from "@absolutejs/absolute/vue";
890
- `);
891
- }
892
- if (config.svelteDirectory) {
893
- const compatTarget = resolve5(config.svelteDirectory, "generated", "absolute-svelte.ts");
894
- removeIfExists(resolve5(config.svelteDirectory, "generated", "islands.ts"));
895
- removeIfExists(resolve5(config.svelteDirectory, "generated", "absolute-svelte.d.ts"));
896
- writeIfChanged(compatTarget, `export * from "@absolutejs/absolute/svelte";
897
- `);
898
- }
899
- if (config.angularDirectory) {
900
- const compatTarget = resolve5(config.angularDirectory, "generated", "absolute-angular.ts");
901
- removeIfExists(resolve5(config.angularDirectory, "generated", "islands.ts"));
902
- removeIfExists(resolve5(config.angularDirectory, "generated", "absolute-angular.d.ts"));
903
- writeIfChanged(compatTarget, `export * from "@absolutejs/absolute/angular";
904
- `);
905
- }
906
- };
907
- var init_generateIslandBindings = () => {};
908
-
909
- // src/utils/getDurationString.ts
910
- var getDurationString = (duration) => {
911
- let durationString;
912
- if (duration < MILLISECONDS_IN_A_SECOND) {
913
- durationString = `${duration.toFixed(TIME_PRECISION)}ms`;
914
- } else if (duration < MILLISECONDS_IN_A_MINUTE) {
915
- durationString = `${(duration / MILLISECONDS_IN_A_SECOND).toFixed(TIME_PRECISION)}s`;
916
- } else {
917
- durationString = `${(duration / MILLISECONDS_IN_A_MINUTE).toFixed(TIME_PRECISION)}m`;
918
- }
919
- return durationString;
920
- };
921
- var init_getDurationString = __esm(() => {
922
- init_constants();
923
- });
924
-
925
- // src/utils/startupBanner.ts
926
- var colors, MONTHS, formatTimestamp = () => {
927
- const now = new Date;
928
- const month = MONTHS[now.getMonth()];
929
- const day = now.getDate().toString().padStart(2, "0");
930
- let hours = now.getHours();
931
- const minutes = now.getMinutes().toString().padStart(2, "0");
932
- const seconds = now.getSeconds().toString().padStart(2, "0");
933
- const ampm = hours >= HOURS_IN_HALF_DAY ? "PM" : "AM";
934
- hours = hours % HOURS_IN_HALF_DAY || HOURS_IN_HALF_DAY;
935
- return `${month} ${day} ${hours}:${minutes}:${seconds} ${ampm}`;
936
- }, startupBanner = (options) => {
937
- const {
938
- version,
939
- duration,
940
- port,
941
- host,
942
- networkUrl,
943
- protocol = "http"
944
- } = options;
945
- const name = `${colors.cyan}${colors.bold}ABSOLUTEJS${colors.reset}`;
946
- const ver = `${colors.dim}v${version}${colors.reset}`;
947
- const time = `${colors.dim}ready in${colors.reset} ${colors.bold}${getDurationString(duration)}${colors.reset}`;
948
- console.log("");
949
- console.log(` ${name} ${ver} ${time}`);
950
- console.log("");
951
- console.log(` ${colors.green}\u279C${colors.reset} ${colors.bold}Local:${colors.reset} ${protocol}://${host === "0.0.0.0" ? "localhost" : host}:${port}/`);
952
- if (networkUrl) {
953
- console.log(` ${colors.green}\u279C${colors.reset} ${colors.bold}Network:${colors.reset} ${networkUrl}`);
954
- }
955
- console.log("");
956
- };
957
- var init_startupBanner = __esm(() => {
958
- init_constants();
959
- init_getDurationString();
960
- colors = {
961
- bold: "\x1B[1m",
962
- cyan: "\x1B[36m",
963
- dim: "\x1B[2m",
964
- green: "\x1B[32m",
965
- reset: "\x1B[0m"
966
- };
967
- MONTHS = [
968
- "Jan",
969
- "Feb",
970
- "Mar",
971
- "Apr",
972
- "May",
973
- "Jun",
974
- "Jul",
975
- "Aug",
976
- "Sep",
977
- "Oct",
978
- "Nov",
979
- "Dec"
980
- ];
981
- });
982
-
983
- // src/utils/logger.ts
984
- var colors2, frameworkColors, formatPath = (filePath) => {
985
- const cwd = process.cwd();
986
- let relative2 = filePath.startsWith(cwd) ? filePath.slice(cwd.length + 1) : filePath;
987
- relative2 = relative2.replace(/\\/g, "/");
988
- if (!relative2.startsWith("/")) {
989
- relative2 = `/${relative2}`;
990
- }
991
- return relative2;
992
- }, getFrameworkColor = (framework) => frameworkColors[framework] || colors2.white, log = (action, options) => {
993
- const timestamp = `${colors2.dim}${formatTimestamp()}${colors2.reset}`;
994
- const tag = `${colors2.cyan}[hmr]${colors2.reset}`;
995
- let message = action;
996
- if (options?.path) {
997
- const pathColor = options.framework ? getFrameworkColor(options.framework) : colors2.white;
998
- message += ` ${pathColor}${formatPath(options.path)}${colors2.reset}`;
999
- }
1000
- if (options?.duration !== undefined) {
1001
- message += ` ${colors2.dim}(${options.duration}ms)${colors2.reset}`;
1002
- }
1003
- console.log(`${timestamp} ${tag} ${message}`);
1004
- }, logCssUpdate = (path, framework, duration) => {
1005
- log("css update", { duration, framework: framework ?? "css", path });
1006
- }, logError = (message, error) => {
1007
- const timestamp = `${colors2.dim}${formatTimestamp()}${colors2.reset}`;
1008
- const tag = `${colors2.red}[hmr]${colors2.reset}`;
1009
- const errorMsg = error instanceof Error ? error.message : error;
1010
- const fullMessage = `${colors2.red}error${colors2.reset} ${message}${errorMsg ? `: ${errorMsg}` : ""}`;
1011
- console.error(`${timestamp} ${tag} ${fullMessage}`);
1012
- }, logHmrUpdate = (path, framework, duration) => {
1013
- log("hmr update", { duration, framework, path });
1014
- }, logScriptUpdate = (path, framework, duration) => {
1015
- log("script update", { duration, framework, path });
1016
- }, logServerReload = () => {
1017
- log(`${colors2.cyan}server module reloaded${colors2.reset}`);
1018
- }, logWarn = (message) => {
1019
- const timestamp = `${colors2.dim}${formatTimestamp()}${colors2.reset}`;
1020
- const tag = `${colors2.yellow}[hmr]${colors2.reset}`;
1021
- console.warn(`${timestamp} ${tag} ${colors2.yellow}warning${colors2.reset} ${message}`);
1022
- };
1023
- var init_logger = __esm(() => {
1024
- init_startupBanner();
1025
- colors2 = {
1026
- blue: "\x1B[34m",
1027
- bold: "\x1B[1m",
1028
- cyan: "\x1B[36m",
1029
- dim: "\x1B[2m",
1030
- green: "\x1B[32m",
1031
- magenta: "\x1B[35m",
1032
- red: "\x1B[31m",
1033
- reset: "\x1B[0m",
1034
- white: "\x1B[37m",
1035
- yellow: "\x1B[33m"
1036
- };
1037
- frameworkColors = {
1038
- angular: colors2.magenta,
1039
- assets: colors2.dim,
1040
- css: colors2.cyan,
1041
- html: colors2.white,
1042
- htmx: colors2.white,
1043
- react: colors2.blue,
1044
- svelte: colors2.yellow,
1045
- vue: colors2.green
1046
- };
1047
- });
1048
-
1049
- // src/utils/normalizePath.ts
1050
- var normalizePath = (path) => path.replace(/\\/g, "/");
1051
-
1052
- // src/build/generateManifest.ts
1053
- var exports_generateManifest = {};
1054
- __export(exports_generateManifest, {
1055
- generateManifest: () => generateManifest
1056
- });
1057
- import { extname as extname2 } from "path";
1058
- var getManifestKey = (folder, pascalName, isClientComponent, isReact, isVue, isSvelte, isAngular) => {
1059
- if (folder === "indexes")
1060
- return `${pascalName}Index`;
1061
- if (isClientComponent)
1062
- return `${pascalName}Client`;
1063
- if (folder !== "pages")
1064
- return pascalName;
1065
- if (isReact)
1066
- return `${pascalName}Page`;
1067
- if (isVue || isSvelte || isAngular)
1068
- return pascalName;
1069
- return `${pascalName}Page`;
1070
- }, getCssKey = (pascalName, segments) => {
1071
- const isFromVue = segments.some((seg) => seg === "vue");
1072
- if (isFromVue && segments.includes("css"))
1073
- return `${pascalName}CompiledCSS`;
1074
- const isFromReact = segments.some((seg) => seg === "react");
1075
- const isFromSvelte = segments.some((seg) => seg === "svelte");
1076
- const isFromAngular = segments.some((seg) => seg === "angular");
1077
- if (isFromReact || isFromVue || isFromSvelte || isFromAngular)
1078
- return `${pascalName}BundledCSS`;
1079
- return `${pascalName}CSS`;
1080
- }, generateManifest = (outputs, buildPath) => outputs.reduce((manifest, artifact) => {
1081
- const normalizedArtifactPath = normalizePath(artifact.path);
1082
- const normalizedBuildPath = normalizePath(buildPath);
1083
- let relative2 = normalizedArtifactPath.startsWith(normalizedBuildPath) ? normalizedArtifactPath.slice(normalizedBuildPath.length) : normalizedArtifactPath;
1084
- relative2 = relative2.replace(/^\/+/, "");
1085
- const segments = relative2.split("/");
1086
- const fileWithHash = segments.pop();
1087
- if (!fileWithHash)
1088
- return manifest;
1089
- const [baseName] = fileWithHash.split(`.${artifact.hash}.`);
1090
- if (!baseName)
1091
- return manifest;
1092
- const pascalName = toPascal(baseName);
1093
- const ext = extname2(fileWithHash);
1094
- const islandIndex = segments.findIndex((seg) => seg === "islands");
1095
- if (ext === ".css") {
1096
- const cssKey = getCssKey(pascalName, segments);
1097
- if (manifest[cssKey] && manifest[cssKey] !== `/${relative2}`)
1098
- logWarn(`Duplicate manifest key "${cssKey}" \u2014 "${manifest[cssKey]}" will be overwritten by "/${relative2}". Use unique page names across frameworks.`);
1099
- manifest[cssKey] = `/${relative2}`;
1100
- return manifest;
1101
- }
1102
- if (islandIndex > UNFOUND_INDEX) {
1103
- const frameworkSegment = segments[islandIndex + 1];
1104
- if (frameworkSegment === "react" || frameworkSegment === "svelte" || frameworkSegment === "vue" || frameworkSegment === "angular") {
1105
- const manifestKey2 = getIslandManifestKey(frameworkSegment, pascalName);
1106
- manifest[manifestKey2] = `/${relative2}`;
1107
- return manifest;
1108
- }
1109
- }
1110
- const idx = segments.findIndex((seg) => seg === "indexes" || seg === "pages" || seg === "client");
1111
- const folder = idx > UNFOUND_INDEX ? segments[idx] : segments[0];
1112
- const isReact = segments.some((seg) => seg === "react");
1113
- const isVue = segments.some((seg) => seg === "vue");
1114
- const isSvelte = segments.some((seg) => seg === "svelte");
1115
- const isAngular = segments.some((seg) => seg === "angular");
1116
- const isClientComponent = segments.includes("client");
1117
- const manifestKey = getManifestKey(folder, pascalName, isClientComponent, isReact, isVue, isSvelte, isAngular);
1118
- if (manifest[manifestKey] && manifest[manifestKey] !== `/${relative2}`) {
1119
- logWarn(`Duplicate manifest key "${manifestKey}" \u2014 "${manifest[manifestKey]}" will be overwritten by "/${relative2}". Use unique page names across frameworks.`);
1120
- }
1121
- manifest[manifestKey] = `/${relative2}`;
1122
- return manifest;
1123
- }, {});
1124
- var init_generateManifest = __esm(() => {
1125
- init_constants();
1126
- init_logger();
1127
- });
1128
-
1129
- // src/build/generateReactIndexes.ts
1130
- var exports_generateReactIndexes = {};
1131
- __export(exports_generateReactIndexes, {
1132
- generateReactIndexFiles: () => generateReactIndexFiles
1133
- });
1134
- import { existsSync as existsSync3, mkdirSync as mkdirSync3 } from "fs";
1135
- import { readdir, rm, writeFile } from "fs/promises";
1136
- import { basename as basename2, join as join2, relative as relative2, resolve as resolve6, sep } from "path";
1137
- var {Glob: Glob2 } = globalThis.Bun;
1138
- var indexContentCache, resolveDevClientDir = () => {
1139
- const projectRoot = process.cwd();
1140
- const fromSource = resolve6(import.meta.dir, "../dev/client");
1141
- if (existsSync3(fromSource) && fromSource.startsWith(projectRoot)) {
1142
- return fromSource;
1143
- }
1144
- const fromNodeModules = resolve6(projectRoot, "node_modules/@absolutejs/absolute/dist/dev/client");
1145
- if (existsSync3(fromNodeModules))
1146
- return fromNodeModules;
1147
- return resolve6(import.meta.dir, "./dev/client");
1148
- }, devClientDir, errorOverlayPath, hmrClientPath, refreshSetupPath, generateReactIndexFiles = async (reactPagesDirectory, reactIndexesDirectory, isDev2 = false) => {
1149
- if (!existsSync3(reactIndexesDirectory)) {
1150
- mkdirSync3(reactIndexesDirectory, { recursive: true });
1151
- }
1152
- const CONVENTION_RE = /^(?:(.+)\.)?(error|loading|not-found)\.[^.]+$/;
1153
- const pagesGlob = new Glob2("*.*");
1154
- const files = [];
1155
- for await (const file2 of pagesGlob.scan({ cwd: reactPagesDirectory })) {
1156
- if (CONVENTION_RE.test(file2))
1157
- continue;
1158
- files.push(file2);
1159
- }
1160
- const currentPageNames = new Set(files.map((file2) => basename2(file2).split(".")[0]));
1161
- const emptyStringArray = [];
1162
- const existingIndexes = await readdir(reactIndexesDirectory).catch(() => emptyStringArray);
1163
- const staleIndexes = existingIndexes.filter((indexFile) => {
1164
- const indexName = indexFile.replace(/\.tsx$/, "");
1165
- return indexName !== "_refresh" && !currentPageNames.has(indexName);
1166
- });
1167
- if (staleIndexes.length > 0) {
1168
- await Promise.all(staleIndexes.map((indexFile) => {
1169
- indexContentCache.delete(join2(reactIndexesDirectory, indexFile));
1170
- return rm(join2(reactIndexesDirectory, indexFile), {
1171
- force: true
1172
- });
1173
- }));
1174
- }
1175
- const pagesRelPath = relative2(resolve6(reactIndexesDirectory), resolve6(reactPagesDirectory)).split(sep).join("/");
1176
- const promises = files.map(async (file2) => {
1177
- const fileName = basename2(file2);
1178
- const [componentName] = fileName.split(".");
1179
- const hmrPreamble = isDev2 ? [
1180
- `window.__HMR_FRAMEWORK__ = "react";`,
1181
- `window.__REACT_COMPONENT_KEY__ = "${componentName}Index";`,
1182
- `import '${refreshSetupPath}';`,
1183
- `import '${hmrClientPath}';`,
1184
- `import { showErrorOverlay, hideErrorOverlay } from '${errorOverlayPath}';
1185
- `
1186
- ] : [];
1187
- const reactImports = isDev2 ? [
1188
- `import { hydrateRoot, createRoot } from 'react-dom/client';`,
1189
- `import { createElement, Component } from 'react';`
1190
- ] : [
1191
- `import { hydrateRoot, createRoot } from 'react-dom/client';`,
1192
- `import { createElement } from 'react';`
1193
- ];
1194
- const errorBoundaryDef = isDev2 ? [
1195
- `
1196
- // Dev-only Error Boundary to catch React render errors`,
1197
- `class ErrorBoundary extends Component {`,
1198
- ` constructor(props) {`,
1199
- ` super(props);`,
1200
- ` this.state = { hasError: false };`,
1201
- ` window.__ERROR_BOUNDARY__ = this;`,
1202
- ` }`,
1203
- ` static getDerivedStateFromError() {`,
1204
- ` return { hasError: true };`,
1205
- ` }`,
1206
- ` componentDidCatch(error) {`,
1207
- ` showErrorOverlay({`,
1208
- ` framework: 'react',`,
1209
- ` kind: 'runtime',`,
1210
- ` message: error && error.stack ? error.stack : String(error)`,
1211
- ` });`,
1212
- ` }`,
1213
- ` componentDidUpdate(prevProps, prevState) {`,
1214
- ` if (prevState.hasError && !this.state.hasError) {`,
1215
- ` hideErrorOverlay();`,
1216
- ` }`,
1217
- ` }`,
1218
- ` reset() {`,
1219
- ` this.setState({ hasError: false });`,
1220
- ` }`,
1221
- ` render() {`,
1222
- ` if (this.state.hasError) return null;`,
1223
- ``,
1224
- ` return this.props.children;`,
1225
- ` }`,
1226
- `}
1227
- `
1228
- ] : [];
1229
- const content = [
1230
- ...hmrPreamble,
1231
- ...reactImports,
1232
- `import type { ComponentType } from 'react'`,
1233
- `import { ${componentName} } from '${pagesRelPath}/${componentName}';
1234
- `,
1235
- `type PropsOf<C> = C extends ComponentType<infer P> ? P : never;
1236
- `,
1237
- `declare global {`,
1238
- ` interface Window {`,
1239
- ` __INITIAL_PROPS__?: PropsOf<typeof ${componentName}>`,
1240
- ` __REACT_ROOT__?: ReturnType<typeof hydrateRoot | typeof createRoot>`,
1241
- ` __HMR_CLIENT_ONLY_MODE__?: boolean`,
1242
- ` }`,
1243
- `}
1244
- `,
1245
- ...errorBoundaryDef,
1246
- `// Hydration with error handling and fallback`,
1247
- `const isDev = ${isDev2};`,
1248
- `const componentPath = '${pagesRelPath}/${componentName}';
1249
- `,
1250
- `function isHydrationError(error) {`,
1251
- ` if (!error) return false;`,
1252
- ` const errorMessage = error instanceof Error ? error.message : String(error);`,
1253
- ` const errorString = String(error);`,
1254
- ` const fullMessage = errorMessage + ' ' + errorString;`,
1255
- ` const hydrationKeywords = ['hydration', 'Hydration', 'mismatch', 'Mismatch', 'did not match', 'server rendered HTML', 'server HTML', 'client HTML', 'Hydration failed'];`,
1256
- ` const isHydration = hydrationKeywords.some(keyword => fullMessage.includes(keyword));`,
1257
- ` `,
1258
- ` // Ignore whitespace-only mismatches in <head> - these are harmless formatting differences`,
1259
- ` // The error often shows: + <link...> vs - {"\\n "} which is just formatting`,
1260
- ` if (isHydration) {`,
1261
- ` // Check if this is a head/link/stylesheet related mismatch`,
1262
- ` const isHeadRelated = fullMessage.includes('<head') || fullMessage.includes('</head>') || fullMessage.includes('head>') || fullMessage.includes('<link') || fullMessage.includes('link>') || fullMessage.includes('stylesheet') || fullMessage.includes('fonts.googleapis') || fullMessage.includes('rel="stylesheet"');`,
1263
- ` `,
1264
- ` // Check if the mismatch involves only whitespace/newlines`,
1265
- ` // Pattern: looks for {"\\n"} or {"\\n "} or similar whitespace-only content`,
1266
- ` // Also check for patterns like: - {"\\n "} or + <link...>`,
1267
- ` const hasWhitespacePattern = /\\{\\s*["']\\\\n[^"']*["']\\s*\\}/.test(fullMessage) || /\\{\\s*["'][\\\\n\\\\r\\\\s]+["']\\s*\\}/.test(fullMessage) || /-\\s*\\{\\s*["'][\\\\n\\\\r\\\\s]+["']\\s*\\}/.test(fullMessage);`,
1268
- ` const isWhitespaceOnly = /^[\\s\\n\\r]*$/.test(errorString) || /^[\\s\\n\\r]*$/.test(errorMessage);`,
1269
- ` const hasNewlinePattern = fullMessage.includes('\\\\n') || fullMessage.includes('\\\\r') || fullMessage.includes('\\n') || fullMessage.includes('\\r');`,
1270
- ` `,
1271
- ` // If it's head-related and involves whitespace/newlines, ignore it`,
1272
- ` if (isHeadRelated && (hasWhitespacePattern || isWhitespaceOnly || hasNewlinePattern)) {`,
1273
- ` return false; // Don't treat whitespace-only head mismatches as errors`,
1274
- ` }`,
1275
- ` }`,
1276
- ` return isHydration;`,
1277
- `}
1278
- `,
1279
- `function logHydrationError(error, componentName) {`,
1280
- ` if (!isDev) return;`,
1281
- ` if (window.__HMR_WS__ && window.__HMR_WS__.readyState === WebSocket.OPEN) {`,
1282
- ` try {`,
1283
- ` window.__HMR_WS__.send(JSON.stringify({`,
1284
- ` type: 'hydration-error',`,
1285
- ` data: {`,
1286
- ` componentName: '${componentName}',`,
1287
- ` componentPath: componentPath,`,
1288
- ` error: error instanceof Error ? error.message : String(error),`,
1289
- ` timestamp: Date.now()`,
1290
- ` }`,
1291
- ` }));`,
1292
- ` } catch (err) {}`,
1293
- ` }`,
1294
- `}
1295
- `,
1296
- `// Track if we've already switched to client-only mode`,
1297
- `let hasSwitchedToClientOnly = false;`,
1298
- `let hydrationErrorDetected = false;
1299
- `,
1300
- `function handleHydrationFallback(error) {`,
1301
- ` if (hasSwitchedToClientOnly) return; // Already handled`,
1302
- ` hasSwitchedToClientOnly = true;`,
1303
- ` hydrationErrorDetected = true;
1304
- `,
1305
- ` logHydrationError(error, '${componentName}');
1306
- `,
1307
- ` // Fallback: client-only render (no hydration)`,
1308
- ` try {`,
1309
- ` // Unmount existing root if it exists`,
1310
- ` if (window.__REACT_ROOT__ && typeof window.__REACT_ROOT__.unmount === 'function') {`,
1311
- ` try {`,
1312
- ` window.__REACT_ROOT__.unmount();`,
1313
- ` } catch (e) {`,
1314
- ` // Ignore unmount errors`,
1315
- ` }`,
1316
- ` }
1317
- `,
1318
- ` // Render into the same root container when falling back to client-only`,
1319
- ` const root = createRoot(container);`,
1320
- ` root.render(${isDev2 ? `createElement(ErrorBoundary, null, createElement(${componentName}, mergedProps))` : `createElement(${componentName}, mergedProps)`});`,
1321
- ` window.__REACT_ROOT__ = root;`,
1322
- ` window.__HMR_CLIENT_ONLY_MODE__ = true;`,
1323
- ` } catch (fallbackError) {`,
1324
- ` window.location.reload();`,
1325
- ` }`,
1326
- `}
1327
- `,
1328
- `// HMR State Preservation: Check for preserved state and merge with initial props`,
1329
- `// This allows state to be preserved across HMR updates without modifying component files`,
1330
- `let preservedState = (typeof window !== 'undefined' && window.__HMR_PRESERVED_STATE__) ? window.__HMR_PRESERVED_STATE__ : {};
1331
- `,
1332
- `// Also check sessionStorage for state that survived a page reload (for React HMR)`,
1333
- `if (typeof window !== 'undefined' && typeof sessionStorage !== 'undefined') {`,
1334
- ` const hmrStateJson = sessionStorage.getItem('__REACT_HMR_STATE__');`,
1335
- ` if (hmrStateJson) {`,
1336
- ` try {`,
1337
- ` const hmrState = JSON.parse(hmrStateJson);`,
1338
- ` preservedState = { ...preservedState, ...hmrState };`,
1339
- ` sessionStorage.removeItem('__REACT_HMR_STATE__');`,
1340
- ` } catch (e) {}`,
1341
- ` }`,
1342
- `}
1343
- `,
1344
- `const mergedProps = { ...(window.__INITIAL_PROPS__ || {}), ...preservedState };`,
1345
- `// Clear preserved state after using it (so it doesn't persist across multiple updates)`,
1346
- `if (typeof window !== 'undefined') {`,
1347
- ` window.__HMR_PRESERVED_STATE__ = undefined;`,
1348
- `}
1349
- `,
1350
- `// Attempt hydration with error handling`,
1351
- `// Use document (not document.body) when the page renders <html><head><body>`,
1352
- `// to avoid "In HTML, <html> cannot be a child of <body>" hydration error`,
1353
- `const container = typeof document !== 'undefined' ? document : null;`,
1354
- `if (!container) {`,
1355
- ` throw new Error('React root container not found: document is null');`,
1356
- `}
1357
- `,
1358
- `// Guard: only hydrate on first load. During HMR re-imports, skip hydration`,
1359
- `// so React Fast Refresh can swap components in-place and preserve state.`,
1360
- `if (!window.__REACT_ROOT__) {`,
1361
- ` let root;`,
1362
- ` // After HMR, SSR is skipped to avoid stale content flash \u2014 render client-only`,
1363
- ` if (window.__SSR_DIRTY__) {`,
1364
- ` root = createRoot(container);`,
1365
- ` root.render(${isDev2 ? `createElement(ErrorBoundary, null, createElement(${componentName}, mergedProps))` : `createElement(${componentName}, mergedProps)`});`,
1366
- ` window.__REACT_ROOT__ = root;`,
1367
- ` } else {`,
1368
- ` try {`,
1369
- ` // Use onRecoverableError to catch hydration errors (React 19)`,
1370
- ` root = hydrateRoot(`,
1371
- ` container,`,
1372
- ` ${isDev2 ? `createElement(ErrorBoundary, null, createElement(${componentName}, mergedProps))` : `createElement(${componentName}, mergedProps)`},`,
1373
- ` {`,
1374
- ` onRecoverableError: (error) => {`,
1375
- ` // Check if this is a hydration error (isHydrationError filters out whitespace-only head mismatches)`,
1376
- ` if (isDev && isHydrationError(error)) {`,
1377
- ` // Real hydration error - handle it`,
1378
- ` handleHydrationFallback(error);`,
1379
- ` } else {`,
1380
- ` // Not a hydration error, or it's a whitespace-only mismatch that was filtered out`,
1381
- ` // Check if it's a whitespace-only head mismatch using the same logic as isHydrationError`,
1382
- ` const errorMessage = error instanceof Error ? error.message : String(error);`,
1383
- ` const errorString = String(error);`,
1384
- ` const fullMessage = errorMessage + ' ' + errorString;`,
1385
- ` const hydrationKeywords = ['hydration', 'Hydration', 'mismatch', 'Mismatch', 'did not match', 'server rendered HTML', 'server HTML', 'client HTML', 'Hydration failed'];`,
1386
- ` const isHydration = hydrationKeywords.some(keyword => fullMessage.includes(keyword));`,
1387
- ` if (isHydration) {`,
1388
- ` // Check if this is a head/link/stylesheet related mismatch`,
1389
- ` const isHeadRelated = fullMessage.includes('<head') || fullMessage.includes('</head>') || fullMessage.includes('head>') || fullMessage.includes('<link') || fullMessage.includes('link>') || fullMessage.includes('stylesheet') || fullMessage.includes('fonts.googleapis') || fullMessage.includes('rel="stylesheet"');`,
1390
- ` // Check if the mismatch involves only whitespace/newlines`,
1391
- ` const hasWhitespacePattern = /\\{\\s*["']\\\\n[^"']*["']\\s*\\}/.test(fullMessage) || /\\{\\s*["'][\\\\n\\\\r\\\\s]+["']\\s*\\}/.test(fullMessage) || /-\\s*\\{\\s*["'][\\\\n\\\\r\\\\s]+["']\\s*\\}/.test(fullMessage);`,
1392
- ` const isWhitespaceOnly = /^[\\s\\n\\r]*$/.test(errorString) || /^[\\s\\n\\r]*$/.test(errorMessage);`,
1393
- ` const hasNewlinePattern = fullMessage.includes('\\\\n') || fullMessage.includes('\\\\r') || fullMessage.includes('\\n') || fullMessage.includes('\\r');`,
1394
- ` // If it's head-related and involves whitespace/newlines, silently ignore it`,
1395
- ` if (isHeadRelated && (hasWhitespacePattern || isWhitespaceOnly || hasNewlinePattern)) {`,
1396
- ` // Already logged by isHydrationError, just return silently`,
1397
- ` return;`,
1398
- ` }`,
1399
- ` }`,
1400
- ` // Log other recoverable errors`,
1401
- ` console.error('React recoverable error:', error);`,
1402
- ` }`,
1403
- ` }`,
1404
- ` }`,
1405
- ` );`,
1406
- ` window.__REACT_ROOT__ = root;`,
1407
- ` } catch (error) {`,
1408
- ` // Catch synchronous errors (shouldn't happen with hydrateRoot, but safety net)`,
1409
- ` if (isDev && isHydrationError(error)) {`,
1410
- ` handleHydrationFallback(error);`,
1411
- ` } else {`,
1412
- ` throw error;`,
1413
- ` }`,
1414
- ` }`,
1415
- ` } // end else (normal hydration path)
1416
- `,
1417
- ` // Also listen for hydration errors via console.error (React logs them there)`,
1418
- ` if (isDev) {`,
1419
- ` const originalError = console.error;`,
1420
- ` console.error = function(...args) {`,
1421
- ` const errorMessage = args.map(arg => {`,
1422
- ` if (arg instanceof Error) return arg.message;`,
1423
- ` return String(arg);`,
1424
- ` }).join(' ');`,
1425
- ` `,
1426
- ` // Check if this is a hydration error`,
1427
- ` if (isHydrationError({ message: errorMessage }) && !hydrationErrorDetected) {`,
1428
- ` hydrationErrorDetected = true;`,
1429
- ` // Create a synthetic error for fallback`,
1430
- ` const syntheticError = new Error(errorMessage);`,
1431
- ` // Use setTimeout to ensure this happens after React's error handling`,
1432
- ` setTimeout(() => {`,
1433
- ` handleHydrationFallback(syntheticError);`,
1434
- ` }, 0);`,
1435
- ` }`,
1436
- ` `,
1437
- ` // Call original console.error`,
1438
- ` originalError.apply(console, args);`,
1439
- ` };`,
1440
- ` }`,
1441
- `}`,
1442
- ...isDev2 ? [
1443
- `
1444
- // Pre-warm: import the page module from the module server`,
1445
- `// immediately so the browser caches all /@src/ URLs.`,
1446
- `import('/@src/${relative2(process.cwd(), resolve6(reactPagesDirectory, `${componentName}.tsx`)).replace(/\\/g, "/")}').catch(() => {});`
1447
- ] : []
1448
- ].join(`
1449
- `);
1450
- const indexPath = join2(reactIndexesDirectory, `${componentName}.tsx`);
1451
- const hasher = new Bun.CryptoHasher("md5");
1452
- hasher.update(content);
1453
- const contentHash = hasher.digest("hex");
1454
- if (indexContentCache.get(indexPath) === contentHash && existsSync3(indexPath)) {
1455
- return;
1456
- }
1457
- indexContentCache.set(indexPath, contentHash);
1458
- await writeFile(indexPath, content);
1459
- });
1460
- await Promise.all(promises);
1461
- if (!isDev2) {
1462
- return;
1463
- }
1464
- const refreshPath = join2(reactIndexesDirectory, "_refresh.tsx");
1465
- if (!existsSync3(refreshPath)) {
1466
- await writeFile(refreshPath, `import '${refreshSetupPath}';
1467
- import 'react';
1468
- import 'react-dom/client';
1469
- `);
1470
- }
1471
- };
1472
- var init_generateReactIndexes = __esm(() => {
1473
- indexContentCache = new Map;
1474
- devClientDir = resolveDevClientDir();
1475
- errorOverlayPath = join2(devClientDir, "errorOverlay.ts").replace(/\\/g, "/");
1476
- hmrClientPath = join2(devClientDir, "hmrClient.ts").replace(/\\/g, "/");
1477
- refreshSetupPath = join2(devClientDir, "reactRefreshSetup.ts").replace(/\\/g, "/");
1478
- });
1479
-
1480
- // src/build/islandBindingCompat.ts
1481
- import { resolve as resolve7 } from "path";
1482
- var packageToFramework, compatFileNames, normalize = (value) => value.replace(/\\/g, "/"), isFrameworkPackage = (value) => (value in packageToFramework), resolveIslandCompatModule = (specifier, importer, frameworkDirs) => {
1483
- if (!isFrameworkPackage(specifier)) {
1484
- return null;
1485
- }
1486
- const framework = packageToFramework[specifier];
1487
- const frameworkDir = frameworkDirs[framework];
1488
- if (!frameworkDir) {
1489
- return null;
1490
- }
1491
- const normalizedImporter = normalize(importer);
1492
- const normalizedFrameworkDir = normalize(resolve7(frameworkDir));
1493
- if (!normalizedImporter.startsWith(normalizedFrameworkDir)) {
1494
- return null;
1495
- }
1496
- if (normalizedImporter.includes("/generated/absolute-") || normalizedImporter.includes("/generated/Island.") || normalizedImporter.includes("/generated/islands.")) {
1497
- return null;
1498
- }
1499
- return resolve7(frameworkDir, "generated", compatFileNames[framework]);
1500
- };
1501
- var init_islandBindingCompat = __esm(() => {
1502
- packageToFramework = {
1503
- "@absolutejs/absolute/angular": "angular",
1504
- "@absolutejs/absolute/react": "react",
1505
- "@absolutejs/absolute/svelte": "svelte",
1506
- "@absolutejs/absolute/vue": "vue"
1507
- };
1508
- compatFileNames = {
1509
- angular: "absolute-angular.ts",
1510
- react: "absolute-react.ts",
1511
- svelte: "absolute-svelte.ts",
1512
- vue: "absolute-vue.ts"
1513
- };
1514
- });
1515
-
1516
- // src/build/islandBindingPlugin.ts
1517
- var exports_islandBindingPlugin = {};
1518
- __export(exports_islandBindingPlugin, {
1519
- createIslandBindingPlugin: () => createIslandBindingPlugin
1520
- });
1521
- var createIslandBindingPlugin = (frameworkDirs) => ({
1522
- name: "absolute-island-binding-plugin",
1523
- setup(build2) {
1524
- build2.onResolve({
1525
- filter: /^@absolutejs\/absolute\/(react|vue|svelte|angular)$/
1526
- }, (args) => {
1527
- const redirected = resolveIslandCompatModule(args.path, args.importer, frameworkDirs);
1528
- if (!redirected) {
1529
- return;
1530
- }
1531
- return {
1532
- path: redirected
1533
- };
1534
- });
1535
- }
1536
- });
1537
- var init_islandBindingPlugin = __esm(() => {
1538
- init_islandBindingCompat();
1539
- });
1540
-
1541
- // src/build/wrapHTMLScript.ts
1542
- var wrapHTMLScriptWithHMR = (code, scriptId) => {
1543
- const escapedId = JSON.stringify(scriptId);
1544
- return `${code}
1545
-
1546
- // HMR acceptance - allows this script to be hot-reloaded
1547
- if (typeof import.meta !== "undefined" && import.meta.hot) {
1548
- import.meta.hot.accept();
1549
- console.log('[HMR] Script ready:', ${escapedId});
1550
- }
1551
- `;
1552
- };
1553
-
1554
- // src/build/htmlScriptHMRPlugin.ts
1555
- var scriptLoaders, toLoader = (ext) => {
1556
- for (const loader of scriptLoaders) {
1557
- if (loader === ext)
1558
- return loader;
1559
- }
1560
- return "ts";
1561
- }, createHTMLScriptHMRPlugin = (htmlDir, htmxDir) => ({
1562
- name: "html-script-hmr",
1563
- setup(build2) {
1564
- build2.onLoad({ filter: /\.(ts|js|tsx|jsx)$/ }, async (args) => {
1565
- const normalizedPath = args.path.replace(/\\/g, "/");
1566
- const isHtmlScript = htmlDir && normalizedPath.includes(htmlDir.replace(/\\/g, "/")) && normalizedPath.includes("/scripts/");
1567
- const isHtmxScript = htmxDir && normalizedPath.includes(htmxDir.replace(/\\/g, "/")) && normalizedPath.includes("/scripts/");
1568
- if (!isHtmlScript && !isHtmxScript) {
1569
- return;
1570
- }
1571
- const text = await Bun.file(args.path).text();
1572
- const wrapped = wrapHTMLScriptWithHMR(text, normalizedPath);
1573
- const ext = args.path.split(".").pop() ?? "ts";
1574
- const loader = toLoader(ext);
1575
- return {
1576
- contents: wrapped,
1577
- loader
1578
- };
1579
- });
1580
- }
1581
- });
1582
- var init_htmlScriptHMRPlugin = __esm(() => {
1583
- scriptLoaders = new Set(["ts", "js", "tsx", "jsx"]);
1584
- });
1585
-
1586
206
  // src/angular/injectorPatch.ts
1587
- import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
1588
- import { dirname as dirname4, join as join3, resolve as resolve8 } from "path";
207
+ import { existsSync, readFileSync, writeFileSync } from "fs";
208
+ import { dirname, join, resolve } from "path";
1589
209
  var applyInjectorPatch = (chunkPath, content) => {
1590
210
  if (content.includes('Symbol.for("angular.currentInjector")')) {
1591
211
  return;
@@ -1619,18 +239,18 @@ var applyInjectorPatch = (chunkPath, content) => {
1619
239
  if (patched === content) {
1620
240
  return;
1621
241
  }
1622
- writeFileSync3(chunkPath, patched, "utf-8");
242
+ writeFileSync(chunkPath, patched, "utf-8");
1623
243
  }, resolveAngularCoreDir = () => {
1624
- const fromProject = resolve8(process.cwd(), "node_modules/@angular/core");
1625
- if (existsSync4(join3(fromProject, "package.json"))) {
244
+ const fromProject = resolve(process.cwd(), "node_modules/@angular/core");
245
+ if (existsSync(join(fromProject, "package.json"))) {
1626
246
  return fromProject;
1627
247
  }
1628
- return dirname4(__require.resolve("@angular/core/package.json"));
248
+ return dirname(__require.resolve("@angular/core/package.json"));
1629
249
  }, patchAngularInjectorSingleton = () => {
1630
250
  try {
1631
251
  const coreDir = resolveAngularCoreDir();
1632
- const chunkPath = join3(coreDir, "fesm2022", "_not_found-chunk.mjs");
1633
- const content = readFileSync2(chunkPath, "utf-8");
252
+ const chunkPath = join(coreDir, "fesm2022", "_not_found-chunk.mjs");
253
+ const content = readFileSync(chunkPath, "utf-8");
1634
254
  applyInjectorPatch(chunkPath, content);
1635
255
  } catch {}
1636
256
  };
@@ -1639,11 +259,11 @@ var init_injectorPatch = __esm(() => {
1639
259
  });
1640
260
 
1641
261
  // src/angular/resolveAngularPackage.ts
1642
- import { existsSync as existsSync5 } from "fs";
1643
- import { resolve as resolve9 } from "path";
262
+ import { existsSync as existsSync2 } from "fs";
263
+ import { resolve as resolve2 } from "path";
1644
264
  var resolveAngularPackage = (specifier) => {
1645
- const fromProject = resolve9(process.cwd(), "node_modules", specifier);
1646
- if (existsSync5(fromProject)) {
265
+ const fromProject = resolve2(process.cwd(), "node_modules", specifier);
266
+ if (existsSync2(fromProject)) {
1647
267
  return fromProject;
1648
268
  }
1649
269
  return specifier;
@@ -1737,6 +357,14 @@ var init_angularDeps = __esm(() => {
1737
357
  init_resolveAngularPackage();
1738
358
  });
1739
359
 
360
+ // src/utils/stringModifiers.ts
361
+ 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) => {
362
+ if (!str.includes("-") && !str.includes("_")) {
363
+ return str.charAt(0).toUpperCase() + str.slice(1);
364
+ }
365
+ return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
366
+ }, toScreamingSnake = (str) => str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase();
367
+
1740
368
  // src/utils/registerClientScript.ts
1741
369
  var scriptRegistry, requestCounter = 0, getRequestId = () => `req_${Date.now()}_${++requestCounter}`, ssrContextGetter = null, getSsrContextId = () => ssrContextGetter?.() || Object.getOwnPropertyDescriptor(globalThis, "__absolutejs_requestId")?.value, registerClientScript = (script, requestId) => {
1742
370
  const id = requestId || getSsrContextId() || getRequestId();
@@ -3278,8 +1906,8 @@ class SourceMapGenerator {
3278
1906
  lines = [];
3279
1907
  lastCol0 = 0;
3280
1908
  hasMappings = false;
3281
- constructor(file2 = null) {
3282
- this.file = file2;
1909
+ constructor(file = null) {
1910
+ this.file = file;
3283
1911
  }
3284
1912
  addSource(url, content = null) {
3285
1913
  if (!this.sourcesContent.has(url)) {
@@ -5172,8 +3800,8 @@ class ParseLocation {
5172
3800
  offset;
5173
3801
  line;
5174
3802
  col;
5175
- constructor(file2, offset, line, col) {
5176
- this.file = file2;
3803
+ constructor(file, offset, line, col) {
3804
+ this.file = file;
5177
3805
  this.offset = offset;
5178
3806
  this.line = line;
5179
3807
  this.col = col;
@@ -5906,12 +4534,12 @@ class ShadowCss {
5906
4534
  let scopedSelector = "";
5907
4535
  let startIndex = 0;
5908
4536
  let res;
5909
- const sep2 = /( |>|\+|~(?!=))(?!([^)(]*(?:\([^)(]*(?:\([^)(]*(?:\([^)(]*\)[^)(]*)*\)[^)(]*)*\)[^)(]*)*\)))\s*/g;
4537
+ const sep = /( |>|\+|~(?!=))(?!([^)(]*(?:\([^)(]*(?:\([^)(]*(?:\([^)(]*\)[^)(]*)*\)[^)(]*)*\)[^)(]*)*\)))\s*/g;
5910
4538
  const hasHost = selector.includes(_polyfillHostNoCombinator);
5911
4539
  if (isParentSelector || this._shouldScopeIndicator) {
5912
4540
  this._shouldScopeIndicator = !hasHost;
5913
4541
  }
5914
- while ((res = sep2.exec(selector)) !== null) {
4542
+ while ((res = sep.exec(selector)) !== null) {
5915
4543
  const separator = res[1];
5916
4544
  const part2 = selector.slice(startIndex, res.index);
5917
4545
  if (part2.match(/__esc-ph-(\d+)__/) && selector[res.index + 1]?.match(/[a-fA-F\d]/)) {
@@ -5919,7 +4547,7 @@ class ShadowCss {
5919
4547
  }
5920
4548
  const scopedPart = _pseudoFunctionAwareScopeSelectorPart(part2);
5921
4549
  scopedSelector += `${scopedPart} ${separator} `;
5922
- startIndex = sep2.lastIndex;
4550
+ startIndex = sep.lastIndex;
5923
4551
  }
5924
4552
  const part = selector.substring(startIndex);
5925
4553
  scopedSelector += _pseudoFunctionAwareScopeSelectorPart(part);
@@ -22376,13 +21004,13 @@ function getTemplateExpression(template2, templateInfo) {
22376
21004
  return literal(templateInfo.content, null, null);
22377
21005
  }
22378
21006
  const contents = templateInfo.content;
22379
- const file2 = new ParseSourceFile(contents, templateInfo.sourceUrl);
22380
- const start = new ParseLocation(file2, 0, 0, 0);
22381
- const end = computeEndLocation(file2, contents);
21007
+ const file = new ParseSourceFile(contents, templateInfo.sourceUrl);
21008
+ const start = new ParseLocation(file, 0, 0, 0);
21009
+ const end = computeEndLocation(file, contents);
22382
21010
  const span = new ParseSourceSpan(start, end);
22383
21011
  return literal(contents, null, span);
22384
21012
  }
22385
- function computeEndLocation(file2, contents) {
21013
+ function computeEndLocation(file, contents) {
22386
21014
  const length = contents.length;
22387
21015
  let lineStart = 0;
22388
21016
  let lastLineStart = 0;
@@ -22395,7 +21023,7 @@ function computeEndLocation(file2, contents) {
22395
21023
  line++;
22396
21024
  }
22397
21025
  } while (lineStart !== -1);
22398
- return new ParseLocation(file2, length, line, length - lastLineStart);
21026
+ return new ParseLocation(file, length, line, length - lastLineStart);
22399
21027
  }
22400
21028
  function compileUsedDependenciesMetadata(meta) {
22401
21029
  const wrapType = meta.declarationListEmitMode !== 0 ? generateForwardRef : (expr) => expr;
@@ -30916,7 +29544,7 @@ If '${name}' is a directive input, make sure the directive is imported by the` +
30916
29544
  transUnits.push(new CR(6), transUnit);
30917
29545
  });
30918
29546
  const body = new Tag("body", {}, [...transUnits, new CR(4)]);
30919
- const file2 = new Tag("file", {
29547
+ const file = new Tag("file", {
30920
29548
  "source-language": locale || _DEFAULT_SOURCE_LANG$1,
30921
29549
  datatype: "plaintext",
30922
29550
  original: "ng2.template"
@@ -30924,7 +29552,7 @@ If '${name}' is a directive input, make sure the directive is imported by the` +
30924
29552
  const xliff = new Tag("xliff", {
30925
29553
  version: _VERSION$1,
30926
29554
  xmlns: _XMLNS$1
30927
- }, [new CR(2), file2, new CR]);
29555
+ }, [new CR(2), file, new CR]);
30928
29556
  return serialize$1([new Declaration({
30929
29557
  version: "1.0",
30930
29558
  encoding: "UTF-8"
@@ -30994,7 +29622,7 @@ ${errors.join(`
30994
29622
  unit.children.push(new CR(6), segment, new CR(4));
30995
29623
  units.push(new CR(4), unit);
30996
29624
  });
30997
- const file2 = new Tag("file", {
29625
+ const file = new Tag("file", {
30998
29626
  original: "ng.template",
30999
29627
  id: "ngi18n"
31000
29628
  }, [...units, new CR(2)]);
@@ -31002,7 +29630,7 @@ ${errors.join(`
31002
29630
  version: _VERSION,
31003
29631
  xmlns: _XMLNS,
31004
29632
  srcLang: locale || _DEFAULT_SOURCE_LANG
31005
- }, [new CR(2), file2, new CR]);
29633
+ }, [new CR(2), file, new CR]);
31006
29634
  return serialize$1([new Declaration({
31007
29635
  version: "1.0",
31008
29636
  encoding: "UTF-8"
@@ -31360,392 +29988,1839 @@ var ISLAND_TAG_RE, extractIslandAttribute = (attributeString, name) => {
31360
29988
  }
31361
29989
  }
31362
29990
  }
31363
- return { expression: "", found: false };
31364
- }, lowerSvelteIslandSyntax = (source, mode = "server") => {
31365
- if (!source.includes("<Island")) {
31366
- return { code: source, transformed: false };
29991
+ return { expression: "", found: false };
29992
+ }, lowerSvelteIslandSyntax = (source, mode = "server") => {
29993
+ if (!source.includes("<Island")) {
29994
+ return { code: source, transformed: false };
29995
+ }
29996
+ let islandIndex = 0;
29997
+ const transformedMarkup = source.replace(ISLAND_TAG_RE, (fullMatch, attributeString) => {
29998
+ const framework = extractIslandAttribute(attributeString, "framework");
29999
+ const component = extractIslandAttribute(attributeString, "component");
30000
+ if (!framework.found || !component.found) {
30001
+ return fullMatch;
30002
+ }
30003
+ const hydrate = extractIslandAttribute(attributeString, "hydrate");
30004
+ const props = extractIslandAttribute(attributeString, "props");
30005
+ const slotId = `absolute-svelte-island-${islandIndex.toString(BASE_36_RADIX)}`;
30006
+ islandIndex += 1;
30007
+ 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 : "{}"} })`;
30008
+ return `<div data-absolute-island-slot="${slotId}" style="display: contents">{@html ${resolveExpression}}</div>`;
30009
+ });
30010
+ const importLine = 'import { resolveIslandHtml as __absoluteResolveIslandHtml } from "@absolutejs/absolute/svelte";';
30011
+ if (transformedMarkup.includes("<script")) {
30012
+ return {
30013
+ code: transformedMarkup.replace(/<script(\s[^>]*)?>/, (match) => `${match}
30014
+ ${importLine}
30015
+ `),
30016
+ transformed: true
30017
+ };
30018
+ }
30019
+ return {
30020
+ code: `<script lang="ts">
30021
+ ${importLine}
30022
+ </script>
30023
+ ${transformedMarkup}`,
30024
+ transformed: true
30025
+ };
30026
+ };
30027
+ var init_lowerIslandSyntax = __esm(() => {
30028
+ init_constants();
30029
+ ISLAND_TAG_RE = /<Island\b([\s\S]*?)\/>/g;
30030
+ });
30031
+
30032
+ // src/core/svelteServerModule.ts
30033
+ import { mkdir } from "fs/promises";
30034
+ import { dirname as dirname2, extname, join as join2, relative, resolve as resolve3 } from "path";
30035
+ var serverCacheRoot, compiledModuleCache, transpiler, ensureRelativeImportPath = (from, to) => {
30036
+ const importPath = relative(dirname2(from), to).replace(/\\/g, "/");
30037
+ return importPath.startsWith(".") ? importPath : `./${importPath}`;
30038
+ }, resolveRelativeModule = async (spec, from) => {
30039
+ if (!spec.startsWith(".")) {
30040
+ return null;
30041
+ }
30042
+ const basePath = resolve3(dirname2(from), spec);
30043
+ const candidates = [
30044
+ basePath,
30045
+ `${basePath}.ts`,
30046
+ `${basePath}.js`,
30047
+ `${basePath}.mjs`,
30048
+ `${basePath}.cjs`,
30049
+ `${basePath}.json`,
30050
+ join2(basePath, "index.ts"),
30051
+ join2(basePath, "index.js"),
30052
+ join2(basePath, "index.mjs"),
30053
+ join2(basePath, "index.cjs"),
30054
+ join2(basePath, "index.json")
30055
+ ];
30056
+ for (const candidate of candidates) {
30057
+ if (await Bun.file(candidate).exists() === true) {
30058
+ return candidate;
30059
+ }
30060
+ }
30061
+ return null;
30062
+ }, getCachedModulePath = (sourcePath) => {
30063
+ const relativeSourcePath = relative(process.cwd(), sourcePath).replace(/\\/g, "/");
30064
+ const normalizedSourcePath = relativeSourcePath.startsWith("..") ? sourcePath.replace(/[:\\/]/g, "_") : relativeSourcePath;
30065
+ return join2(serverCacheRoot, `${normalizedSourcePath}.server.js`);
30066
+ }, resolveSvelteImport = async (spec, from) => {
30067
+ if (spec.startsWith("/")) {
30068
+ return spec;
30069
+ }
30070
+ if (!spec.startsWith(".")) {
30071
+ return null;
30072
+ }
30073
+ const explicitPath = resolve3(dirname2(from), spec);
30074
+ if (extname(explicitPath) === ".svelte") {
30075
+ return explicitPath;
30076
+ }
30077
+ const candidate = `${explicitPath}.svelte`;
30078
+ if (await Bun.file(candidate).exists() === true) {
30079
+ return candidate;
30080
+ }
30081
+ return null;
30082
+ }, writeIfChanged = async (path, content) => {
30083
+ const targetFile = Bun.file(path);
30084
+ const exists = await targetFile.exists();
30085
+ if (exists) {
30086
+ const currentContent = await targetFile.text();
30087
+ if (currentContent === content) {
30088
+ return;
30089
+ }
30090
+ }
30091
+ await Bun.write(path, content);
30092
+ }, compileSvelteServerModule = async (sourcePath) => {
30093
+ const cachedModulePath = compiledModuleCache.get(sourcePath);
30094
+ if (cachedModulePath) {
30095
+ return cachedModulePath;
30096
+ }
30097
+ const source = await Bun.file(sourcePath).text();
30098
+ const { compile, preprocess } = await import("svelte/compiler");
30099
+ const loweredSource = lowerSvelteIslandSyntax(source, "server");
30100
+ const preprocessed = await preprocess(loweredSource.code, {});
30101
+ const transpiled = sourcePath.endsWith(".ts") || sourcePath.endsWith(".svelte.ts") ? transpiler.transformSync(preprocessed.code) : preprocessed.code;
30102
+ const childImportSpecs = Array.from(transpiled.matchAll(/from\s+['"]([^'"]+)['"]/g)).map((match) => match[1]).filter((value) => value !== undefined);
30103
+ const resolvedChildModules = await Promise.all(childImportSpecs.map((spec) => resolveSvelteImport(spec, sourcePath)));
30104
+ const resolvedModuleImports = await Promise.all(childImportSpecs.map((spec) => resolveRelativeModule(spec, sourcePath)));
30105
+ const childModulePaths = new Map;
30106
+ const rewrittenModulePaths = new Map;
30107
+ for (let index = 0;index < childImportSpecs.length; index += 1) {
30108
+ const spec = childImportSpecs[index];
30109
+ const resolvedChild = resolvedChildModules[index];
30110
+ if (!spec || !resolvedChild)
30111
+ continue;
30112
+ const compiledChildPath = await compileSvelteServerModule(resolvedChild);
30113
+ childModulePaths.set(spec, compiledChildPath);
30114
+ }
30115
+ for (let index = 0;index < childImportSpecs.length; index += 1) {
30116
+ const spec = childImportSpecs[index];
30117
+ const resolvedModuleImport = resolvedModuleImports[index];
30118
+ if (!spec || !resolvedModuleImport)
30119
+ continue;
30120
+ if (resolvedChildModules[index])
30121
+ continue;
30122
+ rewrittenModulePaths.set(spec, ensureRelativeImportPath(getCachedModulePath(sourcePath), resolvedModuleImport));
30123
+ }
30124
+ let compiledCode = compile(transpiled, {
30125
+ css: "injected",
30126
+ experimental: {
30127
+ async: loweredSource.transformed
30128
+ },
30129
+ filename: sourcePath,
30130
+ generate: "server"
30131
+ }).js.code;
30132
+ for (const [spec, compiledChildPath] of childModulePaths) {
30133
+ compiledCode = compiledCode.replaceAll(spec, ensureRelativeImportPath(getCachedModulePath(sourcePath), compiledChildPath));
30134
+ }
30135
+ for (const [spec, resolvedModuleImport] of rewrittenModulePaths) {
30136
+ compiledCode = compiledCode.replaceAll(spec, resolvedModuleImport);
30137
+ }
30138
+ const compiledModulePath = getCachedModulePath(sourcePath);
30139
+ await mkdir(dirname2(compiledModulePath), { recursive: true });
30140
+ await writeIfChanged(compiledModulePath, compiledCode);
30141
+ compiledModuleCache.set(sourcePath, compiledModulePath);
30142
+ return compiledModulePath;
30143
+ };
30144
+ var init_svelteServerModule = __esm(() => {
30145
+ init_lowerIslandSyntax();
30146
+ serverCacheRoot = join2(process.cwd(), ".absolutejs", "islands", "svelte");
30147
+ compiledModuleCache = new Map;
30148
+ transpiler = new Bun.Transpiler({
30149
+ loader: "ts",
30150
+ target: "browser"
30151
+ });
30152
+ });
30153
+
30154
+ // src/core/islandMarkupAttributes.ts
30155
+ var getIslandMarkerAttributes = (props, islandId) => ({
30156
+ "data-component": props.component,
30157
+ "data-framework": props.framework,
30158
+ "data-hydrate": props.hydrate ?? "load",
30159
+ "data-island": "true",
30160
+ ...islandId ? { "data-island-id": islandId } : {},
30161
+ "data-props": serializeIslandProps(props.props)
30162
+ }), escapeHtmlAttribute = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"), serializeIslandAttributes = (attributes) => Object.entries(attributes).map(([key, value]) => `${key}="${escapeHtmlAttribute(value)}"`).join(" ");
30163
+ var init_islandMarkupAttributes = __esm(() => {
30164
+ init_islands();
30165
+ });
30166
+
30167
+ // src/core/renderIslandMarkup.ts
30168
+ var islandSequence = 0, resolvedServerComponentCache, resolvedServerBuildComponentCache, nextIslandId = () => {
30169
+ islandSequence += 1;
30170
+ return `island-${islandSequence}`;
30171
+ }, 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) => source.startsWith("file://") ? new URL(source).pathname : source.startsWith(".") ? new URL(source, registryPath).pathname : source, loadServerBuildComponent = async (buildReferencePath) => {
30172
+ const cachedBuildComponent = resolvedServerBuildComponentCache.get(buildReferencePath);
30173
+ if (cachedBuildComponent) {
30174
+ return cachedBuildComponent;
30175
+ }
30176
+ const loadPromise = (async () => {
30177
+ const compiledModulePath = await compileSvelteServerModule(buildReferencePath);
30178
+ const loadedModule = await import(compiledModulePath);
30179
+ return "default" in loadedModule ? loadedModule.default : loadedModule;
30180
+ })();
30181
+ resolvedServerBuildComponentCache.set(buildReferencePath, loadPromise);
30182
+ return loadPromise;
30183
+ }, loadServerImportComponent = async (resolvedComponent) => {
30184
+ const resolvedModulePath = resolvedComponent.startsWith(".") ? new URL(resolvedComponent, import.meta.url).pathname : resolvedComponent;
30185
+ const importTarget = resolvedModulePath.endsWith(".svelte") ? await compileSvelteServerModule(resolvedModulePath) : resolvedModulePath;
30186
+ const loadedModule = await import(importTarget);
30187
+ return "default" in loadedModule ? loadedModule.default : loadedModule;
30188
+ }, resolveServerIslandComponent = async (component) => {
30189
+ const cachedResolvedComponent = resolvedServerComponentCache.get(component);
30190
+ if (cachedResolvedComponent) {
30191
+ return cachedResolvedComponent;
30192
+ }
30193
+ const resolutionPromise = (async () => {
30194
+ const buildReference = getIslandBuildReference(component);
30195
+ const buildReferencePath = buildReference?.source ? resolveBuildReferencePath(buildReference.source, import.meta.url) : null;
30196
+ if (buildReferencePath?.endsWith(".svelte")) {
30197
+ return loadServerBuildComponent(buildReferencePath);
30198
+ }
30199
+ const resolvedComponent = getIslandComponent(component);
30200
+ if (typeof resolvedComponent !== "string") {
30201
+ return resolvedComponent;
30202
+ }
30203
+ return loadServerImportComponent(resolvedComponent);
30204
+ })();
30205
+ resolvedServerComponentCache.set(component, resolutionPromise);
30206
+ return resolutionPromise;
30207
+ }, resolveReactServerIslandComponent = async (component) => {
30208
+ const resolvedComponent = await resolveServerIslandComponent(component);
30209
+ if (!isReactServerIslandComponent(resolvedComponent)) {
30210
+ throw new Error("Resolved React island is not a valid React component.");
30211
+ }
30212
+ return resolvedComponent;
30213
+ }, resolveSvelteServerIslandComponent = async (component) => {
30214
+ const resolvedComponent = await resolveServerIslandComponent(component);
30215
+ if (!isSvelteServerIslandComponent(resolvedComponent)) {
30216
+ throw new Error("Resolved Svelte island is not a valid Svelte component.");
30217
+ }
30218
+ return resolvedComponent;
30219
+ }, resolveVueServerIslandComponent = async (component) => {
30220
+ const resolvedComponent = await resolveServerIslandComponent(component);
30221
+ if (!isVueServerIslandComponent(resolvedComponent)) {
30222
+ throw new Error("Resolved Vue island is not a valid Vue component.");
30223
+ }
30224
+ return resolvedComponent;
30225
+ }, resolveAngularServerIslandComponent = async (component) => {
30226
+ const resolvedComponent = await resolveServerIslandComponent(component);
30227
+ if (!isAngularServerIslandComponent(resolvedComponent)) {
30228
+ throw new Error("Resolved Angular island is not a valid Angular component.");
30229
+ }
30230
+ return resolvedComponent;
30231
+ }, renderIslandResult = async (registry, props) => {
30232
+ const islandId = nextIslandId();
30233
+ const attributes = getIslandMarkerAttributes(props);
30234
+ if (props.framework === "react") {
30235
+ const entry = registry.react?.[props.component];
30236
+ if (!entry) {
30237
+ throw new Error(`Island component "${props.component}" is not registered for framework "react".`);
30238
+ }
30239
+ const component = await resolveReactServerIslandComponent(entry);
30240
+ const html = renderReactIslandToHtml(component, props.props);
30241
+ return { attributes, html };
30242
+ }
30243
+ if (props.framework === "svelte") {
30244
+ const entry = registry.svelte?.[props.component];
30245
+ if (!entry) {
30246
+ throw new Error(`Island component "${props.component}" is not registered for framework "svelte".`);
30247
+ }
30248
+ const component = await resolveSvelteServerIslandComponent(entry);
30249
+ const html = renderSvelteIslandToHtml(component, props.props);
30250
+ return { attributes, html };
30251
+ }
30252
+ if (props.framework === "vue") {
30253
+ const entry = registry.vue?.[props.component];
30254
+ if (!entry) {
30255
+ throw new Error(`Island component "${props.component}" is not registered for framework "vue".`);
30256
+ }
30257
+ const component = await resolveVueServerIslandComponent(entry);
30258
+ const html = await renderVueIslandToHtml(component, props.props);
30259
+ return { attributes, html };
30260
+ }
30261
+ if (props.framework === "angular") {
30262
+ const entry = registry.angular?.[props.component];
30263
+ if (!entry) {
30264
+ throw new Error(`Island component "${props.component}" is not registered for framework "angular".`);
30265
+ }
30266
+ const component = await resolveAngularServerIslandComponent(entry);
30267
+ const html = await renderAngularIslandToHtml(component, props.props, islandId);
30268
+ return {
30269
+ attributes: {
30270
+ ...getIslandMarkerAttributes(props, islandId)
30271
+ },
30272
+ html
30273
+ };
30274
+ }
30275
+ throw new Error(`Framework "${props.framework}" is not implemented in this prototype.`);
30276
+ }, renderIslandMarkup = async (registry, props) => {
30277
+ const result = await renderIslandResult(registry, props);
30278
+ return `<div ${serializeIslandAttributes(result.attributes)}>${result.html}</div>`;
30279
+ };
30280
+ var init_renderIslandMarkup = __esm(() => {
30281
+ init_islandSsr();
30282
+ init_svelteServerModule();
30283
+ init_islandMarkupAttributes();
30284
+ init_islands();
30285
+ resolvedServerComponentCache = new Map;
30286
+ resolvedServerBuildComponentCache = new Map;
30287
+ });
30288
+
30289
+ // src/build/islandEntries.ts
30290
+ import {
30291
+ mkdirSync,
30292
+ rmSync,
30293
+ writeFileSync as writeFileSync2
30294
+ } from "fs";
30295
+ import { dirname as dirname3, extname as extname2, join as join3, relative as relative2, resolve as resolve4 } from "path";
30296
+ var frameworks, isRecord3 = (value) => typeof value === "object" && value !== null, resolveRegistryExport = (mod) => {
30297
+ if (isRecord3(mod.islandRegistry))
30298
+ return mod.islandRegistry;
30299
+ if (isRecord3(mod.default))
30300
+ return mod.default;
30301
+ throw new Error("Island registry module must export `islandRegistry` or a default registry object.");
30302
+ }, normalizeImportPath = (wrapperPath, targetPath) => {
30303
+ const importPath = relative2(dirname3(wrapperPath), targetPath).replace(/\\/g, "/");
30304
+ return importPath.startsWith(".") ? importPath : `./${importPath}`;
30305
+ }, isIdentifier = (value) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value), resolveIslandSourcePath = (registryPath, sourcePath) => {
30306
+ if (sourcePath.startsWith("file://")) {
30307
+ return new URL(sourcePath).pathname;
30308
+ }
30309
+ return resolve4(dirname3(registryPath), sourcePath);
30310
+ }, createRegistryImportCode = (wrapperPath, registryPath, hasNamedExport) => {
30311
+ const normalizedPath = normalizeImportPath(wrapperPath, registryPath);
30312
+ if (hasNamedExport) {
30313
+ return {
30314
+ importStatement: `import { islandRegistry as __absoluteIslandRegistry } from ${JSON.stringify(normalizedPath)};`,
30315
+ registryReference: "__absoluteIslandRegistry"
30316
+ };
30317
+ }
30318
+ return {
30319
+ importStatement: `import __absoluteIslandRegistry from ${JSON.stringify(normalizedPath)};`,
30320
+ registryReference: "__absoluteIslandRegistry"
30321
+ };
30322
+ }, createDirectEntrySource = (wrapperPath, importPath, exportName) => {
30323
+ const normalizedImportPath = normalizeImportPath(wrapperPath, importPath);
30324
+ if (!exportName || exportName === "default") {
30325
+ return `export { default } from ${JSON.stringify(normalizedImportPath)};
30326
+ `;
30327
+ }
30328
+ return `export { ${exportName} as default } from ${JSON.stringify(normalizedImportPath)};
30329
+ `;
30330
+ }, createRegistryEntrySource = (wrapperPath, registryPath, hasNamedExport, framework, component) => {
30331
+ const { importStatement, registryReference } = createRegistryImportCode(wrapperPath, registryPath, hasNamedExport);
30332
+ const frameworkAccess = isIdentifier(framework) ? `${registryReference}.${framework}` : `${registryReference}[${JSON.stringify(framework)}]`;
30333
+ const componentAccess = isIdentifier(component) ? `${frameworkAccess}.${component}` : `${frameworkAccess}[${JSON.stringify(component)}]`;
30334
+ return `${importStatement}
30335
+
30336
+ const component = ${componentAccess};
30337
+
30338
+ export default component;
30339
+ `;
30340
+ }, shouldUseCompiledClientPath = (framework, sourcePath) => {
30341
+ if (framework === "svelte") {
30342
+ return /\.svelte(?:\.(?:ts|js))?$/.test(sourcePath);
30343
+ }
30344
+ if (framework === "vue") {
30345
+ return extname2(sourcePath) === ".vue";
30346
+ }
30347
+ return false;
30348
+ }, loadIslandRegistryBuildInfo = async (registryPath) => {
30349
+ const resolvedRegistryPath = resolve4(registryPath);
30350
+ const registryModule = await import(resolvedRegistryPath);
30351
+ const registry = resolveRegistryExport(registryModule);
30352
+ const definitions = [];
30353
+ for (const framework of frameworks) {
30354
+ const frameworkRegistry = registry[framework];
30355
+ if (!isRecord3(frameworkRegistry))
30356
+ continue;
30357
+ for (const [component, value] of Object.entries(frameworkRegistry)) {
30358
+ definitions.push({
30359
+ buildReference: getIslandBuildReference(value),
30360
+ component,
30361
+ framework
30362
+ });
30363
+ }
30364
+ }
30365
+ return {
30366
+ definitions,
30367
+ hasNamedExport: isRecord3(registryModule.islandRegistry),
30368
+ registry,
30369
+ resolvedRegistryPath
30370
+ };
30371
+ }, collectIslandFrameworkSources = (buildInfo) => {
30372
+ const sources = {};
30373
+ for (const definition of buildInfo.definitions) {
30374
+ const buildReference = definition.buildReference;
30375
+ if (!buildReference)
30376
+ continue;
30377
+ const resolvedSourcePath = resolveIslandSourcePath(buildInfo.resolvedRegistryPath, buildReference.source);
30378
+ if (!shouldUseCompiledClientPath(definition.framework, resolvedSourcePath)) {
30379
+ continue;
30380
+ }
30381
+ const frameworkSources = sources[definition.framework] ?? [];
30382
+ if (!frameworkSources.includes(resolvedSourcePath)) {
30383
+ frameworkSources.push(resolvedSourcePath);
30384
+ }
30385
+ sources[definition.framework] = frameworkSources;
30386
+ }
30387
+ return sources;
30388
+ }, generateIslandEntryPoints = async ({
30389
+ buildInfo,
30390
+ buildPath,
30391
+ clientPathMaps = {}
30392
+ }) => {
30393
+ const generatedRoot = join3(buildPath, "_island_entries");
30394
+ rmSync(generatedRoot, { force: true, recursive: true });
30395
+ const entries = [];
30396
+ for (const definition of buildInfo.definitions) {
30397
+ const entryPath = join3(generatedRoot, "islands", definition.framework, `${definition.component}.ts`);
30398
+ const buildReference = definition.buildReference;
30399
+ const source = buildReference ? resolveIslandSourcePath(buildInfo.resolvedRegistryPath, buildReference.source) : null;
30400
+ const compiledSourcePath = source && shouldUseCompiledClientPath(definition.framework, source) ? clientPathMaps[definition.framework]?.get(source) : undefined;
30401
+ const entrySource = source && (compiledSourcePath || !shouldUseCompiledClientPath(definition.framework, source)) ? createDirectEntrySource(entryPath, compiledSourcePath ?? source, compiledSourcePath ? undefined : buildReference?.export) : createRegistryEntrySource(entryPath, buildInfo.resolvedRegistryPath, buildInfo.hasNamedExport, definition.framework, definition.component);
30402
+ mkdirSync(dirname3(entryPath), { recursive: true });
30403
+ writeFileSync2(entryPath, entrySource);
30404
+ entries.push({
30405
+ component: definition.component,
30406
+ entryPath,
30407
+ framework: definition.framework
30408
+ });
30409
+ }
30410
+ return {
30411
+ entries,
30412
+ generatedRoot
30413
+ };
30414
+ };
30415
+ var init_islandEntries = __esm(() => {
30416
+ init_islands();
30417
+ frameworks = [
30418
+ "react",
30419
+ "svelte",
30420
+ "vue",
30421
+ "angular"
30422
+ ];
30423
+ });
30424
+
30425
+ // src/core/currentIslandRegistry.ts
30426
+ var setCurrentIslandRegistry = (registry) => {
30427
+ globalThis.__absoluteIslandRegistry = registry;
30428
+ }, requireCurrentIslandRegistry = () => {
30429
+ const registry = globalThis.__absoluteIslandRegistry;
30430
+ if (!registry) {
30431
+ throw new Error("No island registry is active. Configure `islands.registry` in absolute.config.ts before rendering <Island />.");
30432
+ }
30433
+ return registry;
30434
+ };
30435
+
30436
+ // src/build/staticIslandPages.ts
30437
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
30438
+ var ISLAND_TAG_RE_SOURCE = "<(?:absolute-island|island)\\b([^>]*?)(?:\\/\\>|>(?:[\\s\\S]*?)<\\/(?:absolute-island|island)>)", ATTRIBUTE_RE_SOURCE = `([A-Za-z_:][-A-Za-z0-9_:.]*)\\s*=\\s*(?:"([^"]*)"|'([^']*)')`, islandFrameworks, islandHydrationModes, isRecord4 = (value) => typeof value === "object" && value !== null, isIslandFramework = (value) => islandFrameworks.some((framework) => framework === value), isIslandHydrationMode = (value) => islandHydrationModes.some((mode) => mode === value), parseIslandAttributes = (attributeString) => {
30439
+ const attributeRe = new RegExp(ATTRIBUTE_RE_SOURCE, "g");
30440
+ const attributes = new Map;
30441
+ let match = attributeRe.exec(attributeString);
30442
+ while (match) {
30443
+ const key = match[1];
30444
+ const doubleQuotedValue = match[2];
30445
+ const singleQuotedValue = match[3];
30446
+ if (!key) {
30447
+ match = attributeRe.exec(attributeString);
30448
+ continue;
30449
+ }
30450
+ const value = doubleQuotedValue ?? singleQuotedValue ?? "";
30451
+ attributes.set(key, value);
30452
+ match = attributeRe.exec(attributeString);
30453
+ }
30454
+ return attributes;
30455
+ }, parseIslandTag = (attributeString) => {
30456
+ const attributes = parseIslandAttributes(attributeString);
30457
+ const framework = attributes.get("framework");
30458
+ const component = attributes.get("component");
30459
+ const hydrate = attributes.get("hydrate") ?? "load";
30460
+ const propsSource = attributes.get("props") ?? "{}";
30461
+ if (!framework || !component) {
30462
+ return null;
30463
+ }
30464
+ if (!isIslandFramework(framework)) {
30465
+ throw new Error(`Unsupported static island framework "${framework}".`);
30466
+ }
30467
+ if (!isIslandHydrationMode(hydrate)) {
30468
+ throw new Error(`Unsupported static island hydrate mode "${hydrate}".`);
30469
+ }
30470
+ let parsedProps;
30471
+ try {
30472
+ const candidate = JSON.parse(propsSource);
30473
+ parsedProps = isRecord4(candidate) ? candidate : {};
30474
+ } catch (error) {
30475
+ throw new Error(`Failed to parse static island props JSON for ${framework}:${component}: ${error instanceof Error ? error.message : String(error)}`);
30476
+ }
30477
+ return {
30478
+ component,
30479
+ framework,
30480
+ hydrate,
30481
+ props: parsedProps
30482
+ };
30483
+ }, transformStaticPageHtml = async (originalHtml, registry) => {
30484
+ const islandTagRe = new RegExp(ISLAND_TAG_RE_SOURCE, "gi");
30485
+ if (!islandTagRe.test(originalHtml)) {
30486
+ return originalHtml;
30487
+ }
30488
+ islandTagRe.lastIndex = 0;
30489
+ let transformedHtml = "";
30490
+ let lastIndex = 0;
30491
+ let match = islandTagRe.exec(originalHtml);
30492
+ while (match) {
30493
+ const fullMatch = match[0];
30494
+ const attributeString = match[1] ?? "";
30495
+ const matchIndex = match.index;
30496
+ transformedHtml += originalHtml.slice(lastIndex, matchIndex);
30497
+ const props = parseIslandTag(attributeString);
30498
+ transformedHtml += props ? await renderIslandMarkup(registry, props) : fullMatch;
30499
+ lastIndex = matchIndex + fullMatch.length;
30500
+ match = islandTagRe.exec(originalHtml);
30501
+ }
30502
+ transformedHtml += originalHtml.slice(lastIndex);
30503
+ return transformedHtml;
30504
+ }, transformStaticPage = async (pagePath, registry) => {
30505
+ const originalHtml = readFileSync2(pagePath, "utf-8");
30506
+ const transformedHtml = await transformStaticPageHtml(originalHtml, registry);
30507
+ if (transformedHtml !== originalHtml) {
30508
+ writeFileSync3(pagePath, transformedHtml);
30509
+ }
30510
+ }, transformStaticPagesWithIslands = async (registryPath, pagePaths) => {
30511
+ if (!registryPath || pagePaths.length === 0) {
30512
+ return;
30513
+ }
30514
+ const { registry } = await loadIslandRegistryBuildInfo(registryPath);
30515
+ await Promise.all(pagePaths.map((pagePath) => transformStaticPage(pagePath, registry)));
30516
+ }, transformCurrentStaticPageHtml = async (html) => transformStaticPageHtml(html, requireCurrentIslandRegistry());
30517
+ var init_staticIslandPages = __esm(() => {
30518
+ init_renderIslandMarkup();
30519
+ init_islandEntries();
30520
+ islandFrameworks = [
30521
+ "react",
30522
+ "svelte",
30523
+ "vue",
30524
+ "angular"
30525
+ ];
30526
+ islandHydrationModes = ["load", "idle", "visible", "none"];
30527
+ });
30528
+
30529
+ // src/core/islandPageContext.ts
30530
+ var BOOTSTRAP_MANIFEST_KEY = "BootstrapClient", ISLAND_MARKER = 'data-island="true"', MANIFEST_MARKER = "__ABSOLUTE_MANIFEST__", ISLAND_STATE_MARKER = "__ABS_ISLAND_STATE__", buildIslandsHeadMarkup = (manifest) => {
30531
+ const manifestScript = `<script>window.__ABSOLUTE_MANIFEST__ = ${JSON.stringify(manifest)}</script>`;
30532
+ const islandStateScript = "<script>window.__ABS_ISLAND_STATE__ = window.__ABS_ISLAND_STATE__ ?? {}</script>";
30533
+ const bootstrapPath = manifest[BOOTSTRAP_MANIFEST_KEY];
30534
+ const bootstrapScript = bootstrapPath ? `<script type="module" src="${bootstrapPath}"></script>` : "";
30535
+ return `${manifestScript}${islandStateScript}${bootstrapScript}`;
30536
+ }, injectHeadMarkup = (html, markup) => {
30537
+ const closingHeadIndex = html.indexOf("</head>");
30538
+ if (closingHeadIndex >= 0) {
30539
+ return `${html.slice(0, closingHeadIndex)}${markup}${html.slice(closingHeadIndex)}`;
30540
+ }
30541
+ const openingBodyIndex = html.indexOf("<body");
30542
+ if (openingBodyIndex >= 0) {
30543
+ const bodyStart = html.indexOf(">", openingBodyIndex);
30544
+ if (bodyStart >= 0) {
30545
+ return `${html.slice(0, openingBodyIndex)}<head>${markup}</head>${html.slice(openingBodyIndex)}`;
30546
+ }
30547
+ }
30548
+ return `<!DOCTYPE html><html><head>${markup}</head><body>${html}</body></html>`;
30549
+ }, setCurrentIslandManifest = (manifest) => {
30550
+ globalThis.__absoluteManifest = manifest;
30551
+ }, htmlContainsIslands = (html) => html.includes(ISLAND_MARKER), injectIslandPageContext = (html, options) => {
30552
+ const manifest = globalThis.__absoluteManifest;
30553
+ const hasIslands = options?.hasIslands ?? htmlContainsIslands(html);
30554
+ if (!manifest || !hasIslands) {
30555
+ return html;
30556
+ }
30557
+ if (html.includes(MANIFEST_MARKER) || html.includes(ISLAND_STATE_MARKER)) {
30558
+ return html;
30559
+ }
30560
+ return injectHeadMarkup(html, buildIslandsHeadMarkup(manifest));
30561
+ };
30562
+
30563
+ // src/utils/ssrErrorPage.ts
30564
+ var ssrErrorPage = (framework, error) => {
30565
+ const frameworkColors = {
30566
+ angular: "#dd0031",
30567
+ html: "#e34c26",
30568
+ htmx: "#1a365d",
30569
+ react: "#61dafb",
30570
+ svelte: "#ff3e00",
30571
+ vue: "#42b883"
30572
+ };
30573
+ const accent = frameworkColors[framework] ?? "#94a3b8";
30574
+ const label = framework.charAt(0).toUpperCase() + framework.slice(1);
30575
+ const message = error instanceof Error ? error.message : String(error);
30576
+ return `<!DOCTYPE html>
30577
+ <html>
30578
+ <head>
30579
+ <meta charset="utf-8">
30580
+ <meta name="viewport" content="width=device-width, initial-scale=1">
30581
+ <title>SSR Error - AbsoluteJS</title>
30582
+ <style>
30583
+ *{margin:0;padding:0;box-sizing:border-box}
30584
+ 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}
30585
+ .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}
30586
+ .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)}
30587
+ .brand{font-weight:700;font-size:20px;color:#fff;letter-spacing:-0.02em}
30588
+ .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)}
30589
+ .kind{color:#94a3b8;font-size:13px;font-weight:500}
30590
+ .content{padding:24px}
30591
+ .label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.08em;color:#94a3b8;margin-bottom:8px}
30592
+ .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}
30593
+ .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}
30594
+ </style>
30595
+ </head>
30596
+ <body>
30597
+ <div class="card">
30598
+ <div class="header">
30599
+ <div style="display:flex;align-items:center;gap:12px">
30600
+ <span class="brand">AbsoluteJS</span>
30601
+ <span class="badge">${label}</span>
30602
+ </div>
30603
+ <span class="kind">Server Render Error</span>
30604
+ </div>
30605
+ <div class="content">
30606
+ <div class="label">What went wrong</div>
30607
+ <pre class="message">${message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")}</pre>
30608
+ <div class="hint">A component threw during server-side rendering. Check the terminal for the full stack trace.</div>
30609
+ </div>
30610
+ </div>
30611
+ </body>
30612
+ </html>`;
30613
+ };
30614
+
30615
+ // src/utils/resolveConvention.ts
30616
+ import { basename } from "path";
30617
+ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boolean(value) && typeof value === "object", getMap = () => {
30618
+ const value = Reflect.get(globalThis, CONVENTIONS_KEY);
30619
+ if (isConventionsMap(value))
30620
+ return value;
30621
+ const empty = {};
30622
+ return empty;
30623
+ }, derivePageName = (pagePath) => {
30624
+ const base = basename(pagePath);
30625
+ const dotIndex = base.indexOf(".");
30626
+ const name = dotIndex > 0 ? base.slice(0, dotIndex) : base;
30627
+ return toPascal(name);
30628
+ }, resolveErrorConventionPath = (framework, pageName) => {
30629
+ const conventions2 = getMap()[framework];
30630
+ if (!conventions2)
30631
+ return;
30632
+ return conventions2.pages?.[pageName]?.error ?? conventions2.defaults?.error;
30633
+ }, resolveNotFoundConventionPath = (framework) => getMap()[framework]?.defaults?.notFound, setConventions = (map) => {
30634
+ Reflect.set(globalThis, CONVENTIONS_KEY, map);
30635
+ }, isDev = () => true, buildErrorProps = (error) => {
30636
+ const message = error instanceof Error ? error.message : String(error);
30637
+ const stack = isDev() && error instanceof Error ? error.stack : undefined;
30638
+ return { error: { message, stack } };
30639
+ }, renderReactError = async (conventionPath, errorProps) => {
30640
+ const { createElement: createElement2 } = await import("react");
30641
+ const { renderToReadableStream } = await import("react-dom/server");
30642
+ const mod = await import(conventionPath);
30643
+ const [firstKey] = Object.keys(mod);
30644
+ const ErrorComponent = mod.default ?? (firstKey ? mod[firstKey] : undefined);
30645
+ const element2 = createElement2(ErrorComponent, errorProps);
30646
+ const stream = await renderToReadableStream(element2);
30647
+ return new Response(stream, {
30648
+ headers: { "Content-Type": "text/html" },
30649
+ status: 500
30650
+ });
30651
+ }, renderSvelteError = async (conventionPath, errorProps) => {
30652
+ const { render } = await import("svelte/server");
30653
+ const mod = await import(conventionPath);
30654
+ const ErrorComponent = mod.default;
30655
+ const { head, body } = render(ErrorComponent, {
30656
+ props: errorProps
30657
+ });
30658
+ const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
30659
+ return new Response(html, {
30660
+ headers: { "Content-Type": "text/html" },
30661
+ status: 500
30662
+ });
30663
+ }, unescapeVueStyles = (ssrBody) => {
30664
+ let styles = "";
30665
+ const body = ssrBody.replace(/<style>([\s\S]*?)<\/style>/g, (_, css) => {
30666
+ styles += `<style>${css.replace(/&quot;/g, '"').replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">")}</style>`;
30667
+ return "";
30668
+ });
30669
+ return { body, styles };
30670
+ }, renderVueError = async (conventionPath, errorProps) => {
30671
+ const { createSSRApp: createSSRApp2, h: h2 } = await import("vue");
30672
+ const { renderToString } = await import("vue/server-renderer");
30673
+ const mod = await import(conventionPath);
30674
+ const ErrorComponent = mod.default;
30675
+ const app = createSSRApp2({
30676
+ render: () => h2(ErrorComponent, errorProps)
30677
+ });
30678
+ const rawBody = await renderToString(app);
30679
+ const { styles, body } = unescapeVueStyles(rawBody);
30680
+ const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
30681
+ return new Response(html, {
30682
+ headers: { "Content-Type": "text/html" },
30683
+ status: 500
30684
+ });
30685
+ }, renderAngularError = async (conventionPath, errorProps) => {
30686
+ const mod = await import(conventionPath);
30687
+ const renderError = mod.default ?? mod.renderError;
30688
+ if (typeof renderError !== "function")
30689
+ return null;
30690
+ const html = renderError(errorProps);
30691
+ return new Response(html, {
30692
+ headers: { "Content-Type": "text/html" },
30693
+ status: 500
30694
+ });
30695
+ }, logConventionRenderError = (framework, label, renderError) => {
30696
+ const message = renderError instanceof Error ? renderError.message : "";
30697
+ if (message.includes("Cannot find module") || message.includes("Cannot find package") || message.includes("not found in module")) {
30698
+ 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}).`);
30699
+ return;
30700
+ }
30701
+ console.error(`[SSR] Failed to render ${framework} convention ${label} page:`, renderError);
30702
+ }, ERROR_RENDERERS, renderConventionError = async (framework, pageName, error) => {
30703
+ const conventionPath = resolveErrorConventionPath(framework, pageName);
30704
+ if (!conventionPath)
30705
+ return null;
30706
+ const errorProps = buildErrorProps(error);
30707
+ const renderer = ERROR_RENDERERS[framework];
30708
+ if (!renderer)
30709
+ return null;
30710
+ try {
30711
+ return await renderer(conventionPath, errorProps);
30712
+ } catch (renderError) {
30713
+ logConventionRenderError(framework, "error", renderError);
30714
+ }
30715
+ return null;
30716
+ }, renderReactNotFound = async (conventionPath) => {
30717
+ const { createElement: createElement2 } = await import("react");
30718
+ const { renderToReadableStream } = await import("react-dom/server");
30719
+ const mod = await import(conventionPath);
30720
+ const [nfKey] = Object.keys(mod);
30721
+ const NotFoundComponent = mod.default ?? (nfKey ? mod[nfKey] : undefined);
30722
+ const element2 = createElement2(NotFoundComponent);
30723
+ const stream = await renderToReadableStream(element2);
30724
+ return new Response(stream, {
30725
+ headers: { "Content-Type": "text/html" },
30726
+ status: 404
30727
+ });
30728
+ }, renderSvelteNotFound = async (conventionPath) => {
30729
+ const { render } = await import("svelte/server");
30730
+ const mod = await import(conventionPath);
30731
+ const NotFoundComponent = mod.default;
30732
+ const { head, body } = render(NotFoundComponent);
30733
+ const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
30734
+ return new Response(html, {
30735
+ headers: { "Content-Type": "text/html" },
30736
+ status: 404
30737
+ });
30738
+ }, renderVueNotFound = async (conventionPath) => {
30739
+ const { createSSRApp: createSSRApp2, h: h2 } = await import("vue");
30740
+ const { renderToString } = await import("vue/server-renderer");
30741
+ const mod = await import(conventionPath);
30742
+ const NotFoundComponent = mod.default;
30743
+ const app = createSSRApp2({
30744
+ render: () => h2(NotFoundComponent)
30745
+ });
30746
+ const rawBody = await renderToString(app);
30747
+ const { styles, body } = unescapeVueStyles(rawBody);
30748
+ const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
30749
+ return new Response(html, {
30750
+ headers: { "Content-Type": "text/html" },
30751
+ status: 404
30752
+ });
30753
+ }, renderAngularNotFound = async (conventionPath) => {
30754
+ const mod = await import(conventionPath);
30755
+ const renderNotFound = mod.default ?? mod.renderNotFound;
30756
+ if (typeof renderNotFound !== "function")
30757
+ return null;
30758
+ const html = renderNotFound();
30759
+ return new Response(html, {
30760
+ headers: { "Content-Type": "text/html" },
30761
+ status: 404
30762
+ });
30763
+ }, NOT_FOUND_RENDERERS, renderConventionNotFound = async (framework) => {
30764
+ const conventionPath = resolveNotFoundConventionPath(framework);
30765
+ if (!conventionPath)
30766
+ return null;
30767
+ const renderer = NOT_FOUND_RENDERERS[framework];
30768
+ if (!renderer)
30769
+ return null;
30770
+ try {
30771
+ return await renderer(conventionPath);
30772
+ } catch (renderError) {
30773
+ logConventionRenderError(framework, "not-found", renderError);
30774
+ }
30775
+ return null;
30776
+ }, NOT_FOUND_PRIORITY, renderFirstNotFound = async () => {
30777
+ for (const framework of NOT_FOUND_PRIORITY) {
30778
+ if (!getMap()[framework]?.defaults?.notFound)
30779
+ continue;
30780
+ const response = await renderConventionNotFound(framework);
30781
+ if (response)
30782
+ return response;
30783
+ }
30784
+ return null;
30785
+ };
30786
+ var init_resolveConvention = __esm(() => {
30787
+ ERROR_RENDERERS = {
30788
+ angular: renderAngularError,
30789
+ react: renderReactError,
30790
+ svelte: renderSvelteError,
30791
+ vue: renderVueError
30792
+ };
30793
+ NOT_FOUND_RENDERERS = {
30794
+ angular: renderAngularNotFound,
30795
+ react: renderReactNotFound,
30796
+ svelte: renderSvelteNotFound,
30797
+ vue: renderVueNotFound
30798
+ };
30799
+ NOT_FOUND_PRIORITY = [
30800
+ "react",
30801
+ "svelte",
30802
+ "vue",
30803
+ "angular"
30804
+ ];
30805
+ });
30806
+
30807
+ // src/react/pageHandler.ts
30808
+ var ssrDirty = false, buildDirtyResponse = (index, maybeProps) => {
30809
+ const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
30810
+ const dirtyFlag = "window.__SSR_DIRTY__=true;";
30811
+ const refreshSetup = "window.__REFRESH_BUFFER__=[];" + "window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};" + "window.$RefreshSig$=function(){return function(t){return t}};";
30812
+ const inlineScript = `${propsScript}${dirtyFlag}${refreshSetup}`;
30813
+ const html = `<!DOCTYPE html><html><head></head><body>` + `<script>${inlineScript}</script>` + `<script type="module" src="${index}"></script>` + `</body></html>`;
30814
+ return new Response(html, {
30815
+ headers: { "Content-Type": "text/html" }
30816
+ });
30817
+ }, handleReactPageRequest = async (PageComponent, index, ...props) => {
30818
+ const [maybeProps] = props;
30819
+ if (ssrDirty) {
30820
+ return buildDirtyResponse(index, maybeProps);
30821
+ }
30822
+ try {
30823
+ const { createElement: createElement2 } = await import("react");
30824
+ const { renderToReadableStream } = await import("react-dom/server");
30825
+ const element2 = maybeProps !== undefined ? createElement2(PageComponent, maybeProps) : createElement2(PageComponent);
30826
+ const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
30827
+ const refreshSetup = "window.__REFRESH_BUFFER__=[];window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};window.$RefreshSig$=function(){return function(t){return t}};";
30828
+ const stream = await renderToReadableStream(element2, {
30829
+ bootstrapModules: [index],
30830
+ bootstrapScriptContent: propsScript + refreshSetup || undefined,
30831
+ onError(error) {
30832
+ console.error("[SSR] React streaming error:", error);
30833
+ }
30834
+ });
30835
+ const html = injectIslandPageContext(await new Response(stream).text());
30836
+ return new Response(html, {
30837
+ headers: { "Content-Type": "text/html" }
30838
+ });
30839
+ } catch (error) {
30840
+ console.error("[SSR] React render error:", error);
30841
+ const pageName = PageComponent.name || PageComponent.displayName || "";
30842
+ const conventionResponse = await renderConventionError("react", pageName, error);
30843
+ if (conventionResponse)
30844
+ return conventionResponse;
30845
+ return new Response(ssrErrorPage("react", error), {
30846
+ headers: { "Content-Type": "text/html" },
30847
+ status: 500
30848
+ });
30849
+ }
30850
+ }, invalidateReactSsrCache = () => {
30851
+ ssrDirty = true;
30852
+ };
30853
+ var init_pageHandler = __esm(() => {
30854
+ init_resolveConvention();
30855
+ });
30856
+
30857
+ // src/build/scanEntryPoints.ts
30858
+ import { existsSync as existsSync3 } from "fs";
30859
+ var {Glob } = globalThis.Bun;
30860
+ var scanEntryPoints = async (dir, pattern) => {
30861
+ if (!existsSync3(dir))
30862
+ return [];
30863
+ const entryPaths = [];
30864
+ const glob = new Glob(pattern);
30865
+ for await (const file2 of glob.scan({ absolute: true, cwd: dir })) {
30866
+ entryPaths.push(file2);
30867
+ }
30868
+ return entryPaths;
30869
+ };
30870
+ var init_scanEntryPoints = () => {};
30871
+
30872
+ // src/islands/sourceMetadata.ts
30873
+ var islandFrameworks2, islandHydrationModes2, isIslandFramework2 = (value) => islandFrameworks2.some((framework) => framework === value), isIslandHydrate = (value) => islandHydrationModes2.some((hydrate) => hydrate === value), parseIslandTagAttributes = (attributeString) => {
30874
+ const frameworkMatch = attributeString.match(/\bframework\s*=\s*["']([^"']+)["']/);
30875
+ const componentMatch = attributeString.match(/\bcomponent\s*=\s*["']([^"']+)["']/);
30876
+ const hydrateMatch = attributeString.match(/\bhydrate\s*=\s*["']([^"']+)["']/);
30877
+ const framework = frameworkMatch?.[1];
30878
+ const component = componentMatch?.[1];
30879
+ if (!framework || !component) {
30880
+ return null;
30881
+ }
30882
+ if (!isIslandFramework2(framework)) {
30883
+ return null;
30884
+ }
30885
+ const hydrateCandidate = hydrateMatch?.[1];
30886
+ return {
30887
+ component,
30888
+ framework,
30889
+ hydrate: hydrateCandidate && isIslandHydrate(hydrateCandidate) ? hydrateCandidate : undefined
30890
+ };
30891
+ }, normalizeUsage = (usage) => `${usage.framework}:${usage.component}:${usage.hydrate ?? ""}`, addUsage = (usageMap, usage) => {
30892
+ if (!usage)
30893
+ return;
30894
+ usageMap.set(normalizeUsage(usage), usage);
30895
+ }, extractIslandUsagesFromSource = (source) => {
30896
+ const usageMap = new Map;
30897
+ const islandTagRegex = /<Island\b([\s\S]*?)(?:\/>|>(?:[\s\S]*?)<\/Island>)/g;
30898
+ let islandTagMatch = islandTagRegex.exec(source);
30899
+ while (islandTagMatch) {
30900
+ addUsage(usageMap, parseIslandTagAttributes(islandTagMatch[1] ?? ""));
30901
+ islandTagMatch = islandTagRegex.exec(source);
30902
+ }
30903
+ const staticRenderCallRegex = /renderIsland\s*\(\s*\{[\s\S]*?\bframework\s*:\s*['"]([^'"]+)['"][\s\S]*?\bcomponent\s*:\s*['"]([^'"]+)['"](?:[\s\S]*?\bhydrate\s*:\s*['"]([^'"]+)['"])?[\s\S]*?\}\s*\)/g;
30904
+ let renderMatch = staticRenderCallRegex.exec(source);
30905
+ while (renderMatch) {
30906
+ const framework = renderMatch[1];
30907
+ const component = renderMatch[2];
30908
+ const hydrate = renderMatch[3];
30909
+ if (!framework || !component || !isIslandFramework2(framework)) {
30910
+ renderMatch = staticRenderCallRegex.exec(source);
30911
+ continue;
30912
+ }
30913
+ addUsage(usageMap, {
30914
+ component,
30915
+ framework,
30916
+ hydrate: hydrate && isIslandHydrate(hydrate) ? hydrate : undefined
30917
+ });
30918
+ renderMatch = staticRenderCallRegex.exec(source);
30919
+ }
30920
+ return [...usageMap.values()];
30921
+ }, buildIslandMetadataExports = (source) => {
30922
+ const usages = extractIslandUsagesFromSource(source);
30923
+ const serialized = JSON.stringify(usages);
30924
+ return `
30925
+ export const __ABSOLUTE_PAGE_ISLANDS__ = ${serialized};
30926
+ export const __ABSOLUTE_PAGE_HAS_ISLANDS__ = ${usages.length > 0};
30927
+ `;
30928
+ };
30929
+ var init_sourceMetadata = __esm(() => {
30930
+ islandFrameworks2 = [
30931
+ "react",
30932
+ "svelte",
30933
+ "vue",
30934
+ "angular"
30935
+ ];
30936
+ islandHydrationModes2 = [
30937
+ "load",
30938
+ "idle",
30939
+ "visible",
30940
+ "none"
30941
+ ];
30942
+ });
30943
+
30944
+ // src/islands/pageMetadata.ts
30945
+ import { readFileSync as readFileSync3 } from "fs";
30946
+ import { dirname as dirname4, resolve as resolve7 } from "path";
30947
+ var pagePatterns, getPageDirs = (config) => [
30948
+ { dir: config.angularDirectory, framework: "angular" },
30949
+ { dir: config.reactDirectory, framework: "react" },
30950
+ { dir: config.svelteDirectory, framework: "svelte" },
30951
+ { dir: config.vueDirectory, framework: "vue" },
30952
+ { dir: config.htmlDirectory, framework: "html" },
30953
+ { dir: config.htmxDirectory, framework: "htmx" }
30954
+ ].filter((entry) => typeof entry.dir === "string" && entry.dir.length > 0), buildIslandSourceLookup = async (config) => {
30955
+ const registryPath = config.islands?.registry;
30956
+ if (!registryPath) {
30957
+ return new Map;
30958
+ }
30959
+ const buildInfo = await loadIslandRegistryBuildInfo(registryPath);
30960
+ const lookup = new Map;
30961
+ for (const definition of buildInfo.definitions) {
30962
+ const source = definition.buildReference?.source;
30963
+ if (!source)
30964
+ continue;
30965
+ const resolvedSource = source.startsWith("file://") ? new URL(source).pathname : resolve7(dirname4(buildInfo.resolvedRegistryPath), source);
30966
+ lookup.set(`${definition.framework}:${definition.component}`, resolve7(resolvedSource));
31367
30967
  }
31368
- let islandIndex = 0;
31369
- const transformedMarkup = source.replace(ISLAND_TAG_RE, (fullMatch, attributeString) => {
31370
- const framework = extractIslandAttribute(attributeString, "framework");
31371
- const component = extractIslandAttribute(attributeString, "component");
31372
- if (!framework.found || !component.found) {
31373
- return fullMatch;
30968
+ return lookup;
30969
+ }, loadPageIslandMetadata = async (config) => {
30970
+ const pageMetadata = new Map;
30971
+ const islandSourceLookup = await buildIslandSourceLookup(config);
30972
+ for (const entry of getPageDirs(config)) {
30973
+ const pattern = pagePatterns[entry.framework];
30974
+ if (!pattern)
30975
+ continue;
30976
+ const files = await scanEntryPoints(resolve7(entry.dir), pattern);
30977
+ for (const filePath of files) {
30978
+ const source = readFileSync3(filePath, "utf-8");
30979
+ const islands = extractIslandUsagesFromSource(source);
30980
+ pageMetadata.set(resolve7(filePath), {
30981
+ islands: islands.map((usage) => {
30982
+ const sourcePath = islandSourceLookup.get(`${usage.framework}:${usage.component}`);
30983
+ return sourcePath ? {
30984
+ ...usage,
30985
+ source: sourcePath
30986
+ } : usage;
30987
+ }),
30988
+ pagePath: resolve7(filePath)
30989
+ });
31374
30990
  }
31375
- const hydrate = extractIslandAttribute(attributeString, "hydrate");
31376
- const props = extractIslandAttribute(attributeString, "props");
31377
- const slotId = `absolute-svelte-island-${islandIndex.toString(BASE_36_RADIX)}`;
31378
- islandIndex += 1;
31379
- 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 : "{}"} })`;
31380
- return `<div data-absolute-island-slot="${slotId}" style="display: contents">{@html ${resolveExpression}}</div>`;
31381
- });
31382
- const importLine = 'import { resolveIslandHtml as __absoluteResolveIslandHtml } from "@absolutejs/absolute/svelte";';
31383
- if (transformedMarkup.includes("<script")) {
31384
- return {
31385
- code: transformedMarkup.replace(/<script(\s[^>]*)?>/, (match) => `${match}
31386
- ${importLine}
31387
- `),
31388
- transformed: true
31389
- };
31390
30991
  }
31391
- return {
31392
- code: `<script lang="ts">
31393
- ${importLine}
31394
- </script>
31395
- ${transformedMarkup}`,
31396
- transformed: true
31397
- };
30992
+ return pageMetadata;
30993
+ }, setCurrentPageIslandMetadata = (metadata2) => {
30994
+ globalThis.__absolutePageIslandMetadata = metadata2;
30995
+ }, getCurrentPageIslandMetadata = () => globalThis.__absolutePageIslandMetadata ?? new Map, getPagesUsingIslandSource = (sourcePath) => {
30996
+ const target = resolve7(sourcePath);
30997
+ const matches = [];
30998
+ for (const metadata2 of getCurrentPageIslandMetadata().values()) {
30999
+ const usesTarget = metadata2.islands.some((usage) => {
31000
+ const candidate = usage.source;
31001
+ return candidate ? resolve7(candidate) === target : false;
31002
+ });
31003
+ if (usesTarget) {
31004
+ matches.push(metadata2.pagePath);
31005
+ }
31006
+ }
31007
+ return matches;
31398
31008
  };
31399
- var init_lowerIslandSyntax = __esm(() => {
31400
- init_constants();
31401
- ISLAND_TAG_RE = /<Island\b([\s\S]*?)\/>/g;
31009
+ var init_pageMetadata = __esm(() => {
31010
+ init_islandEntries();
31011
+ init_scanEntryPoints();
31012
+ init_sourceMetadata();
31013
+ pagePatterns = {
31014
+ angular: "pages/**/*.{ts,js}",
31015
+ html: "pages/**/*.html",
31016
+ htmx: "pages/**/*.html",
31017
+ react: "pages/**/*.{ts,tsx,js,jsx}",
31018
+ svelte: "pages/**/*.svelte",
31019
+ vue: "pages/**/*.vue"
31020
+ };
31402
31021
  });
31403
31022
 
31404
- // src/core/svelteServerModule.ts
31405
- import { mkdir } from "fs/promises";
31406
- import { dirname as dirname5, extname as extname3, join as join4, relative as relative3, resolve as resolve10 } from "path";
31407
- var serverCacheRoot, compiledModuleCache, transpiler, ensureRelativeImportPath = (from, to) => {
31408
- const importPath = relative3(dirname5(from), to).replace(/\\/g, "/");
31409
- return importPath.startsWith(".") ? importPath : `./${importPath}`;
31410
- }, resolveRelativeModule = async (spec, from) => {
31411
- if (!spec.startsWith(".")) {
31412
- return null;
31023
+ // src/build/generateIslandBindings.ts
31024
+ var exports_generateIslandBindings = {};
31025
+ __export(exports_generateIslandBindings, {
31026
+ generateIslandBindings: () => generateIslandBindings
31027
+ });
31028
+ import {
31029
+ existsSync as existsSync4,
31030
+ mkdirSync as mkdirSync2,
31031
+ readFileSync as readFileSync4,
31032
+ rmSync as rmSync2,
31033
+ writeFileSync as writeFileSync4
31034
+ } from "fs";
31035
+ import { dirname as dirname5, relative as relative3, resolve as resolve8 } from "path";
31036
+ var ensureDir = (filePath) => {
31037
+ mkdirSync2(dirname5(filePath), { recursive: true });
31038
+ }, writeIfChanged2 = (filePath, content) => {
31039
+ ensureDir(filePath);
31040
+ writeFileSync4(filePath, content);
31041
+ }, removeIfExists = (filePath) => {
31042
+ if (existsSync4(filePath)) {
31043
+ rmSync2(filePath, { force: true });
31413
31044
  }
31414
- const basePath = resolve10(dirname5(from), spec);
31415
- const candidates = [
31416
- basePath,
31417
- `${basePath}.ts`,
31418
- `${basePath}.js`,
31419
- `${basePath}.mjs`,
31420
- `${basePath}.cjs`,
31421
- `${basePath}.json`,
31422
- join4(basePath, "index.ts"),
31423
- join4(basePath, "index.js"),
31424
- join4(basePath, "index.mjs"),
31425
- join4(basePath, "index.cjs"),
31426
- join4(basePath, "index.json")
31427
- ];
31428
- for (const candidate of candidates) {
31429
- if (await Bun.file(candidate).exists() === true) {
31430
- return candidate;
31045
+ }, writeHTMLCustomData = (projectRoot) => {
31046
+ const customDataPath = resolve8(projectRoot, ".absolutejs", "html-custom-data.json");
31047
+ const vscodeSettingsPath = resolve8(projectRoot, ".vscode", "settings.json");
31048
+ const customDataRelativePath = relative3(dirname5(vscodeSettingsPath), customDataPath).replace(/\\/g, "/");
31049
+ const customData = {
31050
+ version: 1.1,
31051
+ tags: [
31052
+ {
31053
+ name: "absolute-island",
31054
+ description: "Platform-native AbsoluteJS island element for HTML and HTMX host pages. AbsoluteJS server rendering lowers this element into SSR island markup and the client bootstrap hydrates it according to the `hydrate` mode.",
31055
+ attributes: [
31056
+ {
31057
+ name: "framework",
31058
+ description: "Target framework runtime for this island component.",
31059
+ values: [
31060
+ { name: "react" },
31061
+ { name: "svelte" },
31062
+ { name: "vue" },
31063
+ { name: "angular" }
31064
+ ]
31065
+ },
31066
+ {
31067
+ name: "component",
31068
+ description: "Registry component name to render for this island."
31069
+ },
31070
+ {
31071
+ name: "hydrate",
31072
+ description: "Client hydration timing. `load` hydrates immediately, `idle` waits for idle time, `visible` waits for intersection, and `none` renders static HTML only.",
31073
+ values: [
31074
+ { name: "load" },
31075
+ { name: "idle" },
31076
+ { name: "visible" },
31077
+ { name: "none" }
31078
+ ]
31079
+ },
31080
+ {
31081
+ name: "props",
31082
+ description: "JSON-serialized props payload passed to the target island component. In HTML, prefer single quotes around the attribute so the JSON can keep its double quotes."
31083
+ }
31084
+ ]
31085
+ }
31086
+ ]
31087
+ };
31088
+ writeIfChanged2(customDataPath, `${JSON.stringify(customData, null, 2)}
31089
+ `);
31090
+ let settings = {};
31091
+ if (existsSync4(vscodeSettingsPath)) {
31092
+ try {
31093
+ const parsed = JSON.parse(readFileSync4(vscodeSettingsPath, "utf-8"));
31094
+ if (parsed && typeof parsed === "object") {
31095
+ settings = parsed;
31096
+ }
31097
+ } catch {
31098
+ return;
31431
31099
  }
31432
31100
  }
31433
- return null;
31434
- }, getCachedModulePath = (sourcePath) => {
31435
- const relativeSourcePath = relative3(process.cwd(), sourcePath).replace(/\\/g, "/");
31436
- const normalizedSourcePath = relativeSourcePath.startsWith("..") ? sourcePath.replace(/[:\\/]/g, "_") : relativeSourcePath;
31437
- return join4(serverCacheRoot, `${normalizedSourcePath}.server.js`);
31438
- }, resolveSvelteImport = async (spec, from) => {
31439
- if (spec.startsWith("/")) {
31440
- return spec;
31101
+ const currentCustomData = Array.isArray(settings["html.customData"]) ? settings["html.customData"].filter((value) => typeof value === "string") : [];
31102
+ if (!currentCustomData.includes(customDataRelativePath)) {
31103
+ settings["html.customData"] = [
31104
+ ...currentCustomData,
31105
+ customDataRelativePath
31106
+ ];
31107
+ writeIfChanged2(vscodeSettingsPath, `${JSON.stringify(settings, null, 2)}
31108
+ `);
31441
31109
  }
31442
- if (!spec.startsWith(".")) {
31443
- return null;
31110
+ }, generateIslandBindings = (projectRoot, config) => {
31111
+ const registryPath = config.islands?.registry;
31112
+ if (!registryPath) {
31113
+ return;
31444
31114
  }
31445
- const explicitPath = resolve10(dirname5(from), spec);
31446
- if (extname3(explicitPath) === ".svelte") {
31447
- return explicitPath;
31115
+ writeHTMLCustomData(projectRoot);
31116
+ const resolvedRegistryPath = resolve8(projectRoot, registryPath);
31117
+ removeIfExists(resolve8(dirname5(resolvedRegistryPath), "absolute-islands.d.ts"));
31118
+ if (config.reactDirectory) {
31119
+ const compatTarget = resolve8(config.reactDirectory, "generated", "absolute-react.ts");
31120
+ removeIfExists(resolve8(config.reactDirectory, "generated", "Island.tsx"));
31121
+ removeIfExists(resolve8(config.reactDirectory, "generated", "absolute-react.d.ts"));
31122
+ writeIfChanged2(compatTarget, `export * from "@absolutejs/absolute/react";
31123
+ `);
31448
31124
  }
31449
- const candidate = `${explicitPath}.svelte`;
31450
- if (await Bun.file(candidate).exists() === true) {
31451
- return candidate;
31125
+ if (config.vueDirectory) {
31126
+ const compatTarget = resolve8(config.vueDirectory, "generated", "absolute-vue.ts");
31127
+ removeIfExists(resolve8(config.vueDirectory, "generated", "Island.ts"));
31128
+ removeIfExists(resolve8(config.vueDirectory, "generated", "absolute-vue.d.ts"));
31129
+ writeIfChanged2(compatTarget, `export * from "@absolutejs/absolute/vue";
31130
+ `);
31452
31131
  }
31453
- return null;
31454
- }, writeIfChanged2 = async (path, content) => {
31455
- const targetFile = Bun.file(path);
31456
- const exists = await targetFile.exists();
31457
- if (exists) {
31458
- const currentContent = await targetFile.text();
31459
- if (currentContent === content) {
31460
- return;
31461
- }
31132
+ if (config.svelteDirectory) {
31133
+ const compatTarget = resolve8(config.svelteDirectory, "generated", "absolute-svelte.ts");
31134
+ removeIfExists(resolve8(config.svelteDirectory, "generated", "islands.ts"));
31135
+ removeIfExists(resolve8(config.svelteDirectory, "generated", "absolute-svelte.d.ts"));
31136
+ writeIfChanged2(compatTarget, `export * from "@absolutejs/absolute/svelte";
31137
+ `);
31462
31138
  }
31463
- await Bun.write(path, content);
31464
- }, compileSvelteServerModule = async (sourcePath) => {
31465
- const cachedModulePath = compiledModuleCache.get(sourcePath);
31466
- if (cachedModulePath) {
31467
- return cachedModulePath;
31139
+ if (config.angularDirectory) {
31140
+ const compatTarget = resolve8(config.angularDirectory, "generated", "absolute-angular.ts");
31141
+ removeIfExists(resolve8(config.angularDirectory, "generated", "islands.ts"));
31142
+ removeIfExists(resolve8(config.angularDirectory, "generated", "absolute-angular.d.ts"));
31143
+ writeIfChanged2(compatTarget, `export * from "@absolutejs/absolute/angular";
31144
+ `);
31468
31145
  }
31469
- const source = await Bun.file(sourcePath).text();
31470
- const { compile, preprocess } = await import("svelte/compiler");
31471
- const loweredSource = lowerSvelteIslandSyntax(source, "server");
31472
- const preprocessed = await preprocess(loweredSource.code, {});
31473
- const transpiled = sourcePath.endsWith(".ts") || sourcePath.endsWith(".svelte.ts") ? transpiler.transformSync(preprocessed.code) : preprocessed.code;
31474
- const childImportSpecs = Array.from(transpiled.matchAll(/from\s+['"]([^'"]+)['"]/g)).map((match) => match[1]).filter((value) => value !== undefined);
31475
- const resolvedChildModules = await Promise.all(childImportSpecs.map((spec) => resolveSvelteImport(spec, sourcePath)));
31476
- const resolvedModuleImports = await Promise.all(childImportSpecs.map((spec) => resolveRelativeModule(spec, sourcePath)));
31477
- const childModulePaths = new Map;
31478
- const rewrittenModulePaths = new Map;
31479
- for (let index = 0;index < childImportSpecs.length; index += 1) {
31480
- const spec = childImportSpecs[index];
31481
- const resolvedChild = resolvedChildModules[index];
31482
- if (!spec || !resolvedChild)
31483
- continue;
31484
- const compiledChildPath = await compileSvelteServerModule(resolvedChild);
31485
- childModulePaths.set(spec, compiledChildPath);
31146
+ };
31147
+ var init_generateIslandBindings = () => {};
31148
+
31149
+ // src/utils/getDurationString.ts
31150
+ var getDurationString = (duration) => {
31151
+ let durationString;
31152
+ if (duration < MILLISECONDS_IN_A_SECOND) {
31153
+ durationString = `${duration.toFixed(TIME_PRECISION)}ms`;
31154
+ } else if (duration < MILLISECONDS_IN_A_MINUTE) {
31155
+ durationString = `${(duration / MILLISECONDS_IN_A_SECOND).toFixed(TIME_PRECISION)}s`;
31156
+ } else {
31157
+ durationString = `${(duration / MILLISECONDS_IN_A_MINUTE).toFixed(TIME_PRECISION)}m`;
31486
31158
  }
31487
- for (let index = 0;index < childImportSpecs.length; index += 1) {
31488
- const spec = childImportSpecs[index];
31489
- const resolvedModuleImport = resolvedModuleImports[index];
31490
- if (!spec || !resolvedModuleImport)
31491
- continue;
31492
- if (resolvedChildModules[index])
31493
- continue;
31494
- rewrittenModulePaths.set(spec, ensureRelativeImportPath(getCachedModulePath(sourcePath), resolvedModuleImport));
31159
+ return durationString;
31160
+ };
31161
+ var init_getDurationString = __esm(() => {
31162
+ init_constants();
31163
+ });
31164
+
31165
+ // src/utils/startupBanner.ts
31166
+ var colors, MONTHS, formatTimestamp = () => {
31167
+ const now = new Date;
31168
+ const month = MONTHS[now.getMonth()];
31169
+ const day = now.getDate().toString().padStart(2, "0");
31170
+ let hours = now.getHours();
31171
+ const minutes = now.getMinutes().toString().padStart(2, "0");
31172
+ const seconds = now.getSeconds().toString().padStart(2, "0");
31173
+ const ampm = hours >= HOURS_IN_HALF_DAY ? "PM" : "AM";
31174
+ hours = hours % HOURS_IN_HALF_DAY || HOURS_IN_HALF_DAY;
31175
+ return `${month} ${day} ${hours}:${minutes}:${seconds} ${ampm}`;
31176
+ }, startupBanner = (options) => {
31177
+ const {
31178
+ version,
31179
+ duration,
31180
+ port,
31181
+ host,
31182
+ networkUrl,
31183
+ protocol = "http"
31184
+ } = options;
31185
+ const name = `${colors.cyan}${colors.bold}ABSOLUTEJS${colors.reset}`;
31186
+ const ver = `${colors.dim}v${version}${colors.reset}`;
31187
+ const time = `${colors.dim}ready in${colors.reset} ${colors.bold}${getDurationString(duration)}${colors.reset}`;
31188
+ console.log("");
31189
+ console.log(` ${name} ${ver} ${time}`);
31190
+ console.log("");
31191
+ console.log(` ${colors.green}\u279C${colors.reset} ${colors.bold}Local:${colors.reset} ${protocol}://${host === "0.0.0.0" ? "localhost" : host}:${port}/`);
31192
+ if (networkUrl) {
31193
+ console.log(` ${colors.green}\u279C${colors.reset} ${colors.bold}Network:${colors.reset} ${networkUrl}`);
31495
31194
  }
31496
- let compiledCode = compile(transpiled, {
31497
- css: "injected",
31498
- experimental: {
31499
- async: loweredSource.transformed
31500
- },
31501
- filename: sourcePath,
31502
- generate: "server"
31503
- }).js.code;
31504
- for (const [spec, compiledChildPath] of childModulePaths) {
31505
- compiledCode = compiledCode.replaceAll(spec, ensureRelativeImportPath(getCachedModulePath(sourcePath), compiledChildPath));
31195
+ console.log("");
31196
+ };
31197
+ var init_startupBanner = __esm(() => {
31198
+ init_constants();
31199
+ init_getDurationString();
31200
+ colors = {
31201
+ bold: "\x1B[1m",
31202
+ cyan: "\x1B[36m",
31203
+ dim: "\x1B[2m",
31204
+ green: "\x1B[32m",
31205
+ reset: "\x1B[0m"
31206
+ };
31207
+ MONTHS = [
31208
+ "Jan",
31209
+ "Feb",
31210
+ "Mar",
31211
+ "Apr",
31212
+ "May",
31213
+ "Jun",
31214
+ "Jul",
31215
+ "Aug",
31216
+ "Sep",
31217
+ "Oct",
31218
+ "Nov",
31219
+ "Dec"
31220
+ ];
31221
+ });
31222
+
31223
+ // src/utils/logger.ts
31224
+ var colors2, frameworkColors, formatPath = (filePath) => {
31225
+ const cwd = process.cwd();
31226
+ let relative4 = filePath.startsWith(cwd) ? filePath.slice(cwd.length + 1) : filePath;
31227
+ relative4 = relative4.replace(/\\/g, "/");
31228
+ if (!relative4.startsWith("/")) {
31229
+ relative4 = `/${relative4}`;
31506
31230
  }
31507
- for (const [spec, resolvedModuleImport] of rewrittenModulePaths) {
31508
- compiledCode = compiledCode.replaceAll(spec, resolvedModuleImport);
31231
+ return relative4;
31232
+ }, getFrameworkColor = (framework) => frameworkColors[framework] || colors2.white, log = (action, options) => {
31233
+ const timestamp = `${colors2.dim}${formatTimestamp()}${colors2.reset}`;
31234
+ const tag = `${colors2.cyan}[hmr]${colors2.reset}`;
31235
+ let message = action;
31236
+ if (options?.path) {
31237
+ const pathColor = options.framework ? getFrameworkColor(options.framework) : colors2.white;
31238
+ message += ` ${pathColor}${formatPath(options.path)}${colors2.reset}`;
31509
31239
  }
31510
- const compiledModulePath = getCachedModulePath(sourcePath);
31511
- await mkdir(dirname5(compiledModulePath), { recursive: true });
31512
- await writeIfChanged2(compiledModulePath, compiledCode);
31513
- compiledModuleCache.set(sourcePath, compiledModulePath);
31514
- return compiledModulePath;
31240
+ if (options?.duration !== undefined) {
31241
+ message += ` ${colors2.dim}(${options.duration}ms)${colors2.reset}`;
31242
+ }
31243
+ console.log(`${timestamp} ${tag} ${message}`);
31244
+ }, logCssUpdate = (path, framework, duration) => {
31245
+ log("css update", { duration, framework: framework ?? "css", path });
31246
+ }, logError = (message, error) => {
31247
+ const timestamp = `${colors2.dim}${formatTimestamp()}${colors2.reset}`;
31248
+ const tag = `${colors2.red}[hmr]${colors2.reset}`;
31249
+ const errorMsg = error instanceof Error ? error.message : error;
31250
+ const fullMessage = `${colors2.red}error${colors2.reset} ${message}${errorMsg ? `: ${errorMsg}` : ""}`;
31251
+ console.error(`${timestamp} ${tag} ${fullMessage}`);
31252
+ }, logHmrUpdate = (path, framework, duration) => {
31253
+ log("hmr update", { duration, framework, path });
31254
+ }, logScriptUpdate = (path, framework, duration) => {
31255
+ log("script update", { duration, framework, path });
31256
+ }, logServerReload = () => {
31257
+ log(`${colors2.cyan}server module reloaded${colors2.reset}`);
31258
+ }, logWarn = (message) => {
31259
+ const timestamp = `${colors2.dim}${formatTimestamp()}${colors2.reset}`;
31260
+ const tag = `${colors2.yellow}[hmr]${colors2.reset}`;
31261
+ console.warn(`${timestamp} ${tag} ${colors2.yellow}warning${colors2.reset} ${message}`);
31515
31262
  };
31516
- var init_svelteServerModule = __esm(() => {
31517
- init_lowerIslandSyntax();
31518
- serverCacheRoot = join4(process.cwd(), ".absolutejs", "islands", "svelte");
31519
- compiledModuleCache = new Map;
31520
- transpiler = new Bun.Transpiler({
31521
- loader: "ts",
31522
- target: "browser"
31523
- });
31263
+ var init_logger = __esm(() => {
31264
+ init_startupBanner();
31265
+ colors2 = {
31266
+ blue: "\x1B[34m",
31267
+ bold: "\x1B[1m",
31268
+ cyan: "\x1B[36m",
31269
+ dim: "\x1B[2m",
31270
+ green: "\x1B[32m",
31271
+ magenta: "\x1B[35m",
31272
+ red: "\x1B[31m",
31273
+ reset: "\x1B[0m",
31274
+ white: "\x1B[37m",
31275
+ yellow: "\x1B[33m"
31276
+ };
31277
+ frameworkColors = {
31278
+ angular: colors2.magenta,
31279
+ assets: colors2.dim,
31280
+ css: colors2.cyan,
31281
+ html: colors2.white,
31282
+ htmx: colors2.white,
31283
+ react: colors2.blue,
31284
+ svelte: colors2.yellow,
31285
+ vue: colors2.green
31286
+ };
31524
31287
  });
31525
31288
 
31526
- // src/core/islandMarkupAttributes.ts
31527
- var getIslandMarkerAttributes = (props, islandId) => ({
31528
- "data-component": props.component,
31529
- "data-framework": props.framework,
31530
- "data-hydrate": props.hydrate ?? "load",
31531
- "data-island": "true",
31532
- ...islandId ? { "data-island-id": islandId } : {},
31533
- "data-props": serializeIslandProps(props.props)
31534
- }), escapeHtmlAttribute = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"), serializeIslandAttributes = (attributes) => Object.entries(attributes).map(([key, value]) => `${key}="${escapeHtmlAttribute(value)}"`).join(" ");
31535
- var init_islandMarkupAttributes = __esm(() => {
31536
- init_islands();
31537
- });
31289
+ // src/utils/normalizePath.ts
31290
+ var normalizePath = (path) => path.replace(/\\/g, "/");
31538
31291
 
31539
- // src/core/renderIslandMarkup.ts
31540
- var islandSequence = 0, resolvedServerComponentCache, resolvedServerBuildComponentCache, nextIslandId = () => {
31541
- islandSequence += 1;
31542
- return `island-${islandSequence}`;
31543
- }, isRecord4 = (value) => typeof value === "object" && value !== null, isReactServerIslandComponent = (value) => typeof value === "function", isSvelteServerIslandComponent = (value) => typeof value === "function", isVueServerIslandComponent = (value) => typeof value === "function" || isRecord4(value), isAngularServerIslandComponent = (value) => typeof value === "function", resolveBuildReferencePath = (source, registryPath) => source.startsWith("file://") ? new URL(source).pathname : source.startsWith(".") ? new URL(source, registryPath).pathname : source, loadServerBuildComponent = async (buildReferencePath) => {
31544
- const cachedBuildComponent = resolvedServerBuildComponentCache.get(buildReferencePath);
31545
- if (cachedBuildComponent) {
31546
- return cachedBuildComponent;
31547
- }
31548
- const loadPromise = (async () => {
31549
- const compiledModulePath = await compileSvelteServerModule(buildReferencePath);
31550
- const loadedModule = await import(compiledModulePath);
31551
- return "default" in loadedModule ? loadedModule.default : loadedModule;
31552
- })();
31553
- resolvedServerBuildComponentCache.set(buildReferencePath, loadPromise);
31554
- return loadPromise;
31555
- }, loadServerImportComponent = async (resolvedComponent) => {
31556
- const resolvedModulePath = resolvedComponent.startsWith(".") ? new URL(resolvedComponent, import.meta.url).pathname : resolvedComponent;
31557
- const importTarget = resolvedModulePath.endsWith(".svelte") ? await compileSvelteServerModule(resolvedModulePath) : resolvedModulePath;
31558
- const loadedModule = await import(importTarget);
31559
- return "default" in loadedModule ? loadedModule.default : loadedModule;
31560
- }, resolveServerIslandComponent = async (component) => {
31561
- const cachedResolvedComponent = resolvedServerComponentCache.get(component);
31562
- if (cachedResolvedComponent) {
31563
- return cachedResolvedComponent;
31292
+ // src/build/generateManifest.ts
31293
+ var exports_generateManifest = {};
31294
+ __export(exports_generateManifest, {
31295
+ generateManifest: () => generateManifest
31296
+ });
31297
+ import { extname as extname3 } from "path";
31298
+ var getManifestKey = (folder, pascalName, isClientComponent, isReact, isVue, isSvelte, isAngular) => {
31299
+ if (folder === "indexes")
31300
+ return `${pascalName}Index`;
31301
+ if (isClientComponent)
31302
+ return `${pascalName}Client`;
31303
+ if (folder !== "pages")
31304
+ return pascalName;
31305
+ if (isReact)
31306
+ return `${pascalName}Page`;
31307
+ if (isVue || isSvelte || isAngular)
31308
+ return pascalName;
31309
+ return `${pascalName}Page`;
31310
+ }, getCssKey = (pascalName, segments) => {
31311
+ const isFromVue = segments.some((seg) => seg === "vue");
31312
+ if (isFromVue && segments.includes("css"))
31313
+ return `${pascalName}CompiledCSS`;
31314
+ const isFromReact = segments.some((seg) => seg === "react");
31315
+ const isFromSvelte = segments.some((seg) => seg === "svelte");
31316
+ const isFromAngular = segments.some((seg) => seg === "angular");
31317
+ if (isFromReact || isFromVue || isFromSvelte || isFromAngular)
31318
+ return `${pascalName}BundledCSS`;
31319
+ return `${pascalName}CSS`;
31320
+ }, generateManifest = (outputs, buildPath) => outputs.reduce((manifest, artifact) => {
31321
+ const normalizedArtifactPath = normalizePath(artifact.path);
31322
+ const normalizedBuildPath = normalizePath(buildPath);
31323
+ let relative4 = normalizedArtifactPath.startsWith(normalizedBuildPath) ? normalizedArtifactPath.slice(normalizedBuildPath.length) : normalizedArtifactPath;
31324
+ relative4 = relative4.replace(/^\/+/, "");
31325
+ const segments = relative4.split("/");
31326
+ const fileWithHash = segments.pop();
31327
+ if (!fileWithHash)
31328
+ return manifest;
31329
+ const [baseName] = fileWithHash.split(`.${artifact.hash}.`);
31330
+ if (!baseName)
31331
+ return manifest;
31332
+ const pascalName = toPascal(baseName);
31333
+ const ext = extname3(fileWithHash);
31334
+ const islandIndex = segments.findIndex((seg) => seg === "islands");
31335
+ if (ext === ".css") {
31336
+ const cssKey = getCssKey(pascalName, segments);
31337
+ if (manifest[cssKey] && manifest[cssKey] !== `/${relative4}`)
31338
+ logWarn(`Duplicate manifest key "${cssKey}" \u2014 "${manifest[cssKey]}" will be overwritten by "/${relative4}". Use unique page names across frameworks.`);
31339
+ manifest[cssKey] = `/${relative4}`;
31340
+ return manifest;
31564
31341
  }
31565
- const resolutionPromise = (async () => {
31566
- const buildReference = getIslandBuildReference(component);
31567
- const buildReferencePath = buildReference?.source ? resolveBuildReferencePath(buildReference.source, import.meta.url) : null;
31568
- if (buildReferencePath?.endsWith(".svelte")) {
31569
- return loadServerBuildComponent(buildReferencePath);
31570
- }
31571
- const resolvedComponent = getIslandComponent(component);
31572
- if (typeof resolvedComponent !== "string") {
31573
- return resolvedComponent;
31342
+ if (islandIndex > UNFOUND_INDEX) {
31343
+ const frameworkSegment = segments[islandIndex + 1];
31344
+ if (frameworkSegment === "react" || frameworkSegment === "svelte" || frameworkSegment === "vue" || frameworkSegment === "angular") {
31345
+ const manifestKey2 = getIslandManifestKey(frameworkSegment, pascalName);
31346
+ manifest[manifestKey2] = `/${relative4}`;
31347
+ return manifest;
31574
31348
  }
31575
- return loadServerImportComponent(resolvedComponent);
31576
- })();
31577
- resolvedServerComponentCache.set(component, resolutionPromise);
31578
- return resolutionPromise;
31579
- }, resolveReactServerIslandComponent = async (component) => {
31580
- const resolvedComponent = await resolveServerIslandComponent(component);
31581
- if (!isReactServerIslandComponent(resolvedComponent)) {
31582
- throw new Error("Resolved React island is not a valid React component.");
31583
31349
  }
31584
- return resolvedComponent;
31585
- }, resolveSvelteServerIslandComponent = async (component) => {
31586
- const resolvedComponent = await resolveServerIslandComponent(component);
31587
- if (!isSvelteServerIslandComponent(resolvedComponent)) {
31588
- throw new Error("Resolved Svelte island is not a valid Svelte component.");
31350
+ const idx = segments.findIndex((seg) => seg === "indexes" || seg === "pages" || seg === "client");
31351
+ const folder = idx > UNFOUND_INDEX ? segments[idx] : segments[0];
31352
+ const isReact = segments.some((seg) => seg === "react");
31353
+ const isVue = segments.some((seg) => seg === "vue");
31354
+ const isSvelte = segments.some((seg) => seg === "svelte");
31355
+ const isAngular = segments.some((seg) => seg === "angular");
31356
+ const isClientComponent = segments.includes("client");
31357
+ const manifestKey = getManifestKey(folder, pascalName, isClientComponent, isReact, isVue, isSvelte, isAngular);
31358
+ if (manifest[manifestKey] && manifest[manifestKey] !== `/${relative4}`) {
31359
+ logWarn(`Duplicate manifest key "${manifestKey}" \u2014 "${manifest[manifestKey]}" will be overwritten by "/${relative4}". Use unique page names across frameworks.`);
31589
31360
  }
31590
- return resolvedComponent;
31591
- }, resolveVueServerIslandComponent = async (component) => {
31592
- const resolvedComponent = await resolveServerIslandComponent(component);
31593
- if (!isVueServerIslandComponent(resolvedComponent)) {
31594
- throw new Error("Resolved Vue island is not a valid Vue component.");
31361
+ manifest[manifestKey] = `/${relative4}`;
31362
+ return manifest;
31363
+ }, {});
31364
+ var init_generateManifest = __esm(() => {
31365
+ init_constants();
31366
+ init_logger();
31367
+ });
31368
+
31369
+ // src/build/generateReactIndexes.ts
31370
+ var exports_generateReactIndexes = {};
31371
+ __export(exports_generateReactIndexes, {
31372
+ generateReactIndexFiles: () => generateReactIndexFiles
31373
+ });
31374
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
31375
+ import { readdir, rm, writeFile } from "fs/promises";
31376
+ import { basename as basename2, join as join4, relative as relative4, resolve as resolve9, sep } from "path";
31377
+ var {Glob: Glob2 } = globalThis.Bun;
31378
+ var indexContentCache, resolveDevClientDir = () => {
31379
+ const projectRoot = process.cwd();
31380
+ const fromSource = resolve9(import.meta.dir, "../dev/client");
31381
+ if (existsSync5(fromSource) && fromSource.startsWith(projectRoot)) {
31382
+ return fromSource;
31595
31383
  }
31596
- return resolvedComponent;
31597
- }, resolveAngularServerIslandComponent = async (component) => {
31598
- const resolvedComponent = await resolveServerIslandComponent(component);
31599
- if (!isAngularServerIslandComponent(resolvedComponent)) {
31600
- throw new Error("Resolved Angular island is not a valid Angular component.");
31384
+ const fromNodeModules = resolve9(projectRoot, "node_modules/@absolutejs/absolute/dist/dev/client");
31385
+ if (existsSync5(fromNodeModules))
31386
+ return fromNodeModules;
31387
+ return resolve9(import.meta.dir, "./dev/client");
31388
+ }, devClientDir, errorOverlayPath, hmrClientPath, refreshSetupPath, generateReactIndexFiles = async (reactPagesDirectory, reactIndexesDirectory, isDev2 = false) => {
31389
+ if (!existsSync5(reactIndexesDirectory)) {
31390
+ mkdirSync3(reactIndexesDirectory, { recursive: true });
31601
31391
  }
31602
- return resolvedComponent;
31603
- }, renderIslandResult = async (registry, props) => {
31604
- const islandId = nextIslandId();
31605
- const attributes = getIslandMarkerAttributes(props);
31606
- if (props.framework === "react") {
31607
- const entry = registry.react?.[props.component];
31608
- if (!entry) {
31609
- throw new Error(`Island component "${props.component}" is not registered for framework "react".`);
31610
- }
31611
- const component = await resolveReactServerIslandComponent(entry);
31612
- const html = renderReactIslandToHtml(component, props.props);
31613
- return { attributes, html };
31392
+ const CONVENTION_RE = /^(?:(.+)\.)?(error|loading|not-found)\.[^.]+$/;
31393
+ const pagesGlob = new Glob2("*.*");
31394
+ const files = [];
31395
+ for await (const file2 of pagesGlob.scan({ cwd: reactPagesDirectory })) {
31396
+ if (CONVENTION_RE.test(file2))
31397
+ continue;
31398
+ files.push(file2);
31614
31399
  }
31615
- if (props.framework === "svelte") {
31616
- const entry = registry.svelte?.[props.component];
31617
- if (!entry) {
31618
- throw new Error(`Island component "${props.component}" is not registered for framework "svelte".`);
31619
- }
31620
- const component = await resolveSvelteServerIslandComponent(entry);
31621
- const html = renderSvelteIslandToHtml(component, props.props);
31622
- return { attributes, html };
31400
+ const currentPageNames = new Set(files.map((file2) => basename2(file2).split(".")[0]));
31401
+ const emptyStringArray = [];
31402
+ const existingIndexes = await readdir(reactIndexesDirectory).catch(() => emptyStringArray);
31403
+ const staleIndexes = existingIndexes.filter((indexFile) => {
31404
+ const indexName = indexFile.replace(/\.tsx$/, "");
31405
+ return indexName !== "_refresh" && !currentPageNames.has(indexName);
31406
+ });
31407
+ if (staleIndexes.length > 0) {
31408
+ await Promise.all(staleIndexes.map((indexFile) => {
31409
+ indexContentCache.delete(join4(reactIndexesDirectory, indexFile));
31410
+ return rm(join4(reactIndexesDirectory, indexFile), {
31411
+ force: true
31412
+ });
31413
+ }));
31623
31414
  }
31624
- if (props.framework === "vue") {
31625
- const entry = registry.vue?.[props.component];
31626
- if (!entry) {
31627
- throw new Error(`Island component "${props.component}" is not registered for framework "vue".`);
31415
+ const pagesRelPath = relative4(resolve9(reactIndexesDirectory), resolve9(reactPagesDirectory)).split(sep).join("/");
31416
+ const promises = files.map(async (file2) => {
31417
+ const fileName = basename2(file2);
31418
+ const [componentName] = fileName.split(".");
31419
+ const hmrPreamble = isDev2 ? [
31420
+ `window.__HMR_FRAMEWORK__ = "react";`,
31421
+ `window.__REACT_COMPONENT_KEY__ = "${componentName}Index";`,
31422
+ `import '${refreshSetupPath}';`,
31423
+ `import '${hmrClientPath}';`,
31424
+ `import { showErrorOverlay, hideErrorOverlay } from '${errorOverlayPath}';
31425
+ `
31426
+ ] : [];
31427
+ const reactImports = isDev2 ? [
31428
+ `import { hydrateRoot, createRoot } from 'react-dom/client';`,
31429
+ `import { createElement, Component } from 'react';`
31430
+ ] : [
31431
+ `import { hydrateRoot, createRoot } from 'react-dom/client';`,
31432
+ `import { createElement } from 'react';`
31433
+ ];
31434
+ const errorBoundaryDef = isDev2 ? [
31435
+ `
31436
+ // Dev-only Error Boundary to catch React render errors`,
31437
+ `class ErrorBoundary extends Component {`,
31438
+ ` constructor(props) {`,
31439
+ ` super(props);`,
31440
+ ` this.state = { hasError: false };`,
31441
+ ` window.__ERROR_BOUNDARY__ = this;`,
31442
+ ` }`,
31443
+ ` static getDerivedStateFromError() {`,
31444
+ ` return { hasError: true };`,
31445
+ ` }`,
31446
+ ` componentDidCatch(error) {`,
31447
+ ` showErrorOverlay({`,
31448
+ ` framework: 'react',`,
31449
+ ` kind: 'runtime',`,
31450
+ ` message: error && error.stack ? error.stack : String(error)`,
31451
+ ` });`,
31452
+ ` }`,
31453
+ ` componentDidUpdate(prevProps, prevState) {`,
31454
+ ` if (prevState.hasError && !this.state.hasError) {`,
31455
+ ` hideErrorOverlay();`,
31456
+ ` }`,
31457
+ ` }`,
31458
+ ` reset() {`,
31459
+ ` this.setState({ hasError: false });`,
31460
+ ` }`,
31461
+ ` render() {`,
31462
+ ` if (this.state.hasError) return null;`,
31463
+ ``,
31464
+ ` return this.props.children;`,
31465
+ ` }`,
31466
+ `}
31467
+ `
31468
+ ] : [];
31469
+ const content = [
31470
+ ...hmrPreamble,
31471
+ ...reactImports,
31472
+ `import type { ComponentType } from 'react'`,
31473
+ `import { ${componentName} } from '${pagesRelPath}/${componentName}';
31474
+ `,
31475
+ `type PropsOf<C> = C extends ComponentType<infer P> ? P : never;
31476
+ `,
31477
+ `declare global {`,
31478
+ ` interface Window {`,
31479
+ ` __INITIAL_PROPS__?: PropsOf<typeof ${componentName}>`,
31480
+ ` __REACT_ROOT__?: ReturnType<typeof hydrateRoot | typeof createRoot>`,
31481
+ ` __HMR_CLIENT_ONLY_MODE__?: boolean`,
31482
+ ` }`,
31483
+ `}
31484
+ `,
31485
+ ...errorBoundaryDef,
31486
+ `// Hydration with error handling and fallback`,
31487
+ `const isDev = ${isDev2};`,
31488
+ `const componentPath = '${pagesRelPath}/${componentName}';
31489
+ `,
31490
+ `function isHydrationError(error) {`,
31491
+ ` if (!error) return false;`,
31492
+ ` const errorMessage = error instanceof Error ? error.message : String(error);`,
31493
+ ` const errorString = String(error);`,
31494
+ ` const fullMessage = errorMessage + ' ' + errorString;`,
31495
+ ` const hydrationKeywords = ['hydration', 'Hydration', 'mismatch', 'Mismatch', 'did not match', 'server rendered HTML', 'server HTML', 'client HTML', 'Hydration failed'];`,
31496
+ ` const isHydration = hydrationKeywords.some(keyword => fullMessage.includes(keyword));`,
31497
+ ` `,
31498
+ ` // Ignore whitespace-only mismatches in <head> - these are harmless formatting differences`,
31499
+ ` // The error often shows: + <link...> vs - {"\\n "} which is just formatting`,
31500
+ ` if (isHydration) {`,
31501
+ ` // Check if this is a head/link/stylesheet related mismatch`,
31502
+ ` const isHeadRelated = fullMessage.includes('<head') || fullMessage.includes('</head>') || fullMessage.includes('head>') || fullMessage.includes('<link') || fullMessage.includes('link>') || fullMessage.includes('stylesheet') || fullMessage.includes('fonts.googleapis') || fullMessage.includes('rel="stylesheet"');`,
31503
+ ` `,
31504
+ ` // Check if the mismatch involves only whitespace/newlines`,
31505
+ ` // Pattern: looks for {"\\n"} or {"\\n "} or similar whitespace-only content`,
31506
+ ` // Also check for patterns like: - {"\\n "} or + <link...>`,
31507
+ ` const hasWhitespacePattern = /\\{\\s*["']\\\\n[^"']*["']\\s*\\}/.test(fullMessage) || /\\{\\s*["'][\\\\n\\\\r\\\\s]+["']\\s*\\}/.test(fullMessage) || /-\\s*\\{\\s*["'][\\\\n\\\\r\\\\s]+["']\\s*\\}/.test(fullMessage);`,
31508
+ ` const isWhitespaceOnly = /^[\\s\\n\\r]*$/.test(errorString) || /^[\\s\\n\\r]*$/.test(errorMessage);`,
31509
+ ` const hasNewlinePattern = fullMessage.includes('\\\\n') || fullMessage.includes('\\\\r') || fullMessage.includes('\\n') || fullMessage.includes('\\r');`,
31510
+ ` `,
31511
+ ` // If it's head-related and involves whitespace/newlines, ignore it`,
31512
+ ` if (isHeadRelated && (hasWhitespacePattern || isWhitespaceOnly || hasNewlinePattern)) {`,
31513
+ ` return false; // Don't treat whitespace-only head mismatches as errors`,
31514
+ ` }`,
31515
+ ` }`,
31516
+ ` return isHydration;`,
31517
+ `}
31518
+ `,
31519
+ `function logHydrationError(error, componentName) {`,
31520
+ ` if (!isDev) return;`,
31521
+ ` if (window.__HMR_WS__ && window.__HMR_WS__.readyState === WebSocket.OPEN) {`,
31522
+ ` try {`,
31523
+ ` window.__HMR_WS__.send(JSON.stringify({`,
31524
+ ` type: 'hydration-error',`,
31525
+ ` data: {`,
31526
+ ` componentName: '${componentName}',`,
31527
+ ` componentPath: componentPath,`,
31528
+ ` error: error instanceof Error ? error.message : String(error),`,
31529
+ ` timestamp: Date.now()`,
31530
+ ` }`,
31531
+ ` }));`,
31532
+ ` } catch (err) {}`,
31533
+ ` }`,
31534
+ `}
31535
+ `,
31536
+ `// Track if we've already switched to client-only mode`,
31537
+ `let hasSwitchedToClientOnly = false;`,
31538
+ `let hydrationErrorDetected = false;
31539
+ `,
31540
+ `function handleHydrationFallback(error) {`,
31541
+ ` if (hasSwitchedToClientOnly) return; // Already handled`,
31542
+ ` hasSwitchedToClientOnly = true;`,
31543
+ ` hydrationErrorDetected = true;
31544
+ `,
31545
+ ` logHydrationError(error, '${componentName}');
31546
+ `,
31547
+ ` // Fallback: client-only render (no hydration)`,
31548
+ ` try {`,
31549
+ ` // Unmount existing root if it exists`,
31550
+ ` if (window.__REACT_ROOT__ && typeof window.__REACT_ROOT__.unmount === 'function') {`,
31551
+ ` try {`,
31552
+ ` window.__REACT_ROOT__.unmount();`,
31553
+ ` } catch (e) {`,
31554
+ ` // Ignore unmount errors`,
31555
+ ` }`,
31556
+ ` }
31557
+ `,
31558
+ ` // Render into the same root container when falling back to client-only`,
31559
+ ` const root = createRoot(container);`,
31560
+ ` root.render(${isDev2 ? `createElement(ErrorBoundary, null, createElement(${componentName}, mergedProps))` : `createElement(${componentName}, mergedProps)`});`,
31561
+ ` window.__REACT_ROOT__ = root;`,
31562
+ ` window.__HMR_CLIENT_ONLY_MODE__ = true;`,
31563
+ ` } catch (fallbackError) {`,
31564
+ ` window.location.reload();`,
31565
+ ` }`,
31566
+ `}
31567
+ `,
31568
+ `// HMR State Preservation: Check for preserved state and merge with initial props`,
31569
+ `// This allows state to be preserved across HMR updates without modifying component files`,
31570
+ `let preservedState = (typeof window !== 'undefined' && window.__HMR_PRESERVED_STATE__) ? window.__HMR_PRESERVED_STATE__ : {};
31571
+ `,
31572
+ `// Also check sessionStorage for state that survived a page reload (for React HMR)`,
31573
+ `if (typeof window !== 'undefined' && typeof sessionStorage !== 'undefined') {`,
31574
+ ` const hmrStateJson = sessionStorage.getItem('__REACT_HMR_STATE__');`,
31575
+ ` if (hmrStateJson) {`,
31576
+ ` try {`,
31577
+ ` const hmrState = JSON.parse(hmrStateJson);`,
31578
+ ` preservedState = { ...preservedState, ...hmrState };`,
31579
+ ` sessionStorage.removeItem('__REACT_HMR_STATE__');`,
31580
+ ` } catch (e) {}`,
31581
+ ` }`,
31582
+ `}
31583
+ `,
31584
+ `const mergedProps = { ...(window.__INITIAL_PROPS__ || {}), ...preservedState };`,
31585
+ `// Clear preserved state after using it (so it doesn't persist across multiple updates)`,
31586
+ `if (typeof window !== 'undefined') {`,
31587
+ ` window.__HMR_PRESERVED_STATE__ = undefined;`,
31588
+ `}
31589
+ `,
31590
+ `// Attempt hydration with error handling`,
31591
+ `// Use document (not document.body) when the page renders <html><head><body>`,
31592
+ `// to avoid "In HTML, <html> cannot be a child of <body>" hydration error`,
31593
+ `const container = typeof document !== 'undefined' ? document : null;`,
31594
+ `if (!container) {`,
31595
+ ` throw new Error('React root container not found: document is null');`,
31596
+ `}
31597
+ `,
31598
+ `// Guard: only hydrate on first load. During HMR re-imports, skip hydration`,
31599
+ `// so React Fast Refresh can swap components in-place and preserve state.`,
31600
+ `if (!window.__REACT_ROOT__) {`,
31601
+ ` let root;`,
31602
+ ` // After HMR, SSR is skipped to avoid stale content flash \u2014 render client-only`,
31603
+ ` if (window.__SSR_DIRTY__) {`,
31604
+ ` root = createRoot(container);`,
31605
+ ` root.render(${isDev2 ? `createElement(ErrorBoundary, null, createElement(${componentName}, mergedProps))` : `createElement(${componentName}, mergedProps)`});`,
31606
+ ` window.__REACT_ROOT__ = root;`,
31607
+ ` } else {`,
31608
+ ` try {`,
31609
+ ` // Use onRecoverableError to catch hydration errors (React 19)`,
31610
+ ` root = hydrateRoot(`,
31611
+ ` container,`,
31612
+ ` ${isDev2 ? `createElement(ErrorBoundary, null, createElement(${componentName}, mergedProps))` : `createElement(${componentName}, mergedProps)`},`,
31613
+ ` {`,
31614
+ ` onRecoverableError: (error) => {`,
31615
+ ` // Check if this is a hydration error (isHydrationError filters out whitespace-only head mismatches)`,
31616
+ ` if (isDev && isHydrationError(error)) {`,
31617
+ ` // Real hydration error - handle it`,
31618
+ ` handleHydrationFallback(error);`,
31619
+ ` } else {`,
31620
+ ` // Not a hydration error, or it's a whitespace-only mismatch that was filtered out`,
31621
+ ` // Check if it's a whitespace-only head mismatch using the same logic as isHydrationError`,
31622
+ ` const errorMessage = error instanceof Error ? error.message : String(error);`,
31623
+ ` const errorString = String(error);`,
31624
+ ` const fullMessage = errorMessage + ' ' + errorString;`,
31625
+ ` const hydrationKeywords = ['hydration', 'Hydration', 'mismatch', 'Mismatch', 'did not match', 'server rendered HTML', 'server HTML', 'client HTML', 'Hydration failed'];`,
31626
+ ` const isHydration = hydrationKeywords.some(keyword => fullMessage.includes(keyword));`,
31627
+ ` if (isHydration) {`,
31628
+ ` // Check if this is a head/link/stylesheet related mismatch`,
31629
+ ` const isHeadRelated = fullMessage.includes('<head') || fullMessage.includes('</head>') || fullMessage.includes('head>') || fullMessage.includes('<link') || fullMessage.includes('link>') || fullMessage.includes('stylesheet') || fullMessage.includes('fonts.googleapis') || fullMessage.includes('rel="stylesheet"');`,
31630
+ ` // Check if the mismatch involves only whitespace/newlines`,
31631
+ ` const hasWhitespacePattern = /\\{\\s*["']\\\\n[^"']*["']\\s*\\}/.test(fullMessage) || /\\{\\s*["'][\\\\n\\\\r\\\\s]+["']\\s*\\}/.test(fullMessage) || /-\\s*\\{\\s*["'][\\\\n\\\\r\\\\s]+["']\\s*\\}/.test(fullMessage);`,
31632
+ ` const isWhitespaceOnly = /^[\\s\\n\\r]*$/.test(errorString) || /^[\\s\\n\\r]*$/.test(errorMessage);`,
31633
+ ` const hasNewlinePattern = fullMessage.includes('\\\\n') || fullMessage.includes('\\\\r') || fullMessage.includes('\\n') || fullMessage.includes('\\r');`,
31634
+ ` // If it's head-related and involves whitespace/newlines, silently ignore it`,
31635
+ ` if (isHeadRelated && (hasWhitespacePattern || isWhitespaceOnly || hasNewlinePattern)) {`,
31636
+ ` // Already logged by isHydrationError, just return silently`,
31637
+ ` return;`,
31638
+ ` }`,
31639
+ ` }`,
31640
+ ` // Log other recoverable errors`,
31641
+ ` console.error('React recoverable error:', error);`,
31642
+ ` }`,
31643
+ ` }`,
31644
+ ` }`,
31645
+ ` );`,
31646
+ ` window.__REACT_ROOT__ = root;`,
31647
+ ` } catch (error) {`,
31648
+ ` // Catch synchronous errors (shouldn't happen with hydrateRoot, but safety net)`,
31649
+ ` if (isDev && isHydrationError(error)) {`,
31650
+ ` handleHydrationFallback(error);`,
31651
+ ` } else {`,
31652
+ ` throw error;`,
31653
+ ` }`,
31654
+ ` }`,
31655
+ ` } // end else (normal hydration path)
31656
+ `,
31657
+ ` // Also listen for hydration errors via console.error (React logs them there)`,
31658
+ ` if (isDev) {`,
31659
+ ` const originalError = console.error;`,
31660
+ ` console.error = function(...args) {`,
31661
+ ` const errorMessage = args.map(arg => {`,
31662
+ ` if (arg instanceof Error) return arg.message;`,
31663
+ ` return String(arg);`,
31664
+ ` }).join(' ');`,
31665
+ ` `,
31666
+ ` // Check if this is a hydration error`,
31667
+ ` if (isHydrationError({ message: errorMessage }) && !hydrationErrorDetected) {`,
31668
+ ` hydrationErrorDetected = true;`,
31669
+ ` // Create a synthetic error for fallback`,
31670
+ ` const syntheticError = new Error(errorMessage);`,
31671
+ ` // Use setTimeout to ensure this happens after React's error handling`,
31672
+ ` setTimeout(() => {`,
31673
+ ` handleHydrationFallback(syntheticError);`,
31674
+ ` }, 0);`,
31675
+ ` }`,
31676
+ ` `,
31677
+ ` // Call original console.error`,
31678
+ ` originalError.apply(console, args);`,
31679
+ ` };`,
31680
+ ` }`,
31681
+ `}`,
31682
+ ...isDev2 ? [
31683
+ `
31684
+ // Pre-warm: import the page module from the module server`,
31685
+ `// immediately so the browser caches all /@src/ URLs.`,
31686
+ `import('/@src/${relative4(process.cwd(), resolve9(reactPagesDirectory, `${componentName}.tsx`)).replace(/\\/g, "/")}').catch(() => {});`
31687
+ ] : []
31688
+ ].join(`
31689
+ `);
31690
+ const indexPath = join4(reactIndexesDirectory, `${componentName}.tsx`);
31691
+ const hasher = new Bun.CryptoHasher("md5");
31692
+ hasher.update(content);
31693
+ const contentHash = hasher.digest("hex");
31694
+ if (indexContentCache.get(indexPath) === contentHash && existsSync5(indexPath)) {
31695
+ return;
31628
31696
  }
31629
- const component = await resolveVueServerIslandComponent(entry);
31630
- const html = await renderVueIslandToHtml(component, props.props);
31631
- return { attributes, html };
31697
+ indexContentCache.set(indexPath, contentHash);
31698
+ await writeFile(indexPath, content);
31699
+ });
31700
+ await Promise.all(promises);
31701
+ if (!isDev2) {
31702
+ return;
31632
31703
  }
31633
- if (props.framework === "angular") {
31634
- const entry = registry.angular?.[props.component];
31635
- if (!entry) {
31636
- throw new Error(`Island component "${props.component}" is not registered for framework "angular".`);
31637
- }
31638
- const component = await resolveAngularServerIslandComponent(entry);
31639
- const html = await renderAngularIslandToHtml(component, props.props, islandId);
31640
- return {
31641
- attributes: {
31642
- ...getIslandMarkerAttributes(props, islandId)
31643
- },
31644
- html
31645
- };
31704
+ const refreshPath = join4(reactIndexesDirectory, "_refresh.tsx");
31705
+ if (!existsSync5(refreshPath)) {
31706
+ await writeFile(refreshPath, `import '${refreshSetupPath}';
31707
+ import 'react';
31708
+ import 'react-dom/client';
31709
+ `);
31646
31710
  }
31647
- throw new Error(`Framework "${props.framework}" is not implemented in this prototype.`);
31648
- }, renderIslandMarkup = async (registry, props) => {
31649
- const result = await renderIslandResult(registry, props);
31650
- return `<div ${serializeIslandAttributes(result.attributes)}>${result.html}</div>`;
31651
31711
  };
31652
- var init_renderIslandMarkup = __esm(() => {
31653
- init_islandSsr();
31654
- init_svelteServerModule();
31655
- init_islandMarkupAttributes();
31656
- init_islands();
31657
- resolvedServerComponentCache = new Map;
31658
- resolvedServerBuildComponentCache = new Map;
31712
+ var init_generateReactIndexes = __esm(() => {
31713
+ indexContentCache = new Map;
31714
+ devClientDir = resolveDevClientDir();
31715
+ errorOverlayPath = join4(devClientDir, "errorOverlay.ts").replace(/\\/g, "/");
31716
+ hmrClientPath = join4(devClientDir, "hmrClient.ts").replace(/\\/g, "/");
31717
+ refreshSetupPath = join4(devClientDir, "reactRefreshSetup.ts").replace(/\\/g, "/");
31659
31718
  });
31660
31719
 
31661
- // src/build/staticIslandPages.ts
31662
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "fs";
31663
- var ISLAND_TAG_RE_SOURCE = "<island\\b([^>]*?)(?:\\/\\>|>(?:[\\s\\S]*?)<\\/island>)", ATTRIBUTE_RE_SOURCE = `([A-Za-z_:][-A-Za-z0-9_:.]*)\\s*=\\s*(?:"([^"]*)"|'([^']*)')`, islandFrameworks2, islandHydrationModes2, isRecord5 = (value) => typeof value === "object" && value !== null, isIslandFramework2 = (value) => islandFrameworks2.some((framework) => framework === value), isIslandHydrationMode = (value) => islandHydrationModes2.some((mode) => mode === value), parseIslandAttributes = (attributeString) => {
31664
- const attributeRe = new RegExp(ATTRIBUTE_RE_SOURCE, "g");
31665
- const attributes = new Map;
31666
- let match = attributeRe.exec(attributeString);
31667
- while (match) {
31668
- const key = match[1];
31669
- const doubleQuotedValue = match[2];
31670
- const singleQuotedValue = match[3];
31671
- if (!key) {
31672
- match = attributeRe.exec(attributeString);
31673
- continue;
31674
- }
31675
- const value = doubleQuotedValue ?? singleQuotedValue ?? "";
31676
- attributes.set(key, value);
31677
- match = attributeRe.exec(attributeString);
31678
- }
31679
- return attributes;
31680
- }, parseIslandTag = (attributeString) => {
31681
- const attributes = parseIslandAttributes(attributeString);
31682
- const framework = attributes.get("framework");
31683
- const component = attributes.get("component");
31684
- const hydrate = attributes.get("hydrate") ?? "load";
31685
- const propsSource = attributes.get("props") ?? "{}";
31686
- if (!framework || !component) {
31720
+ // src/build/islandBindingCompat.ts
31721
+ import { resolve as resolve10 } from "path";
31722
+ var packageToFramework, compatFileNames, normalize = (value) => value.replace(/\\/g, "/"), isFrameworkPackage = (value) => (value in packageToFramework), resolveIslandCompatModule = (specifier, importer, frameworkDirs) => {
31723
+ if (!isFrameworkPackage(specifier)) {
31687
31724
  return null;
31688
31725
  }
31689
- if (!isIslandFramework2(framework)) {
31690
- throw new Error(`Unsupported static island framework "${framework}".`);
31726
+ const framework = packageToFramework[specifier];
31727
+ const frameworkDir = frameworkDirs[framework];
31728
+ if (!frameworkDir) {
31729
+ return null;
31691
31730
  }
31692
- if (!isIslandHydrationMode(hydrate)) {
31693
- throw new Error(`Unsupported static island hydrate mode "${hydrate}".`);
31731
+ const normalizedImporter = normalize(importer);
31732
+ const normalizedFrameworkDir = normalize(resolve10(frameworkDir));
31733
+ if (!normalizedImporter.startsWith(normalizedFrameworkDir)) {
31734
+ return null;
31694
31735
  }
31695
- let parsedProps;
31696
- try {
31697
- const candidate = JSON.parse(propsSource);
31698
- parsedProps = isRecord5(candidate) ? candidate : {};
31699
- } catch (error) {
31700
- throw new Error(`Failed to parse static island props JSON for ${framework}:${component}: ${error instanceof Error ? error.message : String(error)}`);
31736
+ if (normalizedImporter.includes("/generated/absolute-") || normalizedImporter.includes("/generated/Island.") || normalizedImporter.includes("/generated/islands.")) {
31737
+ return null;
31701
31738
  }
31702
- return {
31703
- component,
31704
- framework,
31705
- hydrate,
31706
- props: parsedProps
31739
+ return resolve10(frameworkDir, "generated", compatFileNames[framework]);
31740
+ };
31741
+ var init_islandBindingCompat = __esm(() => {
31742
+ packageToFramework = {
31743
+ "@absolutejs/absolute/angular": "angular",
31744
+ "@absolutejs/absolute/react": "react",
31745
+ "@absolutejs/absolute/svelte": "svelte",
31746
+ "@absolutejs/absolute/vue": "vue"
31707
31747
  };
31708
- }, transformStaticPage = async (pagePath, registry) => {
31709
- const originalHtml = readFileSync3(pagePath, "utf-8");
31710
- const islandTagRe = new RegExp(ISLAND_TAG_RE_SOURCE, "gi");
31711
- if (!islandTagRe.test(originalHtml)) {
31712
- return;
31713
- }
31714
- islandTagRe.lastIndex = 0;
31715
- let transformedHtml = "";
31716
- let lastIndex = 0;
31717
- let match = islandTagRe.exec(originalHtml);
31718
- while (match) {
31719
- const fullMatch = match[0];
31720
- const attributeString = match[1] ?? "";
31721
- const matchIndex = match.index;
31722
- transformedHtml += originalHtml.slice(lastIndex, matchIndex);
31723
- const props = parseIslandTag(attributeString);
31724
- transformedHtml += props ? await renderIslandMarkup(registry, props) : fullMatch;
31725
- lastIndex = matchIndex + fullMatch.length;
31726
- match = islandTagRe.exec(originalHtml);
31748
+ compatFileNames = {
31749
+ angular: "absolute-angular.ts",
31750
+ react: "absolute-react.ts",
31751
+ svelte: "absolute-svelte.ts",
31752
+ vue: "absolute-vue.ts"
31753
+ };
31754
+ });
31755
+
31756
+ // src/build/islandBindingPlugin.ts
31757
+ var exports_islandBindingPlugin = {};
31758
+ __export(exports_islandBindingPlugin, {
31759
+ createIslandBindingPlugin: () => createIslandBindingPlugin
31760
+ });
31761
+ var createIslandBindingPlugin = (frameworkDirs) => ({
31762
+ name: "absolute-island-binding-plugin",
31763
+ setup(build2) {
31764
+ build2.onResolve({
31765
+ filter: /^@absolutejs\/absolute\/(react|vue|svelte|angular)$/
31766
+ }, (args) => {
31767
+ const redirected = resolveIslandCompatModule(args.path, args.importer, frameworkDirs);
31768
+ if (!redirected) {
31769
+ return;
31770
+ }
31771
+ return {
31772
+ path: redirected
31773
+ };
31774
+ });
31727
31775
  }
31728
- transformedHtml += originalHtml.slice(lastIndex);
31729
- if (transformedHtml !== originalHtml) {
31730
- writeFileSync4(pagePath, transformedHtml);
31776
+ });
31777
+ var init_islandBindingPlugin = __esm(() => {
31778
+ init_islandBindingCompat();
31779
+ });
31780
+
31781
+ // src/build/wrapHTMLScript.ts
31782
+ var wrapHTMLScriptWithHMR = (code, scriptId) => {
31783
+ const escapedId = JSON.stringify(scriptId);
31784
+ return `${code}
31785
+
31786
+ // HMR acceptance - allows this script to be hot-reloaded
31787
+ if (typeof import.meta !== "undefined" && import.meta.hot) {
31788
+ import.meta.hot.accept();
31789
+ console.log('[HMR] Script ready:', ${escapedId});
31790
+ }
31791
+ `;
31792
+ };
31793
+
31794
+ // src/build/htmlScriptHMRPlugin.ts
31795
+ var scriptLoaders, toLoader = (ext) => {
31796
+ for (const loader of scriptLoaders) {
31797
+ if (loader === ext)
31798
+ return loader;
31731
31799
  }
31732
- }, transformStaticPagesWithIslands = async (registryPath, pagePaths) => {
31733
- if (!registryPath || pagePaths.length === 0) {
31734
- return;
31800
+ return "ts";
31801
+ }, createHTMLScriptHMRPlugin = (htmlDir, htmxDir) => ({
31802
+ name: "html-script-hmr",
31803
+ setup(build2) {
31804
+ build2.onLoad({ filter: /\.(ts|js|tsx|jsx)$/ }, async (args) => {
31805
+ const normalizedPath = args.path.replace(/\\/g, "/");
31806
+ const isHtmlScript = htmlDir && normalizedPath.includes(htmlDir.replace(/\\/g, "/")) && normalizedPath.includes("/scripts/");
31807
+ const isHtmxScript = htmxDir && normalizedPath.includes(htmxDir.replace(/\\/g, "/")) && normalizedPath.includes("/scripts/");
31808
+ if (!isHtmlScript && !isHtmxScript) {
31809
+ return;
31810
+ }
31811
+ const text2 = await Bun.file(args.path).text();
31812
+ const wrapped = wrapHTMLScriptWithHMR(text2, normalizedPath);
31813
+ const ext = args.path.split(".").pop() ?? "ts";
31814
+ const loader = toLoader(ext);
31815
+ return {
31816
+ contents: wrapped,
31817
+ loader
31818
+ };
31819
+ });
31735
31820
  }
31736
- const { registry } = await loadIslandRegistryBuildInfo(registryPath);
31737
- await Promise.all(pagePaths.map((pagePath) => transformStaticPage(pagePath, registry)));
31738
- };
31739
- var init_staticIslandPages = __esm(() => {
31740
- init_renderIslandMarkup();
31741
- init_islandEntries();
31742
- islandFrameworks2 = [
31743
- "react",
31744
- "svelte",
31745
- "vue",
31746
- "angular"
31747
- ];
31748
- islandHydrationModes2 = ["load", "idle", "visible", "none"];
31821
+ });
31822
+ var init_htmlScriptHMRPlugin = __esm(() => {
31823
+ scriptLoaders = new Set(["ts", "js", "tsx", "jsx"]);
31749
31824
  });
31750
31825
 
31751
31826
  // src/build/outputLogs.ts
@@ -31834,7 +31909,7 @@ var scanCssEntryPoints = async (dir, ignore) => {
31834
31909
  var init_scanCssEntryPoints = () => {};
31835
31910
 
31836
31911
  // src/utils/imageProcessing.ts
31837
- import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync5 } from "fs";
31912
+ import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
31838
31913
  import { join as join5, resolve as resolve11 } from "path";
31839
31914
  var DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, DEFAULT_QUALITY = 75, OPTIMIZATION_ENDPOINT = "/_absolute/image", BLUR_DEVIATION = 20, sharpModule = undefined, sharpLoaded = false, sharpWarned = false, snapToSize = (target, sizes) => {
31840
31915
  for (const size of sizes) {
@@ -31950,8 +32025,8 @@ var DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, DEFAULT_QUALITY = 75, OPTIMIZATIO
31950
32025
  if (!existsSync8(metaPath) || !existsSync8(dataPath))
31951
32026
  return null;
31952
32027
  try {
31953
- const meta = JSON.parse(readFileSync4(metaPath, "utf-8"));
31954
- const buffer = readFileSync4(dataPath);
32028
+ const meta = JSON.parse(readFileSync5(metaPath, "utf-8"));
32029
+ const buffer = readFileSync5(dataPath);
31955
32030
  return { buffer, meta };
31956
32031
  } catch {
31957
32032
  return null;
@@ -32066,14 +32141,14 @@ var init_optimizeHtmlImages = __esm(() => {
32066
32141
  });
32067
32142
 
32068
32143
  // src/cli/scripts/telemetry.ts
32069
- import { existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync6 } from "fs";
32144
+ import { existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "fs";
32070
32145
  import { homedir } from "os";
32071
32146
  import { join as join6 } from "path";
32072
32147
  var configDir, configPath, getTelemetryConfig = () => {
32073
32148
  try {
32074
32149
  if (!existsSync9(configPath))
32075
32150
  return null;
32076
- const raw = readFileSync5(configPath, "utf-8");
32151
+ const raw = readFileSync6(configPath, "utf-8");
32077
32152
  const config = JSON.parse(raw);
32078
32153
  return config;
32079
32154
  } catch {
@@ -32086,14 +32161,14 @@ var init_telemetry = __esm(() => {
32086
32161
  });
32087
32162
 
32088
32163
  // src/cli/telemetryEvent.ts
32089
- import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
32164
+ import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
32090
32165
  import { arch, platform } from "os";
32091
32166
  import { dirname as dirname6, join as join7, parse as parse2 } from "path";
32092
32167
  var checkCandidate = (candidate) => {
32093
32168
  if (!existsSync10(candidate)) {
32094
32169
  return null;
32095
32170
  }
32096
- const pkg = JSON.parse(readFileSync6(candidate, "utf-8"));
32171
+ const pkg = JSON.parse(readFileSync7(candidate, "utf-8"));
32097
32172
  if (pkg.name === "@absolutejs/absolute") {
32098
32173
  const ver = pkg.version;
32099
32174
  return ver;
@@ -32397,8 +32472,8 @@ var devVendorPaths = null, getDevVendorPaths = () => devVendorPaths, setDevVendo
32397
32472
  };
32398
32473
 
32399
32474
  // src/build/angularLinkerPlugin.ts
32400
- import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "fs";
32401
- import { dirname as dirname7, join as join8, relative as relative4, resolve as resolve14 } from "path";
32475
+ import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
32476
+ import { dirname as dirname7, join as join8, relative as relative5, resolve as resolve14 } from "path";
32402
32477
  import { createHash } from "crypto";
32403
32478
  var CACHE_DIR, angularLinkerPlugin;
32404
32479
  var init_angularLinkerPlugin = __esm(() => {
@@ -32424,7 +32499,7 @@ var init_angularLinkerPlugin = __esm(() => {
32424
32499
  const cachePath = join8(CACHE_DIR, `${hash}.js`);
32425
32500
  if (existsSync12(cachePath)) {
32426
32501
  return {
32427
- contents: readFileSync7(cachePath, "utf-8"),
32502
+ contents: readFileSync8(cachePath, "utf-8"),
32428
32503
  loader: "js"
32429
32504
  };
32430
32505
  }
@@ -32440,8 +32515,8 @@ var init_angularLinkerPlugin = __esm(() => {
32440
32515
  fileSystem: {
32441
32516
  dirname: dirname7,
32442
32517
  exists: existsSync12,
32443
- readFile: readFileSync7,
32444
- relative: relative4,
32518
+ readFile: readFileSync8,
32519
+ relative: relative5,
32445
32520
  resolve: resolve14
32446
32521
  },
32447
32522
  linkerJitMode: false,
@@ -32482,11 +32557,11 @@ var HASHED_FILE_PATTERN, cleanStaleOutputs = async (buildPath, currentOutputPath
32482
32557
  const currentPaths = new Set(currentOutputPaths.map((path) => resolve15(path)));
32483
32558
  const glob = new Glob5("**/*");
32484
32559
  const removals = [];
32485
- for (const relative5 of glob.scanSync({ cwd: buildPath })) {
32486
- const absolute = resolve15(buildPath, relative5);
32560
+ for (const relative6 of glob.scanSync({ cwd: buildPath })) {
32561
+ const absolute = resolve15(buildPath, relative6);
32487
32562
  if (currentPaths.has(absolute))
32488
32563
  continue;
32489
- if (!HASHED_FILE_PATTERN.test(relative5))
32564
+ if (!HASHED_FILE_PATTERN.test(relative6))
32490
32565
  continue;
32491
32566
  removals.push(rm2(absolute, { force: true }));
32492
32567
  }
@@ -32544,11 +32619,11 @@ var commonAncestor = (paths, fallback) => {
32544
32619
  var init_commonAncestor = () => {};
32545
32620
 
32546
32621
  // src/utils/validateSafePath.ts
32547
- import { resolve as resolve16, relative as relative5 } from "path";
32622
+ import { resolve as resolve16, relative as relative6 } from "path";
32548
32623
  var validateSafePath = (targetPath, baseDirectory) => {
32549
32624
  const absoluteBase = resolve16(baseDirectory);
32550
32625
  const absoluteTarget = resolve16(baseDirectory, targetPath);
32551
- const relativePath = normalizePath(relative5(absoluteBase, absoluteTarget));
32626
+ const relativePath = normalizePath(relative6(absoluteBase, absoluteTarget));
32552
32627
  if (relativePath.startsWith("../") || relativePath === "..") {
32553
32628
  throw new Error(`Unsafe path: ${targetPath}`);
32554
32629
  }
@@ -32558,7 +32633,7 @@ var init_validateSafePath = () => {};
32558
32633
 
32559
32634
  // src/build/resolvePackageImport.ts
32560
32635
  import { resolve as resolve17, join as join10 } from "path";
32561
- import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
32636
+ import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
32562
32637
  var resolveExportPath = (entry, conditions) => {
32563
32638
  if (typeof entry === "string")
32564
32639
  return entry;
@@ -32584,7 +32659,7 @@ var resolveExportPath = (entry, conditions) => {
32584
32659
  if (!existsSync13(packageJsonPath))
32585
32660
  return null;
32586
32661
  try {
32587
- const packageJson = JSON.parse(readFileSync8(packageJsonPath, "utf-8"));
32662
+ const packageJson = JSON.parse(readFileSync9(packageJsonPath, "utf-8"));
32588
32663
  const { exports } = packageJson;
32589
32664
  if (!exports)
32590
32665
  return null;
@@ -32616,7 +32691,7 @@ import {
32616
32691
  basename as basename4,
32617
32692
  extname as extname4,
32618
32693
  resolve as resolve18,
32619
- relative as relative6,
32694
+ relative as relative7,
32620
32695
  sep as sep2
32621
32696
  } from "path";
32622
32697
  import { env as env2 } from "process";
@@ -32720,8 +32795,8 @@ var resolveDevClientDir2 = () => {
32720
32795
  const preprocessedClient = isModule ? loweredClientSource.code : (await preprocess(loweredClientSource.code, {})).code;
32721
32796
  const transpiledServer = src.endsWith(".ts") || src.endsWith(".svelte.ts") ? transpiler2.transformSync(preprocessedServer) : preprocessedServer;
32722
32797
  const transpiledClient = src.endsWith(".ts") || src.endsWith(".svelte.ts") ? transpiler2.transformSync(preprocessedClient) : preprocessedClient;
32723
- const rawRel = dirname8(relative6(svelteRoot, src)).replace(/\\/g, "/");
32724
- const relDir = rawRel.startsWith("..") ? `_ext/${relative6(process.cwd(), dirname8(src)).replace(/\\/g, "/")}` : rawRel;
32798
+ const rawRel = dirname8(relative7(svelteRoot, src)).replace(/\\/g, "/");
32799
+ const relDir = rawRel.startsWith("..") ? `_ext/${relative7(process.cwd(), dirname8(src)).replace(/\\/g, "/")}` : rawRel;
32725
32800
  const baseName = basename4(src).replace(/\.svelte(\.(ts|js))?$/, "");
32726
32801
  const importPaths = Array.from(transpiledServer.matchAll(/from\s+['"]([^'"]+)['"]/g)).map((match) => match[1]).filter((path) => path !== undefined);
32727
32802
  const resolvedModuleImports = await Promise.all(importPaths.map((importPath) => resolveRelativeModule2(importPath, src)));
@@ -32738,15 +32813,15 @@ var resolveDevClientDir2 = () => {
32738
32813
  const resolved = resolvedImports[idx];
32739
32814
  const resolvedModule = resolvedModuleImports[idx];
32740
32815
  if (resolved) {
32741
- const childRel = relative6(svelteRoot, resolved).replace(/\\/g, "/");
32816
+ const childRel = relative7(svelteRoot, resolved).replace(/\\/g, "/");
32742
32817
  if (!childRel.startsWith(".."))
32743
32818
  continue;
32744
32819
  const childBuilt = cache.get(resolved);
32745
32820
  if (!childBuilt)
32746
32821
  continue;
32747
32822
  const origSpec = rawSpec.replace(/\.svelte(?:\.(?:ts|js))?$/, ".js");
32748
- const toServer2 = relative6(ssrOutputDir, childBuilt.ssr).replace(/\\/g, "/");
32749
- const toClient2 = relative6(clientOutputDir, childBuilt.client).replace(/\\/g, "/");
32823
+ const toServer2 = relative7(ssrOutputDir, childBuilt.ssr).replace(/\\/g, "/");
32824
+ const toClient2 = relative7(clientOutputDir, childBuilt.client).replace(/\\/g, "/");
32750
32825
  externalRewrites.set(origSpec, {
32751
32826
  client: toClient2.startsWith(".") ? toClient2 : `./${toClient2}`,
32752
32827
  server: toServer2.startsWith(".") ? toServer2 : `./${toServer2}`
@@ -32755,8 +32830,8 @@ var resolveDevClientDir2 = () => {
32755
32830
  }
32756
32831
  if (!resolvedModule)
32757
32832
  continue;
32758
- const toServer = relative6(ssrOutputDir, resolvedModule).replace(/\\/g, "/");
32759
- const toClient = relative6(clientOutputDir, resolvedModule).replace(/\\/g, "/");
32833
+ const toServer = relative7(ssrOutputDir, resolvedModule).replace(/\\/g, "/");
32834
+ const toClient = relative7(clientOutputDir, resolvedModule).replace(/\\/g, "/");
32760
32835
  externalRewrites.set(rawSpec, {
32761
32836
  client: toClient.startsWith(".") || toClient.startsWith("/") ? toClient : `./${toClient}`,
32762
32837
  server: toServer.startsWith(".") ? toServer : `./${toServer}`
@@ -32791,7 +32866,7 @@ var resolveDevClientDir2 = () => {
32791
32866
  }).js.code;
32792
32867
  let code = compiled.replace(/\.svelte(?:\.(?:ts|js))?(['"])/g, ".js$1");
32793
32868
  if (mode === "client" && isDev2) {
32794
- const moduleKey = `/@src/${relative6(process.cwd(), src).replace(/\\/g, "/")}`;
32869
+ const moduleKey = `/@src/${relative7(process.cwd(), src).replace(/\\/g, "/")}`;
32795
32870
  code = code.replace(/if\s*\(import\.meta\.hot\)\s*\{/, `if (typeof window !== "undefined") {
32796
32871
  if (!window.__SVELTE_HMR_ACCEPT__) window.__SVELTE_HMR_ACCEPT__ = {};
32797
32872
  var __hmr_accept = function(cb) { window.__SVELTE_HMR_ACCEPT__[${JSON.stringify(moduleKey)}] = cb; };`);
@@ -32827,10 +32902,10 @@ var resolveDevClientDir2 = () => {
32827
32902
  };
32828
32903
  const roots = await Promise.all(entryPoints.map(build2));
32829
32904
  await Promise.all(roots.map(async ({ client: client2 }) => {
32830
- const relClientDir = dirname8(relative6(clientDir, client2));
32905
+ const relClientDir = dirname8(relative7(clientDir, client2));
32831
32906
  const name = basename4(client2, extname4(client2));
32832
32907
  const indexPath = join11(indexDir, relClientDir, `${name}.js`);
32833
- const importRaw = relative6(dirname8(indexPath), client2).split(sep2).join("/");
32908
+ const importRaw = relative7(dirname8(indexPath), client2).split(sep2).join("/");
32834
32909
  const importPath = importRaw.startsWith(".") || importRaw.startsWith("/") ? importRaw : `./${importRaw}`;
32835
32910
  const hmrImports = isDev2 ? `window.__HMR_FRAMEWORK__ = "svelte";
32836
32911
  import "${hmrClientPath3}";
@@ -32887,7 +32962,7 @@ if (typeof window !== "undefined") {
32887
32962
  return {
32888
32963
  svelteClientPaths: roots.map(({ client: client2 }) => client2),
32889
32964
  svelteIndexPaths: roots.map(({ client: client2 }) => {
32890
- const rel = dirname8(relative6(clientDir, client2));
32965
+ const rel = dirname8(relative7(clientDir, client2));
32891
32966
  return join11(indexDir, rel, basename4(client2));
32892
32967
  }),
32893
32968
  svelteServerPaths: roots.map(({ ssr }) => ssr)
@@ -32916,7 +32991,7 @@ __export(exports_compileVue, {
32916
32991
  });
32917
32992
  import { existsSync as existsSync15 } from "fs";
32918
32993
  import { mkdir as mkdir3 } from "fs/promises";
32919
- import { basename as basename5, dirname as dirname9, join as join12, relative as relative7, resolve as resolve19 } from "path";
32994
+ import { basename as basename5, dirname as dirname9, join as join12, relative as relative8, resolve as resolve19 } from "path";
32920
32995
  var {file: file3, write: write2, Transpiler: Transpiler2 } = globalThis.Bun;
32921
32996
  var resolveDevClientDir3 = () => {
32922
32997
  const projectRoot = process.cwd();
@@ -32966,7 +33041,7 @@ var resolveDevClientDir3 = () => {
32966
33041
  return "template-only";
32967
33042
  }
32968
33043
  return "full";
32969
- }, generateVueHmrId = (sourceFilePath, vueRootDir) => relative7(vueRootDir, sourceFilePath).replace(/\\/g, "/").replace(/\.vue$/, ""), extractImports = (sourceCode) => Array.from(sourceCode.matchAll(/import\s+[\s\S]+?['"]([^'"]+)['"]/g)).map((match) => match[1]).filter((importPath) => importPath !== undefined), toJs = (filePath) => {
33044
+ }, generateVueHmrId = (sourceFilePath, vueRootDir) => relative8(vueRootDir, sourceFilePath).replace(/\\/g, "/").replace(/\.vue$/, ""), extractImports = (sourceCode) => Array.from(sourceCode.matchAll(/import\s+[\s\S]+?['"]([^'"]+)['"]/g)).map((match) => match[1]).filter((importPath) => importPath !== undefined), toJs = (filePath) => {
32970
33045
  if (filePath.endsWith(".vue"))
32971
33046
  return filePath.replace(/\.vue$/, ".js");
32972
33047
  if (filePath.endsWith(".ts"))
@@ -32993,7 +33068,7 @@ var resolveDevClientDir3 = () => {
32993
33068
  const cachedResult = cacheMap.get(sourceFilePath);
32994
33069
  if (cachedResult)
32995
33070
  return cachedResult;
32996
- const relativeFilePath = relative7(vueRootDir, sourceFilePath).replace(/\\/g, "/");
33071
+ const relativeFilePath = relative8(vueRootDir, sourceFilePath).replace(/\\/g, "/");
32997
33072
  const relativeWithoutExtension = relativeFilePath.replace(/\.vue$/, "");
32998
33073
  const fileBaseName = basename5(sourceFilePath, ".vue");
32999
33074
  const componentId = toKebab(fileBaseName);
@@ -33117,7 +33192,7 @@ if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
33117
33192
  let result2 = code;
33118
33193
  for (const [bareImport, paths] of packageImportRewrites) {
33119
33194
  const targetPath = mode === "server" ? paths.server : paths.client;
33120
- let rel = relative7(dirname9(outputPath), targetPath).replace(/\\/g, "/");
33195
+ let rel = relative8(dirname9(outputPath), targetPath).replace(/\\/g, "/");
33121
33196
  if (!rel.startsWith("."))
33122
33197
  rel = `./${rel}`;
33123
33198
  result2 = result2.replaceAll(bareImport, rel);
@@ -33166,7 +33241,7 @@ if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
33166
33241
  result.tsHelperPaths.forEach((path) => allTsHelperPaths.add(path));
33167
33242
  const entryBaseName = basename5(entryPath, ".vue");
33168
33243
  const indexOutputFile = join12(indexOutputDir, `${entryBaseName}.js`);
33169
- const clientOutputFile = join12(clientOutputDir, relative7(vueRootDir, entryPath).replace(/\\/g, "/").replace(/\.vue$/, ".js"));
33244
+ const clientOutputFile = join12(clientOutputDir, relative8(vueRootDir, entryPath).replace(/\\/g, "/").replace(/\.vue$/, ".js"));
33170
33245
  await mkdir3(dirname9(indexOutputFile), { recursive: true });
33171
33246
  const vueHmrImports = isDev2 ? [
33172
33247
  `window.__HMR_FRAMEWORK__ = "vue";`,
@@ -33174,7 +33249,7 @@ if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
33174
33249
  ] : [];
33175
33250
  await write2(indexOutputFile, [
33176
33251
  ...vueHmrImports,
33177
- `import Comp from "${relative7(dirname9(indexOutputFile), clientOutputFile).replace(/\\/g, "/")}";`,
33252
+ `import Comp from "${relative8(dirname9(indexOutputFile), clientOutputFile).replace(/\\/g, "/")}";`,
33178
33253
  'import { createSSRApp, createApp } from "vue";',
33179
33254
  "",
33180
33255
  "// HMR State Preservation: Check for preserved state from HMR",
@@ -33275,7 +33350,7 @@ if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
33275
33350
  await Promise.all(Array.from(allTsHelperPaths).map(async (tsPath) => {
33276
33351
  const sourceCode = await file3(tsPath).text();
33277
33352
  const transpiledCode = transpiler3.transformSync(sourceCode);
33278
- const relativeJsPath = relative7(vueRootDir, tsPath).replace(/\.ts$/, ".js");
33353
+ const relativeJsPath = relative8(vueRootDir, tsPath).replace(/\.ts$/, ".js");
33279
33354
  const outClientPath = join12(clientOutputDir, relativeJsPath);
33280
33355
  const outServerPath = join12(serverOutputDir, relativeJsPath);
33281
33356
  await mkdir3(dirname9(outClientPath), { recursive: true });
@@ -42168,11 +42243,11 @@ ${lanes.join(`
42168
42243
  return toComponents;
42169
42244
  }
42170
42245
  const components = toComponents.slice(start);
42171
- const relative8 = [];
42246
+ const relative9 = [];
42172
42247
  for (;start < fromComponents.length; start++) {
42173
- relative8.push("..");
42248
+ relative9.push("..");
42174
42249
  }
42175
- return ["", ...relative8, ...components];
42250
+ return ["", ...relative9, ...components];
42176
42251
  }
42177
42252
  function getRelativePathFromDirectory(fromDirectory, to, getCanonicalFileNameOrIgnoreCase) {
42178
42253
  Debug.assert(getRootLength(fromDirectory) > 0 === getRootLength(to) > 0, "Paths must either both be absolute or both be relative");
@@ -79468,9 +79543,9 @@ ${lanes.join(`
79468
79543
  if (!startsWithDirectory(target, realPathDirectory, getCanonicalFileName)) {
79469
79544
  return;
79470
79545
  }
79471
- const relative8 = getRelativePathFromDirectory(realPathDirectory, target, getCanonicalFileName);
79546
+ const relative9 = getRelativePathFromDirectory(realPathDirectory, target, getCanonicalFileName);
79472
79547
  for (const symlinkDirectory of symlinkDirectories) {
79473
- const option = resolvePath(symlinkDirectory, relative8);
79548
+ const option = resolvePath(symlinkDirectory, relative9);
79474
79549
  const result2 = cb(option, target === referenceRedirect);
79475
79550
  shouldFilterIgnoredPaths = true;
79476
79551
  if (result2)
@@ -202035,12 +202110,12 @@ __export(exports_compileAngular, {
202035
202110
  compileAngularFile: () => compileAngularFile,
202036
202111
  compileAngular: () => compileAngular
202037
202112
  });
202038
- import { existsSync as existsSync16, readFileSync as readFileSync9, promises as fs } from "fs";
202039
- import { join as join13, basename as basename6, sep as sep3, dirname as dirname10, resolve as resolve20, relative as relative8 } from "path";
202113
+ import { existsSync as existsSync16, readFileSync as readFileSync10, promises as fs } from "fs";
202114
+ import { join as join13, basename as basename6, sep as sep3, dirname as dirname10, resolve as resolve20, relative as relative9 } from "path";
202040
202115
  import { createHash as createHash2 } from "crypto";
202041
202116
  var import_typescript, computeConfigHash = () => {
202042
202117
  try {
202043
- const content = readFileSync9("./tsconfig.json", "utf-8");
202118
+ const content = readFileSync10("./tsconfig.json", "utf-8");
202044
202119
  return createHash2("md5").update(content).digest("hex");
202045
202120
  } catch {
202046
202121
  return "";
@@ -202098,7 +202173,7 @@ ${registrations}
202098
202173
  return fileName.substring(outDir.length + 1);
202099
202174
  return fileName;
202100
202175
  }, compileAngularFile = async (inputPath, outDir) => {
202101
- const islandMetadataExports = buildIslandMetadataExports(readFileSync9(inputPath, "utf-8"));
202176
+ const islandMetadataExports = buildIslandMetadataExports(readFileSync10(inputPath, "utf-8"));
202102
202177
  const {
202103
202178
  readConfiguration,
202104
202179
  performCompilation,
@@ -202368,7 +202443,7 @@ export default ${componentClassName};
202368
202443
  await fs.writeFile(ssrDepsFile, ssrDepsContent, "utf-8");
202369
202444
  }
202370
202445
  await fs.writeFile(rawServerFile, rewritten, "utf-8");
202371
- const relativePath = relative8(indexesDir, rawServerFile).replace(/\\/g, "/");
202446
+ const relativePath = relative9(indexesDir, rawServerFile).replace(/\\/g, "/");
202372
202447
  const normalizedImportPath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
202373
202448
  const hmrPreamble = hmr ? `window.__HMR_FRAMEWORK__ = "angular";
202374
202449
  import "${hmrRuntimePath}";
@@ -202649,11 +202724,11 @@ var vueSpecifiers, toSafeFileName3 = (specifier) => specifier.replace(/\//g, "_"
202649
202724
  console.warn("\u26A0\uFE0F Vue vendor build had errors:", result.logs);
202650
202725
  return;
202651
202726
  }
202652
- const { readFileSync: readFileSync10, writeFileSync: writeFileSync8, readdirSync } = await import("fs");
202727
+ const { readFileSync: readFileSync11, writeFileSync: writeFileSync8, readdirSync } = await import("fs");
202653
202728
  const files = readdirSync(vendorDir).filter((f) => f.endsWith(".js"));
202654
202729
  for (const file4 of files) {
202655
202730
  const filePath = join16(vendorDir, file4);
202656
- const content = readFileSync10(filePath, "utf-8");
202731
+ const content = readFileSync11(filePath, "utf-8");
202657
202732
  if (!content.includes("__VUE_HMR_RUNTIME__"))
202658
202733
  continue;
202659
202734
  const patched = content.replace(/getGlobalThis\(\)\.__VUE_HMR_RUNTIME__\s*=\s*\{/, "getGlobalThis().__VUE_HMR_RUNTIME__ = getGlobalThis().__VUE_HMR_RUNTIME__ || {");
@@ -202777,12 +202852,12 @@ import {
202777
202852
  cpSync,
202778
202853
  existsSync as existsSync17,
202779
202854
  mkdirSync as mkdirSync11,
202780
- readFileSync as readFileSync10,
202855
+ readFileSync as readFileSync11,
202781
202856
  rmSync as rmSync3,
202782
202857
  statSync,
202783
202858
  writeFileSync as writeFileSync8
202784
202859
  } from "fs";
202785
- import { basename as basename7, dirname as dirname11, join as join18, relative as relative9, resolve as resolve21 } from "path";
202860
+ import { basename as basename7, dirname as dirname11, join as join18, relative as relative10, resolve as resolve21 } from "path";
202786
202861
  import { cwd, env as env3, exit } from "process";
202787
202862
  var {build: bunBuild6, Glob: Glob6 } = globalThis.Bun;
202788
202863
  var isDev2, collectConventionSourceFiles = (entry) => {
@@ -202898,7 +202973,7 @@ var isDev2, collectConventionSourceFiles = (entry) => {
202898
202973
  addWorkerPathIfExists(file4, relPath, workerPaths);
202899
202974
  }
202900
202975
  }, collectWorkerPathsFromFile = (file4, patterns, workerPaths) => {
202901
- const content = readFileSync10(file4, "utf-8");
202976
+ const content = readFileSync11(file4, "utf-8");
202902
202977
  for (const pattern of patterns) {
202903
202978
  collectWorkerPathsFromContent(content, pattern, file4, workerPaths);
202904
202979
  }
@@ -202944,9 +203019,9 @@ var isDev2, collectConventionSourceFiles = (entry) => {
202944
203019
  }
202945
203020
  }, copyReactDevIndexes = (reactIndexesPath, reactPagesPath, devIndexDir, readDir) => {
202946
203021
  const indexFiles = readDir(reactIndexesPath).filter((file4) => file4.endsWith(".tsx"));
202947
- const pagesRel = relative9(process.cwd(), resolve21(reactPagesPath)).replace(/\\/g, "/");
203022
+ const pagesRel = relative10(process.cwd(), resolve21(reactPagesPath)).replace(/\\/g, "/");
202948
203023
  for (const file4 of indexFiles) {
202949
- let content = readFileSync10(join18(reactIndexesPath, file4), "utf-8");
203024
+ let content = readFileSync11(join18(reactIndexesPath, file4), "utf-8");
202950
203025
  content = content.replace(/from\s*['"]([^'"]*\/pages\/([^'"]+))['"]/g, (_match, _fullPath, componentName) => `from '/@src/${pagesRel}/${componentName}'`);
202951
203026
  writeFileSync8(join18(devIndexDir, file4), content);
202952
203027
  }
@@ -202958,8 +203033,8 @@ var isDev2, collectConventionSourceFiles = (entry) => {
202958
203033
  const indexFile = join18(svelteIndexDir, "pages", `${name}.js`);
202959
203034
  if (!existsSync17(indexFile))
202960
203035
  continue;
202961
- let content = readFileSync10(indexFile, "utf-8");
202962
- const srcRel = relative9(process.cwd(), resolve21(entry)).replace(/\\/g, "/");
203036
+ let content = readFileSync11(indexFile, "utf-8");
203037
+ const srcRel = relative10(process.cwd(), resolve21(entry)).replace(/\\/g, "/");
202963
203038
  content = content.replace(/import\s+Component\s+from\s+['"]([^'"]+)['"]/, `import Component from "/@src/${srcRel}"`);
202964
203039
  writeFileSync8(join18(devIndexDir, `${name}.svelte.js`), content);
202965
203040
  }
@@ -202971,8 +203046,8 @@ var isDev2, collectConventionSourceFiles = (entry) => {
202971
203046
  const indexFile = join18(vueIndexDir, `${name}.js`);
202972
203047
  if (!existsSync17(indexFile))
202973
203048
  continue;
202974
- let content = readFileSync10(indexFile, "utf-8");
202975
- const srcRel = relative9(process.cwd(), resolve21(entry)).replace(/\\/g, "/");
203049
+ let content = readFileSync11(indexFile, "utf-8");
203050
+ const srcRel = relative10(process.cwd(), resolve21(entry)).replace(/\\/g, "/");
202976
203051
  content = content.replace(/import\s+Comp\s+from\s+['"]([^'"]+)['"]/, `import Comp from "/@src/${srcRel}"`);
202977
203052
  writeFileSync8(join18(devIndexDir, `${name}.vue.js`), content);
202978
203053
  }
@@ -203022,7 +203097,7 @@ var isDev2, collectConventionSourceFiles = (entry) => {
203022
203097
  }
203023
203098
  return result;
203024
203099
  }, VUE_HMR_RUNTIME, injectVueComposableTracking = (outputPath, projectRoot) => {
203025
- let content = readFileSync10(outputPath, "utf-8");
203100
+ let content = readFileSync11(outputPath, "utf-8");
203026
203101
  const usePattern = /^var\s+(use[A-Z]\w*)\s*=/gm;
203027
203102
  const useNames = [];
203028
203103
  let match;
@@ -203047,7 +203122,7 @@ ${content.slice(firstUseIdx)}`;
203047
203122
  }, buildDevUrlFileMap = (urlReferencedFiles, projectRoot) => {
203048
203123
  const urlFileMap = new Map;
203049
203124
  for (const srcPath of urlReferencedFiles) {
203050
- const rel = relative9(projectRoot, srcPath).replace(/\\/g, "/");
203125
+ const rel = relative10(projectRoot, srcPath).replace(/\\/g, "/");
203051
203126
  const name = basename7(srcPath);
203052
203127
  const mtime = Math.round(statSync(srcPath).mtimeMs);
203053
203128
  const url = `/@src/${rel}?v=${mtime}`;
@@ -203062,7 +203137,7 @@ ${content.slice(firstUseIdx)}`;
203062
203137
  const output = nonReactClientOutputs.find((artifact) => basename7(artifact.path).startsWith(`${srcBase}.`));
203063
203138
  if (!output)
203064
203139
  continue;
203065
- urlFileMap.set(basename7(srcPath), `/${relative9(buildPath, output.path).replace(/\\/g, "/")}`);
203140
+ urlFileMap.set(basename7(srcPath), `/${relative10(buildPath, output.path).replace(/\\/g, "/")}`);
203066
203141
  }
203067
203142
  return urlFileMap;
203068
203143
  }, buildUrlFileMap = (urlReferencedFiles, hmr, projectRoot, buildPath, nonReactClientOutputs) => {
@@ -203072,7 +203147,7 @@ ${content.slice(firstUseIdx)}`;
203072
203147
  }, rewriteUrlReferences = (outputPaths, urlFileMap) => {
203073
203148
  const urlPattern = /new\s+URL\(\s*["'](\.\.?\/[^"']+)["']\s*,\s*import\.meta\.url\s*\)/g;
203074
203149
  for (const outputPath of outputPaths) {
203075
- let content = readFileSync10(outputPath, "utf-8");
203150
+ let content = readFileSync11(outputPath, "utf-8");
203076
203151
  let changed = false;
203077
203152
  content = content.replace(urlPattern, (_match, relPath) => {
203078
203153
  const targetName = basename7(relPath);
@@ -203729,7 +203804,7 @@ ${content.slice(firstUseIdx)}`;
203729
203804
  const injectHMRIntoHTMLFile = (filePath, framework) => {
203730
203805
  if (!hmrClientBundle)
203731
203806
  return;
203732
- let html = readFileSync10(filePath, "utf-8");
203807
+ let html = readFileSync11(filePath, "utf-8");
203733
203808
  if (html.includes("data-hmr-client"))
203734
203809
  return;
203735
203810
  const tag = `<script>window.__HMR_FRAMEWORK__="${framework}";</script><script data-hmr-client>${hmrClientBundle}</script>`;
@@ -203891,7 +203966,7 @@ var init_build = __esm(() => {
203891
203966
  });
203892
203967
 
203893
203968
  // src/dev/dependencyGraph.ts
203894
- import { existsSync as existsSync18, readFileSync as readFileSync11 } from "fs";
203969
+ import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
203895
203970
  var {Glob: Glob7 } = globalThis.Bun;
203896
203971
  import { resolve as resolve22 } from "path";
203897
203972
  var emptyDependencyGraph, tsTranspiler, jsTranspiler, loaderForFile = (filePath) => {
@@ -204052,15 +204127,15 @@ var emptyDependencyGraph, tsTranspiler, jsTranspiler, loaderForFile = (filePath)
204052
204127
  const lowerPath = filePath.toLowerCase();
204053
204128
  const isSvelteOrVue = lowerPath.endsWith(".svelte") || lowerPath.endsWith(".vue");
204054
204129
  if (loader === "html") {
204055
- const content = readFileSync11(filePath, "utf-8");
204130
+ const content = readFileSync12(filePath, "utf-8");
204056
204131
  return extractHtmlDependencies(filePath, content);
204057
204132
  }
204058
204133
  if (loader === "tsx" || loader === "js") {
204059
- const content = readFileSync11(filePath, "utf-8");
204134
+ const content = readFileSync12(filePath, "utf-8");
204060
204135
  return extractJsDependencies(filePath, content, loader);
204061
204136
  }
204062
204137
  if (isSvelteOrVue) {
204063
- const content = readFileSync11(filePath, "utf-8");
204138
+ const content = readFileSync12(filePath, "utf-8");
204064
204139
  return extractSvelteVueDependencies(filePath, content);
204065
204140
  }
204066
204141
  return [];
@@ -204526,10 +204601,10 @@ var init_assetStore = __esm(() => {
204526
204601
  });
204527
204602
 
204528
204603
  // src/dev/fileHashTracker.ts
204529
- import { readFileSync as readFileSync12 } from "fs";
204604
+ import { readFileSync as readFileSync13 } from "fs";
204530
204605
  var computeFileHash = (filePath) => {
204531
204606
  try {
204532
- const fileContent = readFileSync12(filePath);
204607
+ const fileContent = readFileSync13(filePath);
204533
204608
  return Number(Bun.hash(fileContent));
204534
204609
  } catch {
204535
204610
  return UNFOUND_INDEX;
@@ -205287,8 +205362,8 @@ __export(exports_moduleServer, {
205287
205362
  createModuleServer: () => createModuleServer,
205288
205363
  SRC_URL_PREFIX: () => SRC_URL_PREFIX
205289
205364
  });
205290
- import { existsSync as existsSync20, readFileSync as readFileSync13, statSync as statSync2 } from "fs";
205291
- import { basename as basename10, dirname as dirname13, extname as extname5, resolve as resolve28, relative as relative10 } from "path";
205365
+ import { existsSync as existsSync20, readFileSync as readFileSync14, statSync as statSync2 } from "fs";
205366
+ import { basename as basename10, dirname as dirname13, extname as extname5, resolve as resolve28, relative as relative11 } from "path";
205292
205367
  var SRC_PREFIX = "/@src/", jsTranspiler2, tsTranspiler2, tsxTranspiler, TRANSPILABLE, ALL_EXPORTS_RE, STRING_CONTENTS_RE, preserveTypeExports = (originalSource, transpiled, valueExports) => {
205293
205368
  const codeOnly = originalSource.replace(STRING_CONTENTS_RE, '""');
205294
205369
  const allExports = [];
@@ -205336,23 +205411,23 @@ ${stubs}
205336
205411
  }
205337
205412
  }, resolveRelativeImport = (relPath, fileDir, projectRoot, extensions) => {
205338
205413
  const absPath = resolve28(fileDir, relPath);
205339
- const rel = relative10(projectRoot, absPath);
205414
+ const rel = relative11(projectRoot, absPath);
205340
205415
  const extension = extname5(rel);
205341
205416
  let srcPath = RESOLVED_MODULE_EXTENSIONS.has(extension) ? rel : resolveRelativeExtension(rel, projectRoot, extensions);
205342
205417
  if (extname5(srcPath) === ".svelte") {
205343
- srcPath = relative10(projectRoot, resolveSvelteModulePath(resolve28(projectRoot, srcPath)));
205418
+ srcPath = relative11(projectRoot, resolveSvelteModulePath(resolve28(projectRoot, srcPath)));
205344
205419
  }
205345
205420
  return srcUrl(srcPath, projectRoot);
205346
205421
  }, resolveAbsoluteSpecifier = (specifier, projectRoot, importer, frameworkDirs) => {
205347
205422
  if (importer && frameworkDirs) {
205348
205423
  const compatModule = resolveIslandCompatModule(specifier, importer, frameworkDirs);
205349
205424
  if (compatModule) {
205350
- return relative10(projectRoot, compatModule);
205425
+ return relative11(projectRoot, compatModule);
205351
205426
  }
205352
205427
  }
205353
205428
  try {
205354
205429
  const target = resolvePackageImport(specifier, ["browser", "import"]) ?? Bun.resolveSync(specifier, projectRoot);
205355
- return relative10(projectRoot, target);
205430
+ return relative11(projectRoot, target);
205356
205431
  } catch {
205357
205432
  return;
205358
205433
  }
@@ -205385,10 +205460,10 @@ ${stubs}
205385
205460
  result = result.replace(/(import\s*["'])(\.\.?\/[^"']+)(["']\s*;?)/g, (_match, prefix, relPath, suffix) => `${prefix}${resolveRelativeImport(relPath, fileDir, projectRoot, SIDE_EFFECT_EXTENSIONS)}${suffix}`);
205386
205461
  result = result.replace(/((?:from|import)\s*["'])(\/[^"']+\.(tsx?|jsx?|ts))(["'])/g, (_match, prefix, absPath, _ext, suffix) => {
205387
205462
  if (absPath.startsWith(projectRoot)) {
205388
- const rel2 = relative10(projectRoot, absPath).replace(/\\/g, "/");
205463
+ const rel2 = relative11(projectRoot, absPath).replace(/\\/g, "/");
205389
205464
  return `${prefix}${srcUrl(rel2, projectRoot)}${suffix}`;
205390
205465
  }
205391
- const rel = relative10(projectRoot, absPath).replace(/\\/g, "/");
205466
+ const rel = relative11(projectRoot, absPath).replace(/\\/g, "/");
205392
205467
  if (!rel.startsWith("..")) {
205393
205468
  return `${prefix}${srcUrl(rel, projectRoot)}${suffix}`;
205394
205469
  }
@@ -205396,12 +205471,12 @@ ${stubs}
205396
205471
  });
205397
205472
  result = result.replace(/new\s+URL\(\s*["'](\.\.?\/[^"']+)["']\s*,\s*import\.meta\.url\s*\)/g, (_match, relPath) => {
205398
205473
  const absPath = resolve28(fileDir, relPath);
205399
- const rel = relative10(projectRoot, absPath);
205474
+ const rel = relative11(projectRoot, absPath);
205400
205475
  return `new URL('${srcUrl(rel, projectRoot)}', import.meta.url)`;
205401
205476
  });
205402
205477
  result = result.replace(/import\.meta\.resolve\(\s*["'](\.\.?\/[^"']+)["']\s*\)/g, (_match, relPath) => {
205403
205478
  const absPath = resolve28(fileDir, relPath);
205404
- const rel = relative10(projectRoot, absPath);
205479
+ const rel = relative11(projectRoot, absPath);
205405
205480
  return `'${srcUrl(rel, projectRoot)}'`;
205406
205481
  });
205407
205482
  return result;
@@ -205429,7 +205504,7 @@ ${stubs}
205429
205504
  `)}
205430
205505
  ${code}`;
205431
205506
  }, reactTranspilerOptions, reactTranspiler, transformReactFile = (filePath, projectRoot, rewriter, frameworkDirs) => {
205432
- const raw = readFileSync13(filePath, "utf-8");
205507
+ const raw = readFileSync14(filePath, "utf-8");
205433
205508
  const valueExports = tsxTranspiler.scan(raw).exports;
205434
205509
  let transpiled = reactTranspiler.transformSync(raw);
205435
205510
  transpiled = preserveTypeExports(raw, transpiled, valueExports);
@@ -205440,12 +205515,12 @@ ${code}`;
205440
205515
  transpiled = `var $RefreshReg$ = window.$RefreshReg$ || function(){};
205441
205516
  ` + `var $RefreshSig$ = window.$RefreshSig$ || function(){ return function(t){ return t; }; };
205442
205517
  ${transpiled}`;
205443
- const relPath = relative10(projectRoot, filePath).replace(/\\/g, "/");
205518
+ const relPath = relative11(projectRoot, filePath).replace(/\\/g, "/");
205444
205519
  transpiled = transpiled.replace(/\binput\.tsx:/g, `${relPath}:`);
205445
205520
  transpiled += buildIslandMetadataExports(raw);
205446
205521
  return rewriteImports2(transpiled, filePath, projectRoot, rewriter, frameworkDirs);
205447
205522
  }, transformPlainFile = (filePath, projectRoot, rewriter, vueDir, frameworkDirs) => {
205448
- const raw = readFileSync13(filePath, "utf-8");
205523
+ const raw = readFileSync14(filePath, "utf-8");
205449
205524
  const ext = extname5(filePath);
205450
205525
  const isTS = ext === ".ts" || ext === ".tsx";
205451
205526
  const isTSX = ext === ".tsx" || ext === ".jsx";
@@ -205591,17 +205666,17 @@ ${code}`;
205591
205666
  if (compiled.css?.code) {
205592
205667
  const cssPath = `${filePath}.css`;
205593
205668
  svelteExternalCss.set(cssPath, compiled.css.code);
205594
- const cssUrl = srcUrl(relative10(projectRoot, cssPath), projectRoot);
205669
+ const cssUrl = srcUrl(relative11(projectRoot, cssPath), projectRoot);
205595
205670
  code = `import "${cssUrl}";
205596
205671
  ${code}`;
205597
205672
  }
205598
- const moduleUrl = `${SRC_PREFIX}${relative10(projectRoot, filePath).replace(/\\/g, "/")}`;
205673
+ const moduleUrl = `${SRC_PREFIX}${relative11(projectRoot, filePath).replace(/\\/g, "/")}`;
205599
205674
  code = code.replace(/if\s*\(import\.meta\.hot\)\s*\{/, `if (typeof window !== "undefined") {
205600
205675
  ` + ` if (!window.__SVELTE_HMR_ACCEPT__) window.__SVELTE_HMR_ACCEPT__ = {};
205601
205676
  ` + ` var __hmr_accept = function(cb) { window.__SVELTE_HMR_ACCEPT__[${JSON.stringify(moduleUrl)}] = cb; };`);
205602
205677
  return code.replace(/import\.meta\.hot\.accept\(/g, "__hmr_accept(");
205603
205678
  }, transformSvelteFile = async (filePath, projectRoot, rewriter, frameworkDirs) => {
205604
- const raw = readFileSync13(filePath, "utf-8");
205679
+ const raw = readFileSync14(filePath, "utf-8");
205605
205680
  if (!svelteCompiler) {
205606
205681
  svelteCompiler = await import("svelte/compiler");
205607
205682
  }
@@ -205657,7 +205732,7 @@ export default __script__;`;
205657
205732
  return `${cssInjection}
205658
205733
  ${code}`;
205659
205734
  }, transformVueFile = async (filePath, projectRoot, rewriter, vueDir, frameworkDirs) => {
205660
- const raw = readFileSync13(filePath, "utf-8");
205735
+ const raw = readFileSync14(filePath, "utf-8");
205661
205736
  if (!vueCompiler) {
205662
205737
  vueCompiler = await import("@vue/compiler-sfc");
205663
205738
  }
@@ -205675,7 +205750,7 @@ ${code}`;
205675
205750
  return rewriteImports2(code, filePath, projectRoot, rewriter, frameworkDirs);
205676
205751
  }, injectVueHmr = (code, filePath, projectRoot, vueDir) => {
205677
205752
  const hmrBase = vueDir ? resolve28(vueDir) : projectRoot;
205678
- const hmrId = relative10(hmrBase, filePath).replace(/\\/g, "/").replace(/\.vue$/, "");
205753
+ const hmrId = relative11(hmrBase, filePath).replace(/\\/g, "/").replace(/\.vue$/, "");
205679
205754
  let result = code.replace(/export\s+default\s+/, "var __hmr_comp__ = ");
205680
205755
  result += [
205681
205756
  "",
@@ -205706,7 +205781,7 @@ ${code}`;
205706
205781
  }
205707
205782
  });
205708
205783
  }, handleCssRequest = (filePath) => {
205709
- const raw = readFileSync13(filePath, "utf-8");
205784
+ const raw = readFileSync14(filePath, "utf-8");
205710
205785
  const escaped = raw.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
205711
205786
  return [
205712
205787
  `const style = document.createElement('style');`,
@@ -206044,7 +206119,7 @@ var init_simpleHTMXHMR = () => {};
206044
206119
  // src/dev/rebuildTrigger.ts
206045
206120
  import { existsSync as existsSync21 } from "fs";
206046
206121
  import { rm as rm8 } from "fs/promises";
206047
- import { basename as basename11, dirname as dirname14, relative as relative11, resolve as resolve31 } from "path";
206122
+ import { basename as basename11, dirname as dirname14, relative as relative12, resolve as resolve31 } from "path";
206048
206123
  var moduleServerPromise, getModuleServer = () => moduleServerPromise, parseErrorLocationFromMessage = (msg) => {
206049
206124
  const pathLineCol = msg.match(/^([^\s:]+):(\d+)(?::(\d+))?/);
206050
206125
  if (pathLineCol) {
@@ -206239,7 +206314,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, parseError
206239
206314
  if (framework === "unknown") {
206240
206315
  const { invalidate: invalidate2 } = (init_transformCache(), __toCommonJS(exports_transformCache));
206241
206316
  invalidate2(resolve31(filePath));
206242
- const relPath = relative11(process.cwd(), filePath);
206317
+ const relPath = relative12(process.cwd(), filePath);
206243
206318
  logHmrUpdate(relPath);
206244
206319
  return;
206245
206320
  }
@@ -206512,7 +206587,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, parseError
206512
206587
  }, getModuleUrl = async (pageFile) => {
206513
206588
  const { invalidateModule: invalidateModule2, warmCache: warmCache2, SRC_URL_PREFIX: SRC_URL_PREFIX2 } = await Promise.resolve().then(() => (init_moduleServer(), exports_moduleServer));
206514
206589
  invalidateModule2(pageFile);
206515
- const rel = relative11(process.cwd(), pageFile).replace(/\\/g, "/");
206590
+ const rel = relative12(process.cwd(), pageFile).replace(/\\/g, "/");
206516
206591
  const url = `${SRC_URL_PREFIX2}${rel}`;
206517
206592
  warmCache2(url);
206518
206593
  return url;
@@ -206544,7 +206619,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, parseError
206544
206619
  const pageModuleUrl = await getReactModuleUrl(broadcastTarget);
206545
206620
  if (pageModuleUrl) {
206546
206621
  const serverDuration = Date.now() - startTime;
206547
- state.lastHmrPath = relative11(process.cwd(), primaryFile).replace(/\\/g, "/");
206622
+ state.lastHmrPath = relative12(process.cwd(), primaryFile).replace(/\\/g, "/");
206548
206623
  state.lastHmrFramework = "react";
206549
206624
  broadcastToClients(state, {
206550
206625
  data: {
@@ -206996,7 +207071,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, parseError
206996
207071
  const baseName = fileName.replace(/\.vue$/, "");
206997
207072
  const pascalName = toPascal(baseName);
206998
207073
  const vueRoot = config.vueDirectory;
206999
- const hmrId = vueRoot ? relative11(vueRoot, vuePagePath).replace(/\\/g, "/").replace(/\.vue$/, "") : baseName;
207074
+ const hmrId = vueRoot ? relative12(vueRoot, vuePagePath).replace(/\\/g, "/").replace(/\.vue$/, "") : baseName;
207000
207075
  const cssKey = `${pascalName}CSS`;
207001
207076
  const cssUrl = manifest[cssKey] || null;
207002
207077
  const { vueHmrMetadata: vueHmrMetadata2 } = await Promise.resolve().then(() => (init_compileVue(), exports_compileVue));
@@ -207622,7 +207697,7 @@ var toSafeFileName5 = (specifier) => specifier.replace(/\//g, "_").replace(/@/g,
207622
207697
  return Array.from(specifiers).filter(isResolvable3);
207623
207698
  }, generateEntrySource2 = (specifier) => `export * from '${specifier}';
207624
207699
  `, rewriteVendorFiles = async (vendorDir) => {
207625
- const { readdirSync: readdirSync2, readFileSync: readFileSync14, writeFileSync: writeFileSync9 } = await import("fs");
207700
+ const { readdirSync: readdirSync2, readFileSync: readFileSync15, writeFileSync: writeFileSync9 } = await import("fs");
207626
207701
  const { computeVendorPaths: computeVendorPaths2 } = await Promise.resolve().then(() => (init_buildReactVendor(), exports_buildReactVendor));
207627
207702
  const reactPaths = Object.entries(computeVendorPaths2());
207628
207703
  const rewriteContent = (content) => reactPaths.reduce((acc, [specifier, webPath]) => {
@@ -207633,7 +207708,7 @@ var toSafeFileName5 = (specifier) => specifier.replace(/\//g, "_").replace(/@/g,
207633
207708
  const files = readdirSync2(vendorDir).filter((f) => f.endsWith(".js"));
207634
207709
  for (const file4 of files) {
207635
207710
  const filePath = join20(vendorDir, file4);
207636
- const original = readFileSync14(filePath, "utf-8");
207711
+ const original = readFileSync15(filePath, "utf-8");
207637
207712
  const rewritten = rewriteContent(original);
207638
207713
  if (rewritten !== original)
207639
207714
  writeFileSync9(filePath, rewritten);
@@ -208411,7 +208486,7 @@ __export(exports_prerender, {
208411
208486
  prerender: () => prerender,
208412
208487
  PRERENDER_BYPASS_HEADER: () => PRERENDER_BYPASS_HEADER
208413
208488
  });
208414
- import { mkdirSync as mkdirSync13, readFileSync as readFileSync14 } from "fs";
208489
+ import { mkdirSync as mkdirSync13, readFileSync as readFileSync15 } from "fs";
208415
208490
  import { join as join21 } from "path";
208416
208491
  var MAX_STARTUP_ATTEMPTS = 50, STARTUP_POLL_INTERVAL_MS = 100, PRERENDER_BYPASS_HEADER = "X-Absolute-Prerender-Bypass", routeToFilename = (route) => route === "/" ? "index.html" : `${route.slice(1).replace(/\//g, "-")}.html`, writeTimestamp = async (htmlPath) => {
208417
208492
  const metaPath = htmlPath.replace(/\.html$/, ".meta");
@@ -208419,7 +208494,7 @@ var MAX_STARTUP_ATTEMPTS = 50, STARTUP_POLL_INTERVAL_MS = 100, PRERENDER_BYPASS_
208419
208494
  }, readTimestamp = (htmlPath) => {
208420
208495
  const metaPath = htmlPath.replace(/\.html$/, ".meta");
208421
208496
  try {
208422
- const content = readFileSync14(metaPath, "utf-8");
208497
+ const content = readFileSync15(metaPath, "utf-8");
208423
208498
  return Number(content) || 0;
208424
208499
  } catch {
208425
208500
  return 0;
@@ -208547,12 +208622,12 @@ __export(exports_devCert, {
208547
208622
  hasCert: () => hasCert,
208548
208623
  ensureDevCert: () => ensureDevCert
208549
208624
  });
208550
- import { existsSync as existsSync24, mkdirSync as mkdirSync14, readFileSync as readFileSync16, rmSync as rmSync4 } from "fs";
208625
+ import { existsSync as existsSync24, mkdirSync as mkdirSync14, readFileSync as readFileSync17, rmSync as rmSync4 } from "fs";
208551
208626
  import { platform as platform3 } from "os";
208552
208627
  import { join as join23 } from "path";
208553
208628
  var CERT_DIR, CERT_PATH, KEY_PATH, CERT_VALIDITY_DAYS = 365, devLog = (msg) => console.log(`\x1B[2m${new Date().toLocaleTimeString()}\x1B[0m \x1B[36m[dev]\x1B[0m ${msg}`), devWarn = (msg) => console.log(`\x1B[2m${new Date().toLocaleTimeString()}\x1B[0m \x1B[33m[dev]\x1B[0m \x1B[33m${msg}\x1B[0m`), certFilesExist = () => existsSync24(CERT_PATH) && existsSync24(KEY_PATH), isCertExpired = () => {
208554
208629
  try {
208555
- const certPem = readFileSync16(CERT_PATH, "utf-8");
208630
+ const certPem = readFileSync17(CERT_PATH, "utf-8");
208556
208631
  const proc = Bun.spawnSync(["openssl", "x509", "-enddate", "-noout"], {
208557
208632
  stdin: new TextEncoder().encode(certPem)
208558
208633
  });
@@ -208641,8 +208716,8 @@ var CERT_DIR, CERT_PATH, KEY_PATH, CERT_VALIDITY_DAYS = 365, devLog = (msg) => c
208641
208716
  return null;
208642
208717
  try {
208643
208718
  return {
208644
- cert: readFileSync16(paths.cert, "utf-8"),
208645
- key: readFileSync16(paths.key, "utf-8")
208719
+ cert: readFileSync17(paths.cert, "utf-8"),
208720
+ key: readFileSync17(paths.key, "utf-8")
208646
208721
  };
208647
208722
  } catch {
208648
208723
  return null;
@@ -208783,24 +208858,26 @@ var asset = (source, name) => {
208783
208858
  init_islands();
208784
208859
 
208785
208860
  // src/core/pageHandlers.ts
208861
+ init_staticIslandPages();
208786
208862
  init_pageHandler();
208787
208863
  var {file } = globalThis.Bun;
208788
208864
  var handleStaticPageRequest = async (pagePath) => {
208789
208865
  const html = await file(pagePath).text();
208790
- return new Response(injectIslandPageContext(html), {
208866
+ const transformedHtml = await transformCurrentStaticPageHtml(html);
208867
+ return new Response(injectIslandPageContext(transformedHtml), {
208791
208868
  headers: { "Content-Type": "text/html" }
208792
208869
  });
208793
208870
  };
208794
208871
  var handleHTMLPageRequest = (pagePath) => handleStaticPageRequest(pagePath);
208795
208872
  var handleHTMXPageRequest = (pagePath) => handleStaticPageRequest(pagePath);
208796
208873
  // src/core/prepare.ts
208797
- import { existsSync as existsSync23, readdirSync as readdirSync2, readFileSync as readFileSync15 } from "fs";
208798
- import { basename as basename12, join as join22, relative as relative12, resolve as resolve34 } from "path";
208874
+ import { existsSync as existsSync23, readdirSync as readdirSync2, readFileSync as readFileSync16 } from "fs";
208875
+ import { basename as basename12, join as join22, relative as relative13, resolve as resolve34 } from "path";
208799
208876
 
208800
208877
  // src/utils/loadConfig.ts
208801
- import { resolve } from "path";
208878
+ import { resolve as resolve5 } from "path";
208802
208879
  var loadConfig = async (configPath) => {
208803
- const resolved = resolve(configPath ?? process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
208880
+ const resolved = resolve5(configPath ?? process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
208804
208881
  const mod = await import(resolved);
208805
208882
  const config = mod.default ?? mod.config;
208806
208883
  if (!config) {
@@ -208810,24 +208887,24 @@ Expected: export default defineConfig({ ... })`);
208810
208887
  return config;
208811
208888
  };
208812
208889
  // src/core/loadIslandRegistry.ts
208813
- import { resolve as resolve2 } from "path";
208814
- var isRecord2 = (value) => typeof value === "object" && value !== null;
208815
- var resolveRegistryExport = (mod) => {
208816
- if (isRecord2(mod.islandRegistry))
208890
+ import { resolve as resolve6 } from "path";
208891
+ var isRecord5 = (value) => typeof value === "object" && value !== null;
208892
+ var resolveRegistryExport2 = (mod) => {
208893
+ if (isRecord5(mod.islandRegistry))
208817
208894
  return mod.islandRegistry;
208818
- if (isRecord2(mod.default))
208895
+ if (isRecord5(mod.default))
208819
208896
  return mod.default;
208820
208897
  throw new Error("Island registry module must export `islandRegistry` or a default registry object.");
208821
208898
  };
208822
- var isRegistryModuleExport = (value) => isRecord2(value);
208823
- var isIslandRegistryInput = (value) => isRecord2(value);
208899
+ var isRegistryModuleExport = (value) => isRecord5(value);
208900
+ var isIslandRegistryInput = (value) => isRecord5(value);
208824
208901
  var loadIslandRegistry = async (registryPath) => {
208825
- const resolvedRegistryPath = resolve2(registryPath);
208902
+ const resolvedRegistryPath = resolve6(registryPath);
208826
208903
  const importedModule = await import(resolvedRegistryPath);
208827
208904
  if (!isRegistryModuleExport(importedModule)) {
208828
208905
  throw new Error("Island registry module must export an object namespace.");
208829
208906
  }
208830
- const registryExport = resolveRegistryExport(importedModule);
208907
+ const registryExport = resolveRegistryExport2(importedModule);
208831
208908
  if (!isIslandRegistryInput(registryExport)) {
208832
208909
  throw new Error("Resolved island registry export is not an object.");
208833
208910
  }
@@ -208875,7 +208952,7 @@ var warmPrewarmDirs = async (prewarmDirs, warmCache2, SRC_URL_PREFIX2) => {
208875
208952
  for (const file4 of files) {
208876
208953
  if (file4.includes("/node_modules/"))
208877
208954
  continue;
208878
- const rel = relative12(process.cwd(), file4).replace(/\\/g, "/");
208955
+ const rel = relative13(process.cwd(), file4).replace(/\\/g, "/");
208879
208956
  warmCache2(`${SRC_URL_PREFIX2}${rel}`);
208880
208957
  }
208881
208958
  };
@@ -208903,7 +208980,7 @@ var patchManifestIndexes = (manifest, devIndexDir, SRC_URL_PREFIX2) => {
208903
208980
  const srcPath = resolve34(devIndexDir, fileName);
208904
208981
  if (!existsSync23(srcPath))
208905
208982
  continue;
208906
- const rel = relative12(process.cwd(), srcPath).replace(/\\/g, "/");
208983
+ const rel = relative13(process.cwd(), srcPath).replace(/\\/g, "/");
208907
208984
  manifest[key] = `${SRC_URL_PREFIX2}${rel}`;
208908
208985
  }
208909
208986
  };
@@ -209009,7 +209086,7 @@ var prepare = async (configOrPath) => {
209009
209086
  const buildDir = resolve34(isDev3 ? config.buildDirectory ?? "build" : process.env.ABSOLUTE_BUILD_DIR ?? config.buildDirectory ?? "build");
209010
209087
  if (isDev3)
209011
209088
  return prepareDev(config, buildDir);
209012
- const manifest = JSON.parse(readFileSync15(`${buildDir}/manifest.json`, "utf-8"));
209089
+ const manifest = JSON.parse(readFileSync16(`${buildDir}/manifest.json`, "utf-8"));
209013
209090
  setCurrentIslandManifest(manifest);
209014
209091
  if (config.islands?.registry) {
209015
209092
  setCurrentIslandRegistry(await loadIslandRegistry(config.islands.registry));
@@ -209017,7 +209094,7 @@ var prepare = async (configOrPath) => {
209017
209094
  setCurrentPageIslandMetadata(await loadPageIslandMetadata(config));
209018
209095
  const conventionsPath = join22(buildDir, "conventions.json");
209019
209096
  if (existsSync23(conventionsPath)) {
209020
- const conventions2 = JSON.parse(readFileSync15(conventionsPath, "utf-8"));
209097
+ const conventions2 = JSON.parse(readFileSync16(conventionsPath, "utf-8"));
209021
209098
  setConventions(conventions2);
209022
209099
  }
209023
209100
  const { staticPlugin } = await import("@elysiajs/static");
@@ -209277,7 +209354,7 @@ var jsonLd2 = (schema) => {
209277
209354
  };
209278
209355
  // src/utils/defineEnv.ts
209279
209356
  var {env: bunEnv } = globalThis.Bun;
209280
- import { existsSync as existsSync25, readFileSync as readFileSync17 } from "fs";
209357
+ import { existsSync as existsSync25, readFileSync as readFileSync18 } from "fs";
209281
209358
  import { resolve as resolve35 } from "path";
209282
209359
 
209283
209360
  // node_modules/@sinclair/typebox/build/esm/type/guard/value.mjs
@@ -215319,13 +215396,13 @@ var checkEnvFileSecurity = (properties) => {
215319
215396
  const sensitiveKeys = Object.keys(properties).filter(isSensitive);
215320
215397
  if (sensitiveKeys.length === 0)
215321
215398
  return;
215322
- const envContent = readFileSync17(envPath, "utf-8");
215399
+ const envContent = readFileSync18(envPath, "utf-8");
215323
215400
  const presentKeys = sensitiveKeys.filter((key) => envContent.includes(`${key}=`));
215324
215401
  if (presentKeys.length === 0)
215325
215402
  return;
215326
215403
  const gitignorePath = resolve35(cwd2, ".gitignore");
215327
215404
  if (existsSync25(gitignorePath)) {
215328
- const gitignore = readFileSync17(gitignorePath, "utf-8");
215405
+ const gitignore = readFileSync18(gitignorePath, "utf-8");
215329
215406
  if (gitignore.split(`
215330
215407
  `).some((line) => line.trim() === ".env"))
215331
215408
  return;
@@ -215445,5 +215522,5 @@ export {
215445
215522
  ANGULAR_INIT_TIMEOUT_MS
215446
215523
  };
215447
215524
 
215448
- //# debugId=F5D0915C24474B6D64756E2164756E21
215525
+ //# debugId=AAE980E3D30DAA4E64756E2164756E21
215449
215526
  //# sourceMappingURL=index.js.map