@useavalon/avalon 0.1.10 → 0.1.12

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 (250) hide show
  1. package/README.md +54 -54
  2. package/dist/mod.js +1 -0
  3. package/dist/src/build/integration-bundler-plugin.js +1 -0
  4. package/dist/src/build/integration-config.js +1 -0
  5. package/dist/src/build/integration-detection-plugin.js +1 -0
  6. package/dist/src/build/integration-resolver-plugin.js +1 -0
  7. package/dist/src/build/island-manifest.js +1 -0
  8. package/dist/src/build/island-types-generator.js +5 -0
  9. package/dist/src/build/mdx-island-transform.js +2 -0
  10. package/dist/src/build/mdx-plugin.js +1 -0
  11. package/dist/src/build/page-island-transform.js +3 -0
  12. package/dist/src/build/prop-extractors/index.js +1 -0
  13. package/dist/src/build/prop-extractors/lit.js +1 -0
  14. package/dist/src/build/prop-extractors/qwik.js +1 -0
  15. package/dist/src/build/prop-extractors/solid.js +1 -0
  16. package/dist/src/build/prop-extractors/svelte.js +1 -0
  17. package/dist/src/build/prop-extractors/vue.js +1 -0
  18. package/dist/src/build/sidecar-file-manager.js +1 -0
  19. package/dist/src/build/sidecar-renderer.js +6 -0
  20. package/dist/src/client/adapters/index.js +1 -0
  21. package/dist/src/client/components.js +1 -0
  22. package/dist/src/client/css-hmr-handler.js +1 -0
  23. package/dist/src/client/framework-adapter.js +13 -0
  24. package/dist/src/client/hmr-coordinator.js +1 -0
  25. package/dist/src/client/hmr-error-overlay.js +214 -0
  26. package/dist/src/client/main.js +39 -0
  27. package/{src → dist/src}/client/types/framework-runtime.d.ts +68 -68
  28. package/{src → dist/src}/client/types/vite-hmr.d.ts +46 -46
  29. package/dist/src/client/types/vite-virtual-modules.d.ts +70 -0
  30. package/dist/src/components/Image.js +1 -0
  31. package/dist/src/components/IslandErrorBoundary.js +1 -0
  32. package/dist/src/components/LayoutDataErrorBoundary.js +1 -0
  33. package/dist/src/components/LayoutErrorBoundary.js +1 -0
  34. package/dist/src/components/PersistentIsland.js +1 -0
  35. package/dist/src/components/StreamingErrorBoundary.js +1 -0
  36. package/dist/src/components/StreamingLayout.js +29 -0
  37. package/dist/src/core/components/component-analyzer.js +1 -0
  38. package/dist/src/core/components/component-detection.js +5 -0
  39. package/dist/src/core/components/enhanced-framework-detector.js +1 -0
  40. package/dist/src/core/components/framework-registry.js +1 -0
  41. package/dist/src/core/content/mdx-processor.js +1 -0
  42. package/dist/src/core/integrations/index.js +1 -0
  43. package/dist/src/core/integrations/loader.js +1 -0
  44. package/dist/src/core/integrations/registry.js +1 -0
  45. package/dist/src/core/islands/island-persistence.js +1 -0
  46. package/dist/src/core/islands/island-state-serializer.js +1 -0
  47. package/dist/src/core/islands/persistent-island-context.js +1 -0
  48. package/dist/src/core/islands/use-persistent-state.js +1 -0
  49. package/dist/src/core/layout/enhanced-layout-resolver.js +1 -0
  50. package/dist/src/core/layout/layout-cache-manager.js +1 -0
  51. package/dist/src/core/layout/layout-composer.js +1 -0
  52. package/dist/src/core/layout/layout-data-loader.js +1 -0
  53. package/dist/src/core/layout/layout-discovery.js +1 -0
  54. package/dist/src/core/layout/layout-matcher.js +1 -0
  55. package/dist/src/core/layout/layout-types.js +1 -0
  56. package/dist/src/core/modules/framework-module-resolver.js +1 -0
  57. package/dist/src/islands/component-analysis.js +1 -0
  58. package/dist/src/islands/css-utils.js +17 -0
  59. package/dist/src/islands/discovery/index.js +1 -0
  60. package/dist/src/islands/discovery/registry.js +1 -0
  61. package/dist/src/islands/discovery/resolver.js +2 -0
  62. package/dist/src/islands/discovery/scanner.js +1 -0
  63. package/dist/src/islands/discovery/types.js +1 -0
  64. package/dist/src/islands/discovery/validator.js +18 -0
  65. package/dist/src/islands/discovery/watcher.js +1 -0
  66. package/dist/src/islands/framework-detection.js +1 -0
  67. package/dist/src/islands/integration-loader.js +1 -0
  68. package/dist/src/islands/island.js +1 -0
  69. package/dist/src/islands/render-cache.js +1 -0
  70. package/dist/src/islands/types.js +1 -0
  71. package/dist/src/islands/universal-css-collector.js +5 -0
  72. package/dist/src/islands/universal-head-collector.js +2 -0
  73. package/{src → dist/src}/layout-system.d.ts +592 -592
  74. package/dist/src/layout-system.js +1 -0
  75. package/dist/src/middleware/discovery.js +1 -0
  76. package/dist/src/middleware/executor.js +1 -0
  77. package/dist/src/middleware/index.js +1 -0
  78. package/dist/src/middleware/types.js +1 -0
  79. package/dist/src/nitro/build-config.js +1 -0
  80. package/dist/src/nitro/config.js +1 -0
  81. package/dist/src/nitro/error-handler.js +198 -0
  82. package/dist/src/nitro/index.js +1 -0
  83. package/dist/src/nitro/island-manifest.js +2 -0
  84. package/dist/src/nitro/middleware-adapter.js +1 -0
  85. package/dist/src/nitro/renderer.js +183 -0
  86. package/dist/src/nitro/route-discovery.js +1 -0
  87. package/dist/src/nitro/types.js +1 -0
  88. package/dist/src/render/collect-css.js +3 -0
  89. package/{src/render/error-pages.ts → dist/src/render/error-pages.js} +7 -38
  90. package/dist/src/render/isolated-ssr-renderer.js +1 -0
  91. package/dist/src/render/ssr.js +90 -0
  92. package/dist/src/schemas/api.js +1 -0
  93. package/dist/src/schemas/core.js +1 -0
  94. package/dist/src/schemas/index.js +1 -0
  95. package/dist/src/schemas/layout.js +1 -0
  96. package/dist/src/schemas/routing/index.js +1 -0
  97. package/dist/src/schemas/routing.js +1 -0
  98. package/dist/src/types/as-island.js +1 -0
  99. package/{src → dist/src}/types/image.d.ts +106 -106
  100. package/{src → dist/src}/types/index.d.ts +22 -22
  101. package/{src → dist/src}/types/island-jsx.d.ts +33 -33
  102. package/{src → dist/src}/types/island-prop.d.ts +20 -20
  103. package/dist/src/types/layout.js +1 -0
  104. package/{src → dist/src}/types/mdx.d.ts +6 -6
  105. package/dist/src/types/routing.js +1 -0
  106. package/dist/src/types/types.js +1 -0
  107. package/{src → dist/src}/types/urlpattern.d.ts +49 -49
  108. package/{src → dist/src}/types/vite-env.d.ts +11 -11
  109. package/dist/src/utils/dev-logger.js +12 -0
  110. package/dist/src/utils/fs.js +1 -0
  111. package/dist/src/vite-plugin/auto-discover.js +1 -0
  112. package/dist/src/vite-plugin/config.js +1 -0
  113. package/dist/src/vite-plugin/errors.js +1 -0
  114. package/dist/src/vite-plugin/image-optimization.js +45 -0
  115. package/dist/src/vite-plugin/integration-activator.js +1 -0
  116. package/dist/src/vite-plugin/island-sidecar-plugin.js +1 -0
  117. package/dist/src/vite-plugin/module-discovery.js +1 -0
  118. package/dist/src/vite-plugin/nitro-integration.js +42 -0
  119. package/dist/src/vite-plugin/plugin.js +1 -0
  120. package/dist/src/vite-plugin/types.js +1 -0
  121. package/dist/src/vite-plugin/validation.js +2 -0
  122. package/package.json +57 -26
  123. package/mod.ts +0 -302
  124. package/src/build/integration-bundler-plugin.ts +0 -116
  125. package/src/build/integration-config.ts +0 -168
  126. package/src/build/integration-detection-plugin.ts +0 -117
  127. package/src/build/integration-resolver-plugin.ts +0 -90
  128. package/src/build/island-manifest.ts +0 -269
  129. package/src/build/island-types-generator.ts +0 -476
  130. package/src/build/mdx-island-transform.ts +0 -464
  131. package/src/build/mdx-plugin.ts +0 -98
  132. package/src/build/page-island-transform.ts +0 -598
  133. package/src/build/prop-extractors/index.ts +0 -21
  134. package/src/build/prop-extractors/lit.ts +0 -140
  135. package/src/build/prop-extractors/qwik.ts +0 -16
  136. package/src/build/prop-extractors/solid.ts +0 -125
  137. package/src/build/prop-extractors/svelte.ts +0 -194
  138. package/src/build/prop-extractors/vue.ts +0 -111
  139. package/src/build/sidecar-file-manager.ts +0 -104
  140. package/src/build/sidecar-renderer.ts +0 -30
  141. package/src/client/adapters/index.js +0 -12
  142. package/src/client/adapters/index.ts +0 -13
  143. package/src/client/adapters/lit-adapter.js +0 -467
  144. package/src/client/adapters/lit-adapter.ts +0 -654
  145. package/src/client/adapters/preact-adapter.js +0 -223
  146. package/src/client/adapters/preact-adapter.ts +0 -331
  147. package/src/client/adapters/qwik-adapter.js +0 -259
  148. package/src/client/adapters/qwik-adapter.ts +0 -345
  149. package/src/client/adapters/react-adapter.js +0 -220
  150. package/src/client/adapters/react-adapter.ts +0 -353
  151. package/src/client/adapters/solid-adapter.js +0 -295
  152. package/src/client/adapters/solid-adapter.ts +0 -451
  153. package/src/client/adapters/svelte-adapter.js +0 -368
  154. package/src/client/adapters/svelte-adapter.ts +0 -524
  155. package/src/client/adapters/vue-adapter.js +0 -278
  156. package/src/client/adapters/vue-adapter.ts +0 -467
  157. package/src/client/components.js +0 -23
  158. package/src/client/components.ts +0 -35
  159. package/src/client/css-hmr-handler.js +0 -263
  160. package/src/client/css-hmr-handler.ts +0 -344
  161. package/src/client/framework-adapter.js +0 -283
  162. package/src/client/framework-adapter.ts +0 -462
  163. package/src/client/hmr-coordinator.js +0 -274
  164. package/src/client/hmr-coordinator.ts +0 -396
  165. package/src/client/hmr-error-overlay.js +0 -533
  166. package/src/client/main.js +0 -816
  167. package/src/client/types/vite-virtual-modules.d.ts +0 -60
  168. package/src/components/Image.tsx +0 -123
  169. package/src/components/IslandErrorBoundary.tsx +0 -145
  170. package/src/components/LayoutDataErrorBoundary.tsx +0 -141
  171. package/src/components/LayoutErrorBoundary.tsx +0 -127
  172. package/src/components/PersistentIsland.tsx +0 -52
  173. package/src/components/StreamingErrorBoundary.tsx +0 -233
  174. package/src/components/StreamingLayout.tsx +0 -538
  175. package/src/core/components/component-analyzer.ts +0 -192
  176. package/src/core/components/component-detection.ts +0 -508
  177. package/src/core/components/enhanced-framework-detector.ts +0 -500
  178. package/src/core/components/framework-registry.ts +0 -563
  179. package/src/core/content/mdx-processor.ts +0 -46
  180. package/src/core/integrations/index.ts +0 -19
  181. package/src/core/integrations/loader.ts +0 -125
  182. package/src/core/integrations/registry.ts +0 -175
  183. package/src/core/islands/island-persistence.ts +0 -325
  184. package/src/core/islands/island-state-serializer.ts +0 -258
  185. package/src/core/islands/persistent-island-context.tsx +0 -80
  186. package/src/core/islands/use-persistent-state.ts +0 -68
  187. package/src/core/layout/enhanced-layout-resolver.ts +0 -322
  188. package/src/core/layout/layout-cache-manager.ts +0 -485
  189. package/src/core/layout/layout-composer.ts +0 -357
  190. package/src/core/layout/layout-data-loader.ts +0 -516
  191. package/src/core/layout/layout-discovery.ts +0 -243
  192. package/src/core/layout/layout-matcher.ts +0 -299
  193. package/src/core/layout/layout-types.ts +0 -110
  194. package/src/core/modules/framework-module-resolver.ts +0 -273
  195. package/src/islands/component-analysis.ts +0 -213
  196. package/src/islands/css-utils.ts +0 -565
  197. package/src/islands/discovery/index.ts +0 -80
  198. package/src/islands/discovery/registry.ts +0 -340
  199. package/src/islands/discovery/resolver.ts +0 -477
  200. package/src/islands/discovery/scanner.ts +0 -386
  201. package/src/islands/discovery/types.ts +0 -117
  202. package/src/islands/discovery/validator.ts +0 -544
  203. package/src/islands/discovery/watcher.ts +0 -368
  204. package/src/islands/framework-detection.ts +0 -428
  205. package/src/islands/integration-loader.ts +0 -490
  206. package/src/islands/island.tsx +0 -565
  207. package/src/islands/render-cache.ts +0 -550
  208. package/src/islands/types.ts +0 -80
  209. package/src/islands/universal-css-collector.ts +0 -157
  210. package/src/islands/universal-head-collector.ts +0 -137
  211. package/src/layout-system.ts +0 -218
  212. package/src/middleware/discovery.ts +0 -268
  213. package/src/middleware/executor.ts +0 -315
  214. package/src/middleware/index.ts +0 -76
  215. package/src/middleware/types.ts +0 -99
  216. package/src/nitro/build-config.ts +0 -576
  217. package/src/nitro/config.ts +0 -483
  218. package/src/nitro/error-handler.ts +0 -636
  219. package/src/nitro/index.ts +0 -173
  220. package/src/nitro/island-manifest.ts +0 -584
  221. package/src/nitro/middleware-adapter.ts +0 -260
  222. package/src/nitro/renderer.ts +0 -1471
  223. package/src/nitro/route-discovery.ts +0 -439
  224. package/src/nitro/types.ts +0 -321
  225. package/src/render/collect-css.ts +0 -198
  226. package/src/render/isolated-ssr-renderer.ts +0 -654
  227. package/src/render/ssr.ts +0 -1030
  228. package/src/schemas/api.ts +0 -30
  229. package/src/schemas/core.ts +0 -64
  230. package/src/schemas/index.ts +0 -212
  231. package/src/schemas/layout.ts +0 -279
  232. package/src/schemas/routing/index.ts +0 -38
  233. package/src/schemas/routing.ts +0 -376
  234. package/src/types/as-island.ts +0 -20
  235. package/src/types/layout.ts +0 -285
  236. package/src/types/routing.ts +0 -555
  237. package/src/types/types.ts +0 -5
  238. package/src/utils/dev-logger.ts +0 -299
  239. package/src/utils/fs.ts +0 -151
  240. package/src/vite-plugin/auto-discover.ts +0 -551
  241. package/src/vite-plugin/config.ts +0 -266
  242. package/src/vite-plugin/errors.ts +0 -127
  243. package/src/vite-plugin/image-optimization.ts +0 -156
  244. package/src/vite-plugin/integration-activator.ts +0 -126
  245. package/src/vite-plugin/island-sidecar-plugin.ts +0 -176
  246. package/src/vite-plugin/module-discovery.ts +0 -189
  247. package/src/vite-plugin/nitro-integration.ts +0 -1354
  248. package/src/vite-plugin/plugin.ts +0 -401
  249. package/src/vite-plugin/types.ts +0 -327
  250. package/src/vite-plugin/validation.ts +0 -228
@@ -1,477 +0,0 @@
1
- /**
2
- * Island Resolver
3
- *
4
- * Handles runtime resolution of island references to actual file paths.
5
- * Supports priority-based resolution with default /src/islands/ having highest priority.
6
- *
7
- * ## Resolution Order
8
- *
9
- * When resolving an island reference, the resolver follows this priority order:
10
- *
11
- * 1. **Explicit path-based references** (e.g., "src/modules/auth/islands/Counter")
12
- * - Full path to the island file
13
- * - Always unambiguous
14
- *
15
- * 2. **Qualified name matches** (e.g., "modules/auth/Counter")
16
- * - Namespace/name format
17
- * - Namespace is derived from directory path between src/ and islands/
18
- *
19
- * 3. **Default /src/islands/ directory**
20
- * - Highest priority for simple names (backward compatibility)
21
- * - If an island exists in both default and nested directories,
22
- * the default directory wins
23
- *
24
- * 4. **Nested directories in alphabetical order**
25
- * - When not found in default directory
26
- * - Sorted alphabetically by namespace
27
- *
28
- * ## Namespace Conventions
29
- *
30
- * - src/islands/Counter.tsx -> namespace: "", qualified: "Counter"
31
- * - src/modules/auth/islands/LoginForm.tsx -> namespace: "modules/auth", qualified: "modules/auth/LoginForm"
32
- * - src/features/checkout/islands/PaymentForm.tsx -> namespace: "features/checkout", qualified: "features/checkout/PaymentForm"
33
- *
34
- * ## Handling Collisions
35
- *
36
- * When multiple islands share the same name:
37
- * - Use qualified names to disambiguate
38
- * - The resolver returns `ambiguous: true` with alternatives
39
- * - Default directory always has priority for simple name resolution
40
- */
41
-
42
- import { relative, resolve, dirname } from "node:path";
43
- import type { DiscoveredIsland, IslandDirectory } from "./types.ts";
44
- import type { IslandRegistry } from "./registry.ts";
45
- import { parseQualifiedIslandName, getQualifiedIslandName } from "./scanner.ts";
46
-
47
- /**
48
- * Result of resolving an island reference
49
- */
50
- export interface ResolutionResult {
51
- /** Resolved island */
52
- island: DiscoveredIsland;
53
- /** Import path for the island */
54
- importPath: string;
55
- /** Whether resolution was ambiguous (multiple matches found) */
56
- ambiguous: boolean;
57
- /** Alternative matches if ambiguous */
58
- alternatives?: DiscoveredIsland[];
59
- }
60
-
61
- /**
62
- * Options for import path generation
63
- */
64
- export interface ImportPathOptions {
65
- /** Whether generating for development (true) or production (false) */
66
- isDevelopment?: boolean;
67
- /** Base path for imports (e.g., "/@fs/" for dev, "/" for prod) */
68
- basePath?: string;
69
- /** Project root directory */
70
- projectRoot?: string;
71
- /** Whether to use absolute paths */
72
- absolute?: boolean;
73
- }
74
-
75
- /**
76
- * Default options for import path generation
77
- */
78
- const DEFAULT_IMPORT_OPTIONS: Required<ImportPathOptions> = {
79
- isDevelopment: true,
80
- basePath: "/",
81
- projectRoot: "",
82
- absolute: false,
83
- };
84
-
85
- /**
86
- * Island Resolver class
87
- *
88
- * Resolves island references to actual file paths with priority-based resolution.
89
- * Default /src/islands/ directory has highest priority for backward compatibility.
90
- */
91
- export class IslandResolver {
92
- private _registry: IslandRegistry;
93
- private _projectRoot: string;
94
-
95
- constructor(registry: IslandRegistry, projectRoot: string) {
96
- this._registry = registry;
97
- this._projectRoot = projectRoot;
98
- }
99
-
100
- /**
101
- * Get the underlying registry
102
- */
103
- get registry(): IslandRegistry {
104
- return this._registry;
105
- }
106
-
107
- /**
108
- * Get the project root
109
- */
110
- get projectRoot(): string {
111
- return this._projectRoot;
112
- }
113
-
114
- /**
115
- * Resolve an island reference to a file path.
116
- *
117
- * Resolution priority:
118
- * 1. Explicit path-based reference (e.g., "modules/auth/Counter")
119
- * 2. Qualified name match (namespace/name)
120
- * 3. Default islands directory (highest priority for unqualified names)
121
- * 4. First match in alphabetical order by namespace
122
- *
123
- * @param reference - Island reference (name, qualified name, or path)
124
- * @returns Resolution result or null if not found
125
- */
126
- resolve(reference: string): ResolutionResult | null {
127
- // Normalize the reference
128
- const normalizedRef = this.normalizeReference(reference);
129
-
130
- // Try to resolve as explicit path first
131
- const explicitResult = this.resolveExplicitPath(normalizedRef);
132
- if (explicitResult) {
133
- return explicitResult;
134
- }
135
-
136
- // Try to resolve as qualified name (namespace/name)
137
- if (normalizedRef.includes("/")) {
138
- const qualifiedResult = this.resolveQualifiedName(normalizedRef);
139
- if (qualifiedResult) {
140
- return qualifiedResult;
141
- }
142
- }
143
-
144
- // Resolve by name with priority-based resolution
145
- return this.resolveByName(normalizedRef);
146
- }
147
-
148
- /**
149
- * Normalize an island reference for consistent resolution.
150
- */
151
- private normalizeReference(reference: string): string {
152
- // Remove leading/trailing slashes and whitespace
153
- let normalized = reference.trim().replace(/^\/+|\/+$/g, "");
154
-
155
- // Normalize path separators
156
- normalized = normalized.replace(/\\/g, "/");
157
-
158
- // Remove file extension if present
159
- const extensionPatterns = [
160
- /\.solid\.(tsx|jsx)$/,
161
- /\.react\.(tsx|jsx)$/,
162
- /\.lit\.(ts|js)$/,
163
- /\.preact\.(tsx|jsx)$/,
164
- /\.(tsx|ts|jsx|js|vue|svelte)$/,
165
- ];
166
-
167
- for (const pattern of extensionPatterns) {
168
- if (pattern.test(normalized)) {
169
- normalized = normalized.replace(pattern, "");
170
- break;
171
- }
172
- }
173
-
174
- return normalized;
175
- }
176
-
177
- /**
178
- * Resolve an explicit path-based reference.
179
- * Handles references like "src/modules/auth/islands/Counter"
180
- */
181
- private resolveExplicitPath(reference: string): ResolutionResult | null {
182
- // Check if reference looks like a path (contains "islands/")
183
- if (!reference.includes("islands/")) {
184
- return null;
185
- }
186
-
187
- // Try to find an island whose relative path matches
188
- const allIslands = this._registry.getAllIslands();
189
-
190
- for (const island of allIslands) {
191
- // Check if the reference matches the relative path (without extension)
192
- const islandPathWithoutExt = island.relativePath.replace(/\.[^.]+$/, "");
193
-
194
- // Handle framework-specific extensions
195
- const frameworkPatterns = [
196
- /\.solid$/, /\.react$/, /\.lit$/, /\.preact$/
197
- ];
198
- let cleanIslandPath = islandPathWithoutExt;
199
- for (const pattern of frameworkPatterns) {
200
- cleanIslandPath = cleanIslandPath.replace(pattern, "");
201
- }
202
-
203
- if (cleanIslandPath === reference ||
204
- cleanIslandPath.endsWith("/" + reference) ||
205
- islandPathWithoutExt === reference ||
206
- islandPathWithoutExt.endsWith("/" + reference)) {
207
- return {
208
- island,
209
- importPath: this.generateImportPath(island),
210
- ambiguous: false,
211
- };
212
- }
213
- }
214
-
215
- return null;
216
- }
217
-
218
- /**
219
- * Resolve a qualified name (namespace/name).
220
- */
221
- private resolveQualifiedName(qualifiedName: string): ResolutionResult | null {
222
- const { namespace, name } = parseQualifiedIslandName(qualifiedName);
223
- const island = this._registry.resolve(name, namespace);
224
-
225
- if (!island) {
226
- return null;
227
- }
228
-
229
- // Check if there are other islands with the same name
230
- const allMatches = this._registry.findByName(name);
231
- const ambiguous = allMatches.length > 1;
232
-
233
- return {
234
- island,
235
- importPath: this.generateImportPath(island),
236
- ambiguous,
237
- alternatives: ambiguous ? allMatches.filter(i => i !== island) : undefined,
238
- };
239
- }
240
-
241
- /**
242
- * Resolve by name with priority-based resolution.
243
- * Default /src/islands/ has highest priority.
244
- */
245
- private resolveByName(name: string): ResolutionResult | null {
246
- const matches = this._registry.findByName(name);
247
-
248
- if (matches.length === 0) {
249
- return null;
250
- }
251
-
252
- // Sort matches by priority:
253
- // 1. Default directory first
254
- // 2. Then alphabetically by namespace
255
- const sortedMatches = [...matches].sort((a, b) => {
256
- if (a.directory.isDefault && !b.directory.isDefault) return -1;
257
- if (!a.directory.isDefault && b.directory.isDefault) return 1;
258
- return a.namespace.localeCompare(b.namespace);
259
- });
260
-
261
- const island = sortedMatches[0];
262
- const ambiguous = matches.length > 1;
263
-
264
- return {
265
- island,
266
- importPath: this.generateImportPath(island),
267
- ambiguous,
268
- alternatives: ambiguous ? sortedMatches.slice(1) : undefined,
269
- };
270
- }
271
-
272
- /**
273
- * Generate an import path for an island.
274
- * Handles both development and production paths.
275
- *
276
- * @param island - The island to generate an import path for
277
- * @param options - Options for path generation
278
- * @returns The import path string
279
- */
280
- generateImportPath(
281
- island: DiscoveredIsland,
282
- options: ImportPathOptions = {}
283
- ): string {
284
- const opts = { ...DEFAULT_IMPORT_OPTIONS, ...options };
285
- const projectRoot = opts.projectRoot || this._projectRoot;
286
-
287
- if (opts.absolute) {
288
- // Return absolute file path
289
- return island.filePath;
290
- }
291
-
292
- if (opts.isDevelopment) {
293
- // Development: use relative path from project root with leading slash
294
- const relativePath = relative(projectRoot, island.filePath);
295
- const normalizedPath = relativePath.replace(/\\/g, "/");
296
- return `${opts.basePath}${normalizedPath}`;
297
- }
298
-
299
- // Production: use the relative path for bundled imports
300
- // The build system will handle the actual resolution
301
- return `${opts.basePath}${island.relativePath}`;
302
- }
303
-
304
- /**
305
- * Generate a qualified import path for disambiguation.
306
- * Always includes the namespace for clarity.
307
- *
308
- * @param island - The island to generate a path for
309
- * @returns Qualified import path
310
- */
311
- generateQualifiedImportPath(island: DiscoveredIsland): string {
312
- const qualifiedName = getQualifiedIslandName(island);
313
- return qualifiedName;
314
- }
315
-
316
- /**
317
- * Get the resolution order documentation.
318
- * Describes how islands are resolved when multiple matches exist.
319
- *
320
- * @returns Array of resolution order descriptions
321
- */
322
- getResolutionOrder(): string[] {
323
- const directories = this._registry.directories;
324
-
325
- return [
326
- "Island Resolution Order:",
327
- "1. Explicit path-based references (e.g., 'src/modules/auth/islands/Counter')",
328
- "2. Qualified name matches (e.g., 'modules/auth/Counter')",
329
- "3. Default /src/islands/ directory (highest priority for unqualified names)",
330
- "4. Nested directories in alphabetical order by namespace",
331
- "",
332
- "Discovered directories (in priority order):",
333
- ...directories.map((dir, index) =>
334
- ` ${index + 1}. ${dir.relativePath}${dir.isDefault ? " (default)" : ""}`
335
- ),
336
- ];
337
- }
338
-
339
- /**
340
- * Check if a reference would resolve ambiguously.
341
- *
342
- * @param reference - Island reference to check
343
- * @returns True if the reference matches multiple islands
344
- */
345
- isAmbiguous(reference: string): boolean {
346
- const result = this.resolve(reference);
347
- return result?.ambiguous ?? false;
348
- }
349
-
350
- /**
351
- * Get all possible resolutions for a reference.
352
- * Useful for providing suggestions when resolution is ambiguous.
353
- *
354
- * @param reference - Island reference
355
- * @returns Array of all matching islands
356
- */
357
- getAllMatches(reference: string): DiscoveredIsland[] {
358
- const normalized = this.normalizeReference(reference);
359
-
360
- // If it's a qualified name, return exact match only
361
- if (normalized.includes("/") && !normalized.includes("islands/")) {
362
- const { namespace, name } = parseQualifiedIslandName(normalized);
363
- const island = this._registry.resolve(name, namespace);
364
- return island ? [island] : [];
365
- }
366
-
367
- // For simple names, return all matches
368
- return this._registry.findByName(normalized);
369
- }
370
-
371
- /**
372
- * Suggest qualified names for disambiguation.
373
- *
374
- * @param name - Component name with multiple matches
375
- * @returns Array of qualified name suggestions
376
- */
377
- suggestQualifiedNames(name: string): string[] {
378
- const matches = this._registry.findByName(name);
379
- return matches.map(island => getQualifiedIslandName(island));
380
- }
381
-
382
- /**
383
- * Resolve an island and throw if not found.
384
- *
385
- * @param reference - Island reference
386
- * @throws Error if island is not found
387
- * @returns Resolution result
388
- */
389
- resolveOrThrow(reference: string): ResolutionResult {
390
- const result = this.resolve(reference);
391
-
392
- if (!result) {
393
- const suggestions = this.findSimilarNames(reference);
394
- let message = `Island not found: "${reference}"`;
395
-
396
- if (suggestions.length > 0) {
397
- message += `\n\nDid you mean one of these?\n${suggestions.map(s => ` - ${s}`).join("\n")}`;
398
- }
399
-
400
- throw new Error(message);
401
- }
402
-
403
- return result;
404
- }
405
-
406
- /**
407
- * Find similar island names for suggestions.
408
- * Uses simple string similarity for fuzzy matching.
409
- */
410
- private findSimilarNames(reference: string): string[] {
411
- const allIslands = this._registry.getAllIslands();
412
- const normalized = reference.toLowerCase();
413
-
414
- // Find islands with similar names
415
- const similar = allIslands
416
- .filter(island => {
417
- const name = island.name.toLowerCase();
418
- const qualified = getQualifiedIslandName(island).toLowerCase();
419
-
420
- // Check for substring match
421
- return name.includes(normalized) ||
422
- normalized.includes(name) ||
423
- qualified.includes(normalized) ||
424
- this.levenshteinDistance(name, normalized) <= 3;
425
- })
426
- .map(island => getQualifiedIslandName(island))
427
- .slice(0, 5); // Limit suggestions
428
-
429
- return similar;
430
- }
431
-
432
- /**
433
- * Calculate Levenshtein distance between two strings.
434
- * Used for fuzzy name matching.
435
- */
436
- private levenshteinDistance(a: string, b: string): number {
437
- const matrix: number[][] = [];
438
-
439
- for (let i = 0; i <= b.length; i++) {
440
- matrix[i] = [i];
441
- }
442
-
443
- for (let j = 0; j <= a.length; j++) {
444
- matrix[0][j] = j;
445
- }
446
-
447
- for (let i = 1; i <= b.length; i++) {
448
- for (let j = 1; j <= a.length; j++) {
449
- if (b.charAt(i - 1) === a.charAt(j - 1)) {
450
- matrix[i][j] = matrix[i - 1][j - 1];
451
- } else {
452
- matrix[i][j] = Math.min(
453
- matrix[i - 1][j - 1] + 1,
454
- matrix[i][j - 1] + 1,
455
- matrix[i - 1][j] + 1
456
- );
457
- }
458
- }
459
- }
460
-
461
- return matrix[b.length][a.length];
462
- }
463
- }
464
-
465
- /**
466
- * Create an island resolver from a registry.
467
- *
468
- * @param registry - The island registry to use
469
- * @param projectRoot - The project root directory
470
- * @returns A new IslandResolver instance
471
- */
472
- export function createIslandResolver(
473
- registry: IslandRegistry,
474
- projectRoot: string
475
- ): IslandResolver {
476
- return new IslandResolver(registry, projectRoot);
477
- }