Repolinter is broken down into 7 main components, each of which is contained in a subfolder:
- Axioms - located under axioms
- CLI - located under bin
- Rules - located under rules
- Fixes - located under fixes
- Formatters - located under formatters
- Utilities - located under lib
- Built-In Rulesets and Schema - located under rulesets
Axioms are registered in axioms/axioms.js and in rulesets/schema.json. An axiom implementation consists of a module with the following interface:
async (fs: FileSystem) => Result
Where fs is a FileSystem
scoped to the current repository.
The contents of the result should be an array of targets where t.path
is a target that the axiom has determined is valid (ex. for language detecting axiom a possible result could be new Result('', [{ path: 'javascript' passed: true }, { path: 'typescript', passed: true}], true)
). If the axiom fails to execute, it should return a failing result with an error message included instead of throwing an error.
A rule consists of two parts: a JavaScript module, which determines the rule's functionality and a JSON schema, which validates the rule's configuration options in rulesets. Rules are registered in rules/rules.js and rulesets/schema.json. Rules are also documented under rules.md.
The configuration JSON schema determines how rule.options
should be validated for this rule. All JSON Schema tools supported by AJV all available, with a few important caveats:
- The file itself should always be named
<rule-name>-config.json
and be located under therules
folder. - The top-level type should always be
object
. - The
$id
field should be an absolute raw.githubusercontent.com URL to where the schema is hosted on GitHub (ex. https://raw.githubusercontent.com/todogroup/repolinter/master/rules/apache-notice-config.json). This allows IDEs such as VSCode to apply the schema via a URL.
To get started, you can use the following template:
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://raw.githubusercontent.com/todogroup/repolinter/master/rules/<rule-name>-config.json",
"type": "object",
"properties": {}
}
Due to limitations with JSON Schema, you also must register your rule configuration schema in rulesets/schema.json by adding the following item to the list under root.then.properties.rules.properties.rule.allOf
:
{ "if": { "properties": { "type": { "const": "<rule-name>" } } }, "then": { "properties": { "options": { "$ref": "../rules/<rule-name>-config.json" } } } }
A rule implementation consists of a module with the following interface:
async (fs: FileSystem, opts /* type determined by your JSON schema */) => Result
Where fs is a FileSystem
scoped to the current repository and opts
is the options provided by the ruleset.
A rule implementation is encouraged to use Result#targets
to show the individual files/patterns checked when processing the rule. Including filenames in Result#message
is discouraged as it makes formatting difficult. If a rule fails to execute, it should throw an error.
A fix, similar to a rule, consists of two parts: a JavaScript module, which determines the fix's functionality and a JSON schema, which validates the fix's configuration options in rulesets. Fixes are registered in fixes/fixes.js and rulesets/schema.json. Fixes are also documented under fixes.md.
Fix JSON schemas work identically to rule JSON schemas, with the only difference the respective names and paths.
To get started, you can use the following template:
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://raw.githubusercontent.com/todogroup/repolinter/master/fixes/<fix-name>-config.json",
"type": "object",
"properties": {}
}
Similar as with rules, you must register the fix schema in rulesets/schema.json by adding the following item to the list under root.then.properties.rules.properties.fix.allOf
(note that this is a different list than the rule registration list):
{ "if": { "properties": { "type": { "const": "<fix-name>" } } }, "then": { "properties": { "options": { "$ref": "../rules/<fix-name>-config.json" } } } }
Unlike rules, a fix implementation consists of a module with the following interface:
async (fs: FileSystem, options /* Type determined by your JSON schema */, targets: string[], dryRun: boolean) => Result
Where fs is a FileSystem
scoped to the current repository, opts
is the options provided by the ruleset, targets
are filepaths which did not pass the rule associated with this fix, and dryRun
determines if the fix is allowed to make changes to the repository.
The fix implementation is encouraged to use Result#targets
to show the individual files/patterns changed. If the fix fails to execute, it should either return a failed result or throw an error.
Formatters are exported by index.js and manually called by the CLI. A formatter implementation consists of the following interface:
interface Formatter {
formatOutput(output: LintResult, dryRun: boolean): string
}
Formatters do not print to STDOUT
instead choosing to return the output as a string.
If needed, a formatter can accept extra configuration from the ruleset through the formatOptions
property, which will be directly passed through to LintResult#formatOptions
. These options are not typed and are formatter dependent.