@useavalon/avalon 0.1.11 → 0.1.13

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 (141) hide show
  1. package/README.md +54 -54
  2. package/mod.ts +302 -302
  3. package/package.json +49 -26
  4. package/src/build/integration-bundler-plugin.ts +116 -116
  5. package/src/build/integration-config.ts +168 -168
  6. package/src/build/integration-detection-plugin.ts +117 -117
  7. package/src/build/integration-resolver-plugin.ts +90 -90
  8. package/src/build/island-manifest.ts +269 -269
  9. package/src/build/island-types-generator.ts +476 -476
  10. package/src/build/mdx-island-transform.ts +464 -464
  11. package/src/build/mdx-plugin.ts +98 -98
  12. package/src/build/page-island-transform.ts +598 -598
  13. package/src/build/prop-extractors/index.ts +21 -21
  14. package/src/build/prop-extractors/lit.ts +140 -140
  15. package/src/build/prop-extractors/qwik.ts +16 -16
  16. package/src/build/prop-extractors/solid.ts +125 -125
  17. package/src/build/prop-extractors/svelte.ts +194 -194
  18. package/src/build/prop-extractors/vue.ts +111 -111
  19. package/src/build/sidecar-file-manager.ts +104 -104
  20. package/src/build/sidecar-renderer.ts +30 -30
  21. package/src/client/adapters/index.ts +21 -13
  22. package/src/client/components.ts +35 -35
  23. package/src/client/css-hmr-handler.ts +344 -344
  24. package/src/client/framework-adapter.ts +462 -462
  25. package/src/client/hmr-coordinator.ts +396 -396
  26. package/src/client/hmr-error-overlay.js +533 -533
  27. package/src/client/main.js +824 -816
  28. package/src/client/types/framework-runtime.d.ts +68 -68
  29. package/src/client/types/vite-hmr.d.ts +46 -46
  30. package/src/client/types/vite-virtual-modules.d.ts +70 -60
  31. package/src/components/Image.tsx +123 -123
  32. package/src/components/IslandErrorBoundary.tsx +145 -145
  33. package/src/components/LayoutDataErrorBoundary.tsx +141 -141
  34. package/src/components/LayoutErrorBoundary.tsx +127 -127
  35. package/src/components/PersistentIsland.tsx +52 -52
  36. package/src/components/StreamingErrorBoundary.tsx +233 -233
  37. package/src/components/StreamingLayout.tsx +538 -538
  38. package/src/core/components/component-analyzer.ts +192 -192
  39. package/src/core/components/component-detection.ts +508 -508
  40. package/src/core/components/enhanced-framework-detector.ts +500 -500
  41. package/src/core/components/framework-registry.ts +563 -563
  42. package/src/core/content/mdx-processor.ts +46 -46
  43. package/src/core/integrations/index.ts +19 -19
  44. package/src/core/integrations/loader.ts +125 -125
  45. package/src/core/integrations/registry.ts +175 -175
  46. package/src/core/islands/island-persistence.ts +325 -325
  47. package/src/core/islands/island-state-serializer.ts +258 -258
  48. package/src/core/islands/persistent-island-context.tsx +80 -80
  49. package/src/core/islands/use-persistent-state.ts +68 -68
  50. package/src/core/layout/enhanced-layout-resolver.ts +322 -322
  51. package/src/core/layout/layout-cache-manager.ts +485 -485
  52. package/src/core/layout/layout-composer.ts +357 -357
  53. package/src/core/layout/layout-data-loader.ts +516 -516
  54. package/src/core/layout/layout-discovery.ts +243 -243
  55. package/src/core/layout/layout-matcher.ts +299 -299
  56. package/src/core/layout/layout-types.ts +110 -110
  57. package/src/core/modules/framework-module-resolver.ts +273 -273
  58. package/src/islands/component-analysis.ts +213 -213
  59. package/src/islands/css-utils.ts +565 -565
  60. package/src/islands/discovery/index.ts +80 -80
  61. package/src/islands/discovery/registry.ts +340 -340
  62. package/src/islands/discovery/resolver.ts +477 -477
  63. package/src/islands/discovery/scanner.ts +386 -386
  64. package/src/islands/discovery/types.ts +117 -117
  65. package/src/islands/discovery/validator.ts +544 -544
  66. package/src/islands/discovery/watcher.ts +368 -368
  67. package/src/islands/framework-detection.ts +428 -428
  68. package/src/islands/integration-loader.ts +490 -490
  69. package/src/islands/island.tsx +565 -565
  70. package/src/islands/render-cache.ts +550 -550
  71. package/src/islands/types.ts +80 -80
  72. package/src/islands/universal-css-collector.ts +157 -157
  73. package/src/islands/universal-head-collector.ts +137 -137
  74. package/src/layout-system.d.ts +592 -592
  75. package/src/layout-system.ts +218 -218
  76. package/src/middleware/discovery.ts +268 -268
  77. package/src/middleware/executor.ts +315 -315
  78. package/src/middleware/index.ts +76 -76
  79. package/src/middleware/types.ts +99 -99
  80. package/src/nitro/build-config.ts +575 -575
  81. package/src/nitro/config.ts +483 -483
  82. package/src/nitro/error-handler.ts +636 -636
  83. package/src/nitro/index.ts +173 -173
  84. package/src/nitro/island-manifest.ts +584 -584
  85. package/src/nitro/middleware-adapter.ts +260 -260
  86. package/src/nitro/renderer.ts +1471 -1471
  87. package/src/nitro/route-discovery.ts +439 -439
  88. package/src/nitro/types.ts +321 -321
  89. package/src/render/collect-css.ts +198 -198
  90. package/src/render/error-pages.ts +79 -79
  91. package/src/render/isolated-ssr-renderer.ts +654 -654
  92. package/src/render/ssr.ts +1030 -1030
  93. package/src/schemas/api.ts +30 -30
  94. package/src/schemas/core.ts +64 -64
  95. package/src/schemas/index.ts +212 -212
  96. package/src/schemas/layout.ts +279 -279
  97. package/src/schemas/routing/index.ts +38 -38
  98. package/src/schemas/routing.ts +376 -376
  99. package/src/types/as-island.ts +20 -20
  100. package/src/types/image.d.ts +106 -106
  101. package/src/types/index.d.ts +22 -22
  102. package/src/types/island-jsx.d.ts +33 -33
  103. package/src/types/island-prop.d.ts +20 -20
  104. package/src/types/layout.ts +285 -285
  105. package/src/types/mdx.d.ts +6 -6
  106. package/src/types/routing.ts +555 -555
  107. package/src/types/types.ts +5 -5
  108. package/src/types/urlpattern.d.ts +49 -49
  109. package/src/types/vite-env.d.ts +11 -11
  110. package/src/utils/dev-logger.ts +299 -299
  111. package/src/utils/fs.ts +151 -151
  112. package/src/vite-plugin/auto-discover.ts +551 -551
  113. package/src/vite-plugin/config.ts +266 -266
  114. package/src/vite-plugin/errors.ts +127 -127
  115. package/src/vite-plugin/image-optimization.ts +156 -156
  116. package/src/vite-plugin/integration-activator.ts +126 -126
  117. package/src/vite-plugin/island-sidecar-plugin.ts +176 -176
  118. package/src/vite-plugin/module-discovery.ts +189 -189
  119. package/src/vite-plugin/nitro-integration.ts +1354 -1354
  120. package/src/vite-plugin/plugin.ts +403 -409
  121. package/src/vite-plugin/types.ts +327 -327
  122. package/src/vite-plugin/validation.ts +228 -228
  123. package/src/client/adapters/index.js +0 -12
  124. package/src/client/adapters/lit-adapter.js +0 -467
  125. package/src/client/adapters/lit-adapter.ts +0 -654
  126. package/src/client/adapters/preact-adapter.js +0 -223
  127. package/src/client/adapters/preact-adapter.ts +0 -331
  128. package/src/client/adapters/qwik-adapter.js +0 -259
  129. package/src/client/adapters/qwik-adapter.ts +0 -345
  130. package/src/client/adapters/react-adapter.js +0 -220
  131. package/src/client/adapters/react-adapter.ts +0 -353
  132. package/src/client/adapters/solid-adapter.js +0 -295
  133. package/src/client/adapters/solid-adapter.ts +0 -451
  134. package/src/client/adapters/svelte-adapter.js +0 -368
  135. package/src/client/adapters/svelte-adapter.ts +0 -524
  136. package/src/client/adapters/vue-adapter.js +0 -278
  137. package/src/client/adapters/vue-adapter.ts +0 -467
  138. package/src/client/components.js +0 -23
  139. package/src/client/css-hmr-handler.js +0 -263
  140. package/src/client/framework-adapter.js +0 -283
  141. package/src/client/hmr-coordinator.js +0 -274
@@ -1,368 +0,0 @@
1
- /**
2
- * Svelte HMR Adapter
3
- *
4
- * Provides Hot Module Replacement support for Svelte 5 components.
5
- * Integrates with @sveltejs/vite-plugin-svelte for HMR updates.
6
- *
7
- * IMPORTANT: Svelte 5 HMR Behavior
8
- * - HMR is controlled via compilerOptions.hmr in the Vite plugin config
9
- * - Local state is NOT preserved during HMR (by design in Svelte 5)
10
- * - CSS-only changes DO preserve state (100% preserved)
11
- * - Store subscriptions are maintained across updates
12
- * - The component is remounted with fresh state on JS changes
13
- *
14
- * Requirements: 2.4
15
- */
16
- /// <reference lib="dom" />
17
- import { BaseFrameworkAdapter } from "../framework-adapter.js";
18
- /**
19
- * Svelte HMR Adapter
20
- *
21
- * Handles HMR for Svelte 5 components in the Avalon islands architecture.
22
- *
23
- * Svelte 5 HMR Behavior:
24
- * - HMR is controlled via compilerOptions.hmr in the Vite plugin config
25
- * - Local state is NOT preserved during HMR (by design in Svelte 5)
26
- * - CSS-only changes DO preserve state (100% preserved)
27
- * - Store subscriptions are maintained across updates
28
- * - The component is remounted with fresh state on JS changes
29
- *
30
- * How it works:
31
- * 1. When a component module is updated, Vite sends an HMR event
32
- * 2. Svelte's compiler-integrated HMR handles the update
33
- * 3. We clean up the old instance and mount the new component
34
- * 4. DOM state (scroll, focus, form values) is preserved where possible
35
- * 5. The component re-renders with fresh state
36
- */
37
- export class SvelteHMRAdapter extends BaseFrameworkAdapter {
38
- name = "svelte";
39
- /**
40
- * Store Svelte component instances for each island to enable proper cleanup
41
- */
42
- instances = new WeakMap();
43
- /**
44
- * Store component IDs for tracking
45
- */
46
- componentIds = new WeakMap();
47
- /**
48
- * Store active store subscriptions for cleanup
49
- */
50
- storeSubscriptions = new WeakMap();
51
- /**
52
- * Check if a function/class has Svelte component markers
53
- */
54
- isSvelteFunction(component) {
55
- const comp = component;
56
- if (comp.$$render) {
57
- return true;
58
- }
59
- const proto = component.prototype;
60
- if (proto && (proto.$set && proto.$destroy || proto.$$)) {
61
- return true;
62
- }
63
- try {
64
- const funcStr = component.toString();
65
- if (funcStr.includes("$set") || funcStr.includes("$destroy") || funcStr.includes("$$")) {
66
- return true;
67
- }
68
- } catch {}
69
- return false;
70
- }
71
- /**
72
- * Check if a component is a Svelte component
73
- *
74
- * Svelte components are compiled to classes with specific markers:
75
- * - Constructor function
76
- * - $$render method (SSR marker)
77
- * - Prototype with $set, $destroy methods
78
- */
79
- canHandle(component) {
80
- if (!component) return false;
81
- if (typeof component === "function") {
82
- return this.isSvelteFunction(component);
83
- }
84
- if (typeof component !== "object") {
85
- return false;
86
- }
87
- const obj = component;
88
- if (obj.default && typeof obj.default === "function") {
89
- return this.canHandle(obj.default);
90
- }
91
- return obj.$$render !== undefined;
92
- }
93
- /**
94
- * Preserve Svelte component state before HMR update
95
- *
96
- * Note: In Svelte 5, local state is NOT preserved during HMR (by design).
97
- * We capture DOM state (scroll, focus, form values) which CAN be restored.
98
- */
99
- preserveState(island) {
100
- try {
101
- // Get base DOM state
102
- const baseSnapshot = super.preserveState(island);
103
- if (!baseSnapshot) return null;
104
- // Get Svelte-specific data
105
- const propsAttr = island.dataset.props;
106
- const capturedProps = propsAttr ? JSON.parse(propsAttr) : {};
107
- // Try to get component name from the island
108
- const src = island.dataset.src || "";
109
- const componentName = this.extractComponentName(src);
110
- // Note: In Svelte 5, local state is not preserved during HMR
111
- // We still capture it for debugging purposes, but it won't be restored
112
- const localState = this.captureLocalState(island);
113
- // Store values are maintained by Svelte's reactivity system
114
- const storeValues = this.captureStoreValues(island);
115
- const svelteSnapshot = {
116
- ...baseSnapshot,
117
- framework: "svelte",
118
- data: {
119
- componentName,
120
- capturedProps,
121
- localState,
122
- storeValues
123
- }
124
- };
125
- return svelteSnapshot;
126
- } catch (error) {
127
- console.warn("Failed to preserve Svelte state:", error);
128
- return null;
129
- }
130
- }
131
- /**
132
- * Extract the Svelte component class from a module or function
133
- */
134
- extractComponent(newComponent) {
135
- if (typeof newComponent === "object" && newComponent !== null) {
136
- const obj = newComponent;
137
- if (obj.default && typeof obj.default === "function") {
138
- return obj.default;
139
- }
140
- throw new Error("Svelte component object must have a default export");
141
- }
142
- if (typeof newComponent === "function") {
143
- return newComponent;
144
- }
145
- throw new TypeError("Invalid Svelte component type");
146
- }
147
- /**
148
- * Clean up an existing Svelte component instance
149
- */
150
- async cleanupInstance(island, instance) {
151
- try {
152
- const subscriptions = this.storeSubscriptions.get(island);
153
- if (subscriptions) {
154
- subscriptions.forEach((unsubscribe) => unsubscribe());
155
- this.storeSubscriptions.delete(island);
156
- }
157
- const svelteModule = await import("svelte");
158
- const svelteUnmount = svelteModule.unmount;
159
- if (svelteUnmount) {
160
- svelteUnmount(instance);
161
- } else if (instance.$destroy) {
162
- instance.$destroy();
163
- }
164
- } catch {
165
- if (instance.$destroy) {
166
- instance.$destroy();
167
- }
168
- }
169
- }
170
- /**
171
- * Mount a Svelte component, trying Svelte 5 API first then falling back to constructor
172
- */
173
- async mountComponent(Component, island, props) {
174
- try {
175
- const svelteModule = await import("svelte");
176
- const svelteMount = svelteModule.mount;
177
- if (svelteMount) {
178
- return svelteMount(Component, {
179
- target: island,
180
- props
181
- });
182
- }
183
- return new Component({
184
- target: island,
185
- props,
186
- hydrate: false,
187
- intro: false
188
- });
189
- } catch (svelte5Error) {
190
- console.debug("Svelte 5 API not available, using constructor API:", svelte5Error);
191
- return new Component({
192
- target: island,
193
- props,
194
- hydrate: false,
195
- intro: false
196
- });
197
- }
198
- }
199
- /**
200
- * Update Svelte component with HMR
201
- *
202
- * Svelte 5 HMR Behavior:
203
- * - HMR is handled by the Svelte compiler via compilerOptions.hmr
204
- * - Local state is NOT preserved (by design)
205
- * - CSS-only changes preserve state 100%
206
- * - We clean up the old instance and mount the new component
207
- */
208
- async update(island, newComponent, props) {
209
- if (!this.canHandle(newComponent)) {
210
- throw new Error("Component is not a valid Svelte component");
211
- }
212
- const Component = this.extractComponent(newComponent);
213
- try {
214
- const existingInstance = this.instances.get(island);
215
- if (existingInstance) {
216
- await this.cleanupInstance(island, existingInstance).catch((error) => {
217
- console.warn("Failed to destroy existing Svelte instance:", error);
218
- });
219
- }
220
- island.innerHTML = "";
221
- const instance = await this.mountComponent(Component, island, props);
222
- this.instances.set(island, instance);
223
- const src = island.dataset.src || "";
224
- this.componentIds.set(island, this.generateComponentId(src));
225
- island.dataset.hydrated = "true";
226
- island.dataset.hydrationStatus = "success";
227
- } catch (error) {
228
- console.error("Svelte HMR update failed:", error);
229
- island.dataset.hydrationStatus = "error";
230
- throw error;
231
- }
232
- }
233
- /**
234
- * Restore Svelte component state after HMR update
235
- *
236
- * Note: In Svelte 5, local state is NOT preserved during HMR (by design).
237
- * We only restore DOM state (scroll, focus, form values).
238
- */
239
- restoreState(island, state) {
240
- try {
241
- // Restore DOM state (scroll, focus, form values)
242
- super.restoreState(island, state);
243
- } catch (error) {
244
- console.warn("Failed to restore Svelte state:", error);
245
- }
246
- }
247
- /**
248
- * Handle errors during Svelte HMR update
249
- *
250
- * Provides Svelte-specific error handling with helpful messages
251
- */
252
- handleError(island, error) {
253
- console.error("Svelte HMR error:", error);
254
- // Use base error handling
255
- super.handleError(island, error);
256
- // Add Svelte-specific error information
257
- const errorIndicator = island.querySelector(".hmr-error-indicator");
258
- if (errorIndicator) {
259
- const errorMessage = error.message;
260
- // Provide helpful hints for common Svelte errors
261
- let hint = "";
262
- if (errorMessage.includes("$:") || errorMessage.includes("reactive")) {
263
- hint = " (Hint: Check reactive statements ($:) - they must be at component top level)";
264
- } else if (errorMessage.includes("store")) {
265
- hint = " (Hint: Check store usage - stores must be imported and subscribed correctly)";
266
- } else if (errorMessage.includes("hydration") || errorMessage.includes("hydrate")) {
267
- hint = " (Hint: Server and client render must match)";
268
- } else if (errorMessage.includes("target")) {
269
- hint = " (Hint: Check component target - it must be a valid DOM element)";
270
- } else if (errorMessage.includes("props")) {
271
- hint = " (Hint: Check component props - they must match the component definition)";
272
- }
273
- errorIndicator.textContent = `Svelte HMR Error: ${errorMessage}${hint}`;
274
- }
275
- }
276
- /**
277
- * Extract component name from source path
278
- * Used for debugging and error messages
279
- */
280
- extractComponentName(src) {
281
- const parts = src.split("/");
282
- const filename = parts.at(-1) ?? "";
283
- return filename.replace(/\.svelte$/, "");
284
- }
285
- /**
286
- * Detect if an island has existing SSR content vs being an empty container
287
- *
288
- * @param island - Island element to check
289
- * @returns True if island has SSR content
290
- */
291
- detectSSRContent(island) {
292
- // Check if element has any meaningful content
293
- const hasTextContent = island.textContent && island.textContent.trim().length > 0;
294
- const hasChildElements = island.children && island.children.length > 0;
295
- const hasAttributes = island.dataset.ssrContent !== undefined || island.dataset.svelteRendered !== undefined;
296
- // Consider it SSR content if it has text, child elements, or explicit markers
297
- return hasTextContent || hasChildElements || hasAttributes;
298
- }
299
- /**
300
- * Generate a unique component ID for HMR runtime
301
- */
302
- generateComponentId(src) {
303
- // Use the source path as the component ID
304
- // This ensures consistency across HMR updates
305
- return src.replaceAll(/[^a-zA-Z0-9]/g, "_");
306
- }
307
- /**
308
- * Attempt to capture local state from Svelte instance
309
- * This is best-effort and may not work in all cases
310
- */
311
- captureLocalState(island) {
312
- try {
313
- const instance = this.instances.get(island);
314
- if (!instance) return undefined;
315
- // Try to access Svelte's internal state
316
- // This is internal API and may change, so we wrap in try-catch
317
- const internalState = instance.$$;
318
- if (internalState?.ctx) {
319
- // ctx is an array of component state values
320
- // We can't easily map these back to variable names,
321
- // so we just store the raw values
322
- return {
323
- ctx: internalState.ctx,
324
- props: internalState.props,
325
- bound: internalState.bound
326
- };
327
- }
328
- return undefined;
329
- } catch (error) {
330
- // Silently fail - this is best-effort
331
- console.debug("Could not capture Svelte local state:", error);
332
- return undefined;
333
- }
334
- }
335
- /**
336
- * Attempt to capture store values
337
- * This is best-effort and may not work in all cases
338
- */
339
- captureStoreValues(_island) {
340
- // Svelte stores are typically imported at module level,
341
- // so we can't easily access them from the component instance
342
- // The HMR system should handle store subscriptions automatically
343
- // We could potentially track stores if we intercept store.subscribe calls,
344
- // but that would require modifying the Svelte runtime, which is not feasible
345
- // For now, we rely on Svelte's HMR to preserve store subscriptions
346
- return undefined;
347
- }
348
- /**
349
- * Clean up Svelte component when island is removed
350
- * This should be called when an island is unmounted
351
- */
352
- async unmount(_island) {
353
- const instance = this.instances.get(_island);
354
- if (instance) {
355
- try {
356
- await this.cleanupInstance(_island, instance);
357
- this.instances.delete(_island);
358
- this.componentIds.delete(_island);
359
- } catch (error) {
360
- console.warn("Failed to unmount Svelte component:", error);
361
- }
362
- }
363
- }
364
- }
365
- /**
366
- * Create and export a singleton instance of the Svelte HMR adapter
367
- */
368
- export const svelteAdapter = new SvelteHMRAdapter();