Skip to content

Commit

Permalink
fix(adapter-commons): clean up in sort.ts and select function (#2492)
Browse files Browse the repository at this point in the history
  • Loading branch information
vonagam authored Nov 26, 2021
1 parent b701bf7 commit c3ec8a4
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 64 deletions.
17 changes: 6 additions & 11 deletions packages/adapter-commons/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
86 changes: 33 additions & 53 deletions packages/adapter-commons/src/sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,102 +7,82 @@ 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);
}

// 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;
Expand Down

0 comments on commit c3ec8a4

Please sign in to comment.