@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.cjs +216 -87
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +216 -87
- package/dist/bin.js.map +1 -1
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/core/lintEngine.d.ts +15 -0
- package/dist/core/lintEngine.d.ts.map +1 -1
- package/dist/index.cjs +225 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +225 -65
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lint.d.ts +8 -5
- package/dist/types/lint.d.ts.map +1 -1
- package/dist/utils/config.d.ts +10 -8
- package/dist/utils/config.d.ts.map +1 -1
- package/package.json +1 -1
- package/schema.json +7 -13
|
@@ -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,
|
|
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":"AAEA,OAAO,KAAK,EACV,sBAAsB,EAEtB,yBAAyB,EACzB,SAAS,EACT,WAAW,EACX,WAAW,EAEX,UAAU,EAEV,SAAS,EACV,MAAM,kBAAkB,CAAC;AAK1B,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,SAAgB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxC,SAAgB,UAAU,EAAE,OAAO,CAAC;IAEpC,YAAY,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,UAAU,GAAE,OAAe,EAKhF;CACF;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACrC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,cAAc,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACtC;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAa1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAyBxE;AAED,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EACvB,aAAa,CAAC,EAAE,MAAM,EACtB,aAAa,CAAC,EAAE,MAAM,GACrB;IACD,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,KAAK,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CAC/B,
|
|
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
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
|
235
|
-
const configuredShared = config
|
|
236
|
-
const configuredErrors = config
|
|
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
|
|
4949
|
-
featuresBaseAbs =
|
|
4950
|
-
sharedBaseAbs =
|
|
4951
|
-
errorsBaseAbs =
|
|
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
|
|
4958
|
-
|
|
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
|
-
|
|
4967
|
-
|
|
4968
|
-
const parts =
|
|
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
|
|
4995
|
+
const subfolder = parts[1];
|
|
4972
4996
|
let layer = "root";
|
|
4973
|
-
if (
|
|
4997
|
+
if (subfolder === "domain" || subfolder === "errors") {
|
|
4974
4998
|
layer = "domain";
|
|
4975
|
-
} else if (
|
|
4999
|
+
} else if (subfolder === "ports") {
|
|
4976
5000
|
layer = "ports";
|
|
4977
|
-
} else if (
|
|
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
|
-
|
|
4984
|
-
|
|
4985
|
-
const parts =
|
|
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
|
|
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
|
|
5028
|
-
featuresBaseAbs = featuresBaseAbs ||
|
|
5029
|
-
sharedBaseAbs = sharedBaseAbs ||
|
|
5030
|
-
errorsBaseAbs = errorsBaseAbs ||
|
|
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
|
|
5672
|
-
const
|
|
5673
|
-
const
|
|
5674
|
-
if (!
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
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
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
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 '${
|
|
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 ${
|
|
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 '${
|
|
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 ${
|
|
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
|
|
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 ${
|
|
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);
|