@useavalon/avalon 0.1.13 → 0.1.15

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 (230) hide show
  1. package/dist/mod.js +1 -0
  2. package/dist/src/build/integration-bundler-plugin.js +1 -0
  3. package/dist/src/build/integration-config.js +1 -0
  4. package/dist/src/build/integration-detection-plugin.js +1 -0
  5. package/dist/src/build/integration-resolver-plugin.js +1 -0
  6. package/dist/src/build/island-manifest.js +1 -0
  7. package/dist/src/build/island-types-generator.js +5 -0
  8. package/dist/src/build/mdx-island-transform.js +2 -0
  9. package/dist/src/build/mdx-plugin.js +1 -0
  10. package/dist/src/build/page-island-transform.js +3 -0
  11. package/dist/src/build/prop-extractors/index.js +1 -0
  12. package/dist/src/build/prop-extractors/lit.js +1 -0
  13. package/dist/src/build/prop-extractors/qwik.js +1 -0
  14. package/dist/src/build/prop-extractors/solid.js +1 -0
  15. package/dist/src/build/prop-extractors/svelte.js +1 -0
  16. package/dist/src/build/prop-extractors/vue.js +1 -0
  17. package/dist/src/build/sidecar-file-manager.js +1 -0
  18. package/dist/src/build/sidecar-renderer.js +6 -0
  19. package/dist/src/client/adapters/index.js +1 -0
  20. package/dist/src/client/components.js +1 -0
  21. package/dist/src/client/css-hmr-handler.js +1 -0
  22. package/dist/src/client/framework-adapter.js +13 -0
  23. package/dist/src/client/hmr-coordinator.js +1 -0
  24. package/dist/src/client/hmr-error-overlay.js +214 -0
  25. package/dist/src/client/main.js +39 -0
  26. package/dist/src/components/Image.js +1 -0
  27. package/dist/src/components/IslandErrorBoundary.js +1 -0
  28. package/dist/src/components/LayoutDataErrorBoundary.js +1 -0
  29. package/dist/src/components/LayoutErrorBoundary.js +1 -0
  30. package/dist/src/components/PersistentIsland.js +1 -0
  31. package/dist/src/components/StreamingErrorBoundary.js +1 -0
  32. package/dist/src/components/StreamingLayout.js +29 -0
  33. package/dist/src/core/components/component-analyzer.js +1 -0
  34. package/dist/src/core/components/component-detection.js +5 -0
  35. package/dist/src/core/components/enhanced-framework-detector.js +1 -0
  36. package/dist/src/core/components/framework-registry.js +1 -0
  37. package/dist/src/core/content/mdx-processor.js +1 -0
  38. package/dist/src/core/integrations/index.js +1 -0
  39. package/dist/src/core/integrations/loader.js +1 -0
  40. package/dist/src/core/integrations/registry.js +1 -0
  41. package/dist/src/core/islands/island-persistence.js +1 -0
  42. package/dist/src/core/islands/island-state-serializer.js +1 -0
  43. package/dist/src/core/islands/persistent-island-context.js +1 -0
  44. package/dist/src/core/islands/use-persistent-state.js +1 -0
  45. package/dist/src/core/layout/enhanced-layout-resolver.js +1 -0
  46. package/dist/src/core/layout/layout-cache-manager.js +1 -0
  47. package/dist/src/core/layout/layout-composer.js +1 -0
  48. package/dist/src/core/layout/layout-data-loader.js +1 -0
  49. package/dist/src/core/layout/layout-discovery.js +1 -0
  50. package/dist/src/core/layout/layout-matcher.js +1 -0
  51. package/dist/src/core/layout/layout-types.js +1 -0
  52. package/dist/src/core/modules/framework-module-resolver.js +1 -0
  53. package/dist/src/islands/component-analysis.js +1 -0
  54. package/dist/src/islands/css-utils.js +17 -0
  55. package/dist/src/islands/discovery/index.js +1 -0
  56. package/dist/src/islands/discovery/registry.js +1 -0
  57. package/dist/src/islands/discovery/resolver.js +2 -0
  58. package/dist/src/islands/discovery/scanner.js +1 -0
  59. package/dist/src/islands/discovery/types.js +1 -0
  60. package/dist/src/islands/discovery/validator.js +18 -0
  61. package/dist/src/islands/discovery/watcher.js +1 -0
  62. package/dist/src/islands/framework-detection.js +1 -0
  63. package/dist/src/islands/integration-loader.js +1 -0
  64. package/dist/src/islands/island.js +1 -0
  65. package/dist/src/islands/render-cache.js +1 -0
  66. package/dist/src/islands/types.js +1 -0
  67. package/dist/src/islands/universal-css-collector.js +5 -0
  68. package/dist/src/islands/universal-head-collector.js +2 -0
  69. package/dist/src/layout-system.js +1 -0
  70. package/dist/src/middleware/discovery.js +1 -0
  71. package/dist/src/middleware/executor.js +1 -0
  72. package/dist/src/middleware/index.js +1 -0
  73. package/dist/src/middleware/types.js +1 -0
  74. package/dist/src/nitro/build-config.js +1 -0
  75. package/dist/src/nitro/config.js +1 -0
  76. package/dist/src/nitro/error-handler.js +198 -0
  77. package/dist/src/nitro/index.js +1 -0
  78. package/dist/src/nitro/island-manifest.js +2 -0
  79. package/dist/src/nitro/middleware-adapter.js +1 -0
  80. package/dist/src/nitro/renderer.js +183 -0
  81. package/dist/src/nitro/route-discovery.js +1 -0
  82. package/dist/src/nitro/types.js +1 -0
  83. package/dist/src/render/collect-css.js +3 -0
  84. package/dist/src/render/error-pages.js +48 -0
  85. package/dist/src/render/isolated-ssr-renderer.js +1 -0
  86. package/dist/src/render/ssr.js +90 -0
  87. package/dist/src/schemas/api.js +1 -0
  88. package/dist/src/schemas/core.js +1 -0
  89. package/dist/src/schemas/index.js +1 -0
  90. package/dist/src/schemas/layout.js +1 -0
  91. package/dist/src/schemas/routing/index.js +1 -0
  92. package/dist/src/schemas/routing.js +1 -0
  93. package/dist/src/types/as-island.js +1 -0
  94. package/dist/src/types/layout.js +1 -0
  95. package/dist/src/types/routing.js +1 -0
  96. package/dist/src/types/types.js +1 -0
  97. package/dist/src/utils/dev-logger.js +12 -0
  98. package/dist/src/utils/fs.js +1 -0
  99. package/dist/src/vite-plugin/auto-discover.js +1 -0
  100. package/dist/src/vite-plugin/config.js +1 -0
  101. package/dist/src/vite-plugin/errors.js +1 -0
  102. package/dist/src/vite-plugin/image-optimization.js +45 -0
  103. package/dist/src/vite-plugin/integration-activator.js +1 -0
  104. package/dist/src/vite-plugin/island-sidecar-plugin.js +1 -0
  105. package/dist/src/vite-plugin/module-discovery.js +1 -0
  106. package/dist/src/vite-plugin/nitro-integration.js +42 -0
  107. package/dist/src/vite-plugin/plugin.js +1 -0
  108. package/dist/src/vite-plugin/types.js +1 -0
  109. package/dist/src/vite-plugin/validation.js +2 -0
  110. package/package.json +14 -20
  111. package/mod.ts +0 -302
  112. package/src/build/integration-bundler-plugin.ts +0 -116
  113. package/src/build/integration-config.ts +0 -168
  114. package/src/build/integration-detection-plugin.ts +0 -117
  115. package/src/build/integration-resolver-plugin.ts +0 -90
  116. package/src/build/island-manifest.ts +0 -269
  117. package/src/build/island-types-generator.ts +0 -476
  118. package/src/build/mdx-island-transform.ts +0 -464
  119. package/src/build/mdx-plugin.ts +0 -98
  120. package/src/build/page-island-transform.ts +0 -598
  121. package/src/build/prop-extractors/index.ts +0 -21
  122. package/src/build/prop-extractors/lit.ts +0 -140
  123. package/src/build/prop-extractors/qwik.ts +0 -16
  124. package/src/build/prop-extractors/solid.ts +0 -125
  125. package/src/build/prop-extractors/svelte.ts +0 -194
  126. package/src/build/prop-extractors/vue.ts +0 -111
  127. package/src/build/sidecar-file-manager.ts +0 -104
  128. package/src/build/sidecar-renderer.ts +0 -30
  129. package/src/client/adapters/index.ts +0 -21
  130. package/src/client/components.ts +0 -35
  131. package/src/client/css-hmr-handler.ts +0 -344
  132. package/src/client/framework-adapter.ts +0 -462
  133. package/src/client/hmr-coordinator.ts +0 -396
  134. package/src/client/hmr-error-overlay.js +0 -533
  135. package/src/client/main.js +0 -824
  136. package/src/components/Image.tsx +0 -123
  137. package/src/components/IslandErrorBoundary.tsx +0 -145
  138. package/src/components/LayoutDataErrorBoundary.tsx +0 -141
  139. package/src/components/LayoutErrorBoundary.tsx +0 -127
  140. package/src/components/PersistentIsland.tsx +0 -52
  141. package/src/components/StreamingErrorBoundary.tsx +0 -233
  142. package/src/components/StreamingLayout.tsx +0 -538
  143. package/src/core/components/component-analyzer.ts +0 -192
  144. package/src/core/components/component-detection.ts +0 -508
  145. package/src/core/components/enhanced-framework-detector.ts +0 -500
  146. package/src/core/components/framework-registry.ts +0 -563
  147. package/src/core/content/mdx-processor.ts +0 -46
  148. package/src/core/integrations/index.ts +0 -19
  149. package/src/core/integrations/loader.ts +0 -125
  150. package/src/core/integrations/registry.ts +0 -175
  151. package/src/core/islands/island-persistence.ts +0 -325
  152. package/src/core/islands/island-state-serializer.ts +0 -258
  153. package/src/core/islands/persistent-island-context.tsx +0 -80
  154. package/src/core/islands/use-persistent-state.ts +0 -68
  155. package/src/core/layout/enhanced-layout-resolver.ts +0 -322
  156. package/src/core/layout/layout-cache-manager.ts +0 -485
  157. package/src/core/layout/layout-composer.ts +0 -357
  158. package/src/core/layout/layout-data-loader.ts +0 -516
  159. package/src/core/layout/layout-discovery.ts +0 -243
  160. package/src/core/layout/layout-matcher.ts +0 -299
  161. package/src/core/layout/layout-types.ts +0 -110
  162. package/src/core/modules/framework-module-resolver.ts +0 -273
  163. package/src/islands/component-analysis.ts +0 -213
  164. package/src/islands/css-utils.ts +0 -565
  165. package/src/islands/discovery/index.ts +0 -80
  166. package/src/islands/discovery/registry.ts +0 -340
  167. package/src/islands/discovery/resolver.ts +0 -477
  168. package/src/islands/discovery/scanner.ts +0 -386
  169. package/src/islands/discovery/types.ts +0 -117
  170. package/src/islands/discovery/validator.ts +0 -544
  171. package/src/islands/discovery/watcher.ts +0 -368
  172. package/src/islands/framework-detection.ts +0 -428
  173. package/src/islands/integration-loader.ts +0 -490
  174. package/src/islands/island.tsx +0 -565
  175. package/src/islands/render-cache.ts +0 -550
  176. package/src/islands/types.ts +0 -80
  177. package/src/islands/universal-css-collector.ts +0 -157
  178. package/src/islands/universal-head-collector.ts +0 -137
  179. package/src/layout-system.ts +0 -218
  180. package/src/middleware/discovery.ts +0 -268
  181. package/src/middleware/executor.ts +0 -315
  182. package/src/middleware/index.ts +0 -76
  183. package/src/middleware/types.ts +0 -99
  184. package/src/nitro/build-config.ts +0 -576
  185. package/src/nitro/config.ts +0 -483
  186. package/src/nitro/error-handler.ts +0 -636
  187. package/src/nitro/index.ts +0 -173
  188. package/src/nitro/island-manifest.ts +0 -584
  189. package/src/nitro/middleware-adapter.ts +0 -260
  190. package/src/nitro/renderer.ts +0 -1471
  191. package/src/nitro/route-discovery.ts +0 -439
  192. package/src/nitro/types.ts +0 -321
  193. package/src/render/collect-css.ts +0 -198
  194. package/src/render/error-pages.ts +0 -79
  195. package/src/render/isolated-ssr-renderer.ts +0 -654
  196. package/src/render/ssr.ts +0 -1030
  197. package/src/schemas/api.ts +0 -30
  198. package/src/schemas/core.ts +0 -64
  199. package/src/schemas/index.ts +0 -212
  200. package/src/schemas/layout.ts +0 -279
  201. package/src/schemas/routing/index.ts +0 -38
  202. package/src/schemas/routing.ts +0 -376
  203. package/src/types/as-island.ts +0 -20
  204. package/src/types/layout.ts +0 -285
  205. package/src/types/routing.ts +0 -555
  206. package/src/types/types.ts +0 -5
  207. package/src/utils/dev-logger.ts +0 -299
  208. package/src/utils/fs.ts +0 -151
  209. package/src/vite-plugin/auto-discover.ts +0 -551
  210. package/src/vite-plugin/config.ts +0 -266
  211. package/src/vite-plugin/errors.ts +0 -127
  212. package/src/vite-plugin/image-optimization.ts +0 -156
  213. package/src/vite-plugin/integration-activator.ts +0 -126
  214. package/src/vite-plugin/island-sidecar-plugin.ts +0 -176
  215. package/src/vite-plugin/module-discovery.ts +0 -189
  216. package/src/vite-plugin/nitro-integration.ts +0 -1354
  217. package/src/vite-plugin/plugin.ts +0 -403
  218. package/src/vite-plugin/types.ts +0 -327
  219. package/src/vite-plugin/validation.ts +0 -228
  220. /package/{src → dist/src}/client/types/framework-runtime.d.ts +0 -0
  221. /package/{src → dist/src}/client/types/vite-hmr.d.ts +0 -0
  222. /package/{src → dist/src}/client/types/vite-virtual-modules.d.ts +0 -0
  223. /package/{src → dist/src}/layout-system.d.ts +0 -0
  224. /package/{src → dist/src}/types/image.d.ts +0 -0
  225. /package/{src → dist/src}/types/index.d.ts +0 -0
  226. /package/{src → dist/src}/types/island-jsx.d.ts +0 -0
  227. /package/{src → dist/src}/types/island-prop.d.ts +0 -0
  228. /package/{src → dist/src}/types/mdx.d.ts +0 -0
  229. /package/{src → dist/src}/types/urlpattern.d.ts +0 -0
  230. /package/{src → dist/src}/types/vite-env.d.ts +0 -0
@@ -1,490 +0,0 @@
1
- import { registry } from "../core/integrations/registry.ts";
2
- import type { Integration } from "@useavalon/core";
3
- import { devWarn } from "../utils/dev-logger.ts";
4
-
5
- /**
6
- * Cache for loaded integrations to avoid repeated lookups
7
- */
8
- const frameworkCache = new Map<string, Integration>();
9
-
10
- // Pattern to match nested island paths like /modules/*/islands/ or /src/*/islands/
11
- const NESTED_ISLANDS_PATTERN = /\/(?:src\/)?(?:modules\/)?([^/]+\/)*islands\//;
12
-
13
- /**
14
- * Load an integration by framework name
15
- * Uses cache to avoid repeated dynamic imports
16
- *
17
- * This function supports on-demand loading: if an integration hasn't been
18
- * preloaded, it will be loaded and cached on first use. This enables
19
- * lazy loading at server startup while ensuring fast subsequent renders.
20
- */
21
- export async function loadIntegration(framework: string) {
22
- // Check local cache first (fastest path)
23
- if (frameworkCache.has(framework)) {
24
- return frameworkCache.get(framework)!;
25
- }
26
-
27
- // Check if already loaded in registry (e.g., by native preloader)
28
- if (registry.has(framework)) {
29
- const integration = registry.get(framework)!;
30
- frameworkCache.set(framework, integration);
31
- return integration;
32
- }
33
-
34
- // On-demand loading: load the integration now and cache it
35
- try {
36
- const integration = await registry.load(framework);
37
- frameworkCache.set(framework, integration);
38
- return integration;
39
- } catch (error) {
40
- throw new Error(
41
- `Integration '${framework}' could not be loaded. Make sure @useavalon/${framework} is installed.`,
42
- { cause: error }
43
- );
44
- }
45
- }
46
-
47
- /**
48
- * Detect framework from file path and load the appropriate integration
49
- */
50
- export async function detectAndLoadIntegration(src: string) {
51
- const framework = detectFrameworkFromPath(src);
52
- return await loadIntegration(framework);
53
- }
54
-
55
- /**
56
- * Detect framework from file path based on extension and naming conventions.
57
- *
58
- * Updated to support nested island paths like:
59
- * - /src/islands/Counter.tsx
60
- * - /src/modules/auth/islands/Counter.tsx
61
- * - /modules/dashboard/islands/Chart.vue
62
- *
63
- * @param src - The source path to detect framework from
64
- * @returns The detected framework name
65
- */
66
- export function detectFrameworkFromPath(src: string) {
67
- // Normalize path separators
68
- const normalizedSrc = src.replaceAll('\\', "/");
69
-
70
- // Vue files (.vue)
71
- if (normalizedSrc.endsWith(".vue")) {
72
- return "vue";
73
- }
74
-
75
- // Svelte files (.svelte)
76
- if (normalizedSrc.endsWith(".svelte")) {
77
- return "svelte";
78
- }
79
-
80
- // Solid files (convention: .solid.tsx or .solid.jsx)
81
- if (normalizedSrc.includes(".solid.")) {
82
- return "solid";
83
- }
84
-
85
- // Qwik files (convention: .qwik.tsx or .qwik.jsx)
86
- if (normalizedSrc.includes(".qwik.")) {
87
- return "qwik";
88
- }
89
-
90
- // React files (convention: .react.tsx or .react.jsx)
91
- if (normalizedSrc.includes(".react.")) {
92
- return "react";
93
- }
94
-
95
- // Lit files (convention: .lit.ts or .lit.js, or files starting with "Lit")
96
- if (normalizedSrc.includes(".lit.")) {
97
- return "lit";
98
- }
99
-
100
- // Lit files by naming convention (LitComponent.ts)
101
- const fileName = normalizedSrc.split("/").pop() || "";
102
- if (fileName.startsWith("Lit") && (normalizedSrc.endsWith(".ts") || normalizedSrc.endsWith(".js"))) {
103
- return "lit";
104
- }
105
-
106
- // Check if path is in any islands directory (including nested)
107
- // Plain .ts/.js files in islands are likely Lit components (Lit doesn't use JSX)
108
- if (isInIslandsDirectory(normalizedSrc) && (normalizedSrc.endsWith(".ts") || normalizedSrc.endsWith(".js"))) {
109
- return "lit";
110
- }
111
-
112
- // Default to Preact for .tsx and .jsx files
113
- if (normalizedSrc.endsWith(".tsx") || normalizedSrc.endsWith(".jsx")) {
114
- return "preact";
115
- }
116
-
117
- // Fallback to Preact
118
- return "preact";
119
- }
120
-
121
- /**
122
- * Check if a path is within any islands directory (including nested).
123
- *
124
- * Matches patterns like:
125
- * - /islands/
126
- * - /src/islands/
127
- * - /src/modules/auth/islands/
128
- * - /modules/dashboard/islands/
129
- * - /src/features/user/islands/
130
- *
131
- * @param path - The path to check
132
- * @returns True if the path is in an islands directory
133
- */
134
- export function isInIslandsDirectory(path: string): boolean {
135
- const normalized = path.replaceAll('\\', "/");
136
-
137
- // Check for /islands/ anywhere in the path
138
- return normalized.includes("/islands/");
139
- }
140
-
141
- /**
142
- * Check if a path is a nested island path (not in default /src/islands/).
143
- *
144
- * @param path - The path to check
145
- * @returns True if the path is a nested island path
146
- */
147
- export function isNestedIslandPath(path: string): boolean {
148
- const normalized = path.replaceAll('\\', "/");
149
-
150
- // Check if it contains /islands/ but not at the root level
151
- if (!normalized.includes("/islands/")) {
152
- return false;
153
- }
154
-
155
- // Default path patterns
156
- const defaultPatterns = [
157
- /^\/islands\//,
158
- /^\/src\/islands\//,
159
- /^src\/islands\//,
160
- /^islands\//,
161
- ];
162
-
163
- for (const pattern of defaultPatterns) {
164
- if (pattern.test(normalized)) {
165
- return false;
166
- }
167
- }
168
-
169
- // If it contains /islands/ but doesn't match default patterns, it's nested
170
- return true;
171
- }
172
-
173
- /**
174
- * Extract the namespace from a nested island path.
175
- *
176
- * Examples:
177
- * - /src/modules/auth/islands/Counter.tsx -> "modules/auth"
178
- * - /src/features/user/islands/Profile.tsx -> "features/user"
179
- * - /src/islands/Button.tsx -> ""
180
- *
181
- * @param path - The path to extract namespace from
182
- * @returns The namespace or empty string for default islands
183
- */
184
- export function extractNamespaceFromPath(path: string): string {
185
- const normalized = path.replaceAll('\\', "/");
186
-
187
- // Match patterns like /src/modules/auth/islands/ or /modules/auth/islands/
188
- const match = new RegExp(/(?:\/src)?\/(.+?)\/islands\//).exec(normalized);
189
- if (match) {
190
- return match[1];
191
- }
192
-
193
- return "";
194
- }
195
-
196
- /**
197
- * Detect framework from file content by analyzing imports and patterns.
198
- *
199
- * Updated to support nested island paths.
200
- *
201
- * @param src - The source path
202
- * @param content - The file content to analyze
203
- * @returns The detected framework name
204
- */
205
- export function detectFrameworkFromContent(
206
- src: string,
207
- content: string
208
- ) {
209
- // First try path-based detection
210
- const pathFramework = detectFrameworkFromPath(src);
211
-
212
- // If we have a definitive answer from path (not default), use it
213
- if (pathFramework === "vue" || pathFramework === "svelte" || pathFramework === "react" || pathFramework === "lit") {
214
- return pathFramework;
215
- }
216
-
217
- // For .tsx/.jsx files, analyze content to distinguish between frameworks
218
-
219
- // Check for React imports (must check before Preact since they share hooks)
220
- if (
221
- content.includes("from 'react'") ||
222
- content.includes('from "react"') ||
223
- content.includes("from 'react-dom'") ||
224
- content.includes('from "react-dom"') ||
225
- content.includes('"use client"') ||
226
- content.includes("'use client'") ||
227
- content.includes('"use server"') ||
228
- content.includes("'use server'")
229
- ) {
230
- return "react";
231
- }
232
-
233
- // Check for Lit imports
234
- if (
235
- content.includes("from 'lit'") ||
236
- content.includes('from "lit"') ||
237
- content.includes("@lit-labs/ssr") ||
238
- content.includes("LitElement") ||
239
- content.includes("@customElement")
240
- ) {
241
- return "lit";
242
- }
243
-
244
- // Check for Solid imports
245
- if (
246
- content.includes("solid-js") ||
247
- content.includes("from 'solid-js'") ||
248
- content.includes('from "solid-js"')
249
- ) {
250
- return "solid";
251
- }
252
-
253
- // Check for Preact imports
254
- if (
255
- content.includes("from 'preact'") ||
256
- content.includes('from "preact"') ||
257
- content.includes("preact/hooks")
258
- ) {
259
- return "preact";
260
- }
261
-
262
- // Check for Lit-specific patterns
263
- if (
264
- content.includes("extends LitElement") ||
265
- content.includes("@property") ||
266
- content.includes("@state") ||
267
- content.includes("html`") ||
268
- content.includes("css`")
269
- ) {
270
- return "lit";
271
- }
272
-
273
- // Check for Solid-specific patterns
274
- if (
275
- content.includes("createSignal") ||
276
- content.includes("createEffect") ||
277
- content.includes("createMemo")
278
- ) {
279
- return "solid";
280
- }
281
-
282
- // Check for React/Preact-specific patterns (hooks)
283
- // Note: React and Preact share the same hooks API, so we default to Preact
284
- // unless React imports are explicitly detected above
285
- if (
286
- content.includes("useState") ||
287
- content.includes("useEffect") ||
288
- content.includes("useRef")
289
- ) {
290
- return "preact";
291
- }
292
-
293
- // Default to path-based detection
294
- return pathFramework;
295
- }
296
-
297
- /**
298
- * Get integration for a specific framework, with error handling
299
- */
300
- export async function getIntegration(framework: string) {
301
- try {
302
- return await loadIntegration(framework);
303
- } catch (error) {
304
- console.error(`Failed to load integration for ${framework}:`, error);
305
- return null;
306
- }
307
- }
308
-
309
- /**
310
- * Check if an integration is available for a framework
311
- */
312
- export async function hasIntegration(framework: string) {
313
- try {
314
- await loadIntegration(framework);
315
- return true;
316
- } catch {
317
- return false;
318
- }
319
- }
320
-
321
- /**
322
- * Get all loaded integrations from cache
323
- */
324
- export function getLoadedIntegrations() {
325
- return Array.from(frameworkCache.values());
326
- }
327
-
328
- /**
329
- * Get all loaded framework names from cache
330
- */
331
- export function getLoadedFrameworks() {
332
- return Array.from(frameworkCache.keys());
333
- }
334
-
335
- /**
336
- * Clear the integration cache
337
- * Useful for testing or hot module replacement
338
- */
339
- export function clearIntegrationCache() {
340
- frameworkCache.clear();
341
- }
342
-
343
- /**
344
- * Check if an integration is loaded in cache
345
- */
346
- export function isIntegrationLoaded(framework: string) {
347
- return frameworkCache.has(framework);
348
- }
349
-
350
- /**
351
- * Default frameworks to preload at server startup
352
- * These are the most commonly used frameworks in island architecture
353
- */
354
- export const DEFAULT_PRELOAD_FRAMEWORKS = ['preact', 'react', 'vue', 'svelte', 'solid', 'lit'] as const;
355
-
356
- /**
357
- * Options for preloading integrations
358
- */
359
- export interface PreloadIntegrationsOptions {
360
- /**
361
- * When true, only preload integrations that are actually used on the page.
362
- * This is determined by analyzing page components for framework usage.
363
- * When false (default), preload all specified frameworks.
364
- */
365
- lazy?: boolean;
366
-
367
- /**
368
- * Array of framework names to preload.
369
- * Defaults to DEFAULT_PRELOAD_FRAMEWORKS.
370
- */
371
- frameworks?: readonly string[];
372
-
373
- /**
374
- * Array of detected frameworks from page analysis.
375
- * Only used when lazy=true to filter which frameworks to preload.
376
- */
377
- detectedFrameworks?: string[];
378
- }
379
-
380
- /**
381
- * Preload integrations for multiple frameworks
382
- * Useful for warming up the cache during build or startup
383
- *
384
- * Uses Promise.allSettled to load all integrations concurrently,
385
- * ensuring that one failed integration doesn't block others.
386
- *
387
- * @param options - Preload options
388
- * @returns Promise that resolves when all preloading attempts complete
389
- */
390
- export async function preloadIntegrations(
391
- options?: PreloadIntegrationsOptions
392
- ): Promise<void> {
393
- let frameworks: readonly string[];
394
- let lazy = false;
395
- let detectedFrameworks: string[] | undefined;
396
-
397
- if (options) {
398
- frameworks = options.frameworks ?? DEFAULT_PRELOAD_FRAMEWORKS;
399
- lazy = options.lazy ?? false;
400
- detectedFrameworks = options.detectedFrameworks;
401
- } else {
402
- frameworks = DEFAULT_PRELOAD_FRAMEWORKS;
403
- }
404
-
405
- // When lazy mode is enabled, only preload detected frameworks
406
- if (lazy && detectedFrameworks && detectedFrameworks.length > 0) {
407
- // Filter to only frameworks that are both in the default list and detected
408
- const frameworksToLoad = frameworks.filter(fw =>
409
- detectedFrameworks.includes(fw)
410
- );
411
-
412
- if (frameworksToLoad.length === 0) {
413
- return;
414
- }
415
-
416
- frameworks = frameworksToLoad;
417
- } else if (lazy && (!detectedFrameworks || detectedFrameworks.length === 0)) {
418
- // Lazy mode but no detected frameworks - skip preloading entirely
419
- return;
420
- }
421
-
422
- const results = await Promise.allSettled(
423
- frameworks.map(framework => loadIntegration(framework))
424
- );
425
-
426
- // Track success/failure counts for logging
427
- let successCount = 0;
428
- let failureCount = 0;
429
-
430
- // Log any failures (dev mode only)
431
- results.forEach((result, index) => {
432
- if (result.status === "rejected") {
433
- failureCount++;
434
- devWarn(
435
- `⚠️ Failed to preload integration '${frameworks[index]}':`,
436
- result.reason
437
- );
438
- } else {
439
- successCount++;
440
- }
441
- });
442
- }
443
-
444
- /**
445
- * Detect frameworks used in a page by analyzing component imports.
446
- * This is used for lazy integration loading to only preload what's needed.
447
- *
448
- * @param pageContent - The content of the page file to analyze
449
- * @returns Array of detected framework names
450
- */
451
- export function detectFrameworksFromPageContent(pageContent: string): string[] {
452
- const detectedFrameworks: Set<string> = new Set();
453
-
454
- // Check for island imports and their framework hints
455
- // Look for patterns like: <Island src="/src/islands/Counter.tsx" framework="preact" />
456
- const frameworkPropMatches = pageContent.matchAll(/framework\s*=\s*["'](\w+)["']/g);
457
- for (const match of frameworkPropMatches) {
458
- detectedFrameworks.add(match[1]);
459
- }
460
-
461
- // Check for island source paths to detect framework from file extension
462
- const srcMatches = pageContent.matchAll(/src\s*=\s*["']([^"']+)["']/g);
463
- for (const match of srcMatches) {
464
- const src = match[1];
465
- const framework = detectFrameworkFromPath(src);
466
- detectedFrameworks.add(framework);
467
- }
468
-
469
- // Check for direct framework imports
470
- if (pageContent.includes("from 'react'") || pageContent.includes('from "react"')) {
471
- detectedFrameworks.add('react');
472
- }
473
- if (pageContent.includes("from 'preact'") || pageContent.includes('from "preact"')) {
474
- detectedFrameworks.add('preact');
475
- }
476
- if (pageContent.includes("from 'vue'") || pageContent.includes('from "vue"')) {
477
- detectedFrameworks.add('vue');
478
- }
479
- if (pageContent.includes("from 'svelte'") || pageContent.includes('from "svelte"')) {
480
- detectedFrameworks.add('svelte');
481
- }
482
- if (pageContent.includes("from 'solid-js'") || pageContent.includes('from "solid-js"')) {
483
- detectedFrameworks.add('solid');
484
- }
485
- if (pageContent.includes("from 'lit'") || pageContent.includes('from "lit"')) {
486
- detectedFrameworks.add('lit');
487
- }
488
-
489
- return Array.from(detectedFrameworks);
490
- }