Statoscope stats validator
npm install @statoscope/stats-validator

This package contains a toolkit to validate stats.
Create the Validator instance with config (see below), relative rootDir-directory (current working directory by default)
Apply rules to input and reference (if specified) files.
input-file is a current stats (e.g. stats of current branch).
reference-file is a stats to compare with (e.g. stats of master branch).
Returns validation results (see below).
``ts`
type Config = {
plugins?: Array
rules: Record
reporters?: ReporterConfig[];
warnAsError?: boolean;
};
List of plugins (see more about plugins API below).
The main goal of a plugin is providing some rules for validation.
There is a plugin to validate webpack stats (need to be installed)
npm install --save-dev @statoscope/stats-validator-plugin-webpack
statoscope.config.js:
`js`
module.export = {
validate: {
plugins: ['@statoscope/webpack'],
rules: {
'@statoscope/webpack/no-modules-deopts': ["error"]
}
}
};
#### Plugin path resolution
There are a few ways to how you can specify a plugin name:
- full package name
- short package name (please see example below)
- relative or absolute path
Here are the examples with all possible ways:
statoscope.config.js:
`js`
module.export = {
validate: {
plugins: [
'statoscope-stats-validator-plugin-foo', // full package name
'@statoscope/webpack', // short package name, resolves to @statoscope/stats-validator-plugin-webpack
'@foo/my-validator', // short package name, resolves to @foo/statoscope-stats-validator-plugin-my-validator
'webpack', // short package name, resolves to statoscope-stats-validator-plugin-webpack
['./my/plugin.js', 'my-plugin'], // relative path (relative config path)
[require.resolve('./my/another/plugin.js'), 'my-another-plugin'] // absolute path
],
rules: {
'statoscope-stats-validator-plugin-foo/some-rule': ['error'],
'@statoscope/webpack/no-modules-deopts': ['error'],
'foo/some-rule': ['error'],
'my-plugin/some-rule': ['error'],
'my-another-plugin/some-rule': ['error'],
}
}
};
To use short package name, its name must have statoscope-stats-validator-plugin--prefix or @statoscope/stats-validator-plugin--prefix.
Note that relative or absolute path should be specified with an alias
List of rules (see more about rules API below).
Rule validates some part of a bundle.
Every item of the list contains: rule name, execution mode and rule options (optional).
Execution modes:
- error - rules messages have treated as an errorwarn
- - rules messages have treated as a warningoff
- - rules messages have ignored
statoscope.config.js:
`js`
module.export = {
validate: {
plugins: [
'@statoscope/webpack',
],
rules: {
'@statoscope/webpack/restricted-packages': ['error', ['lodash']],
}
}
};
List of reporters (see more about reporters API below).
Reporter handles validation results.
There are two builtin reporters:
statoscope.config.js:
`js`
module.export = {
validate: {
plugins: [
'@statoscope/webpack',
],
reporters: [
'statoscope-stats-validator-reporter-foo', // full package name
'@statoscope/stats-report', // short package name, resolves to @statoscope/stats-validator-reporter-stats-report
'stats-report', // short package name, resolves to @statoscope/stats-validator-reporter-stats-report or statoscope-stats-validator-reporter-stats-report
['./my/plugin.js', 'my-report'], // relative path (relative config path)
[require.resolve('./my/another/report.js'), 'my-another-report'] // absolute path
],
rules: {
'@statoscope/webpack/restricted-packages': ['error', ['lodash']],
}
}
};
To use short package name, its name must have statoscope-stats-validator-reporter--prefix or @statoscope/stats-validator-reporter--prefix.
ConsoleReporter has used by default.
Treat warn-messages from rules as errors.
Plugin is a function that must return a plugin descriptor:
`js`
const myPlugin = () => {
return {
prepare(files) {
return doSomethingWithFiles(files);
},
rules: {
foo: fooRule,
bar: barRule,
}
};
};
prepare-function of every plugin will be called for input and reference files.
List of rules that plugin provides.
Rule is a function that validates some part of bundle:
`js`
const myRule = (params, data, api) => {
if (!isOK(data)) {
api.message('Something is wrong');
}
}
- params - options from config (e.g. 'my-plugin/my-rule': ['error', { foo: 'bar'}])data
- - input and reference files contentapi
- - rule API instance
Add validation message from the rule.
#### options.filename?: string
File name that the message has associated with
#### options.compilation?: string
Compilation id that the message has associated with
#### options.related?: RelatedItem[]
Entities that the message has associated with
`js`
api.message(
'Something is wrong with module ./foo.js',
{
related: [
{ type: 'module', id: './foo.js' }
]
}
);
There are several types of related items:
- modulepackage
- package-instance
- resource
- entry
- compilation
-
#### options.details?: Details
Details for reporters
There are several types of details:
text
Used by text-reporters
`js`
api.message(
'Something is wrong with module ./foo.js',
{
details: [
{
type: 'text',
content: [
'Here are the module reasons:',
...module.resons.map(r => r.name)
]
}
]
}
);
``
ā Something is wrong with module ./foo.js
Here are the module reasons:
./bar.js
./baz.js
> content might be string | string[] | (() => string | string[])
tty
Used by TTY-reporters (e.g. ConsoleReporter)
`js
import chalk from 'chalk';
api.message(
'Something is wrong with module ./foo.js',
{
details: [
{
type: 'tty',
content: [
chalk.cyan('Here are the module reasons:'),
...module.resons.map(r => chalk.yellow(r.name))
]
}
]
}
);
`
> content might be string | string[] | (() => string | string[])
discovery
Used by discovery-reporters (e.g. StatsReportReporter)
The main idea around this type of details is passing some data to stats report viewer (based on DiscoveryJS).
It helps to discover validation message with flexible UI.
`jsModule ${module.name} should not be used
api.message(, {
details: [
{
type: 'discovery',
query:
$input: resolveInputFile();
{ module: #.module.resolveModule(#.compilation) }
,{ module }
payload: {
context: {
compilation: compilation.hash,
module: module.name,
},
},
view: {
view: 'module-item',
data: `
}
},
],
});
See examples at Stats Validator Webpack Plugin
Get list of validation messages (results) that was emitted by the rule.
`js
const items = api.getStorage();
for (const item of items) {
console.log(item.message);
}
`
Every storage item has the following format:
`ts`
type Item = {
message: string; // item message
filename?: string; // file name that the message has associated with
compilation?: string; // compilation id that the message has associated with
details?: Details; // rule's details (see api.message method for more info)
related?: RelatedItem[]; // rule's related entities (see api.message method for more info)
};
Set rule meta-data.
`jsMy pretty cool rule
api.setRuleDescriptor({
description: ,`
package: {
name: 'my-package-with-validator-plugin',
version: '7.7.7',
},
});
Get rule meta-data
Reporter is a class with run method:
`ts`
interface Reporter {
run(result: Result): Promise
}
Example:
`jsRule name: ${rule.name}
class MyConsoleReporter {
run(result) {
for (const rule of result.rules) {
const ruleDescriptor = rule.api.getRuleDescriptor();
console.log();Rule description: ${ruleDescriptor.description}
console.log();
const items = rule.api.getStorage();
for (const item of items) {
console.log(item.message);
for (const detail of item.details) {
if (detail.type === 'tty') {
console.log(detail.content);
}
}
}
}
}
}
`
Create custom plugin script:
__my-custom-stats-validator-plugin.js:__
`js
module.exports = () => {
return {
rules: {
'my-rule': (ruleParams, data, api) => {
const result = data.query('some jora query', data.files, {ruleParams});
if(result.notOk) {
api.message(':(')
}
}
}
}
}
`
Add this plugin to statoscope config:
__statoscope.config.js:__
`js``
module.exports = {
validate: {
plugins: ['@statoscope/webpack', ['./my-custom-stats-validator-plugin.js', 'my-plugin']],
rules: {
'@statoscope/webpack/restricted-packages': ['error', ['foo']],
'my-plugin/my-rule': ['error', 'rule params'],
},
}
}
> For more rule examples, please see existing rule sources