@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/build.js +201 -126
- package/dist/build.js.map +6 -6
- package/dist/cli/index.js +74 -2
- package/dist/index.js +1949 -1872
- package/dist/index.js.map +22 -22
- package/dist/src/build/staticIslandPages.d.ts +3 -0
- package/dist/types/globals.d.ts +20 -0
- package/dist/types/island.d.ts +0 -7
- package/package.json +1 -1
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, "&").replace(/</g, "<").replace(/>/g, ">")}</pre>
|
|
285
|
-
<div class="hint">A component threw during server-side rendering. Check the terminal for the full stack trace.</div>
|
|
286
|
-
</div>
|
|
287
|
-
</div>
|
|
288
|
-
</body>
|
|
289
|
-
</html>`;
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
// src/utils/stringModifiers.ts
|
|
293
|
-
var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9\-_]+/g, "").replace(/[-_]{2,}/g, "-"), toKebab = (str) => normalizeSlug(str).replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), toPascal = (str) => {
|
|
294
|
-
if (!str.includes("-") && !str.includes("_")) {
|
|
295
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
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(/"/g, '"').replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</style>`;
|
|
352
|
-
return "";
|
|
353
|
-
});
|
|
354
|
-
return { body, styles };
|
|
355
|
-
}, renderVueError = async (conventionPath, errorProps) => {
|
|
356
|
-
const { createSSRApp, h } = await import("vue");
|
|
357
|
-
const { renderToString } = await import("vue/server-renderer");
|
|
358
|
-
const mod = await import(conventionPath);
|
|
359
|
-
const ErrorComponent = mod.default;
|
|
360
|
-
const app = createSSRApp({
|
|
361
|
-
render: () => h(ErrorComponent, errorProps)
|
|
362
|
-
});
|
|
363
|
-
const rawBody = await renderToString(app);
|
|
364
|
-
const { styles, body } = unescapeVueStyles(rawBody);
|
|
365
|
-
const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
|
|
366
|
-
return new Response(html, {
|
|
367
|
-
headers: { "Content-Type": "text/html" },
|
|
368
|
-
status: 500
|
|
369
|
-
});
|
|
370
|
-
}, renderAngularError = async (conventionPath, errorProps) => {
|
|
371
|
-
const mod = await import(conventionPath);
|
|
372
|
-
const renderError = mod.default ?? mod.renderError;
|
|
373
|
-
if (typeof renderError !== "function")
|
|
374
|
-
return null;
|
|
375
|
-
const html = renderError(errorProps);
|
|
376
|
-
return new Response(html, {
|
|
377
|
-
headers: { "Content-Type": "text/html" },
|
|
378
|
-
status: 500
|
|
379
|
-
});
|
|
380
|
-
}, logConventionRenderError = (framework, label, renderError) => {
|
|
381
|
-
const message = renderError instanceof Error ? renderError.message : "";
|
|
382
|
-
if (message.includes("Cannot find module") || message.includes("Cannot find package") || message.includes("not found in module")) {
|
|
383
|
-
console.error(`[SSR] Convention ${label} page for ${framework} failed: missing framework package. Ensure the ${framework} runtime is installed (e.g. bun add ${framework === "react" ? "react react-dom" : framework}).`);
|
|
384
|
-
return;
|
|
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
|
|
1588
|
-
import { dirname
|
|
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
|
-
|
|
242
|
+
writeFileSync(chunkPath, patched, "utf-8");
|
|
1623
243
|
}, resolveAngularCoreDir = () => {
|
|
1624
|
-
const fromProject =
|
|
1625
|
-
if (
|
|
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
|
|
248
|
+
return dirname(__require.resolve("@angular/core/package.json"));
|
|
1629
249
|
}, patchAngularInjectorSingleton = () => {
|
|
1630
250
|
try {
|
|
1631
251
|
const coreDir = resolveAngularCoreDir();
|
|
1632
|
-
const chunkPath =
|
|
1633
|
-
const content =
|
|
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
|
|
1643
|
-
import { resolve as
|
|
262
|
+
import { existsSync as existsSync2 } from "fs";
|
|
263
|
+
import { resolve as resolve2 } from "path";
|
|
1644
264
|
var resolveAngularPackage = (specifier) => {
|
|
1645
|
-
const fromProject =
|
|
1646
|
-
if (
|
|
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(
|
|
3282
|
-
this.file =
|
|
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(
|
|
5176
|
-
this.file =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
22380
|
-
const start = new ParseLocation(
|
|
22381
|
-
const end = computeEndLocation(
|
|
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(
|
|
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(
|
|
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
|
|
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),
|
|
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
|
|
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),
|
|
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("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">"), 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, "&").replace(/</g, "<").replace(/>/g, ">")}</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(/"/g, '"').replace(/&/g, "&").replace(/</g, "<").replace(/>/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
|
-
|
|
31369
|
-
|
|
31370
|
-
|
|
31371
|
-
|
|
31372
|
-
|
|
31373
|
-
|
|
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
|
-
|
|
31393
|
-
|
|
31394
|
-
|
|
31395
|
-
|
|
31396
|
-
|
|
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
|
|
31400
|
-
|
|
31401
|
-
|
|
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/
|
|
31405
|
-
|
|
31406
|
-
|
|
31407
|
-
|
|
31408
|
-
|
|
31409
|
-
|
|
31410
|
-
|
|
31411
|
-
|
|
31412
|
-
|
|
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
|
-
|
|
31415
|
-
const
|
|
31416
|
-
|
|
31417
|
-
|
|
31418
|
-
|
|
31419
|
-
|
|
31420
|
-
|
|
31421
|
-
|
|
31422
|
-
|
|
31423
|
-
|
|
31424
|
-
|
|
31425
|
-
|
|
31426
|
-
|
|
31427
|
-
|
|
31428
|
-
|
|
31429
|
-
|
|
31430
|
-
|
|
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
|
-
|
|
31434
|
-
|
|
31435
|
-
|
|
31436
|
-
|
|
31437
|
-
|
|
31438
|
-
|
|
31439
|
-
|
|
31440
|
-
|
|
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
|
-
|
|
31443
|
-
|
|
31110
|
+
}, generateIslandBindings = (projectRoot, config) => {
|
|
31111
|
+
const registryPath = config.islands?.registry;
|
|
31112
|
+
if (!registryPath) {
|
|
31113
|
+
return;
|
|
31444
31114
|
}
|
|
31445
|
-
|
|
31446
|
-
|
|
31447
|
-
|
|
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
|
-
|
|
31450
|
-
|
|
31451
|
-
|
|
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
|
-
|
|
31454
|
-
|
|
31455
|
-
|
|
31456
|
-
|
|
31457
|
-
|
|
31458
|
-
|
|
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
|
-
|
|
31464
|
-
|
|
31465
|
-
|
|
31466
|
-
|
|
31467
|
-
|
|
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
|
-
|
|
31470
|
-
|
|
31471
|
-
|
|
31472
|
-
|
|
31473
|
-
|
|
31474
|
-
|
|
31475
|
-
|
|
31476
|
-
|
|
31477
|
-
|
|
31478
|
-
|
|
31479
|
-
|
|
31480
|
-
|
|
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
|
-
|
|
31488
|
-
|
|
31489
|
-
|
|
31490
|
-
|
|
31491
|
-
|
|
31492
|
-
|
|
31493
|
-
|
|
31494
|
-
|
|
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
|
-
|
|
31497
|
-
|
|
31498
|
-
|
|
31499
|
-
|
|
31500
|
-
|
|
31501
|
-
|
|
31502
|
-
|
|
31503
|
-
|
|
31504
|
-
|
|
31505
|
-
|
|
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
|
-
|
|
31508
|
-
|
|
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
|
-
|
|
31511
|
-
|
|
31512
|
-
|
|
31513
|
-
|
|
31514
|
-
|
|
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
|
|
31517
|
-
|
|
31518
|
-
|
|
31519
|
-
|
|
31520
|
-
|
|
31521
|
-
|
|
31522
|
-
|
|
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/
|
|
31527
|
-
var
|
|
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("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">"), 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/
|
|
31540
|
-
var
|
|
31541
|
-
|
|
31542
|
-
|
|
31543
|
-
}
|
|
31544
|
-
|
|
31545
|
-
|
|
31546
|
-
|
|
31547
|
-
|
|
31548
|
-
|
|
31549
|
-
|
|
31550
|
-
|
|
31551
|
-
return
|
|
31552
|
-
|
|
31553
|
-
|
|
31554
|
-
|
|
31555
|
-
|
|
31556
|
-
|
|
31557
|
-
|
|
31558
|
-
const
|
|
31559
|
-
|
|
31560
|
-
|
|
31561
|
-
const
|
|
31562
|
-
|
|
31563
|
-
|
|
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
|
-
|
|
31566
|
-
const
|
|
31567
|
-
|
|
31568
|
-
|
|
31569
|
-
|
|
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
|
-
|
|
31585
|
-
|
|
31586
|
-
const
|
|
31587
|
-
|
|
31588
|
-
|
|
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
|
-
|
|
31591
|
-
|
|
31592
|
-
|
|
31593
|
-
|
|
31594
|
-
|
|
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
|
-
|
|
31597
|
-
|
|
31598
|
-
|
|
31599
|
-
|
|
31600
|
-
|
|
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
|
-
|
|
31603
|
-
|
|
31604
|
-
const
|
|
31605
|
-
const
|
|
31606
|
-
|
|
31607
|
-
|
|
31608
|
-
|
|
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
|
-
|
|
31616
|
-
|
|
31617
|
-
|
|
31618
|
-
|
|
31619
|
-
|
|
31620
|
-
|
|
31621
|
-
|
|
31622
|
-
|
|
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
|
-
|
|
31625
|
-
|
|
31626
|
-
|
|
31627
|
-
|
|
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
|
-
|
|
31630
|
-
|
|
31631
|
-
|
|
31697
|
+
indexContentCache.set(indexPath, contentHash);
|
|
31698
|
+
await writeFile(indexPath, content);
|
|
31699
|
+
});
|
|
31700
|
+
await Promise.all(promises);
|
|
31701
|
+
if (!isDev2) {
|
|
31702
|
+
return;
|
|
31632
31703
|
}
|
|
31633
|
-
|
|
31634
|
-
|
|
31635
|
-
|
|
31636
|
-
|
|
31637
|
-
|
|
31638
|
-
|
|
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
|
|
31653
|
-
|
|
31654
|
-
|
|
31655
|
-
|
|
31656
|
-
|
|
31657
|
-
|
|
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/
|
|
31662
|
-
import {
|
|
31663
|
-
var
|
|
31664
|
-
|
|
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
|
-
|
|
31690
|
-
|
|
31726
|
+
const framework = packageToFramework[specifier];
|
|
31727
|
+
const frameworkDir = frameworkDirs[framework];
|
|
31728
|
+
if (!frameworkDir) {
|
|
31729
|
+
return null;
|
|
31691
31730
|
}
|
|
31692
|
-
|
|
31693
|
-
|
|
31731
|
+
const normalizedImporter = normalize(importer);
|
|
31732
|
+
const normalizedFrameworkDir = normalize(resolve10(frameworkDir));
|
|
31733
|
+
if (!normalizedImporter.startsWith(normalizedFrameworkDir)) {
|
|
31734
|
+
return null;
|
|
31694
31735
|
}
|
|
31695
|
-
|
|
31696
|
-
|
|
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
|
-
|
|
31704
|
-
|
|
31705
|
-
|
|
31706
|
-
|
|
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
|
-
|
|
31709
|
-
|
|
31710
|
-
|
|
31711
|
-
|
|
31712
|
-
|
|
31713
|
-
}
|
|
31714
|
-
|
|
31715
|
-
|
|
31716
|
-
|
|
31717
|
-
|
|
31718
|
-
|
|
31719
|
-
|
|
31720
|
-
|
|
31721
|
-
|
|
31722
|
-
|
|
31723
|
-
|
|
31724
|
-
|
|
31725
|
-
|
|
31726
|
-
|
|
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
|
-
|
|
31729
|
-
|
|
31730
|
-
|
|
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
|
-
|
|
31733
|
-
|
|
31734
|
-
|
|
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
|
-
|
|
31737
|
-
|
|
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
|
|
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(
|
|
31954
|
-
const buffer =
|
|
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
|
|
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 =
|
|
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
|
|
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(
|
|
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
|
|
32401
|
-
import { dirname as dirname7, join as join8, relative as
|
|
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:
|
|
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:
|
|
32444
|
-
relative:
|
|
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
|
|
32486
|
-
const absolute = resolve15(buildPath,
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
32724
|
-
const relDir = rawRel.startsWith("..") ? `_ext/${
|
|
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 =
|
|
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 =
|
|
32749
|
-
const toClient2 =
|
|
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 =
|
|
32759
|
-
const toClient =
|
|
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/${
|
|
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(
|
|
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 =
|
|
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(
|
|
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
|
|
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) =>
|
|
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 =
|
|
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 =
|
|
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,
|
|
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 "${
|
|
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 =
|
|
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
|
|
42246
|
+
const relative9 = [];
|
|
42172
42247
|
for (;start < fromComponents.length; start++) {
|
|
42173
|
-
|
|
42248
|
+
relative9.push("..");
|
|
42174
42249
|
}
|
|
42175
|
-
return ["", ...
|
|
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
|
|
79546
|
+
const relative9 = getRelativePathFromDirectory(realPathDirectory, target, getCanonicalFileName);
|
|
79472
79547
|
for (const symlinkDirectory of symlinkDirectories) {
|
|
79473
|
-
const option = resolvePath(symlinkDirectory,
|
|
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
|
|
202039
|
-
import { join as join13, basename as basename6, sep as sep3, dirname as dirname10, resolve as resolve20, relative as
|
|
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 =
|
|
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(
|
|
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 =
|
|
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:
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
203022
|
+
const pagesRel = relative10(process.cwd(), resolve21(reactPagesPath)).replace(/\\/g, "/");
|
|
202948
203023
|
for (const file4 of indexFiles) {
|
|
202949
|
-
let content =
|
|
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 =
|
|
202962
|
-
const srcRel =
|
|
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 =
|
|
202975
|
-
const srcRel =
|
|
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 =
|
|
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 =
|
|
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), `/${
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
204134
|
+
const content = readFileSync12(filePath, "utf-8");
|
|
204060
204135
|
return extractJsDependencies(filePath, content, loader);
|
|
204061
204136
|
}
|
|
204062
204137
|
if (isSvelteOrVue) {
|
|
204063
|
-
const content =
|
|
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
|
|
204604
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
204530
204605
|
var computeFileHash = (filePath) => {
|
|
204531
204606
|
try {
|
|
204532
|
-
const fileContent =
|
|
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
|
|
205291
|
-
import { basename as basename10, dirname as dirname13, extname as extname5, resolve as resolve28, relative as
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
205463
|
+
const rel2 = relative11(projectRoot, absPath).replace(/\\/g, "/");
|
|
205389
205464
|
return `${prefix}${srcUrl(rel2, projectRoot)}${suffix}`;
|
|
205390
205465
|
}
|
|
205391
|
-
const rel =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
205669
|
+
const cssUrl = srcUrl(relative11(projectRoot, cssPath), projectRoot);
|
|
205595
205670
|
code = `import "${cssUrl}";
|
|
205596
205671
|
${code}`;
|
|
205597
205672
|
}
|
|
205598
|
-
const moduleUrl = `${SRC_PREFIX}${
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 ?
|
|
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:
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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:
|
|
208645
|
-
key:
|
|
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
|
-
|
|
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
|
|
208798
|
-
import { basename as basename12, join as join22, relative as
|
|
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 =
|
|
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
|
|
208814
|
-
var
|
|
208815
|
-
var
|
|
208816
|
-
if (
|
|
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 (
|
|
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) =>
|
|
208823
|
-
var isIslandRegistryInput = (value) =>
|
|
208899
|
+
var isRegistryModuleExport = (value) => isRecord5(value);
|
|
208900
|
+
var isIslandRegistryInput = (value) => isRecord5(value);
|
|
208824
208901
|
var loadIslandRegistry = async (registryPath) => {
|
|
208825
|
-
const resolvedRegistryPath =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
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
|
|
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 =
|
|
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 =
|
|
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=
|
|
215525
|
+
//# debugId=AAE980E3D30DAA4E64756E2164756E21
|
|
215449
215526
|
//# sourceMappingURL=index.js.map
|