wireweaver 0.1.0 → 0.1.2
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/dist/vite-plugin.cjs +123 -33
- package/dist/vite-plugin.js +124 -34
- package/package.json +2 -1
package/dist/vite-plugin.cjs
CHANGED
|
@@ -287,18 +287,74 @@ function discoverBeanRegistrations(root, implementations, extraScanDirs = []) {
|
|
|
287
287
|
return result;
|
|
288
288
|
}
|
|
289
289
|
function collectBeanRegistrationsFromDir(root, implementations, result, allowNodeModules) {
|
|
290
|
-
const
|
|
291
|
-
if (!tsconfigPath) return;
|
|
292
|
-
const configFile = import_typescript.default.readConfigFile(tsconfigPath, import_typescript.default.sys.readFile);
|
|
293
|
-
if (configFile.error) return;
|
|
294
|
-
const parsedConfig = import_typescript.default.parseJsonConfigFileContent(configFile.config, import_typescript.default.sys, getDirName(tsconfigPath));
|
|
295
|
-
const program = import_typescript.default.createProgram({ rootNames: parsedConfig.fileNames, options: parsedConfig.options });
|
|
296
|
-
for (const sourceFile of program.getSourceFiles()) {
|
|
297
|
-
if (sourceFile.isDeclarationFile) continue;
|
|
298
|
-
if (!allowNodeModules && sourceFile.fileName.includes("/node_modules/")) continue;
|
|
290
|
+
for (const sourceFile of getScanSourceFiles(root, allowNodeModules)) {
|
|
299
291
|
collectBeanRegistrationsFromFile(sourceFile, sourceFile.fileName, implementations, result);
|
|
300
292
|
}
|
|
301
293
|
}
|
|
294
|
+
function getScanSourceFiles(root, allowNodeModules) {
|
|
295
|
+
const tsconfigPath = allowNodeModules ? findTsconfigWithin(root) : import_typescript.default.findConfigFile(root, import_typescript.default.sys.fileExists, "tsconfig.json");
|
|
296
|
+
if (tsconfigPath) {
|
|
297
|
+
const configFile = import_typescript.default.readConfigFile(tsconfigPath, import_typescript.default.sys.readFile);
|
|
298
|
+
if (configFile.error) return [];
|
|
299
|
+
const parsedConfig = import_typescript.default.parseJsonConfigFileContent(configFile.config, import_typescript.default.sys, getDirName(tsconfigPath));
|
|
300
|
+
const program = import_typescript.default.createProgram({ rootNames: parsedConfig.fileNames, options: parsedConfig.options });
|
|
301
|
+
const files = [];
|
|
302
|
+
for (const sourceFile of program.getSourceFiles()) {
|
|
303
|
+
if (!allowNodeModules && sourceFile.isDeclarationFile) continue;
|
|
304
|
+
if (!allowNodeModules && sourceFile.fileName.includes("/node_modules/")) continue;
|
|
305
|
+
files.push(sourceFile);
|
|
306
|
+
}
|
|
307
|
+
return files;
|
|
308
|
+
}
|
|
309
|
+
if (!allowNodeModules) return [];
|
|
310
|
+
return parseSourceFilesInDir(root);
|
|
311
|
+
}
|
|
312
|
+
function findTsconfigWithin(dir) {
|
|
313
|
+
const candidate = (0, import_node_path.join)(dir, "tsconfig.json");
|
|
314
|
+
return (0, import_node_fs.existsSync)(candidate) ? candidate : void 0;
|
|
315
|
+
}
|
|
316
|
+
function parseSourceFilesInDir(dir) {
|
|
317
|
+
const sourceFiles = [];
|
|
318
|
+
function walk(current) {
|
|
319
|
+
let names;
|
|
320
|
+
try {
|
|
321
|
+
names = (0, import_node_fs.readdirSync)(current);
|
|
322
|
+
} catch {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
for (const name of names) {
|
|
326
|
+
const fullPath = (0, import_node_path.join)(current, name);
|
|
327
|
+
let isDir = false;
|
|
328
|
+
try {
|
|
329
|
+
isDir = (0, import_node_fs.statSync)(fullPath).isDirectory();
|
|
330
|
+
} catch {
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
if (isDir) {
|
|
334
|
+
if (name === "node_modules") continue;
|
|
335
|
+
walk(fullPath);
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
if (!/\.(ts|tsx)$/.test(name)) continue;
|
|
339
|
+
try {
|
|
340
|
+
const content = (0, import_node_fs.readFileSync)(fullPath, "utf-8");
|
|
341
|
+
sourceFiles.push(
|
|
342
|
+
import_typescript.default.createSourceFile(
|
|
343
|
+
fullPath,
|
|
344
|
+
content,
|
|
345
|
+
import_typescript.default.ScriptTarget.Latest,
|
|
346
|
+
/* setParentNodes */
|
|
347
|
+
true,
|
|
348
|
+
import_typescript.default.ScriptKind.TS
|
|
349
|
+
)
|
|
350
|
+
);
|
|
351
|
+
} catch {
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
walk(dir);
|
|
356
|
+
return sourceFiles;
|
|
357
|
+
}
|
|
302
358
|
function collectBeanRegistrationsFromFile(sourceFile, filePath, globalImplementations, result) {
|
|
303
359
|
const localImpls = discoverLocalImplementations(sourceFile, filePath);
|
|
304
360
|
const typeOnlySymbols = collectTypeOnlySymbols(sourceFile);
|
|
@@ -339,7 +395,8 @@ function discoverInterfaceImplementations(root, extraScanDirs = []) {
|
|
|
339
395
|
scanSourceFilesForImplementations(root, implementations, allClassHeritage, beanReturnTypes, false);
|
|
340
396
|
for (const dir of extraScanDirs) {
|
|
341
397
|
const packageRoot = findPackageRoot(dir);
|
|
342
|
-
|
|
398
|
+
const componentNames = collectComponentClassNames(dir);
|
|
399
|
+
scanSourceFilesForImplementations(dir, implementations, allClassHeritage, beanReturnTypes, true, packageRoot, componentNames);
|
|
343
400
|
}
|
|
344
401
|
for (const typeName of beanReturnTypes) {
|
|
345
402
|
const entries = allClassHeritage.get(typeName);
|
|
@@ -355,23 +412,8 @@ function discoverInterfaceImplementations(root, extraScanDirs = []) {
|
|
|
355
412
|
}
|
|
356
413
|
return implementations;
|
|
357
414
|
}
|
|
358
|
-
function scanSourceFilesForImplementations(root, implementations, allClassHeritage, beanReturnTypes, allowNodeModules, packageRoot) {
|
|
359
|
-
const
|
|
360
|
-
if (!tsconfigPath) return;
|
|
361
|
-
const configFile = import_typescript.default.readConfigFile(tsconfigPath, import_typescript.default.sys.readFile);
|
|
362
|
-
if (configFile.error) return;
|
|
363
|
-
const parsedConfig = import_typescript.default.parseJsonConfigFileContent(
|
|
364
|
-
configFile.config,
|
|
365
|
-
import_typescript.default.sys,
|
|
366
|
-
getDirName(tsconfigPath)
|
|
367
|
-
);
|
|
368
|
-
const program = import_typescript.default.createProgram({
|
|
369
|
-
rootNames: parsedConfig.fileNames,
|
|
370
|
-
options: parsedConfig.options
|
|
371
|
-
});
|
|
372
|
-
for (const sourceFile of program.getSourceFiles()) {
|
|
373
|
-
if (sourceFile.isDeclarationFile) continue;
|
|
374
|
-
if (!allowNodeModules && sourceFile.fileName.includes("/node_modules/")) continue;
|
|
415
|
+
function scanSourceFilesForImplementations(root, implementations, allClassHeritage, beanReturnTypes, allowNodeModules, packageRoot, componentNames = /* @__PURE__ */ new Set()) {
|
|
416
|
+
for (const sourceFile of getScanSourceFiles(root, allowNodeModules)) {
|
|
375
417
|
import_typescript.default.forEachChild(sourceFile, (node) => {
|
|
376
418
|
if (import_typescript.default.isClassDeclaration(node) && node.name) {
|
|
377
419
|
const importSpecifier = packageRoot ? resolvePackageImportSpecifier(node.name.text, packageRoot) : void 0;
|
|
@@ -385,7 +427,7 @@ function scanSourceFilesForImplementations(root, implementations, allClassHerita
|
|
|
385
427
|
heritageEntries.push({ interfaceName, filePath: sourceFile.fileName, importSpecifier });
|
|
386
428
|
allClassHeritage.set(node.name.text, heritageEntries);
|
|
387
429
|
}
|
|
388
|
-
if (!hasServiceDecorator(node)) continue;
|
|
430
|
+
if (!hasServiceDecorator(node) && !componentNames.has(node.name.text)) continue;
|
|
389
431
|
const existing = implementations.get(interfaceName) ?? [];
|
|
390
432
|
if (existing.some((impl) => impl.className === node.name.text && normalizeFilePath(impl.filePath) === normalizeFilePath(sourceFile.fileName))) {
|
|
391
433
|
continue;
|
|
@@ -496,14 +538,17 @@ function buildImportInsertions(code, sourceFile, importsToInject, sideEffectImpo
|
|
|
496
538
|
if (unresolved.length === 0) continue;
|
|
497
539
|
const existing = findImportByModule(sourceFile, importPath);
|
|
498
540
|
if (existing && existing.importClause?.namedBindings && import_typescript.default.isNamedImports(existing.importClause.namedBindings)) {
|
|
499
|
-
const
|
|
541
|
+
const namedImports = existing.importClause.namedBindings;
|
|
542
|
+
const existingNames = new Set(namedImports.elements.map((element) => element.name.text));
|
|
500
543
|
const missing = unresolved.filter((name) => !existingNames.has(name));
|
|
501
544
|
if (missing.length === 0) continue;
|
|
502
|
-
const
|
|
545
|
+
const hasElements = namedImports.elements.length > 0;
|
|
546
|
+
const insertionPoint2 = namedImports.getEnd() - 1;
|
|
547
|
+
const prefix = hasElements ? ", " : "";
|
|
503
548
|
replacements.push({
|
|
504
|
-
start:
|
|
505
|
-
end:
|
|
506
|
-
text: `${
|
|
549
|
+
start: insertionPoint2,
|
|
550
|
+
end: insertionPoint2,
|
|
551
|
+
text: `${prefix}${missing.sort().join(", ")}`
|
|
507
552
|
});
|
|
508
553
|
continue;
|
|
509
554
|
}
|
|
@@ -610,6 +655,51 @@ function resolveExtraScanDirs(root, extraScanDirs) {
|
|
|
610
655
|
if (!extraScanDirs || extraScanDirs.length === 0) return [];
|
|
611
656
|
return extraScanDirs.map((dir) => (0, import_node_path.isAbsolute)(dir) ? dir : (0, import_node_path.resolve)(root, dir));
|
|
612
657
|
}
|
|
658
|
+
function collectComponentClassNames(dir) {
|
|
659
|
+
const names = /* @__PURE__ */ new Set();
|
|
660
|
+
const stage3 = /_([A-Za-z_$][\w$]*)_decorators\s*=\s*\[([^\]]*)\]/g;
|
|
661
|
+
const legacy = /__decorate\(\s*\[([^\]]*?)\]\s*,\s*([A-Za-z_$][\w$]*)/g;
|
|
662
|
+
function containsComponentDecorator(decoratorList) {
|
|
663
|
+
return /\b(Component|Service)\s*\(/.test(decoratorList);
|
|
664
|
+
}
|
|
665
|
+
function walk(current) {
|
|
666
|
+
let entries;
|
|
667
|
+
try {
|
|
668
|
+
entries = (0, import_node_fs.readdirSync)(current);
|
|
669
|
+
} catch {
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
for (const name of entries) {
|
|
673
|
+
const fullPath = (0, import_node_path.join)(current, name);
|
|
674
|
+
let isDir = false;
|
|
675
|
+
try {
|
|
676
|
+
isDir = (0, import_node_fs.statSync)(fullPath).isDirectory();
|
|
677
|
+
} catch {
|
|
678
|
+
continue;
|
|
679
|
+
}
|
|
680
|
+
if (isDir) {
|
|
681
|
+
if (name === "node_modules") continue;
|
|
682
|
+
walk(fullPath);
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
685
|
+
if (!/\.(js|cjs|mjs)$/.test(name)) continue;
|
|
686
|
+
let content;
|
|
687
|
+
try {
|
|
688
|
+
content = (0, import_node_fs.readFileSync)(fullPath, "utf-8");
|
|
689
|
+
} catch {
|
|
690
|
+
continue;
|
|
691
|
+
}
|
|
692
|
+
for (const match of content.matchAll(stage3)) {
|
|
693
|
+
if (containsComponentDecorator(match[2])) names.add(match[1]);
|
|
694
|
+
}
|
|
695
|
+
for (const match of content.matchAll(legacy)) {
|
|
696
|
+
if (containsComponentDecorator(match[1])) names.add(match[2]);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
walk(dir);
|
|
701
|
+
return names;
|
|
702
|
+
}
|
|
613
703
|
function findPackageRoot(startDir) {
|
|
614
704
|
let current = startDir;
|
|
615
705
|
while (true) {
|
package/dist/vite-plugin.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import ts from "typescript";
|
|
3
3
|
import { readFile } from "fs/promises";
|
|
4
4
|
import { isAbsolute, resolve as resolvePath, join as joinPath, dirname } from "path";
|
|
5
|
-
import { existsSync, readFileSync } from "fs";
|
|
5
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "fs";
|
|
6
6
|
function wireWeaverPlugin(options = {}) {
|
|
7
7
|
let implementations = /* @__PURE__ */ new Map();
|
|
8
8
|
let beanRegistrations = /* @__PURE__ */ new Map();
|
|
@@ -250,18 +250,74 @@ function discoverBeanRegistrations(root, implementations, extraScanDirs = []) {
|
|
|
250
250
|
return result;
|
|
251
251
|
}
|
|
252
252
|
function collectBeanRegistrationsFromDir(root, implementations, result, allowNodeModules) {
|
|
253
|
-
const
|
|
254
|
-
if (!tsconfigPath) return;
|
|
255
|
-
const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
|
|
256
|
-
if (configFile.error) return;
|
|
257
|
-
const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, getDirName(tsconfigPath));
|
|
258
|
-
const program = ts.createProgram({ rootNames: parsedConfig.fileNames, options: parsedConfig.options });
|
|
259
|
-
for (const sourceFile of program.getSourceFiles()) {
|
|
260
|
-
if (sourceFile.isDeclarationFile) continue;
|
|
261
|
-
if (!allowNodeModules && sourceFile.fileName.includes("/node_modules/")) continue;
|
|
253
|
+
for (const sourceFile of getScanSourceFiles(root, allowNodeModules)) {
|
|
262
254
|
collectBeanRegistrationsFromFile(sourceFile, sourceFile.fileName, implementations, result);
|
|
263
255
|
}
|
|
264
256
|
}
|
|
257
|
+
function getScanSourceFiles(root, allowNodeModules) {
|
|
258
|
+
const tsconfigPath = allowNodeModules ? findTsconfigWithin(root) : ts.findConfigFile(root, ts.sys.fileExists, "tsconfig.json");
|
|
259
|
+
if (tsconfigPath) {
|
|
260
|
+
const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
|
|
261
|
+
if (configFile.error) return [];
|
|
262
|
+
const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, getDirName(tsconfigPath));
|
|
263
|
+
const program = ts.createProgram({ rootNames: parsedConfig.fileNames, options: parsedConfig.options });
|
|
264
|
+
const files = [];
|
|
265
|
+
for (const sourceFile of program.getSourceFiles()) {
|
|
266
|
+
if (!allowNodeModules && sourceFile.isDeclarationFile) continue;
|
|
267
|
+
if (!allowNodeModules && sourceFile.fileName.includes("/node_modules/")) continue;
|
|
268
|
+
files.push(sourceFile);
|
|
269
|
+
}
|
|
270
|
+
return files;
|
|
271
|
+
}
|
|
272
|
+
if (!allowNodeModules) return [];
|
|
273
|
+
return parseSourceFilesInDir(root);
|
|
274
|
+
}
|
|
275
|
+
function findTsconfigWithin(dir) {
|
|
276
|
+
const candidate = joinPath(dir, "tsconfig.json");
|
|
277
|
+
return existsSync(candidate) ? candidate : void 0;
|
|
278
|
+
}
|
|
279
|
+
function parseSourceFilesInDir(dir) {
|
|
280
|
+
const sourceFiles = [];
|
|
281
|
+
function walk(current) {
|
|
282
|
+
let names;
|
|
283
|
+
try {
|
|
284
|
+
names = readdirSync(current);
|
|
285
|
+
} catch {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
for (const name of names) {
|
|
289
|
+
const fullPath = joinPath(current, name);
|
|
290
|
+
let isDir = false;
|
|
291
|
+
try {
|
|
292
|
+
isDir = statSync(fullPath).isDirectory();
|
|
293
|
+
} catch {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
if (isDir) {
|
|
297
|
+
if (name === "node_modules") continue;
|
|
298
|
+
walk(fullPath);
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
if (!/\.(ts|tsx)$/.test(name)) continue;
|
|
302
|
+
try {
|
|
303
|
+
const content = readFileSync(fullPath, "utf-8");
|
|
304
|
+
sourceFiles.push(
|
|
305
|
+
ts.createSourceFile(
|
|
306
|
+
fullPath,
|
|
307
|
+
content,
|
|
308
|
+
ts.ScriptTarget.Latest,
|
|
309
|
+
/* setParentNodes */
|
|
310
|
+
true,
|
|
311
|
+
ts.ScriptKind.TS
|
|
312
|
+
)
|
|
313
|
+
);
|
|
314
|
+
} catch {
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
walk(dir);
|
|
319
|
+
return sourceFiles;
|
|
320
|
+
}
|
|
265
321
|
function collectBeanRegistrationsFromFile(sourceFile, filePath, globalImplementations, result) {
|
|
266
322
|
const localImpls = discoverLocalImplementations(sourceFile, filePath);
|
|
267
323
|
const typeOnlySymbols = collectTypeOnlySymbols(sourceFile);
|
|
@@ -302,7 +358,8 @@ function discoverInterfaceImplementations(root, extraScanDirs = []) {
|
|
|
302
358
|
scanSourceFilesForImplementations(root, implementations, allClassHeritage, beanReturnTypes, false);
|
|
303
359
|
for (const dir of extraScanDirs) {
|
|
304
360
|
const packageRoot = findPackageRoot(dir);
|
|
305
|
-
|
|
361
|
+
const componentNames = collectComponentClassNames(dir);
|
|
362
|
+
scanSourceFilesForImplementations(dir, implementations, allClassHeritage, beanReturnTypes, true, packageRoot, componentNames);
|
|
306
363
|
}
|
|
307
364
|
for (const typeName of beanReturnTypes) {
|
|
308
365
|
const entries = allClassHeritage.get(typeName);
|
|
@@ -318,23 +375,8 @@ function discoverInterfaceImplementations(root, extraScanDirs = []) {
|
|
|
318
375
|
}
|
|
319
376
|
return implementations;
|
|
320
377
|
}
|
|
321
|
-
function scanSourceFilesForImplementations(root, implementations, allClassHeritage, beanReturnTypes, allowNodeModules, packageRoot) {
|
|
322
|
-
const
|
|
323
|
-
if (!tsconfigPath) return;
|
|
324
|
-
const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
|
|
325
|
-
if (configFile.error) return;
|
|
326
|
-
const parsedConfig = ts.parseJsonConfigFileContent(
|
|
327
|
-
configFile.config,
|
|
328
|
-
ts.sys,
|
|
329
|
-
getDirName(tsconfigPath)
|
|
330
|
-
);
|
|
331
|
-
const program = ts.createProgram({
|
|
332
|
-
rootNames: parsedConfig.fileNames,
|
|
333
|
-
options: parsedConfig.options
|
|
334
|
-
});
|
|
335
|
-
for (const sourceFile of program.getSourceFiles()) {
|
|
336
|
-
if (sourceFile.isDeclarationFile) continue;
|
|
337
|
-
if (!allowNodeModules && sourceFile.fileName.includes("/node_modules/")) continue;
|
|
378
|
+
function scanSourceFilesForImplementations(root, implementations, allClassHeritage, beanReturnTypes, allowNodeModules, packageRoot, componentNames = /* @__PURE__ */ new Set()) {
|
|
379
|
+
for (const sourceFile of getScanSourceFiles(root, allowNodeModules)) {
|
|
338
380
|
ts.forEachChild(sourceFile, (node) => {
|
|
339
381
|
if (ts.isClassDeclaration(node) && node.name) {
|
|
340
382
|
const importSpecifier = packageRoot ? resolvePackageImportSpecifier(node.name.text, packageRoot) : void 0;
|
|
@@ -348,7 +390,7 @@ function scanSourceFilesForImplementations(root, implementations, allClassHerita
|
|
|
348
390
|
heritageEntries.push({ interfaceName, filePath: sourceFile.fileName, importSpecifier });
|
|
349
391
|
allClassHeritage.set(node.name.text, heritageEntries);
|
|
350
392
|
}
|
|
351
|
-
if (!hasServiceDecorator(node)) continue;
|
|
393
|
+
if (!hasServiceDecorator(node) && !componentNames.has(node.name.text)) continue;
|
|
352
394
|
const existing = implementations.get(interfaceName) ?? [];
|
|
353
395
|
if (existing.some((impl) => impl.className === node.name.text && normalizeFilePath(impl.filePath) === normalizeFilePath(sourceFile.fileName))) {
|
|
354
396
|
continue;
|
|
@@ -459,14 +501,17 @@ function buildImportInsertions(code, sourceFile, importsToInject, sideEffectImpo
|
|
|
459
501
|
if (unresolved.length === 0) continue;
|
|
460
502
|
const existing = findImportByModule(sourceFile, importPath);
|
|
461
503
|
if (existing && existing.importClause?.namedBindings && ts.isNamedImports(existing.importClause.namedBindings)) {
|
|
462
|
-
const
|
|
504
|
+
const namedImports = existing.importClause.namedBindings;
|
|
505
|
+
const existingNames = new Set(namedImports.elements.map((element) => element.name.text));
|
|
463
506
|
const missing = unresolved.filter((name) => !existingNames.has(name));
|
|
464
507
|
if (missing.length === 0) continue;
|
|
465
|
-
const
|
|
508
|
+
const hasElements = namedImports.elements.length > 0;
|
|
509
|
+
const insertionPoint2 = namedImports.getEnd() - 1;
|
|
510
|
+
const prefix = hasElements ? ", " : "";
|
|
466
511
|
replacements.push({
|
|
467
|
-
start:
|
|
468
|
-
end:
|
|
469
|
-
text: `${
|
|
512
|
+
start: insertionPoint2,
|
|
513
|
+
end: insertionPoint2,
|
|
514
|
+
text: `${prefix}${missing.sort().join(", ")}`
|
|
470
515
|
});
|
|
471
516
|
continue;
|
|
472
517
|
}
|
|
@@ -573,6 +618,51 @@ function resolveExtraScanDirs(root, extraScanDirs) {
|
|
|
573
618
|
if (!extraScanDirs || extraScanDirs.length === 0) return [];
|
|
574
619
|
return extraScanDirs.map((dir) => isAbsolute(dir) ? dir : resolvePath(root, dir));
|
|
575
620
|
}
|
|
621
|
+
function collectComponentClassNames(dir) {
|
|
622
|
+
const names = /* @__PURE__ */ new Set();
|
|
623
|
+
const stage3 = /_([A-Za-z_$][\w$]*)_decorators\s*=\s*\[([^\]]*)\]/g;
|
|
624
|
+
const legacy = /__decorate\(\s*\[([^\]]*?)\]\s*,\s*([A-Za-z_$][\w$]*)/g;
|
|
625
|
+
function containsComponentDecorator(decoratorList) {
|
|
626
|
+
return /\b(Component|Service)\s*\(/.test(decoratorList);
|
|
627
|
+
}
|
|
628
|
+
function walk(current) {
|
|
629
|
+
let entries;
|
|
630
|
+
try {
|
|
631
|
+
entries = readdirSync(current);
|
|
632
|
+
} catch {
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
for (const name of entries) {
|
|
636
|
+
const fullPath = joinPath(current, name);
|
|
637
|
+
let isDir = false;
|
|
638
|
+
try {
|
|
639
|
+
isDir = statSync(fullPath).isDirectory();
|
|
640
|
+
} catch {
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
if (isDir) {
|
|
644
|
+
if (name === "node_modules") continue;
|
|
645
|
+
walk(fullPath);
|
|
646
|
+
continue;
|
|
647
|
+
}
|
|
648
|
+
if (!/\.(js|cjs|mjs)$/.test(name)) continue;
|
|
649
|
+
let content;
|
|
650
|
+
try {
|
|
651
|
+
content = readFileSync(fullPath, "utf-8");
|
|
652
|
+
} catch {
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
655
|
+
for (const match of content.matchAll(stage3)) {
|
|
656
|
+
if (containsComponentDecorator(match[2])) names.add(match[1]);
|
|
657
|
+
}
|
|
658
|
+
for (const match of content.matchAll(legacy)) {
|
|
659
|
+
if (containsComponentDecorator(match[1])) names.add(match[2]);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
walk(dir);
|
|
664
|
+
return names;
|
|
665
|
+
}
|
|
576
666
|
function findPackageRoot(startDir) {
|
|
577
667
|
let current = startDir;
|
|
578
668
|
while (true) {
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "wireweaver",
|
|
3
3
|
"description": "A lightweight TypeScript Dependency Injection Library",
|
|
4
4
|
"productName": "WireWeaver",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.2",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.cjs",
|
|
8
8
|
"module": "./dist/index.js",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build": "tsup",
|
|
27
|
+
"ver": "npm --no-git-tag-version version",
|
|
27
28
|
"build:dev": "tsc -p tsconfig.build.json",
|
|
28
29
|
"test": "vitest run"
|
|
29
30
|
},
|