lint: move rule iteration to its own fn
This commit is contained in:
parent
9eacea6b61
commit
18a3321061
34
src/index.ts
34
src/index.ts
|
@ -1,11 +1,9 @@
|
||||||
import { createLogger } from 'bunyan';
|
import { createLogger } from 'bunyan';
|
||||||
import { applyDiff, diff } from 'deep-diff';
|
|
||||||
import { cloneDeep } from 'lodash';
|
|
||||||
import { Options, usage } from 'yargs';
|
import { Options, usage } from 'yargs';
|
||||||
|
|
||||||
import { loadConfig } from 'src/config';
|
import { loadConfig } from 'src/config';
|
||||||
import { YamlParser } from 'src/parser/YamlParser';
|
import { YamlParser } from 'src/parser/YamlParser';
|
||||||
import { loadRules, resolveRules } from 'src/rule';
|
import { loadRules, resolveRules, visitRules } from 'src/rule';
|
||||||
import { loadSource, writeSource } from 'src/source';
|
import { loadSource, writeSource } from 'src/source';
|
||||||
import { VERSION_INFO } from 'src/version';
|
import { VERSION_INFO } from 'src/version';
|
||||||
import { VisitorContext } from 'src/visitor/context';
|
import { VisitorContext } from 'src/visitor/context';
|
||||||
|
@ -21,7 +19,7 @@ const RULE_OPTION: Options = {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
};
|
};
|
||||||
|
|
||||||
const MAIN_ARGS = usage(`Usage: salty-dog <mode> [options]`)
|
const MAIN_ARGS = usage(`Usage: salty-dog [-m mode] [options]`)
|
||||||
.option(CONFIG_ARGS_NAME, {
|
.option(CONFIG_ARGS_NAME, {
|
||||||
default: `.${VERSION_INFO.app.name}.yml`,
|
default: `.${VERSION_INFO.app.name}.yml`,
|
||||||
group: 'Config:',
|
group: 'Config:',
|
||||||
|
@ -95,6 +93,7 @@ export async function main(argv: Array<string>): Promise<number> {
|
||||||
// check mode
|
// check mode
|
||||||
if (!MODES.includes(args.mode)) {
|
if (!MODES.includes(args.mode)) {
|
||||||
logger.error({ mode: args.mode }, 'unsupported mode');
|
logger.error({ mode: args.mode }, 'unsupported mode');
|
||||||
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const schema = new Schema();
|
// const schema = new Schema();
|
||||||
|
@ -123,32 +122,7 @@ export async function main(argv: Array<string>): Promise<number> {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const data of docs) {
|
for (const data of docs) {
|
||||||
for (const rule of activeRules) {
|
await visitRules(ctx, activeRules, data);
|
||||||
const items = await rule.pick(ctx, data);
|
|
||||||
for (const item of items) {
|
|
||||||
const itemCopy = cloneDeep(item);
|
|
||||||
const itemResult = await rule.visit(ctx, itemCopy);
|
|
||||||
|
|
||||||
if (itemResult.errors.length > 0) {
|
|
||||||
logger.warn({ count: itemResult.errors.length, rule }, 'rule failed');
|
|
||||||
|
|
||||||
ctx.mergeResult(itemResult);
|
|
||||||
} else {
|
|
||||||
const itemDiff = diff(item, itemCopy);
|
|
||||||
if (Array.isArray(itemDiff) && itemDiff.length > 0) {
|
|
||||||
logger.info({
|
|
||||||
diff: itemDiff,
|
|
||||||
item,
|
|
||||||
rule: rule.name,
|
|
||||||
}, 'rule passed with modifications');
|
|
||||||
|
|
||||||
applyDiff(item, itemCopy);
|
|
||||||
} else {
|
|
||||||
logger.info({ rule: rule.name }, 'rule passed');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.errors.length > 0) {
|
if (ctx.errors.length > 0) {
|
||||||
|
|
35
src/rule.ts
35
src/rule.ts
|
@ -1,3 +1,4 @@
|
||||||
|
import { applyDiff, diff } from 'deep-diff';
|
||||||
import { JSONPath } from 'jsonpath-plus';
|
import { JSONPath } from 'jsonpath-plus';
|
||||||
import { cloneDeep, intersection, isNil } from 'lodash';
|
import { cloneDeep, intersection, isNil } from 'lodash';
|
||||||
import { LogLevel } from 'noicejs';
|
import { LogLevel } from 'noicejs';
|
||||||
|
@ -114,9 +115,39 @@ export async function resolveRules(rules: Array<Rule>, selector: RuleSelector):
|
||||||
return Array.from(activeRules);
|
return Array.from(activeRules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function visitRules(ctx: VisitorContext, rules: Array<Rule>, data: any): Promise<VisitorContext> {
|
||||||
|
for (const rule of rules) {
|
||||||
|
const items = await rule.pick(ctx, data);
|
||||||
|
for (const item of items) {
|
||||||
|
const itemCopy = cloneDeep(item);
|
||||||
|
const itemResult = await rule.visit(ctx, itemCopy);
|
||||||
|
|
||||||
|
if (itemResult.errors.length > 0) {
|
||||||
|
ctx.logger.warn({ count: itemResult.errors.length, rule }, 'rule failed');
|
||||||
|
ctx.mergeResult(itemResult);
|
||||||
|
} else {
|
||||||
|
const itemDiff = diff(item, itemCopy);
|
||||||
|
if (Array.isArray(itemDiff) && itemDiff.length > 0) {
|
||||||
|
ctx.logger.info({
|
||||||
|
diff: itemDiff,
|
||||||
|
item,
|
||||||
|
rule: rule.name,
|
||||||
|
}, 'rule passed with modifications');
|
||||||
|
|
||||||
|
applyDiff(item, itemCopy);
|
||||||
|
} else {
|
||||||
|
ctx.logger.info({ rule: rule.name }, 'rule passed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
export interface RuleResult extends VisitorResult {
|
export interface RuleResult extends VisitorResult {
|
||||||
rule: Rule;
|
rule: Rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Rule implements RuleData, Visitor<RuleResult> {
|
export class Rule implements RuleData, Visitor<RuleResult> {
|
||||||
public readonly check: any;
|
public readonly check: any;
|
||||||
|
@ -156,7 +187,7 @@ export class Rule implements RuleData, Visitor<RuleResult> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async visit(ctx: VisitorContext, node: any): Promise<RuleResult> {
|
public async visit(ctx: VisitorContext, node: any): Promise<RuleResult> {
|
||||||
ctx.logger.debug({ item: node, rule: this}, 'visiting node');
|
ctx.logger.debug({ item: node, rule: this }, 'visiting node');
|
||||||
|
|
||||||
const check = ctx.ajv.compile(this.check);
|
const check = ctx.ajv.compile(this.check);
|
||||||
const filter = this.compileFilter(ctx);
|
const filter = this.compileFilter(ctx);
|
||||||
|
|
Loading…
Reference in New Issue