@solid-stack/mason 1.0.29 → 1.0.31
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/bin.cjs +64 -3
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +64 -3
- package/dist/bin.js.map +1 -1
- package/dist/core/lintEngine.d.ts +1 -0
- package/dist/core/lintEngine.d.ts.map +1 -1
- package/dist/index.cjs +64 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +64 -3
- package/dist/index.js.map +1 -1
- package/dist/types/lint.d.ts +1 -1
- package/dist/types/lint.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -4913,14 +4913,19 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot) {
|
|
|
4913
4913
|
resolvedRel = specifier.replace(/^[@~]\//, "src/");
|
|
4914
4914
|
} else if (specifier.startsWith("@shared/")) {
|
|
4915
4915
|
resolvedRel = "src/" + specifier.slice(1);
|
|
4916
|
+
} else if (specifier.startsWith("@/configs/") || specifier.startsWith("~/configs/") || specifier === "@/configs" || specifier === "~/configs") {
|
|
4917
|
+
resolvedRel = specifier.replace(/^[@~]\//, "src/");
|
|
4918
|
+
} else if (specifier === "@configs" || specifier.startsWith("@configs/")) {
|
|
4919
|
+
resolvedRel = "src/" + specifier.slice(1);
|
|
4916
4920
|
} else if (specifier.startsWith("@/") || specifier.startsWith("~/")) {
|
|
4917
4921
|
resolvedRel = "src/" + specifier.slice(2);
|
|
4918
|
-
} else if (specifier.startsWith("features/") || specifier.startsWith("shared/")) {
|
|
4922
|
+
} else if (specifier.startsWith("features/") || specifier.startsWith("shared/") || specifier.startsWith("configs/") || specifier === "configs") {
|
|
4919
4923
|
resolvedRel = specifier;
|
|
4920
4924
|
}
|
|
4921
4925
|
if (!resolvedRel) {
|
|
4922
4926
|
return { isExternal: true, isDiFramework: false };
|
|
4923
4927
|
}
|
|
4928
|
+
const isGlobalConfig = resolvedRel.startsWith("src/configs/") || resolvedRel === "src/configs" || resolvedRel.startsWith("configs/") || resolvedRel === "configs";
|
|
4924
4929
|
const featMatch = resolvedRel.match(/(?:^|\/)(?:src\/)?features\/([^/]+)\/([^/]+)(?:\/(.*))?$/);
|
|
4925
4930
|
if (featMatch && featMatch[1] && featMatch[2]) {
|
|
4926
4931
|
const targetFeature = featMatch[1];
|
|
@@ -4971,7 +4976,7 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot) {
|
|
|
4971
4976
|
isSharedDomain
|
|
4972
4977
|
};
|
|
4973
4978
|
}
|
|
4974
|
-
return { isExternal: true, isDiFramework: false };
|
|
4979
|
+
return { isExternal: true, isDiFramework: false, isGlobalConfig };
|
|
4975
4980
|
}
|
|
4976
4981
|
function extractImportStatements(content) {
|
|
4977
4982
|
const statements = [];
|
|
@@ -5542,6 +5547,44 @@ Code: ${v.code}`;
|
|
|
5542
5547
|
}
|
|
5543
5548
|
});
|
|
5544
5549
|
}
|
|
5550
|
+
if (target.targetLayer === "domain" && !target.isTargetPort) {
|
|
5551
|
+
addViolation({
|
|
5552
|
+
feature: feat.name,
|
|
5553
|
+
layer,
|
|
5554
|
+
file,
|
|
5555
|
+
relativePath: relPath,
|
|
5556
|
+
line: stmt.line,
|
|
5557
|
+
category: "Cross-Feature Domain Violation",
|
|
5558
|
+
code: stmt.rawCode,
|
|
5559
|
+
ruleId: "F1_CROSS_FEATURE_DOMAIN",
|
|
5560
|
+
severity: "error",
|
|
5561
|
+
advice: `Cannot import domain entities/factories directly from foreign feature '${target.targetFeature}'. This bypasses its use cases and breaks Bounded Context encapsulation. Communicate via ports instead.`,
|
|
5562
|
+
fixExample: {
|
|
5563
|
+
bad: stmt.rawCode,
|
|
5564
|
+
good: `// Define a Port in ${feat.name}/domain/ and implement the cross-feature communication in ${feat.name}/infrastructure/ (which can then call ${target.targetFeature}'s Use Case).`
|
|
5565
|
+
}
|
|
5566
|
+
});
|
|
5567
|
+
}
|
|
5568
|
+
}
|
|
5569
|
+
if (target.isGlobalConfig) {
|
|
5570
|
+
addViolation({
|
|
5571
|
+
feature: feat.name,
|
|
5572
|
+
layer,
|
|
5573
|
+
file,
|
|
5574
|
+
relativePath: relPath,
|
|
5575
|
+
line: stmt.line,
|
|
5576
|
+
category: "Global Configuration Violation",
|
|
5577
|
+
code: stmt.rawCode,
|
|
5578
|
+
ruleId: "F2_GLOBAL_CONFIG_DEPENDENCY",
|
|
5579
|
+
severity: "error",
|
|
5580
|
+
advice: `Feature layers (${layer}) must not depend directly on global configurations. Define a configuration interface/token within the feature (e.g., '${feat.name}/domain/I${toPascalCase(feat.name)}Config') and inject it. The feature's diProvider.ts will handle mapping the global config to this token.`,
|
|
5581
|
+
fixExample: {
|
|
5582
|
+
bad: stmt.rawCode,
|
|
5583
|
+
good: `// 1. Define I${toPascalCase(feat.name)}Config locally
|
|
5584
|
+
// 2. Inject it via static deps
|
|
5585
|
+
// 3. Import and bind global configs inside diProvider.ts`
|
|
5586
|
+
}
|
|
5587
|
+
});
|
|
5545
5588
|
}
|
|
5546
5589
|
if (layer === "domain") {
|
|
5547
5590
|
if (target.targetLayer && ["useCases", "services", "infrastructure", "presentation"].includes(target.targetLayer)) {
|
|
@@ -5598,7 +5641,7 @@ Code: ${v.code}`;
|
|
|
5598
5641
|
}
|
|
5599
5642
|
});
|
|
5600
5643
|
}
|
|
5601
|
-
if (target.isExternal && !target.isDiFramework) {
|
|
5644
|
+
if (target.isExternal && !target.isDiFramework && !target.isGlobalConfig) {
|
|
5602
5645
|
addViolation({
|
|
5603
5646
|
feature: feat.name,
|
|
5604
5647
|
layer,
|
|
@@ -5908,6 +5951,24 @@ Code: ${v.code}`;
|
|
|
5908
5951
|
}
|
|
5909
5952
|
});
|
|
5910
5953
|
}
|
|
5954
|
+
if (target.targetLayer === "domain" && !target.isTargetPort && !target.isTargetRepo) {
|
|
5955
|
+
addViolation({
|
|
5956
|
+
feature: feat.name,
|
|
5957
|
+
layer,
|
|
5958
|
+
file,
|
|
5959
|
+
relativePath: relPath,
|
|
5960
|
+
line: stmt.line,
|
|
5961
|
+
category: "Presentation Layer Violation",
|
|
5962
|
+
code: stmt.rawCode,
|
|
5963
|
+
ruleId: "P5_DIRECT_DOMAIN_ENTITY",
|
|
5964
|
+
severity: "error",
|
|
5965
|
+
advice: "Presentation handlers must not directly instantiate or import domain entities/factories. They must map requests to flat DTOs and pass them to the Use Case.",
|
|
5966
|
+
fixExample: {
|
|
5967
|
+
bad: stmt.rawCode,
|
|
5968
|
+
good: "// Construct a DTO and pass it into the injected Use Case's execute() method."
|
|
5969
|
+
}
|
|
5970
|
+
});
|
|
5971
|
+
}
|
|
5911
5972
|
}
|
|
5912
5973
|
}
|
|
5913
5974
|
}
|