@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/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
  }