atollic 0.0.2 → 0.0.3
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/README.md +43 -7
- package/dist/adapter.d.ts +16 -0
- package/dist/adapters/solid.js +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -2
- package/dist/{server-DhToIUB0.js → server-DAuZqGuP.js} +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/servers/elysia.js +2 -2
- package/dist/servers/hono.js +2 -2
- package/dist/shared-Bv39_NsU.js +39 -0
- package/dist/shared.d.ts +17 -2
- package/dist/vite.js +88 -74
- package/package.json +1 -1
- package/dist/shared-CfRCLggd.js +0 -23
package/README.md
CHANGED
|
@@ -126,7 +126,9 @@ const app = new Elysia()
|
|
|
126
126
|
export default app.handle;
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
-
The Elysia adapter intercepts responses via `mapResponse`, extracts HTML
|
|
129
|
+
The Elysia adapter intercepts responses via `mapResponse`, extracts HTML, ensures DOCTYPE, and injects production assets.
|
|
130
|
+
|
|
131
|
+
The HTML-extraction step is **registry-based** — each `FrameworkAdapter` contributes an extractor function (via the `extractHtml` field) that knows how to convert its framework's SSR output (e.g. Solid's `{ t: "..." }` shape) into a plain HTML string. The atollic Vite plugin wires these registrations up automatically before the first request, so the core stays framework-agnostic. Plain strings are always recognized as a fallback. See [Writing a framework adapter](#writing-a-framework-adapter) and the [`registerHtmlExtractor`](#atollic) API.
|
|
130
132
|
|
|
131
133
|
### Hono
|
|
132
134
|
|
|
@@ -280,9 +282,9 @@ Listen to lifecycle events on `document`:
|
|
|
280
282
|
| `atollic:before-morph` | `{ newDoc, mountedIslands }` | Cancelable, before HMR page morph |
|
|
281
283
|
| `atollic:after-morph` | `{ defaultSwap }` | After HMR page morph |
|
|
282
284
|
|
|
283
|
-
## htmx
|
|
285
|
+
## htmx, Alpine, and other DOM-mutating libraries
|
|
284
286
|
|
|
285
|
-
Islands
|
|
287
|
+
Islands added to the DOM after the initial mount — by htmx swaps, Alpine templates, or any other source — are picked up automatically. The client runtime installs a `MutationObserver` on `document.body` and mounts any newly inserted `[data-island]` element. No library-specific event listener is required.
|
|
286
288
|
|
|
287
289
|
## CSS handling
|
|
288
290
|
|
|
@@ -348,10 +350,22 @@ export function myFramework(): FrameworkAdapter {
|
|
|
348
350
|
|
|
349
351
|
// Optional: script tag for hydration bootstrap (e.g., Solid's _$HY)
|
|
350
352
|
hydrationScript: `<script>/* bootstrap */</script>`,
|
|
353
|
+
|
|
354
|
+
// Optional: source code for an extractor function `(value) => string | null`.
|
|
355
|
+
// Atollic includes this in the server boot module so the runtime knows
|
|
356
|
+
// how to convert this framework's SSR output (e.g. Solid's `{ t: "..." }`
|
|
357
|
+
// shape) into a plain HTML string. Frameworks whose SSR output is already
|
|
358
|
+
// a string can omit this — plain strings are always recognized.
|
|
359
|
+
extractHtml: `(value) => {
|
|
360
|
+
if (value && typeof value === "object" && "t" in value) return value.t;
|
|
361
|
+
return null;
|
|
362
|
+
}`,
|
|
351
363
|
};
|
|
352
364
|
}
|
|
353
365
|
```
|
|
354
366
|
|
|
367
|
+
The `extractHtml` strings from every registered adapter are emitted into a generated server-boot module that runs once before the first request. Each one calls `registerHtmlExtractor()` on the atollic core, which `extractHtml` (used internally by the Elysia and Hono adapters) iterates in order. This is how the core stays decoupled from any specific UI framework's SSR output shape.
|
|
368
|
+
|
|
355
369
|
## API reference
|
|
356
370
|
|
|
357
371
|
### `atollic/vite`
|
|
@@ -368,9 +382,20 @@ atollic(options: AtollicOptions): Plugin[]
|
|
|
368
382
|
### `atollic`
|
|
369
383
|
|
|
370
384
|
```ts
|
|
371
|
-
|
|
385
|
+
// Wrap an HTML string (or async JSX) in a Response with DOCTYPE.
|
|
386
|
+
// Returns a Promise<Response> when given a Promise<string>.
|
|
387
|
+
html(input: string | Promise<string>): Response | Promise<Response>
|
|
388
|
+
|
|
372
389
|
setProductionAssets(assets: string): void // Set production asset tags
|
|
373
390
|
getProductionAssets(): string | undefined // Get production asset tags
|
|
391
|
+
|
|
392
|
+
// Register a function that converts a framework-specific SSR output value
|
|
393
|
+
// into an HTML string (or returns null if it doesn't recognize the shape).
|
|
394
|
+
// Normally wired up automatically by the Vite plugin from each adapter's
|
|
395
|
+
// `extractHtml` field — call this directly only if you need a custom one.
|
|
396
|
+
// Returns a dispose function.
|
|
397
|
+
type HtmlExtractor = (value: unknown) => string | null
|
|
398
|
+
registerHtmlExtractor(fn: HtmlExtractor): () => void
|
|
374
399
|
```
|
|
375
400
|
|
|
376
401
|
### `atollic/elysia`
|
|
@@ -402,15 +427,26 @@ solid(): FrameworkAdapter // Solid.js framework adapter
|
|
|
402
427
|
Types for server-side JSX:
|
|
403
428
|
|
|
404
429
|
```ts
|
|
405
|
-
type
|
|
406
|
-
|
|
430
|
+
type Children =
|
|
431
|
+
| string
|
|
432
|
+
| number
|
|
433
|
+
| bigint
|
|
434
|
+
| boolean
|
|
435
|
+
| null
|
|
436
|
+
| undefined
|
|
437
|
+
| Promise<Children>
|
|
438
|
+
| Children[]
|
|
439
|
+
|
|
440
|
+
type Component<T = {}> = (
|
|
441
|
+
props: T & { children?: Children },
|
|
442
|
+
) => string | Promise<string>
|
|
407
443
|
```
|
|
408
444
|
|
|
409
445
|
## Exports
|
|
410
446
|
|
|
411
447
|
| Export | Description |
|
|
412
448
|
|---|---|
|
|
413
|
-
| `atollic` | Core — `html()`, `setProductionAssets()`, `getProductionAssets()` |
|
|
449
|
+
| `atollic` | Core — `html()`, `setProductionAssets()`, `getProductionAssets()`, `registerHtmlExtractor()` |
|
|
414
450
|
| `atollic/vite` | Vite plugin |
|
|
415
451
|
| `atollic/client` | Client runtime (auto-imported) |
|
|
416
452
|
| `atollic/adapter` | `FrameworkAdapter` type |
|
package/dist/adapter.d.ts
CHANGED
|
@@ -36,4 +36,20 @@ export interface FrameworkAdapter {
|
|
|
36
36
|
* can omit this.
|
|
37
37
|
*/
|
|
38
38
|
hydrationScript?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Source code for an extractor function with the signature
|
|
41
|
+
* `(value: unknown) => string | null`.
|
|
42
|
+
*
|
|
43
|
+
* The atollic Vite plugin includes this in the server boot module so the
|
|
44
|
+
* runtime knows how to convert this framework's SSR output (e.g. Solid's
|
|
45
|
+
* `{ t: "..." }` shape) into a plain HTML string. Frameworks whose SSR
|
|
46
|
+
* output is already a string can omit this — the core falls back to
|
|
47
|
+
* recognizing plain strings on its own.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* extractHtml: `(value) => value && typeof value === "object" && "t" in value
|
|
51
|
+
* ? value.t
|
|
52
|
+
* : null`
|
|
53
|
+
*/
|
|
54
|
+
extractHtml?: string;
|
|
39
55
|
}
|
package/dist/adapters/solid.js
CHANGED
|
@@ -30,7 +30,8 @@ function n() {
|
|
|
30
30
|
return a;
|
|
31
31
|
},
|
|
32
32
|
clientRuntime: "\nimport { hydrate as _hydrate, render as _render } from \"solid-js/web\";\nimport { $DEVCOMP } from \"solid-js\";\n\nexport function hydrateIsland(el, Component, props, id) {\n if ($DEVCOMP && !($DEVCOMP in Component)) {\n Component[$DEVCOMP] = true;\n }\n return _hydrate(() => Component(props), el, { renderId: id });\n}\n\nexport function renderIsland(el, Component, props) {\n if ($DEVCOMP && !($DEVCOMP in Component)) {\n Component[$DEVCOMP] = true;\n }\n el.textContent = \"\";\n return _render(() => Component(props), el);\n}\n",
|
|
33
|
-
hydrationScript: "<script>(self._$HY||(self._$HY={events:[],completed:new WeakSet,r:{}}))<\/script>"
|
|
33
|
+
hydrationScript: "<script>(self._$HY||(self._$HY={events:[],completed:new WeakSet,r:{}}))<\/script>",
|
|
34
|
+
extractHtml: "(value) => {\n if (value && typeof value === \"object\" && \"t\" in value && typeof value.t === \"string\") {\n return value.t;\n }\n if (Array.isArray(value)) {\n const html = value.flat(Infinity).map((item) => {\n if (typeof item === \"string\") return item;\n if (item && typeof item === \"object\" && \"t\" in item) return item.t;\n return \"\";\n }).join(\"\");\n return html || null;\n }\n return null;\n}"
|
|
34
35
|
};
|
|
35
36
|
}
|
|
36
37
|
//#endregion
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export type { HtmlExtractor } from "./server.js";
|
|
2
|
+
export { getProductionAssets, html, registerHtmlExtractor, setProductionAssets, } from "./server.js";
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { o as e } from "./shared-Bv39_NsU.js";
|
|
2
|
+
import { n as t, r as n, t as r } from "./server-DAuZqGuP.js";
|
|
3
|
+
export { r as getProductionAssets, t as html, e as registerHtmlExtractor, n as setProductionAssets };
|
package/dist/server.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Server-side helpers for atollic.
|
|
3
3
|
*/
|
|
4
|
+
export type { HtmlExtractor } from "./shared.js";
|
|
5
|
+
export { registerHtmlExtractor } from "./shared.js";
|
|
4
6
|
/**
|
|
5
7
|
* Set the production asset tags (scripts + CSS) to inject into HTML responses.
|
|
6
8
|
* Called by the generated production entry before the server starts.
|
package/dist/servers/elysia.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as e, i as t, n } from "../shared-
|
|
2
|
-
import { t as r } from "../server-
|
|
1
|
+
import { a as e, i as t, n } from "../shared-Bv39_NsU.js";
|
|
2
|
+
import { t as r } from "../server-DAuZqGuP.js";
|
|
3
3
|
import { Elysia as i } from "elysia";
|
|
4
4
|
//#region src/servers/elysia.ts
|
|
5
5
|
function a() {
|
package/dist/servers/hono.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as e, i as t } from "../shared-
|
|
2
|
-
import { t as n } from "../server-
|
|
1
|
+
import { a as e, i as t } from "../shared-Bv39_NsU.js";
|
|
2
|
+
import { t as n } from "../server-DAuZqGuP.js";
|
|
3
3
|
//#region src/servers/hono.ts
|
|
4
4
|
function r() {
|
|
5
5
|
return async (r, i) => {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//#region src/shared.ts
|
|
2
|
+
var e = /<meta\s+name="atollic-head"\s*\/?>/;
|
|
3
|
+
function t(t, n) {
|
|
4
|
+
let r = t.replace(e, n);
|
|
5
|
+
return r === t ? t.includes("</head>") ? t.replace("</head>", ` ${n}\n</head>`) : t : r;
|
|
6
|
+
}
|
|
7
|
+
var n = "__atollicHtmlExtractors";
|
|
8
|
+
function r() {
|
|
9
|
+
let e = globalThis;
|
|
10
|
+
return Array.isArray(e[n]) || (e[n] = []), e[n];
|
|
11
|
+
}
|
|
12
|
+
function i(e) {
|
|
13
|
+
let t = r();
|
|
14
|
+
return t.push(e), () => {
|
|
15
|
+
let n = t.indexOf(e);
|
|
16
|
+
n >= 0 && t.splice(n, 1);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function a(e) {
|
|
20
|
+
for (let t of r()) {
|
|
21
|
+
let n = t(e);
|
|
22
|
+
if (n !== null) return n;
|
|
23
|
+
}
|
|
24
|
+
return typeof e == "string" ? e : null;
|
|
25
|
+
}
|
|
26
|
+
function o(e) {
|
|
27
|
+
let t = e.trimStart();
|
|
28
|
+
return t.startsWith("<html") && !t.startsWith("<!DOCTYPE") ? `<!DOCTYPE html>\n${e}` : e;
|
|
29
|
+
}
|
|
30
|
+
function s(e) {
|
|
31
|
+
let t = e.trimStart();
|
|
32
|
+
return t.startsWith("<!DOCTYPE") || t.startsWith("<html");
|
|
33
|
+
}
|
|
34
|
+
function c(e, n) {
|
|
35
|
+
let r = o(e);
|
|
36
|
+
return n && (r = t(r, n)), r;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { c as a, s as i, a as n, i as o, t as r, o as t };
|
package/dist/shared.d.ts
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
/** Replace <Head /> marker with tags, or fall back to </head> injection. */
|
|
2
2
|
export declare function injectHead(html: string, tags: string): string;
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* A function that converts a framework-specific SSR output value into an HTML
|
|
5
|
+
* string, or returns `null` if it doesn't recognize the shape.
|
|
6
|
+
*/
|
|
7
|
+
export type HtmlExtractor = (value: unknown) => string | null;
|
|
8
|
+
/**
|
|
9
|
+
* Register a function that extracts an HTML string from a framework-specific
|
|
10
|
+
* SSR output. The atollic Vite plugin wires this up automatically — every
|
|
11
|
+
* `FrameworkAdapter` with an `extractHtml` source string gets registered
|
|
12
|
+
* before the first request is served.
|
|
13
|
+
*
|
|
14
|
+
* @returns A dispose function that removes the extractor.
|
|
15
|
+
*/
|
|
16
|
+
export declare function registerHtmlExtractor(fn: HtmlExtractor): () => void;
|
|
17
|
+
/**
|
|
18
|
+
* Convert a server response value into an HTML string by trying each
|
|
19
|
+
* registered framework extractor, then falling back to a plain string.
|
|
20
|
+
* Returns `null` when nothing recognizes the shape.
|
|
6
21
|
*/
|
|
7
22
|
export declare function extractHtml(value: unknown): string | null;
|
|
8
23
|
/** Prepend DOCTYPE if the string looks like HTML but is missing it. */
|
package/dist/vite.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { i as e, n as t, r as n, t as r } from "./shared-
|
|
1
|
+
import { i as e, n as t, r as n, t as r } from "./shared-Bv39_NsU.js";
|
|
2
2
|
import { readFileSync as i } from "node:fs";
|
|
3
3
|
import { glob as a, readFile as o } from "node:fs/promises";
|
|
4
4
|
import { basename as s, dirname as c, extname as l, relative as u, resolve as d } from "node:path";
|
|
5
5
|
import { fileURLToPath as f } from "node:url";
|
|
6
6
|
import { transformWithOxc as p } from "vite";
|
|
7
7
|
//#region src/vite.ts
|
|
8
|
-
var m = c(f(import.meta.url)), h = "virtual:atollic/client", g = `\0${h}`, _ = "virtual:atollic/prod-entry", v = `\0${_}`, y = "virtual:atollic/
|
|
9
|
-
function
|
|
8
|
+
var m = c(f(import.meta.url)), h = "virtual:atollic/client", g = `\0${h}`, _ = "virtual:atollic/prod-entry", v = `\0${_}`, y = "virtual:atollic/server-boot", b = `\0${y}`, x = "virtual:atollic/fw-", S = "atollic:reload", C = "?raw-island", w = /\.[jt]sx?$/, T = /\.[jt]sx$/, E = /\.css($|\?)/;
|
|
9
|
+
function D(e) {
|
|
10
10
|
let t = e.replace(/^\s*(\/\*[\s\S]*?\*\/\s*|\/\/[^\n]*\n\s*)*/g, "").match(/^["']use client(?::(\w+))?["']/);
|
|
11
11
|
return t ? {
|
|
12
12
|
hasDirective: !0,
|
|
13
13
|
framework: t[1]
|
|
14
14
|
} : { hasDirective: !1 };
|
|
15
15
|
}
|
|
16
|
-
function
|
|
16
|
+
function O(e) {
|
|
17
17
|
return e.replace(/^["']use client(?::\w+)?["'];?\s*/m, "");
|
|
18
18
|
}
|
|
19
|
-
function
|
|
20
|
-
let n = [], r =
|
|
19
|
+
function k(e, t) {
|
|
20
|
+
let n = [], r = O(e), i = r.match(/export\s+default\s+(?:function|class)\s+([A-Z]\w*)/);
|
|
21
21
|
i ? n.push({
|
|
22
22
|
exportName: "default",
|
|
23
23
|
islandName: i[1]
|
|
@@ -31,7 +31,10 @@ function D(e, t) {
|
|
|
31
31
|
});
|
|
32
32
|
return n;
|
|
33
33
|
}
|
|
34
|
-
function
|
|
34
|
+
function A(e) {
|
|
35
|
+
return e.map((e) => e.extractHtml).filter((e) => !!e).map((e) => `registerHtmlExtractor(${e});`).join("\n");
|
|
36
|
+
}
|
|
37
|
+
function j(e, t, n, r) {
|
|
35
38
|
let i = [...n].map((e) => `import "${e}";`).join("\n"), a = [...t].map((e) => `import "/${u(r, e)}";`).join("\n"), o = /* @__PURE__ */ new Map();
|
|
36
39
|
for (let [t, n] of Object.entries(e)) {
|
|
37
40
|
let e = n.adapter.name;
|
|
@@ -40,7 +43,7 @@ function O(e, t, n, r) {
|
|
|
40
43
|
let s = "import { registerIsland, registerFramework, initRuntime } from \"atollic/client\";\n";
|
|
41
44
|
s += `${i}\n`, s += `${a}\n\n`;
|
|
42
45
|
for (let [e, t] of o) {
|
|
43
|
-
let n = `${
|
|
46
|
+
let n = `${x}${e}`;
|
|
44
47
|
s += `import { hydrateIsland as __hydrate_${e}, renderIsland as __render_${e} } from "${n}";\n`, s += `registerFramework("${e}", __hydrate_${e}, __render_${e});\n\n`;
|
|
45
48
|
for (let [n, i] of t) {
|
|
46
49
|
let t = `/${u(r, i.absPath)}`;
|
|
@@ -49,7 +52,7 @@ function O(e, t, n, r) {
|
|
|
49
52
|
}
|
|
50
53
|
return s += "\ninitRuntime();\n", s;
|
|
51
54
|
}
|
|
52
|
-
function
|
|
55
|
+
function M(e) {
|
|
53
56
|
let t = new URL(e.url ?? "/", `http://${e.headers.host || "localhost"}`), n = new Headers();
|
|
54
57
|
for (let [t, r] of Object.entries(e.headers)) if (r) if (Array.isArray(r)) for (let e of r) n.append(t, e);
|
|
55
58
|
else n.set(t, r);
|
|
@@ -61,48 +64,48 @@ function k(e) {
|
|
|
61
64
|
e.on("data", (e) => t.enqueue(e)), e.on("end", () => t.close()), e.on("error", (e) => t.error(e));
|
|
62
65
|
} }), r.duplex = "half"), new Request(t, r);
|
|
63
66
|
}
|
|
64
|
-
function
|
|
67
|
+
function N(e, t) {
|
|
65
68
|
let n = [];
|
|
66
69
|
if (t) for (let e of t) n.push(`<link rel="stylesheet" href="${e}">`);
|
|
67
70
|
for (let t of e) t.hydrationScript && n.push(t.hydrationScript);
|
|
68
71
|
return n.push(`<script type="module">import "${h}";<\/script>`), n.join("\n ");
|
|
69
72
|
}
|
|
70
|
-
function
|
|
73
|
+
function P(e, t) {
|
|
71
74
|
let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set();
|
|
72
75
|
function i(t) {
|
|
73
76
|
if (r.has(t)) return;
|
|
74
77
|
r.add(t);
|
|
75
78
|
let a = e.moduleGraph.getModuleById(t);
|
|
76
79
|
if (a) {
|
|
77
|
-
|
|
80
|
+
E.test(a.url) && n.add(a.url);
|
|
78
81
|
for (let e of a.ssrImportedModules) i(e.id ?? e.url);
|
|
79
82
|
}
|
|
80
83
|
}
|
|
81
84
|
let a = e.moduleGraph.getModuleById(t);
|
|
82
85
|
return a && i(a.id ?? a.url), n;
|
|
83
86
|
}
|
|
84
|
-
function
|
|
85
|
-
let f = u.frameworks ?? [],
|
|
86
|
-
function
|
|
87
|
-
return e ? f.find((t) => t.name === e) :
|
|
87
|
+
function F(u) {
|
|
88
|
+
let f = u.frameworks ?? [], E = f[0], F = "", I = {}, L = /* @__PURE__ */ new Set(), R = /* @__PURE__ */ new Set(), z = "", B = 3e3, V = null, H = "", U = !1, W = null;
|
|
89
|
+
function G(e) {
|
|
90
|
+
return e ? f.find((t) => t.name === e) : E;
|
|
88
91
|
}
|
|
89
|
-
function
|
|
90
|
-
if (!
|
|
91
|
-
let e =
|
|
92
|
-
e &&
|
|
92
|
+
function K() {
|
|
93
|
+
if (!V) return;
|
|
94
|
+
let e = V.moduleGraph.getModuleById(g);
|
|
95
|
+
e && V.moduleGraph.invalidateModule(e);
|
|
93
96
|
}
|
|
94
|
-
function
|
|
95
|
-
|
|
97
|
+
function q(e, t) {
|
|
98
|
+
I[t] || (I[t] = e, K());
|
|
96
99
|
}
|
|
97
|
-
function
|
|
98
|
-
let r =
|
|
99
|
-
for (let t of r)
|
|
100
|
+
function J(e, t, n) {
|
|
101
|
+
let r = k(t, s(e, l(e)));
|
|
102
|
+
for (let t of r) q({
|
|
100
103
|
absPath: e,
|
|
101
104
|
exportName: t.exportName,
|
|
102
105
|
adapter: n
|
|
103
106
|
}, t.islandName);
|
|
104
107
|
}
|
|
105
|
-
let
|
|
108
|
+
let Y = {
|
|
106
109
|
name: "atollic",
|
|
107
110
|
enforce: "pre",
|
|
108
111
|
sharedDuringBuild: !0,
|
|
@@ -129,31 +132,31 @@ function M(u) {
|
|
|
129
132
|
},
|
|
130
133
|
async buildApp(e) {
|
|
131
134
|
await e.build(e.environments.client);
|
|
132
|
-
let t = d(
|
|
135
|
+
let t = d(F, "dist/client/.vite/manifest.json"), n = JSON.parse(await o(t, "utf-8")), r = n.client ?? n["virtual:atollic/client"], i = [];
|
|
133
136
|
for (let e of Object.values(n)) if (e.css) for (let t of e.css) i.push(`<link rel="stylesheet" href="/${t}">`);
|
|
134
137
|
for (let e of f) e.hydrationScript && i.push(e.hydrationScript);
|
|
135
|
-
r && i.push(`<script type="module" src="/${r.file}"><\/script>`),
|
|
138
|
+
r && i.push(`<script type="module" src="/${r.file}"><\/script>`), H = i.join("\n "), await e.build(e.environments.ssr);
|
|
136
139
|
},
|
|
137
140
|
async configResolved(e) {
|
|
138
|
-
|
|
141
|
+
F = e.root, z = d(F, u.entry), B = e.server.port ?? 3e3;
|
|
139
142
|
},
|
|
140
143
|
async buildStart() {
|
|
141
|
-
if (
|
|
142
|
-
|
|
144
|
+
if (U) return;
|
|
145
|
+
U = !0;
|
|
143
146
|
let e = /import\s+['"]([^'"]+\.css)['"]/g, t = /import\s.*?from\s+['"](\.\.?\/[^'"]+)['"]/g, n = /* @__PURE__ */ new Set();
|
|
144
147
|
function r(t, n) {
|
|
145
|
-
let r =
|
|
146
|
-
if (r.hasDirective) if (
|
|
147
|
-
let e =
|
|
148
|
-
e ?
|
|
149
|
-
} else
|
|
150
|
-
for (let t of n.matchAll(e))
|
|
148
|
+
let r = D(n);
|
|
149
|
+
if (r.hasDirective) if (T.test(t)) {
|
|
150
|
+
let e = G(r.framework);
|
|
151
|
+
e ? J(t, n, e) : r.framework && console.warn(`[atollic] Unknown framework "${r.framework}" in ${t}`);
|
|
152
|
+
} else L.add(t);
|
|
153
|
+
for (let t of n.matchAll(e)) R.add(t[1]);
|
|
151
154
|
}
|
|
152
155
|
for await (let e of a("**/*.{ts,tsx,js,jsx}", {
|
|
153
|
-
cwd:
|
|
156
|
+
cwd: F,
|
|
154
157
|
exclude: ["node_modules/**", "dist/**"]
|
|
155
158
|
})) {
|
|
156
|
-
let t = d(
|
|
159
|
+
let t = d(F, e);
|
|
157
160
|
n.add(t);
|
|
158
161
|
try {
|
|
159
162
|
r(t, await o(t, "utf-8"));
|
|
@@ -183,23 +186,31 @@ function M(u) {
|
|
|
183
186
|
} catch {}
|
|
184
187
|
}
|
|
185
188
|
}
|
|
186
|
-
await i(
|
|
189
|
+
await i(z);
|
|
187
190
|
},
|
|
188
191
|
resolveId(e) {
|
|
189
192
|
if (e === h) return g;
|
|
190
193
|
if (e === _) return v;
|
|
191
|
-
if (e
|
|
192
|
-
if (e.
|
|
194
|
+
if (e === y) return b;
|
|
195
|
+
if (e.startsWith(x)) return `\0${e}`;
|
|
196
|
+
if (e.endsWith(C)) return `${e.slice(0, -11)}${C}`;
|
|
193
197
|
},
|
|
194
198
|
load(e, t) {
|
|
195
|
-
if (e === g) return
|
|
196
|
-
if (e ===
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
199
|
+
if (e === g) return j(I, L, R, F);
|
|
200
|
+
if (e === b) {
|
|
201
|
+
let e = d(m, "index.js"), t = A(f);
|
|
202
|
+
return t ? `import { registerHtmlExtractor } from "${e}";\n${t}\n` : "// no html extractors registered\n";
|
|
203
|
+
}
|
|
204
|
+
if (e === v) {
|
|
205
|
+
let e = d(m, "index.js"), t = A(f);
|
|
206
|
+
return `import { resolve, join } from "node:path";
|
|
207
|
+
import { setProductionAssets, registerHtmlExtractor } from "${e}";
|
|
208
|
+
setProductionAssets(${JSON.stringify(H)});
|
|
209
|
+
${t}
|
|
210
|
+
import handler from "${z}";
|
|
200
211
|
|
|
201
212
|
const clientDir = resolve(import.meta.dirname, "..", "client");
|
|
202
|
-
const port = process.env.PORT || ${
|
|
213
|
+
const port = process.env.PORT || ${B};
|
|
203
214
|
|
|
204
215
|
Bun.serve({
|
|
205
216
|
port,
|
|
@@ -215,45 +226,48 @@ Bun.serve({
|
|
|
215
226
|
});
|
|
216
227
|
console.log(\`Listening on http://localhost:\${port}\`);
|
|
217
228
|
`;
|
|
218
|
-
|
|
219
|
-
|
|
229
|
+
}
|
|
230
|
+
if (e.startsWith("\0" + x)) {
|
|
231
|
+
let t = e.slice(("\0" + x).length), n = f.find((e) => e.name === t);
|
|
220
232
|
if (n) return n.clientRuntime;
|
|
221
233
|
}
|
|
222
|
-
if (e.endsWith(
|
|
234
|
+
if (e.endsWith(C)) {
|
|
223
235
|
let t = e.slice(0, -11);
|
|
224
236
|
try {
|
|
225
|
-
return
|
|
237
|
+
return O(i(t, "utf-8"));
|
|
226
238
|
} catch {}
|
|
227
239
|
return;
|
|
228
240
|
}
|
|
229
|
-
if (!(!t?.ssr || !
|
|
230
|
-
let t = i(e, "utf-8"), n =
|
|
241
|
+
if (!(!t?.ssr || !w.test(e))) try {
|
|
242
|
+
let t = i(e, "utf-8"), n = D(t);
|
|
231
243
|
if (n.hasDirective) {
|
|
232
|
-
if (!
|
|
233
|
-
let r =
|
|
244
|
+
if (!T.test(e)) return L.add(e), K(), "export default {};";
|
|
245
|
+
let r = G(n.framework);
|
|
234
246
|
if (!r) {
|
|
235
247
|
n.framework && console.warn(`[atollic] Unknown framework "${n.framework}" in ${e}`);
|
|
236
248
|
return;
|
|
237
249
|
}
|
|
238
|
-
let i =
|
|
239
|
-
for (let t of i)
|
|
250
|
+
let i = k(t, s(e, l(e)));
|
|
251
|
+
for (let t of i) q({
|
|
240
252
|
absPath: e,
|
|
241
253
|
exportName: t.exportName,
|
|
242
254
|
adapter: r
|
|
243
255
|
}, t.islandName);
|
|
244
|
-
let a = `${e}${
|
|
256
|
+
let a = `${e}${C}`;
|
|
245
257
|
return r.ssrStub(a, i);
|
|
246
258
|
}
|
|
247
259
|
} catch {}
|
|
248
260
|
},
|
|
249
261
|
configureServer(i) {
|
|
250
|
-
|
|
262
|
+
V = i, i.ssrLoadModule(y).catch((e) => {
|
|
263
|
+
console.error("[atollic] Failed to load server boot module:", e);
|
|
264
|
+
}), i.middlewares.use(async (a, o, s) => {
|
|
251
265
|
let c = a.url || "";
|
|
252
266
|
if (c.startsWith("/@") || c.startsWith("/node_modules") || c.startsWith("/__") || /\.\w+($|\?)/.test(c)) return s();
|
|
253
267
|
try {
|
|
254
|
-
let l = await i.ssrLoadModule(
|
|
268
|
+
let l = await i.ssrLoadModule(z), u = l.default ?? l.handler;
|
|
255
269
|
if (typeof u != "function") return console.error("[atollic] Entry must default-export a fetch function: (req: Request) => Response"), s();
|
|
256
|
-
let d = await u(
|
|
270
|
+
let d = await u(M(a));
|
|
257
271
|
if (d.status === 404) return s();
|
|
258
272
|
let p = await d.text(), m = d.headers.get("content-type") || "";
|
|
259
273
|
if (m.includes("application/json")) try {
|
|
@@ -261,7 +275,7 @@ console.log(\`Listening on http://localhost:\${port}\`);
|
|
|
261
275
|
e && (p = e, m = "");
|
|
262
276
|
} catch {}
|
|
263
277
|
let h = e(p);
|
|
264
|
-
!m.includes("text/html") && h && (m = "text/html; charset=utf-8"), h && (p = r(p),
|
|
278
|
+
!m.includes("text/html") && h && (m = "text/html; charset=utf-8"), h && (p = r(p), W ||= P(i, z), p = n(p, N(f, W)), p = await i.transformIndexHtml(c, p));
|
|
265
279
|
let g = {};
|
|
266
280
|
for (let [e, t] of d.headers) g[e] = t;
|
|
267
281
|
m ? g["content-type"] = m : g["content-type"] ||= "text/html; charset=utf-8", o.writeHead(d.status, g), o.end(p);
|
|
@@ -271,23 +285,23 @@ console.log(\`Listening on http://localhost:\${port}\`);
|
|
|
271
285
|
});
|
|
272
286
|
},
|
|
273
287
|
handleHotUpdate({ file: e, server: t }) {
|
|
274
|
-
if (
|
|
288
|
+
if (W = null, !e.endsWith(".ts") && !e.endsWith(".tsx")) return;
|
|
275
289
|
try {
|
|
276
|
-
if (
|
|
290
|
+
if (D(i(e, "utf-8")).hasDirective) return;
|
|
277
291
|
} catch {}
|
|
278
292
|
let n = t.moduleGraph.getModulesByFile(e);
|
|
279
293
|
if (n) for (let e of n) t.moduleGraph.invalidateModule(e);
|
|
280
294
|
return t.ws.send({
|
|
281
295
|
type: "custom",
|
|
282
|
-
event:
|
|
296
|
+
event: S
|
|
283
297
|
}), [];
|
|
284
298
|
}
|
|
285
|
-
},
|
|
299
|
+
}, X = /@jsxImportSource\s+(\S+)/, Z = {
|
|
286
300
|
name: "atollic:jsx-pre-transform",
|
|
287
301
|
enforce: "pre",
|
|
288
302
|
async transform(e, t) {
|
|
289
303
|
if (!/\.[jt]sx$/.test(t)) return;
|
|
290
|
-
let n = e.match(
|
|
304
|
+
let n = e.match(X);
|
|
291
305
|
if (n) {
|
|
292
306
|
let e = n[1];
|
|
293
307
|
for (let t of f) if (e.includes(t.name)) return;
|
|
@@ -301,13 +315,13 @@ console.log(\`Listening on http://localhost:\${port}\`);
|
|
|
301
315
|
map: r.map
|
|
302
316
|
};
|
|
303
317
|
}
|
|
304
|
-
},
|
|
305
|
-
for (let e of f) e.plugins &&
|
|
318
|
+
}, Q = [];
|
|
319
|
+
for (let e of f) e.plugins && Q.push(...e.plugins());
|
|
306
320
|
return [
|
|
307
|
-
|
|
308
|
-
...
|
|
309
|
-
|
|
321
|
+
Z,
|
|
322
|
+
...Q,
|
|
323
|
+
Y
|
|
310
324
|
];
|
|
311
325
|
}
|
|
312
326
|
//#endregion
|
|
313
|
-
export {
|
|
327
|
+
export { F as atollic };
|
package/package.json
CHANGED
package/dist/shared-CfRCLggd.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
//#region src/shared.ts
|
|
2
|
-
var e = /<meta\s+name="atollic-head"\s*\/?>/;
|
|
3
|
-
function t(t, n) {
|
|
4
|
-
let r = t.replace(e, n);
|
|
5
|
-
return r === t ? t.includes("</head>") ? t.replace("</head>", ` ${n}\n</head>`) : t : r;
|
|
6
|
-
}
|
|
7
|
-
function n(e) {
|
|
8
|
-
return e && typeof e == "object" && "t" in e && typeof e.t == "string" ? e.t : Array.isArray(e) ? e.flat(Infinity).map((e) => typeof e == "string" ? e : e && typeof e == "object" && "t" in e ? e.t : "").join("") || null : typeof e == "string" ? e : null;
|
|
9
|
-
}
|
|
10
|
-
function r(e) {
|
|
11
|
-
let t = e.trimStart();
|
|
12
|
-
return t.startsWith("<html") && !t.startsWith("<!DOCTYPE") ? `<!DOCTYPE html>\n${e}` : e;
|
|
13
|
-
}
|
|
14
|
-
function i(e) {
|
|
15
|
-
let t = e.trimStart();
|
|
16
|
-
return t.startsWith("<!DOCTYPE") || t.startsWith("<html");
|
|
17
|
-
}
|
|
18
|
-
function a(e, n) {
|
|
19
|
-
let i = r(e);
|
|
20
|
-
return n && (i = t(i, n)), i;
|
|
21
|
-
}
|
|
22
|
-
//#endregion
|
|
23
|
-
export { a, i, n, t as r, r as t };
|