@ogygia/core 0.12.2 → 0.13.0
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/LateIsland.svelte +3 -2
- package/dist/LateIslandAwait.svelte +6 -2
- package/dist/Region.svelte +22 -33
- package/dist/boundary.d.ts +0 -2
- package/dist/boundary.js +8 -6
- package/dist/compiler/debarrel/barrel.d.ts +15 -8
- package/dist/compiler/debarrel/barrel.js +92 -45
- package/dist/compiler/debarrel/plugin.js +41 -17
- package/dist/compiler/dev/dev-hmr.d.ts +3 -0
- package/dist/compiler/dev/dev-hmr.js +3 -0
- package/dist/compiler/driver.js +11 -4
- package/dist/compiler/flags.js +21 -7
- package/dist/compiler/fouc-css.js +5 -1
- package/dist/compiler/kit.js +5 -1
- package/dist/compiler/link/build-output.js +12 -3
- package/dist/compiler/macros/bake.js +18 -4
- package/dist/compiler/macros/dollar.js +6 -1
- package/dist/compiler/macros/source.js +6 -1
- package/dist/compiler/macros/store.js +10 -2
- package/dist/compiler/macros/wire.js +6 -1
- package/dist/compiler/parse/scan.js +10 -3
- package/dist/compiler/region/transform.js +188 -74
- package/dist/context-bridge.js +13 -5
- package/dist/context.d.ts +9 -0
- package/dist/context.js +30 -1
- package/dist/document.d.ts +1 -1
- package/dist/document.js +7 -1
- package/dist/early-holes-head.d.ts +5 -0
- package/dist/early-holes-head.js +20 -0
- package/dist/early-holes.d.ts +34 -0
- package/dist/early-holes.js +51 -0
- package/dist/entry-hydrate.js +9 -12
- package/dist/events/bus.js +7 -2
- package/dist/events/schema.d.ts +2 -2
- package/dist/fn-transport.js +4 -3
- package/dist/hooks.js +94 -163
- package/dist/insights/page-assets.js +11 -3
- package/dist/insights/page-insights.d.ts +0 -2
- package/dist/insights/page-insights.js +14 -10
- package/dist/insights/session-insights.js +2 -2
- package/dist/internal-instruments.d.ts +3 -1
- package/dist/internal-instruments.js +3 -1
- package/dist/internal-server.d.ts +3 -2
- package/dist/internal-server.js +3 -2
- package/dist/internal.d.ts +1 -2
- package/dist/internal.js +1 -2
- package/dist/keep-fallback.d.ts +0 -2
- package/dist/keep-fallback.js +4 -5
- package/dist/live-transport.js +3 -2
- package/dist/messages/build.d.ts +585 -0
- package/dist/messages/build.js +800 -0
- package/dist/messages/core.d.ts +464 -0
- package/dist/messages/core.js +843 -0
- package/dist/messages/define.d.ts +62 -0
- package/dist/messages/define.js +49 -0
- package/dist/messages/index.d.ts +6 -0
- package/dist/messages/index.js +6 -0
- package/dist/messages/island.d.ts +4 -0
- package/dist/messages/island.js +34 -0
- package/dist/messages/lazy.d.ts +3 -0
- package/dist/messages/lazy.js +22 -0
- package/dist/messages/prose.d.ts +15 -0
- package/dist/messages/prose.js +43 -0
- package/dist/messages/server.d.ts +142 -0
- package/dist/messages/server.js +246 -0
- package/dist/nested.d.ts +3 -0
- package/dist/nested.js +8 -1
- package/dist/plugin/css.js +14 -13
- package/dist/plugin/facts.d.ts +2 -0
- package/dist/plugin/facts.js +10 -6
- package/dist/plugin/hooks.d.ts +7 -17
- package/dist/plugin/hooks.js +32 -4
- package/dist/plugin/index.d.ts +9 -2
- package/dist/plugin/request-scope.d.ts +20 -0
- package/dist/plugin/request-scope.js +149 -0
- package/dist/plugin/server.d.ts +20 -2
- package/dist/plugin/server.js +98 -28
- package/dist/plugin/testing.d.ts +6 -0
- package/dist/plugin/testing.js +14 -2
- package/dist/policies.d.ts +21 -0
- package/dist/policies.js +66 -0
- package/dist/preference.js +6 -1
- package/dist/preload.js +6 -9
- package/dist/ref-watch.d.ts +0 -10
- package/dist/ref-watch.js +14 -1
- package/dist/ref.js +17 -5
- package/dist/region-snippet.js +9 -3
- package/dist/region.js +2 -1
- package/dist/report-thrown.d.ts +9 -0
- package/dist/report-thrown.js +15 -0
- package/dist/rules.d.ts +17 -0
- package/dist/rules.js +57 -0
- package/dist/runtime/beacon.d.ts +0 -4
- package/dist/runtime/beacon.js +58 -43
- package/dist/runtime/boot-link.js +19 -2
- package/dist/runtime/client-hooks.js +2 -1
- package/dist/runtime/concurrency.d.ts +16 -5
- package/dist/runtime/concurrency.js +123 -7
- package/dist/runtime/core.d.ts +3 -1
- package/dist/runtime/core.js +718 -384
- package/dist/runtime/devalue-lane.d.ts +13 -0
- package/dist/runtime/devalue-lane.js +49 -0
- package/dist/runtime/disclose-version.d.ts +1 -0
- package/dist/runtime/disclose-version.js +14 -0
- package/dist/runtime/early-holes.d.ts +4 -0
- package/dist/runtime/early-holes.js +40 -0
- package/dist/runtime/entry-locations.js +40 -49
- package/dist/runtime/foreign-props.d.ts +0 -7
- package/dist/runtime/foreign-props.js +2 -1
- package/dist/runtime/form-continuity.d.ts +2 -2
- package/dist/runtime/form-continuity.js +30 -8
- package/dist/runtime/frame-nav.d.ts +7 -1
- package/dist/runtime/frame-nav.js +84 -18
- package/dist/runtime/frame-store.d.ts +25 -16
- package/dist/runtime/frame-store.js +124 -98
- package/dist/runtime/frames.js +8 -4
- package/dist/runtime/hole-facts.js +6 -7
- package/dist/runtime/hole-fetch.d.ts +17 -0
- package/dist/runtime/hole-fetch.js +47 -0
- package/dist/runtime/hydrate-core.d.ts +4 -4
- package/dist/runtime/hydrate-core.js +80 -64
- package/dist/runtime/import-again.d.ts +33 -0
- package/dist/runtime/import-again.js +217 -0
- package/dist/runtime/interaction-replay.d.ts +5 -3
- package/dist/runtime/interaction-replay.js +6 -6
- package/dist/runtime/interaction.d.ts +14 -3
- package/dist/runtime/interaction.js +46 -23
- package/dist/runtime/kit-page-thread.svelte.d.ts +2 -1
- package/dist/runtime/kit-page-thread.svelte.js +44 -20
- package/dist/runtime/lakes.d.ts +1 -1
- package/dist/runtime/lakes.js +18 -5
- package/dist/runtime/live.d.ts +1 -2
- package/dist/runtime/live.js +6 -8
- package/dist/runtime/load-scheduler.d.ts +29 -18
- package/dist/runtime/load-scheduler.js +236 -136
- package/dist/runtime/nav-handle.js +25 -6
- package/dist/runtime/navigation.d.ts +24 -0
- package/dist/runtime/navigation.js +24 -0
- package/dist/runtime/ownership.d.ts +1 -1
- package/dist/runtime/page-defer.js +3 -3
- package/dist/runtime/parse-html.d.ts +15 -4
- package/dist/runtime/parse-html.js +24 -5
- package/dist/runtime/pushable-props.svelte.d.ts +21 -0
- package/dist/runtime/pushable-props.svelte.js +37 -0
- package/dist/runtime/region-endpoint-url.js +4 -6
- package/dist/runtime/region-machines.d.ts +111 -0
- package/dist/runtime/region-machines.js +97 -0
- package/dist/runtime/region-sheets.d.ts +31 -0
- package/dist/runtime/region-sheets.js +49 -0
- package/dist/runtime/restore-report.d.ts +1 -0
- package/dist/runtime/restore-report.js +36 -0
- package/dist/runtime/restore.d.ts +5 -2
- package/dist/runtime/restore.js +33 -14
- package/dist/runtime/router-nav.d.ts +32 -12
- package/dist/runtime/router-nav.js +320 -228
- package/dist/runtime/router.d.ts +83 -19
- package/dist/runtime/router.js +297 -129
- package/dist/runtime/rules.d.ts +35 -0
- package/dist/runtime/rules.js +137 -0
- package/dist/runtime/schedule.d.ts +6 -3
- package/dist/runtime/schedule.js +172 -57
- package/dist/runtime/seeds.d.ts +5 -1
- package/dist/runtime/seeds.js +11 -5
- package/dist/runtime/session.d.ts +46 -7
- package/dist/runtime/session.js +78 -10
- package/dist/runtime/slots.d.ts +53 -20
- package/dist/runtime/slots.js +2 -3
- package/dist/runtime/soft-refresh.d.ts +16 -0
- package/dist/runtime/soft-refresh.js +14 -0
- package/dist/runtime/svelte-warnings.d.ts +4 -10
- package/dist/runtime/svelte-warnings.js +7 -4
- package/dist/runtime/wire-classes.js +21 -8
- package/dist/runtime/wire-format.js +6 -3
- package/dist/script.js +8 -7
- package/dist/seed-ref-reviver.d.ts +0 -9
- package/dist/seed-ref-reviver.js +2 -1
- package/dist/seed-refs.d.ts +46 -36
- package/dist/seed-refs.js +131 -92
- package/dist/server/document-tail.d.ts +6 -0
- package/dist/server/document-tail.js +7 -1
- package/dist/server/early-holes-csp.d.ts +14 -0
- package/dist/server/early-holes-csp.js +73 -0
- package/dist/server/page-facts.d.ts +4 -1
- package/dist/server/page-facts.js +4 -1
- package/dist/server/page-seed.d.ts +2 -2
- package/dist/server/page-seed.js +104 -11
- package/dist/server/page-stream.d.ts +14 -1
- package/dist/server/page-stream.js +119 -2
- package/dist/server/personal-response.d.ts +0 -5
- package/dist/server/personal-response.js +6 -2
- package/dist/server/props-wire.js +5 -1
- package/dist/server/region-endpoint.js +10 -2
- package/dist/server/render-cache.d.ts +24 -20
- package/dist/server/render-cache.js +99 -40
- package/dist/server/render-page.js +46 -15
- package/dist/server/request-stats.d.ts +10 -8
- package/dist/server/request-stats.js +20 -12
- package/dist/server/rules.d.ts +11 -0
- package/dist/server/rules.js +64 -0
- package/dist/server/signing-key.js +31 -18
- package/dist/server/stream-regions.d.ts +14 -1
- package/dist/server/stream-regions.js +38 -2
- package/dist/shared-state.js +5 -1
- package/dist/shims/app-navigation.js +3 -2
- package/dist/shims/page-store.svelte.js +16 -2
- package/dist/source.js +7 -2
- package/dist/store-transport.js +12 -5
- package/dist/transport.js +3 -2
- package/dist/vite/index.js +83 -74
- package/dist/vite/kit-dirs.js +7 -1
- package/dist/vite/options.d.ts +2 -1
- package/dist/vite/options.js +11 -20
- package/dist/vite/package-files.js +13 -3
- package/dist/vite/paths.d.ts +2 -0
- package/dist/vite/paths.js +4 -4
- package/dist/vite/plugin-api.d.ts +6 -5
- package/dist/vite/plugin-api.js +42 -14
- package/dist/vite/style-preprocess.js +10 -3
- package/package.json +8 -1
- package/dist/KeepHost.svelte +0 -19
- package/dist/KeepHost.svelte.d.ts +0 -10
- package/dist/LiveHost.svelte +0 -19
- package/dist/LiveHost.svelte.d.ts +0 -10
- package/dist/NestedProvider.svelte +0 -13
- package/dist/NestedProvider.svelte.d.ts +0 -8
- package/dist/runtime/page-cache.d.ts +0 -23
- package/dist/runtime/page-cache.js +0 -74
|
@@ -0,0 +1,843 @@
|
|
|
1
|
+
import { define_messages } from "./define.js";
|
|
2
|
+
import { prose } from "./prose.js";
|
|
3
|
+
// src/messages/core.ts
|
|
4
|
+
/**
|
|
5
|
+
* EVERY MESSAGE OGYGIA'S RUNTIME PRINTS IN THE BROWSER, in one place: its code, whether it is thrown
|
|
6
|
+
* or logged, its wording, and what to do about it (./define.ts says how the system works).
|
|
7
|
+
*
|
|
8
|
+
* throw new OgygiaError('goto_not_http');
|
|
9
|
+
* warn('island_hydrate_failed', { entry }, err);
|
|
10
|
+
*
|
|
11
|
+
* Dev: the wording and the code's page. A production build: the page's link alone. The runtime's lazy
|
|
12
|
+
* chunks take the same two from ./lazy.ts, island-side code (a shim a component imports) from
|
|
13
|
+
* ./island.ts — neither imports this module (see there).
|
|
14
|
+
*/
|
|
15
|
+
const BUG = "An ogygia bug: please report it with the page that shows it.";
|
|
16
|
+
/** Each message's arguments are its `text`'s: the one place they are written. */
|
|
17
|
+
/** The errors: `throw new OgygiaError(code, args)`, or `console.error(new OgygiaError(…), err)` for a
|
|
18
|
+
* failure that is caught. */
|
|
19
|
+
const ERRORS = {
|
|
20
|
+
goto_not_http: {
|
|
21
|
+
text: () => "goto() only supports http(s) URLs",
|
|
22
|
+
details: () => prose`
|
|
23
|
+
\`goto()\` was called with a URL whose scheme is not \`http:\` or \`https:\` (a \`mailto:\`,
|
|
24
|
+
a \`javascript:\`, a custom scheme). Navigate to it with a plain link or
|
|
25
|
+
\`location.assign()\` instead.
|
|
26
|
+
`
|
|
27
|
+
},
|
|
28
|
+
goto_cross_origin: {
|
|
29
|
+
text: () => "goto() only supports same-origin URLs (pass { external: true } to leave)",
|
|
30
|
+
details: () => prose`
|
|
31
|
+
\`goto()\` navigates inside the app, so a URL on another origin is refused. To leave the
|
|
32
|
+
app, pass \`{ external: true }\`: \`goto(url, { external: true })\` does a full page load.
|
|
33
|
+
`
|
|
34
|
+
},
|
|
35
|
+
island_load_failed: {
|
|
36
|
+
text: (a) => `island entry failed to load: ${a.entry}`,
|
|
37
|
+
details: () => prose`
|
|
38
|
+
The island's module could not be fetched, so the island stays as its server HTML. This is
|
|
39
|
+
a load error, not a hydration error: the file is missing or the network failed. After a
|
|
40
|
+
deploy, ogygia retries the current build's file first.
|
|
41
|
+
`
|
|
42
|
+
},
|
|
43
|
+
chunk_reload_needed: {
|
|
44
|
+
text: (a) => `a file this page needs cannot load until the page reloads: ${a.url}`,
|
|
45
|
+
details: () => prose`
|
|
46
|
+
A file the runtime loads when it needs it (an island's code, a part of the runtime) failed,
|
|
47
|
+
and asking for it again failed the same way although the file itself came: one of the files
|
|
48
|
+
it imports failed to download, and the browser keeps that failure for the life of the page.
|
|
49
|
+
No retry can load it, so ogygia stops asking. The islands that need it stay as their server
|
|
50
|
+
HTML until the page reloads. Said once per page.
|
|
51
|
+
`
|
|
52
|
+
},
|
|
53
|
+
runtime_load_failed: {
|
|
54
|
+
text: () => "the ogygia runtime failed to load: no island on this page wakes",
|
|
55
|
+
details: () => prose`
|
|
56
|
+
The runtime's script, or one of the files it imports, failed to download (a dropped
|
|
57
|
+
connection, a file a deploy removed). The runtime never ran, so every island on the page
|
|
58
|
+
stays as its server HTML: links and forms still work, nothing interactive does. Reloading
|
|
59
|
+
the page loads it again. Printed by the runtime's script tag itself, as the page link alone.
|
|
60
|
+
`
|
|
61
|
+
},
|
|
62
|
+
island_load_failed_stale_deps: {
|
|
63
|
+
text: (a) => prose`
|
|
64
|
+
island entry failed to load: ${a.entry}
|
|
65
|
+
|
|
66
|
+
The module could not be FETCHED (not a hydration error). In dev this almost always means
|
|
67
|
+
Vite re-optimized dependencies and rotated its optimizer hash while this tab was open, so
|
|
68
|
+
its dep imports 404. Recovering… Original error:
|
|
69
|
+
`,
|
|
70
|
+
details: () => prose`
|
|
71
|
+
Dev only. Vite re-optimized its dependencies while the tab was open, so the island's
|
|
72
|
+
imports point at files that no longer exist. ogygia reloads the page to recover.
|
|
73
|
+
`
|
|
74
|
+
},
|
|
75
|
+
island_hydrate_failed: {
|
|
76
|
+
text: (a) => `hydration failed for ${a.entry}`,
|
|
77
|
+
details: () => prose`
|
|
78
|
+
The island's module loaded, but hydrating it threw. The error follows the message: it is
|
|
79
|
+
usually the component itself throwing while it initializes.
|
|
80
|
+
`
|
|
81
|
+
},
|
|
82
|
+
interaction_hydrate_failed: {
|
|
83
|
+
text: () => "interaction island failed to hydrate — leaving it static.",
|
|
84
|
+
details: () => prose`
|
|
85
|
+
An island waking on interaction threw while it hydrated, so it stays as its server HTML.
|
|
86
|
+
The click that woke it is replayed on that HTML. The error follows the message.
|
|
87
|
+
`
|
|
88
|
+
},
|
|
89
|
+
restore_markup_broken: {
|
|
90
|
+
text: (a) => `the transform broke hydration markup: ${a.diff}`,
|
|
91
|
+
details: () => prose`
|
|
92
|
+
A transform rewrote a restored region's markup so that its hydration markers no longer
|
|
93
|
+
match. \`diff\` names the first difference. (The restore runs as a self-contained script,
|
|
94
|
+
so it prints this code's link itself.)
|
|
95
|
+
`
|
|
96
|
+
},
|
|
97
|
+
client_hooks_init_failed: {
|
|
98
|
+
text: () => "hooks.client init failed:",
|
|
99
|
+
details: () => "The app's `hooks.client` `init()` threw. The error follows the message."
|
|
100
|
+
},
|
|
101
|
+
wired_class_foreign: {
|
|
102
|
+
text: () => prose`
|
|
103
|
+
a wired class crossed a build boundary: foreign (stitched-fragment) island props must be
|
|
104
|
+
plain data — wired live objects cannot reunite across two svelte runtimes. Pass the
|
|
105
|
+
underlying data instead.
|
|
106
|
+
`,
|
|
107
|
+
details: () => prose`
|
|
108
|
+
A stitched fragment's island received a wired object (a class registered with ogygia's
|
|
109
|
+
wire) from another build. Two Svelte runtimes cannot share it. Pass plain data instead.
|
|
110
|
+
`
|
|
111
|
+
},
|
|
112
|
+
devalue_not_loaded: {
|
|
113
|
+
text: () => "a devalue-lane payload was read before devalue loaded (load_devalue() first)",
|
|
114
|
+
details: () => BUG
|
|
115
|
+
},
|
|
116
|
+
slot_not_linked: {
|
|
117
|
+
text: (a) => `runtime chunk used \`slots.${a.name}\` before the boot linked it`,
|
|
118
|
+
details: () => BUG
|
|
119
|
+
},
|
|
120
|
+
boundary_refused: {
|
|
121
|
+
text: (a) => `${a.site} — og.$ value${a.path ? ` @ ${a.path}` : ""}: ${a.detail}${a.more ? ` (+${a.more} more)` : ""}`,
|
|
122
|
+
details: () => prose`
|
|
123
|
+
A value marked with \`import.meta.og.$\` cannot cross into an island: a DOM node, a bare
|
|
124
|
+
function, a class with no wire codec, a secret. It fails where it is marked, so the file
|
|
125
|
+
and line point at it. Pass plain data, or give the class a codec.
|
|
126
|
+
`
|
|
127
|
+
},
|
|
128
|
+
function_prop_cannot_cross: {
|
|
129
|
+
text: (a) => prose`
|
|
130
|
+
${a.where} is a function that can't cross the island boundary — ${a.reason}. Island props
|
|
131
|
+
must be SERIALIZABLE; a function crosses only as a Svelte snippet that freezes to HTML, and
|
|
132
|
+
this one didn't. Usually one of:
|
|
133
|
+
|
|
134
|
+
• it's a PLAIN function (an event handler / callback) — those can't cross into an island;
|
|
135
|
+
pass serializable data as props and keep the behavior inside the island component;
|
|
136
|
+
|
|
137
|
+
• it's a snippet WITH PARAMETERS — declare it as a {#snippet} so it crosses LIVE, or pass
|
|
138
|
+
its data as props;
|
|
139
|
+
|
|
140
|
+
• it's children containing a NESTED island — keep those out of frozen children for now.
|
|
141
|
+
`,
|
|
142
|
+
details: () => prose`
|
|
143
|
+
An island's props must be serializable. A function only crosses as a snippet that freezes
|
|
144
|
+
to HTML, and this one could not.
|
|
145
|
+
|
|
146
|
+
A plain function (an event handler, a callback) never crosses: keep the behavior inside the
|
|
147
|
+
island and pass data. A snippet with parameters crosses live when it is declared as a
|
|
148
|
+
snippet. Children that contain another island cannot be frozen yet.
|
|
149
|
+
`
|
|
150
|
+
},
|
|
151
|
+
region_snippet_on_client: {
|
|
152
|
+
text: () => prose`
|
|
153
|
+
region_snippet(fn) freezes a snippet by server-rendering it — call it during SSR, not on
|
|
154
|
+
the client. Pass a raw { render, setup } region snippet for client-constructed regions.
|
|
155
|
+
`,
|
|
156
|
+
details: () => prose`
|
|
157
|
+
\`region_snippet(fn)\` renders the snippet on the server to freeze it. In the browser, build
|
|
158
|
+
the region from a raw \`{ render, setup }\` snippet instead.
|
|
159
|
+
`
|
|
160
|
+
},
|
|
161
|
+
raw_region_on_client: {
|
|
162
|
+
text: () => prose`
|
|
163
|
+
a \`with { region: 'raw' }\` component must be turned into a region on the server (the
|
|
164
|
+
signer lives server-side). Call region() in a load / remote / render context, not in client
|
|
165
|
+
code.
|
|
166
|
+
`,
|
|
167
|
+
details: () => prose`
|
|
168
|
+
A held region is signed on the server, so \`region()\` on a \`with { region: 'raw' }\`
|
|
169
|
+
component must run there: in a load, a remote function or a render.
|
|
170
|
+
`
|
|
171
|
+
},
|
|
172
|
+
held_region_plain_import: {
|
|
173
|
+
text: () => prose`
|
|
174
|
+
a held region reached the wire but its component is a plain import, so nothing built a
|
|
175
|
+
chunk for it. \`await\` the region before returning it from a remote/load — an awaited
|
|
176
|
+
region bakes its SSR HTML and crosses as an HTML-only ticket. Or import the component
|
|
177
|
+
\`with { region: 'raw' }\` (or a \`wake:\` mark) to make it a signed, fetchable capability. On
|
|
178
|
+
a csr=false page you can also skip the wire entirely: call \`get()\` in a universal
|
|
179
|
+
\`+page.ts\` load / the component — its data reaches the render by reference.
|
|
180
|
+
`,
|
|
181
|
+
details: () => prose`
|
|
182
|
+
A region returned from a load or a remote function has to travel: as HTML, or as a signed
|
|
183
|
+
address the browser fetches. This one's component was imported plainly, so neither exists.
|
|
184
|
+
|
|
185
|
+
\`await\` the region (it then travels as its HTML), or import the component
|
|
186
|
+
\`with { region: 'raw' }\` or with a \`wake\` mark.
|
|
187
|
+
`
|
|
188
|
+
},
|
|
189
|
+
region_kind_mismatch: {
|
|
190
|
+
text: () => "region kind claimed a non-region value",
|
|
191
|
+
details: () => BUG
|
|
192
|
+
},
|
|
193
|
+
keep_fallback_inline: {
|
|
194
|
+
text: () => prose`
|
|
195
|
+
keepFallback() ran inside the PAGE render: this server island is nested inside a \`wake\`
|
|
196
|
+
island, where \`render: "deferred"\` is ignored and its component renders inline — nothing
|
|
197
|
+
catches the signal there and its fallback never shows. Move the island out of the
|
|
198
|
+
enclosing island (into the page, a layout, or a lake), or drop keepFallback() from a
|
|
199
|
+
component that can render inline.
|
|
200
|
+
`,
|
|
201
|
+
details: () => prose`
|
|
202
|
+
\`keepFallback()\` tells a deferred region to keep the page's fallback. Inside a \`wake\`
|
|
203
|
+
island the region renders inline instead, so nothing can keep a fallback. Move the region
|
|
204
|
+
out of the island (into the page, a layout or a lake).
|
|
205
|
+
`
|
|
206
|
+
},
|
|
207
|
+
keep_fallback_signal: {
|
|
208
|
+
text: () => "keepFallback(): the page fallback stands",
|
|
209
|
+
details: () => prose`
|
|
210
|
+
Not an error: the signal \`keepFallback()\` throws to end a deferred region's render. You
|
|
211
|
+
only see it when something catches and logs every error the render throws.
|
|
212
|
+
`
|
|
213
|
+
},
|
|
214
|
+
preference_default_invalid: {
|
|
215
|
+
text: (a) => `preference('${a.name}'): default '${a.fallback}' is not one of values [${a.values}]`,
|
|
216
|
+
details: () => prose`
|
|
217
|
+
A preference's \`default\` must be one of its \`values\`.
|
|
218
|
+
`
|
|
219
|
+
},
|
|
220
|
+
fn_factory_missing: {
|
|
221
|
+
text: (a) => prose`
|
|
222
|
+
fn_handle("${a.tag}"): its factory is not registered on this side. The generated module
|
|
223
|
+
must be imported as a VALUE at the call site (the compiler emits this import).
|
|
224
|
+
`,
|
|
225
|
+
details: () => prose`
|
|
226
|
+
A function marked to cross into an island is rebuilt on the other side from a factory the
|
|
227
|
+
compiler generates. That factory's module was not imported here. Import it as a value, not
|
|
228
|
+
\`import type\`.
|
|
229
|
+
`
|
|
230
|
+
},
|
|
231
|
+
fn_factory_not_function: {
|
|
232
|
+
text: (a) => `fn factory "${a.tag}" did not return a function.`,
|
|
233
|
+
details: () => BUG
|
|
234
|
+
},
|
|
235
|
+
fn_revive_missing: {
|
|
236
|
+
text: (a) => prose`
|
|
237
|
+
cannot revive fn "${a.tag}": its factory is not loaded on this side and the payload carries
|
|
238
|
+
no source. The island must import the generated module as a VALUE so \`__register_fn\`
|
|
239
|
+
runs in its bundle (or the fn manifest must be in the runtime).
|
|
240
|
+
`,
|
|
241
|
+
details: () => prose`
|
|
242
|
+
An island received a function it cannot rebuild: the module that registers its factory is
|
|
243
|
+
not in the island's bundle. Import that module as a value in the island.
|
|
244
|
+
`
|
|
245
|
+
},
|
|
246
|
+
transportable_class_missing: {
|
|
247
|
+
text: (a) => prose`
|
|
248
|
+
cannot revive transportable "${a.tag}": its class is not loaded on this side. The island
|
|
249
|
+
must import the class as a VALUE (not \`import type\`) so its codec travels with the
|
|
250
|
+
island's bundle.
|
|
251
|
+
`,
|
|
252
|
+
details: () => prose`
|
|
253
|
+
An island received an instance of a wired class whose module it never imports, so the
|
|
254
|
+
class's codec is not there to rebuild it. Import the class as a value in the island.
|
|
255
|
+
`
|
|
256
|
+
},
|
|
257
|
+
transportable_unregistered: {
|
|
258
|
+
text: (a) => prose`
|
|
259
|
+
class "${a.name}" has a [import.meta.og.wire] codec but was never registered. Transportable
|
|
260
|
+
classes must be declared in a module the ogygia vite plugin transforms (an \`export class\`
|
|
261
|
+
in your app source, not node_modules or a dynamic eval).
|
|
262
|
+
`,
|
|
263
|
+
details: () => prose`
|
|
264
|
+
A class with a wire codec is registered by the ogygia Vite plugin while it compiles the
|
|
265
|
+
class's module. This class was declared somewhere the plugin does not compile. Declare it
|
|
266
|
+
as an \`export class\` in the app's source.
|
|
267
|
+
`
|
|
268
|
+
},
|
|
269
|
+
ref_kind_missing: {
|
|
270
|
+
text: (a) => prose`
|
|
271
|
+
cannot resolve a "${a.kind}" ref: no such kind is registered on this side. The module that
|
|
272
|
+
registers it must be imported as a VALUE in this bundle.
|
|
273
|
+
`,
|
|
274
|
+
details: () => prose`
|
|
275
|
+
A value crossed into an island as a reference of a kind this bundle does not know. Import
|
|
276
|
+
the module that registers that kind as a value.
|
|
277
|
+
`
|
|
278
|
+
},
|
|
279
|
+
continuity_id_collision: {
|
|
280
|
+
text: (a) => prose`
|
|
281
|
+
two transportables both use continuity id "${a.name}" ("${a.owner}" and "${a.tag}"). A
|
|
282
|
+
continuity id must be unique per class — rename one, or they will clobber each other in the
|
|
283
|
+
session Keep.
|
|
284
|
+
`,
|
|
285
|
+
details: () => prose`
|
|
286
|
+
Two different wired classes claim the same continuity id, so they would share one kept
|
|
287
|
+
instance. Give each class its own id.
|
|
288
|
+
`
|
|
289
|
+
},
|
|
290
|
+
shared_state_not_plain: {
|
|
291
|
+
text: (a) => prose`
|
|
292
|
+
SharedState '${a.name}': values must be plain data (devalue-serializable — JSON, Date, Map,
|
|
293
|
+
Set, BigInt, RegExp). Functions, class instances, and DOM nodes do not cross build
|
|
294
|
+
boundaries — share facts, not live objects. (${a.reason})
|
|
295
|
+
`,
|
|
296
|
+
details: () => prose`
|
|
297
|
+
Shared state crosses between builds as data, so its values must serialize. Share plain
|
|
298
|
+
facts; keep live objects (functions, class instances, DOM nodes) on one side.
|
|
299
|
+
`
|
|
300
|
+
},
|
|
301
|
+
og_derived_formula_missing: {
|
|
302
|
+
text: () => prose`
|
|
303
|
+
cannot resume og_derived: its formula did not cross — mark it with import.meta.og.$ at the
|
|
304
|
+
og_derived call site so it travels as a fn ref.
|
|
305
|
+
`,
|
|
306
|
+
details: () => prose`
|
|
307
|
+
An \`og_derived\` crossed into an island without its formula. Mark the formula with
|
|
308
|
+
\`import.meta.og.$\` where \`og_derived\` is called, so it travels too.
|
|
309
|
+
`
|
|
310
|
+
},
|
|
311
|
+
script_run_not_function: {
|
|
312
|
+
text: () => "script(): `run` must be a function",
|
|
313
|
+
details: () => "`script({ run })` takes a function, which it inlines as the script body."
|
|
314
|
+
},
|
|
315
|
+
script_imports_need_module: {
|
|
316
|
+
text: () => "script(): `imports` needs `type: 'module'` (a static import only works in a module)",
|
|
317
|
+
details: () => "`imports` become static `import` lines, which only work in a module: add `type: 'module'`."
|
|
318
|
+
},
|
|
319
|
+
script_import_not_url: {
|
|
320
|
+
text: (a) => `script(): \`imports.${a.name}\` must be a URL string`,
|
|
321
|
+
details: () => "Each entry of `imports` is a module URL, as a string."
|
|
322
|
+
},
|
|
323
|
+
script_run_rewritten: {
|
|
324
|
+
text: () => prose`
|
|
325
|
+
script(): \`run\` was rewritten by the bundler (it holds \`__vite_ssr_…\`): an \`import()\` or
|
|
326
|
+
an imported binding inside it cannot cross into the browser. Declare the module in
|
|
327
|
+
\`imports\` (with \`type: 'module'\`) and read it from \`run\`'s first parameter.
|
|
328
|
+
`,
|
|
329
|
+
details: () => prose`
|
|
330
|
+
\`run\` is inlined into the page as its source, so it cannot use what Vite rewrites for
|
|
331
|
+
the server: an \`import()\` or an imported binding. Declare the module in \`imports\` and
|
|
332
|
+
read it from \`run\`'s first parameter.
|
|
333
|
+
`
|
|
334
|
+
},
|
|
335
|
+
script_not_json: {
|
|
336
|
+
text: (a) => `script(): \`${a.key}\` must be JSON-serializable`,
|
|
337
|
+
details: () => "The value is written into the page as JSON, so it must serialize to JSON."
|
|
338
|
+
},
|
|
339
|
+
script_one_kind: {
|
|
340
|
+
text: (a) => `script(): pass exactly one of \`run\`, \`json\`, \`ld\`, \`importmap\`, \`speculation\` (got ${a.count})`,
|
|
341
|
+
details: () => "A script has one body: pass one of `run`, `json`, `ld`, `importmap` or `speculation`."
|
|
342
|
+
},
|
|
343
|
+
script_bad_attribute: {
|
|
344
|
+
text: (a) => `script(): \`${a.key}\` is not an attribute name`,
|
|
345
|
+
details: () => "Options other than the body become attributes of the script element, so each must be a valid attribute name."
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
/** The warnings: `warn(code, args, ...rest)`. */
|
|
349
|
+
const WARNINGS = {
|
|
350
|
+
shallow_routing_unsupported: {
|
|
351
|
+
text: (a) => `${a.method}() shallow routing is not supported; use goto().`,
|
|
352
|
+
details: () => prose`
|
|
353
|
+
Kit's \`pushState\` / \`replaceState\` (shallow routing) have no equivalent in the ogygia
|
|
354
|
+
router: the call does nothing. Navigate with \`goto()\`, or keep the state in the URL.
|
|
355
|
+
`
|
|
356
|
+
},
|
|
357
|
+
scroll_handling_noop: {
|
|
358
|
+
text: () => "disableScrollHandling() is a no-op in the islands SPA router.",
|
|
359
|
+
details: () => prose`
|
|
360
|
+
The ogygia router restores and resets scroll itself on every navigation;
|
|
361
|
+
\`disableScrollHandling()\` does nothing there.
|
|
362
|
+
`
|
|
363
|
+
},
|
|
364
|
+
hole_without_address: {
|
|
365
|
+
text: (a) => prose`
|
|
366
|
+
deferred region ${a.region} was rendered in the browser with no server-minted address,
|
|
367
|
+
and the document records none for it (a client-side navigation mounted it, or its props
|
|
368
|
+
differ from the server render) — its fallback stands. A hole is server HTML: render it on
|
|
369
|
+
the server.
|
|
370
|
+
`,
|
|
371
|
+
details: () => prose`
|
|
372
|
+
A deferred region (a hole) is fetched from an address the server signs while it renders
|
|
373
|
+
the page. This one was created in the browser, so it has no address and keeps its
|
|
374
|
+
fallback.
|
|
375
|
+
|
|
376
|
+
Render the hole on the server: keep it out of browser-only branches, and give it the same
|
|
377
|
+
props on both sides.
|
|
378
|
+
`
|
|
379
|
+
},
|
|
380
|
+
nested_region_rides_parent: {
|
|
381
|
+
text: (a) => prose`
|
|
382
|
+
nested region "${a.entry}" skipped self-run; the nearest region above it is awake, so it
|
|
383
|
+
rides that hydration (inner hydrate "${a.wake}" ignored).
|
|
384
|
+
`,
|
|
385
|
+
details: () => prose`
|
|
386
|
+
A region inside an awake region hydrates with it, once, as part of the outer island. Its
|
|
387
|
+
own \`wake\` schedule is ignored. To give it its own schedule, put a lake
|
|
388
|
+
(\`wake: 'none'\`) between the two.
|
|
389
|
+
`
|
|
390
|
+
},
|
|
391
|
+
region_endpoint_foreign: {
|
|
392
|
+
text: (a) => `refused non-same-origin region endpoint ${a.endpoint}`,
|
|
393
|
+
details: () => prose`
|
|
394
|
+
A region's \`endpoint\` pointed at another origin. The runtime only fetches region answers
|
|
395
|
+
from the page's own origin; the fallback stands.
|
|
396
|
+
`
|
|
397
|
+
},
|
|
398
|
+
region_answer_denied: {
|
|
399
|
+
text: (a) => prose`
|
|
400
|
+
region answer refused for ${a.endpoint}:
|
|
401
|
+
${a.deny.startsWith("not ogygia") ? a.deny : `the islands endpoint refused its capability (403: ${a.deny})`}.
|
|
402
|
+
${a.deny.startsWith("foreign-key") && prose`
|
|
403
|
+
The page and its islands endpoint came from different deployments (two keys): route
|
|
404
|
+
the endpoint to the deployment that served the page, or give every deployment one
|
|
405
|
+
OGYGIA_SECRET.
|
|
406
|
+
`}
|
|
407
|
+
The fallback stands.
|
|
408
|
+
`,
|
|
409
|
+
details: () => prose`
|
|
410
|
+
The islands endpoint refused the signed address of a region (a 403), so its fallback
|
|
411
|
+
stands. The reason is in \`deny\`.
|
|
412
|
+
|
|
413
|
+
\`foreign-key\`: the page and its islands endpoint came from different deployments, each
|
|
414
|
+
signing with its own key. Route the endpoint to the deployment that served the page, or
|
|
415
|
+
give every deployment the same \`OGYGIA_SECRET\`.
|
|
416
|
+
|
|
417
|
+
\`not ogygia\`: the answer did not come from ogygia at all; something in front of
|
|
418
|
+
\`ogygia.handle()\` answered it.
|
|
419
|
+
`
|
|
420
|
+
},
|
|
421
|
+
region_answer_redirected: {
|
|
422
|
+
text: (a) => prose`
|
|
423
|
+
region answer refused for ${a.endpoint}: the request was
|
|
424
|
+
${a.how === "redirected" ? "redirected to" : "answered with a whole document at"} ${a.final_url}.
|
|
425
|
+
A handle in front of ogygia.handle() (an auth redirect, a locale bounce, a 404 handler)
|
|
426
|
+
took the region request — exempt the islands endpoint there. The fallback stands.
|
|
427
|
+
`,
|
|
428
|
+
details: () => prose`
|
|
429
|
+
A handle that runs before \`ogygia.handle()\` answered the region request itself: an auth
|
|
430
|
+
redirect, a locale bounce, a 404 page. The runtime refuses such an answer and keeps the
|
|
431
|
+
fallback.
|
|
432
|
+
|
|
433
|
+
Exempt the islands endpoint (\`/__ogygia__\`) in that handle.
|
|
434
|
+
`
|
|
435
|
+
},
|
|
436
|
+
region_fetch_failed: {
|
|
437
|
+
text: (a) => `region fetch failed for ${a.endpoint}`,
|
|
438
|
+
details: () => prose`
|
|
439
|
+
The request for a region's HTML failed (the network, a server error). The runtime retries
|
|
440
|
+
a few times; the fallback stands until one succeeds. The error follows the message.
|
|
441
|
+
`
|
|
442
|
+
},
|
|
443
|
+
island_healed: {
|
|
444
|
+
text: (a) => prose`
|
|
445
|
+
island "${a.entry}" was edited while it slept (its light DOM no longer matched the server
|
|
446
|
+
render — a design-system runtime, an A/B tool, a translator), so its server HTML was put
|
|
447
|
+
back and hydrated instead of re-rendering it client-side. Whatever the edit added is gone;
|
|
448
|
+
the script that made it should leave <ogygia-region> subtrees alone.
|
|
449
|
+
|
|
450
|
+
${a.drift && `What drifted: ${a.drift}`}
|
|
451
|
+
`,
|
|
452
|
+
details: () => prose`
|
|
453
|
+
Dev only. Something edited the island's HTML before it woke (a design-system runtime, an
|
|
454
|
+
A/B tool, a translator). ogygia put the server HTML back and hydrated that, instead of
|
|
455
|
+
letting Svelte throw it away and re-render. Whatever the edit added is gone.
|
|
456
|
+
|
|
457
|
+
Make the script that edits the page leave \`<ogygia-region>\` subtrees alone.
|
|
458
|
+
`
|
|
459
|
+
},
|
|
460
|
+
ownership_conflict: {
|
|
461
|
+
text: (a) => prose`
|
|
462
|
+
${a.element} is a web component that changed its own children in a position Svelte's
|
|
463
|
+
hydration reads, so the repair had to remove the nodes it added. Render that subtree with
|
|
464
|
+
{@html} or as static markup (Svelte never reads inside it), put it in a lake
|
|
465
|
+
(wake: 'none'), or mark the element data-ogygia-keep.
|
|
466
|
+
`,
|
|
467
|
+
details: () => prose`
|
|
468
|
+
Dev only. A web component inside the island added children where Svelte's hydration
|
|
469
|
+
expects the server's nodes. To hydrate the island, the repair removed them.
|
|
470
|
+
|
|
471
|
+
Render that subtree with \`{@html}\` or as static markup (Svelte never reads inside it),
|
|
472
|
+
put it in a lake (\`wake: 'none'\`), or mark the element \`data-ogygia-keep\`.
|
|
473
|
+
`
|
|
474
|
+
},
|
|
475
|
+
hydration_discarded: {
|
|
476
|
+
text: (a) => prose`
|
|
477
|
+
island "${a.entry}" discarded its ENTIRE server-rendered DOM during hydration and
|
|
478
|
+
re-rendered client-side (Svelte hydration-mismatch recovery). Three things cause this.
|
|
479
|
+
(1) Something changed this region's HTML between SSR and wake — a post-SSR transform
|
|
480
|
+
(transformPageChunk / an HTML-rewriting middleware), an A/B-testing snippet, or an edge
|
|
481
|
+
rewriter; whatever it injected (e.g. declarative shadow DOM) was just destroyed, and the
|
|
482
|
+
swap is timing-dependent, so symptoms look erratic. (2) A component in this island reads
|
|
483
|
+
a page/layout CONTEXT via plain Svelte setContext — on csr=false that runs only on the
|
|
484
|
+
server, so getContext returns undefined on the client and the island renders a different
|
|
485
|
+
tree. (3) A block in this island ({#if} / {:else if} / {#each} / {#await}) took a
|
|
486
|
+
DIFFERENT branch on the client than on the server — its condition reads something that
|
|
487
|
+
differs between the two (a browser global, a store's client default, url/page state, a
|
|
488
|
+
Date). Svelte recovers a branch mismatch SILENTLY (no throw); the walk is then off and
|
|
489
|
+
the rest of the tree follows.
|
|
490
|
+
|
|
491
|
+
${a.drift && `What changed: ${a.drift}`}
|
|
492
|
+
|
|
493
|
+
${a.strict ? `Svelte threw on the strict attempt (after repair): ${a.strict}` : a.drift ? "Svelte did not throw after the repair — the mismatch is one this walk does not model." : prose`
|
|
494
|
+
The server node sequence was INTACT and Svelte did not throw: nothing mutated
|
|
495
|
+
this region's DOM, so this is (3) (or (2)). Find the block whose branch
|
|
496
|
+
differs: in the server markup its anchor reads <!--[N--> where N is the
|
|
497
|
+
branch the SERVER chose.
|
|
498
|
+
`}
|
|
499
|
+
|
|
500
|
+
Fix: for (1) make the mutation invisible to hydration (mutate only <head>, attributes, or
|
|
501
|
+
shadow templates — never the region's light DOM), or freeze the foreign-owned subtree
|
|
502
|
+
with a wake:'none' (lake) boundary; for (2) provide the value with setContext / <Provide>
|
|
503
|
+
/ createContext imported from 'ogygia', read it with the same getContext(key); for (3)
|
|
504
|
+
make the condition read the same value on both sides (a prop / page.data), or move the
|
|
505
|
+
browser-only branch behind an $effect / hydratedBy().
|
|
506
|
+
`,
|
|
507
|
+
details: () => prose`
|
|
508
|
+
Svelte could not adopt the island's server HTML, so it threw it away and rendered the
|
|
509
|
+
island again in the browser: a flash, and anything injected into that HTML is gone. Three
|
|
510
|
+
things cause it.
|
|
511
|
+
|
|
512
|
+
1. Something changed the region's HTML between the server render and the wake: a
|
|
513
|
+
post-SSR transform (\`transformPageChunk\`, an HTML-rewriting middleware), an A/B-testing
|
|
514
|
+
snippet, an edge rewriter. \`drift\` names the first difference. Mutate only the head,
|
|
515
|
+
attributes or shadow templates, never the region's light DOM, or freeze that subtree in a
|
|
516
|
+
lake (\`wake: 'none'\`).
|
|
517
|
+
|
|
518
|
+
2. A component reads a page or layout context set with plain \`setContext\`. On a
|
|
519
|
+
csr=false page that runs only on the server, so the browser renders a different tree.
|
|
520
|
+
Provide the value with \`setContext\` / \`<Provide>\` / \`createContext\` imported from
|
|
521
|
+
\`ogygia\`.
|
|
522
|
+
|
|
523
|
+
3. A block (\`if\`, \`each\`, \`await\`) took a different branch in the browser than on
|
|
524
|
+
the server: its condition reads a browser global, a store's client default, URL state or a
|
|
525
|
+
date. With no \`drift\` and no \`strict\` error this is the cause. Make the condition read
|
|
526
|
+
the same value on both sides (a prop, \`page.data\`), or move the browser-only branch
|
|
527
|
+
behind an \`$effect\` or \`hydratedBy()\`.
|
|
528
|
+
`
|
|
529
|
+
},
|
|
530
|
+
prop_mutation: {
|
|
531
|
+
text: (a) => prose`
|
|
532
|
+
mutating prop '${a.prop}' inside island ${a.entry} — island props are a serialized
|
|
533
|
+
snapshot of the host, or a reference into page.data shared with every island that reads
|
|
534
|
+
it: the write updates nothing (or leaks into page.data). Move mutable state inside the
|
|
535
|
+
island component.
|
|
536
|
+
`,
|
|
537
|
+
details: () => prose`
|
|
538
|
+
Dev only. An island's props are a snapshot the server serialized, or a reference into
|
|
539
|
+
\`page.data\` that every island shares. Writing to them updates nothing on the page (or
|
|
540
|
+
leaks into \`page.data\`). Copy the value into the island's own \`$state\` and change that.
|
|
541
|
+
`
|
|
542
|
+
},
|
|
543
|
+
island_on_kit_page: {
|
|
544
|
+
text: (a) => prose`
|
|
545
|
+
island "${a.entry}" is on a csr=true page; Kit hydrates it, so the island directive is
|
|
546
|
+
redundant here (it behaves as a normal component).
|
|
547
|
+
`,
|
|
548
|
+
details: () => prose`
|
|
549
|
+
Dev only. On a csr=true page Kit hydrates the whole page, so an island there is an
|
|
550
|
+
ordinary component. Its \`wake\` does nothing on this page.
|
|
551
|
+
`
|
|
552
|
+
},
|
|
553
|
+
island_block_in_inline: {
|
|
554
|
+
text: (a) => prose`
|
|
555
|
+
island "${a.entry}" rendered a BLOCK element inline inside a <p> (or other phrasing-only
|
|
556
|
+
context). The browser's HTML parser hoisted that block out of the paragraph before
|
|
557
|
+
hydration, so this region is empty and a SECOND copy is about to mount here — the
|
|
558
|
+
server-rendered copy is now an orphaned sibling of the paragraph. Fix: make the component
|
|
559
|
+
render an inline element (e.g. <span> instead of <div>), or place the island on its own
|
|
560
|
+
line (block context) rather than inside a sentence.
|
|
561
|
+
`,
|
|
562
|
+
details: () => prose`
|
|
563
|
+
Dev only. The island renders a block element (a \`div\`, a \`p\`) inside a paragraph. The
|
|
564
|
+
browser's parser moves that block out of the paragraph before any script runs, so the
|
|
565
|
+
region is empty and a second copy mounts beside the first.
|
|
566
|
+
|
|
567
|
+
Render an inline element (a \`span\`), or place the island on its own line.
|
|
568
|
+
`
|
|
569
|
+
},
|
|
570
|
+
keep_without_router: {
|
|
571
|
+
text: (a) => prose`
|
|
572
|
+
island "${a.entry}" has keep:'${a.key}' but the SPA router is off
|
|
573
|
+
(ogygia({ router: false })) — keep relies on SPA navigation; a full-page load replaces
|
|
574
|
+
the DOM, so the attribute is a no-op here.
|
|
575
|
+
`,
|
|
576
|
+
details: () => prose`
|
|
577
|
+
Dev only. \`keep\` keeps an island across client navigations, so it needs the ogygia
|
|
578
|
+
router. With \`ogygia({ router: false })\` every navigation is a full page load and nothing
|
|
579
|
+
is kept.
|
|
580
|
+
`
|
|
581
|
+
},
|
|
582
|
+
live_feature_missing: {
|
|
583
|
+
text: () => "live region needs the live feature plugin (pushable props missing)",
|
|
584
|
+
details: () => prose`
|
|
585
|
+
Dev only. A live region woke, but the build has no live feature to hydrate it with. ${BUG}
|
|
586
|
+
`
|
|
587
|
+
},
|
|
588
|
+
live_region_no_host: {
|
|
589
|
+
text: (a) => prose`
|
|
590
|
+
render:'live' region "${a.id}" has no island host — on regular pages it will never
|
|
591
|
+
revalidate (only on documents served from a page store). Wrap it in a wake:'load' island
|
|
592
|
+
to drive remount revalidation.
|
|
593
|
+
`,
|
|
594
|
+
details: () => prose`
|
|
595
|
+
A \`render: 'live'\` lake revalidates when the island around it remounts. This one has no
|
|
596
|
+
island around it, so it never refreshes on a regular page. Wrap it in a
|
|
597
|
+
\`wake: 'load'\` island.
|
|
598
|
+
`
|
|
599
|
+
},
|
|
600
|
+
live_region_no_endpoint: {
|
|
601
|
+
text: (a) => prose`
|
|
602
|
+
region "${a.id}" is render:'live' but no signed endpoint was captured at SSR — painting
|
|
603
|
+
the cache only.
|
|
604
|
+
`,
|
|
605
|
+
details: () => prose`
|
|
606
|
+
Dev only. The live region has no signed address from the server render, so it shows its
|
|
607
|
+
cached HTML and never refreshes.
|
|
608
|
+
`
|
|
609
|
+
},
|
|
610
|
+
region_newer_page_data: {
|
|
611
|
+
text: (a) => prose`
|
|
612
|
+
a region came back rendered with newer page.data (${a.keys}) than this Kit page holds.
|
|
613
|
+
Refresh the page's data (invalidateAll()) before refreshing the region, or the islands
|
|
614
|
+
inside it hydrate against the older values.
|
|
615
|
+
`,
|
|
616
|
+
details: () => prose`
|
|
617
|
+
A region's answer was rendered against newer \`page.data\` than the Kit page in the
|
|
618
|
+
browser holds, so the islands inside it would hydrate against older values. Call
|
|
619
|
+
\`invalidateAll()\` before refreshing the region.
|
|
620
|
+
`
|
|
621
|
+
},
|
|
622
|
+
kit_page_waiting: {
|
|
623
|
+
text: (a) => prose`
|
|
624
|
+
islands inside a lake / hole answer on this Kit (csr=true) page have waited ${a.seconds}s
|
|
625
|
+
for Kit to apply its page and are still holding their server HTML.
|
|
626
|
+
${a.booted ? "Kit's client entry evaluated but start() has not applied the page (status is still -1) — Kit's start() may have thrown; check the console above." : "Kit's client entry has not evaluated (no page bridge yet) — Kit's boot script may be blocked, failing, or missing."}
|
|
627
|
+
They hydrate the moment Kit does; nothing is discarded meanwhile.
|
|
628
|
+
`,
|
|
629
|
+
details: () => prose`
|
|
630
|
+
Dev only. On a csr=true page, an island inside a lake or a hole answer waits for Kit to
|
|
631
|
+
apply its page before it hydrates. Kit has not done so yet.
|
|
632
|
+
|
|
633
|
+
\`booted=false\`: Kit's client entry never ran; its boot script is blocked, failing or
|
|
634
|
+
missing. \`booted=true\`: it ran, but \`start()\` has not applied the page; it may have
|
|
635
|
+
thrown, so check the console above. The islands keep their server HTML meanwhile.
|
|
636
|
+
`
|
|
637
|
+
},
|
|
638
|
+
foreign_page_read: {
|
|
639
|
+
text: (a) => prose`
|
|
640
|
+
${a.expr} was read inside a mounted MFE island (${a.entry}, from ${a.origin}).
|
|
641
|
+
|
|
642
|
+
In the browser this is the SHELL's page, not the MFE's. The HTML you see was rendered with
|
|
643
|
+
the MFE's own load data, so this island will repaint with different values after hydrate.
|
|
644
|
+
|
|
645
|
+
Pass the value as a prop, or read it with a remote function.
|
|
646
|
+
`,
|
|
647
|
+
details: () => prose`
|
|
648
|
+
Dev only. An island from another app (a stitched fragment) read the page store. In the
|
|
649
|
+
browser that is the host app's page, not the fragment's, so the island repaints with
|
|
650
|
+
different values after it hydrates. Pass the value as a prop, or read it with a remote
|
|
651
|
+
function.
|
|
652
|
+
`
|
|
653
|
+
},
|
|
654
|
+
context_marker_large: {
|
|
655
|
+
text: (a) => prose`
|
|
656
|
+
the island context marker is ${a.size}kB — it ships in every page's HTML. Biggest keys:
|
|
657
|
+
${a.top}. Slim the values, or mark host-only keys with setContext(key, value, { islands:
|
|
658
|
+
false }).
|
|
659
|
+
`,
|
|
660
|
+
details: () => prose`
|
|
661
|
+
Dev only. Context set above islands is serialized into the page so the islands can read it,
|
|
662
|
+
and it has grown large. Slim the values, or keep a key on the server with
|
|
663
|
+
\`setContext(key, value, { islands: false })\`.
|
|
664
|
+
`
|
|
665
|
+
},
|
|
666
|
+
context_dropped: {
|
|
667
|
+
text: (a) => `context '${a.key}' could not be serialized for islands and was dropped.`,
|
|
668
|
+
details: () => prose`
|
|
669
|
+
Dev only. A context value set above islands could not be serialized, so islands do not see
|
|
670
|
+
it. Pass plain data, or a wired value.
|
|
671
|
+
`
|
|
672
|
+
},
|
|
673
|
+
context_unserializable: {
|
|
674
|
+
text: (a) => `context '${a.key}'${a.path ? ` @ ${a.path}` : ""}: ${a.detail}`,
|
|
675
|
+
details: () => prose`
|
|
676
|
+
Dev only. Part of a context value set above islands does not cross into them: \`path\`
|
|
677
|
+
names where, \`detail\` what. Pass plain data there.
|
|
678
|
+
`
|
|
679
|
+
},
|
|
680
|
+
page_seed_ref_missing: {
|
|
681
|
+
text: (a) => prose`
|
|
682
|
+
island props reference page.data at ${a.path} but the page seed does not carry it — the
|
|
683
|
+
island receives undefined there.
|
|
684
|
+
`,
|
|
685
|
+
details: () => prose`
|
|
686
|
+
Dev only. An island's props point into \`page.data\`, but the page did not ship that part,
|
|
687
|
+
so the island reads \`undefined\` there.
|
|
688
|
+
`
|
|
689
|
+
},
|
|
690
|
+
store_not_extensible: {
|
|
691
|
+
text: (a) => prose`
|
|
692
|
+
store "${a.tag}": the store object is not extensible (frozen/sealed), so it cannot carry
|
|
693
|
+
its factory brand — it will cross boundaries as a plain writable (custom methods
|
|
694
|
+
unavailable). Brand before freezing, or leave the store extensible.
|
|
695
|
+
`,
|
|
696
|
+
details: () => prose`
|
|
697
|
+
A store crosses into an island with a mark naming the factory that rebuilds it. A frozen
|
|
698
|
+
store cannot take the mark, so it crosses as a plain writable. Freeze it after it is
|
|
699
|
+
branded, or leave it extensible.
|
|
700
|
+
`
|
|
701
|
+
},
|
|
702
|
+
store_factory_missing: {
|
|
703
|
+
text: (a) => prose`
|
|
704
|
+
store "${a.tag}": factory not loaded in this bundle — degraded to a plain writable (custom
|
|
705
|
+
methods unavailable). Import the factory's module in the island (or its graph) so
|
|
706
|
+
\`__register_store_factory\` runs there.
|
|
707
|
+
`,
|
|
708
|
+
details: () => prose`
|
|
709
|
+
The island received a store whose factory module it never imports, so the store arrives
|
|
710
|
+
as a plain writable. Import that module in the island.
|
|
711
|
+
`
|
|
712
|
+
},
|
|
713
|
+
store_factory_bad_rebuild: {
|
|
714
|
+
text: (a) => prose`
|
|
715
|
+
store "${a.tag}": factory returned ${a.got} while rebuilding — degraded to a plain writable
|
|
716
|
+
(custom methods unavailable). A store factory must return a store on every call; move
|
|
717
|
+
environment guards inside the factory body.
|
|
718
|
+
`,
|
|
719
|
+
details: () => prose`
|
|
720
|
+
A store factory returned something other than a store while the island rebuilt it. Return
|
|
721
|
+
a store on every call, and put environment checks inside the factory's body.
|
|
722
|
+
`
|
|
723
|
+
},
|
|
724
|
+
store_factory_unbranded: {
|
|
725
|
+
text: (a) => prose`
|
|
726
|
+
store "${a.tag}": factory returned ${a.got} — nothing to brand, value passed through as-is.
|
|
727
|
+
Fine for a client-only store; a store that must cross an island boundary has to exist on
|
|
728
|
+
the server too — return e.g. writable(seed) under your guard and gate the side effects
|
|
729
|
+
inside the factory instead.
|
|
730
|
+
`,
|
|
731
|
+
details: () => prose`
|
|
732
|
+
A store factory returned something other than a store, so it cannot be marked to cross
|
|
733
|
+
into islands. That is fine for a store only the browser uses; to cross, the factory must
|
|
734
|
+
return a store on the server too.
|
|
735
|
+
`
|
|
736
|
+
},
|
|
737
|
+
region_promise_no_placeholder: {
|
|
738
|
+
text: () => prose`
|
|
739
|
+
<Region of={promise}> has no \`placeholder\` — the region will sit empty until the promise
|
|
740
|
+
resolves and its stylesheet loads. Add {#snippet placeholder()}…{/snippet} for the wait.
|
|
741
|
+
`,
|
|
742
|
+
details: () => prose`
|
|
743
|
+
Dev only. A region given a promise shows nothing until it resolves. Give it a
|
|
744
|
+
\`placeholder\` snippet for the wait.
|
|
745
|
+
`
|
|
746
|
+
},
|
|
747
|
+
nested_server_island_inline: {
|
|
748
|
+
text: (a) => prose`
|
|
749
|
+
nested server island "${a.entry}" is inside another island; it renders inline as frozen
|
|
750
|
+
HTML (no JS ships; islands inside it wake on their own) — 'deferred' ignored.
|
|
751
|
+
`,
|
|
752
|
+
details: () => prose`
|
|
753
|
+
Dev only. A deferred region inside an island cannot be fetched on its own, so it renders
|
|
754
|
+
inline as part of the island's HTML.
|
|
755
|
+
`
|
|
756
|
+
},
|
|
757
|
+
nested_island_with_parent: {
|
|
758
|
+
text: (a) => `nested island "${a.entry}" is inside another island; it hydrates with its parent (strategy ignored).`,
|
|
759
|
+
details: () => prose`
|
|
760
|
+
Dev only. An island inside an island hydrates with the outer one, so its own \`wake\` is
|
|
761
|
+
ignored. Put a lake (\`wake: 'none'\`) between them to give it its own schedule.
|
|
762
|
+
`
|
|
763
|
+
},
|
|
764
|
+
lake_mounted_without_html: {
|
|
765
|
+
text: (a) => prose`
|
|
766
|
+
lake "${a.entry}" was mounted by Kit on the client with no server HTML to adopt (a
|
|
767
|
+
client-side navigation, or a hydration failure — look for an error above). The runtime
|
|
768
|
+
restores it from its server HTML when this document rendered it; otherwise it stays empty.
|
|
769
|
+
A lake is server HTML: keep chrome lakes in a layout that persists across navigations, or
|
|
770
|
+
serve that route csr=false.
|
|
771
|
+
`,
|
|
772
|
+
details: () => prose`
|
|
773
|
+
Dev only. On a csr=true page Kit mounted a lake in the browser, but a lake is server HTML
|
|
774
|
+
and there was none to adopt. Keep such lakes in a layout that stays across navigations, or
|
|
775
|
+
serve the route with \`csr = false\`.
|
|
776
|
+
`
|
|
777
|
+
},
|
|
778
|
+
rule_region_mounted_twice: {
|
|
779
|
+
text: (a) => `rule broken, one mount per region: ${a.detail}`,
|
|
780
|
+
details: () => prose`
|
|
781
|
+
Dev and e2e only (a rule ogygia checks on itself). A region element holds one island at a
|
|
782
|
+
time, and an island whose element left the page is let go with it. One held two, or kept
|
|
783
|
+
its island after its element left: ${BUG}
|
|
784
|
+
`
|
|
785
|
+
},
|
|
786
|
+
rule_address_bar_drift: {
|
|
787
|
+
text: (a) => `rule broken, the address bar and the router's history agree: ${a.detail}`,
|
|
788
|
+
details: () => prose`
|
|
789
|
+
Dev and e2e only (a rule ogygia checks on itself). With no navigation out, the address bar
|
|
790
|
+
is the router's page on screen. They differ: a later back or forward step would show the
|
|
791
|
+
wrong page, or scroll to the wrong place. If the app writes \`history\` itself (outside
|
|
792
|
+
\`pushState\`/\`replaceState\` from \`$app/navigation\`), that is the likely cause; else
|
|
793
|
+
${BUG}
|
|
794
|
+
`
|
|
795
|
+
},
|
|
796
|
+
rule_old_page_open: {
|
|
797
|
+
text: (a) => `rule broken, nothing of a page that was left stays open: ${a.detail}`,
|
|
798
|
+
details: () => prose`
|
|
799
|
+
Dev and e2e only (a rule ogygia checks on itself). Each page the router shows owns what it
|
|
800
|
+
starts (listeners, timers, streams), and all of it is let go when the next page takes over.
|
|
801
|
+
Something of an earlier page is still open: ${BUG}
|
|
802
|
+
`
|
|
803
|
+
},
|
|
804
|
+
rule_failure_uncoded: {
|
|
805
|
+
text: (a) => `rule broken, no failure leaves ogygia without a code: ${a.detail}`,
|
|
806
|
+
details: () => prose`
|
|
807
|
+
Dev and e2e only (a rule ogygia checks on itself). Every failure ogygia lets out names its
|
|
808
|
+
code's page, and its internal \`STALE\` answer is never a rejection. One got out without
|
|
809
|
+
either: ${BUG}
|
|
810
|
+
`
|
|
811
|
+
},
|
|
812
|
+
rule_parse_upgraded: {
|
|
813
|
+
text: (a) => `rule broken, a parsed answer is inert: ${a.detail}`,
|
|
814
|
+
details: () => prose`
|
|
815
|
+
Dev and e2e only (a rule ogygia checks on itself). A region or hole answer is parsed in a
|
|
816
|
+
document with no browsing context, so no component's constructor runs before the restore
|
|
817
|
+
puts the answer in the shape its components expect. An element of an answer was built
|
|
818
|
+
during the parse anyway: the engine built custom elements in a document that has no
|
|
819
|
+
registry. ${BUG}
|
|
820
|
+
`
|
|
821
|
+
},
|
|
822
|
+
restore_late: {
|
|
823
|
+
text: (a) => `<${a.host}> was upgraded before the restore reached it; its own root is kept and the server's copy of its render dropped.`,
|
|
824
|
+
details: () => prose`
|
|
825
|
+
A custom element of a reversible transform (an \`og-h\` host) already had a shadow root when
|
|
826
|
+
the restore reached it: a component runtime upgraded it first. The restore keeps the root
|
|
827
|
+
the component made, puts its light DOM back into Svelte's form (its children, its
|
|
828
|
+
attributes) and drops the server's rendered copy, which would otherwise show a second time
|
|
829
|
+
through the slot. Until the component renders, that part of the page is empty.
|
|
830
|
+
|
|
831
|
+
Load the component runtime after ogygia's restore (the handle inlines it at the end of the
|
|
832
|
+
body), or let it hydrate a declarative root instead of attaching its own in the
|
|
833
|
+
constructor. Said once per page and element name.
|
|
834
|
+
`
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
const core = /* @__PURE__ */ define_messages(import.meta.env?.DEV ? ERRORS : null, import.meta.env?.DEV ? WARNINGS : null);
|
|
838
|
+
/** `throw new OgygiaError(code, args)`; `warn(code, args, ...rest)` logs. Wording and link in dev,
|
|
839
|
+
* the link alone in a production build. */
|
|
840
|
+
const OgygiaError = core.OgygiaError;
|
|
841
|
+
const warn = core.warn;
|
|
842
|
+
const line = core.line;
|
|
843
|
+
export { ERRORS, OgygiaError, WARNINGS, line, warn };
|