@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,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
- }