@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.cjs
CHANGED
|
@@ -4942,14 +4942,19 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot) {
|
|
|
4942
4942
|
resolvedRel = specifier.replace(/^[@~]\//, "src/");
|
|
4943
4943
|
} else if (specifier.startsWith("@shared/")) {
|
|
4944
4944
|
resolvedRel = "src/" + specifier.slice(1);
|
|
4945
|
+
} else if (specifier.startsWith("@/configs/") || specifier.startsWith("~/configs/") || specifier === "@/configs" || specifier === "~/configs") {
|
|
4946
|
+
resolvedRel = specifier.replace(/^[@~]\//, "src/");
|
|
4947
|
+
} else if (specifier === "@configs" || specifier.startsWith("@configs/")) {
|
|
4948
|
+
resolvedRel = "src/" + specifier.slice(1);
|
|
4945
4949
|
} else if (specifier.startsWith("@/") || specifier.startsWith("~/")) {
|
|
4946
4950
|
resolvedRel = "src/" + specifier.slice(2);
|
|
4947
|
-
} else if (specifier.startsWith("features/") || specifier.startsWith("shared/")) {
|
|
4951
|
+
} else if (specifier.startsWith("features/") || specifier.startsWith("shared/") || specifier.startsWith("configs/") || specifier === "configs") {
|
|
4948
4952
|
resolvedRel = specifier;
|
|
4949
4953
|
}
|
|
4950
4954
|
if (!resolvedRel) {
|
|
4951
4955
|
return { isExternal: true, isDiFramework: false };
|
|
4952
4956
|
}
|
|
4957
|
+
const isGlobalConfig = resolvedRel.startsWith("src/configs/") || resolvedRel === "src/configs" || resolvedRel.startsWith("configs/") || resolvedRel === "configs";
|
|
4953
4958
|
const featMatch = resolvedRel.match(/(?:^|\/)(?:src\/)?features\/([^/]+)\/([^/]+)(?:\/(.*))?$/);
|
|
4954
4959
|
if (featMatch && featMatch[1] && featMatch[2]) {
|
|
4955
4960
|
const targetFeature = featMatch[1];
|
|
@@ -5000,7 +5005,7 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot) {
|
|
|
5000
5005
|
isSharedDomain
|
|
5001
5006
|
};
|
|
5002
5007
|
}
|
|
5003
|
-
return { isExternal: true, isDiFramework: false };
|
|
5008
|
+
return { isExternal: true, isDiFramework: false, isGlobalConfig };
|
|
5004
5009
|
}
|
|
5005
5010
|
function extractImportStatements(content) {
|
|
5006
5011
|
const statements = [];
|
|
@@ -5571,6 +5576,44 @@ Code: ${v.code}`;
|
|
|
5571
5576
|
}
|
|
5572
5577
|
});
|
|
5573
5578
|
}
|
|
5579
|
+
if (target.targetLayer === "domain" && !target.isTargetPort) {
|
|
5580
|
+
addViolation({
|
|
5581
|
+
feature: feat.name,
|
|
5582
|
+
layer,
|
|
5583
|
+
file,
|
|
5584
|
+
relativePath: relPath,
|
|
5585
|
+
line: stmt.line,
|
|
5586
|
+
category: "Cross-Feature Domain Violation",
|
|
5587
|
+
code: stmt.rawCode,
|
|
5588
|
+
ruleId: "F1_CROSS_FEATURE_DOMAIN",
|
|
5589
|
+
severity: "error",
|
|
5590
|
+
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.`,
|
|
5591
|
+
fixExample: {
|
|
5592
|
+
bad: stmt.rawCode,
|
|
5593
|
+
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).`
|
|
5594
|
+
}
|
|
5595
|
+
});
|
|
5596
|
+
}
|
|
5597
|
+
}
|
|
5598
|
+
if (target.isGlobalConfig) {
|
|
5599
|
+
addViolation({
|
|
5600
|
+
feature: feat.name,
|
|
5601
|
+
layer,
|
|
5602
|
+
file,
|
|
5603
|
+
relativePath: relPath,
|
|
5604
|
+
line: stmt.line,
|
|
5605
|
+
category: "Global Configuration Violation",
|
|
5606
|
+
code: stmt.rawCode,
|
|
5607
|
+
ruleId: "F2_GLOBAL_CONFIG_DEPENDENCY",
|
|
5608
|
+
severity: "error",
|
|
5609
|
+
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.`,
|
|
5610
|
+
fixExample: {
|
|
5611
|
+
bad: stmt.rawCode,
|
|
5612
|
+
good: `// 1. Define I${toPascalCase(feat.name)}Config locally
|
|
5613
|
+
// 2. Inject it via static deps
|
|
5614
|
+
// 3. Import and bind global configs inside diProvider.ts`
|
|
5615
|
+
}
|
|
5616
|
+
});
|
|
5574
5617
|
}
|
|
5575
5618
|
if (layer === "domain") {
|
|
5576
5619
|
if (target.targetLayer && ["useCases", "services", "infrastructure", "presentation"].includes(target.targetLayer)) {
|
|
@@ -5627,7 +5670,7 @@ Code: ${v.code}`;
|
|
|
5627
5670
|
}
|
|
5628
5671
|
});
|
|
5629
5672
|
}
|
|
5630
|
-
if (target.isExternal && !target.isDiFramework) {
|
|
5673
|
+
if (target.isExternal && !target.isDiFramework && !target.isGlobalConfig) {
|
|
5631
5674
|
addViolation({
|
|
5632
5675
|
feature: feat.name,
|
|
5633
5676
|
layer,
|
|
@@ -5937,6 +5980,24 @@ Code: ${v.code}`;
|
|
|
5937
5980
|
}
|
|
5938
5981
|
});
|
|
5939
5982
|
}
|
|
5983
|
+
if (target.targetLayer === "domain" && !target.isTargetPort && !target.isTargetRepo) {
|
|
5984
|
+
addViolation({
|
|
5985
|
+
feature: feat.name,
|
|
5986
|
+
layer,
|
|
5987
|
+
file,
|
|
5988
|
+
relativePath: relPath,
|
|
5989
|
+
line: stmt.line,
|
|
5990
|
+
category: "Presentation Layer Violation",
|
|
5991
|
+
code: stmt.rawCode,
|
|
5992
|
+
ruleId: "P5_DIRECT_DOMAIN_ENTITY",
|
|
5993
|
+
severity: "error",
|
|
5994
|
+
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.",
|
|
5995
|
+
fixExample: {
|
|
5996
|
+
bad: stmt.rawCode,
|
|
5997
|
+
good: "// Construct a DTO and pass it into the injected Use Case's execute() method."
|
|
5998
|
+
}
|
|
5999
|
+
});
|
|
6000
|
+
}
|
|
5940
6001
|
}
|
|
5941
6002
|
}
|
|
5942
6003
|
}
|