@kimesh/auto-import 0.0.1
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 +3 -0
- package/dist/builder-CnceYcPH.mjs +4 -0
- package/dist/builder-c6-47OHx.mjs +614 -0
- package/dist/builder-c6-47OHx.mjs.map +1 -0
- package/dist/index.d.mts +417 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +961 -0
- package/dist/index.mjs.map +1 -0
- package/dist/oxc-scanner-DrjjlY9k.mjs +195 -0
- package/dist/oxc-scanner-DrjjlY9k.mjs.map +1 -0
- package/dist/oxc-scanner-g5pD6w1O.mjs +3 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,614 @@
|
|
|
1
|
+
import { t as OxcExportScanner } from "./oxc-scanner-DrjjlY9k.mjs";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "pathe";
|
|
4
|
+
import { consola } from "consola";
|
|
5
|
+
|
|
6
|
+
//#region src/registry/utils.ts
|
|
7
|
+
/**
|
|
8
|
+
* @kimesh/auto-import - Registry Utilities
|
|
9
|
+
*
|
|
10
|
+
* Shared utility functions for registry building and conflict resolution.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Convert string to PascalCase
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* toPascalCase('foo-bar') // 'FooBar'
|
|
17
|
+
* toPascalCase('some_name') // 'SomeName'
|
|
18
|
+
*/
|
|
19
|
+
function toPascalCase(str) {
|
|
20
|
+
return str.split(/[-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("");
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Layer name patterns for extracting the meaningful part
|
|
24
|
+
*/
|
|
25
|
+
const LAYER_NAME_PATTERNS = [/^@[\w-]+\/(?:layer-)?(.+)$/, /^(?:layer-)?(.+)$/];
|
|
26
|
+
/**
|
|
27
|
+
* Derive component prefix from layer name
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* deriveLayerPrefix('@kimesh-layers/cms') // 'Cms'
|
|
31
|
+
* deriveLayerPrefix('@company/layer-auth') // 'Auth'
|
|
32
|
+
* deriveLayerPrefix('local-layer') // 'LocalLayer'
|
|
33
|
+
*/
|
|
34
|
+
function deriveLayerPrefix(layerName) {
|
|
35
|
+
for (const pattern of LAYER_NAME_PATTERNS) {
|
|
36
|
+
const match = layerName.match(pattern);
|
|
37
|
+
if (match) return toPascalCase(match[1]);
|
|
38
|
+
}
|
|
39
|
+
return "";
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resolve directory path, checking both root and src locations
|
|
43
|
+
*
|
|
44
|
+
* @returns The resolved path if it exists, or null if not found
|
|
45
|
+
*/
|
|
46
|
+
function resolveDirectory(layerPath, dir) {
|
|
47
|
+
const srcDir = path.join(layerPath, "src", dir);
|
|
48
|
+
if (fs.existsSync(srcDir)) return srcDir;
|
|
49
|
+
const rootDir = path.join(layerPath, dir);
|
|
50
|
+
if (fs.existsSync(rootDir)) return rootDir;
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Collect all existing directories from a list of directory names
|
|
55
|
+
*/
|
|
56
|
+
function collectExistingDirectories(layerPath, dirs) {
|
|
57
|
+
const result = [];
|
|
58
|
+
for (const dir of dirs) {
|
|
59
|
+
const resolved = resolveDirectory(layerPath, dir);
|
|
60
|
+
if (resolved) result.push(resolved);
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/registry/conflict-resolver.ts
|
|
67
|
+
var ConflictResolver = class {
|
|
68
|
+
imports = /* @__PURE__ */ new Map();
|
|
69
|
+
resolved = /* @__PURE__ */ new Map();
|
|
70
|
+
conflicts = [];
|
|
71
|
+
addImport(entry) {
|
|
72
|
+
const existing = this.imports.get(entry.name) ?? [];
|
|
73
|
+
existing.push(entry);
|
|
74
|
+
this.imports.set(entry.name, existing);
|
|
75
|
+
}
|
|
76
|
+
resolve() {
|
|
77
|
+
this.conflicts = [];
|
|
78
|
+
this.resolved = /* @__PURE__ */ new Map();
|
|
79
|
+
for (const [name, entries] of this.imports) {
|
|
80
|
+
if (entries.length === 1) {
|
|
81
|
+
this.resolved.set(name, entries[0]);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const sorted = [...entries].sort((a, b) => a.priority - b.priority);
|
|
85
|
+
const winner = sorted[0];
|
|
86
|
+
const losers = sorted.slice(1);
|
|
87
|
+
this.resolved.set(name, winner);
|
|
88
|
+
const uniqueLosers = losers.filter((l) => l.layer !== winner.layer || l.from !== winner.from);
|
|
89
|
+
if (uniqueLosers.length > 0) this.conflicts.push({
|
|
90
|
+
name,
|
|
91
|
+
winner,
|
|
92
|
+
losers: uniqueLosers,
|
|
93
|
+
suggestion: this.generateSuggestion(name, uniqueLosers)
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
resolved: this.resolved,
|
|
98
|
+
conflicts: this.conflicts
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
generateSuggestion(name, losers) {
|
|
102
|
+
const layerNames = [...new Set(losers.map((l) => l.layer))];
|
|
103
|
+
if (layerNames.length === 0) return void 0;
|
|
104
|
+
const prefixedNames = layerNames.map((layer) => {
|
|
105
|
+
const prefix = deriveLayerPrefix(layer);
|
|
106
|
+
return prefix ? `${prefix}${name}` : name;
|
|
107
|
+
}).filter((n) => n !== name);
|
|
108
|
+
const uniquePrefixed = [...new Set(prefixedNames)];
|
|
109
|
+
if (uniquePrefixed.length === 0) return void 0;
|
|
110
|
+
return `Consider using prefixed versions: ${uniquePrefixed.join(", ")}`;
|
|
111
|
+
}
|
|
112
|
+
getConflicts() {
|
|
113
|
+
return this.conflicts;
|
|
114
|
+
}
|
|
115
|
+
hasConflict(name) {
|
|
116
|
+
return this.conflicts.some((c) => c.name === name);
|
|
117
|
+
}
|
|
118
|
+
getConflict(name) {
|
|
119
|
+
return this.conflicts.find((c) => c.name === name);
|
|
120
|
+
}
|
|
121
|
+
clear() {
|
|
122
|
+
this.imports.clear();
|
|
123
|
+
this.resolved.clear();
|
|
124
|
+
this.conflicts = [];
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
//#endregion
|
|
129
|
+
//#region src/presets/index.ts
|
|
130
|
+
/**
|
|
131
|
+
* Vue core preset
|
|
132
|
+
*/
|
|
133
|
+
const vuePreset = {
|
|
134
|
+
name: "vue",
|
|
135
|
+
from: "vue",
|
|
136
|
+
imports: [
|
|
137
|
+
"ref",
|
|
138
|
+
"reactive",
|
|
139
|
+
"computed",
|
|
140
|
+
"readonly",
|
|
141
|
+
"shallowRef",
|
|
142
|
+
"shallowReactive",
|
|
143
|
+
"shallowReadonly",
|
|
144
|
+
"toRef",
|
|
145
|
+
"toRefs",
|
|
146
|
+
"toRaw",
|
|
147
|
+
"unref",
|
|
148
|
+
"isRef",
|
|
149
|
+
"isReactive",
|
|
150
|
+
"isReadonly",
|
|
151
|
+
"isProxy",
|
|
152
|
+
"triggerRef",
|
|
153
|
+
"customRef",
|
|
154
|
+
"markRaw",
|
|
155
|
+
"effectScope",
|
|
156
|
+
"getCurrentScope",
|
|
157
|
+
"onScopeDispose",
|
|
158
|
+
"watch",
|
|
159
|
+
"watchEffect",
|
|
160
|
+
"watchPostEffect",
|
|
161
|
+
"watchSyncEffect",
|
|
162
|
+
"onMounted",
|
|
163
|
+
"onUpdated",
|
|
164
|
+
"onUnmounted",
|
|
165
|
+
"onBeforeMount",
|
|
166
|
+
"onBeforeUpdate",
|
|
167
|
+
"onBeforeUnmount",
|
|
168
|
+
"onActivated",
|
|
169
|
+
"onDeactivated",
|
|
170
|
+
"onErrorCaptured",
|
|
171
|
+
"onRenderTracked",
|
|
172
|
+
"onRenderTriggered",
|
|
173
|
+
"onServerPrefetch",
|
|
174
|
+
"provide",
|
|
175
|
+
"inject",
|
|
176
|
+
"defineComponent",
|
|
177
|
+
"defineAsyncComponent",
|
|
178
|
+
"getCurrentInstance",
|
|
179
|
+
"h",
|
|
180
|
+
"nextTick",
|
|
181
|
+
"resolveComponent",
|
|
182
|
+
"resolveDirective",
|
|
183
|
+
"useAttrs",
|
|
184
|
+
"useSlots",
|
|
185
|
+
"useCssModule",
|
|
186
|
+
{
|
|
187
|
+
name: "Ref",
|
|
188
|
+
type: true
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
name: "ComputedRef",
|
|
192
|
+
type: true
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
name: "UnwrapRef",
|
|
196
|
+
type: true
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: "ShallowRef",
|
|
200
|
+
type: true
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: "WritableComputedRef",
|
|
204
|
+
type: true
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: "ToRefs",
|
|
208
|
+
type: true
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: "PropType",
|
|
212
|
+
type: true
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: "Component",
|
|
216
|
+
type: true
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
name: "ComponentPublicInstance",
|
|
220
|
+
type: true
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: "VNode",
|
|
224
|
+
type: true
|
|
225
|
+
}
|
|
226
|
+
]
|
|
227
|
+
};
|
|
228
|
+
/**
|
|
229
|
+
* Vue Router preset
|
|
230
|
+
*/
|
|
231
|
+
const vueRouterPreset = {
|
|
232
|
+
name: "vue-router",
|
|
233
|
+
from: "vue-router",
|
|
234
|
+
imports: [
|
|
235
|
+
"useRouter",
|
|
236
|
+
"useRoute",
|
|
237
|
+
"useLink",
|
|
238
|
+
"onBeforeRouteLeave",
|
|
239
|
+
"onBeforeRouteUpdate",
|
|
240
|
+
"createRouter",
|
|
241
|
+
"createWebHistory",
|
|
242
|
+
"createWebHashHistory",
|
|
243
|
+
"createMemoryHistory",
|
|
244
|
+
{
|
|
245
|
+
name: "RouteLocationNormalized",
|
|
246
|
+
type: true
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
name: "RouteLocationNormalizedLoaded",
|
|
250
|
+
type: true
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: "RouteRecordRaw",
|
|
254
|
+
type: true
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
name: "NavigationGuard",
|
|
258
|
+
type: true
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
name: "NavigationFailure",
|
|
262
|
+
type: true
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: "Router",
|
|
266
|
+
type: true
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
name: "RouteLocation",
|
|
270
|
+
type: true
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
name: "LocationQuery",
|
|
274
|
+
type: true
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
name: "RouteParams",
|
|
278
|
+
type: true
|
|
279
|
+
}
|
|
280
|
+
]
|
|
281
|
+
};
|
|
282
|
+
/**
|
|
283
|
+
* TanStack Vue Query preset
|
|
284
|
+
*/
|
|
285
|
+
const tanstackQueryPreset = {
|
|
286
|
+
name: "tanstack-query",
|
|
287
|
+
from: "@tanstack/vue-query",
|
|
288
|
+
imports: [
|
|
289
|
+
"useQuery",
|
|
290
|
+
"useMutation",
|
|
291
|
+
"useQueryClient",
|
|
292
|
+
"useSuspenseQuery",
|
|
293
|
+
"useInfiniteQuery",
|
|
294
|
+
"useSuspenseInfiniteQuery",
|
|
295
|
+
"useIsFetching",
|
|
296
|
+
"useIsMutating",
|
|
297
|
+
"useQueries",
|
|
298
|
+
"QueryClient",
|
|
299
|
+
"QueryClientProvider",
|
|
300
|
+
"VueQueryPlugin",
|
|
301
|
+
{
|
|
302
|
+
name: "UseQueryOptions",
|
|
303
|
+
type: true
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
name: "UseMutationOptions",
|
|
307
|
+
type: true
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
name: "UseQueryReturnType",
|
|
311
|
+
type: true
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
name: "UseMutationReturnType",
|
|
315
|
+
type: true
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
name: "QueryKey",
|
|
319
|
+
type: true
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
name: "MutationKey",
|
|
323
|
+
type: true
|
|
324
|
+
}
|
|
325
|
+
]
|
|
326
|
+
};
|
|
327
|
+
/**
|
|
328
|
+
* Pinia preset
|
|
329
|
+
*/
|
|
330
|
+
const piniaPreset = {
|
|
331
|
+
name: "pinia",
|
|
332
|
+
from: "pinia",
|
|
333
|
+
imports: [
|
|
334
|
+
"defineStore",
|
|
335
|
+
"storeToRefs",
|
|
336
|
+
"acceptHMRUpdate",
|
|
337
|
+
"createPinia",
|
|
338
|
+
"setActivePinia",
|
|
339
|
+
"getActivePinia",
|
|
340
|
+
"mapStores",
|
|
341
|
+
"mapState",
|
|
342
|
+
"mapWritableState",
|
|
343
|
+
"mapActions",
|
|
344
|
+
"mapGetters",
|
|
345
|
+
{
|
|
346
|
+
name: "Store",
|
|
347
|
+
type: true
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
name: "StoreDefinition",
|
|
351
|
+
type: true
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
name: "StateTree",
|
|
355
|
+
type: true
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
name: "PiniaPlugin",
|
|
359
|
+
type: true
|
|
360
|
+
}
|
|
361
|
+
]
|
|
362
|
+
};
|
|
363
|
+
/**
|
|
364
|
+
* Kimesh runtime preset
|
|
365
|
+
*/
|
|
366
|
+
const kimeshPreset = {
|
|
367
|
+
name: "kimesh",
|
|
368
|
+
from: "@kimesh/router-runtime",
|
|
369
|
+
imports: [
|
|
370
|
+
"createFileRoute",
|
|
371
|
+
"defineRoute",
|
|
372
|
+
"defineContext",
|
|
373
|
+
"useKimeshContext",
|
|
374
|
+
"useNavigate",
|
|
375
|
+
"useParams",
|
|
376
|
+
"useReactiveParams",
|
|
377
|
+
"useSearch",
|
|
378
|
+
"KmOutlet",
|
|
379
|
+
"KmLink",
|
|
380
|
+
"KmDeferred"
|
|
381
|
+
]
|
|
382
|
+
};
|
|
383
|
+
/**
|
|
384
|
+
* All built-in presets
|
|
385
|
+
*/
|
|
386
|
+
const builtinPresets = {
|
|
387
|
+
vue: vuePreset,
|
|
388
|
+
"vue-router": vueRouterPreset,
|
|
389
|
+
"tanstack-query": tanstackQueryPreset,
|
|
390
|
+
pinia: piniaPreset,
|
|
391
|
+
kimesh: kimeshPreset
|
|
392
|
+
};
|
|
393
|
+
/**
|
|
394
|
+
* Normalize preset configuration to ImportPreset
|
|
395
|
+
*/
|
|
396
|
+
function normalizePreset(preset) {
|
|
397
|
+
if (typeof preset === "string") return builtinPresets[preset] || null;
|
|
398
|
+
return preset;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Get all enabled presets from configuration
|
|
402
|
+
*/
|
|
403
|
+
function resolvePresets(presets) {
|
|
404
|
+
if (!presets || presets.length === 0) return [vuePreset, vueRouterPreset];
|
|
405
|
+
const resolved = [];
|
|
406
|
+
for (const preset of presets) {
|
|
407
|
+
const normalized = normalizePreset(preset);
|
|
408
|
+
if (normalized) resolved.push(normalized);
|
|
409
|
+
}
|
|
410
|
+
return resolved;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
//#endregion
|
|
414
|
+
//#region src/registry/builder.ts
|
|
415
|
+
/**
|
|
416
|
+
* @kimesh/auto-import - Import Registry Builder
|
|
417
|
+
*
|
|
418
|
+
* Builds a unified import registry from all layer sources.
|
|
419
|
+
*/
|
|
420
|
+
const logger = consola.withTag("kimesh:auto-import:registry");
|
|
421
|
+
const DEFAULT_EXTENSIONS = [
|
|
422
|
+
".ts",
|
|
423
|
+
".js",
|
|
424
|
+
".tsx",
|
|
425
|
+
".jsx",
|
|
426
|
+
".mts",
|
|
427
|
+
".mjs"
|
|
428
|
+
];
|
|
429
|
+
const COMPONENT_EXTENSIONS = [".vue", ...DEFAULT_EXTENSIONS];
|
|
430
|
+
var RegistryBuilder = class {
|
|
431
|
+
scanner = new OxcExportScanner();
|
|
432
|
+
resolver = new ConflictResolver();
|
|
433
|
+
async build(sources) {
|
|
434
|
+
const startTime = performance.now();
|
|
435
|
+
const sortedSources = [...sources].sort((a, b) => b.priority - a.priority);
|
|
436
|
+
for (const source of sortedSources) await this.processLayerSource(source);
|
|
437
|
+
const { resolved, conflicts } = this.resolver.resolve();
|
|
438
|
+
const components = this.extractComponents(resolved);
|
|
439
|
+
const scanTime = performance.now() - startTime;
|
|
440
|
+
const stats = this.calculateStats(resolved, conflicts.length, scanTime);
|
|
441
|
+
this.logBuildResults(stats, conflicts);
|
|
442
|
+
return {
|
|
443
|
+
imports: resolved,
|
|
444
|
+
components,
|
|
445
|
+
conflicts,
|
|
446
|
+
stats
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
extractComponents(resolved) {
|
|
450
|
+
const components = /* @__PURE__ */ new Map();
|
|
451
|
+
for (const [name, entry] of resolved) {
|
|
452
|
+
const isComponent = entry.type === "component";
|
|
453
|
+
const isPresetComponent = entry.type === "preset" && /^[A-Z][a-zA-Z0-9]*$/.test(name);
|
|
454
|
+
if (isComponent || isPresetComponent) components.set(name, entry);
|
|
455
|
+
}
|
|
456
|
+
return components;
|
|
457
|
+
}
|
|
458
|
+
calculateStats(resolved, conflictsCount, scanTimeMs) {
|
|
459
|
+
const entries = [...resolved.values()];
|
|
460
|
+
return {
|
|
461
|
+
totalScanned: this.scanner.getCacheStats().size,
|
|
462
|
+
componentsCount: entries.filter((e) => e.type === "component").length,
|
|
463
|
+
composablesCount: entries.filter((e) => e.type === "composable").length,
|
|
464
|
+
utilitiesCount: entries.filter((e) => e.type === "utility").length,
|
|
465
|
+
presetsCount: entries.filter((e) => e.type === "preset").length,
|
|
466
|
+
conflictsCount,
|
|
467
|
+
scanTimeMs
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
logBuildResults(stats, conflicts) {
|
|
471
|
+
logger.debug(`Built registry in ${stats.scanTimeMs.toFixed(1)}ms`);
|
|
472
|
+
logger.debug(` Components: ${stats.componentsCount}`);
|
|
473
|
+
logger.debug(` Composables: ${stats.composablesCount}`);
|
|
474
|
+
logger.debug(` Utilities: ${stats.utilitiesCount}`);
|
|
475
|
+
logger.debug(` Presets: ${stats.presetsCount}`);
|
|
476
|
+
logger.debug(` Conflicts: ${stats.conflictsCount}`);
|
|
477
|
+
for (const conflict of conflicts) {
|
|
478
|
+
logger.warn(`Auto-import conflict for "${conflict.name}": Using ${conflict.winner.layer} (priority ${conflict.winner.priority}), ignoring ${conflict.losers.map((l) => l.layer).join(", ")}`);
|
|
479
|
+
if (conflict.suggestion) logger.info(` Suggestion: ${conflict.suggestion}`);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
async processLayerSource(source) {
|
|
483
|
+
const { layer, priority, layerPath, config } = source;
|
|
484
|
+
logger.debug(`Processing layer: ${layer} (priority ${priority})`);
|
|
485
|
+
await this.processPresets(config.presets ?? [], layer, priority);
|
|
486
|
+
if (config.components) await this.processComponents(config.components, layerPath, layer, priority);
|
|
487
|
+
if (config.composables) {
|
|
488
|
+
const dirs = config.composables.dirs ?? ["composables"];
|
|
489
|
+
const extensions = config.composables.extensions ?? DEFAULT_EXTENSIONS;
|
|
490
|
+
await this.processDirectories(dirs, layerPath, layer, priority, "composable", extensions);
|
|
491
|
+
}
|
|
492
|
+
if (config.utils) {
|
|
493
|
+
const dirs = config.utils.dirs ?? ["utils"];
|
|
494
|
+
const extensions = config.utils.extensions ?? DEFAULT_EXTENSIONS;
|
|
495
|
+
await this.processDirectories(dirs, layerPath, layer, priority, "utility", extensions);
|
|
496
|
+
}
|
|
497
|
+
if (config.stores) {
|
|
498
|
+
const dirs = config.stores.dirs ?? ["stores"];
|
|
499
|
+
await this.processDirectories(dirs, layerPath, layer, priority, "store", DEFAULT_EXTENSIONS);
|
|
500
|
+
}
|
|
501
|
+
if (config.imports) this.processAdditionalImports(config.imports, layer, priority);
|
|
502
|
+
}
|
|
503
|
+
async processPresets(presets, layer, priority) {
|
|
504
|
+
for (const presetConfig of presets) {
|
|
505
|
+
const preset = normalizePreset(presetConfig);
|
|
506
|
+
if (!preset) continue;
|
|
507
|
+
for (const importItem of preset.imports) {
|
|
508
|
+
const name = typeof importItem === "string" ? importItem : importItem.name;
|
|
509
|
+
const isType = typeof importItem === "object" && importItem.type === true;
|
|
510
|
+
const alias = typeof importItem === "object" ? importItem.as : void 0;
|
|
511
|
+
this.resolver.addImport({
|
|
512
|
+
name: alias ?? name,
|
|
513
|
+
as: alias,
|
|
514
|
+
from: preset.from,
|
|
515
|
+
type: "preset",
|
|
516
|
+
layer,
|
|
517
|
+
priority: priority + .5,
|
|
518
|
+
isDefault: false,
|
|
519
|
+
isType
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
async processComponents(config, layerPath, layer, priority) {
|
|
525
|
+
const dirs = config.dirs ?? ["components"];
|
|
526
|
+
const extensions = config.extensions ?? COMPONENT_EXTENSIONS;
|
|
527
|
+
const prefix = config.prefix;
|
|
528
|
+
for (const dir of dirs) {
|
|
529
|
+
const dirPath = resolveDirectory(layerPath, dir);
|
|
530
|
+
if (!dirPath) continue;
|
|
531
|
+
const files = this.scanDirectory(dirPath, extensions);
|
|
532
|
+
const results = await this.scanner.scanFiles(files);
|
|
533
|
+
for (const result of results) for (const exp of result.exports) {
|
|
534
|
+
if (!exp.isDefault) continue;
|
|
535
|
+
const componentName = this.resolveComponentName(exp.name, prefix, layer);
|
|
536
|
+
this.resolver.addImport({
|
|
537
|
+
name: componentName,
|
|
538
|
+
from: result.filePath,
|
|
539
|
+
type: "component",
|
|
540
|
+
layer,
|
|
541
|
+
priority,
|
|
542
|
+
isDefault: true,
|
|
543
|
+
isType: false
|
|
544
|
+
});
|
|
545
|
+
if (componentName !== exp.name) this.resolver.addImport({
|
|
546
|
+
name: exp.name,
|
|
547
|
+
from: result.filePath,
|
|
548
|
+
type: "component",
|
|
549
|
+
layer,
|
|
550
|
+
priority,
|
|
551
|
+
isDefault: true,
|
|
552
|
+
isType: false
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
resolveComponentName(name, prefix, layer) {
|
|
558
|
+
if (prefix !== false && prefix) return `${prefix}${name}`;
|
|
559
|
+
if (layer !== "app") return `${deriveLayerPrefix(layer)}${name}`;
|
|
560
|
+
return name;
|
|
561
|
+
}
|
|
562
|
+
async processDirectories(dirs, layerPath, layer, priority, type, extensions) {
|
|
563
|
+
for (const dir of dirs) {
|
|
564
|
+
const dirPath = resolveDirectory(layerPath, dir);
|
|
565
|
+
if (!dirPath) continue;
|
|
566
|
+
const files = this.scanDirectory(dirPath, extensions);
|
|
567
|
+
const results = await this.scanner.scanFiles(files);
|
|
568
|
+
for (const result of results) for (const exp of result.exports) this.resolver.addImport({
|
|
569
|
+
name: exp.name,
|
|
570
|
+
from: result.filePath,
|
|
571
|
+
type,
|
|
572
|
+
layer,
|
|
573
|
+
priority,
|
|
574
|
+
isDefault: exp.isDefault,
|
|
575
|
+
isType: exp.isType
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
processAdditionalImports(imports, layer, priority) {
|
|
580
|
+
for (const { from, imports: names } of imports) for (const name of names) this.resolver.addImport({
|
|
581
|
+
name,
|
|
582
|
+
from,
|
|
583
|
+
type: "utility",
|
|
584
|
+
layer,
|
|
585
|
+
priority,
|
|
586
|
+
isDefault: false,
|
|
587
|
+
isType: false
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
scanDirectory(dirPath, extensions) {
|
|
591
|
+
const files = [];
|
|
592
|
+
this.scanDirectoryRecursive(dirPath, extensions, files);
|
|
593
|
+
return files;
|
|
594
|
+
}
|
|
595
|
+
scanDirectoryRecursive(dir, extensions, files) {
|
|
596
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
597
|
+
for (const entry of entries) {
|
|
598
|
+
const fullPath = path.join(dir, entry.name);
|
|
599
|
+
if (entry.isDirectory()) this.scanDirectoryRecursive(fullPath, extensions, files);
|
|
600
|
+
else if (entry.isFile() && extensions.includes(path.extname(entry.name))) files.push(fullPath);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
invalidate(filePath) {
|
|
604
|
+
this.scanner.invalidate(filePath);
|
|
605
|
+
}
|
|
606
|
+
clearCache() {
|
|
607
|
+
this.scanner.clearCache();
|
|
608
|
+
this.resolver.clear();
|
|
609
|
+
}
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
//#endregion
|
|
613
|
+
export { piniaPreset as a, vuePreset as c, collectExistingDirectories as d, normalizePreset as i, vueRouterPreset as l, builtinPresets as n, resolvePresets as o, kimeshPreset as r, tanstackQueryPreset as s, RegistryBuilder as t, ConflictResolver as u };
|
|
614
|
+
//# sourceMappingURL=builder-c6-47OHx.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder-c6-47OHx.mjs","names":[],"sources":["../src/registry/utils.ts","../src/registry/conflict-resolver.ts","../src/presets/index.ts","../src/registry/builder.ts"],"sourcesContent":["/**\n * @kimesh/auto-import - Registry Utilities\n *\n * Shared utility functions for registry building and conflict resolution.\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'pathe';\n\n/**\n * Convert string to PascalCase\n *\n * @example\n * toPascalCase('foo-bar') // 'FooBar'\n * toPascalCase('some_name') // 'SomeName'\n */\nexport function toPascalCase(str: string): string {\n return str\n .split(/[-_]/)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())\n .join('');\n}\n\n/**\n * Layer name patterns for extracting the meaningful part\n */\nconst LAYER_NAME_PATTERNS = [\n /^@[\\w-]+\\/(?:layer-)?(.+)$/, // Scoped package: @kimesh-layers/cms -> cms\n /^(?:layer-)?(.+)$/, // Regular name: layer-auth -> auth\n];\n\n/**\n * Derive component prefix from layer name\n *\n * @example\n * deriveLayerPrefix('@kimesh-layers/cms') // 'Cms'\n * deriveLayerPrefix('@company/layer-auth') // 'Auth'\n * deriveLayerPrefix('local-layer') // 'LocalLayer'\n */\nexport function deriveLayerPrefix(layerName: string): string {\n for (const pattern of LAYER_NAME_PATTERNS) {\n const match = layerName.match(pattern);\n if (match) {\n return toPascalCase(match[1]);\n }\n }\n return '';\n}\n\n/**\n * Resolve directory path, checking both root and src locations\n *\n * @returns The resolved path if it exists, or null if not found\n */\nexport function resolveDirectory(layerPath: string, dir: string): string | null {\n const srcDir = path.join(layerPath, 'src', dir);\n if (fs.existsSync(srcDir)) {\n return srcDir;\n }\n\n const rootDir = path.join(layerPath, dir);\n if (fs.existsSync(rootDir)) {\n return rootDir;\n }\n\n return null;\n}\n\n/**\n * Collect all existing directories from a list of directory names\n */\nexport function collectExistingDirectories(\n layerPath: string,\n dirs: string[]\n): string[] {\n const result: string[] = [];\n\n for (const dir of dirs) {\n const resolved = resolveDirectory(layerPath, dir);\n if (resolved) {\n result.push(resolved);\n }\n }\n\n return result;\n}\n","/**\n * @kimesh/auto-import - Conflict Resolution\n *\n * Handles conflicts when multiple layers export the same name.\n * Priority-based resolution: lower priority number wins.\n */\n\nimport type { ImportEntry, ConflictReport } from '../types';\nimport { deriveLayerPrefix } from './utils';\n\nexport class ConflictResolver {\n private imports: Map<string, ImportEntry[]> = new Map();\n private resolved: Map<string, ImportEntry> = new Map();\n private conflicts: ConflictReport[] = [];\n\n addImport(entry: ImportEntry): void {\n const existing = this.imports.get(entry.name) ?? [];\n existing.push(entry);\n this.imports.set(entry.name, existing);\n }\n\n resolve(): { resolved: Map<string, ImportEntry>; conflicts: ConflictReport[] } {\n this.conflicts = [];\n this.resolved = new Map();\n\n for (const [name, entries] of this.imports) {\n if (entries.length === 1) {\n this.resolved.set(name, entries[0]);\n continue;\n }\n\n const sorted = [...entries].sort((a, b) => a.priority - b.priority);\n const winner = sorted[0];\n const losers = sorted.slice(1);\n\n this.resolved.set(name, winner);\n\n const uniqueLosers = losers.filter(\n (l) => l.layer !== winner.layer || l.from !== winner.from\n );\n\n if (uniqueLosers.length > 0) {\n this.conflicts.push({\n name,\n winner,\n losers: uniqueLosers,\n suggestion: this.generateSuggestion(name, uniqueLosers),\n });\n }\n }\n\n return { resolved: this.resolved, conflicts: this.conflicts };\n }\n\n private generateSuggestion(name: string, losers: ImportEntry[]): string | undefined {\n const layerNames = [...new Set(losers.map((l) => l.layer))];\n if (layerNames.length === 0) return undefined;\n\n const prefixedNames = layerNames\n .map((layer) => {\n const prefix = deriveLayerPrefix(layer);\n return prefix ? `${prefix}${name}` : name;\n })\n .filter((n) => n !== name);\n\n const uniquePrefixed = [...new Set(prefixedNames)];\n if (uniquePrefixed.length === 0) return undefined;\n\n return `Consider using prefixed versions: ${uniquePrefixed.join(', ')}`;\n }\n\n getConflicts(): ConflictReport[] {\n return this.conflicts;\n }\n\n hasConflict(name: string): boolean {\n return this.conflicts.some((c) => c.name === name);\n }\n\n getConflict(name: string): ConflictReport | undefined {\n return this.conflicts.find((c) => c.name === name);\n }\n\n clear(): void {\n this.imports.clear();\n this.resolved.clear();\n this.conflicts = [];\n }\n}\n","/**\n * @kimesh/auto-import - Built-in Presets\n *\n * Presets for common libraries: Vue, Vue Router, TanStack Query, Pinia.\n */\n\nimport type { ImportPreset } from '../types';\n\n/**\n * Vue core preset\n */\nexport const vuePreset: ImportPreset = {\n name: 'vue',\n from: 'vue',\n imports: [\n // Reactivity\n 'ref',\n 'reactive',\n 'computed',\n 'readonly',\n 'shallowRef',\n 'shallowReactive',\n 'shallowReadonly',\n 'toRef',\n 'toRefs',\n 'toRaw',\n 'unref',\n 'isRef',\n 'isReactive',\n 'isReadonly',\n 'isProxy',\n 'triggerRef',\n 'customRef',\n 'markRaw',\n 'effectScope',\n 'getCurrentScope',\n 'onScopeDispose',\n\n // Watch\n 'watch',\n 'watchEffect',\n 'watchPostEffect',\n 'watchSyncEffect',\n\n // Lifecycle\n 'onMounted',\n 'onUpdated',\n 'onUnmounted',\n 'onBeforeMount',\n 'onBeforeUpdate',\n 'onBeforeUnmount',\n 'onActivated',\n 'onDeactivated',\n 'onErrorCaptured',\n 'onRenderTracked',\n 'onRenderTriggered',\n 'onServerPrefetch',\n\n // Dependency Injection\n 'provide',\n 'inject',\n\n // Composition\n 'defineComponent',\n 'defineAsyncComponent',\n 'getCurrentInstance',\n 'h',\n 'nextTick',\n 'resolveComponent',\n 'resolveDirective',\n 'useAttrs',\n 'useSlots',\n 'useCssModule',\n\n // Types (as type-only imports)\n { name: 'Ref', type: true },\n { name: 'ComputedRef', type: true },\n { name: 'UnwrapRef', type: true },\n { name: 'ShallowRef', type: true },\n { name: 'WritableComputedRef', type: true },\n { name: 'ToRefs', type: true },\n { name: 'PropType', type: true },\n { name: 'Component', type: true },\n { name: 'ComponentPublicInstance', type: true },\n { name: 'VNode', type: true },\n ],\n};\n\n/**\n * Vue Router preset\n */\nexport const vueRouterPreset: ImportPreset = {\n name: 'vue-router',\n from: 'vue-router',\n imports: [\n 'useRouter',\n 'useRoute',\n 'useLink',\n 'onBeforeRouteLeave',\n 'onBeforeRouteUpdate',\n 'createRouter',\n 'createWebHistory',\n 'createWebHashHistory',\n 'createMemoryHistory',\n\n // Types\n { name: 'RouteLocationNormalized', type: true },\n { name: 'RouteLocationNormalizedLoaded', type: true },\n { name: 'RouteRecordRaw', type: true },\n { name: 'NavigationGuard', type: true },\n { name: 'NavigationFailure', type: true },\n { name: 'Router', type: true },\n { name: 'RouteLocation', type: true },\n { name: 'LocationQuery', type: true },\n { name: 'RouteParams', type: true },\n ],\n};\n\n/**\n * TanStack Vue Query preset\n */\nexport const tanstackQueryPreset: ImportPreset = {\n name: 'tanstack-query',\n from: '@tanstack/vue-query',\n imports: [\n 'useQuery',\n 'useMutation',\n 'useQueryClient',\n 'useSuspenseQuery',\n 'useInfiniteQuery',\n 'useSuspenseInfiniteQuery',\n 'useIsFetching',\n 'useIsMutating',\n 'useQueries',\n 'QueryClient',\n 'QueryClientProvider',\n 'VueQueryPlugin',\n\n // Types\n { name: 'UseQueryOptions', type: true },\n { name: 'UseMutationOptions', type: true },\n { name: 'UseQueryReturnType', type: true },\n { name: 'UseMutationReturnType', type: true },\n { name: 'QueryKey', type: true },\n { name: 'MutationKey', type: true },\n ],\n};\n\n/**\n * Pinia preset\n */\nexport const piniaPreset: ImportPreset = {\n name: 'pinia',\n from: 'pinia',\n imports: [\n 'defineStore',\n 'storeToRefs',\n 'acceptHMRUpdate',\n 'createPinia',\n 'setActivePinia',\n 'getActivePinia',\n 'mapStores',\n 'mapState',\n 'mapWritableState',\n 'mapActions',\n 'mapGetters',\n\n // Types\n { name: 'Store', type: true },\n { name: 'StoreDefinition', type: true },\n { name: 'StateTree', type: true },\n { name: 'PiniaPlugin', type: true },\n ],\n};\n\n/**\n * Kimesh runtime preset\n */\nexport const kimeshPreset: ImportPreset = {\n name: 'kimesh',\n from: '@kimesh/router-runtime',\n imports: [\n // Route definition\n 'createFileRoute',\n 'defineRoute',\n // Context\n 'defineContext',\n 'useKimeshContext',\n // Navigation & params\n 'useNavigate',\n 'useParams',\n 'useReactiveParams',\n 'useSearch',\n // Components\n 'KmOutlet',\n 'KmLink',\n 'KmDeferred',\n ],\n};\n\n/**\n * All built-in presets\n */\nexport const builtinPresets: Record<string, ImportPreset> = {\n vue: vuePreset,\n 'vue-router': vueRouterPreset,\n 'tanstack-query': tanstackQueryPreset,\n pinia: piniaPreset,\n kimesh: kimeshPreset,\n};\n\n/**\n * Normalize preset configuration to ImportPreset\n */\nexport function normalizePreset(preset: string | ImportPreset): ImportPreset | null {\n if (typeof preset === 'string') {\n return builtinPresets[preset] || null;\n }\n return preset;\n}\n\n/**\n * Get all enabled presets from configuration\n */\nexport function resolvePresets(\n presets: Array<string | ImportPreset> | undefined\n): ImportPreset[] {\n if (!presets || presets.length === 0) {\n // Default presets when none specified\n return [vuePreset, vueRouterPreset];\n }\n\n const resolved: ImportPreset[] = [];\n\n for (const preset of presets) {\n const normalized = normalizePreset(preset);\n if (normalized) {\n resolved.push(normalized);\n }\n }\n\n return resolved;\n}\n","/**\n * @kimesh/auto-import - Import Registry Builder\n *\n * Builds a unified import registry from all layer sources.\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'pathe';\nimport { consola } from 'consola';\nimport { OxcExportScanner } from '../scanner/oxc-scanner';\nimport { ConflictResolver } from './conflict-resolver';\nimport { normalizePreset } from '../presets';\nimport { deriveLayerPrefix, resolveDirectory } from './utils';\nimport type {\n ImportEntry,\n ImportRegistry,\n LayerAutoImportSource,\n AutoImportConfig,\n ImportPreset,\n} from '../types';\n\nconst logger = consola.withTag('kimesh:auto-import:registry');\n\nconst DEFAULT_EXTENSIONS = ['.ts', '.js', '.tsx', '.jsx', '.mts', '.mjs'];\nconst COMPONENT_EXTENSIONS = ['.vue', ...DEFAULT_EXTENSIONS];\n\nexport class RegistryBuilder {\n private scanner = new OxcExportScanner();\n private resolver = new ConflictResolver();\n\n async build(sources: LayerAutoImportSource[]): Promise<ImportRegistry> {\n const startTime = performance.now();\n const sortedSources = [...sources].sort((a, b) => b.priority - a.priority);\n\n for (const source of sortedSources) {\n await this.processLayerSource(source);\n }\n\n const { resolved, conflicts } = this.resolver.resolve();\n const components = this.extractComponents(resolved);\n const scanTime = performance.now() - startTime;\n const stats = this.calculateStats(resolved, conflicts.length, scanTime);\n\n this.logBuildResults(stats, conflicts);\n\n return { imports: resolved, components, conflicts, stats };\n }\n\n private extractComponents(resolved: Map<string, ImportEntry>): Map<string, ImportEntry> {\n const components = new Map<string, ImportEntry>();\n for (const [name, entry] of resolved) {\n const isComponent = entry.type === 'component';\n const isPresetComponent = entry.type === 'preset' && /^[A-Z][a-zA-Z0-9]*$/.test(name);\n if (isComponent || isPresetComponent) {\n components.set(name, entry);\n }\n }\n return components;\n }\n\n private calculateStats(\n resolved: Map<string, ImportEntry>,\n conflictsCount: number,\n scanTimeMs: number\n ): ImportRegistry['stats'] {\n const entries = [...resolved.values()];\n return {\n totalScanned: this.scanner.getCacheStats().size,\n componentsCount: entries.filter((e) => e.type === 'component').length,\n composablesCount: entries.filter((e) => e.type === 'composable').length,\n utilitiesCount: entries.filter((e) => e.type === 'utility').length,\n presetsCount: entries.filter((e) => e.type === 'preset').length,\n conflictsCount,\n scanTimeMs,\n };\n }\n\n private logBuildResults(\n stats: ImportRegistry['stats'],\n conflicts: ImportRegistry['conflicts']\n ): void {\n logger.debug(`Built registry in ${stats.scanTimeMs.toFixed(1)}ms`);\n logger.debug(` Components: ${stats.componentsCount}`);\n logger.debug(` Composables: ${stats.composablesCount}`);\n logger.debug(` Utilities: ${stats.utilitiesCount}`);\n logger.debug(` Presets: ${stats.presetsCount}`);\n logger.debug(` Conflicts: ${stats.conflictsCount}`);\n\n for (const conflict of conflicts) {\n logger.warn(\n `Auto-import conflict for \"${conflict.name}\": ` +\n `Using ${conflict.winner.layer} (priority ${conflict.winner.priority}), ` +\n `ignoring ${conflict.losers.map((l) => l.layer).join(', ')}`\n );\n if (conflict.suggestion) {\n logger.info(` Suggestion: ${conflict.suggestion}`);\n }\n }\n }\n\n private async processLayerSource(source: LayerAutoImportSource): Promise<void> {\n const { layer, priority, layerPath, config } = source;\n\n logger.debug(`Processing layer: ${layer} (priority ${priority})`);\n\n await this.processPresets(config.presets ?? [], layer, priority);\n\n if (config.components) {\n await this.processComponents(config.components, layerPath, layer, priority);\n }\n if (config.composables) {\n const dirs = config.composables.dirs ?? ['composables'];\n const extensions = config.composables.extensions ?? DEFAULT_EXTENSIONS;\n await this.processDirectories(dirs, layerPath, layer, priority, 'composable', extensions);\n }\n if (config.utils) {\n const dirs = config.utils.dirs ?? ['utils'];\n const extensions = config.utils.extensions ?? DEFAULT_EXTENSIONS;\n await this.processDirectories(dirs, layerPath, layer, priority, 'utility', extensions);\n }\n if (config.stores) {\n const dirs = config.stores.dirs ?? ['stores'];\n await this.processDirectories(dirs, layerPath, layer, priority, 'store', DEFAULT_EXTENSIONS);\n }\n if (config.imports) {\n this.processAdditionalImports(config.imports, layer, priority);\n }\n }\n\n private async processPresets(\n presets: Array<string | ImportPreset>,\n layer: string,\n priority: number\n ): Promise<void> {\n for (const presetConfig of presets) {\n const preset = normalizePreset(presetConfig);\n if (!preset) continue;\n\n for (const importItem of preset.imports) {\n const name = typeof importItem === 'string' ? importItem : importItem.name;\n const isType = typeof importItem === 'object' && importItem.type === true;\n const alias = typeof importItem === 'object' ? importItem.as : undefined;\n\n this.resolver.addImport({\n name: alias ?? name,\n as: alias,\n from: preset.from,\n type: 'preset',\n layer,\n priority: priority + 0.5,\n isDefault: false,\n isType,\n });\n }\n }\n }\n\n private async processComponents(\n config: NonNullable<AutoImportConfig['components']>,\n layerPath: string,\n layer: string,\n priority: number\n ): Promise<void> {\n const dirs = config.dirs ?? ['components'];\n const extensions = config.extensions ?? COMPONENT_EXTENSIONS;\n const prefix = config.prefix;\n\n for (const dir of dirs) {\n const dirPath = resolveDirectory(layerPath, dir);\n if (!dirPath) continue;\n\n const files = this.scanDirectory(dirPath, extensions);\n const results = await this.scanner.scanFiles(files);\n\n for (const result of results) {\n for (const exp of result.exports) {\n if (!exp.isDefault) continue;\n\n const componentName = this.resolveComponentName(exp.name, prefix, layer);\n\n this.resolver.addImport({\n name: componentName,\n from: result.filePath,\n type: 'component',\n layer,\n priority,\n isDefault: true,\n isType: false,\n });\n\n if (componentName !== exp.name) {\n this.resolver.addImport({\n name: exp.name,\n from: result.filePath,\n type: 'component',\n layer,\n priority,\n isDefault: true,\n isType: false,\n });\n }\n }\n }\n }\n }\n\n private resolveComponentName(\n name: string,\n prefix: string | false | undefined,\n layer: string\n ): string {\n if (prefix !== false && prefix) {\n return `${prefix}${name}`;\n }\n if (layer !== 'app') {\n return `${deriveLayerPrefix(layer)}${name}`;\n }\n return name;\n }\n\n private async processDirectories(\n dirs: string[],\n layerPath: string,\n layer: string,\n priority: number,\n type: ImportEntry['type'],\n extensions: string[]\n ): Promise<void> {\n for (const dir of dirs) {\n const dirPath = resolveDirectory(layerPath, dir);\n if (!dirPath) continue;\n\n const files = this.scanDirectory(dirPath, extensions);\n const results = await this.scanner.scanFiles(files);\n\n for (const result of results) {\n for (const exp of result.exports) {\n this.resolver.addImport({\n name: exp.name,\n from: result.filePath,\n type,\n layer,\n priority,\n isDefault: exp.isDefault,\n isType: exp.isType,\n });\n }\n }\n }\n }\n\n private processAdditionalImports(\n imports: Array<{ from: string; imports: string[] }>,\n layer: string,\n priority: number\n ): void {\n for (const { from, imports: names } of imports) {\n for (const name of names) {\n this.resolver.addImport({\n name,\n from,\n type: 'utility',\n layer,\n priority,\n isDefault: false,\n isType: false,\n });\n }\n }\n }\n\n private scanDirectory(dirPath: string, extensions: string[]): string[] {\n const files: string[] = [];\n this.scanDirectoryRecursive(dirPath, extensions, files);\n return files;\n }\n\n private scanDirectoryRecursive(\n dir: string,\n extensions: string[],\n files: string[]\n ): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n this.scanDirectoryRecursive(fullPath, extensions, files);\n } else if (entry.isFile() && extensions.includes(path.extname(entry.name))) {\n files.push(fullPath);\n }\n }\n }\n\n invalidate(filePath: string): void {\n this.scanner.invalidate(filePath);\n }\n\n clearCache(): void {\n this.scanner.clearCache();\n this.resolver.clear();\n }\n}\n"],"mappings":"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"}
|