diff --git a/sample/src/componentA/fence.json b/sample/src/componentA/fence.json index c0ba3e2..a747ef2 100644 --- a/sample/src/componentA/fence.json +++ b/sample/src/componentA/fence.json @@ -2,5 +2,6 @@ "tags": [ "tagA" ], "exports": { "componentA": "*" - } + }, + "imports":[] } \ No newline at end of file diff --git a/src/core/cli.ts b/src/core/cli.ts index c561dbe..3a5ebcc 100644 --- a/src/core/cli.ts +++ b/src/core/cli.ts @@ -17,8 +17,8 @@ let hadError = false; // Run good-fences run({ ...options, - onError(message) { - console.error(`Error: ${message}`); + onError(error) { + console.error(error.detailedMessage); hadError = true; }, }); diff --git a/src/core/reportError.ts b/src/core/reportError.ts index 229fc44..eb78ede 100644 --- a/src/core/reportError.ts +++ b/src/core/reportError.ts @@ -1,7 +1,27 @@ +import * as path from 'path'; import getOptions from '../utils/getOptions'; +import Config from '../types/Config'; + +export default function reportError( + message: string, + sourceFile: string, + rawImport: string, + config: Config +) { + let fencePath = config.path + path.sep + 'fence.json'; + + let detailedMessage = + `Good-fences violation in ${sourceFile}:\n` + + ` ${message}: ${rawImport}\n` + + ` Fence: ${fencePath}`; -export default function reportError(message: string) { if (getOptions().onError) { - getOptions().onError(message); + getOptions().onError({ + message, + sourceFile, + rawImport, + fencePath, + detailedMessage, + }); } } diff --git a/src/types/NormalizedOptions.ts b/src/types/NormalizedOptions.ts index eb3eb7c..d8afee0 100644 --- a/src/types/NormalizedOptions.ts +++ b/src/types/NormalizedOptions.ts @@ -1,7 +1,9 @@ import NormalizedPath from './NormalizedPath'; +import ValidationError from './ValidationError'; export default interface NormalizedOptions { project: NormalizedPath; rootDir: NormalizedPath; - onError?: (message: string) => void; + ignoreExternalFences: boolean; + onError?: (error: ValidationError) => void; }; diff --git a/src/types/Options.ts b/src/types/Options.ts index 7788d3a..268c8f8 100644 --- a/src/types/Options.ts +++ b/src/types/Options.ts @@ -1,5 +1,8 @@ +import ValidationError from './ValidationError'; + export default interface Options { project?: string; rootDir?: string; - onError?: (message: string) => void; + ignoreExternalFences?: boolean; + onError?: (error: ValidationError) => void; }; diff --git a/src/types/ValidationError.ts b/src/types/ValidationError.ts new file mode 100644 index 0000000..c887039 --- /dev/null +++ b/src/types/ValidationError.ts @@ -0,0 +1,7 @@ +export default interface ValidationError { + message: string; + sourceFile: string; + rawImport: string; + fencePath: string; + detailedMessage: string; +}; diff --git a/src/utils/getAllConfigs.ts b/src/utils/getAllConfigs.ts index 580ab06..5a558a8 100644 --- a/src/utils/getAllConfigs.ts +++ b/src/utils/getAllConfigs.ts @@ -13,6 +13,11 @@ export default function getAllConfigs(): ConfigSet { // Glob for configs under the project root directory let files = glob.sync(normalizePath(getOptions().rootDir, '**/fence.json')); + + if (getOptions().ignoreExternalFences) { + files = files.filter(f => f.split(path.sep).indexOf('node_modules') > -1); + } + files.forEach(file => { let configPath = normalizePath(path.dirname(file)); configSet[configPath] = JSON.parse(fs.readFileSync(file).toString()); diff --git a/src/utils/getOptions.ts b/src/utils/getOptions.ts index 89edbf1..9d1c8eb 100644 --- a/src/utils/getOptions.ts +++ b/src/utils/getOptions.ts @@ -18,6 +18,7 @@ export function setOptions(providedOptions: Options) { options = { project, rootDir, + ignoreExternalFences: providedOptions.ignoreExternalFences, onError: providedOptions.onError, }; } diff --git a/src/validation/validateDependencyRules.ts b/src/validation/validateDependencyRules.ts index 3392b80..d69303c 100644 --- a/src/validation/validateDependencyRules.ts +++ b/src/validation/validateDependencyRules.ts @@ -43,7 +43,7 @@ function validateConfig(config: Config, sourceFile: NormalizedPath, importRecord } // If we made it here, we didn't find a rule that allows the dependency - reportError(`${sourceFile} is not allowed to import '${importRecord.rawImport}'`); + reportError('Dependency is not allowed', sourceFile, importRecord.rawImport, config); } function getFullDependencyRule(dependency: DependencyRule): FullDependencyRule { diff --git a/src/validation/validateExportRules.ts b/src/validation/validateExportRules.ts index 25709ab..6cde884 100644 --- a/src/validation/validateExportRules.ts +++ b/src/validation/validateExportRules.ts @@ -33,7 +33,7 @@ function validateConfig(config: Config, sourceFile: NormalizedPath, importFile: } // If we made it here, the import is invalid - reportError(`${sourceFile} is importing inaccessible module ${importFile}`); + reportError('Module is not exported', sourceFile, importFile, config); } function hasMatchingExport(config: Config, sourceFile: NormalizedPath, importFile: NormalizedPath) { diff --git a/src/validation/validateImportRules.ts b/src/validation/validateImportRules.ts index 6c5bd7d..1361b05 100644 --- a/src/validation/validateImportRules.ts +++ b/src/validation/validateImportRules.ts @@ -39,5 +39,5 @@ function validateConfig(config: Config, sourceFile: NormalizedPath, importRecord } // If we made it here, the import is invalid - reportError(`${sourceFile} is not allowed to import '${importRecord.rawImport}'`); + reportError('Import not allowed', sourceFile, importRecord.rawImport, config); } diff --git a/tsconfig.json b/tsconfig.json index bf01d69..cf7235e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,8 @@ "sourceMap": false, "outDir": "lib", "noImplicitAny": true, - "noUnusedLocals": true + "noUnusedLocals": true, + "noImplicitThis": true }, "exclude": [ "node_modules",