From c3ec8a418bdc85506e3c5100015720a45454d8d3 Mon Sep 17 00:00:00 2001 From: Dmitrii Maganov Date: Fri, 26 Nov 2021 20:07:58 +0300 Subject: [PATCH] fix(adapter-commons): clean up in sort.ts and select function (#2492) --- packages/adapter-commons/src/index.ts | 17 ++---- packages/adapter-commons/src/sort.ts | 86 ++++++++++----------------- 2 files changed, 39 insertions(+), 64 deletions(-) diff --git a/packages/adapter-commons/src/index.ts b/packages/adapter-commons/src/index.ts index f14730b67e..aa83aca48f 100644 --- a/packages/adapter-commons/src/index.ts +++ b/packages/adapter-commons/src/index.ts @@ -7,20 +7,15 @@ export * from './sort'; // Return a function that filters a result object or array // and picks only the fields passed as `params.query.$select` // and additional `otherFields` -export function select (params: any, ...otherFields: any[]) { - const fields = params && params.query && params.query.$select; +export function select (params: any, ...otherFields: string[]) { + const queryFields: string[] | undefined = params?.query?.$select; - if (Array.isArray(fields) && otherFields.length) { - fields.push(...otherFields); + if (!queryFields) { + return (result: any) => result; } - const convert = (result: any) => { - if (!Array.isArray(fields)) { - return result; - } - - return _.pick(result, ...fields); - }; + const resultFields = queryFields.concat(otherFields); + const convert = (result: any) => _.pick(result, ...resultFields); return (result: any) => { if (Array.isArray(result)) { diff --git a/packages/adapter-commons/src/sort.ts b/packages/adapter-commons/src/sort.ts index 4ad85fd2b9..fc2e436bda 100644 --- a/packages/adapter-commons/src/sort.ts +++ b/packages/adapter-commons/src/sort.ts @@ -7,60 +7,56 @@ export function compareNSB (a: any, b: any) { return 0; } -export function compareArrays (a: any, b: any) { - let i; - let comp; +export function compareArrays (a: any[], b: any[]) { + for (let i = 0, l = Math.min(a.length, b.length); i < l; i++) { + const comparison = compare(a[i], b[i]); - for (i = 0; i < Math.min(a.length, b.length); i += 1) { - comp = exports.compare(a[i], b[i]); - - if (comp !== 0) { return comp; } + if (comparison !== 0) { return comparison; } } // Common section was identical, longest one wins - return exports.compareNSB(a.length, b.length); + return compareNSB(a.length, b.length); } -export function compare (a: any, b: any, compareStrings: any = exports.compareNSB) { - const { compareNSB, compare, compareArrays } = exports; +export function compare (a: any, b: any, compareStrings: any = compareNSB): 0 | 1 | -1 { + if (a === b) { return 0; } // undefined - if (a === undefined) { return b === undefined ? 0 : -1; } - if (b === undefined) { return a === undefined ? 0 : 1; } + if (a === undefined) { return -1; } + if (b === undefined) { return 1; } // null - if (a === null) { return b === null ? 0 : -1; } - if (b === null) { return a === null ? 0 : 1; } + if (a === null) { return -1; } + if (b === null) { return 1; } // Numbers if (typeof a === 'number') { return typeof b === 'number' ? compareNSB(a, b) : -1; } - if (typeof b === 'number') { return typeof a === 'number' ? compareNSB(a, b) : 1; } + if (typeof b === 'number') { return 1; } // Strings if (typeof a === 'string') { return typeof b === 'string' ? compareStrings(a, b) : -1; } - if (typeof b === 'string') { return typeof a === 'string' ? compareStrings(a, b) : 1; } + if (typeof b === 'string') { return 1; } // Booleans if (typeof a === 'boolean') { return typeof b === 'boolean' ? compareNSB(a, b) : -1; } - if (typeof b === 'boolean') { return typeof a === 'boolean' ? compareNSB(a, b) : 1; } + if (typeof b === 'boolean') { return 1; } // Dates if (a instanceof Date) { return b instanceof Date ? compareNSB(a.getTime(), b.getTime()) : -1; } - if (b instanceof Date) { return a instanceof Date ? compareNSB(a.getTime(), b.getTime()) : 1; } + if (b instanceof Date) { return 1; } // Arrays (first element is most significant and so on) if (Array.isArray(a)) { return Array.isArray(b) ? compareArrays(a, b) : -1; } - if (Array.isArray(b)) { return Array.isArray(a) ? compareArrays(a, b) : 1; } + if (Array.isArray(b)) { return 1; } // Objects const aKeys = Object.keys(a).sort(); const bKeys = Object.keys(b).sort(); - let comp = 0; - for (let i = 0; i < Math.min(aKeys.length, bKeys.length); i += 1) { - comp = compare(a[aKeys[i]], b[bKeys[i]]); + for (let i = 0, l = Math.min(aKeys.length, bKeys.length); i < l; i++) { + const comparison = compare(a[aKeys[i]], b[bKeys[i]]); - if (comp !== 0) { return comp; } + if (comparison !== 0) { return comparison; } } return compareNSB(aKeys.length, bKeys.length); @@ -68,41 +64,25 @@ export function compare (a: any, b: any, compareStrings: any = exports.compareNS // An in-memory sorting function according to the // $sort special query parameter -export function sorter ($sort: any) { - let sortLevels = 0; // > 0 if $sort has tags with '.' i.e. '{a: 1, b: -1, "c.x.z": 1}' - - const getVal = (a: any, sortKeys: any[]) => { - let keys = sortKeys.map(key => key); - let val = a; - do { - let key = keys.shift(); - val = val[key]; - } while (keys.length); - - return val; - }; - - const criteria = Object.keys($sort).map(key => { - const direction = $sort[key]; - const keys = key.split('.'); - sortLevels += (keys.length > 1) ? 1 : 0; - - return { keys, direction }; - }); +export function sorter ($sort: { [key: string]: -1 | 1 }) { + const get = (value: any, path: string[]) => path.reduce((value, key) => value[key], value); - return function (a: any, b: any) { - let compare; + const compares = Object.keys($sort).map(key => { + const direction = $sort[key]; + const path = key.split('.'); - for (const criterion of criteria) { - if (sortLevels) { - compare = criterion.direction * exports.compare(getVal(a, criterion.keys), getVal(b, criterion.keys)); + if (path.length === 1) { + return (a: any, b: any) => direction * compare(a[key], b[key]); } else { - compare = criterion.direction * exports.compare(a[criterion.keys[0]], b[criterion.keys[0]]); + return (a: any, b: any) => direction * compare(get(a, path), get(b, path)); } + }); + + return function (a: any, b: any) { + for (const compare of compares) { + const comparasion = compare(a, b); - if (compare !== 0) { - return compare; - } + if (comparasion !== 0) { return comparasion; } } return 0;