1
0
Fork 0

lint: consolidate ajv-related code, visitor trait interfaces

This commit is contained in:
ssube 2019-11-03 13:42:43 -06:00 committed by Sean Sube
parent 9183ef3307
commit de5dd2833a
10 changed files with 67 additions and 84 deletions

View File

@ -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/`

View File

@ -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}`;
}
}

View File

@ -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 */

View File

@ -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}`;
}
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -1,4 +0,0 @@
export interface VisitorResult {
changes: ReadonlyArray<any>;
errors: ReadonlyArray<any>;
}

View File

@ -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> {
/** /**

View File

@ -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('');
});
});

View File

@ -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('');
});
});