@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.
- package/README.md +54 -54
- package/dist/mod.js +1 -0
- package/dist/src/build/integration-bundler-plugin.js +1 -0
- package/dist/src/build/integration-config.js +1 -0
- package/dist/src/build/integration-detection-plugin.js +1 -0
- package/dist/src/build/integration-resolver-plugin.js +1 -0
- package/dist/src/build/island-manifest.js +1 -0
- package/dist/src/build/island-types-generator.js +5 -0
- package/dist/src/build/mdx-island-transform.js +2 -0
- package/dist/src/build/mdx-plugin.js +1 -0
- package/dist/src/build/page-island-transform.js +3 -0
- package/dist/src/build/prop-extractors/index.js +1 -0
- package/dist/src/build/prop-extractors/lit.js +1 -0
- package/dist/src/build/prop-extractors/qwik.js +1 -0
- package/dist/src/build/prop-extractors/solid.js +1 -0
- package/dist/src/build/prop-extractors/svelte.js +1 -0
- package/dist/src/build/prop-extractors/vue.js +1 -0
- package/dist/src/build/sidecar-file-manager.js +1 -0
- package/dist/src/build/sidecar-renderer.js +6 -0
- package/dist/src/client/adapters/index.js +1 -0
- package/dist/src/client/components.js +1 -0
- package/dist/src/client/css-hmr-handler.js +1 -0
- package/dist/src/client/framework-adapter.js +13 -0
- package/dist/src/client/hmr-coordinator.js +1 -0
- package/dist/src/client/hmr-error-overlay.js +214 -0
- package/dist/src/client/main.js +39 -0
- package/{src → dist/src}/client/types/framework-runtime.d.ts +68 -68
- package/{src → dist/src}/client/types/vite-hmr.d.ts +46 -46
- package/dist/src/client/types/vite-virtual-modules.d.ts +70 -0
- package/dist/src/components/Image.js +1 -0
- package/dist/src/components/IslandErrorBoundary.js +1 -0
- package/dist/src/components/LayoutDataErrorBoundary.js +1 -0
- package/dist/src/components/LayoutErrorBoundary.js +1 -0
- package/dist/src/components/PersistentIsland.js +1 -0
- package/dist/src/components/StreamingErrorBoundary.js +1 -0
- package/dist/src/components/StreamingLayout.js +29 -0
- package/dist/src/core/components/component-analyzer.js +1 -0
- package/dist/src/core/components/component-detection.js +5 -0
- package/dist/src/core/components/enhanced-framework-detector.js +1 -0
- package/dist/src/core/components/framework-registry.js +1 -0
- package/dist/src/core/content/mdx-processor.js +1 -0
- package/dist/src/core/integrations/index.js +1 -0
- package/dist/src/core/integrations/loader.js +1 -0
- package/dist/src/core/integrations/registry.js +1 -0
- package/dist/src/core/islands/island-persistence.js +1 -0
- package/dist/src/core/islands/island-state-serializer.js +1 -0
- package/dist/src/core/islands/persistent-island-context.js +1 -0
- package/dist/src/core/islands/use-persistent-state.js +1 -0
- package/dist/src/core/layout/enhanced-layout-resolver.js +1 -0
- package/dist/src/core/layout/layout-cache-manager.js +1 -0
- package/dist/src/core/layout/layout-composer.js +1 -0
- package/dist/src/core/layout/layout-data-loader.js +1 -0
- package/dist/src/core/layout/layout-discovery.js +1 -0
- package/dist/src/core/layout/layout-matcher.js +1 -0
- package/dist/src/core/layout/layout-types.js +1 -0
- package/dist/src/core/modules/framework-module-resolver.js +1 -0
- package/dist/src/islands/component-analysis.js +1 -0
- package/dist/src/islands/css-utils.js +17 -0
- package/dist/src/islands/discovery/index.js +1 -0
- package/dist/src/islands/discovery/registry.js +1 -0
- package/dist/src/islands/discovery/resolver.js +2 -0
- package/dist/src/islands/discovery/scanner.js +1 -0
- package/dist/src/islands/discovery/types.js +1 -0
- package/dist/src/islands/discovery/validator.js +18 -0
- package/dist/src/islands/discovery/watcher.js +1 -0
- package/dist/src/islands/framework-detection.js +1 -0
- package/dist/src/islands/integration-loader.js +1 -0
- package/dist/src/islands/island.js +1 -0
- package/dist/src/islands/render-cache.js +1 -0
- package/dist/src/islands/types.js +1 -0
- package/dist/src/islands/universal-css-collector.js +5 -0
- package/dist/src/islands/universal-head-collector.js +2 -0
- package/{src → dist/src}/layout-system.d.ts +592 -592
- package/dist/src/layout-system.js +1 -0
- package/dist/src/middleware/discovery.js +1 -0
- package/dist/src/middleware/executor.js +1 -0
- package/dist/src/middleware/index.js +1 -0
- package/dist/src/middleware/types.js +1 -0
- package/dist/src/nitro/build-config.js +1 -0
- package/dist/src/nitro/config.js +1 -0
- package/dist/src/nitro/error-handler.js +198 -0
- package/dist/src/nitro/index.js +1 -0
- package/dist/src/nitro/island-manifest.js +2 -0
- package/dist/src/nitro/middleware-adapter.js +1 -0
- package/dist/src/nitro/renderer.js +183 -0
- package/dist/src/nitro/route-discovery.js +1 -0
- package/dist/src/nitro/types.js +1 -0
- package/dist/src/render/collect-css.js +3 -0
- package/{src/render/error-pages.ts → dist/src/render/error-pages.js} +7 -38
- package/dist/src/render/isolated-ssr-renderer.js +1 -0
- package/dist/src/render/ssr.js +90 -0
- package/dist/src/schemas/api.js +1 -0
- package/dist/src/schemas/core.js +1 -0
- package/dist/src/schemas/index.js +1 -0
- package/dist/src/schemas/layout.js +1 -0
- package/dist/src/schemas/routing/index.js +1 -0
- package/dist/src/schemas/routing.js +1 -0
- package/dist/src/types/as-island.js +1 -0
- package/{src → dist/src}/types/image.d.ts +106 -106
- package/{src → dist/src}/types/index.d.ts +22 -22
- package/{src → dist/src}/types/island-jsx.d.ts +33 -33
- package/{src → dist/src}/types/island-prop.d.ts +20 -20
- package/dist/src/types/layout.js +1 -0
- package/{src → dist/src}/types/mdx.d.ts +6 -6
- package/dist/src/types/routing.js +1 -0
- package/dist/src/types/types.js +1 -0
- package/{src → dist/src}/types/urlpattern.d.ts +49 -49
- package/{src → dist/src}/types/vite-env.d.ts +11 -11
- package/dist/src/utils/dev-logger.js +12 -0
- package/dist/src/utils/fs.js +1 -0
- package/dist/src/vite-plugin/auto-discover.js +1 -0
- package/dist/src/vite-plugin/config.js +1 -0
- package/dist/src/vite-plugin/errors.js +1 -0
- package/dist/src/vite-plugin/image-optimization.js +45 -0
- package/dist/src/vite-plugin/integration-activator.js +1 -0
- package/dist/src/vite-plugin/island-sidecar-plugin.js +1 -0
- package/dist/src/vite-plugin/module-discovery.js +1 -0
- package/dist/src/vite-plugin/nitro-integration.js +42 -0
- package/dist/src/vite-plugin/plugin.js +1 -0
- package/dist/src/vite-plugin/types.js +1 -0
- package/dist/src/vite-plugin/validation.js +2 -0
- package/package.json +57 -26
- package/mod.ts +0 -302
- package/src/build/integration-bundler-plugin.ts +0 -116
- package/src/build/integration-config.ts +0 -168
- package/src/build/integration-detection-plugin.ts +0 -117
- package/src/build/integration-resolver-plugin.ts +0 -90
- package/src/build/island-manifest.ts +0 -269
- package/src/build/island-types-generator.ts +0 -476
- package/src/build/mdx-island-transform.ts +0 -464
- package/src/build/mdx-plugin.ts +0 -98
- package/src/build/page-island-transform.ts +0 -598
- package/src/build/prop-extractors/index.ts +0 -21
- package/src/build/prop-extractors/lit.ts +0 -140
- package/src/build/prop-extractors/qwik.ts +0 -16
- package/src/build/prop-extractors/solid.ts +0 -125
- package/src/build/prop-extractors/svelte.ts +0 -194
- package/src/build/prop-extractors/vue.ts +0 -111
- package/src/build/sidecar-file-manager.ts +0 -104
- package/src/build/sidecar-renderer.ts +0 -30
- package/src/client/adapters/index.js +0 -12
- package/src/client/adapters/index.ts +0 -13
- package/src/client/adapters/lit-adapter.js +0 -467
- package/src/client/adapters/lit-adapter.ts +0 -654
- package/src/client/adapters/preact-adapter.js +0 -223
- package/src/client/adapters/preact-adapter.ts +0 -331
- package/src/client/adapters/qwik-adapter.js +0 -259
- package/src/client/adapters/qwik-adapter.ts +0 -345
- package/src/client/adapters/react-adapter.js +0 -220
- package/src/client/adapters/react-adapter.ts +0 -353
- package/src/client/adapters/solid-adapter.js +0 -295
- package/src/client/adapters/solid-adapter.ts +0 -451
- package/src/client/adapters/svelte-adapter.js +0 -368
- package/src/client/adapters/svelte-adapter.ts +0 -524
- package/src/client/adapters/vue-adapter.js +0 -278
- package/src/client/adapters/vue-adapter.ts +0 -467
- package/src/client/components.js +0 -23
- package/src/client/components.ts +0 -35
- package/src/client/css-hmr-handler.js +0 -263
- package/src/client/css-hmr-handler.ts +0 -344
- package/src/client/framework-adapter.js +0 -283
- package/src/client/framework-adapter.ts +0 -462
- package/src/client/hmr-coordinator.js +0 -274
- package/src/client/hmr-coordinator.ts +0 -396
- package/src/client/hmr-error-overlay.js +0 -533
- package/src/client/main.js +0 -816
- package/src/client/types/vite-virtual-modules.d.ts +0 -60
- package/src/components/Image.tsx +0 -123
- package/src/components/IslandErrorBoundary.tsx +0 -145
- package/src/components/LayoutDataErrorBoundary.tsx +0 -141
- package/src/components/LayoutErrorBoundary.tsx +0 -127
- package/src/components/PersistentIsland.tsx +0 -52
- package/src/components/StreamingErrorBoundary.tsx +0 -233
- package/src/components/StreamingLayout.tsx +0 -538
- package/src/core/components/component-analyzer.ts +0 -192
- package/src/core/components/component-detection.ts +0 -508
- package/src/core/components/enhanced-framework-detector.ts +0 -500
- package/src/core/components/framework-registry.ts +0 -563
- package/src/core/content/mdx-processor.ts +0 -46
- package/src/core/integrations/index.ts +0 -19
- package/src/core/integrations/loader.ts +0 -125
- package/src/core/integrations/registry.ts +0 -175
- package/src/core/islands/island-persistence.ts +0 -325
- package/src/core/islands/island-state-serializer.ts +0 -258
- package/src/core/islands/persistent-island-context.tsx +0 -80
- package/src/core/islands/use-persistent-state.ts +0 -68
- package/src/core/layout/enhanced-layout-resolver.ts +0 -322
- package/src/core/layout/layout-cache-manager.ts +0 -485
- package/src/core/layout/layout-composer.ts +0 -357
- package/src/core/layout/layout-data-loader.ts +0 -516
- package/src/core/layout/layout-discovery.ts +0 -243
- package/src/core/layout/layout-matcher.ts +0 -299
- package/src/core/layout/layout-types.ts +0 -110
- package/src/core/modules/framework-module-resolver.ts +0 -273
- package/src/islands/component-analysis.ts +0 -213
- package/src/islands/css-utils.ts +0 -565
- package/src/islands/discovery/index.ts +0 -80
- package/src/islands/discovery/registry.ts +0 -340
- package/src/islands/discovery/resolver.ts +0 -477
- package/src/islands/discovery/scanner.ts +0 -386
- package/src/islands/discovery/types.ts +0 -117
- package/src/islands/discovery/validator.ts +0 -544
- package/src/islands/discovery/watcher.ts +0 -368
- package/src/islands/framework-detection.ts +0 -428
- package/src/islands/integration-loader.ts +0 -490
- package/src/islands/island.tsx +0 -565
- package/src/islands/render-cache.ts +0 -550
- package/src/islands/types.ts +0 -80
- package/src/islands/universal-css-collector.ts +0 -157
- package/src/islands/universal-head-collector.ts +0 -137
- package/src/layout-system.ts +0 -218
- package/src/middleware/discovery.ts +0 -268
- package/src/middleware/executor.ts +0 -315
- package/src/middleware/index.ts +0 -76
- package/src/middleware/types.ts +0 -99
- package/src/nitro/build-config.ts +0 -576
- package/src/nitro/config.ts +0 -483
- package/src/nitro/error-handler.ts +0 -636
- package/src/nitro/index.ts +0 -173
- package/src/nitro/island-manifest.ts +0 -584
- package/src/nitro/middleware-adapter.ts +0 -260
- package/src/nitro/renderer.ts +0 -1471
- package/src/nitro/route-discovery.ts +0 -439
- package/src/nitro/types.ts +0 -321
- package/src/render/collect-css.ts +0 -198
- package/src/render/isolated-ssr-renderer.ts +0 -654
- package/src/render/ssr.ts +0 -1030
- package/src/schemas/api.ts +0 -30
- package/src/schemas/core.ts +0 -64
- package/src/schemas/index.ts +0 -212
- package/src/schemas/layout.ts +0 -279
- package/src/schemas/routing/index.ts +0 -38
- package/src/schemas/routing.ts +0 -376
- package/src/types/as-island.ts +0 -20
- package/src/types/layout.ts +0 -285
- package/src/types/routing.ts +0 -555
- package/src/types/types.ts +0 -5
- package/src/utils/dev-logger.ts +0 -299
- package/src/utils/fs.ts +0 -151
- package/src/vite-plugin/auto-discover.ts +0 -551
- package/src/vite-plugin/config.ts +0 -266
- package/src/vite-plugin/errors.ts +0 -127
- package/src/vite-plugin/image-optimization.ts +0 -156
- package/src/vite-plugin/integration-activator.ts +0 -126
- package/src/vite-plugin/island-sidecar-plugin.ts +0 -176
- package/src/vite-plugin/module-discovery.ts +0 -189
- package/src/vite-plugin/nitro-integration.ts +0 -1354
- package/src/vite-plugin/plugin.ts +0 -401
- package/src/vite-plugin/types.ts +0 -327
- 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
|
-
}
|