Skip to content

Commit

Permalink
perf: minor tweaks to core functions
Browse files Browse the repository at this point in the history
  • Loading branch information
P0lip committed May 26, 2020
1 parent 9f203d0 commit fd3e70d
Show file tree
Hide file tree
Showing 11 changed files with 49 additions and 54 deletions.
16 changes: 8 additions & 8 deletions src/functions/__tests__/alphabetical.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ function runAlphabetical(target: any, keyedBy?: string) {
}

describe('alphabetical', () => {
test('given falsy target should return empty array', () => {
expect(runAlphabetical(false)).toEqual([]);
test('given falsy target should return nothing', () => {
expect(runAlphabetical(false)).toBeUndefined();
});

test('given single element target should return empty array', () => {
expect(runAlphabetical(['a'])).toEqual([]);
test('given single element target should return nothing', () => {
expect(runAlphabetical(['a'])).toBeUndefined();
});

test('given an object and keys not in order return an error message', () => {
Expand Down Expand Up @@ -68,7 +68,7 @@ describe('alphabetical', () => {
});

test('given a sorted array of strings should NOT return error', () => {
expect(runAlphabetical(['a', 'ab'])).toEqual([]);
expect(runAlphabetical(['a', 'ab'])).toBeUndefined();
});

test('given an unsorted array of numbers should return error', () => {
Expand All @@ -81,7 +81,7 @@ describe('alphabetical', () => {
});

test('given an array of objects should NOT return an error', () => {
expect(runAlphabetical([{ a: '10' }, { b: '1' }])).toEqual([]);
expect(runAlphabetical([{ a: '10' }, { b: '1' }])).toBeUndefined();
});
});

Expand All @@ -95,11 +95,11 @@ describe('alphabetical', () => {
});

test('given an array of objects with sorted prop values to NOT return an error', () => {
expect(runAlphabetical([{ a: '1' }, { a: '2' }, { a: '2' }], 'a')).toEqual([]);
expect(runAlphabetical([{ a: '1' }, { a: '2' }, { a: '2' }], 'a')).toBeUndefined();
});

test('given an array primitives should not return error', () => {
expect(runAlphabetical([100, 1], 'a')).toEqual([]);
expect(runAlphabetical([100, 1], 'a')).toBeUndefined();
});
});

Expand Down
4 changes: 2 additions & 2 deletions src/functions/__tests__/unreferencedReusableObject.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('unreferencedReusableObject', () => {
expect(() => runUnreferencedReusableObject({}, 'Nope')).toThrow();
});

test('given a non object data should return empty array', () => {
expect(runUnreferencedReusableObject('Nope', '#')).toEqual([]);
test('given a non object data should return nothing', () => {
expect(runUnreferencedReusableObject('Nope', '#')).toBeUndefined();
});
});
37 changes: 18 additions & 19 deletions src/functions/alphabetical.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { isObject } from 'lodash';
import { IFunction, IFunctionResult } from '../types';
import { IFunction } from '../types';

export interface IAlphaRuleOptions {
/** if sorting array of objects, which key to use for comparison */
Expand Down Expand Up @@ -29,13 +29,9 @@ const getUnsortedItems = <T>(arr: T[], compareFn: (a: T, B: T) => number): null
};

export const alphabetical: IFunction<IAlphaRuleOptions | null> = (targetVal, opts, paths, { documentInventory }) => {
const results: IFunctionResult[] = [];
if (!isObject(targetVal)) return;

if (!isObject(targetVal)) {
return results;
}

let targetArray: any[] | string[] = [];
let targetArray: any[] | string[];

if (Array.isArray(targetVal)) {
targetArray = targetVal;
Expand All @@ -46,14 +42,14 @@ export const alphabetical: IFunction<IAlphaRuleOptions | null> = (targetVal, opt
}

if (targetArray.length < 2) {
return results;
return;
}

const keyedBy = opts?.keyedBy;

const unsortedItems = getUnsortedItems<unknown>(
targetArray,
keyedBy
keyedBy !== void 0
? (a, b) => {
if (!isObject(a) || !isObject(b)) return 0;

Expand All @@ -66,16 +62,19 @@ export const alphabetical: IFunction<IAlphaRuleOptions | null> = (targetVal, opt

if (unsortedItems != null) {
const path = paths.target || paths.given;

results.push({
...(!keyedBy && { path: [...path, Array.isArray(targetVal) ? unsortedItems[0] : targetArray[unsortedItems[0]]] }),
message: keyedBy
? 'properties are not in alphabetical order'
: `at least 2 properties are not in alphabetical order: "${
targetArray[unsortedItems[0]]
}" should be placed after "${targetArray[unsortedItems[1]]}"`,
});
return [
{
...(!keyedBy && {
path: [...path, Array.isArray(targetVal) ? unsortedItems[0] : targetArray[unsortedItems[0]]],
}),
message: keyedBy
? 'properties are not in alphabetical order'
: `at least 2 properties are not in alphabetical order: "${
targetArray[unsortedItems[0]]
}" should be placed after "${targetArray[unsortedItems[1]]}"`,
},
];
}

return results;
return;
};
6 changes: 3 additions & 3 deletions src/functions/enumeration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ export interface IEnumRuleOptions {
}

export const enumeration: IFunction<IEnumRuleOptions> = (targetVal, opts) => {
const results: IFunctionResult[] = [];
if (targetVal === void 0) return;

const { values } = opts;
const { values } = opts!;

if (!targetVal) return results;
const results: IFunctionResult[] = [];

if (!values.includes(targetVal)) {
results.push({
Expand Down
8 changes: 4 additions & 4 deletions src/functions/length.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ export interface ILengthRuleOptions {
}

export const length: IFunction<ILengthRuleOptions> = (targetVal, opts) => {
const results: IFunctionResult[] = [];
if (targetVal === void 0 || targetVal === null) return;

const { min, max } = opts;

if (!targetVal) return results;

let value;
const valueType = typeof targetVal;
if (valueType === 'object') {
Expand All @@ -24,7 +22,9 @@ export const length: IFunction<ILengthRuleOptions> = (targetVal, opts) => {
value = targetVal.length;
}

if (typeof value === 'undefined') return results;
if (typeof value === 'undefined') return;

const results: IFunctionResult[] = [];

if (typeof min !== 'undefined' && value < min) {
results.push({
Expand Down
4 changes: 2 additions & 2 deletions src/functions/pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ function test(value: string, regex: RegExp | string) {
}

export const pattern: IFunction<IRulePatternOptions> = (targetVal, opts) => {
const results: IFunctionResult[] = [];
if (typeof targetVal !== 'string') return;

if (!targetVal || typeof targetVal !== 'string') return results;
const results: IFunctionResult[] = [];

const { match, notMatch } = opts;

Expand Down
4 changes: 2 additions & 2 deletions src/functions/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,6 @@ const cleanAJVErrorMessage = (message: string, path: Optional<string>, suggestio
};

export const schema: ISchemaFunction = (targetVal, opts, paths, { rule }) => {
const results: IFunctionResult[] = [];

const path = paths.target || paths.given;

if (targetVal === void 0) {
Expand All @@ -157,6 +155,8 @@ export const schema: ISchemaFunction = (targetVal, opts, paths, { rule }) => {
];
}

const results: IFunctionResult[] = [];

// we already access a resolved object in src/functions/schema-path.ts
const { schema: schemaObj } = opts;

Expand Down
8 changes: 1 addition & 7 deletions src/functions/unreferencedReusableObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,7 @@ export const unreferencedReusableObject: IFunction<{ reusableObjectsLocation: st
_paths,
otherValues,
) => {
if (!isObject(data)) return [];

if (!opts.reusableObjectsLocation.startsWith('#')) {
throw new Error(
"Function option 'reusableObjectsLocation' doesn't look like containing a valid local json pointer.",
);
}
if (!isObject(data)) return;

const normalizedSource = otherValues.documentInventory.source ?? '';

Expand Down
6 changes: 3 additions & 3 deletions src/functions/xor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ export interface IXorRuleOptions {
}

export const xor: IFunction<IXorRuleOptions> = (targetVal, opts) => {
const results: IFunctionResult[] = [];

const { properties } = opts;

if (!targetVal || typeof targetVal !== 'object' || properties.length !== 2) return results;
if (targetVal === null || typeof targetVal !== 'object' || properties.length !== 2) return;

const results: IFunctionResult[] = [];

const intersection = Object.keys(targetVal).filter(value => -1 !== properties.indexOf(value));
if (intersection.length !== 1) {
Expand Down
4 changes: 3 additions & 1 deletion src/meta/rule.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,9 @@
"additionalProperties": false,
"properties": {
"reusableObjectsLocation": {
"type": "string"
"type": "string",
"minLength": 1,
"pattern": "^#"
}
},
"required": [
Expand Down
6 changes: 3 additions & 3 deletions src/rulesets/__tests__/validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,7 @@ describe('Ruleset Validation', () => {
then: {
function: 'unreferencedReusableObject',
functionOptions: {
reusableObjectsLocation: 'foo',
reusableObjectsLocation: '#',
},
},
},
Expand Down Expand Up @@ -888,7 +888,7 @@ describe('Ruleset Validation', () => {
).toThrow(ValidationError);
});

it('complains about invalid options', () => {
it.each([2, '', 'd'])('complains about invalid options %s', reusableObjectsLocation => {
expect(
assertValidRuleset.bind(null, {
rules: {
Expand All @@ -897,7 +897,7 @@ describe('Ruleset Validation', () => {
then: {
function: 'unreferencedReusableObject',
functionOptions: {
reusableObjectsLocation: 2,
reusableObjectsLocation,
},
},
},
Expand Down

0 comments on commit fd3e70d

Please sign in to comment.