@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.
Files changed (227) hide show
  1. package/dist/LateIsland.svelte +3 -2
  2. package/dist/LateIslandAwait.svelte +6 -2
  3. package/dist/Region.svelte +22 -33
  4. package/dist/boundary.d.ts +0 -2
  5. package/dist/boundary.js +8 -6
  6. package/dist/compiler/debarrel/barrel.d.ts +15 -8
  7. package/dist/compiler/debarrel/barrel.js +92 -45
  8. package/dist/compiler/debarrel/plugin.js +41 -17
  9. package/dist/compiler/dev/dev-hmr.d.ts +3 -0
  10. package/dist/compiler/dev/dev-hmr.js +3 -0
  11. package/dist/compiler/driver.js +11 -4
  12. package/dist/compiler/flags.js +21 -7
  13. package/dist/compiler/fouc-css.js +5 -1
  14. package/dist/compiler/kit.js +5 -1
  15. package/dist/compiler/link/build-output.js +12 -3
  16. package/dist/compiler/macros/bake.js +18 -4
  17. package/dist/compiler/macros/dollar.js +6 -1
  18. package/dist/compiler/macros/source.js +6 -1
  19. package/dist/compiler/macros/store.js +10 -2
  20. package/dist/compiler/macros/wire.js +6 -1
  21. package/dist/compiler/parse/scan.js +10 -3
  22. package/dist/compiler/region/transform.js +188 -74
  23. package/dist/context-bridge.js +13 -5
  24. package/dist/context.d.ts +9 -0
  25. package/dist/context.js +30 -1
  26. package/dist/document.d.ts +1 -1
  27. package/dist/document.js +7 -1
  28. package/dist/early-holes-head.d.ts +5 -0
  29. package/dist/early-holes-head.js +20 -0
  30. package/dist/early-holes.d.ts +34 -0
  31. package/dist/early-holes.js +51 -0
  32. package/dist/entry-hydrate.js +9 -12
  33. package/dist/events/bus.js +7 -2
  34. package/dist/events/schema.d.ts +2 -2
  35. package/dist/fn-transport.js +4 -3
  36. package/dist/hooks.js +94 -163
  37. package/dist/insights/page-assets.js +11 -3
  38. package/dist/insights/page-insights.d.ts +0 -2
  39. package/dist/insights/page-insights.js +14 -10
  40. package/dist/insights/session-insights.js +2 -2
  41. package/dist/internal-instruments.d.ts +3 -1
  42. package/dist/internal-instruments.js +3 -1
  43. package/dist/internal-server.d.ts +3 -2
  44. package/dist/internal-server.js +3 -2
  45. package/dist/internal.d.ts +1 -2
  46. package/dist/internal.js +1 -2
  47. package/dist/keep-fallback.d.ts +0 -2
  48. package/dist/keep-fallback.js +4 -5
  49. package/dist/live-transport.js +3 -2
  50. package/dist/messages/build.d.ts +585 -0
  51. package/dist/messages/build.js +800 -0
  52. package/dist/messages/core.d.ts +464 -0
  53. package/dist/messages/core.js +843 -0
  54. package/dist/messages/define.d.ts +62 -0
  55. package/dist/messages/define.js +49 -0
  56. package/dist/messages/index.d.ts +6 -0
  57. package/dist/messages/index.js +6 -0
  58. package/dist/messages/island.d.ts +4 -0
  59. package/dist/messages/island.js +34 -0
  60. package/dist/messages/lazy.d.ts +3 -0
  61. package/dist/messages/lazy.js +22 -0
  62. package/dist/messages/prose.d.ts +15 -0
  63. package/dist/messages/prose.js +43 -0
  64. package/dist/messages/server.d.ts +142 -0
  65. package/dist/messages/server.js +246 -0
  66. package/dist/nested.d.ts +3 -0
  67. package/dist/nested.js +8 -1
  68. package/dist/plugin/css.js +14 -13
  69. package/dist/plugin/facts.d.ts +2 -0
  70. package/dist/plugin/facts.js +10 -6
  71. package/dist/plugin/hooks.d.ts +7 -17
  72. package/dist/plugin/hooks.js +32 -4
  73. package/dist/plugin/index.d.ts +9 -2
  74. package/dist/plugin/request-scope.d.ts +20 -0
  75. package/dist/plugin/request-scope.js +149 -0
  76. package/dist/plugin/server.d.ts +20 -2
  77. package/dist/plugin/server.js +98 -28
  78. package/dist/plugin/testing.d.ts +6 -0
  79. package/dist/plugin/testing.js +14 -2
  80. package/dist/policies.d.ts +21 -0
  81. package/dist/policies.js +66 -0
  82. package/dist/preference.js +6 -1
  83. package/dist/preload.js +6 -9
  84. package/dist/ref-watch.d.ts +0 -10
  85. package/dist/ref-watch.js +14 -1
  86. package/dist/ref.js +17 -5
  87. package/dist/region-snippet.js +9 -3
  88. package/dist/region.js +2 -1
  89. package/dist/report-thrown.d.ts +9 -0
  90. package/dist/report-thrown.js +15 -0
  91. package/dist/rules.d.ts +17 -0
  92. package/dist/rules.js +57 -0
  93. package/dist/runtime/beacon.d.ts +0 -4
  94. package/dist/runtime/beacon.js +58 -43
  95. package/dist/runtime/boot-link.js +19 -2
  96. package/dist/runtime/client-hooks.js +2 -1
  97. package/dist/runtime/concurrency.d.ts +16 -5
  98. package/dist/runtime/concurrency.js +123 -7
  99. package/dist/runtime/core.d.ts +3 -1
  100. package/dist/runtime/core.js +718 -384
  101. package/dist/runtime/devalue-lane.d.ts +13 -0
  102. package/dist/runtime/devalue-lane.js +49 -0
  103. package/dist/runtime/disclose-version.d.ts +1 -0
  104. package/dist/runtime/disclose-version.js +14 -0
  105. package/dist/runtime/early-holes.d.ts +4 -0
  106. package/dist/runtime/early-holes.js +40 -0
  107. package/dist/runtime/entry-locations.js +40 -49
  108. package/dist/runtime/foreign-props.d.ts +0 -7
  109. package/dist/runtime/foreign-props.js +2 -1
  110. package/dist/runtime/form-continuity.d.ts +2 -2
  111. package/dist/runtime/form-continuity.js +30 -8
  112. package/dist/runtime/frame-nav.d.ts +7 -1
  113. package/dist/runtime/frame-nav.js +84 -18
  114. package/dist/runtime/frame-store.d.ts +25 -16
  115. package/dist/runtime/frame-store.js +124 -98
  116. package/dist/runtime/frames.js +8 -4
  117. package/dist/runtime/hole-facts.js +6 -7
  118. package/dist/runtime/hole-fetch.d.ts +17 -0
  119. package/dist/runtime/hole-fetch.js +47 -0
  120. package/dist/runtime/hydrate-core.d.ts +4 -4
  121. package/dist/runtime/hydrate-core.js +80 -64
  122. package/dist/runtime/import-again.d.ts +33 -0
  123. package/dist/runtime/import-again.js +217 -0
  124. package/dist/runtime/interaction-replay.d.ts +5 -3
  125. package/dist/runtime/interaction-replay.js +6 -6
  126. package/dist/runtime/interaction.d.ts +14 -3
  127. package/dist/runtime/interaction.js +46 -23
  128. package/dist/runtime/kit-page-thread.svelte.d.ts +2 -1
  129. package/dist/runtime/kit-page-thread.svelte.js +44 -20
  130. package/dist/runtime/lakes.d.ts +1 -1
  131. package/dist/runtime/lakes.js +18 -5
  132. package/dist/runtime/live.d.ts +1 -2
  133. package/dist/runtime/live.js +6 -8
  134. package/dist/runtime/load-scheduler.d.ts +29 -18
  135. package/dist/runtime/load-scheduler.js +236 -136
  136. package/dist/runtime/nav-handle.js +25 -6
  137. package/dist/runtime/navigation.d.ts +24 -0
  138. package/dist/runtime/navigation.js +24 -0
  139. package/dist/runtime/ownership.d.ts +1 -1
  140. package/dist/runtime/page-defer.js +3 -3
  141. package/dist/runtime/parse-html.d.ts +15 -4
  142. package/dist/runtime/parse-html.js +24 -5
  143. package/dist/runtime/pushable-props.svelte.d.ts +21 -0
  144. package/dist/runtime/pushable-props.svelte.js +37 -0
  145. package/dist/runtime/region-endpoint-url.js +4 -6
  146. package/dist/runtime/region-machines.d.ts +111 -0
  147. package/dist/runtime/region-machines.js +97 -0
  148. package/dist/runtime/region-sheets.d.ts +31 -0
  149. package/dist/runtime/region-sheets.js +49 -0
  150. package/dist/runtime/restore-report.d.ts +1 -0
  151. package/dist/runtime/restore-report.js +36 -0
  152. package/dist/runtime/restore.d.ts +5 -2
  153. package/dist/runtime/restore.js +33 -14
  154. package/dist/runtime/router-nav.d.ts +32 -12
  155. package/dist/runtime/router-nav.js +320 -228
  156. package/dist/runtime/router.d.ts +83 -19
  157. package/dist/runtime/router.js +297 -129
  158. package/dist/runtime/rules.d.ts +35 -0
  159. package/dist/runtime/rules.js +137 -0
  160. package/dist/runtime/schedule.d.ts +6 -3
  161. package/dist/runtime/schedule.js +172 -57
  162. package/dist/runtime/seeds.d.ts +5 -1
  163. package/dist/runtime/seeds.js +11 -5
  164. package/dist/runtime/session.d.ts +46 -7
  165. package/dist/runtime/session.js +78 -10
  166. package/dist/runtime/slots.d.ts +53 -20
  167. package/dist/runtime/slots.js +2 -3
  168. package/dist/runtime/soft-refresh.d.ts +16 -0
  169. package/dist/runtime/soft-refresh.js +14 -0
  170. package/dist/runtime/svelte-warnings.d.ts +4 -10
  171. package/dist/runtime/svelte-warnings.js +7 -4
  172. package/dist/runtime/wire-classes.js +21 -8
  173. package/dist/runtime/wire-format.js +6 -3
  174. package/dist/script.js +8 -7
  175. package/dist/seed-ref-reviver.d.ts +0 -9
  176. package/dist/seed-ref-reviver.js +2 -1
  177. package/dist/seed-refs.d.ts +46 -36
  178. package/dist/seed-refs.js +131 -92
  179. package/dist/server/document-tail.d.ts +6 -0
  180. package/dist/server/document-tail.js +7 -1
  181. package/dist/server/early-holes-csp.d.ts +14 -0
  182. package/dist/server/early-holes-csp.js +73 -0
  183. package/dist/server/page-facts.d.ts +4 -1
  184. package/dist/server/page-facts.js +4 -1
  185. package/dist/server/page-seed.d.ts +2 -2
  186. package/dist/server/page-seed.js +104 -11
  187. package/dist/server/page-stream.d.ts +14 -1
  188. package/dist/server/page-stream.js +119 -2
  189. package/dist/server/personal-response.d.ts +0 -5
  190. package/dist/server/personal-response.js +6 -2
  191. package/dist/server/props-wire.js +5 -1
  192. package/dist/server/region-endpoint.js +10 -2
  193. package/dist/server/render-cache.d.ts +24 -20
  194. package/dist/server/render-cache.js +99 -40
  195. package/dist/server/render-page.js +46 -15
  196. package/dist/server/request-stats.d.ts +10 -8
  197. package/dist/server/request-stats.js +20 -12
  198. package/dist/server/rules.d.ts +11 -0
  199. package/dist/server/rules.js +64 -0
  200. package/dist/server/signing-key.js +31 -18
  201. package/dist/server/stream-regions.d.ts +14 -1
  202. package/dist/server/stream-regions.js +38 -2
  203. package/dist/shared-state.js +5 -1
  204. package/dist/shims/app-navigation.js +3 -2
  205. package/dist/shims/page-store.svelte.js +16 -2
  206. package/dist/source.js +7 -2
  207. package/dist/store-transport.js +12 -5
  208. package/dist/transport.js +3 -2
  209. package/dist/vite/index.js +83 -74
  210. package/dist/vite/kit-dirs.js +7 -1
  211. package/dist/vite/options.d.ts +2 -1
  212. package/dist/vite/options.js +11 -20
  213. package/dist/vite/package-files.js +13 -3
  214. package/dist/vite/paths.d.ts +2 -0
  215. package/dist/vite/paths.js +4 -4
  216. package/dist/vite/plugin-api.d.ts +6 -5
  217. package/dist/vite/plugin-api.js +42 -14
  218. package/dist/vite/style-preprocess.js +10 -3
  219. package/package.json +8 -1
  220. package/dist/KeepHost.svelte +0 -19
  221. package/dist/KeepHost.svelte.d.ts +0 -10
  222. package/dist/LiveHost.svelte +0 -19
  223. package/dist/LiveHost.svelte.d.ts +0 -10
  224. package/dist/NestedProvider.svelte +0 -13
  225. package/dist/NestedProvider.svelte.d.ts +0 -8
  226. package/dist/runtime/page-cache.d.ts +0 -23
  227. package/dist/runtime/page-cache.js +0 -74
@@ -0,0 +1,800 @@
1
+ import { define_messages } from "./define.js";
2
+ import { prose } from "./prose.js";
3
+ // src/messages/build.ts
4
+ /**
5
+ * EVERY MESSAGE OGYGIA PRINTS AT BUILD TIME — the compiler and the Vite plugin, which run in Node
6
+ * (never in a page, so there is no production build to keep the wording out of): their code, their
7
+ * wording, what to do about them. Same calls as the runtime's (./core.ts):
8
+ *
9
+ * throw new OgygiaError('some_code', { file });
10
+ * warn('some_code', { file });
11
+ *
12
+ * The wording always prints, then the code's page `https://ogygiajs.dev/e/<code>?<args>`.
13
+ */
14
+ const BUG = "An ogygia bug: please report it with the file that shows it.";
15
+ /** Retired `ogygia({ … })` keys, each with its new spelling: the config check throws
16
+ * `option_retired` for any of them (a legacy key that silently did nothing would un-tune real
17
+ * apps). */
18
+ const RETIRED_OPTIONS = {
19
+ regions: "`regions` is gone — its keys sit at the root now: write `visible`, `presets`, `ttl` and `maxPageAge` directly in `ogygia({ … })`.",
20
+ continuity: "`continuity` is gone — form continuity rides the router. Write `router: { forms: false }` to disable it.",
21
+ regionTtl: "`regionTtl` is `ttl` now — write `ogygia({ ttl: … })`.",
22
+ preload: "`preload` is gone — there is nothing to choose any more. The page carries each island’s chunk list as data, and the runtime preloads an island’s whole graph when it wakes (after the page has painted), so no island code moves before its wake and none waits on a waterfall after it. Remove the key.",
23
+ plugins: "`plugins` is gone — ogygia plugins are Vite plugins: list them beside `ogygia()` in vite.config, `plugins: [ogygia(), flags(), sveltekit()]`.",
24
+ freeze: "`freeze` is a plugin now, named postrender — install `@ogygia/postrender` and list `postrender({ ttl, default })` (from `@ogygia/postrender/vite`) beside `ogygia()` in vite.config `plugins`.",
25
+ content: "`content` is a plugin now — install `@ogygia/content` and list `content({ markdown, presets })` (from `@ogygia/content/vite`) beside `ogygia()` in vite.config `plugins`; the svelte config takes `preprocess()` / `extensions()` from there too.",
26
+ devtools: "`devtools` is a plugin now — install `@ogygia/devtools` and list `devtools()` (from `@ogygia/devtools/vite`) beside `ogygia()` in vite.config `plugins`; only where you want it, e.g. `...(mode !== 'production' ? [devtools()] : [])`.",
27
+ profiler: "`profiler` is part of the devtools plugin now — install `@ogygia/devtools` and list `devtools({ profiler: { … } })` (from `@ogygia/devtools/vite`) beside `ogygia()` in vite.config `plugins`."
28
+ };
29
+ /** The errors: `throw new OgygiaError(code, args)`. */
30
+ const BUILD_ERRORS = {
31
+ macro_store_misuse: {
32
+ text: (a) => prose`
33
+ ${a.file}:${a.line} — ${a.problem}. import.meta.og.store is legal in exactly one shape: a
34
+ direct call wrapping a store factory — import.meta.og.store((seed) => ({ subscribe, … })).
35
+ It registers the factory under a build tag so islands rebuild the store THROUGH it (custom
36
+ methods survive); the factory's first parameter is the seed value.
37
+ `,
38
+ details: () => prose`
39
+ \`import.meta.og.store\` is a compile-time mark, not a value: it only works as a direct
40
+ call around a store factory, \`import.meta.og.store((seed) => writable(seed))\`. The
41
+ build registers that factory so an island rebuilds the store through it, custom methods
42
+ and all.
43
+
44
+ \`problem\` names what was written instead (no argument, two arguments, a bare
45
+ reference). Wrap the factory itself in one call.
46
+ `
47
+ },
48
+ macro_dollar_misuse: {
49
+ text: (a) => prose`
50
+ ${a.file}:${a.line} — ${a.problem}. import.meta.og.$ is legal in exactly one shape: a
51
+ direct call wrapping an inline function — import.meta.og.$((args) => { … }). It hoists
52
+ that function so its VALUE can cross an island boundary as a handle.
53
+ `,
54
+ details: () => prose`
55
+ \`import.meta.og.$\` hoists a function into its own module so a handle to it can cross an
56
+ island boundary. The build has to see the function itself, so the mark only works as a
57
+ direct call around an inline function: \`import.meta.og.$((args) => ...)\`.
58
+
59
+ \`problem\` names what was written instead. Pass the function inline, as the one argument.
60
+ `
61
+ },
62
+ macro_wire_misuse: {
63
+ text: (a) => prose`
64
+ ${a.file}:${a.line} — ${a.problem}. import.meta.og.wire is legal in exactly one position:
65
+ \`static wire = import.meta.og.wire({ encode, decode })\` inside a class body. The macro
66
+ consumes that member and mints the symbol key; the construct is not a value.
67
+ `,
68
+ details: () => prose`
69
+ \`import.meta.og.wire\` makes a class transportable across an island boundary. The build
70
+ replaces the member that holds it, so it only works in one place: a static member of a
71
+ class, \`static wire = import.meta.og.wire(codec)\`, where the codec has \`encode\` and
72
+ \`decode\`.
73
+
74
+ \`problem\` names what was written instead. Move the call into that member.
75
+ `
76
+ },
77
+ macro_source_misuse: {
78
+ text: (a) => prose`
79
+ ${a.file}:${a.line} — ${a.problem}. import.meta.og.source is legal in exactly one
80
+ position: \`export const <name> = import.meta.og.source(fn)\` (optionally
81
+ \`(fn, { key })\`) at module top level. The compiler stamps the source id from that
82
+ export's identity.
83
+ `,
84
+ details: () => prose`
85
+ \`import.meta.og.source\` declares a data source. Its id is the file and export name it is
86
+ declared under, so the build only accepts it as the initializer of a top-level
87
+ \`export const\`: \`export const loadThing = import.meta.og.source(fn)\`.
88
+
89
+ \`problem\` names what was written instead. Declare the source as its own exported
90
+ constant.
91
+ `
92
+ },
93
+ macro_bake_arity: {
94
+ text: (a) => `${a.file}:${a.line} — import.meta.og.bake(fn) takes exactly one argument (a function).`,
95
+ details: () => prose`
96
+ \`import.meta.og.bake\` runs one function at build time and inlines its result. It takes
97
+ that function and nothing else: \`import.meta.og.bake(() => buildNav())\`.
98
+ `
99
+ },
100
+ macro_bake_not_function: {
101
+ text: (a) => `${a.file}:${a.line} — import.meta.og.bake(fn): the argument must be a function (\`() => …\`).`,
102
+ details: () => prose`
103
+ \`import.meta.og.bake\` was given something other than an inline function (a variable, a
104
+ value). The build evaluates the function's own source, so write it inline:
105
+ \`import.meta.og.bake(() => buildNav())\`.
106
+ `
107
+ },
108
+ macro_bake_eval_failed: {
109
+ text: (a) => prose`
110
+ import.meta.og.bake() in ${a.file}: evaluating the function failed — ${a.reason}. A baked
111
+ function may use this module's IMPORTS and literals only (not its other local variables),
112
+ and must not touch runtime-only modules ($app/*, the browser).
113
+ `,
114
+ details: () => prose`
115
+ The build bundled the baked function with the module's imports and ran it, and it threw.
116
+ \`reason\` is the error.
117
+
118
+ The function runs alone, at build time: it sees the module's imports and literals, not its
119
+ other local variables, and there is no request, no \`$app/*\` module and no browser. Move
120
+ what it needs into an import.
121
+ `
122
+ },
123
+ macro_bake_not_serializable: {
124
+ text: (a) => prose`
125
+ ${a.file}:${a.line} — import.meta.og.bake(): the result is not serializable (${a.reason}).
126
+ bake produces DATA — return plain values (JSON + Date/Map/Set/RegExp/BigInt), never a
127
+ function, Promise, or class instance.
128
+ `,
129
+ details: () => prose`
130
+ The baked function ran, but its result cannot be written into the module as a constant.
131
+ \`reason\` names the value that failed.
132
+
133
+ Return plain data: JSON values, \`Date\`, \`Map\`, \`Set\`, \`RegExp\`, \`BigInt\`. A
134
+ function, a promise or a class instance cannot be baked.
135
+ `
136
+ },
137
+ kit_config_not_literal: {
138
+ text: (a) => `${a.file}: \`config.${a.key}\` must be a literal (true, false, a number, a string or null) — ogygia reads it at build time.`,
139
+ details: () => prose`
140
+ ogygia reads some keys of a route's \`export const config\` while it builds, from the
141
+ source. This one is an expression (a variable, a call), which only has a value when the
142
+ app runs. Write the value itself: \`true\`, \`false\`, a number, a string or \`null\`.
143
+ `
144
+ },
145
+ island_import_unresolved: {
146
+ text: (a) => prose`
147
+ cannot resolve '${a.specifier}' imported by the generated island module for ${a.host}.
148
+ That island was marked on a package import, so the specifier must resolve from the host
149
+ file: check the package is installed and its "exports" map exposes this subpath (with a
150
+ "svelte" condition for .svelte components).
151
+ `,
152
+ details: () => prose`
153
+ An island was marked on an import from a package, and the module ogygia generates for it
154
+ imports that same specifier. It does not resolve from the file that marked it.
155
+
156
+ Check the package is installed in the app, and that its \`exports\` map lists this
157
+ subpath, with a \`svelte\` condition for a \`.svelte\` component.
158
+ `
159
+ },
160
+ call_arg_not_literal: {
161
+ text: (a) => `${a.call}: the first argument must be a static string literal, got '${a.got}…'`,
162
+ details: () => prose`
163
+ The build reads this call's first argument from the source, so it has to be a plain
164
+ string, written out. \`got\` is what was written instead (a variable, a call). Put the
165
+ string itself there.
166
+ `
167
+ },
168
+ call_arg_interpolated: {
169
+ text: (a) => prose`
170
+ ${a.call}: the first argument must be a static string literal — a template literal with
171
+ \${…} interpolation is a runtime value the build cannot resolve.
172
+ `,
173
+ details: () => prose`
174
+ The build reads this call's first argument from the source. A template literal with a
175
+ value inside it only has its text when the app runs. Write one plain string.
176
+ `
177
+ },
178
+ call_arg_in_expression: {
179
+ text: (a) => prose`
180
+ ${a.call}: the first argument must be a static string literal, but it is part of a larger
181
+ expression (near '${a.near}…'). Use one plain string.
182
+ `,
183
+ details: () => prose`
184
+ The build reads this call's first argument from the source. Here the string is joined
185
+ with something else (\`'./' + dir\`, a \`.concat()\` call), which only has its value when
186
+ the app runs. Write the whole string out.
187
+ `
188
+ },
189
+ import_key_invalid: {
190
+ text: (a) => `importKeys.${a.role} must be a non-empty JS identifier (got ${a.got}).`,
191
+ details: () => prose`
192
+ \`importKeys\` renames the import attributes ogygia reads (\`wake\`, \`fetch\`,
193
+ \`render\`, \`preset\`, \`region\`). Each name is written as a key inside \`with\`, so it
194
+ has to be a JavaScript identifier.
195
+ `
196
+ },
197
+ import_keys_not_distinct: {
198
+ text: () => "importKeys.wake, importKeys.fetch, importKeys.render, importKeys.preset, and importKeys.region must be distinct.",
199
+ details: () => prose`
200
+ Two of the attribute names in \`importKeys\` are the same, so the build could not tell
201
+ which one an import means. Give each its own name.
202
+ `
203
+ },
204
+ region_value_not_raw: {
205
+ text: (a) => prose`
206
+ ${a.host}: \`${a.key}\` only takes the value 'raw' (a held region with no baked
207
+ schedule). To bake a schedule use a \`wake:\` mark, or set it at the \`region()\` call.
208
+ `,
209
+ details: () => prose`
210
+ The \`region\` import attribute marks a held region and has one value, \`'raw'\`. It
211
+ carries no schedule. To give the region one, mark the import with \`wake\` instead, or
212
+ pass \`wake\` where it is placed: \`region(C, props, opts)\`.
213
+ `
214
+ },
215
+ wake_strategy_unknown: {
216
+ text: (a) => `${a.host}: unknown \`${a.key}\` strategy '${a.value}'. Use 'load' | 'idle' | 'visible' | 'interaction' | a media query.`,
217
+ details: () => prose`
218
+ A \`wake\` mark says when an island's JavaScript runs. It takes \`'load'\`, \`'idle'\`,
219
+ \`'visible'\`, \`'interaction'\` or a media query such as \`'(min-width: 800px)'\`.
220
+ `
221
+ },
222
+ generated_module_relative_import: {
223
+ text: (a) => prose`
224
+ ${a.host}: cannot resolve the relative import '${a.specifier}' from a generated module —
225
+ it has no directory. Its real origin must be threaded (HostCtx.originOf); this is an
226
+ ogygia bug, please report it.
227
+ `,
228
+ details: () => BUG
229
+ },
230
+ region_import_invalid: {
231
+ text: (a) => `${a.host}: import { ${a.names} } — ${a.problem}`,
232
+ details: () => prose`
233
+ A marked import (one with \`wake\`, \`render\`, \`fetch\`, \`preset\` or \`region\` in
234
+ its \`with\` clause) is written in a way the build cannot turn into a region. \`problem\`
235
+ says what is wrong and what to write.
236
+ `
237
+ },
238
+ as_region_invalid: {
239
+ text: (a) => `${a.host}: import.meta.og.asRegion (${a.name}) — ${a.problem}`,
240
+ details: () => prose`
241
+ \`import.meta.og.asRegion\` marks a component as a region, like a marked import. It only
242
+ works on a plain \`const Name = import.meta.og.asRegion(Component, options)\`, with the
243
+ same options an import's \`with\` clause takes. \`problem\` says what is wrong.
244
+ `
245
+ },
246
+ region_children_not_portable: {
247
+ text: (a) => prose`
248
+ ${a.host}: <${a.tag}> has host children/snippets that cannot cross the island boundary.
249
+ Under portable bindings, pass serializable props and put UI inside the island
250
+ component${a.server ? " (only the reserved `{#snippet ogygiaFallback()}` may appear at the call site)." : "."}
251
+ `,
252
+ details: () => prose`
253
+ A deferred region or a held region renders on its own, from its props alone, so markup
254
+ written between its tags has nowhere to go. Pass the data as props and put the markup
255
+ inside the component.
256
+
257
+ A deferred region may keep one snippet at the call site: \`ogygiaFallback\`, what shows
258
+ until its HTML arrives.
259
+ `
260
+ },
261
+ region_dotted_tag: {
262
+ text: (a) => prose`
263
+ ${a.host}: dotted tag \`<${a.tag}>\` is not supported for region import '${a.import}'.
264
+ Import the leaf component with \`with { hydrate|defer }\` instead.
265
+ `,
266
+ details: () => prose`
267
+ A marked import becomes one region, so the build cannot reach a component hanging off it
268
+ (\`Menu.Item\`). Import that component on its own and mark that import.
269
+ `
270
+ },
271
+ dynamic_region_import: {
272
+ text: (a) => prose`
273
+ ${a.host}: dynamic import() with { with: { ${a.keys} } } is not supported. Mark islands
274
+ with a static \`import X from '…' with { ${a.wake_key}: '…' }\` (or \`${a.render_key}\` /
275
+ \`${a.preset_key}\`) — the binding becomes a portable island component. For a
276
+ click-loaded chunk that is not an island, use plain \`await import('./Comp.svelte')\` (no
277
+ region attributes) inside a host island. To delay a real island until click, gate a static
278
+ region import with \`{#if}\`.
279
+ `,
280
+ details: () => prose`
281
+ A region needs a static import and a tag the server can render, so region attributes on
282
+ a dynamic \`import()\` do nothing (Vite drops them). Use a static marked import.
283
+
284
+ To load a plain component on click, call \`await import('./Comp.svelte')\` with no region
285
+ attributes, inside an island. To delay an island, put its tag behind an \`if\` block.
286
+ `
287
+ },
288
+ region_import_no_specifier: {
289
+ text: (a) => `${a.host}: ${a.held ? "held-region import" : "region import"} '${a.name}' needs a module specifier ($lib/…, relative, or a package specifier like 'pkg/component').`,
290
+ details: () => prose`
291
+ A marked import has no module path the build can resolve. Import the component from
292
+ \`$lib/...\`, a relative path, or a package subpath such as \`'pkg/component'\`.
293
+ `
294
+ },
295
+ snippet_reads_dollar_props: {
296
+ text: (a) => prose`
297
+ ${a.host}: {#snippet ${a.snippet}} crosses an island boundary but reads \`${a.name}\` —
298
+ the host's $$-props cannot cross. Read the value into a plain host variable outside the
299
+ snippet and use that instead.
300
+ `,
301
+ details: () => prose`
302
+ A snippet passed into an island is rendered from the values it captures. \`$$props\` and
303
+ \`$$restProps\` belong to the host component and cannot be captured. Read what the
304
+ snippet needs into a plain variable in the host, outside the snippet, and use that.
305
+ `
306
+ },
307
+ held_fetch_without_render: {
308
+ text: (a) => prose`
309
+ ${a.host}: \`${a.fetch_key}: '${a.value}'\` without \`${a.render_key}: 'deferred'\` —
310
+ \`${a.fetch_key}\` is a hole's timing. Write \`${a.render_key}: 'deferred',
311
+ ${a.fetch_key}: '${a.value}'\` for a hole, or \`${a.wake_key}: '${a.value}'\` for an
312
+ island.
313
+ `,
314
+ details: () => prose`
315
+ \`fetch\` says when a deferred region's (a hole's) HTML arrives, so it only goes with
316
+ \`render: 'deferred'\`. For a hole, write both. For an island that runs its JavaScript
317
+ at that time, write \`wake\` instead.
318
+ `
319
+ },
320
+ held_render_live: {
321
+ text: (a) => `${a.host}: \`${a.render_key}: 'live'\` is not supported on a .ts import — use it in a .svelte file.`,
322
+ details: () => prose`
323
+ A live region is placed by a Svelte component. A \`.ts\` or \`.js\` module can only hand
324
+ out held regions and holes, so mark the import in a \`.svelte\` file.
325
+ `
326
+ },
327
+ held_render_unknown: {
328
+ text: (a) => `${a.host}: unknown \`${a.render_key}\` '${a.value}'. Use 'deferred'.`,
329
+ details: () => prose`
330
+ In a \`.ts\` or \`.js\` module, \`render\` takes one value, \`'deferred'\`: a hole whose
331
+ HTML is fetched from the server.
332
+ `
333
+ },
334
+ held_hole_timed_twice: {
335
+ text: (a) => prose`
336
+ ${a.host}: a \`${a.render_key}: 'deferred'\` hole timed twice, with \`${a.fetch_key}:
337
+ '${a.fetch}'\` and \`${a.wake_key}: '${a.wake}'\`. Keep \`${a.fetch_key}\`: it says when a
338
+ hole's HTML arrives.
339
+ `,
340
+ details: () => prose`
341
+ A hole has one timing, \`fetch\`. The old spelling, \`wake\` on a hole, is still read,
342
+ but with both the build cannot tell which one is meant. Remove \`wake\`.
343
+ `
344
+ },
345
+ held_fetch_not_timing: {
346
+ text: (a) => prose`
347
+ ${a.host}: \`${a.fetch_key}: '${a.value}'\` is not a timing. Use \`${a.fetch_key}: 'load'
348
+ | 'idle' | 'visible' | 'interaction'\` or a media query (a hole must fetch — not 'none').
349
+ `,
350
+ details: () => prose`
351
+ \`fetch\` says when a hole's HTML arrives: \`'load'\`, \`'idle'\`, \`'visible'\`,
352
+ \`'interaction'\` or a media query. A hole always fetches, so \`'none'\` is not one.
353
+ `
354
+ },
355
+ held_marker_mixed: {
356
+ text: (a) => prose`
357
+ ${a.host}: a held-region import on '${a.name}' takes ONE marker — \`${a.region_key}:
358
+ 'raw'\`, \`${a.wake_key}: '…'\`, or \`${a.render_key}: 'deferred'\` (with
359
+ \`${a.fetch_key}\` as its timing).
360
+ `,
361
+ details: () => prose`
362
+ An import in a \`.ts\` or \`.js\` module is one kind of held region: \`region: 'raw'\`
363
+ (no schedule), \`wake\` (an island) or \`render: 'deferred'\` (a hole, timed by
364
+ \`fetch\`). Keep the one you mean.
365
+ `
366
+ },
367
+ option_retired: {
368
+ text: (a) => RETIRED_OPTIONS[a.option] ?? `\`${a.option}\` is gone.`,
369
+ details: () => prose`
370
+ An \`ogygia()\` option from an earlier version was passed. It is refused rather than
371
+ ignored, so nothing silently stops working. The message says what replaced it.
372
+ `
373
+ },
374
+ preset_empty: {
375
+ text: (a) => `presets.${a.name} is empty — a preset with nothing is a mistake.`,
376
+ details: () => prose`
377
+ A region preset names a set of import options (\`with { preset: 'card' }\`). This one sets
378
+ none. Give it its options, or remove it.
379
+ `
380
+ },
381
+ preset_key_unknown: {
382
+ text: (a) => `presets.${a.name}: unknown key \`${a.key}\`. A preset takes ${a.allowed}.`,
383
+ details: () => prose`
384
+ A region preset holds the options a marked import takes. \`key\` is not one of them;
385
+ \`allowed\` lists those that are.
386
+ `
387
+ },
388
+ max_page_age_invalid: {
389
+ text: (a) => prose`
390
+ maxPageAge must be a number of seconds ≥ 0 (got ${a.value}). Write e.g. \`30 * 24 *
391
+ 3600\` for 30 days, or \`0\` to turn renewal off.
392
+ `,
393
+ details: () => prose`
394
+ \`maxPageAge\` is how long, in seconds, a page's expired region addresses may still be
395
+ renewed. Write a number, such as \`30 * 24 * 3600\` for 30 days, or \`0\` to never renew.
396
+ `
397
+ },
398
+ secret_too_short: {
399
+ text: (a) => `OGYGIA_SECRET is too short for production builds (need ≥${a.min_bytes} UTF-8 bytes).`,
400
+ details: () => prose`
401
+ \`OGYGIA_SECRET\` signs region addresses. A short key can be guessed, so a production
402
+ build refuses it (dev accepts any). Use a long random value, such as the output of
403
+ \`openssl rand -base64 32\`.
404
+ `
405
+ },
406
+ kit_remote_src_missing: {
407
+ text: () => "could not locate Kit's client remote-functions (src). Use an @sveltejs/kit that publishes its `src/` (2.70.2 or later, or 3.x).",
408
+ details: () => prose`
409
+ ogygia reuses SvelteKit's own client code for remote functions, from the \`src/\` folder
410
+ Kit publishes. This version of \`@sveltejs/kit\` does not ship it. Upgrade to 2.70.2 or
411
+ later.
412
+ `
413
+ },
414
+ package_files_not_array: {
415
+ text: (a) => prose`
416
+ ${a.package}: \`"ogygia": { "files": […] }\` must be an array of package-relative
417
+ paths/globs (like npm's "files") — got ${a.got}.
418
+ `,
419
+ details: () => prose`
420
+ A package puts its files on ogygia's compile surface with \`ogygia.files\` in its
421
+ \`package.json\`: a list of paths or globs inside the package, like npm's \`files\`.
422
+ This one is not a list of strings.
423
+ `
424
+ },
425
+ package_files_escapes: {
426
+ text: (a) => `${a.package}: ogygia.files entry '${a.entry}' escapes the package.`,
427
+ details: () => prose`
428
+ An \`ogygia.files\` entry points outside its own package (\`../\`), which would compile
429
+ code the package does not own. List paths inside the package only.
430
+ `
431
+ },
432
+ plugin_without_ogygia: {
433
+ text: (a) => `\`${a.plugin}\` is listed in vite.config but \`ogygia()\` is not — add \`ogygia()\` from \`ogygia/vite\` to \`plugins\`.`,
434
+ details: () => prose`
435
+ An ogygia plugin runs inside \`ogygia()\`, so it does nothing alone. Import \`ogygia\`
436
+ from \`ogygia/vite\` and list \`ogygia()\` first in \`plugins\`.
437
+ `
438
+ },
439
+ plugin_factory_not_called: {
440
+ text: () => "a function is listed in vite.config `plugins` — call the factory: `flags()`, not `flags`.",
441
+ details: () => prose`
442
+ A plugin is listed by its factory's name without calling it. Add the parentheses:
443
+ \`flags()\`, not \`flags\`.
444
+ `
445
+ },
446
+ plugin_after_sveltekit: {
447
+ text: (a) => `\`${a.plugin}\` is listed after \`sveltekit()\` in vite.config — list \`ogygia()\` and its plugins first: \`plugins: [ogygia(), flags(), sveltekit()]\`.`,
448
+ details: () => prose`
449
+ Vite runs plugins in the order they are listed. ogygia and its plugins must see each
450
+ module before SvelteKit does, so list them first:
451
+ \`plugins: [ogygia(), flags(), sveltekit()]\`.
452
+ `
453
+ },
454
+ plugin_name_missing: {
455
+ text: () => "a plugin definition needs a `name` (its package name).",
456
+ details: () => prose`
457
+ \`definePlugin()\` was called without a \`name\`. The name is the plugin's package name:
458
+ ogygia resolves the package by it.
459
+ `
460
+ },
461
+ plugin_listed_twice: {
462
+ text: (a) => `plugin \`${a.plugin}\` is listed twice.`,
463
+ details: () => "The same ogygia plugin appears twice in `plugins`. List it once, with all its options."
464
+ },
465
+ plugin_realm_not_location: {
466
+ text: (a) => `plugin \`${a.plugin}\`: \`${a.realm}\` is a module location — \`import.meta.resolve('./${a.realm}.ts')\`.`,
467
+ details: () => prose`
468
+ A plugin's \`server\` and \`client\` name the module that runs there, as a location, not
469
+ the module itself. Resolve it next to the factory:
470
+ \`server: import.meta.resolve('./server.ts')\`.
471
+ `
472
+ },
473
+ plugin_options_not_json: {
474
+ text: (a) => `plugin \`${a.plugin}\`: \`options\` must be plain JSON (configure live objects in hooks.server.ts).`,
475
+ details: () => prose`
476
+ A plugin's \`options\` are written into the server build, so they must survive
477
+ \`JSON.stringify\`. Set up live objects (clients, functions) in \`hooks.server.ts\`
478
+ instead.
479
+ `
480
+ },
481
+ plugin_realm_not_file: {
482
+ text: (a) => `plugin \`${a.plugin}\`: its \`${a.realm}\` realm \`${a.location}\` is not a file — resolve it next to the factory: \`import.meta.resolve('./${a.realm}.ts')\`.`,
483
+ details: () => prose`
484
+ A plugin's \`server\` or \`client\` location does not point at a file. Resolve it next to
485
+ the factory, so it is the file the package ships:
486
+ \`import.meta.resolve('./server.ts')\`.
487
+ `
488
+ },
489
+ plugin_package_unresolved: {
490
+ text: (a) => `plugin \`${a.plugin}\`: no package by that name resolves from ${a.root} — its name must be its package name.`,
491
+ details: () => prose`
492
+ A plugin's \`name\` is its package name, and ogygia resolves the package by it from the
493
+ app. Nothing by that name is installed there: install the package, or fix the name.
494
+ `
495
+ },
496
+ route_config_key_invalid: {
497
+ text: (a) => `plugin \`${a.plugin}\`: route config key \`${a.key}\` must be a camelCase identifier.`,
498
+ details: () => prose`
499
+ A plugin claimed a key of a route's \`export const config\` that is not a camelCase name.
500
+ Use one such as \`postrender\`.
501
+ `
502
+ },
503
+ route_config_key_claimed: {
504
+ text: (a) => `route config key \`${a.key}\` is claimed by both \`${a.owner}\` and \`${a.plugin}\`.`,
505
+ details: () => prose`
506
+ Two plugins claimed the same key of a route's \`export const config\`, so a route could
507
+ not say which one it configures. One of them has to use another key.
508
+ `
509
+ },
510
+ plugin_macro_name_invalid: {
511
+ text: (a) => `plugin \`${a.plugin}\`: macro \`import.meta.og.${a.name}\` must be a camelCase name core does not own.`,
512
+ details: () => prose`
513
+ A plugin's macro is a camelCase name under \`import.meta.og\`. The names \`wire\`,
514
+ \`$\`, \`source\`, \`store\` and \`bake\` are ogygia's own.
515
+ `
516
+ },
517
+ plugin_macro_claimed: {
518
+ text: (a) => `macro \`import.meta.og.${a.name}\` is claimed by both \`${a.owner}\` and \`${a.plugin}\`.`,
519
+ details: () => prose`
520
+ Two plugins registered the same \`import.meta.og\` macro. One of them has to use another
521
+ name.
522
+ `
523
+ },
524
+ page_modules_not_absolute: {
525
+ text: (a) => `plugin \`${a.plugin}\`: \`pageModules({ files })\` takes absolute paths (got \`${a.file}\`).`,
526
+ details: () => prose`
527
+ \`pageModules\` was given a relative file path. Pass absolute paths, for example
528
+ resolved from the app's root.
529
+ `
530
+ },
531
+ request_event_server_only: {
532
+ text: () => "getRequestEvent is server-only",
533
+ details: () => prose`
534
+ \`getRequestEvent()\` was called in the browser. There is no request there: a deferred
535
+ region's HTML is fetched from the server, so read the request in the component that
536
+ renders on the server, and pass what the browser needs as props. (The build writes this
537
+ message into the browser's stub, so it prints in the page.)
538
+ `
539
+ }
540
+ };
541
+ /** The warnings: `warn(code, args, ...rest)`; and, at its end, the build's reports, which print
542
+ * their `line(code, args)` at info level. */
543
+ const BUILD_WARNINGS = {
544
+ macro_store_returns_non_store: {
545
+ text: (a) => prose`
546
+ ${a.file}:${a.line} — this import.meta.og.store factory has a return that is provably not
547
+ a store (undefined/null/primitive). Where that branch runs, the product crosses as plain
548
+ data, unbranded. If it is an environment guard, return a store there too (e.g.
549
+ writable(seed)) and guard the side effects inside the factory instead.
550
+ `,
551
+ details: () => prose`
552
+ A store factory marked with \`import.meta.og.store\` returns something that is not a
553
+ store on one branch (\`undefined\`, \`null\`, a number). Where that branch runs, the
554
+ value reaches islands as plain data, not as the store.
555
+
556
+ If the branch guards an environment (the server), return a store there too, such as
557
+ \`writable(seed)\`, and guard the side effects inside the factory.
558
+ `
559
+ },
560
+ scoped_css_failed: {
561
+ text: (a) => `scoped CSS for ${a.file} could not be compiled (${a.reason}) — shipping its style bodies unscoped`,
562
+ details: () => prose`
563
+ ogygia compiles a component's styles on their own to ship them with its HTML, and that
564
+ compile failed (\`reason\`). The styles ship without Svelte's scoping, so its rules can
565
+ reach the rest of the page. Fix the component so it compiles.
566
+ `
567
+ },
568
+ package_marks_undeclared: {
569
+ text: (a) => prose`
570
+ ${a.file} uses ogygia marks, but its package declares no \`"ogygia": { "files": [...] }\`
571
+ — the marks are IGNORED. Add the field to that package's package.json
572
+ (npm-"files"-style paths/globs) to put it on ogygia's compile surface.
573
+ `,
574
+ details: () => prose`
575
+ A file in a dependency marks imports for ogygia (\`with { wake }\`), but ogygia only
576
+ compiles a package's files when the package asks for it. So the marks do nothing.
577
+
578
+ Add \`ogygia.files\` to that package's \`package.json\`: the paths or globs ogygia
579
+ compiles, like npm's \`files\`.
580
+ `
581
+ },
582
+ island_context_unprovided: {
583
+ text: (a) => prose`
584
+ island code ${a.file} reads getContext('${a.key}'), but this app registers no ogygia
585
+ context provider and no island code sets '${a.key}'. On a csr=false page a value set with
586
+ Svelte's setContext in a page/layout does NOT cross the island boundary — the island reads
587
+ undefined on the client, re-renders a different tree, and Svelte discards its
588
+ server-rendered DOM on hydration (a silent full re-render). Fix: provide '${a.key}' with
589
+ setContext / <Provide> / createContext imported from 'ogygia' (in a csr=false layout); the
590
+ read stays getContext('${a.key}').
591
+ `,
592
+ details: () => prose`
593
+ An island reads a context nothing in the browser provides. On a csr=false page a layout
594
+ or page runs only on the server, so a value it sets with Svelte's \`setContext\` never
595
+ reaches the island there. The island renders a different tree and Svelte throws its
596
+ server HTML away.
597
+
598
+ Provide the value with \`setContext\`, \`<Provide>\` or \`createContext\` imported from
599
+ \`ogygia\`. The island keeps reading it with \`getContext\`.
600
+ `
601
+ },
602
+ content_leaked_to_client: {
603
+ text: (a) => `content leaked into the CLIENT bundle: ${a.count} corpus module(s) (.svx/.md) shipped to the browser (in chunk '${a.chunk}').\n A content() collection was imported into client-shipped code — usually an island — which drags its eager import.meta.glob (every doc) in.\n Fix: keep the collection in a server-only module (or a .remote.ts) and feed islands DATA (refs) via props or a remote, never the collection itself.\n` + a.modules.split("\n").map((m) => " " + m).join("\n") + (a.count > 5 ? "\n …" : ""),
604
+ details: () => prose`
605
+ Documents of a content collection ended up in the browser bundle. A collection imports
606
+ every document it holds, so importing it into an island ships all of them.
607
+
608
+ Keep the collection in server-only code (a \`+page.server.ts\`, a \`.remote.ts\`) and
609
+ pass islands the data they need, as props or from a remote function.
610
+ `
611
+ },
612
+ region_host_skipped: {
613
+ text: (a) => `regions: skipped ${a.file}: ${a.reason}${a.at ? ` at ${a.at}` : ""} — its region imports stay plain imports`,
614
+ details: () => prose`
615
+ ogygia could not parse the component, so its marked imports were left as plain imports:
616
+ no island, no hole. The Svelte compiler reports the parse error itself. Fix it and the
617
+ regions come back.
618
+ `
619
+ },
620
+ hole_wake_deprecated: {
621
+ text: (a) => prose`
622
+ ${a.host}: ${a.said ? `${a.said} times a \`${a.render_key}: 'deferred'\` hole with` : `a \`${a.render_key}: 'deferred'\` hole timed with`} \`${a.wake_key}: '${a.value}'\`, which is deprecated. Write \`${a.render_key}:
623
+ 'deferred', ${a.fetch_key}: '${a.value}'\` instead: \`${a.fetch_key}\` says when a hole's
624
+ HTML arrives. (\`${a.wake_key}\` is when an island's JS runs; a hole ships no JS.)
625
+ `,
626
+ details: () => prose`
627
+ A deferred region (a hole) is timed with \`wake\`. \`wake\` is when an island's
628
+ JavaScript runs, and a hole ships none: its timing is \`fetch\`, when its HTML arrives.
629
+ The old spelling still works for now. Write \`render: 'deferred', fetch: 'visible'\`.
630
+ `
631
+ },
632
+ snippet_store_snapshot: {
633
+ text: (a) => prose`
634
+ ${a.host}: {#snippet ${a.snippet}} crosses an island boundary and reads \`${a.store}\`
635
+ (at ${a.at}) — captured as a FROZEN snapshot of the store's value at render time; later
636
+ store updates never reach the island. To make the snapshot explicit (and silence this),
637
+ read it at host scope outside the snippet — e.g. \`const ${a.store.slice(1)}_value =
638
+ ${a.store};\` — and use that.
639
+ `,
640
+ details: () => prose`
641
+ A snippet passed into an island reads a store with \`$\`. In plain Svelte that value is
642
+ live. Across an island boundary the snippet is rendered once from the values it captured,
643
+ so the island keeps the value the store had at render time.
644
+
645
+ To say so in the code (and silence this), read the value into a host variable outside
646
+ the snippet and use that. For a value that keeps changing, share a wired class instead.
647
+ `
648
+ },
649
+ snippet_store_unverified: {
650
+ text: (a) => prose`
651
+ ${a.host}: {#snippet ${a.snippet}} reads \`${a.store}\` (at ${a.at}), but
652
+ \`${a.store.slice(1)}\` is not a host declaration or import, so ogygia cannot verify it
653
+ is a store. Its value is captured at the host anyway — if the build now errors in
654
+ ${a.host}, start there.
655
+ `,
656
+ details: () => prose`
657
+ A snippet passed into an island reads \`$name\`, but \`name\` is not declared or imported
658
+ in the host, so ogygia cannot tell it is a store. It captures the value at the host as if
659
+ it were. If the build then fails in that file, this is the place to look.
660
+ `
661
+ },
662
+ snippet_captures_store: {
663
+ text: (a) => prose`
664
+ ${a.host}: {#snippet ${a.snippet}} crosses an island boundary and captures the store
665
+ \`${a.store}\` as an OBJECT — a host-declared store cannot cross (its functions don't
666
+ serialize). Use its value (\`$${a.store}\`) inside the snippet, or share live state with a
667
+ wired class instead.
668
+ `,
669
+ details: () => prose`
670
+ A snippet passed into an island uses a store declared in the host as an object. The
671
+ snippet's captures are serialized, and a store's functions cannot be. Read its value
672
+ with \`$\` inside the snippet, or share live state with a wired class.
673
+ `
674
+ },
675
+ barrels_component_skipped: {
676
+ text: (a) => `barrels: skipped ${a.file}: ${a.reason}${a.at ? ` at ${a.at}` : ""} — its imports stay on their barrels`,
677
+ details: () => prose`
678
+ ogygia rewrites imports from an index file (a barrel) to the files that define them, so
679
+ an island ships only what it uses. It could not parse this component, so its imports
680
+ stay as written and its island ships each barrel whole.
681
+ `
682
+ },
683
+ sass_missing: {
684
+ text: () => "a server-rendered component has `<style lang=\"scss\">` but neither `sass-embedded` nor `sass` is installed — its hole/router CSS ships unprocessed",
685
+ details: () => prose`
686
+ ogygia compiles the styles of components it serves itself (holes, router pages). One is
687
+ written in SCSS and no Sass compiler is installed, so its CSS ships as written. Install
688
+ \`sass-embedded\` or \`sass\`.
689
+ `
690
+ },
691
+ scss_compile_failed: {
692
+ text: (a) => `${a.file}: scss compile failed — ${a.reason}`,
693
+ details: () => prose`
694
+ A component's SCSS did not compile (\`reason\`), so its style block ships as written.
695
+ Fix the stylesheet.
696
+ `
697
+ },
698
+ ts_strip_failed: {
699
+ text: (a) => `${a.file}: TypeScript strip failed — ${a.reason}`,
700
+ details: () => prose`
701
+ ogygia strips the types from a component's TypeScript script to compile its styles, and
702
+ that failed (\`reason\`). The component's CSS may then ship unscoped. Fix the script.
703
+ `
704
+ },
705
+ optimize_deps_includes_ogygia: {
706
+ text: (a) => prose`
707
+ optimizeDeps.include lists ${a.specifiers}: ogygia must not be pre-bundled in dev (the
708
+ page would run two copies of its runtime, and islands with snippet props fail to
709
+ hydrate). Remove ${a.count === 1 ? "it" : "them"}.
710
+ `,
711
+ details: () => prose`
712
+ Vite's \`optimizeDeps.include\` lists part of ogygia. ogygia keeps itself out of Vite's
713
+ dependency pre-bundling, and listing it brings a second copy of its runtime into the dev
714
+ page. Remove those entries.
715
+ `
716
+ },
717
+ island_handoff_write_failed: {
718
+ text: () => "could not write the server-leg island handoff:",
719
+ details: () => prose`
720
+ The server build writes which components it transformed, so the client build emits only
721
+ the islands those pages place. Writing it failed (the error follows the message). The
722
+ build goes on and emits every island it found.
723
+ `
724
+ },
725
+ package_files_missing: {
726
+ text: (a) => `${a.package}: ogygia.files entry '${a.entry}' does not exist — skipped.`,
727
+ details: () => prose`
728
+ An \`ogygia.files\` entry in a dependency's \`package.json\` names a path that is not in
729
+ the package. It is skipped. The package should fix or remove the entry.
730
+ `
731
+ },
732
+ kit_config_unreadable: {
733
+ text: (a) => `could not read ${a.file} for kit.files.routes / kit.outDir — using the defaults (${a.routes}, ${a.out}). ${a.reason}`,
734
+ details: () => prose`
735
+ ogygia loads \`svelte.config.js\` to find the routes folder and Kit's output folder, and
736
+ loading it threw (the reason follows). It uses Kit's defaults. If the app moved either
737
+ folder, fix the config so it loads.
738
+ `
739
+ },
740
+ island_chunks_not_emitted: {
741
+ text: (a) => `${a.count} island chunk(s) not emitted: their host modules are not in the server bundle (unreachable from this build's routes).`,
742
+ details: () => prose`
743
+ The client build found islands whose host components no route of this build renders, so
744
+ it left their chunks out. Nothing is wrong unless an island is missing from a page that
745
+ should have it: then check the route that renders its host is part of the build.
746
+ `
747
+ },
748
+ flags_manifest_written: {
749
+ text: (a) => `flags manifest: ${a.count} flag(s) → node_modules/.ogygia/flags-manifest.json`,
750
+ details: () => prose`
751
+ The build wrote the inventory of every \`flag()\` it found, with where each is read, to
752
+ \`node_modules/.ogygia/flags-manifest.json\`. Tools (the devtools, a flag dashboard) read it
753
+ from there.
754
+ `
755
+ },
756
+ page_seed_report: {
757
+ text: (a) => `page seed: ${a.islands} island${a.islands === 1 ? "" : "s"} read page.data — ${a.pinned} pinned to ${a.keys} key${a.keys === 1 ? "" : "s"}, ${a.unpinned} ship all of it`,
758
+ details: () => prose`
759
+ An island that reads \`page.data\` gets a copy of it in the page. When the build can see
760
+ which keys it reads, the island is pinned to them and only those ship. When it cannot (the
761
+ whole object is spread, passed on, or read with a computed key), the island ships all of
762
+ \`page.data\`.
763
+
764
+ The lines below the report name the modules that made an island ship everything, with
765
+ the reason. Read the keys you need by name there, and the copy shrinks.
766
+ `
767
+ },
768
+ barrels_report: {
769
+ text: (a) => `barrels: ${a.importers} of ${a.files} files rewritten — ${a.imports} barrel imports → leaves (${a.names} names), ${a.barrels} barrels bypassed, ${a.seconds} s first to last transform`,
770
+ details: () => prose`
771
+ ogygia rewrote imports from index files (barrels) to the files that define each name, so
772
+ an island ships only what it uses. The report counts the rewrites and lists the barrels
773
+ that were bypassed the most, with how many files imported through each.
774
+
775
+ \`barrels: { report: 'all' }\` lists every barrel, \`report: false\` turns the report off,
776
+ and \`debug: true\` prints each rewrite as it happens.
777
+ `
778
+ },
779
+ barrels_report_none: {
780
+ text: (a) => `barrels: ${a.files} files scanned, no barrel imports to rewrite (${a.seconds} s)`,
781
+ details: () => prose`
782
+ ogygia looked for imports through index files (barrels) to rewrite to the files that
783
+ define each name, and found none. Nothing to do.
784
+ `
785
+ },
786
+ barrels_rewrite: {
787
+ text: (a) => `barrels: ${a.file}: ${a.names} ← ${a.barrel} → ${a.leaves}`,
788
+ details: () => prose`
789
+ With \`barrels: { debug: true }\`, ogygia prints each import it rewrites: the names,
790
+ the index file (barrel) they were imported through, and the files that define them,
791
+ which the import now points at.
792
+ `
793
+ }
794
+ };
795
+ const build = define_messages(BUILD_ERRORS, BUILD_WARNINGS);
796
+ const OgygiaError = build.OgygiaError;
797
+ const warn = build.warn;
798
+ /** A code's line as a string, for a logger that takes one (Rollup's `this.warn`). */
799
+ const line = build.line;
800
+ export { BUILD_ERRORS, BUILD_WARNINGS, OgygiaError, RETIRED_OPTIONS, line, warn };