@ilha/router 0.10.2 → 0.10.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/dist/{plugin-Bh0y5kkI.js → plugin-DBbbaeFm.js} +4 -3
- package/dist/rsbuild.js +1 -1
- package/dist/server-island.d.ts +3 -3
- package/dist/server-island.js +10 -5
- package/dist/{ssr-CGcMUP1G.js → ssr-CTd2quoA.js} +12 -4
- package/dist/ssr.d.ts +3 -1
- package/dist/ssr.js +2 -2
- package/dist/vite.js +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { E as runWithIslandRequest, S as setFrameGuard, _ as parseFrameProps, b as renderServerIsland, c as frameEnvelope, m as isSafeFramePath, n as FrameError, o as authorizeFrameRequest, u as getFrameGuard, w as setLoaderGuard, x as setFrameAuth } from "./ssr-CTd2quoA.js";
|
|
2
2
|
import { existsSync, readFileSync, statSync, watch } from "node:fs";
|
|
3
3
|
import { basename, dirname, extname, join, relative, resolve, sep } from "node:path";
|
|
4
4
|
import { createUnplugin } from "unplugin";
|
|
@@ -198,7 +198,7 @@ function generateServerIslandModule(spec, scan) {
|
|
|
198
198
|
if (actions.length) wiring.push(`actions: { ${actions.join(", ")} }`);
|
|
199
199
|
if (scan.clientRefs.length) wiring.push(`children: { ${scan.clientRefs.map((ref, index) => `${JSON.stringify(ref.id)}: $$child${index}`).join(", ")} }`);
|
|
200
200
|
const id = serverIslandPublicId(spec, island.name);
|
|
201
|
-
wiring.push(`frame: () => fetch("/__ilha/frame", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ id: ${JSON.stringify(id)}, path: location.pathname + location.search }) }).then((r) => { if (!r.ok) throw new Error("frame failed"); return r.json(); }).then((j) => { if (j.redirect) { location.assign(j.redirect); throw new Error("frame redirected"); } __ilhaApplyHead(j.head); return j.html; })`);
|
|
201
|
+
wiring.push(`frame: (props) => fetch("/__ilha/frame", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ id: ${JSON.stringify(id)}, path: location.pathname + location.search, props }) }).then((r) => { if (!r.ok) throw new Error("frame failed"); return r.json(); }).then((j) => { if (j.redirect) { location.assign(j.redirect); throw new Error("frame redirected"); } __ilhaApplyHead(j.head); return j.html; })`);
|
|
202
202
|
if (scan.clientLoader) wiring.push(`clientLoader: () => $$call("load", [])`);
|
|
203
203
|
const call = `__ilhaServerIsland(${JSON.stringify(id)}, ${JSON.stringify(island.as)}, { ${wiring.join(", ")} })`;
|
|
204
204
|
if (island.name === "default") lines.push(`export default ${call};`);
|
|
@@ -1046,6 +1046,7 @@ const pagesFactory = (options = {}) => {
|
|
|
1046
1046
|
}
|
|
1047
1047
|
try {
|
|
1048
1048
|
const body = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
1049
|
+
const incomingProps = parseFrameProps(body.props);
|
|
1049
1050
|
const target = serverIslands.get(body.id ?? "");
|
|
1050
1051
|
if (!target) throw new Error("unknown island");
|
|
1051
1052
|
let framePath = "/";
|
|
@@ -1068,7 +1069,7 @@ const pagesFactory = (options = {}) => {
|
|
|
1068
1069
|
headers
|
|
1069
1070
|
});
|
|
1070
1071
|
let head;
|
|
1071
|
-
const html = await renderServerIsland(body.id ?? "", request, (r, fn) => runWithIslandRequest(r, fn), (entries) => head = entries);
|
|
1072
|
+
const html = await renderServerIsland(body.id ?? "", request, (r, fn) => runWithIslandRequest(r, fn), (entries) => head = entries, incomingProps);
|
|
1072
1073
|
const env = frameEnvelope(200, {
|
|
1073
1074
|
html: String(html),
|
|
1074
1075
|
head
|
package/dist/rsbuild.js
CHANGED
package/dist/server-island.d.ts
CHANGED
|
@@ -22,8 +22,8 @@ export interface ServerIslandWiring {
|
|
|
22
22
|
/** Action key → client transport. Event payloads are not serializable;
|
|
23
23
|
* handlers receive `undefined` and should read island state instead. */
|
|
24
24
|
actions?: Record<string, (payload?: unknown) => unknown>;
|
|
25
|
-
/** Frame transport: re-renders the island
|
|
26
|
-
frame?: () => unknown;
|
|
25
|
+
/** Frame transport: re-renders the island with the latest parent props. */
|
|
26
|
+
frame?: (props?: Record<string, unknown>) => unknown;
|
|
27
27
|
/** RPC transport for the module's `loader.client` export — invoked once
|
|
28
28
|
* when the view hydrates. Side-effect loader on server pages. */
|
|
29
29
|
clientLoader?: () => unknown;
|
|
@@ -51,7 +51,7 @@ interface IslandCallShape {
|
|
|
51
51
|
key: string;
|
|
52
52
|
}
|
|
53
53
|
export type ServerIslandCallable = Record<symbol, unknown> & ((props?: Record<string, unknown>) => string) & {
|
|
54
|
-
mount: (host: Element) => () => void;
|
|
54
|
+
mount: (host: Element, props?: Record<string, unknown>) => () => void;
|
|
55
55
|
toString: () => string;
|
|
56
56
|
key: (slotKey: string) => (props?: Record<string, unknown>) => IslandCallShape;
|
|
57
57
|
};
|
package/dist/server-island.js
CHANGED
|
@@ -48,7 +48,7 @@ function belongsToHost(host, candidate) {
|
|
|
48
48
|
}
|
|
49
49
|
return el === host;
|
|
50
50
|
}
|
|
51
|
-
function hydrateServerIsland(host, id, wiring) {
|
|
51
|
+
function hydrateServerIsland(host, id, wiring, props) {
|
|
52
52
|
const controller = new AbortController();
|
|
53
53
|
const cleanups = [];
|
|
54
54
|
cleanups.push(() => controller.abort());
|
|
@@ -61,12 +61,14 @@ function hydrateServerIsland(host, id, wiring) {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
const frame = wiring.frame;
|
|
64
|
+
let currentProps = props;
|
|
64
65
|
let repaintChain = Promise.resolve();
|
|
65
66
|
const scheduleRepaint = () => {
|
|
66
67
|
if (!frame || controller.signal.aborted) return;
|
|
68
|
+
const sent = currentProps;
|
|
67
69
|
repaintChain = repaintChain.then(async () => {
|
|
68
70
|
if (controller.signal.aborted || !host.isConnected) return;
|
|
69
|
-
const html = await frame();
|
|
71
|
+
const html = await frame(sent);
|
|
70
72
|
if (controller.signal.aborted || typeof html !== "string") return;
|
|
71
73
|
morph(host, html);
|
|
72
74
|
syncChildren();
|
|
@@ -187,7 +189,10 @@ function hydrateServerIsland(host, id, wiring) {
|
|
|
187
189
|
for (const cleanup of cleanups) cleanup();
|
|
188
190
|
cleanups.length = 0;
|
|
189
191
|
},
|
|
190
|
-
updateProps: () => {
|
|
192
|
+
updateProps: (next) => {
|
|
193
|
+
currentProps = next;
|
|
194
|
+
scheduleRepaint();
|
|
195
|
+
}
|
|
191
196
|
};
|
|
192
197
|
}
|
|
193
198
|
function __ilhaServerIsland(id, as, wiring = {}) {
|
|
@@ -208,8 +213,8 @@ function __ilhaServerIsland(id, as, wiring = {}) {
|
|
|
208
213
|
key: slotKey
|
|
209
214
|
});
|
|
210
215
|
};
|
|
211
|
-
island[ISLAND_MOUNT_INTERNAL] = (host) => hydrateServerIsland(host, id, wiring);
|
|
212
|
-
island.mount = (host) => hydrateServerIsland(host, id, wiring).unmount;
|
|
216
|
+
island[ISLAND_MOUNT_INTERNAL] = (host, mountProps) => hydrateServerIsland(host, id, wiring, mountProps);
|
|
217
|
+
island.mount = (host, mountProps) => hydrateServerIsland(host, id, wiring, mountProps).unmount;
|
|
213
218
|
return island;
|
|
214
219
|
}
|
|
215
220
|
|
|
@@ -214,10 +214,10 @@ function matchPatternParams(pattern, pathname) {
|
|
|
214
214
|
* caller's scope. Throws `FrameError` with an HTTP status for client-facing
|
|
215
215
|
* failures; loader redirects surface via `FrameError.redirect`.
|
|
216
216
|
*/
|
|
217
|
-
async function renderServerIsland(id, request, runWithScope, onHead) {
|
|
217
|
+
async function renderServerIsland(id, request, runWithScope, onHead, incomingProps) {
|
|
218
218
|
const entry = registry().get(id);
|
|
219
219
|
if (!entry) throw new FrameError(400, "unknown island");
|
|
220
|
-
let props;
|
|
220
|
+
let props = incomingProps;
|
|
221
221
|
if (entry.load) {
|
|
222
222
|
let url;
|
|
223
223
|
try {
|
|
@@ -264,6 +264,12 @@ const FRAME_ENDPOINT = "/__ilha/frame";
|
|
|
264
264
|
const LOADER_ENDPOINT = "/__ilha/loader";
|
|
265
265
|
/** Max request body size — matches the dev middleware cap. */
|
|
266
266
|
const MAX_BODY = 16384;
|
|
267
|
+
/** Parent-island props on a frame POST. Missing is fine; anything else is 400. */
|
|
268
|
+
function parseFrameProps(value) {
|
|
269
|
+
if (value == null) return void 0;
|
|
270
|
+
if (typeof value !== "object" || Array.isArray(value)) throw new FrameError(400, "frame failed");
|
|
271
|
+
return value;
|
|
272
|
+
}
|
|
267
273
|
function json(status, body) {
|
|
268
274
|
const env = frameEnvelope(status, body);
|
|
269
275
|
return new Response(env.body, {
|
|
@@ -423,11 +429,13 @@ async function ssr(request) {
|
|
|
423
429
|
if (!authorized.ok) return json(authorized.status, { error: "frame failed" });
|
|
424
430
|
let id;
|
|
425
431
|
let path = "/";
|
|
432
|
+
let incomingProps;
|
|
426
433
|
try {
|
|
427
434
|
const text = await readBodyBounded(request, MAX_BODY);
|
|
428
435
|
if (text === null) return json(413, { error: "frame failed" });
|
|
429
436
|
const body = JSON.parse(text);
|
|
430
437
|
id = String(body.id ?? "");
|
|
438
|
+
incomingProps = parseFrameProps(body.props);
|
|
431
439
|
if (typeof body.path === "string") {
|
|
432
440
|
if (!isSafeFramePath(body.path)) return json(400, { error: "frame failed" });
|
|
433
441
|
path = body.path;
|
|
@@ -455,7 +463,7 @@ async function ssr(request) {
|
|
|
455
463
|
}
|
|
456
464
|
let head;
|
|
457
465
|
return json(200, {
|
|
458
|
-
html: await renderServerIsland(id, scoped, (scopedRequest, fn) => Promise.resolve(runWithIslandRequest(scopedRequest, fn)), (entries) => head = entries),
|
|
466
|
+
html: await renderServerIsland(id, scoped, (scopedRequest, fn) => Promise.resolve(runWithIslandRequest(scopedRequest, fn)), (entries) => head = entries, incomingProps),
|
|
459
467
|
head
|
|
460
468
|
});
|
|
461
469
|
} catch (error) {
|
|
@@ -472,4 +480,4 @@ async function ssr(request) {
|
|
|
472
480
|
ssr.imports = ["ilha:pages/server", "ilha:loaders"];
|
|
473
481
|
|
|
474
482
|
//#endregion
|
|
475
|
-
export {
|
|
483
|
+
export { setFrameLoaderRunner as C, runWithIslandRequest as E, setFrameGuard as S, ssr as T, parseFrameProps as _, __ilhaServerAction as a, renderServerIsland as b, frameEnvelope as c, getFrameLoaderRunner as d, getLoaderGuard as f, json as g, isTrustedOrigin as h, MAX_BODY as i, getFrameAuth as l, isSafeFramePath as m, FrameError as n, authorizeFrameRequest as o, getServerIslandEntry as p, LOADER_ENDPOINT as r, forwardIdentityHeaders as s, FRAME_ENDPOINT as t, getFrameGuard as u, readBodyBounded as v, setLoaderGuard as w, setFrameAuth as x, registerServerIsland as y };
|
package/dist/ssr.d.ts
CHANGED
|
@@ -164,12 +164,14 @@ export declare class FrameError extends Error {
|
|
|
164
164
|
* caller's scope. Throws `FrameError` with an HTTP status for client-facing
|
|
165
165
|
* failures; loader redirects surface via `FrameError.redirect`.
|
|
166
166
|
*/
|
|
167
|
-
export declare function renderServerIsland(id: string, request: Request, runWithScope: <T>(request: Request, fn: () => T) => T | Promise<T>, onHead?: (entries: HeadInput[]) => void): Promise<string>;
|
|
167
|
+
export declare function renderServerIsland(id: string, request: Request, runWithScope: <T>(request: Request, fn: () => T) => T | Promise<T>, onHead?: (entries: HeadInput[]) => void, incomingProps?: Record<string, unknown>): Promise<string>;
|
|
168
168
|
export declare const FRAME_ENDPOINT = "/__ilha/frame";
|
|
169
169
|
/** Regular-page server loads: served through the loader-runner slot. */
|
|
170
170
|
export declare const LOADER_ENDPOINT = "/__ilha/loader";
|
|
171
171
|
/** Max request body size — matches the dev middleware cap. */
|
|
172
172
|
export declare const MAX_BODY: number;
|
|
173
|
+
/** Parent-island props on a frame POST. Missing is fine; anything else is 400. */
|
|
174
|
+
export declare function parseFrameProps(value: unknown): Record<string, unknown> | undefined;
|
|
173
175
|
export declare function json(status: number, body: Record<string, unknown>): Response;
|
|
174
176
|
/**
|
|
175
177
|
* Read a request body as UTF-8, streaming it with a hard byte cap. Returns
|
package/dist/ssr.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { C as setFrameLoaderRunner, S as setFrameGuard, T as ssr, _ as parseFrameProps, a as __ilhaServerAction, b as renderServerIsland, c as frameEnvelope, d as getFrameLoaderRunner, f as getLoaderGuard, g as json, h as isTrustedOrigin, i as MAX_BODY, l as getFrameAuth, m as isSafeFramePath, n as FrameError, o as authorizeFrameRequest, p as getServerIslandEntry, r as LOADER_ENDPOINT, s as forwardIdentityHeaders, t as FRAME_ENDPOINT, u as getFrameGuard, v as readBodyBounded, w as setLoaderGuard, x as setFrameAuth, y as registerServerIsland } from "./ssr-CTd2quoA.js";
|
|
2
2
|
|
|
3
|
-
export { FRAME_ENDPOINT, FrameError, LOADER_ENDPOINT, MAX_BODY, __ilhaServerAction, authorizeFrameRequest, ssr as default, forwardIdentityHeaders, frameEnvelope, getFrameAuth, getFrameGuard, getFrameLoaderRunner, getLoaderGuard, getServerIslandEntry, isSafeFramePath, isTrustedOrigin, json, readBodyBounded, registerServerIsland, renderServerIsland, setFrameAuth, setFrameGuard, setFrameLoaderRunner, setLoaderGuard };
|
|
3
|
+
export { FRAME_ENDPOINT, FrameError, LOADER_ENDPOINT, MAX_BODY, __ilhaServerAction, authorizeFrameRequest, ssr as default, forwardIdentityHeaders, frameEnvelope, getFrameAuth, getFrameGuard, getFrameLoaderRunner, getLoaderGuard, getServerIslandEntry, isSafeFramePath, isTrustedOrigin, json, parseFrameProps, readBodyBounded, registerServerIsland, renderServerIsland, setFrameAuth, setFrameGuard, setFrameLoaderRunner, setLoaderGuard };
|
package/dist/vite.js
CHANGED