@solid-stack/mason 1.0.34 → 1.0.36

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.
@@ -1 +1 @@
1
- {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG5E,wBAAgB,eAAe,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAsBpD;AAED,wBAAsB,UAAU,CAAC,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA0EtF"}
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG5E,wBAAgB,eAAe,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAsBpD;AAED,wBAAsB,UAAU,CAAC,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA4EtF"}
@@ -24,6 +24,12 @@ export interface TargetInfo {
24
24
  }
25
25
  export declare function isTestFile(filePath: string, projectRoot?: string): boolean;
26
26
  export declare function scanDirFiles(dir: string, projectRoot?: string): string[];
27
+ export declare function resolveLintEnvironment(projectRoot: string): {
28
+ featuresBase: string;
29
+ sharedBase: string;
30
+ errorsBase: string;
31
+ baseErrorAbs: string;
32
+ };
27
33
  export declare function classifyFile(fullPathAbs: string, featuresBaseAbs: string, sharedBaseAbs?: string, errorsBaseAbs?: string): {
28
34
  moduleType?: ModuleType | undefined;
29
35
  moduleName?: string | undefined;
@@ -72,5 +78,14 @@ export interface ClassMethodInfo {
72
78
  export declare function extractClassMethods(content: string, className: string): ClassMethodInfo[] | null;
73
79
  export declare function checkUseCaseShape(featureName: string, filePath: string, relativePath: string, content: string, addViolation: (v: Violation) => void): void;
74
80
  export declare function checkServiceShape(featureName: string, filePath: string, relativePath: string, content: string, addViolation: (v: Violation) => void): void;
81
+ export interface RegistryModuleErrorInfo {
82
+ errorsDir: string;
83
+ hasErrorsDir: boolean;
84
+ baseErrorFileAbs?: string | undefined;
85
+ baseErrorClassName?: string | undefined;
86
+ baseErrorExtendsName?: string | undefined;
87
+ baseErrorRawClassCode?: string | undefined;
88
+ }
89
+ export declare function resolveRegistryModuleError(modDir: string, modName: string): RegistryModuleErrorInfo;
75
90
  export declare function lintCodebase(options?: LintOptions): LintSummary;
76
91
  //# sourceMappingURL=lintEngine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lintEngine.d.ts","sourceRoot":"","sources":["../../src/core/lintEngine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lintEngine.d.ts","sourceRoot":"","sources":["../../src/core/lintEngine.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -220,20 +220,20 @@ function getConfiguredSharedDir(projectRoot, flags) {
220
220
  return path26__default.default.join(projectRoot, "shared");
221
221
  }
222
222
  function loadLintConfig(projectRoot) {
223
- const configPath = path26__default.default.join(projectRoot, "mason-lint.config.json");
224
- if (fs17__default.default.existsSync(configPath)) {
225
- try {
226
- return JSON.parse(fs17__default.default.readFileSync(configPath, "utf-8"));
227
- } catch {
228
- }
223
+ const masonConfig = loadMasonConfig(projectRoot);
224
+ if (masonConfig) {
225
+ return {
226
+ baseErrorPath: masonConfig.paths?.baseError,
227
+ paths: masonConfig.paths
228
+ };
229
229
  }
230
230
  return {};
231
231
  }
232
232
  function getResolvedLintPaths(projectRoot, config) {
233
233
  const masonConfig = loadMasonConfig(projectRoot);
234
- const configuredFeatures = config.paths?.features ?? masonConfig?.paths?.features;
235
- const configuredShared = config.paths?.shared ?? masonConfig?.paths?.shared;
236
- const configuredErrors = config.paths?.errors;
234
+ const configuredFeatures = config?.paths?.features ?? masonConfig?.paths?.features;
235
+ const configuredShared = config?.paths?.shared ?? masonConfig?.paths?.shared;
236
+ const configuredErrors = config?.paths?.errors ?? masonConfig?.paths?.errors;
237
237
  const resolveBase = (configuredPath, defaultSrc, defaultRoot) => {
238
238
  if (configuredPath !== void 0) {
239
239
  return path26__default.default.resolve(projectRoot, configuredPath);
@@ -4943,19 +4943,43 @@ function scanDirFiles(dir, projectRoot) {
4943
4943
  }
4944
4944
  return files;
4945
4945
  }
4946
+ function resolveLintEnvironment(projectRoot) {
4947
+ const config = loadMasonConfig(projectRoot);
4948
+ const resolveDir = (configured, defaultSrc, defaultRoot) => {
4949
+ if (configured !== void 0) {
4950
+ return path26__default.default.resolve(projectRoot, configured);
4951
+ }
4952
+ const srcPath = path26__default.default.join(projectRoot, defaultSrc);
4953
+ if (fs17__default.default.existsSync(srcPath)) return srcPath;
4954
+ const rootPath = path26__default.default.join(projectRoot, defaultRoot);
4955
+ if (fs17__default.default.existsSync(rootPath)) return rootPath;
4956
+ return srcPath;
4957
+ };
4958
+ const featuresBase = resolveDir(config?.paths?.features, "src/features", "features");
4959
+ const sharedBase = resolveDir(config?.paths?.shared, "src/shared", "shared");
4960
+ const errorsBase = resolveDir(config?.paths?.errors, "src/errors", "errors");
4961
+ const defaultBaseErrorRelative = config?.paths?.errors ? path26__default.default.join(config.paths.errors, "AppError.ts") : fs17__default.default.existsSync(path26__default.default.join(projectRoot, "src/errors")) ? "src/errors/AppError.ts" : fs17__default.default.existsSync(path26__default.default.join(projectRoot, "errors")) ? "errors/AppError.ts" : "src/errors/AppError.ts";
4962
+ const baseErrorAbs = path26__default.default.resolve(
4963
+ projectRoot,
4964
+ config?.paths?.baseError || defaultBaseErrorRelative
4965
+ );
4966
+ return { featuresBase, sharedBase, errorsBase, baseErrorAbs };
4967
+ }
4946
4968
  function classifyFile(fullPathAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs) {
4947
4969
  if (!sharedBaseAbs || !errorsBaseAbs) {
4948
- const paths = getResolvedLintPaths(featuresBaseAbs, loadLintConfig(featuresBaseAbs));
4949
- featuresBaseAbs = paths.featuresBase;
4950
- sharedBaseAbs = paths.sharedBase;
4951
- errorsBaseAbs = paths.errorsBase;
4970
+ const env = resolveLintEnvironment(featuresBaseAbs);
4971
+ featuresBaseAbs = env.featuresBase;
4972
+ sharedBaseAbs = env.sharedBase;
4973
+ errorsBaseAbs = env.errorsBase;
4952
4974
  }
4953
4975
  const normFullPath = path26__default.default.resolve(fullPathAbs);
4954
4976
  const normErrorsBase = path26__default.default.resolve(errorsBaseAbs);
4955
4977
  const normSharedBase = path26__default.default.resolve(sharedBaseAbs);
4956
4978
  const normFeaturesBase = path26__default.default.resolve(featuresBaseAbs);
4957
- const relErrors = path26__default.default.relative(normErrorsBase, normFullPath).replace(/\\/g, "/");
4958
- if (!relErrors.startsWith("..") && !path26__default.default.isAbsolute(relErrors)) {
4979
+ const isUnder = (base, target) => {
4980
+ return target === base || target.startsWith(base + path26__default.default.sep);
4981
+ };
4982
+ if (isUnder(normErrorsBase, normFullPath)) {
4959
4983
  return {
4960
4984
  moduleType: "error",
4961
4985
  moduleName: "global-errors",
@@ -4963,26 +4987,26 @@ function classifyFile(fullPathAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs
4963
4987
  layer: "domain"
4964
4988
  };
4965
4989
  }
4966
- const relShared = path26__default.default.relative(normSharedBase, normFullPath).replace(/\\/g, "/");
4967
- if (!relShared.startsWith("..") && !path26__default.default.isAbsolute(relShared)) {
4968
- const parts = relShared.split("/").filter(Boolean);
4990
+ if (isUnder(normSharedBase, normFullPath)) {
4991
+ const rel = path26__default.default.relative(normSharedBase, normFullPath).replace(/\\/g, "/");
4992
+ const parts = rel.split("/").filter(Boolean);
4969
4993
  if (parts.length >= 1) {
4970
4994
  const moduleName = parts[0];
4971
- const rest = parts.slice(1).join("/");
4995
+ const subfolder = parts[1];
4972
4996
  let layer = "root";
4973
- if (rest.startsWith("domain/") || rest === "domain" || rest.startsWith("errors/") || rest === "errors") {
4997
+ if (subfolder === "domain" || subfolder === "errors") {
4974
4998
  layer = "domain";
4975
- } else if (rest.startsWith("ports/") || rest === "ports") {
4999
+ } else if (subfolder === "ports") {
4976
5000
  layer = "ports";
4977
- } else if (rest.startsWith("infrastructure/") || rest === "infrastructure") {
5001
+ } else if (subfolder === "infrastructure") {
4978
5002
  layer = "infrastructure";
4979
5003
  }
4980
5004
  return { moduleType: "shared", moduleName, feature: moduleName, layer };
4981
5005
  }
4982
5006
  }
4983
- const relFeatures = path26__default.default.relative(normFeaturesBase, normFullPath).replace(/\\/g, "/");
4984
- if (!relFeatures.startsWith("..") && !path26__default.default.isAbsolute(relFeatures)) {
4985
- const parts = relFeatures.split("/").filter(Boolean);
5007
+ if (isUnder(normFeaturesBase, normFullPath)) {
5008
+ const rel = path26__default.default.relative(normFeaturesBase, normFullPath).replace(/\\/g, "/");
5009
+ const parts = rel.split("/").filter(Boolean);
4986
5010
  if (parts.length >= 2) {
4987
5011
  const moduleName = parts[0];
4988
5012
  const subfolder = parts[1];
@@ -4995,7 +5019,7 @@ function classifyFile(fullPathAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs
4995
5019
  layer = "services";
4996
5020
  } else if (subfolder === "infrastructure") {
4997
5021
  layer = "infrastructure";
4998
- } else if (subfolder === "pxExpress" || subfolder === "presentation" || subfolder === "handlers" || subfolder.startsWith("px")) {
5022
+ } else if (subfolder.startsWith("px") || subfolder === "presentation" || subfolder === "handlers" || subfolder === "transformers") {
4999
5023
  layer = "presentation";
5000
5024
  }
5001
5025
  return { moduleType: "feature", moduleName, feature: moduleName, layer };
@@ -5024,10 +5048,10 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot, featuresBaseAbs,
5024
5048
  return { isExternal: true, isDiFramework: false };
5025
5049
  }
5026
5050
  if (!featuresBaseAbs || !sharedBaseAbs || !errorsBaseAbs) {
5027
- const paths = getResolvedLintPaths(projectRoot, loadLintConfig(projectRoot));
5028
- featuresBaseAbs = featuresBaseAbs || paths.featuresBase;
5029
- sharedBaseAbs = sharedBaseAbs || paths.sharedBase;
5030
- errorsBaseAbs = errorsBaseAbs || paths.errorsBase;
5051
+ const env = resolveLintEnvironment(projectRoot);
5052
+ featuresBaseAbs = featuresBaseAbs || env.featuresBase;
5053
+ sharedBaseAbs = sharedBaseAbs || env.sharedBase;
5054
+ errorsBaseAbs = errorsBaseAbs || env.errorsBase;
5031
5055
  }
5032
5056
  const isGlobalConfig = specifier === "@configs" || specifier.startsWith("@configs/") || specifier === "@/configs" || specifier.startsWith("@/configs/") || specifier === "~/configs" || specifier.startsWith("~/configs/") || specifier === "configs" || specifier.startsWith("configs/");
5033
5057
  let targetAbs = null;
@@ -5664,45 +5688,108 @@ private ${m.name}(...) { ... }`
5664
5688
  }
5665
5689
  }
5666
5690
  }
5691
+ function resolveRegistryModuleError(modDir, modName) {
5692
+ const errorsDir = path26__default.default.join(modDir, "errors");
5693
+ if (!fs17__default.default.existsSync(errorsDir) || !fs17__default.default.statSync(errorsDir).isDirectory()) {
5694
+ return { errorsDir, hasErrorsDir: false };
5695
+ }
5696
+ const entries = fs17__default.default.readdirSync(errorsDir);
5697
+ const errorFiles = entries.filter((f) => f.endsWith(".ts") || f.endsWith(".js"));
5698
+ const nameNormalized = modName.toLowerCase().replace(/[-_]/g, "");
5699
+ const singularNormalized = toSingular(modName).toLowerCase().replace(/[-_]/g, "");
5700
+ let baseErrorFileName = errorFiles.find((f) => {
5701
+ const baseNoExt = f.replace(/\.(ts|js)$/, "").toLowerCase().replace(/[-_]/g, "");
5702
+ return baseNoExt === `${nameNormalized}error` || baseNoExt === `${singularNormalized}error` || baseNoExt === `${nameNormalized}errors` || baseNoExt === `${singularNormalized}errors`;
5703
+ });
5704
+ if (!baseErrorFileName) {
5705
+ return { errorsDir, hasErrorsDir: true };
5706
+ }
5707
+ const baseErrorFileAbs = path26__default.default.join(errorsDir, baseErrorFileName);
5708
+ const content = fs17__default.default.readFileSync(baseErrorFileAbs, "utf-8");
5709
+ const classRegex = /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)(?:<[^>]+>)?(?:\s+extends\s+([A-Za-z0-9_]+))?/g;
5710
+ let match;
5711
+ const classes = [];
5712
+ while ((match = classRegex.exec(content)) !== null) {
5713
+ classes.push({
5714
+ name: match[1],
5715
+ extendsName: match[2],
5716
+ raw: match[0]
5717
+ });
5718
+ }
5719
+ const expectedNames = [
5720
+ `${toPascalCase(modName)}Error`,
5721
+ `${toPascalCase(toSingular(modName))}Error`,
5722
+ `${toPascalCase(modName)}Errors`,
5723
+ `${toPascalCase(toSingular(modName))}Errors`
5724
+ ].map((n) => n.toLowerCase());
5725
+ const targetClass = classes.find((c) => expectedNames.includes(c.name.toLowerCase())) || classes.find((c) => c.raw.includes("export")) || classes[0];
5726
+ return {
5727
+ errorsDir,
5728
+ hasErrorsDir: true,
5729
+ baseErrorFileAbs,
5730
+ baseErrorClassName: targetClass ? targetClass.name : void 0,
5731
+ baseErrorExtendsName: targetClass ? targetClass.extendsName : void 0,
5732
+ baseErrorRawClassCode: targetClass ? targetClass.raw : void 0
5733
+ };
5734
+ }
5667
5735
  function lintCodebase(options = {}) {
5668
5736
  const startTime = Date.now();
5669
5737
  const projectRoot = options.projectRoot || findProjectRoot(options.targetDir || process.cwd());
5670
5738
  const failFast = !options.complete;
5671
- const lintConfig = loadLintConfig(projectRoot);
5672
- const { featuresBase, sharedBase, errorsBase } = getResolvedLintPaths(projectRoot, lintConfig);
5673
- const missingFoundations = [];
5674
- if (!fs17__default.default.existsSync(featuresBase)) missingFoundations.push("features/");
5675
- if (!fs17__default.default.existsSync(sharedBase)) missingFoundations.push("shared/");
5676
- if (!fs17__default.default.existsSync(errorsBase)) missingFoundations.push("errors/");
5677
- if (missingFoundations.length > 0) {
5678
- throw new DependencyRuleError(
5679
- `Project Structure Violation: Missing required foundational directories: ${missingFoundations.join(", ")}. Every project must contain 'features/', 'shared/', and 'errors/'.`,
5680
- [],
5681
- true
5682
- );
5739
+ const effectiveMode = options.mode || getEffectiveMode(projectRoot, options.registry !== void 0 ? { registry: options.registry } : void 0);
5740
+ const isRegistryMode = effectiveMode === "registry";
5741
+ const { featuresBase, sharedBase, errorsBase, baseErrorAbs } = resolveLintEnvironment(projectRoot);
5742
+ if (!isRegistryMode) {
5743
+ const missingFoundations = [];
5744
+ if (!fs17__default.default.existsSync(featuresBase)) missingFoundations.push("features/");
5745
+ if (!fs17__default.default.existsSync(sharedBase)) missingFoundations.push("shared/");
5746
+ if (!fs17__default.default.existsSync(errorsBase)) missingFoundations.push("errors/");
5747
+ if (missingFoundations.length > 0) {
5748
+ throw new DependencyRuleError(
5749
+ `Project Structure Violation: Missing required foundational directories: ${missingFoundations.join(", ")}. Every architecture must contain 'features/', 'shared/', and 'errors/'.`,
5750
+ [],
5751
+ true
5752
+ );
5753
+ }
5754
+ if (!fs17__default.default.existsSync(baseErrorAbs)) {
5755
+ throw new DependencyRuleError(
5756
+ `Project Structure Violation: Base error class not found at '${path26__default.default.relative(projectRoot, baseErrorAbs).replace(/\\/g, "/")}'. Configure paths.baseError in mason.config.json.`,
5757
+ [],
5758
+ true
5759
+ );
5760
+ }
5761
+ } else {
5762
+ if (!fs17__default.default.existsSync(featuresBase) && !fs17__default.default.existsSync(sharedBase)) {
5763
+ throw new DependencyRuleError(
5764
+ `Project Structure Violation: Missing required foundational directories: features/ or shared/. A registry must contain 'features/' or 'shared/'.`,
5765
+ [],
5766
+ true
5767
+ );
5768
+ }
5683
5769
  }
5684
- const baseErrorRelative = lintConfig.baseErrorPath || path26__default.default.relative(projectRoot, path26__default.default.join(errorsBase, "AppError.ts")).replace(/\\/g, "/");
5685
- const baseErrorAbs = path26__default.default.resolve(projectRoot, baseErrorRelative);
5686
- if (!fs17__default.default.existsSync(baseErrorAbs)) {
5687
- throw new DependencyRuleError(
5688
- `Project Structure Violation: Base error class not found at '${baseErrorRelative}'. Create this file or update 'baseErrorPath' in mason-lint.config.json.`,
5689
- [],
5690
- true
5770
+ let baseErrorClassName = "AppError";
5771
+ if (!isRegistryMode && fs17__default.default.existsSync(baseErrorAbs)) {
5772
+ const baseErrorContent = fs17__default.default.readFileSync(baseErrorAbs, "utf-8");
5773
+ const baseClassMatch = baseErrorContent.match(
5774
+ /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)/
5691
5775
  );
5776
+ baseErrorClassName = baseClassMatch ? baseClassMatch[1] : "AppError";
5692
5777
  }
5693
- const baseErrorContent = fs17__default.default.readFileSync(baseErrorAbs, "utf-8");
5694
- const baseClassMatch = baseErrorContent.match(
5695
- /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)/
5696
- );
5697
- const baseErrorClassName = baseClassMatch ? baseClassMatch[1] : "AppError";
5698
5778
  const features = discoverAllFeatures(featuresBase, [sharedBase, errorsBase]);
5699
5779
  const sharedModules = discoverAllShared(sharedBase, [featuresBase, errorsBase]);
5700
- const errorModule = { name: "global-errors", dir: errorsBase, type: "error" };
5701
5780
  const allModules = [
5702
5781
  ...features.map((f) => ({ ...f, type: "feature" })),
5703
- ...sharedModules.map((s) => ({ ...s, type: "shared" })),
5704
- errorModule
5782
+ ...sharedModules.map((s) => ({ ...s, type: "shared" }))
5705
5783
  ];
5784
+ if (!isRegistryMode) {
5785
+ const errorModule = { name: "global-errors", dir: errorsBase, type: "error" };
5786
+ allModules.push(errorModule);
5787
+ } else if (fs17__default.default.existsSync(errorsBase)) {
5788
+ const errorFiles = scanDirFiles(errorsBase, projectRoot);
5789
+ if (errorFiles.length > 0) {
5790
+ allModules.push({ name: "global-errors", dir: errorsBase, type: "error" });
5791
+ }
5792
+ }
5706
5793
  const graph = new FeatureDependencyGraph();
5707
5794
  const allViolations = [];
5708
5795
  const results = [];
@@ -5736,6 +5823,77 @@ Code: ${v.code}`;
5736
5823
  }
5737
5824
  for (const mod of allModules) {
5738
5825
  const modResult = results.find((r) => r.featureName === mod.name);
5826
+ let modBaseErrorClass = baseErrorClassName;
5827
+ let modBaseErrorAbs = !isRegistryMode ? baseErrorAbs : void 0;
5828
+ if (isRegistryMode && (mod.type === "feature" || mod.type === "shared")) {
5829
+ const errorInfo = resolveRegistryModuleError(mod.dir, mod.name);
5830
+ if (!errorInfo.hasErrorsDir) {
5831
+ addViolation({
5832
+ feature: mod.name,
5833
+ layer: "domain",
5834
+ file: mod.dir,
5835
+ relativePath: path26__default.default.relative(projectRoot, errorInfo.errorsDir).replace(/\\/g, "/"),
5836
+ line: 1,
5837
+ category: "Project Structure Violation",
5838
+ code: `Missing errors/ directory in registry ${mod.type} '${mod.name}'`,
5839
+ ruleId: "REG_ERRORS_DIR_REQUIRED",
5840
+ severity: "error",
5841
+ advice: `Registry ${mod.type} '${mod.name}' must implement its own 'errors/' directory at '${path26__default.default.relative(projectRoot, errorInfo.errorsDir).replace(/\\/g, "/")}'.`,
5842
+ fixExample: {
5843
+ bad: "// Missing errors directory",
5844
+ good: `mkdir -p ${path26__default.default.relative(projectRoot, errorInfo.errorsDir).replace(/\\/g, "/")}`
5845
+ }
5846
+ });
5847
+ } else if (!errorInfo.baseErrorFileAbs) {
5848
+ const expectedFileName = `${toPascalCase(mod.name)}Error.ts`;
5849
+ const expectedRel = path26__default.default.relative(projectRoot, path26__default.default.join(errorInfo.errorsDir, expectedFileName)).replace(/\\/g, "/");
5850
+ addViolation({
5851
+ feature: mod.name,
5852
+ layer: "domain",
5853
+ file: errorInfo.errorsDir,
5854
+ relativePath: expectedRel,
5855
+ line: 1,
5856
+ category: "Project Structure Violation",
5857
+ code: `Missing base error file in '${mod.name}/errors'`,
5858
+ ruleId: "REG_BASE_ERROR_REQUIRED",
5859
+ severity: "error",
5860
+ advice: `Registry ${mod.type} '${mod.name}' must have a base error file at '${expectedRel}'.`,
5861
+ fixExample: {
5862
+ bad: "// Missing base error file",
5863
+ good: `export class ${toPascalCase(mod.name)}Error extends Error {
5864
+ constructor(message: string) {
5865
+ super(message);
5866
+ }
5867
+ }`
5868
+ }
5869
+ });
5870
+ } else {
5871
+ modBaseErrorAbs = errorInfo.baseErrorFileAbs;
5872
+ modBaseErrorClass = errorInfo.baseErrorClassName || `${toPascalCase(mod.name)}Error`;
5873
+ if (!errorInfo.baseErrorClassName || errorInfo.baseErrorExtendsName !== "Error") {
5874
+ addViolation({
5875
+ feature: mod.name,
5876
+ layer: "domain",
5877
+ file: errorInfo.baseErrorFileAbs,
5878
+ relativePath: path26__default.default.relative(projectRoot, errorInfo.baseErrorFileAbs).replace(/\\/g, "/"),
5879
+ line: 1,
5880
+ category: "Error Inheritance Violation",
5881
+ code: errorInfo.baseErrorRawClassCode || `class ${modBaseErrorClass}`,
5882
+ ruleId: "REG_BASE_ERROR_MUST_EXTEND_ERROR",
5883
+ severity: "error",
5884
+ advice: `Registry ${mod.type} base error class '${modBaseErrorClass}' in '${mod.name}' must extend native 'Error'.`,
5885
+ fixExample: {
5886
+ bad: errorInfo.baseErrorRawClassCode || `class ${modBaseErrorClass}`,
5887
+ good: `export class ${modBaseErrorClass} extends Error {
5888
+ constructor(message: string) {
5889
+ super(message);
5890
+ }
5891
+ }`
5892
+ }
5893
+ });
5894
+ }
5895
+ }
5896
+ }
5739
5897
  const allFiles = scanDirFiles(mod.dir, projectRoot);
5740
5898
  modResult.scannedFilesCount = allFiles.length;
5741
5899
  for (const file of allFiles) {
@@ -5763,15 +5921,15 @@ Code: ${v.code}`;
5763
5921
  code: lineCode,
5764
5922
  ruleId: "E3_PLAIN_ERROR_THROW",
5765
5923
  severity: "error",
5766
- advice: `Throwing plain 'Error' is prohibited. You must throw '${baseErrorClassName}' or a domain-specific error class that inherits from it.`,
5924
+ advice: isRegistryMode ? `Throwing plain 'Error' is prohibited in registry ${mod.type} '${mod.name}'. You must throw '${modBaseErrorClass}' or a class that inherits from it.` : `Throwing plain 'Error' is prohibited. You must throw '${modBaseErrorClass}' or a custom error class that inherits from it.`,
5767
5925
  fixExample: {
5768
5926
  bad: lineCode,
5769
- good: `throw new ${baseErrorClassName}("Something went wrong");`
5927
+ good: `throw new ${modBaseErrorClass}("Something went wrong");`
5770
5928
  }
5771
5929
  });
5772
5930
  }
5773
5931
  const isErrorFile = relPath.includes("/errors/") || relPath.startsWith("errors/") || relPath.startsWith("src/errors/") || moduleType === "error" || baseName.endsWith("Error.ts") || baseName.endsWith("Errors.ts") || baseName.endsWith("Error.js") || baseName.endsWith("Errors.js");
5774
- const isBaseErrorFile = path26__default.default.resolve(file) === path26__default.default.resolve(baseErrorAbs);
5932
+ const isBaseErrorFile = modBaseErrorAbs ? path26__default.default.resolve(file) === path26__default.default.resolve(modBaseErrorAbs) : !isRegistryMode && path26__default.default.resolve(file) === path26__default.default.resolve(baseErrorAbs);
5775
5933
  if (isErrorFile && !isBaseErrorFile) {
5776
5934
  const classRegex = /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)(?:<[^>]+>)?(?:\s+extends\s+([A-Za-z0-9_]+))?/g;
5777
5935
  let classMatch;
@@ -5793,10 +5951,10 @@ Code: ${v.code}`;
5793
5951
  code: lineCode,
5794
5952
  ruleId: "E4_MISSING_INHERITANCE",
5795
5953
  severity: "error",
5796
- advice: `Error class '${className}' must extend '${baseErrorClassName}' (or another class that derives from it).`,
5954
+ advice: isRegistryMode ? `Error class '${className}' in registry ${mod.type} '${mod.name}' must extend '${modBaseErrorClass}'.` : `Error class '${className}' must extend '${modBaseErrorClass}'.`,
5797
5955
  fixExample: {
5798
5956
  bad: lineCode,
5799
- good: `export class ${className} extends ${baseErrorClassName} { ... }`
5957
+ good: `export class ${className} extends ${modBaseErrorClass} { ... }`
5800
5958
  }
5801
5959
  });
5802
5960
  } else if (extendsName === "Error") {
@@ -5810,10 +5968,10 @@ Code: ${v.code}`;
5810
5968
  code: lineCode,
5811
5969
  ruleId: "E5_NATIVE_ERROR_INHERITANCE",
5812
5970
  severity: "error",
5813
- advice: `Error class '${className}' extends the native 'Error'. It must extend your base error class ('${baseErrorClassName}').`,
5971
+ advice: isRegistryMode ? `Error class '${className}' extends native 'Error'. In registry ${mod.type} '${mod.name}', it must extend your base error class ('${modBaseErrorClass}').` : `Error class '${className}' extends native 'Error'. It must extend your configured base error class ('${modBaseErrorClass}').`,
5814
5972
  fixExample: {
5815
5973
  bad: lineCode,
5816
- good: `export class ${className} extends ${baseErrorClassName} { ... }`
5974
+ good: `export class ${className} extends ${modBaseErrorClass} { ... }`
5817
5975
  }
5818
5976
  });
5819
5977
  }
@@ -6573,7 +6731,9 @@ async function handleLint(flags = {}) {
6573
6731
  targetDir: flags.targetDir || flags.target,
6574
6732
  projectRoot: flags.projectRoot,
6575
6733
  fixHint: flags.fixHint !== false,
6576
- throwOnError: false
6734
+ throwOnError: false,
6735
+ mode: flags.mode || (flags.registry ? "registry" : void 0),
6736
+ registry: Boolean(flags.registry)
6577
6737
  };
6578
6738
  try {
6579
6739
  const summary = lintCodebase(options);