@farm.js/islx 0.0.6 → 0.0.8
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/CHANGELOG.md +39 -0
- package/README.md +56 -26
- package/SPEC.md +7 -4
- package/dist/_chunks/{actions-BuS5jDi0.mjs → actions-CvQ0-zjg.mjs} +15 -14
- package/dist/_chunks/{actions-Eutk6UzT.mjs → infer-BIVT5aDz.mjs} +269 -1
- package/dist/_chunks/{island-DVOr-OUw.mjs → island-DXAGP4FN.mjs} +10 -3
- package/dist/_chunks/{prehydration-B1GLTLdk.mjs → prehydration-zEYsfFxW.mjs} +3 -2
- package/dist/_chunks/{schedule-CjoybS3b.mjs → schedule-Cwn9vQL0.mjs} +12 -3
- package/dist/_chunks/{tree-C47p6khN.mjs → tree-BQphP23Y.mjs} +1 -1
- package/dist/_chunks/{tree-B4RMU2UX.d.mts → tree-CV13RsJv.d.mts} +8 -1
- package/dist/_chunks/{vite-BTzYlEiY.mjs → vite-0bH_ZDys.mjs} +27 -12
- package/dist/boot.d.mts +31 -0
- package/dist/boot.mjs +177 -0
- package/dist/client.d.mts +2 -1
- package/dist/client.mjs +1 -1
- package/dist/compiler.d.mts +23 -1
- package/dist/compiler.mjs +1 -1
- package/dist/react/client.d.mts +1 -1
- package/dist/react/client.mjs +3 -3
- package/dist/react/server.d.mts +1 -1
- package/dist/react/server.mjs +17 -9
- package/dist/react.d.mts +1 -1
- package/dist/react.mjs +2 -2
- package/dist/server.d.mts +9 -4
- package/dist/server.mjs +1 -1
- package/dist/tanstack-start/server.mjs +1 -1
- package/dist/tanstack-start.mjs +1 -1
- package/dist/vite.d.mts +16 -1
- package/dist/vite.mjs +1 -1
- package/package.json +5 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as hasPendingInteraction, o as takePendingInteractions, t as INTERACTION_EVENT } from "./prehydration-
|
|
1
|
+
import { a as hasPendingInteraction, o as takePendingInteractions, t as INTERACTION_EVENT } from "./prehydration-zEYsfFxW.mjs";
|
|
2
2
|
import { m as HYDRATED_ATTRIBUTE } from "./wire-QEQWBr5s.mjs";
|
|
3
3
|
// src/client/schedule.ts
|
|
4
4
|
/**
|
|
@@ -24,6 +24,15 @@ function isIslandStrategy(value) {
|
|
|
24
24
|
}
|
|
25
25
|
/** Elements whose click is held and replayed rather than merely observed. */
|
|
26
26
|
const REPLAYABLE = "button,[role=\"button\"],input[type=\"button\"],input[type=\"submit\"],input[type=\"reset\"]";
|
|
27
|
+
/**
|
|
28
|
+
* The element a click before hydration is held on: a control, or a same-page link, whose handler
|
|
29
|
+
* the island may need (a table of contents marking its heading). Any other link navigates.
|
|
30
|
+
*/
|
|
31
|
+
function heldTarget(target) {
|
|
32
|
+
const link = target.closest("a[href]");
|
|
33
|
+
if (link) return link.getAttribute("href")?.startsWith("#") ? link : null;
|
|
34
|
+
return target.closest(REPLAYABLE);
|
|
35
|
+
}
|
|
27
36
|
function whenIdle(callback) {
|
|
28
37
|
const scope = window;
|
|
29
38
|
if (typeof scope.requestIdleCallback === "function") {
|
|
@@ -190,8 +199,8 @@ function scheduleHydration({ container, strategy, signal, hydrate }) {
|
|
|
190
199
|
};
|
|
191
200
|
const onClick = (event) => {
|
|
192
201
|
const mouse = event;
|
|
193
|
-
const target = event.target instanceof Element ? event.target
|
|
194
|
-
if (!target || !container.contains(target) ||
|
|
202
|
+
const target = event.target instanceof Element ? heldTarget(event.target) : null;
|
|
203
|
+
if (!target || !container.contains(target) || mouse.button !== 0 || mouse.metaKey || mouse.altKey || mouse.ctrlKey || mouse.shiftKey) return;
|
|
195
204
|
hold(event, target, "click");
|
|
196
205
|
};
|
|
197
206
|
const onSubmit = (event) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { i as decodeTagged, n as NOT_A_VALUE, o as encodeLeaf } from "./codec-C8to-RQW.mjs";
|
|
2
2
|
import { M as VALUE_SCRIPT_TYPE, c as CHUNK_SCRIPT_TYPE, k as TREE_SCRIPT_TYPE, p as HTML_ELEMENT } from "./wire-QEQWBr5s.mjs";
|
|
3
3
|
import { t as createServerReference, u as getValueStore } from "./actions-C-IwUCKU.mjs";
|
|
4
|
-
import { a as getIslandServerHook, o as isolateIslands, r as getClientReference } from "./island-
|
|
4
|
+
import { a as getIslandServerHook, o as isolateIslands, r as getClientReference } from "./island-DXAGP4FN.mjs";
|
|
5
5
|
import * as React from "react";
|
|
6
6
|
// src/react/tree.ts
|
|
7
7
|
/**
|
|
@@ -52,7 +52,14 @@ interface IslandRenderState {
|
|
|
52
52
|
* Wraps a client component so the server renders it as an island. `src` is the module the browser
|
|
53
53
|
* imports, `exportName` the component's export there.
|
|
54
54
|
*/
|
|
55
|
-
declare function createIsland<P extends object>(Component: React.ComponentType<P>, src: string, exportName: string,
|
|
55
|
+
declare function createIsland<P extends object>(Component: React.ComponentType<P>, src: string, exportName: string, declared?: IslandStrategy,
|
|
56
|
+
/**
|
|
57
|
+
* `inferred`: the compiler inferred `declared` (`"interaction"`). A render that passes the island
|
|
58
|
+
* server output hydrates at load instead: islands inside that output would wait with it.
|
|
59
|
+
*/
|
|
60
|
+
options?: {
|
|
61
|
+
inferred?: boolean;
|
|
62
|
+
}): React.ComponentType<P>;
|
|
56
63
|
/**
|
|
57
64
|
* Marks a navigation response that carries only the page's payload. The browser rebuilds such a
|
|
58
65
|
* page in its layout's React root and never shows its HTML, so the server leaves the HTML out.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as ISLAND_STRATEGIES } from "./schedule-
|
|
1
|
+
import { a as transformActions, i as hasModuleDirective, n as ActionCompileError, t as inferStrategy } from "./infer-BIVT5aDz.mjs";
|
|
2
|
+
import { t as ISLAND_STRATEGIES } from "./schedule-Cwn9vQL0.mjs";
|
|
3
3
|
import { randomBytes } from "node:crypto";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { walk } from "estree-walker";
|
|
@@ -78,10 +78,12 @@ function transformClientModule(options) {
|
|
|
78
78
|
throw new ActionCompileError(message, file, code, node.start);
|
|
79
79
|
};
|
|
80
80
|
const strategies = readStrategies(program, fail);
|
|
81
|
+
const inference = options.infer && strategies.all === void 0 && strategies.byName.size === 0 ? inferStrategy(file, code, options.infer) : void 0;
|
|
82
|
+
const inferred = (name) => options.strategy?.(name) === void 0 && inference?.strategy === "interaction";
|
|
81
83
|
const strategyOf = (name) => {
|
|
82
84
|
const configured = options.strategy?.(name);
|
|
83
85
|
if (configured !== void 0 && !ISLAND_STRATEGIES.includes(configured)) throw new Error(`islx: strategy for ${name} must be one of ${ISLAND_STRATEGIES.join(", ")}`);
|
|
84
|
-
return configured ?? strategies.byName.get(name) ?? strategies.all ?? "load";
|
|
86
|
+
return configured ?? strategies.byName.get(name) ?? strategies.all ?? (inference?.strategy === "interaction" ? "interaction" : "load");
|
|
85
87
|
};
|
|
86
88
|
const output = new MagicString(code);
|
|
87
89
|
const wrapped = [];
|
|
@@ -140,7 +142,9 @@ function transformClientModule(options) {
|
|
|
140
142
|
const runtime = options.runtime ?? "@farm.js/islx/react";
|
|
141
143
|
const src = options.reference(relative);
|
|
142
144
|
const lines = [...wrapped.map(({ local, exportName }, index) => {
|
|
143
|
-
|
|
145
|
+
const strategy = JSON.stringify(strategyOf(exportName));
|
|
146
|
+
const flags = inferred(exportName) ? ", { inferred: true }" : "";
|
|
147
|
+
return `const $$islx_island_${index} = $$islx_island(${local}, ${src}, ${JSON.stringify(exportName)}, ${strategy}${flags});`;
|
|
144
148
|
}), `export { ${wrapped.map(({ exportName }, index) => `$$islx_island_${index} as ${exportName}`).join(", ")} };`];
|
|
145
149
|
const imports = [`import { createIsland as $$islx_island } from ${JSON.stringify(runtime)};`, ...(options.sideEffects ?? []).map((module) => `import ${JSON.stringify(module)};`)];
|
|
146
150
|
output.prepend(`${imports.join("\n")}\n`);
|
|
@@ -154,7 +158,8 @@ function transformClientModule(options) {
|
|
|
154
158
|
islands: wrapped.map(({ exportName }) => ({
|
|
155
159
|
exportName,
|
|
156
160
|
strategy: strategyOf(exportName)
|
|
157
|
-
}))
|
|
161
|
+
})),
|
|
162
|
+
...inference ? { inference } : {}
|
|
158
163
|
};
|
|
159
164
|
}
|
|
160
165
|
// src/vite.ts
|
|
@@ -177,6 +182,8 @@ function transformClientModule(options) {
|
|
|
177
182
|
const RUNTIME_ID = "virtual:islx/runtime";
|
|
178
183
|
/** @internal The browser entry, for a framework whose own entry imports it. */
|
|
179
184
|
const ENTRY_ID = "virtual:islx/client-entry";
|
|
185
|
+
/** The boot entry: pages start with it, and it loads ENTRY_ID when the page first needs it. */
|
|
186
|
+
const BOOT_ID = "virtual:islx/boot";
|
|
180
187
|
const LIBRARY_RUNTIME_ID = "virtual:islx/react-for-libraries";
|
|
181
188
|
const CLIENT_HOOKS_ID = "virtual:islx/hooks-client";
|
|
182
189
|
const SERVER_HOOKS_ID = "virtual:islx/hooks-server";
|
|
@@ -244,6 +251,7 @@ function serializeHooks(hooks, where, parse) {
|
|
|
244
251
|
* build until the browser build names them. */
|
|
245
252
|
const ENTRY_PLACEHOLDER = "__islx_client_entry_url__";
|
|
246
253
|
const MODULES_PLACEHOLDER = "__islx_client_modules__";
|
|
254
|
+
const BOOT_PLACEHOLDER = "__islx_boot_url__";
|
|
247
255
|
const SCRIPT = /\.[cm]?[jt]sx?$/;
|
|
248
256
|
async function createParser() {
|
|
249
257
|
const withErrors = (result) => Object.assign(result.program, { errors: result.errors ?? [] });
|
|
@@ -315,6 +323,7 @@ function islx(options = {}, host = {}) {
|
|
|
315
323
|
const discovered = /* @__PURE__ */ new Set();
|
|
316
324
|
/** The browser entry's URL, once the browser build named it. */
|
|
317
325
|
let entryUrl;
|
|
326
|
+
let bootUrl;
|
|
318
327
|
/** The files each client module needs, once the browser build named them. */
|
|
319
328
|
const moduleFiles = {};
|
|
320
329
|
/** Whether the browser build ran first (a framework that orders the build). */
|
|
@@ -355,7 +364,8 @@ function islx(options = {}, host = {}) {
|
|
|
355
364
|
outDir: clientBuild?.outDir ?? "dist/client",
|
|
356
365
|
rollupOptions: { input: host.frameworkEntry ? input : {
|
|
357
366
|
...typeof input === "string" ? { index: input } : Array.isArray(input) ? Object.fromEntries(input.map((entry, index) => [`input${index}`, entry])) : input,
|
|
358
|
-
"islx-entry": ENTRY_ID
|
|
367
|
+
"islx-entry": ENTRY_ID,
|
|
368
|
+
...options.boot === false ? {} : { "islx-boot": BOOT_ID }
|
|
359
369
|
} }
|
|
360
370
|
}
|
|
361
371
|
} }
|
|
@@ -368,17 +378,18 @@ function islx(options = {}, host = {}) {
|
|
|
368
378
|
},
|
|
369
379
|
resolveId(id) {
|
|
370
380
|
if (id === LIBRARY_RUNTIME_ID) return this.resolve("@farm.js/islx/react", path.join(config.root, "package.json"), { skipSelf: true });
|
|
371
|
-
if (id === RUNTIME_ID || id === "virtual:islx/client-entry" || id === CLIENT_HOOKS_ID || id === SERVER_HOOKS_ID) return `\0${id}`;
|
|
381
|
+
if (id === RUNTIME_ID || id === "virtual:islx/client-entry" || id === "virtual:islx/boot" || id === CLIENT_HOOKS_ID || id === SERVER_HOOKS_ID) return `\0${id}`;
|
|
372
382
|
},
|
|
373
383
|
async load(id) {
|
|
374
384
|
if (id === `\0${RUNTIME_ID}`) {
|
|
375
385
|
const entry = host.frameworkEntry ? void 0 : !isBuild() ? `${config.base}@id/__x00__${ENTRY_ID}` : clientBuilt ? entryUrl : ENTRY_PLACEHOLDER;
|
|
386
|
+
const boot = host.frameworkEntry || options.boot === false ? void 0 : !isBuild() ? `${config.base}@id/__x00__${BOOT_ID}` : clientBuilt ? bootUrl : BOOT_PLACEHOLDER;
|
|
376
387
|
const modules = !isBuild() ? "{}" : clientBuilt ? JSON.stringify(moduleFiles) : `JSON.parse(${JSON.stringify(MODULES_PLACEHOLDER)})`;
|
|
377
388
|
return [
|
|
378
389
|
...host.frameworkRender ? [`import "@farm.js/islx/react/server";`] : [],
|
|
379
390
|
`import { setBuildDefaults, setServerHooks } from "@farm.js/islx/server";`,
|
|
380
391
|
`import hooks from ${JSON.stringify(SERVER_HOOKS_ID)};`,
|
|
381
|
-
`setBuildDefaults({ entry: ${JSON.stringify(entry)}, key: ${JSON.stringify(buildKey)}, modules: ${modules} });`,
|
|
392
|
+
`setBuildDefaults({ entry: ${JSON.stringify(entry)}, boot: ${JSON.stringify(boot)}, key: ${JSON.stringify(buildKey)}, modules: ${modules} });`,
|
|
382
393
|
`setServerHooks(hooks);`
|
|
383
394
|
].join("\n");
|
|
384
395
|
}
|
|
@@ -389,6 +400,7 @@ function islx(options = {}, host = {}) {
|
|
|
389
400
|
if (typeof hooks === "string") return `export { default } from ${JSON.stringify(path.resolve(config.root, hooks))};`;
|
|
390
401
|
return serializeHooks(hooks, where, parse);
|
|
391
402
|
}
|
|
403
|
+
if (id === `\0virtual:islx/boot`) return `import { startBoot } from "@farm.js/islx/boot";\nstartBoot();\n`;
|
|
392
404
|
if (id === `\0virtual:islx/client-entry`) {
|
|
393
405
|
const load = isBuild() ? `const modules = {\n${(await clientInputs()).map((relative) => ` ${JSON.stringify(relative)}: () => import(${JSON.stringify(path.resolve(config.root, relative))}),`).join("\n")}\n};\nconst load = (src) => modules[src] ? modules[src]() : Promise.reject(new Error("islx: no client module " + src));` : `const root = new URL(${JSON.stringify(`file://${toPosix(config.root)}/`)});\nconst load = (src) => import(/* @vite-ignore */ src.startsWith("../") ? "/@fs" + new URL(src, root).pathname : ${JSON.stringify(config.base)} + src);`;
|
|
394
406
|
return [
|
|
@@ -428,8 +440,10 @@ function islx(options = {}, host = {}) {
|
|
|
428
440
|
},
|
|
429
441
|
sideEffects: [RUNTIME_ID],
|
|
430
442
|
directive: clientDirective,
|
|
431
|
-
...library ? { runtime: LIBRARY_RUNTIME_ID } : {}
|
|
443
|
+
...library ? { runtime: LIBRARY_RUNTIME_ID } : {},
|
|
444
|
+
...options.infer !== false && !library ? { infer: { parse } } : {}
|
|
432
445
|
});
|
|
446
|
+
for (const read of island?.inference?.files ?? []) if (read !== file) this.addWatchFile(read);
|
|
433
447
|
if (island) {
|
|
434
448
|
if (!library) transformActions({
|
|
435
449
|
code,
|
|
@@ -484,9 +498,9 @@ function islx(options = {}, host = {}) {
|
|
|
484
498
|
const outDir = path.resolve(config.root, environment.config.build.outDir);
|
|
485
499
|
for (const file of await listOutput(outDir)) {
|
|
486
500
|
const source = await readFile(file, "utf8");
|
|
487
|
-
if (!source.includes(ENTRY_PLACEHOLDER) && !source.includes(MODULES_PLACEHOLDER)) continue;
|
|
501
|
+
if (!source.includes(ENTRY_PLACEHOLDER) && !source.includes(MODULES_PLACEHOLDER) && !source.includes(BOOT_PLACEHOLDER)) continue;
|
|
488
502
|
const modules = JSON.stringify(JSON.stringify(moduleFiles)).slice(1, -1);
|
|
489
|
-
await writeFile(file, source.replaceAll(ENTRY_PLACEHOLDER, entryUrl).replaceAll(MODULES_PLACEHOLDER, modules));
|
|
503
|
+
await writeFile(file, source.replaceAll(ENTRY_PLACEHOLDER, entryUrl).replaceAll(MODULES_PLACEHOLDER, modules).replaceAll(BOOT_PLACEHOLDER, bootUrl ?? ""));
|
|
490
504
|
}
|
|
491
505
|
}
|
|
492
506
|
},
|
|
@@ -496,6 +510,7 @@ function islx(options = {}, host = {}) {
|
|
|
496
510
|
for (const chunk of Object.values(bundle)) {
|
|
497
511
|
if (chunk.type !== "chunk" || !chunk.facadeModuleId) continue;
|
|
498
512
|
if (chunk.isEntry && chunk.facadeModuleId === `\0virtual:islx/client-entry`) entryUrl = url(chunk.fileName);
|
|
513
|
+
else if (chunk.isEntry && chunk.facadeModuleId === `\0virtual:islx/boot`) bootUrl = url(chunk.fileName);
|
|
499
514
|
else if (chunk.isDynamicEntry && !chunk.facadeModuleId.startsWith("\0")) moduleFiles[relativeOf(chunk.facadeModuleId)] = [chunk.fileName, ...chunk.imports].map(url);
|
|
500
515
|
}
|
|
501
516
|
clientBuilt = true;
|
|
@@ -503,4 +518,4 @@ function islx(options = {}, host = {}) {
|
|
|
503
518
|
}
|
|
504
519
|
];
|
|
505
520
|
}
|
|
506
|
-
export { serializeHooks as i,
|
|
521
|
+
export { serializeHooks as a, resolveDirectives as i, ENTRY_ID as n, islx as r, BOOT_ID as t };
|
package/dist/boot.d.mts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @farm.js/islx/boot: the first script of a page, in place of the browser entry. It loads the entry
|
|
3
|
+
* (the runtime: the renderer, islx's hydration, navigation and forms) when the page first needs
|
|
4
|
+
* it, so a page whose islands all wait loads only this script until one is used:
|
|
5
|
+
*
|
|
6
|
+
* - at once, when an island hydrates at load (`strategy="load"`, also one that streams in later)
|
|
7
|
+
* or a Suspense boundary is left for the browser to finish;
|
|
8
|
+
* - otherwise on the first island trigger (`idle`; `visible`, with the scheduler's 200px margin;
|
|
9
|
+
* an interaction the inline pre-hydration script saw) or on intent to follow a link (a pointer
|
|
10
|
+
* over it, a press, a focus), or a focus in a form.
|
|
11
|
+
*
|
|
12
|
+
* The inline pre-hydration script holds the clicks and submits on waiting islands until then. A
|
|
13
|
+
* same-site link clicked before the entry has run is held too, and clicked again once it has, so
|
|
14
|
+
* navigation decides as for any click; if the entry fails to load, the link navigates natively.
|
|
15
|
+
*
|
|
16
|
+
* Renderer-neutral, and it imports nothing: a module it shared with the entry would change how the
|
|
17
|
+
* entry splits into chunks. The server names the entry in `window.__islxRuntime`.
|
|
18
|
+
*/
|
|
19
|
+
/** Kept equal to the island element (protocol/wire.ts); a test compares them. */
|
|
20
|
+
declare const BOOT_ISLAND_ELEMENT = "f-island";
|
|
21
|
+
/** Kept equal to HYDRATED_ATTRIBUTE (protocol/wire.ts). */
|
|
22
|
+
declare const BOOT_HYDRATED_ATTRIBUTE = "hydrated";
|
|
23
|
+
/** Kept equal to INTERACTION_EVENT (client/prehydration.ts). */
|
|
24
|
+
declare const BOOT_INTERACTION_EVENT = "f:island-interaction";
|
|
25
|
+
/** Kept equal to the scheduler's visibility margin (client/schedule.ts). */
|
|
26
|
+
declare const BOOT_VISIBLE_MARGIN = "200px";
|
|
27
|
+
/** Where the server names the browser entry for the boot. */
|
|
28
|
+
declare const RUNTIME_GLOBAL = "__islxRuntime";
|
|
29
|
+
/** Starts the runtime when the page first needs it. `load` runs it; it starts as it runs. */
|
|
30
|
+
declare function startBoot(load?: () => Promise<unknown>): void;
|
|
31
|
+
export { BOOT_HYDRATED_ATTRIBUTE, BOOT_INTERACTION_EVENT, BOOT_ISLAND_ELEMENT, BOOT_VISIBLE_MARGIN, RUNTIME_GLOBAL, startBoot };
|
package/dist/boot.mjs
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// src/boot.ts
|
|
2
|
+
/**
|
|
3
|
+
* @farm.js/islx/boot: the first script of a page, in place of the browser entry. It loads the entry
|
|
4
|
+
* (the runtime: the renderer, islx's hydration, navigation and forms) when the page first needs
|
|
5
|
+
* it, so a page whose islands all wait loads only this script until one is used:
|
|
6
|
+
*
|
|
7
|
+
* - at once, when an island hydrates at load (`strategy="load"`, also one that streams in later)
|
|
8
|
+
* or a Suspense boundary is left for the browser to finish;
|
|
9
|
+
* - otherwise on the first island trigger (`idle`; `visible`, with the scheduler's 200px margin;
|
|
10
|
+
* an interaction the inline pre-hydration script saw) or on intent to follow a link (a pointer
|
|
11
|
+
* over it, a press, a focus), or a focus in a form.
|
|
12
|
+
*
|
|
13
|
+
* The inline pre-hydration script holds the clicks and submits on waiting islands until then. A
|
|
14
|
+
* same-site link clicked before the entry has run is held too, and clicked again once it has, so
|
|
15
|
+
* navigation decides as for any click; if the entry fails to load, the link navigates natively.
|
|
16
|
+
*
|
|
17
|
+
* Renderer-neutral, and it imports nothing: a module it shared with the entry would change how the
|
|
18
|
+
* entry splits into chunks. The server names the entry in `window.__islxRuntime`.
|
|
19
|
+
*/
|
|
20
|
+
/** Kept equal to the island element (protocol/wire.ts); a test compares them. */
|
|
21
|
+
const BOOT_ISLAND_ELEMENT = "f-island";
|
|
22
|
+
/** Kept equal to HYDRATED_ATTRIBUTE (protocol/wire.ts). */
|
|
23
|
+
const BOOT_HYDRATED_ATTRIBUTE = "hydrated";
|
|
24
|
+
/** Kept equal to INTERACTION_EVENT (client/prehydration.ts). */
|
|
25
|
+
const BOOT_INTERACTION_EVENT = "f:island-interaction";
|
|
26
|
+
/** Kept equal to the scheduler's visibility margin (client/schedule.ts). */
|
|
27
|
+
const BOOT_VISIBLE_MARGIN = "200px";
|
|
28
|
+
/** Where the server names the browser entry for the boot. */
|
|
29
|
+
const RUNTIME_GLOBAL = "__islxRuntime";
|
|
30
|
+
function isModified(event) {
|
|
31
|
+
return event.metaKey || event.altKey || event.ctrlKey || event.shiftKey;
|
|
32
|
+
}
|
|
33
|
+
/** A link islx navigation takes: the same checks as its click handler. */
|
|
34
|
+
function navigableLink(target) {
|
|
35
|
+
const link = target instanceof Element ? target.closest("a[href]") : null;
|
|
36
|
+
if (!(link instanceof HTMLAnchorElement)) return null;
|
|
37
|
+
if (link.target && link.target !== "_self") return null;
|
|
38
|
+
if (link.hasAttribute("download") || link.relList.contains("external")) return null;
|
|
39
|
+
const url = new URL(link.href);
|
|
40
|
+
if (url.origin !== location.origin || !/^https?:$/.test(url.protocol)) return null;
|
|
41
|
+
if (url.pathname === location.pathname && url.search === location.search && url.hash) return null;
|
|
42
|
+
return link;
|
|
43
|
+
}
|
|
44
|
+
/** Runs the browser entry the server named, as a module script: the same URL, so the same module. */
|
|
45
|
+
function loadRuntime() {
|
|
46
|
+
const src = window[RUNTIME_GLOBAL];
|
|
47
|
+
if (typeof src !== "string" || src === "") return Promise.reject(/* @__PURE__ */ new Error(`islx: the page names no browser entry (${RUNTIME_GLOBAL}).`));
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const script = document.createElement("script");
|
|
50
|
+
script.type = "module";
|
|
51
|
+
script.src = src;
|
|
52
|
+
const nonce = document.querySelector("script[nonce]")?.nonce;
|
|
53
|
+
if (nonce) script.nonce = nonce;
|
|
54
|
+
script.addEventListener("load", () => resolve(), { once: true });
|
|
55
|
+
script.addEventListener("error", () => reject(/* @__PURE__ */ new Error(`islx: ${src} failed to load.`)), { once: true });
|
|
56
|
+
document.head.append(script);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/** Starts the runtime when the page first needs it. `load` runs it; it starts as it runs. */
|
|
60
|
+
function startBoot(load = loadRuntime) {
|
|
61
|
+
const cleanups = [];
|
|
62
|
+
let loading;
|
|
63
|
+
const release = () => {
|
|
64
|
+
for (const cleanup of cleanups.splice(0)) cleanup();
|
|
65
|
+
};
|
|
66
|
+
const start = () => {
|
|
67
|
+
if (!loading) {
|
|
68
|
+
loading = load().then(release, (error) => {
|
|
69
|
+
release();
|
|
70
|
+
throw error;
|
|
71
|
+
});
|
|
72
|
+
loading.catch((error) => console.error(error));
|
|
73
|
+
}
|
|
74
|
+
return loading;
|
|
75
|
+
};
|
|
76
|
+
const listen = (type, handler, capture) => {
|
|
77
|
+
document.addEventListener(type, handler, capture);
|
|
78
|
+
cleanups.push(() => document.removeEventListener(type, handler, capture));
|
|
79
|
+
};
|
|
80
|
+
listen(BOOT_INTERACTION_EVENT, () => void start(), false);
|
|
81
|
+
const intent = (event) => {
|
|
82
|
+
if (navigableLink(event.target)) start();
|
|
83
|
+
else if (event.type !== "mouseover" && event.target?.closest?.("form")) start();
|
|
84
|
+
};
|
|
85
|
+
for (const type of [
|
|
86
|
+
"pointerdown",
|
|
87
|
+
"focusin",
|
|
88
|
+
"mouseover"
|
|
89
|
+
]) listen(type, intent, true);
|
|
90
|
+
listen("click", (event) => {
|
|
91
|
+
const click = event;
|
|
92
|
+
if (click.defaultPrevented || click.button !== 0 || isModified(click)) return;
|
|
93
|
+
const link = navigableLink(click.target);
|
|
94
|
+
if (!link) return;
|
|
95
|
+
click.preventDefault();
|
|
96
|
+
start().then(() => {
|
|
97
|
+
if (link.isConnected) link.dispatchEvent(new MouseEvent("click", {
|
|
98
|
+
bubbles: true,
|
|
99
|
+
cancelable: true
|
|
100
|
+
}));
|
|
101
|
+
else location.assign(link.href);
|
|
102
|
+
}, () => location.assign(link.href));
|
|
103
|
+
}, false);
|
|
104
|
+
const visibility = typeof IntersectionObserver === "function" ? new IntersectionObserver((entries) => {
|
|
105
|
+
if (entries.some((entry) => entry.isIntersecting)) start();
|
|
106
|
+
}, { rootMargin: BOOT_VISIBLE_MARGIN }) : null;
|
|
107
|
+
if (visibility) cleanups.push(() => visibility.disconnect());
|
|
108
|
+
let idle = false;
|
|
109
|
+
const startWhenIdle = () => {
|
|
110
|
+
if (idle) return;
|
|
111
|
+
idle = true;
|
|
112
|
+
const scope = window;
|
|
113
|
+
if (typeof scope.requestIdleCallback === "function") {
|
|
114
|
+
const handle = scope.requestIdleCallback(() => void start(), { timeout: 2e3 });
|
|
115
|
+
cleanups.push(() => scope.cancelIdleCallback?.(handle));
|
|
116
|
+
} else {
|
|
117
|
+
const handle = window.setTimeout(() => void start(), 1);
|
|
118
|
+
cleanups.push(() => window.clearTimeout(handle));
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const parsedVisible = [];
|
|
122
|
+
const observeVisible = (island) => {
|
|
123
|
+
const targets = island.getClientRects().length > 0 ? [island] : Array.from(island.children);
|
|
124
|
+
if (!visibility || targets.length === 0) start();
|
|
125
|
+
else for (const target of targets) visibility.observe(target);
|
|
126
|
+
};
|
|
127
|
+
const considerIsland = (island) => {
|
|
128
|
+
if (island.hasAttribute("hydrated")) return;
|
|
129
|
+
if (island.parentElement?.closest("f-island")) return;
|
|
130
|
+
const strategy = island.getAttribute("strategy");
|
|
131
|
+
if (strategy === "interaction") return;
|
|
132
|
+
if (strategy === "idle") startWhenIdle();
|
|
133
|
+
else if (strategy !== "visible") start();
|
|
134
|
+
else if (document.readyState === "loading") parsedVisible.push(island);
|
|
135
|
+
else observeVisible(island);
|
|
136
|
+
};
|
|
137
|
+
const consider = (node) => {
|
|
138
|
+
if (loading) return;
|
|
139
|
+
if (node.nodeType === Node.COMMENT_NODE) {
|
|
140
|
+
if (node.data === "$!") start();
|
|
141
|
+
} else if (node instanceof Element) {
|
|
142
|
+
if (node.matches("f-island")) considerIsland(node);
|
|
143
|
+
for (const island of Array.from(node.querySelectorAll(BOOT_ISLAND_ELEMENT))) considerIsland(island);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
const pendingBoundary = () => {
|
|
147
|
+
const walker = document.createTreeWalker(document, NodeFilter.SHOW_COMMENT);
|
|
148
|
+
while (walker.nextNode()) if (walker.currentNode.data === "$?") return true;
|
|
149
|
+
return false;
|
|
150
|
+
};
|
|
151
|
+
const walker = document.createTreeWalker(document, NodeFilter.SHOW_COMMENT);
|
|
152
|
+
while (!loading && walker.nextNode()) consider(walker.currentNode);
|
|
153
|
+
consider(document.documentElement);
|
|
154
|
+
const parsed = () => {
|
|
155
|
+
if (pendingBoundary()) start();
|
|
156
|
+
for (const island of parsedVisible.splice(0)) if (!loading) observeVisible(island);
|
|
157
|
+
};
|
|
158
|
+
if (!loading && document.readyState === "loading") {
|
|
159
|
+
const observer = new MutationObserver((records) => {
|
|
160
|
+
for (const record of records) for (const node of Array.from(record.addedNodes)) consider(node);
|
|
161
|
+
});
|
|
162
|
+
observer.observe(document, {
|
|
163
|
+
childList: true,
|
|
164
|
+
subtree: true
|
|
165
|
+
});
|
|
166
|
+
const done = () => {
|
|
167
|
+
observer.disconnect();
|
|
168
|
+
parsed();
|
|
169
|
+
};
|
|
170
|
+
document.addEventListener("DOMContentLoaded", done, { once: true });
|
|
171
|
+
cleanups.push(() => {
|
|
172
|
+
observer.disconnect();
|
|
173
|
+
document.removeEventListener("DOMContentLoaded", done);
|
|
174
|
+
});
|
|
175
|
+
} else if (!loading) parsed();
|
|
176
|
+
}
|
|
177
|
+
export { BOOT_HYDRATED_ATTRIBUTE, BOOT_INTERACTION_EVENT, BOOT_ISLAND_ELEMENT, BOOT_VISIBLE_MARGIN, RUNTIME_GLOBAL, startBoot };
|
package/dist/client.d.mts
CHANGED
|
@@ -57,7 +57,8 @@ declare function startNavigation(options: NavigationOptions): {
|
|
|
57
57
|
declare function navigate(href: string, options?: NavigateOptions): Promise<void>;
|
|
58
58
|
/**
|
|
59
59
|
* Holding interactions that happen before the islx script has run. An inline script in the page
|
|
60
|
-
* captures a click or a submit on an island that has not hydrated (it is prevented and queued
|
|
60
|
+
* captures a click or a submit on an island that has not hydrated (it is prevented and queued; a
|
|
61
|
+
* click on a link only when the link stays on the page, `#…`),
|
|
61
62
|
* and announces a pointerdown or a focus (which go through). The runtime then hydrates those
|
|
62
63
|
* islands first and replays what was held.
|
|
63
64
|
*
|
package/dist/client.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as defineClientHooks, c as setClientHooks, d as valueHeaders, i as setActionNavigator, l as createValueStore, n as decodeActionReference, o as emit, r as setActionInterceptor, s as hookEventName, t as createServerReference, u as getValueStore } from "./_chunks/actions-C-IwUCKU.mjs";
|
|
2
2
|
import { C as RENDER_HEADER, I as readPostedAction, L as stripRuntimeFields } from "./_chunks/wire-QEQWBr5s.mjs";
|
|
3
|
-
import { i as REPLAYABLE_SELECTOR, n as PENDING_INTERACTIONS, r as PREHYDRATION_SCRIPT, t as INTERACTION_EVENT } from "./_chunks/prehydration-
|
|
3
|
+
import { i as REPLAYABLE_SELECTOR, n as PENDING_INTERACTIONS, r as PREHYDRATION_SCRIPT, t as INTERACTION_EVENT } from "./_chunks/prehydration-zEYsfFxW.mjs";
|
|
4
4
|
// src/client/forms.ts
|
|
5
5
|
/**
|
|
6
6
|
* Forms written in server components submit without reloading the page once JavaScript runs.
|
package/dist/compiler.d.mts
CHANGED
|
@@ -1,2 +1,24 @@
|
|
|
1
1
|
import { a as getActionId, i as TransformActionsResult, n as AstNode, o as hasModuleDirective, r as TransformActionsOptions, s as transformActions, t as ActionCompileError } from "./_chunks/actions-BCtIGvrP.mjs";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
// src/compiler/infer.d.ts
|
|
4
|
+
interface InferOptions {
|
|
5
|
+
/** Parses a module's source (TypeScript and JSX included) to an ESTree program. */
|
|
6
|
+
parse(file: string, code: string): AstNode;
|
|
7
|
+
/**
|
|
8
|
+
* Resolves an import to a source file of the app's own, or null for a package or anything
|
|
9
|
+
* unknown (which keeps `"load"`). Default: relative and root-absolute paths, with the usual
|
|
10
|
+
* extensions and index files.
|
|
11
|
+
*/
|
|
12
|
+
resolve?(specifier: string, importer: string): string | null;
|
|
13
|
+
}
|
|
14
|
+
interface Inference {
|
|
15
|
+
/** `"interaction"` when the islands can wait; null to keep `"load"`. */
|
|
16
|
+
strategy: "interaction" | null;
|
|
17
|
+
/** The source files the result read, the module itself first. */
|
|
18
|
+
files: string[];
|
|
19
|
+
/** Why the islands keep `"load"`. */
|
|
20
|
+
reason?: string;
|
|
21
|
+
}
|
|
22
|
+
/** Infers when the islands `file` exports hydrate; `code` is its source. */
|
|
23
|
+
declare function inferStrategy(file: string, code: string, options: InferOptions): Inference;
|
|
24
|
+
export { ActionCompileError, type AstNode, type InferOptions, type Inference, type TransformActionsOptions, type TransformActionsResult, getActionId, hasModuleDirective, inferStrategy, transformActions };
|
package/dist/compiler.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { n as ActionCompileError, r as getActionId, i as hasModuleDirective, t as inferStrategy, a as transformActions } from "./_chunks/infer-BIVT5aDz.mjs";
|
package/dist/react/client.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as scheduleHydration, i as isIslandStrategy, n as IslandStrategy, r as ScheduleOptions, t as ISLAND_STRATEGIES } from "../_chunks/schedule-Dw14dW0H.mjs";
|
|
2
2
|
import { m as HYDRATED_ATTRIBUTE } from "../_chunks/wire-Dipqh-EB.mjs";
|
|
3
3
|
import { t as ValueStore } from "../_chunks/value-store-Dm-7xJ6W.mjs";
|
|
4
|
-
import { a as ServerTreeLayoutOptions, c as createServerTreeLayout, g as isolateIslands, i as ServerTreeLayout, n as PAYLOAD_ONLY_ATTRIBUTE, r as ServerTreeElementOptions, s as createServerTreeElement, u as updateServerTrees, v as withinClientRoot } from "../_chunks/tree-
|
|
4
|
+
import { a as ServerTreeLayoutOptions, c as createServerTreeLayout, g as isolateIslands, i as ServerTreeLayout, n as PAYLOAD_ONLY_ATTRIBUTE, r as ServerTreeElementOptions, s as createServerTreeElement, u as updateServerTrees, v as withinClientRoot } from "../_chunks/tree-CV13RsJv.mjs";
|
|
5
5
|
import * as React from "react";
|
|
6
6
|
|
|
7
7
|
// src/react/hydrate.d.ts
|
package/dist/react/client.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { d as valueHeaders, o as emit, t as createServerReference, u as getValueStore } from "../_chunks/actions-C-IwUCKU.mjs";
|
|
2
2
|
import { i as decodeTagged, n as NOT_A_VALUE, r as decode, u as setOwn } from "../_chunks/codec-C8to-RQW.mjs";
|
|
3
3
|
import { F as getTag, f as FORM_STATE_SCRIPT_TYPE, h as ISLAND_ELEMENT, m as HYDRATED_ATTRIBUTE, w as SLOT_ELEMENT, x as PROPS_SCRIPT_TYPE, y as PROMISE_SCRIPT_TYPE } from "../_chunks/wire-QEQWBr5s.mjs";
|
|
4
|
-
import { i as getContexts, o as isolateIslands, u as withinClientRoot } from "../_chunks/island-
|
|
5
|
-
import { i as createServerTreeLayout, n as PAYLOAD_ONLY_ATTRIBUTE, o as updateServerTrees, r as createServerTreeElement } from "../_chunks/tree-
|
|
6
|
-
import { n as isIslandStrategy, r as scheduleHydration, t as ISLAND_STRATEGIES } from "../_chunks/schedule-
|
|
4
|
+
import { i as getContexts, o as isolateIslands, u as withinClientRoot } from "../_chunks/island-DXAGP4FN.mjs";
|
|
5
|
+
import { i as createServerTreeLayout, n as PAYLOAD_ONLY_ATTRIBUTE, o as updateServerTrees, r as createServerTreeElement } from "../_chunks/tree-BQphP23Y.mjs";
|
|
6
|
+
import { n as isIslandStrategy, r as scheduleHydration, t as ISLAND_STRATEGIES } from "../_chunks/schedule-Cwn9vQL0.mjs";
|
|
7
7
|
import * as React from "react";
|
|
8
8
|
import { hydrateRoot } from "react-dom/client";
|
|
9
9
|
// src/react/hydrate.ts
|
package/dist/react/server.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as ReactFormState } from "../_chunks/handle-C0N9ZyNV.mjs";
|
|
2
|
-
import { _ as setRenderStateResolver, d as ClientReference, f as IslandRenderState, g as isolateIslands, h as getClientReference, l as renderServerTree, m as createIsland, n as PAYLOAD_ONLY_ATTRIBUTE, o as ServerTreeRenderOptions, p as IslandsProvider, t as Outlet, v as withinClientRoot } from "../_chunks/tree-
|
|
2
|
+
import { _ as setRenderStateResolver, d as ClientReference, f as IslandRenderState, g as isolateIslands, h as getClientReference, l as renderServerTree, m as createIsland, n as PAYLOAD_ONLY_ATTRIBUTE, o as ServerTreeRenderOptions, p as IslandsProvider, t as Outlet, v as withinClientRoot } from "../_chunks/tree-CV13RsJv.mjs";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { RenderToReadableStreamOptions } from "react-dom/server";
|
|
5
5
|
|
package/dist/react/server.mjs
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
import { a as encode } from "../_chunks/codec-C8to-RQW.mjs";
|
|
2
2
|
import { f as FORM_STATE_SCRIPT_TYPE } from "../_chunks/wire-QEQWBr5s.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { RUNTIME_GLOBAL } from "../boot.mjs";
|
|
4
|
+
import { r as PREHYDRATION_SCRIPT } from "../_chunks/prehydration-zEYsfFxW.mjs";
|
|
5
|
+
import { i as encodeActionReference } from "../_chunks/actions-CvQ0-zjg.mjs";
|
|
5
6
|
import { t as getBuildDefaults } from "../_chunks/build-COIcs7wm.mjs";
|
|
6
7
|
import { a as parseHeldValues, n as addressValues, o as selectValuesToSend, r as escapeScriptJson } from "../_chunks/values-37UIzxM0.mjs";
|
|
7
|
-
import { c as setIslandServerHook, i as getContexts, l as setRenderStateResolver, n as createIsland, o as isolateIslands, r as getClientReference, s as runtimeTagged, t as IslandsProvider, u as withinClientRoot } from "../_chunks/island-
|
|
8
|
-
import { a as renderServerTree, n as PAYLOAD_ONLY_ATTRIBUTE, t as Outlet } from "../_chunks/tree-
|
|
8
|
+
import { c as setIslandServerHook, i as getContexts, l as setRenderStateResolver, n as createIsland, o as isolateIslands, r as getClientReference, s as runtimeTagged, t as IslandsProvider, u as withinClientRoot } from "../_chunks/island-DXAGP4FN.mjs";
|
|
9
|
+
import { a as renderServerTree, n as PAYLOAD_ONLY_ATTRIBUTE, t as Outlet } from "../_chunks/tree-BQphP23Y.mjs";
|
|
9
10
|
import * as React from "react";
|
|
10
11
|
// src/react/server.ts
|
|
11
12
|
/**
|
|
12
13
|
* @farm.js/islx/react/server: rendering a React page with islands. Importing it gives islands the
|
|
13
14
|
* server code they need (values, action references); `renderToStream` renders a page.
|
|
14
15
|
*/
|
|
15
|
-
|
|
16
|
+
let promisePrefix;
|
|
16
17
|
let promiseCount = 0;
|
|
18
|
+
function nextPromiseName() {
|
|
19
|
+
promisePrefix ??= `${Array.from(crypto.getRandomValues(/* @__PURE__ */ new Uint32Array(2)), (part) => part.toString(36)).join("")}.`;
|
|
20
|
+
return promisePrefix + (promiseCount++).toString(36);
|
|
21
|
+
}
|
|
17
22
|
function isThenable(value) {
|
|
18
23
|
return value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
19
24
|
}
|
|
@@ -23,7 +28,7 @@ setIslandServerHook({
|
|
|
23
28
|
const addressed = addressValues(props, { encodeSpecial: (value) => {
|
|
24
29
|
if (value && typeof value === "object" && runtimeTagged.has(value)) return value;
|
|
25
30
|
if (isThenable(value)) {
|
|
26
|
-
const name =
|
|
31
|
+
const name = nextPromiseName();
|
|
27
32
|
promises.push({
|
|
28
33
|
name,
|
|
29
34
|
promise: value
|
|
@@ -84,9 +89,12 @@ async function renderToStream(element, { request, formState, bootstrap = true, p
|
|
|
84
89
|
held: held && held.size > 0 ? held : null,
|
|
85
90
|
sent: /* @__PURE__ */ new Set()
|
|
86
91
|
} }, element, formState ? React.createElement(FormStateScript, { formState }) : null);
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
const
|
|
92
|
+
const defaults = getBuildDefaults();
|
|
93
|
+
const entry = bootstrap ? defaults.entry : void 0;
|
|
94
|
+
const boot = entry !== void 0 ? defaults.boot : void 0;
|
|
95
|
+
const bootstrapModules = entry ? [...options.bootstrapModules ?? [], boot ?? entry] : options.bootstrapModules;
|
|
96
|
+
const runtime = boot ? `window.${RUNTIME_GLOBAL}=${escapeScriptJson(JSON.stringify(entry))};` : "";
|
|
97
|
+
const bootstrapScriptContent = prehydration ?? entry !== void 0 ? `${PREHYDRATION_SCRIPT}${runtime}${options.bootstrapScriptContent ?? ""}` : runtime || options.bootstrapScriptContent ? `${runtime}${options.bootstrapScriptContent ?? ""}` : void 0;
|
|
90
98
|
const { renderToReadableStream } = await import("react-dom/server");
|
|
91
99
|
const stream = await renderToReadableStream(tree, {
|
|
92
100
|
...options,
|
package/dist/react.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { f as IslandRenderState, g as isolateIslands, l as renderServerTree, m as createIsland, o as ServerTreeRenderOptions, p as IslandsProvider, t as Outlet, v as withinClientRoot } from "./_chunks/tree-
|
|
1
|
+
import { f as IslandRenderState, g as isolateIslands, l as renderServerTree, m as createIsland, o as ServerTreeRenderOptions, p as IslandsProvider, t as Outlet, v as withinClientRoot } from "./_chunks/tree-CV13RsJv.mjs";
|
|
2
2
|
import { n as IslandStrategy } from "./_chunks/schedule-Dw14dW0H.mjs";
|
|
3
3
|
export { type IslandRenderState, type IslandStrategy, IslandsProvider, Outlet, type ServerTreeRenderOptions, createIsland, isolateIslands, renderServerTree, withinClientRoot };
|
package/dist/react.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as createIsland, o as isolateIslands, t as IslandsProvider, u as withinClientRoot } from "./_chunks/island-
|
|
2
|
-
import { a as renderServerTree, t as Outlet } from "./_chunks/tree-
|
|
1
|
+
import { n as createIsland, o as isolateIslands, t as IslandsProvider, u as withinClientRoot } from "./_chunks/island-DXAGP4FN.mjs";
|
|
2
|
+
import { a as renderServerTree, t as Outlet } from "./_chunks/tree-BQphP23Y.mjs";
|
|
3
3
|
export { IslandsProvider, Outlet, createIsland, isolateIslands, renderServerTree, withinClientRoot };
|
package/dist/server.d.mts
CHANGED
|
@@ -71,15 +71,15 @@ declare class SealError extends Error {
|
|
|
71
71
|
interface ActionKeys {
|
|
72
72
|
/** The key new values are sealed with. */
|
|
73
73
|
current: CryptoKey;
|
|
74
|
-
/** Its id, written into each sealed value (
|
|
74
|
+
/** Its id, written into each sealed value (a 32-bit unsigned integer). */
|
|
75
75
|
currentId: number;
|
|
76
76
|
/**
|
|
77
|
-
* Every key that opens a value, by id: the current one and earlier ones still accepted.
|
|
78
|
-
*
|
|
77
|
+
* Every key that opens a value, by id: the current one and earlier ones still accepted. Two keys
|
|
78
|
+
* may still share an id; each is tried.
|
|
79
79
|
*/
|
|
80
80
|
byId: ReadonlyMap<number, readonly CryptoKey[]>;
|
|
81
81
|
}
|
|
82
|
-
/** A new random key, as base64url: what `
|
|
82
|
+
/** A new random key, as base64url: what `ISLX_ACTIONS_KEY` holds. */
|
|
83
83
|
declare function generateActionKey(): string;
|
|
84
84
|
/**
|
|
85
85
|
* The keys values are sealed and opened with. `current` seals; `previous` keys still open
|
|
@@ -187,6 +187,11 @@ declare function isSameOriginRequest(request: Request, allowedOrigins: readonly
|
|
|
187
187
|
interface BuildDefaults {
|
|
188
188
|
/** The URL of the browser entry `renderToStream` adds to pages. */
|
|
189
189
|
entry?: string;
|
|
190
|
+
/**
|
|
191
|
+
* The URL of the boot entry (`@farm.js/islx/boot`): pages start with it instead, and it loads
|
|
192
|
+
* `entry` when the page first needs it. An island that hydrates at load preloads `entry`.
|
|
193
|
+
*/
|
|
194
|
+
boot?: string;
|
|
190
195
|
/** A key made for this build: every instance of one build shares it. */
|
|
191
196
|
key?: string;
|
|
192
197
|
/**
|
package/dist/server.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as parseHeldValues, i as hashValue, n as addressValues, o as selectValuesToSend, r as escapeScriptJson, t as VALUE_MIN_LENGTH } from "./_chunks/values-37UIzxM0.mjs";
|
|
2
|
-
import { a as getActionReference, c as resolveAction, d as generateActionKey, f as sealBound, i as encodeActionReference, l as SealError, n as configureActionKeys, o as registerInlineAction, p as unsealBound, r as decodeActionReference, s as registerServerReference, t as bindInlineAction, u as createActionKeys } from "./_chunks/actions-
|
|
2
|
+
import { a as getActionReference, c as resolveAction, d as generateActionKey, f as sealBound, i as encodeActionReference, l as SealError, n as configureActionKeys, o as registerInlineAction, p as unsealBound, r as decodeActionReference, s as registerServerReference, t as bindInlineAction, u as createActionKeys } from "./_chunks/actions-CvQ0-zjg.mjs";
|
|
3
3
|
import { a as encode, r as decode } from "./_chunks/codec-C8to-RQW.mjs";
|
|
4
4
|
import { I as readPostedAction, L as stripRuntimeFields, N as attachmentField, n as ACTION_KEY_FIELD, o as BOUND_FIELD, r as ACTION_STALE_HEADER, s as CALL_FIELD, t as ACTION_HEADER } from "./_chunks/wire-QEQWBr5s.mjs";
|
|
5
5
|
import { n as setBuildDefaults, t as getBuildDefaults } from "./_chunks/build-COIcs7wm.mjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as IslandsProvider } from "../_chunks/island-
|
|
1
|
+
import { t as IslandsProvider } from "../_chunks/island-DXAGP4FN.mjs";
|
|
2
2
|
import { A as VALUES_HEADER, C as RENDER_HEADER } from "../_chunks/wire-QEQWBr5s.mjs";
|
|
3
3
|
import { a as parseHeldValues } from "../_chunks/values-37UIzxM0.mjs";
|
|
4
4
|
import * as React from "react";
|
package/dist/tanstack-start.mjs
CHANGED