technical-debt-radar 1.7.1 → 1.8.0
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/index.js +123 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12889,6 +12889,7 @@ var require_boundary_checker = __commonJS({
|
|
|
12889
12889
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
12890
12890
|
exports2.checkBoundaries = checkBoundaries;
|
|
12891
12891
|
exports2._resetPathAliasCache = _resetPathAliasCache;
|
|
12892
|
+
exports2._resetModuleParsingCache = _resetModuleParsingCache;
|
|
12892
12893
|
var shared_1 = require_dist();
|
|
12893
12894
|
var minimatch_1 = require_commonjs3();
|
|
12894
12895
|
var ts_morph_1 = require("ts-morph");
|
|
@@ -13222,6 +13223,12 @@ var require_boundary_checker = __commonJS({
|
|
|
13222
13223
|
continue;
|
|
13223
13224
|
if (typeOnly)
|
|
13224
13225
|
continue;
|
|
13226
|
+
if (isNestJS) {
|
|
13227
|
+
const importedNames = getImportedNamesFromSpecifier(sourceFile, specifier);
|
|
13228
|
+
const suppressed = importedNames.length > 0 && importedNames.every((name) => isLegitimateNestJSModuleImport(sourceModule, targetModule, name, input));
|
|
13229
|
+
if (suppressed)
|
|
13230
|
+
continue;
|
|
13231
|
+
}
|
|
13225
13232
|
violations.push({
|
|
13226
13233
|
category: "architecture",
|
|
13227
13234
|
type: "module-boundary-violation",
|
|
@@ -13461,6 +13468,117 @@ var require_boundary_checker = __commonJS({
|
|
|
13461
13468
|
function _resetPathAliasCache() {
|
|
13462
13469
|
_cachedAliases = void 0;
|
|
13463
13470
|
}
|
|
13471
|
+
var _cachedModuleParsing;
|
|
13472
|
+
function parseNestJSModules(input) {
|
|
13473
|
+
if (_cachedModuleParsing)
|
|
13474
|
+
return _cachedModuleParsing;
|
|
13475
|
+
const result = /* @__PURE__ */ new Map();
|
|
13476
|
+
const project = new ts_morph_1.Project({ useInMemoryFileSystem: true });
|
|
13477
|
+
for (const file of input.changedFiles) {
|
|
13478
|
+
if (file.status === "deleted")
|
|
13479
|
+
continue;
|
|
13480
|
+
if (!/\.module\.(ts|js)$/.test(file.path))
|
|
13481
|
+
continue;
|
|
13482
|
+
const sf = project.createSourceFile(file.path, file.content);
|
|
13483
|
+
for (const cls of sf.getClasses()) {
|
|
13484
|
+
const moduleDecorator = cls.getDecorators().find((d) => d.getName() === "Module");
|
|
13485
|
+
if (!moduleDecorator)
|
|
13486
|
+
continue;
|
|
13487
|
+
const className = cls.getName() ?? "";
|
|
13488
|
+
const pathMatch = file.path.match(/src\/([^/]+)\//);
|
|
13489
|
+
const moduleName = pathMatch ? pathMatch[1] : "";
|
|
13490
|
+
if (!moduleName)
|
|
13491
|
+
continue;
|
|
13492
|
+
const callExpr = moduleDecorator.getCallExpression?.();
|
|
13493
|
+
if (!callExpr)
|
|
13494
|
+
continue;
|
|
13495
|
+
const args = callExpr.getArguments();
|
|
13496
|
+
if (args.length === 0 || !ts_morph_1.Node.isObjectLiteralExpression(args[0]))
|
|
13497
|
+
continue;
|
|
13498
|
+
const objLit = args[0];
|
|
13499
|
+
const imports = [];
|
|
13500
|
+
const exports3 = [];
|
|
13501
|
+
const hasForwardRef = /* @__PURE__ */ new Map();
|
|
13502
|
+
const importsProp = objLit.getProperty("imports");
|
|
13503
|
+
if (importsProp && ts_morph_1.Node.isPropertyAssignment(importsProp)) {
|
|
13504
|
+
const init = importsProp.getInitializer();
|
|
13505
|
+
if (init && ts_morph_1.Node.isArrayLiteralExpression(init)) {
|
|
13506
|
+
for (const el of init.getElements()) {
|
|
13507
|
+
if (ts_morph_1.Node.isIdentifier(el)) {
|
|
13508
|
+
imports.push(el.getText());
|
|
13509
|
+
hasForwardRef.set(el.getText(), false);
|
|
13510
|
+
} else if (ts_morph_1.Node.isCallExpression(el)) {
|
|
13511
|
+
const callText = el.getText();
|
|
13512
|
+
const fwdMatch = callText.match(/forwardRef\s*\(\s*\(\)\s*=>\s*(\w+)\s*\)/);
|
|
13513
|
+
if (fwdMatch) {
|
|
13514
|
+
imports.push(fwdMatch[1]);
|
|
13515
|
+
hasForwardRef.set(fwdMatch[1], true);
|
|
13516
|
+
} else {
|
|
13517
|
+
const expr = el.getExpression();
|
|
13518
|
+
if (ts_morph_1.Node.isPropertyAccessExpression(expr)) {
|
|
13519
|
+
const obj = expr.getExpression();
|
|
13520
|
+
if (ts_morph_1.Node.isIdentifier(obj)) {
|
|
13521
|
+
imports.push(obj.getText());
|
|
13522
|
+
hasForwardRef.set(obj.getText(), false);
|
|
13523
|
+
}
|
|
13524
|
+
}
|
|
13525
|
+
}
|
|
13526
|
+
}
|
|
13527
|
+
}
|
|
13528
|
+
}
|
|
13529
|
+
}
|
|
13530
|
+
const exportsProp = objLit.getProperty("exports");
|
|
13531
|
+
if (exportsProp && ts_morph_1.Node.isPropertyAssignment(exportsProp)) {
|
|
13532
|
+
const init = exportsProp.getInitializer();
|
|
13533
|
+
if (init && ts_morph_1.Node.isArrayLiteralExpression(init)) {
|
|
13534
|
+
for (const el of init.getElements()) {
|
|
13535
|
+
if (ts_morph_1.Node.isIdentifier(el)) {
|
|
13536
|
+
exports3.push(el.getText());
|
|
13537
|
+
}
|
|
13538
|
+
}
|
|
13539
|
+
}
|
|
13540
|
+
}
|
|
13541
|
+
result.set(moduleName, { moduleName, className, imports, exports: exports3, hasForwardRef });
|
|
13542
|
+
}
|
|
13543
|
+
project.removeSourceFile(sf);
|
|
13544
|
+
}
|
|
13545
|
+
_cachedModuleParsing = result;
|
|
13546
|
+
return result;
|
|
13547
|
+
}
|
|
13548
|
+
function getImportedNamesFromSpecifier(sourceFile, specifier) {
|
|
13549
|
+
const names = [];
|
|
13550
|
+
for (const decl of sourceFile.getImportDeclarations()) {
|
|
13551
|
+
if (decl.getModuleSpecifierValue() !== specifier)
|
|
13552
|
+
continue;
|
|
13553
|
+
const defaultImport = decl.getDefaultImport();
|
|
13554
|
+
if (defaultImport)
|
|
13555
|
+
names.push(defaultImport.getText());
|
|
13556
|
+
for (const named of decl.getNamedImports()) {
|
|
13557
|
+
names.push(named.getName());
|
|
13558
|
+
}
|
|
13559
|
+
}
|
|
13560
|
+
return names;
|
|
13561
|
+
}
|
|
13562
|
+
function isLegitimateNestJSModuleImport(sourceModuleName, targetModuleName, importedClassName, input) {
|
|
13563
|
+
const modules = parseNestJSModules(input);
|
|
13564
|
+
const importingMod = modules.get(sourceModuleName);
|
|
13565
|
+
if (!importingMod)
|
|
13566
|
+
return false;
|
|
13567
|
+
const targetMod = modules.get(targetModuleName);
|
|
13568
|
+
if (!targetMod)
|
|
13569
|
+
return false;
|
|
13570
|
+
const targetClassName = targetMod.className;
|
|
13571
|
+
if (!importingMod.imports.includes(targetClassName))
|
|
13572
|
+
return false;
|
|
13573
|
+
if (importingMod.hasForwardRef.get(targetClassName))
|
|
13574
|
+
return false;
|
|
13575
|
+
if (!targetMod.exports.includes(importedClassName))
|
|
13576
|
+
return false;
|
|
13577
|
+
return true;
|
|
13578
|
+
}
|
|
13579
|
+
function _resetModuleParsingCache() {
|
|
13580
|
+
_cachedModuleParsing = void 0;
|
|
13581
|
+
}
|
|
13464
13582
|
function normalizeForMatching(filePath) {
|
|
13465
13583
|
let normalized = filePath.replace(/\\/g, "/");
|
|
13466
13584
|
if (normalized.startsWith("/")) {
|
|
@@ -19209,7 +19327,10 @@ var require_dead_code_detector = __commonJS({
|
|
|
19209
19327
|
for (const [otherFilePath, otherText] of allFileTexts) {
|
|
19210
19328
|
if (otherFilePath === filePath)
|
|
19211
19329
|
continue;
|
|
19212
|
-
if (callPattern.test(otherText))
|
|
19330
|
+
if (!callPattern.test(otherText))
|
|
19331
|
+
continue;
|
|
19332
|
+
const importPattern = new RegExp(`import\\s+.*\\b${className}\\b.*from\\s+`);
|
|
19333
|
+
if (importPattern.test(otherText)) {
|
|
19213
19334
|
hasExternalCall = true;
|
|
19214
19335
|
break;
|
|
19215
19336
|
}
|
|
@@ -19650,7 +19771,7 @@ var require_orchestrator = __commonJS({
|
|
|
19650
19771
|
(0, reliability_detector_1.detectReliabilityIssues)(filteredInput, policy),
|
|
19651
19772
|
(0, duplication_detector_1.detectDuplication)(filteredInput),
|
|
19652
19773
|
projectRoot ? (0, missing_tests_detector_1.detectMissingTests)(filteredInput, projectRoot, buildMissingTestsConfig(policy)) : Promise.resolve(null),
|
|
19653
|
-
(0, dead_code_detector_1.detectDeadCode)(filteredInput, {}, projectRoot),
|
|
19774
|
+
(0, dead_code_detector_1.detectDeadCode)(filteredInput, { excludeBarrels: false, excludeTypes: false }, projectRoot),
|
|
19654
19775
|
projectRoot ? Promise.resolve((0, coverage_delta_detector_1.detectCoverageDelta)(projectRoot)) : Promise.resolve(null)
|
|
19655
19776
|
]);
|
|
19656
19777
|
const runtimeViolations = runtimeResult.violations;
|