lint: consolidate ajv-related code, visitor trait interfaces
This commit is contained in:
parent
9183ef3307
commit
de5dd2833a
|
@ -244,7 +244,7 @@ An example rule module [is available here](https://github.com/ssube/salty-dog-oo
|
||||||
## From Path
|
## From Path
|
||||||
|
|
||||||
Rules may be loaded from a directory. Files with `.json` and `.yaml`/`.yml` extensions will be loaded,
|
Rules may be loaded from a directory. Files with `.json` and `.yaml`/`.yml` extensions will be loaded,
|
||||||
with filenames lowercased before checking.
|
with file names converted to lowercase before being checked.
|
||||||
|
|
||||||
To load a directory: `--rule-path rules/`
|
To load a directory: `--rule-path rules/`
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
import { ValidateFunction } from 'ajv';
|
import { ErrorObject, ValidateFunction } from 'ajv';
|
||||||
import { cloneDeep, defaultTo, isNil } from 'lodash';
|
import { cloneDeep, defaultTo, isNil } from 'lodash';
|
||||||
import { LogLevel } from 'noicejs';
|
import { LogLevel } from 'noicejs';
|
||||||
|
|
||||||
import { Rule, RuleData } from '.';
|
import { Rule, RuleData } from '.';
|
||||||
import { hasItems } from '../utils';
|
import { hasItems } from '../utils';
|
||||||
import { friendlyError } from '../utils/ajv';
|
import { Visitor, VisitorError, VisitorResult } from '../visitor';
|
||||||
import { Visitor } from '../visitor';
|
|
||||||
import { VisitorContext } from '../visitor/VisitorContext';
|
import { VisitorContext } from '../visitor/VisitorContext';
|
||||||
import { VisitorError } from '../visitor/VisitorError';
|
|
||||||
import { VisitorResult } from '../visitor/VisitorResult';
|
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/strict-boolean-expressions */
|
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/strict-boolean-expressions */
|
||||||
|
|
||||||
|
@ -76,3 +73,22 @@ export class SchemaRule implements Rule, RuleData, Visitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function friendlyError(ctx: VisitorContext, err: ErrorObject, rule: SchemaRule): VisitorError {
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
err,
|
||||||
|
rule,
|
||||||
|
},
|
||||||
|
level: 'error',
|
||||||
|
msg: friendlyErrorMessage(err, rule),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function friendlyErrorMessage(err: ErrorObject, rule: SchemaRule): string {
|
||||||
|
if (isNil(err.message)) {
|
||||||
|
return `${err.dataPath} ${err.keyword} at ${rule.select} for ${rule.name}`;
|
||||||
|
} else {
|
||||||
|
return `${err.dataPath} ${err.message} at ${rule.select} for ${rule.name}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ import { join } from 'path';
|
||||||
import { YamlParser } from '../parser/YamlParser';
|
import { YamlParser } from '../parser/YamlParser';
|
||||||
import { readDir, readFile } from '../source';
|
import { readDir, readFile } from '../source';
|
||||||
import { ensureArray, hasItems } from '../utils';
|
import { ensureArray, hasItems } from '../utils';
|
||||||
|
import { VisitorResult } from '../visitor';
|
||||||
import { VisitorContext } from '../visitor/VisitorContext';
|
import { VisitorContext } from '../visitor/VisitorContext';
|
||||||
import { VisitorResult } from '../visitor/VisitorResult';
|
|
||||||
import { SchemaRule } from './SchemaRule';
|
import { SchemaRule } from './SchemaRule';
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import { ErrorObject } from 'ajv';
|
|
||||||
import { isNil } from 'lodash';
|
|
||||||
|
|
||||||
import { SchemaRule } from '../../rule/SchemaRule';
|
|
||||||
import { VisitorContext } from '../../visitor/VisitorContext';
|
|
||||||
import { VisitorError } from '../../visitor/VisitorError';
|
|
||||||
|
|
||||||
export function friendlyError(ctx: VisitorContext, err: ErrorObject, rule: SchemaRule): VisitorError {
|
|
||||||
return {
|
|
||||||
data: {
|
|
||||||
err,
|
|
||||||
rule,
|
|
||||||
},
|
|
||||||
level: 'error',
|
|
||||||
msg: friendlyErrorMessage(err, rule),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function friendlyErrorMessage(err: ErrorObject, rule: SchemaRule): string {
|
|
||||||
if (isNil(err.message)) {
|
|
||||||
return `${err.dataPath} ${err.keyword} at ${rule.select} for ${rule.name}`;
|
|
||||||
} else {
|
|
||||||
return `${err.dataPath} ${err.message} at ${rule.select} for ${rule.name}`;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,9 +2,8 @@ import Ajv from 'ajv';
|
||||||
import { JSONPath } from 'jsonpath-plus';
|
import { JSONPath } from 'jsonpath-plus';
|
||||||
import { Logger } from 'noicejs';
|
import { Logger } from 'noicejs';
|
||||||
|
|
||||||
|
import { VisitorError, VisitorResult } from '.';
|
||||||
import { doesExist, hasItems } from '../utils';
|
import { doesExist, hasItems } from '../utils';
|
||||||
import { VisitorError } from './VisitorError';
|
|
||||||
import { VisitorResult } from './VisitorResult';
|
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
import { LogLevel } from 'noicejs';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an runtime error, not an exception.
|
|
||||||
*/
|
|
||||||
export interface VisitorError {
|
|
||||||
data: any;
|
|
||||||
level: LogLevel;
|
|
||||||
msg: string;
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
export interface VisitorResult {
|
|
||||||
changes: ReadonlyArray<any>;
|
|
||||||
errors: ReadonlyArray<any>;
|
|
||||||
}
|
|
|
@ -1,5 +1,20 @@
|
||||||
|
import { LogLevel } from 'noicejs';
|
||||||
|
|
||||||
import { VisitorContext } from './VisitorContext';
|
import { VisitorContext } from './VisitorContext';
|
||||||
import { VisitorResult } from './VisitorResult';
|
|
||||||
|
/**
|
||||||
|
* This is a runtime error, not an exception.
|
||||||
|
*/
|
||||||
|
export interface VisitorError {
|
||||||
|
data: any;
|
||||||
|
level: LogLevel;
|
||||||
|
msg: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VisitorResult {
|
||||||
|
changes: ReadonlyArray<any>;
|
||||||
|
errors: ReadonlyArray<any>;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Visitor<TResult extends VisitorResult = VisitorResult> {
|
export interface Visitor<TResult extends VisitorResult = VisitorResult> {
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { expect } from 'chai';
|
||||||
import { NullLogger } from 'noicejs';
|
import { NullLogger } from 'noicejs';
|
||||||
import { stub } from 'sinon';
|
import { stub } from 'sinon';
|
||||||
|
|
||||||
import { SchemaRule } from '../../src/rule/SchemaRule';
|
import { friendlyError, SchemaRule } from '../../src/rule/SchemaRule';
|
||||||
import { VisitorContext } from '../../src/visitor/VisitorContext';
|
import { VisitorContext } from '../../src/visitor/VisitorContext';
|
||||||
import { describeLeaks, itLeaks } from '../helpers/async';
|
import { describeLeaks, itLeaks } from '../helpers/async';
|
||||||
|
|
||||||
|
@ -157,3 +157,29 @@ describeLeaks('schema rule', async () => {
|
||||||
expect(checkSpy, 'check spy should not have been called').to.have.callCount(0);
|
expect(checkSpy, 'check spy should not have been called').to.have.callCount(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('friendly errors', () => {
|
||||||
|
it('should have a message', () => {
|
||||||
|
const err = friendlyError(new VisitorContext({
|
||||||
|
innerOptions: {
|
||||||
|
coerce: false,
|
||||||
|
defaults: false,
|
||||||
|
mutate: false,
|
||||||
|
},
|
||||||
|
logger: NullLogger.global,
|
||||||
|
}), {
|
||||||
|
dataPath: 'test-path',
|
||||||
|
keyword: TEST_NAME,
|
||||||
|
params: { /* ? */ },
|
||||||
|
schemaPath: 'test-path',
|
||||||
|
}, new SchemaRule({
|
||||||
|
check: {},
|
||||||
|
desc: TEST_NAME,
|
||||||
|
level: 'info',
|
||||||
|
name: TEST_NAME,
|
||||||
|
select: '',
|
||||||
|
tags: [TEST_NAME],
|
||||||
|
}));
|
||||||
|
expect(err.msg).to.not.equal('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
import { expect } from 'chai';
|
|
||||||
import { NullLogger } from 'noicejs';
|
|
||||||
|
|
||||||
import { SchemaRule } from '../../../src/rule/SchemaRule';
|
|
||||||
import { friendlyError } from '../../../src/utils/ajv';
|
|
||||||
import { VisitorContext } from '../../../src/visitor/VisitorContext';
|
|
||||||
|
|
||||||
const TEST_NAME = 'test';
|
|
||||||
|
|
||||||
describe('friendly errors', () => {
|
|
||||||
it('should have a message', () => {
|
|
||||||
const err = friendlyError(new VisitorContext({
|
|
||||||
innerOptions: {
|
|
||||||
coerce: false,
|
|
||||||
defaults: false,
|
|
||||||
mutate: false,
|
|
||||||
},
|
|
||||||
logger: NullLogger.global,
|
|
||||||
}), {
|
|
||||||
dataPath: 'test-path',
|
|
||||||
keyword: TEST_NAME,
|
|
||||||
params: { /* ? */ },
|
|
||||||
schemaPath: 'test-path',
|
|
||||||
}, new SchemaRule({
|
|
||||||
check: {},
|
|
||||||
desc: TEST_NAME,
|
|
||||||
level: 'info',
|
|
||||||
name: TEST_NAME,
|
|
||||||
select: '',
|
|
||||||
tags: [TEST_NAME],
|
|
||||||
}));
|
|
||||||
expect(err.msg).to.not.equal('');
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Reference in New Issue