mauss
Version:
practical functions and reusable configurations
73 lines (72 loc) • 2.43 kB
JavaScript
export const compare = {
/** Compares nullish values, sorting `null` and `undefined` to the end */
undefined(x, y) {
if (x == null && y == null)
return 0;
return (x == null && 1) || (y == null && -1) || 0;
},
/** Compares boolean values, prioritizing `true` over `false` */
boolean(x, y) {
return +y - +x;
},
/**
* Put `(x, y)` for bigger number first, and `(y, x)` for smaller number first
* @returns `y - x` which defaults to descending order
*/
number(x, y) {
return y - x;
},
/** Compares bigint values, defaults to ascending order */
bigint(x, y) {
return x < y ? -1 : x > y ? 1 : 0;
},
/** Compares symbols using its string values */
symbol(x, y) {
return x.toString().localeCompare(y.toString());
},
/** Compares string values using `.localeCompare` */
string(x, y) {
return x.localeCompare(y);
},
/** Compares generic object values using {@link inspect} */
object(x, y) {
if (x === null)
return 1;
if (y === null)
return -1;
return inspect(x, y);
},
};
/** Compares anything with anything */
export function wildcard(x, y) {
if (x == null)
return 1;
if (y == null)
return -1;
const [xt, yt] = [typeof x, typeof y];
if (xt === 'function')
return 0;
if (xt !== yt || xt === 'object') {
const xs = JSON.stringify(x);
const ys = JSON.stringify(y);
return compare.string(xs, ys);
}
return compare[xt](x, y);
}
/**
* Recursively compares common object properties until the first difference is found
* @returns `0` if both objects are identical or completely different, otherwise their respective primitive difference
*/
export function inspect(x, y) {
const common = [...new Set([...Object.keys(x), ...Object.keys(y)])].filter((k) => k in x && k in y && typeof x[k] === typeof y[k] && x[k] !== y[k]);
for (let i = 0, key = common[i], data = typeof x[key]; i < common.length && x[key] !== null && y[key] !== null; key = common[++i], data = typeof x[key]) {
if (data === 'function')
continue;
if (data === 'object')
return inspect(x[key], y[key]);
const constrained = compare[data];
if (data in compare)
return constrained(x[key], y[key]);
}
return 0;
}