@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/index.js
CHANGED
|
@@ -4922,14 +4922,19 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot) {
|
|
|
4922
4922
|
resolvedRel = specifier.replace(/^[@~]\//, "src/");
|
|
4923
4923
|
} else if (specifier.startsWith("@shared/")) {
|
|
4924
4924
|
resolvedRel = "src/" + specifier.slice(1);
|
|
4925
|
+
} else if (specifier.startsWith("@/configs/") || specifier.startsWith("~/configs/") || specifier === "@/configs" || specifier === "~/configs") {
|
|
4926
|
+
resolvedRel = specifier.replace(/^[@~]\//, "src/");
|
|
4927
|
+
} else if (specifier === "@configs" || specifier.startsWith("@configs/")) {
|
|
4928
|
+
resolvedRel = "src/" + specifier.slice(1);
|
|
4925
4929
|
} else if (specifier.startsWith("@/") || specifier.startsWith("~/")) {
|
|
4926
4930
|
resolvedRel = "src/" + specifier.slice(2);
|
|
4927
|
-
} else if (specifier.startsWith("features/") || specifier.startsWith("shared/")) {
|
|
4931
|
+
} else if (specifier.startsWith("features/") || specifier.startsWith("shared/") || specifier.startsWith("configs/") || specifier === "configs") {
|
|
4928
4932
|
resolvedRel = specifier;
|
|
4929
4933
|
}
|
|
4930
4934
|
if (!resolvedRel) {
|
|
4931
4935
|
return { isExternal: true, isDiFramework: false };
|
|
4932
4936
|
}
|
|
4937
|
+
const isGlobalConfig = resolvedRel.startsWith("src/configs/") || resolvedRel === "src/configs" || resolvedRel.startsWith("configs/") || resolvedRel === "configs";
|
|
4933
4938
|
const featMatch = resolvedRel.match(/(?:^|\/)(?:src\/)?features\/([^/]+)\/([^/]+)(?:\/(.*))?$/);
|
|
4934
4939
|
if (featMatch && featMatch[1] && featMatch[2]) {
|
|
4935
4940
|
const targetFeature = featMatch[1];
|
|
@@ -4980,7 +4985,7 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot) {
|
|
|
4980
4985
|
isSharedDomain
|
|
4981
4986
|
};
|
|
4982
4987
|
}
|
|
4983
|
-
return { isExternal: true, isDiFramework: false };
|
|
4988
|
+
return { isExternal: true, isDiFramework: false, isGlobalConfig };
|
|
4984
4989
|
}
|
|
4985
4990
|
function extractImportStatements(content) {
|
|
4986
4991
|
const statements = [];
|
|
@@ -5551,6 +5556,44 @@ Code: ${v.code}`;
|
|
|
5551
5556
|
}
|
|
5552
5557
|
});
|
|
5553
5558
|
}
|
|
5559
|
+
if (target.targetLayer === "domain" && !target.isTargetPort) {
|
|
5560
|
+
addViolation({
|
|
5561
|
+
feature: feat.name,
|
|
5562
|
+
layer,
|
|
5563
|
+
file,
|
|
5564
|
+
relativePath: relPath,
|
|
5565
|
+
line: stmt.line,
|
|
5566
|
+
category: "Cross-Feature Domain Violation",
|
|
5567
|
+
code: stmt.rawCode,
|
|
5568
|
+
ruleId: "F1_CROSS_FEATURE_DOMAIN",
|
|
5569
|
+
severity: "error",
|
|
5570
|
+
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.`,
|
|
5571
|
+
fixExample: {
|
|
5572
|
+
bad: stmt.rawCode,
|
|
5573
|
+
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).`
|
|
5574
|
+
}
|
|
5575
|
+
});
|
|
5576
|
+
}
|
|
5577
|
+
}
|
|
5578
|
+
if (target.isGlobalConfig) {
|
|
5579
|
+
addViolation({
|
|
5580
|
+
feature: feat.name,
|
|
5581
|
+
layer,
|
|
5582
|
+
file,
|
|
5583
|
+
relativePath: relPath,
|
|
5584
|
+
line: stmt.line,
|
|
5585
|
+
category: "Global Configuration Violation",
|
|
5586
|
+
code: stmt.rawCode,
|
|
5587
|
+
ruleId: "F2_GLOBAL_CONFIG_DEPENDENCY",
|
|
5588
|
+
severity: "error",
|
|
5589
|
+
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.`,
|
|
5590
|
+
fixExample: {
|
|
5591
|
+
bad: stmt.rawCode,
|
|
5592
|
+
good: `// 1. Define I${toPascalCase(feat.name)}Config locally
|
|
5593
|
+
// 2. Inject it via static deps
|
|
5594
|
+
// 3. Import and bind global configs inside diProvider.ts`
|
|
5595
|
+
}
|
|
5596
|
+
});
|
|
5554
5597
|
}
|
|
5555
5598
|
if (layer === "domain") {
|
|
5556
5599
|
if (target.targetLayer && ["useCases", "services", "infrastructure", "presentation"].includes(target.targetLayer)) {
|
|
@@ -5607,7 +5650,7 @@ Code: ${v.code}`;
|
|
|
5607
5650
|
}
|
|
5608
5651
|
});
|
|
5609
5652
|
}
|
|
5610
|
-
if (target.isExternal && !target.isDiFramework) {
|
|
5653
|
+
if (target.isExternal && !target.isDiFramework && !target.isGlobalConfig) {
|
|
5611
5654
|
addViolation({
|
|
5612
5655
|
feature: feat.name,
|
|
5613
5656
|
layer,
|
|
@@ -5917,6 +5960,24 @@ Code: ${v.code}`;
|
|
|
5917
5960
|
}
|
|
5918
5961
|
});
|
|
5919
5962
|
}
|
|
5963
|
+
if (target.targetLayer === "domain" && !target.isTargetPort && !target.isTargetRepo) {
|
|
5964
|
+
addViolation({
|
|
5965
|
+
feature: feat.name,
|
|
5966
|
+
layer,
|
|
5967
|
+
file,
|
|
5968
|
+
relativePath: relPath,
|
|
5969
|
+
line: stmt.line,
|
|
5970
|
+
category: "Presentation Layer Violation",
|
|
5971
|
+
code: stmt.rawCode,
|
|
5972
|
+
ruleId: "P5_DIRECT_DOMAIN_ENTITY",
|
|
5973
|
+
severity: "error",
|
|
5974
|
+
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.",
|
|
5975
|
+
fixExample: {
|
|
5976
|
+
bad: stmt.rawCode,
|
|
5977
|
+
good: "// Construct a DTO and pass it into the injected Use Case's execute() method."
|
|
5978
|
+
}
|
|
5979
|
+
});
|
|
5980
|
+
}
|
|
5920
5981
|
}
|
|
5921
5982
|
}
|
|
5922
5983
|
}
|