@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.
package/dist/bin.js CHANGED
@@ -189,37 +189,6 @@ function getConfiguredSharedDir(projectRoot, flags) {
189
189
  }
190
190
  return path26.join(projectRoot, "shared");
191
191
  }
192
- function loadLintConfig(projectRoot) {
193
- const configPath = path26.join(projectRoot, "mason-lint.config.json");
194
- if (fs17.existsSync(configPath)) {
195
- try {
196
- return JSON.parse(fs17.readFileSync(configPath, "utf-8"));
197
- } catch {
198
- }
199
- }
200
- return {};
201
- }
202
- function getResolvedLintPaths(projectRoot, config) {
203
- const masonConfig = loadMasonConfig(projectRoot);
204
- const configuredFeatures = config.paths?.features ?? masonConfig?.paths?.features;
205
- const configuredShared = config.paths?.shared ?? masonConfig?.paths?.shared;
206
- const configuredErrors = config.paths?.errors;
207
- const resolveBase = (configuredPath, defaultSrc, defaultRoot) => {
208
- if (configuredPath !== void 0) {
209
- return path26.resolve(projectRoot, configuredPath);
210
- }
211
- const srcPath = path26.join(projectRoot, defaultSrc);
212
- if (fs17.existsSync(srcPath)) return srcPath;
213
- const rootPath = path26.join(projectRoot, defaultRoot);
214
- if (fs17.existsSync(rootPath)) return rootPath;
215
- return srcPath;
216
- };
217
- return {
218
- featuresBase: resolveBase(configuredFeatures, "src/features", "features"),
219
- sharedBase: resolveBase(configuredShared, "src/shared", "shared"),
220
- errorsBase: resolveBase(configuredErrors, "src/errors", "errors")
221
- };
222
- }
223
192
 
224
193
  // src/utils/project.ts
225
194
  function findProjectRoot(startDir = process.cwd()) {
@@ -4905,19 +4874,43 @@ function scanDirFiles(dir, projectRoot) {
4905
4874
  }
4906
4875
  return files;
4907
4876
  }
4877
+ function resolveLintEnvironment(projectRoot) {
4878
+ const config = loadMasonConfig(projectRoot);
4879
+ const resolveDir = (configured, defaultSrc, defaultRoot) => {
4880
+ if (configured !== void 0) {
4881
+ return path26.resolve(projectRoot, configured);
4882
+ }
4883
+ const srcPath = path26.join(projectRoot, defaultSrc);
4884
+ if (fs17.existsSync(srcPath)) return srcPath;
4885
+ const rootPath = path26.join(projectRoot, defaultRoot);
4886
+ if (fs17.existsSync(rootPath)) return rootPath;
4887
+ return srcPath;
4888
+ };
4889
+ const featuresBase = resolveDir(config?.paths?.features, "src/features", "features");
4890
+ const sharedBase = resolveDir(config?.paths?.shared, "src/shared", "shared");
4891
+ const errorsBase = resolveDir(config?.paths?.errors, "src/errors", "errors");
4892
+ const defaultBaseErrorRelative = config?.paths?.errors ? path26.join(config.paths.errors, "AppError.ts") : fs17.existsSync(path26.join(projectRoot, "src/errors")) ? "src/errors/AppError.ts" : fs17.existsSync(path26.join(projectRoot, "errors")) ? "errors/AppError.ts" : "src/errors/AppError.ts";
4893
+ const baseErrorAbs = path26.resolve(
4894
+ projectRoot,
4895
+ config?.paths?.baseError || defaultBaseErrorRelative
4896
+ );
4897
+ return { featuresBase, sharedBase, errorsBase, baseErrorAbs };
4898
+ }
4908
4899
  function classifyFile(fullPathAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs) {
4909
4900
  if (!sharedBaseAbs || !errorsBaseAbs) {
4910
- const paths = getResolvedLintPaths(featuresBaseAbs, loadLintConfig(featuresBaseAbs));
4911
- featuresBaseAbs = paths.featuresBase;
4912
- sharedBaseAbs = paths.sharedBase;
4913
- errorsBaseAbs = paths.errorsBase;
4901
+ const env = resolveLintEnvironment(featuresBaseAbs);
4902
+ featuresBaseAbs = env.featuresBase;
4903
+ sharedBaseAbs = env.sharedBase;
4904
+ errorsBaseAbs = env.errorsBase;
4914
4905
  }
4915
4906
  const normFullPath = path26.resolve(fullPathAbs);
4916
4907
  const normErrorsBase = path26.resolve(errorsBaseAbs);
4917
4908
  const normSharedBase = path26.resolve(sharedBaseAbs);
4918
4909
  const normFeaturesBase = path26.resolve(featuresBaseAbs);
4919
- const relErrors = path26.relative(normErrorsBase, normFullPath).replace(/\\/g, "/");
4920
- if (!relErrors.startsWith("..") && !path26.isAbsolute(relErrors)) {
4910
+ const isUnder = (base, target) => {
4911
+ return target === base || target.startsWith(base + path26.sep);
4912
+ };
4913
+ if (isUnder(normErrorsBase, normFullPath)) {
4921
4914
  return {
4922
4915
  moduleType: "error",
4923
4916
  moduleName: "global-errors",
@@ -4925,26 +4918,26 @@ function classifyFile(fullPathAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs
4925
4918
  layer: "domain"
4926
4919
  };
4927
4920
  }
4928
- const relShared = path26.relative(normSharedBase, normFullPath).replace(/\\/g, "/");
4929
- if (!relShared.startsWith("..") && !path26.isAbsolute(relShared)) {
4930
- const parts = relShared.split("/").filter(Boolean);
4921
+ if (isUnder(normSharedBase, normFullPath)) {
4922
+ const rel = path26.relative(normSharedBase, normFullPath).replace(/\\/g, "/");
4923
+ const parts = rel.split("/").filter(Boolean);
4931
4924
  if (parts.length >= 1) {
4932
4925
  const moduleName = parts[0];
4933
- const rest = parts.slice(1).join("/");
4926
+ const subfolder = parts[1];
4934
4927
  let layer = "root";
4935
- if (rest.startsWith("domain/") || rest === "domain" || rest.startsWith("errors/") || rest === "errors") {
4928
+ if (subfolder === "domain" || subfolder === "errors") {
4936
4929
  layer = "domain";
4937
- } else if (rest.startsWith("ports/") || rest === "ports") {
4930
+ } else if (subfolder === "ports") {
4938
4931
  layer = "ports";
4939
- } else if (rest.startsWith("infrastructure/") || rest === "infrastructure") {
4932
+ } else if (subfolder === "infrastructure") {
4940
4933
  layer = "infrastructure";
4941
4934
  }
4942
4935
  return { moduleType: "shared", moduleName, feature: moduleName, layer };
4943
4936
  }
4944
4937
  }
4945
- const relFeatures = path26.relative(normFeaturesBase, normFullPath).replace(/\\/g, "/");
4946
- if (!relFeatures.startsWith("..") && !path26.isAbsolute(relFeatures)) {
4947
- const parts = relFeatures.split("/").filter(Boolean);
4938
+ if (isUnder(normFeaturesBase, normFullPath)) {
4939
+ const rel = path26.relative(normFeaturesBase, normFullPath).replace(/\\/g, "/");
4940
+ const parts = rel.split("/").filter(Boolean);
4948
4941
  if (parts.length >= 2) {
4949
4942
  const moduleName = parts[0];
4950
4943
  const subfolder = parts[1];
@@ -4957,7 +4950,7 @@ function classifyFile(fullPathAbs, featuresBaseAbs, sharedBaseAbs, errorsBaseAbs
4957
4950
  layer = "services";
4958
4951
  } else if (subfolder === "infrastructure") {
4959
4952
  layer = "infrastructure";
4960
- } else if (subfolder === "pxExpress" || subfolder === "presentation" || subfolder === "handlers" || subfolder.startsWith("px")) {
4953
+ } else if (subfolder.startsWith("px") || subfolder === "presentation" || subfolder === "handlers" || subfolder === "transformers") {
4961
4954
  layer = "presentation";
4962
4955
  }
4963
4956
  return { moduleType: "feature", moduleName, feature: moduleName, layer };
@@ -4986,10 +4979,10 @@ function classifyTarget(specifier, sourceFileAbs, projectRoot, featuresBaseAbs,
4986
4979
  return { isExternal: true, isDiFramework: false };
4987
4980
  }
4988
4981
  if (!featuresBaseAbs || !sharedBaseAbs || !errorsBaseAbs) {
4989
- const paths = getResolvedLintPaths(projectRoot, loadLintConfig(projectRoot));
4990
- featuresBaseAbs = featuresBaseAbs || paths.featuresBase;
4991
- sharedBaseAbs = sharedBaseAbs || paths.sharedBase;
4992
- errorsBaseAbs = errorsBaseAbs || paths.errorsBase;
4982
+ const env = resolveLintEnvironment(projectRoot);
4983
+ featuresBaseAbs = featuresBaseAbs || env.featuresBase;
4984
+ sharedBaseAbs = sharedBaseAbs || env.sharedBase;
4985
+ errorsBaseAbs = errorsBaseAbs || env.errorsBase;
4993
4986
  }
4994
4987
  const isGlobalConfig = specifier === "@configs" || specifier.startsWith("@configs/") || specifier === "@/configs" || specifier.startsWith("@/configs/") || specifier === "~/configs" || specifier.startsWith("~/configs/") || specifier === "configs" || specifier.startsWith("configs/");
4995
4988
  let targetAbs = null;
@@ -5626,45 +5619,108 @@ private ${m.name}(...) { ... }`
5626
5619
  }
5627
5620
  }
5628
5621
  }
5622
+ function resolveRegistryModuleError(modDir, modName) {
5623
+ const errorsDir = path26.join(modDir, "errors");
5624
+ if (!fs17.existsSync(errorsDir) || !fs17.statSync(errorsDir).isDirectory()) {
5625
+ return { errorsDir, hasErrorsDir: false };
5626
+ }
5627
+ const entries = fs17.readdirSync(errorsDir);
5628
+ const errorFiles = entries.filter((f) => f.endsWith(".ts") || f.endsWith(".js"));
5629
+ const nameNormalized = modName.toLowerCase().replace(/[-_]/g, "");
5630
+ const singularNormalized = toSingular(modName).toLowerCase().replace(/[-_]/g, "");
5631
+ let baseErrorFileName = errorFiles.find((f) => {
5632
+ const baseNoExt = f.replace(/\.(ts|js)$/, "").toLowerCase().replace(/[-_]/g, "");
5633
+ return baseNoExt === `${nameNormalized}error` || baseNoExt === `${singularNormalized}error` || baseNoExt === `${nameNormalized}errors` || baseNoExt === `${singularNormalized}errors`;
5634
+ });
5635
+ if (!baseErrorFileName) {
5636
+ return { errorsDir, hasErrorsDir: true };
5637
+ }
5638
+ const baseErrorFileAbs = path26.join(errorsDir, baseErrorFileName);
5639
+ const content = fs17.readFileSync(baseErrorFileAbs, "utf-8");
5640
+ const classRegex = /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)(?:<[^>]+>)?(?:\s+extends\s+([A-Za-z0-9_]+))?/g;
5641
+ let match;
5642
+ const classes = [];
5643
+ while ((match = classRegex.exec(content)) !== null) {
5644
+ classes.push({
5645
+ name: match[1],
5646
+ extendsName: match[2],
5647
+ raw: match[0]
5648
+ });
5649
+ }
5650
+ const expectedNames = [
5651
+ `${toPascalCase(modName)}Error`,
5652
+ `${toPascalCase(toSingular(modName))}Error`,
5653
+ `${toPascalCase(modName)}Errors`,
5654
+ `${toPascalCase(toSingular(modName))}Errors`
5655
+ ].map((n) => n.toLowerCase());
5656
+ const targetClass = classes.find((c) => expectedNames.includes(c.name.toLowerCase())) || classes.find((c) => c.raw.includes("export")) || classes[0];
5657
+ return {
5658
+ errorsDir,
5659
+ hasErrorsDir: true,
5660
+ baseErrorFileAbs,
5661
+ baseErrorClassName: targetClass ? targetClass.name : void 0,
5662
+ baseErrorExtendsName: targetClass ? targetClass.extendsName : void 0,
5663
+ baseErrorRawClassCode: targetClass ? targetClass.raw : void 0
5664
+ };
5665
+ }
5629
5666
  function lintCodebase(options = {}) {
5630
5667
  const startTime = Date.now();
5631
5668
  const projectRoot = options.projectRoot || findProjectRoot(options.targetDir || process.cwd());
5632
5669
  const failFast = !options.complete;
5633
- const lintConfig = loadLintConfig(projectRoot);
5634
- const { featuresBase, sharedBase, errorsBase } = getResolvedLintPaths(projectRoot, lintConfig);
5635
- const missingFoundations = [];
5636
- if (!fs17.existsSync(featuresBase)) missingFoundations.push("features/");
5637
- if (!fs17.existsSync(sharedBase)) missingFoundations.push("shared/");
5638
- if (!fs17.existsSync(errorsBase)) missingFoundations.push("errors/");
5639
- if (missingFoundations.length > 0) {
5640
- throw new DependencyRuleError(
5641
- `Project Structure Violation: Missing required foundational directories: ${missingFoundations.join(", ")}. Every project must contain 'features/', 'shared/', and 'errors/'.`,
5642
- [],
5643
- true
5644
- );
5670
+ const effectiveMode = options.mode || getEffectiveMode(projectRoot, options.registry !== void 0 ? { registry: options.registry } : void 0);
5671
+ const isRegistryMode = effectiveMode === "registry";
5672
+ const { featuresBase, sharedBase, errorsBase, baseErrorAbs } = resolveLintEnvironment(projectRoot);
5673
+ if (!isRegistryMode) {
5674
+ const missingFoundations = [];
5675
+ if (!fs17.existsSync(featuresBase)) missingFoundations.push("features/");
5676
+ if (!fs17.existsSync(sharedBase)) missingFoundations.push("shared/");
5677
+ if (!fs17.existsSync(errorsBase)) missingFoundations.push("errors/");
5678
+ if (missingFoundations.length > 0) {
5679
+ throw new DependencyRuleError(
5680
+ `Project Structure Violation: Missing required foundational directories: ${missingFoundations.join(", ")}. Every architecture must contain 'features/', 'shared/', and 'errors/'.`,
5681
+ [],
5682
+ true
5683
+ );
5684
+ }
5685
+ if (!fs17.existsSync(baseErrorAbs)) {
5686
+ throw new DependencyRuleError(
5687
+ `Project Structure Violation: Base error class not found at '${path26.relative(projectRoot, baseErrorAbs).replace(/\\/g, "/")}'. Configure paths.baseError in mason.config.json.`,
5688
+ [],
5689
+ true
5690
+ );
5691
+ }
5692
+ } else {
5693
+ if (!fs17.existsSync(featuresBase) && !fs17.existsSync(sharedBase)) {
5694
+ throw new DependencyRuleError(
5695
+ `Project Structure Violation: Missing required foundational directories: features/ or shared/. A registry must contain 'features/' or 'shared/'.`,
5696
+ [],
5697
+ true
5698
+ );
5699
+ }
5645
5700
  }
5646
- const baseErrorRelative = lintConfig.baseErrorPath || path26.relative(projectRoot, path26.join(errorsBase, "AppError.ts")).replace(/\\/g, "/");
5647
- const baseErrorAbs = path26.resolve(projectRoot, baseErrorRelative);
5648
- if (!fs17.existsSync(baseErrorAbs)) {
5649
- throw new DependencyRuleError(
5650
- `Project Structure Violation: Base error class not found at '${baseErrorRelative}'. Create this file or update 'baseErrorPath' in mason-lint.config.json.`,
5651
- [],
5652
- true
5701
+ let baseErrorClassName = "AppError";
5702
+ if (!isRegistryMode && fs17.existsSync(baseErrorAbs)) {
5703
+ const baseErrorContent = fs17.readFileSync(baseErrorAbs, "utf-8");
5704
+ const baseClassMatch = baseErrorContent.match(
5705
+ /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)/
5653
5706
  );
5707
+ baseErrorClassName = baseClassMatch ? baseClassMatch[1] : "AppError";
5654
5708
  }
5655
- const baseErrorContent = fs17.readFileSync(baseErrorAbs, "utf-8");
5656
- const baseClassMatch = baseErrorContent.match(
5657
- /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)/
5658
- );
5659
- const baseErrorClassName = baseClassMatch ? baseClassMatch[1] : "AppError";
5660
5709
  const features = discoverAllFeatures(featuresBase, [sharedBase, errorsBase]);
5661
5710
  const sharedModules = discoverAllShared(sharedBase, [featuresBase, errorsBase]);
5662
- const errorModule = { name: "global-errors", dir: errorsBase, type: "error" };
5663
5711
  const allModules = [
5664
5712
  ...features.map((f) => ({ ...f, type: "feature" })),
5665
- ...sharedModules.map((s) => ({ ...s, type: "shared" })),
5666
- errorModule
5713
+ ...sharedModules.map((s) => ({ ...s, type: "shared" }))
5667
5714
  ];
5715
+ if (!isRegistryMode) {
5716
+ const errorModule = { name: "global-errors", dir: errorsBase, type: "error" };
5717
+ allModules.push(errorModule);
5718
+ } else if (fs17.existsSync(errorsBase)) {
5719
+ const errorFiles = scanDirFiles(errorsBase, projectRoot);
5720
+ if (errorFiles.length > 0) {
5721
+ allModules.push({ name: "global-errors", dir: errorsBase, type: "error" });
5722
+ }
5723
+ }
5668
5724
  const graph = new FeatureDependencyGraph();
5669
5725
  const allViolations = [];
5670
5726
  const results = [];
@@ -5698,6 +5754,77 @@ Code: ${v.code}`;
5698
5754
  }
5699
5755
  for (const mod of allModules) {
5700
5756
  const modResult = results.find((r) => r.featureName === mod.name);
5757
+ let modBaseErrorClass = baseErrorClassName;
5758
+ let modBaseErrorAbs = !isRegistryMode ? baseErrorAbs : void 0;
5759
+ if (isRegistryMode && (mod.type === "feature" || mod.type === "shared")) {
5760
+ const errorInfo = resolveRegistryModuleError(mod.dir, mod.name);
5761
+ if (!errorInfo.hasErrorsDir) {
5762
+ addViolation({
5763
+ feature: mod.name,
5764
+ layer: "domain",
5765
+ file: mod.dir,
5766
+ relativePath: path26.relative(projectRoot, errorInfo.errorsDir).replace(/\\/g, "/"),
5767
+ line: 1,
5768
+ category: "Project Structure Violation",
5769
+ code: `Missing errors/ directory in registry ${mod.type} '${mod.name}'`,
5770
+ ruleId: "REG_ERRORS_DIR_REQUIRED",
5771
+ severity: "error",
5772
+ advice: `Registry ${mod.type} '${mod.name}' must implement its own 'errors/' directory at '${path26.relative(projectRoot, errorInfo.errorsDir).replace(/\\/g, "/")}'.`,
5773
+ fixExample: {
5774
+ bad: "// Missing errors directory",
5775
+ good: `mkdir -p ${path26.relative(projectRoot, errorInfo.errorsDir).replace(/\\/g, "/")}`
5776
+ }
5777
+ });
5778
+ } else if (!errorInfo.baseErrorFileAbs) {
5779
+ const expectedFileName = `${toPascalCase(mod.name)}Error.ts`;
5780
+ const expectedRel = path26.relative(projectRoot, path26.join(errorInfo.errorsDir, expectedFileName)).replace(/\\/g, "/");
5781
+ addViolation({
5782
+ feature: mod.name,
5783
+ layer: "domain",
5784
+ file: errorInfo.errorsDir,
5785
+ relativePath: expectedRel,
5786
+ line: 1,
5787
+ category: "Project Structure Violation",
5788
+ code: `Missing base error file in '${mod.name}/errors'`,
5789
+ ruleId: "REG_BASE_ERROR_REQUIRED",
5790
+ severity: "error",
5791
+ advice: `Registry ${mod.type} '${mod.name}' must have a base error file at '${expectedRel}'.`,
5792
+ fixExample: {
5793
+ bad: "// Missing base error file",
5794
+ good: `export class ${toPascalCase(mod.name)}Error extends Error {
5795
+ constructor(message: string) {
5796
+ super(message);
5797
+ }
5798
+ }`
5799
+ }
5800
+ });
5801
+ } else {
5802
+ modBaseErrorAbs = errorInfo.baseErrorFileAbs;
5803
+ modBaseErrorClass = errorInfo.baseErrorClassName || `${toPascalCase(mod.name)}Error`;
5804
+ if (!errorInfo.baseErrorClassName || errorInfo.baseErrorExtendsName !== "Error") {
5805
+ addViolation({
5806
+ feature: mod.name,
5807
+ layer: "domain",
5808
+ file: errorInfo.baseErrorFileAbs,
5809
+ relativePath: path26.relative(projectRoot, errorInfo.baseErrorFileAbs).replace(/\\/g, "/"),
5810
+ line: 1,
5811
+ category: "Error Inheritance Violation",
5812
+ code: errorInfo.baseErrorRawClassCode || `class ${modBaseErrorClass}`,
5813
+ ruleId: "REG_BASE_ERROR_MUST_EXTEND_ERROR",
5814
+ severity: "error",
5815
+ advice: `Registry ${mod.type} base error class '${modBaseErrorClass}' in '${mod.name}' must extend native 'Error'.`,
5816
+ fixExample: {
5817
+ bad: errorInfo.baseErrorRawClassCode || `class ${modBaseErrorClass}`,
5818
+ good: `export class ${modBaseErrorClass} extends Error {
5819
+ constructor(message: string) {
5820
+ super(message);
5821
+ }
5822
+ }`
5823
+ }
5824
+ });
5825
+ }
5826
+ }
5827
+ }
5701
5828
  const allFiles = scanDirFiles(mod.dir, projectRoot);
5702
5829
  modResult.scannedFilesCount = allFiles.length;
5703
5830
  for (const file of allFiles) {
@@ -5725,15 +5852,15 @@ Code: ${v.code}`;
5725
5852
  code: lineCode,
5726
5853
  ruleId: "E3_PLAIN_ERROR_THROW",
5727
5854
  severity: "error",
5728
- advice: `Throwing plain 'Error' is prohibited. You must throw '${baseErrorClassName}' or a domain-specific error class that inherits from it.`,
5855
+ 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.`,
5729
5856
  fixExample: {
5730
5857
  bad: lineCode,
5731
- good: `throw new ${baseErrorClassName}("Something went wrong");`
5858
+ good: `throw new ${modBaseErrorClass}("Something went wrong");`
5732
5859
  }
5733
5860
  });
5734
5861
  }
5735
5862
  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");
5736
- const isBaseErrorFile = path26.resolve(file) === path26.resolve(baseErrorAbs);
5863
+ const isBaseErrorFile = modBaseErrorAbs ? path26.resolve(file) === path26.resolve(modBaseErrorAbs) : !isRegistryMode && path26.resolve(file) === path26.resolve(baseErrorAbs);
5737
5864
  if (isErrorFile && !isBaseErrorFile) {
5738
5865
  const classRegex = /(?:export\s+(?:default\s+)?)?(?:abstract\s+)?class\s+([A-Za-z0-9_]+)(?:<[^>]+>)?(?:\s+extends\s+([A-Za-z0-9_]+))?/g;
5739
5866
  let classMatch;
@@ -5755,10 +5882,10 @@ Code: ${v.code}`;
5755
5882
  code: lineCode,
5756
5883
  ruleId: "E4_MISSING_INHERITANCE",
5757
5884
  severity: "error",
5758
- advice: `Error class '${className}' must extend '${baseErrorClassName}' (or another class that derives from it).`,
5885
+ advice: isRegistryMode ? `Error class '${className}' in registry ${mod.type} '${mod.name}' must extend '${modBaseErrorClass}'.` : `Error class '${className}' must extend '${modBaseErrorClass}'.`,
5759
5886
  fixExample: {
5760
5887
  bad: lineCode,
5761
- good: `export class ${className} extends ${baseErrorClassName} { ... }`
5888
+ good: `export class ${className} extends ${modBaseErrorClass} { ... }`
5762
5889
  }
5763
5890
  });
5764
5891
  } else if (extendsName === "Error") {
@@ -5772,10 +5899,10 @@ Code: ${v.code}`;
5772
5899
  code: lineCode,
5773
5900
  ruleId: "E5_NATIVE_ERROR_INHERITANCE",
5774
5901
  severity: "error",
5775
- advice: `Error class '${className}' extends the native 'Error'. It must extend your base error class ('${baseErrorClassName}').`,
5902
+ 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}').`,
5776
5903
  fixExample: {
5777
5904
  bad: lineCode,
5778
- good: `export class ${className} extends ${baseErrorClassName} { ... }`
5905
+ good: `export class ${className} extends ${modBaseErrorClass} { ... }`
5779
5906
  }
5780
5907
  });
5781
5908
  }
@@ -6535,7 +6662,9 @@ async function handleLint(flags = {}) {
6535
6662
  targetDir: flags.targetDir || flags.target,
6536
6663
  projectRoot: flags.projectRoot,
6537
6664
  fixHint: flags.fixHint !== false,
6538
- throwOnError: false
6665
+ throwOnError: false,
6666
+ mode: flags.mode || (flags.registry ? "registry" : void 0),
6667
+ registry: Boolean(flags.registry)
6539
6668
  };
6540
6669
  try {
6541
6670
  const summary = lintCodebase(options);