@art-suite/art-core-ts-compare 0.0.11 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +158 -132
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -24
- package/dist/{index.d.ts → index.d.mts} +27 -24
- package/dist/index.mjs +159 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +9 -9
- package/dist/index.js +0 -107
- package/dist/index.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,140 +1,166 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let _art_suite_art_core_ts_types = require("@art-suite/art-core-ts-types");
|
|
3
|
+
//#region src/compare.ts
|
|
4
|
+
const compareArrays = (a, b) => {
|
|
5
|
+
const minLength = Math.min(a.length, b.length);
|
|
6
|
+
for (let i = 0; i < minLength; i++) {
|
|
7
|
+
const result = compare(a[i], b[i]);
|
|
8
|
+
if (result !== 0) return result;
|
|
9
|
+
}
|
|
10
|
+
return a.length - b.length;
|
|
9
11
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Compares two plain objects. If the keys are different, the two key sets are sorted and compared as arrays of strings.
|
|
14
|
+
* If the keys are the same, the values are compared recursively.
|
|
15
|
+
* @param a - The first object to compare
|
|
16
|
+
* @param b - The second object to compare
|
|
17
|
+
* @returns A number indicating the comparison result
|
|
18
|
+
*/
|
|
19
|
+
const comparePlainObjects = (a, b) => {
|
|
20
|
+
let differentKeys = false;
|
|
21
|
+
let leastDifferentKey;
|
|
22
|
+
let leastDifferentKeyResult = 0;
|
|
23
|
+
for (const key in a) if (!(key in b)) differentKeys = true;
|
|
24
|
+
else {
|
|
25
|
+
const result = compare(a[key], b[key]);
|
|
26
|
+
if (result !== 0) {
|
|
27
|
+
if (!leastDifferentKey || leastDifferentKey > key) {
|
|
28
|
+
leastDifferentKey = key;
|
|
29
|
+
leastDifferentKeyResult = result;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (!differentKeys) {
|
|
34
|
+
for (const key in b) if (!(key in a)) {
|
|
35
|
+
differentKeys = true;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (differentKeys) return compareArrays(Object.keys(a), Object.keys(b));
|
|
40
|
+
return leastDifferentKeyResult;
|
|
17
41
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
lte: () => lte,
|
|
29
|
-
neq: () => neq
|
|
30
|
-
});
|
|
31
|
-
module.exports = __toCommonJS(index_exports);
|
|
32
|
-
|
|
33
|
-
// src/compare.ts
|
|
34
|
-
var import_art_core_ts_types = require("@art-suite/art-core-ts-types");
|
|
35
|
-
var compareArrays = (a, b) => {
|
|
36
|
-
const minLength = Math.min(a.length, b.length);
|
|
37
|
-
for (let i = 0; i < minLength; i++) {
|
|
38
|
-
const result = compare(a[i], b[i]);
|
|
39
|
-
if (result !== 0) return result;
|
|
40
|
-
}
|
|
41
|
-
return a.length - b.length;
|
|
42
|
-
};
|
|
43
|
-
var comparePlainObjects = (a, b) => {
|
|
44
|
-
let differentKeys = false;
|
|
45
|
-
let leastDifferentKey;
|
|
46
|
-
let leastDifferentKeyResult = 0;
|
|
47
|
-
for (const key in a) {
|
|
48
|
-
if (!(key in b)) differentKeys = true;
|
|
49
|
-
else {
|
|
50
|
-
const result = compare(a[key], b[key]);
|
|
51
|
-
if (result !== 0) {
|
|
52
|
-
if (!leastDifferentKey || leastDifferentKey > key) {
|
|
53
|
-
leastDifferentKey = key;
|
|
54
|
-
leastDifferentKeyResult = result;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (!differentKeys) {
|
|
60
|
-
for (const key in b) {
|
|
61
|
-
if (!(key in a)) {
|
|
62
|
-
differentKeys = true;
|
|
63
|
-
break;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
if (differentKeys) {
|
|
68
|
-
return compareArrays(Object.keys(a), Object.keys(b));
|
|
69
|
-
}
|
|
70
|
-
return leastDifferentKeyResult;
|
|
71
|
-
};
|
|
72
|
-
var compareCustomComparableHelper = (a, b) => {
|
|
73
|
-
if (a !== null && a !== void 0 && typeof a === "object") {
|
|
74
|
-
if ((0, import_art_core_ts_types.isFunction)(a.compare)) return a.compare(b);
|
|
75
|
-
if ((0, import_art_core_ts_types.isFunction)(a.eq) && a?.eq(b)) return 0;
|
|
76
|
-
if ((0, import_art_core_ts_types.isFunction)(a.lt) && a?.lt(b)) return -1;
|
|
77
|
-
if ((0, import_art_core_ts_types.isFunction)(a.gt) && a?.gt(b)) return 1;
|
|
78
|
-
if ((0, import_art_core_ts_types.isFunction)(a.lte) && a?.lte(b)) return -1;
|
|
79
|
-
if ((0, import_art_core_ts_types.isFunction)(a.gte) && a?.gte(b)) return 1;
|
|
80
|
-
}
|
|
81
|
-
return NaN;
|
|
42
|
+
const compareCustomComparableHelper = (a, b) => {
|
|
43
|
+
if (a !== null && a !== void 0 && typeof a === "object") {
|
|
44
|
+
if ((0, _art_suite_art_core_ts_types.isFunction)(a.compare)) return a.compare(b);
|
|
45
|
+
if ((0, _art_suite_art_core_ts_types.isFunction)(a.eq) && a?.eq(b)) return 0;
|
|
46
|
+
if ((0, _art_suite_art_core_ts_types.isFunction)(a.lt) && a?.lt(b)) return -1;
|
|
47
|
+
if ((0, _art_suite_art_core_ts_types.isFunction)(a.gt) && a?.gt(b)) return 1;
|
|
48
|
+
if ((0, _art_suite_art_core_ts_types.isFunction)(a.lte) && a?.lte(b)) return -1;
|
|
49
|
+
if ((0, _art_suite_art_core_ts_types.isFunction)(a.gte) && a?.gte(b)) return 1;
|
|
50
|
+
}
|
|
51
|
+
return NaN;
|
|
82
52
|
};
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
53
|
+
const compareCustomComparable = (a, b) => {
|
|
54
|
+
const customResult = compareCustomComparableHelper(a, b);
|
|
55
|
+
if (!Number.isNaN(customResult)) return customResult;
|
|
56
|
+
return -compareCustomComparableHelper(b, a);
|
|
87
57
|
};
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
if (typeof a === "boolean" && typeof b === "boolean") {
|
|
105
|
-
return Number(a) - Number(b);
|
|
106
|
-
}
|
|
107
|
-
if (typeof a !== typeof b) return NaN;
|
|
108
|
-
return NaN;
|
|
58
|
+
const comparePrimitives = (a, b) => {
|
|
59
|
+
if (a === null && b === null) return 0;
|
|
60
|
+
if (a === null) return -1;
|
|
61
|
+
if (b === null) return 1;
|
|
62
|
+
if (a === void 0 && b === void 0) return 0;
|
|
63
|
+
if (a === void 0) return 1;
|
|
64
|
+
if (b === void 0) return -1;
|
|
65
|
+
if (Number.isNaN(a) && Number.isNaN(b)) return 0;
|
|
66
|
+
if (Number.isNaN(a)) return -1;
|
|
67
|
+
if (Number.isNaN(b)) return 1;
|
|
68
|
+
if (typeof a === "number" && typeof b === "number") return a - b;
|
|
69
|
+
if (typeof a === "string" && typeof b === "string") return a.localeCompare(b);
|
|
70
|
+
if (typeof a === "boolean" && typeof b === "boolean") return Number(a) - Number(b);
|
|
71
|
+
if (typeof a !== typeof b) return NaN;
|
|
72
|
+
return NaN;
|
|
109
73
|
};
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
74
|
+
/**
|
|
75
|
+
* deep structural comparison
|
|
76
|
+
*
|
|
77
|
+
* @param a - The first value to compare
|
|
78
|
+
* @param b - The second value to compare
|
|
79
|
+
* @returns A number indicating the comparison result:
|
|
80
|
+
* - **< 0**: `a` is less than `b`
|
|
81
|
+
* - **== 0**: `a` is equal to `b` (deep structural equality)
|
|
82
|
+
* - **> 0**: `a` is greater than `b`
|
|
83
|
+
* - **NaN**: Values cannot be compared (incompatible types or custom comparison failed)
|
|
84
|
+
*
|
|
85
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
86
|
+
*/
|
|
87
|
+
const compare = (a, b) => {
|
|
88
|
+
if (a === b) return 0;
|
|
89
|
+
const customResult = compareCustomComparable(a, b);
|
|
90
|
+
if (!Number.isNaN(customResult)) return customResult;
|
|
91
|
+
if ((0, _art_suite_art_core_ts_types.isArray)(a) && (0, _art_suite_art_core_ts_types.isArray)(b)) return compareArrays(a, b);
|
|
92
|
+
if ((0, _art_suite_art_core_ts_types.isPlainObject)(a) && (0, _art_suite_art_core_ts_types.isPlainObject)(b)) return comparePlainObjects(a, b);
|
|
93
|
+
return comparePrimitives(a, b);
|
|
121
94
|
};
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/equality.ts
|
|
97
|
+
/**
|
|
98
|
+
* deep structural == test
|
|
99
|
+
*
|
|
100
|
+
* @param a - The first value to compare
|
|
101
|
+
* @param b - The second value to compare
|
|
102
|
+
* @returns `true` if the values are deeply equal (compare returns 0), `false` otherwise
|
|
103
|
+
*
|
|
104
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
105
|
+
*/
|
|
106
|
+
const eq = (a, b) => compare(a, b) === 0;
|
|
107
|
+
/**
|
|
108
|
+
* deep structural != test
|
|
109
|
+
*
|
|
110
|
+
* @param a - The first value to compare
|
|
111
|
+
* @param b - The second value to compare
|
|
112
|
+
* @returns `true` if the values are not deeply equal (compare returns non-zero), `false` otherwise
|
|
113
|
+
*
|
|
114
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
115
|
+
*/
|
|
116
|
+
const neq = (a, b) => compare(a, b) !== 0;
|
|
117
|
+
/**
|
|
118
|
+
* deep structural < test
|
|
119
|
+
*
|
|
120
|
+
* @param a - The first value to compare
|
|
121
|
+
* @param b - The second value to compare
|
|
122
|
+
* @returns `true` if `a` is less than `b` (compare returns negative), `false` otherwise
|
|
123
|
+
*
|
|
124
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
125
|
+
*/
|
|
126
|
+
const lt = (a, b) => compare(a, b) < 0;
|
|
127
|
+
/**
|
|
128
|
+
* deep structural > test
|
|
129
|
+
*
|
|
130
|
+
* @param a - The first value to compare
|
|
131
|
+
* @param b - The second value to compare
|
|
132
|
+
* @returns `true` if `a` is greater than `b` (compare returns positive), `false` otherwise
|
|
133
|
+
*
|
|
134
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
135
|
+
*/
|
|
136
|
+
const gt = (a, b) => compare(a, b) > 0;
|
|
137
|
+
/**
|
|
138
|
+
* deep structural <= test
|
|
139
|
+
*
|
|
140
|
+
* @param a - The first value to compare
|
|
141
|
+
* @param b - The second value to compare
|
|
142
|
+
* @returns `true` if `a` is less than or equal to `b` (compare returns negative or zero), `false` otherwise
|
|
143
|
+
*
|
|
144
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
145
|
+
*/
|
|
146
|
+
const lte = (a, b) => compare(a, b) <= 0;
|
|
147
|
+
/**
|
|
148
|
+
* deep structural >= test
|
|
149
|
+
*
|
|
150
|
+
* @param a - The first value to compare
|
|
151
|
+
* @param b - The second value to compare
|
|
152
|
+
* @returns `true` if `a` is greater than or equal to `b` (compare returns positive or zero), `false` otherwise
|
|
153
|
+
*
|
|
154
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
155
|
+
*/
|
|
156
|
+
const gte = (a, b) => compare(a, b) >= 0;
|
|
157
|
+
//#endregion
|
|
158
|
+
exports.compare = compare;
|
|
159
|
+
exports.eq = eq;
|
|
160
|
+
exports.gt = gt;
|
|
161
|
+
exports.gte = gte;
|
|
162
|
+
exports.lt = lt;
|
|
163
|
+
exports.lte = lte;
|
|
164
|
+
exports.neq = neq;
|
|
122
165
|
|
|
123
|
-
// src/equality.ts
|
|
124
|
-
var eq = (a, b) => compare(a, b) === 0;
|
|
125
|
-
var neq = (a, b) => compare(a, b) !== 0;
|
|
126
|
-
var lt = (a, b) => compare(a, b) < 0;
|
|
127
|
-
var gt = (a, b) => compare(a, b) > 0;
|
|
128
|
-
var lte = (a, b) => compare(a, b) <= 0;
|
|
129
|
-
var gte = (a, b) => compare(a, b) >= 0;
|
|
130
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
131
|
-
0 && (module.exports = {
|
|
132
|
-
compare,
|
|
133
|
-
eq,
|
|
134
|
-
gt,
|
|
135
|
-
gte,
|
|
136
|
-
lt,
|
|
137
|
-
lte,
|
|
138
|
-
neq
|
|
139
|
-
});
|
|
140
166
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/compare.ts","../src/equality.ts"],"sourcesContent":["export * from './compare'\nexport * from './equality'","import { isArray, isPlainObject, isFunction } from '@art-suite/art-core-ts-types'\nimport { objectKeyCount } from '@art-suite/art-core-ts-containers'\n\nexport interface CustomComparableInterface {\n\n /**\n * Compares `this` with `b`\n * @param b - The value to compare `this` with\n * @returns A number greater than zero if `this` is greater than `b`, less than zero if `this` is less than `b`, and zero if `this` is equal to `b`\n */\n compare(b: any): number\n}\n\nexport interface CustomEqualityInterface {\n /**\n * Checks if `this` equals `b`\n * @param b - The value to compare `this` with\n * @returns true if equal, false otherwise\n */\n eq(b: any): boolean\n}\n\nexport interface CustomInequalityInterface extends CustomEqualityInterface {\n /**\n * Checks if `this` is not equal to `b`\n * @param b - The value to compare `this` with\n * @returns true if not equal, false otherwise\n */\n lt(b: any): boolean\n gt(b: any): boolean\n lte(b: any): boolean\n gte(b: any): boolean\n}\n\nconst compareArrays = (a: any[], b: any[]): number => {\n const minLength = Math.min(a.length, b.length)\n\n for (let i = 0; i < minLength; i++) {\n const result = compare(a[i], b[i])\n if (result !== 0) return result\n }\n\n return a.length - b.length\n}\n\n/**\n * Compares two plain objects. If the keys are different, the two key sets are sorted and compared as arrays of strings.\n * If the keys are the same, the values are compared recursively.\n * @param a - The first object to compare\n * @param b - The second object to compare\n * @returns A number indicating the comparison result\n */\nconst comparePlainObjects = (a: Record<string, any>, b: Record<string, any>): number => {\n // Create a merged list of all unique keys and sort it\n // const allKeys = [...new Set([...Object.keys(a), ...Object.keys(b)])].sort()\n\n // Compare values for keys in A that are also in B\n let differentKeys = false\n let leastDifferentKey: string | undefined\n let leastDifferentKeyResult: number = 0\n for (const key in a) {\n if (!(key in b)) differentKeys = true;\n else {\n // Both have the key, compare their values\n const result = compare(a[key], b[key])\n if (result !== 0) {\n if (!leastDifferentKey || leastDifferentKey > key) {\n leastDifferentKey = key\n leastDifferentKeyResult = result\n }\n }\n }\n }\n\n // if B had all As keys, we need to check if B has any keys that A doesn't have\n if (!differentKeys) {\n for (const key in b) {\n if (!(key in a)) { differentKeys = true; break }\n }\n }\n\n // if the keys are different, compare the keys\n if (differentKeys) {\n return compareArrays(Object.keys(a), Object.keys(b))\n }\n\n return leastDifferentKeyResult // All keys and values are equal\n}\n\nconst compareCustomComparableHelper = (a: any, b: any): number => {\n // Only check for custom methods if a is not null/undefined and is an object\n if (a !== null && a !== undefined && typeof a === 'object') {\n // Check if left operand supports any of the custom methods (highest priority)\n if (isFunction(a.compare)) return a.compare(b);\n if (isFunction(a.eq) && a?.eq(b)) return 0;\n if (isFunction(a.lt) && a?.lt(b)) return -1;\n if (isFunction(a.gt) && a?.gt(b)) return 1;\n if (isFunction(a.lte) && a?.lte(b)) return -1;\n if (isFunction(a.gte) && a?.gte(b)) return 1;\n }\n return NaN\n}\n\nconst compareCustomComparable = (a: any, b: any): number => {\n const customResult = compareCustomComparableHelper(a, b)\n if (!Number.isNaN(customResult)) return customResult\n return -compareCustomComparableHelper(b, a)\n}\n\nconst comparePrimitives = (a: any, b: any): number => {\n // Handle null\n if (a === null && b === null) return 0\n if (a === null) return -1\n if (b === null) return 1\n\n // Handle undefined\n if (a === undefined && b === undefined) return 0\n if (a === undefined) return 1\n if (b === undefined) return -1\n\n // Handle NaN\n if (Number.isNaN(a) && Number.isNaN(b)) return 0\n if (Number.isNaN(a)) return -1\n if (Number.isNaN(b)) return 1\n\n // Handle numbers - use subtraction for efficiency\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b\n }\n\n // Handle strings - use localeCompare for proper string comparison\n if (typeof a === 'string' && typeof b === 'string') {\n return a.localeCompare(b)\n }\n\n // Handle booleans - convert to numbers for comparison\n if (typeof a === 'boolean' && typeof b === 'boolean') {\n return Number(a) - Number(b)\n }\n\n // Return NaN for different types or incompatible comparisons\n if (typeof a !== typeof b) return NaN\n\n // For same types that aren't numbers, strings, or booleans, return NaN\n return NaN\n}\n\n/**\n * deep structural comparison\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns A number indicating the comparison result:\n * - **< 0**: `a` is less than `b`\n * - **== 0**: `a` is equal to `b` (deep structural equality)\n * - **> 0**: `a` is greater than `b`\n * - **NaN**: Values cannot be compared (incompatible types or custom comparison failed)\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const compare = (a: any, b: any): number => {\n if (a === b) return 0;\n // Handle custom comparable first\n const customResult = compareCustomComparable(a, b)\n if (!Number.isNaN(customResult)) return customResult\n\n // Handle arrays\n if (isArray(a) && isArray(b)) {\n return compareArrays(a, b)\n }\n\n // Handle plain objects\n if (isPlainObject(a) && isPlainObject(b)) {\n return comparePlainObjects(a, b)\n }\n\n // Handle primitives\n return comparePrimitives(a, b)\n}","import { compare } from './compare'\n\n/**\n * deep structural == test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are deeply equal (compare returns 0), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const eq = (a: any, b: any): boolean => compare(a, b) === 0;\n\n/**\n * deep structural != test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are not deeply equal (compare returns non-zero), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const neq = (a: any, b: any): boolean => compare(a, b) !== 0;\n\n/**\n * deep structural < test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is less than `b` (compare returns negative), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const lt = (a: any, b: any): boolean => compare(a, b) < 0;\n\n/**\n * deep structural > test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is greater than `b` (compare returns positive), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const gt = (a: any, b: any): boolean => compare(a, b) > 0;\n\n/**\n * deep structural <= test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is less than or equal to `b` (compare returns negative or zero), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const lte = (a: any, b: any): boolean => compare(a, b) <= 0;\n\n/**\n * deep structural >= test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is greater than or equal to `b` (compare returns positive or zero), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const gte = (a: any, b: any): boolean => compare(a, b) >= 0;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/compare.ts","../src/equality.ts"],"sourcesContent":["import { isArray, isPlainObject, isFunction } from '@art-suite/art-core-ts-types'\nimport { objectKeyCount } from '@art-suite/art-core-ts-containers'\n\nexport interface CustomComparableInterface {\n\n /**\n * Compares `this` with `b`\n * @param b - The value to compare `this` with\n * @returns A number greater than zero if `this` is greater than `b`, less than zero if `this` is less than `b`, and zero if `this` is equal to `b`\n */\n compare(b: any): number\n}\n\nexport interface CustomEqualityInterface {\n /**\n * Checks if `this` equals `b`\n * @param b - The value to compare `this` with\n * @returns true if equal, false otherwise\n */\n eq(b: any): boolean\n}\n\nexport interface CustomInequalityInterface extends CustomEqualityInterface {\n /**\n * Checks if `this` is not equal to `b`\n * @param b - The value to compare `this` with\n * @returns true if not equal, false otherwise\n */\n lt(b: any): boolean\n gt(b: any): boolean\n lte(b: any): boolean\n gte(b: any): boolean\n}\n\nconst compareArrays = (a: any[], b: any[]): number => {\n const minLength = Math.min(a.length, b.length)\n\n for (let i = 0; i < minLength; i++) {\n const result = compare(a[i], b[i])\n if (result !== 0) return result\n }\n\n return a.length - b.length\n}\n\n/**\n * Compares two plain objects. If the keys are different, the two key sets are sorted and compared as arrays of strings.\n * If the keys are the same, the values are compared recursively.\n * @param a - The first object to compare\n * @param b - The second object to compare\n * @returns A number indicating the comparison result\n */\nconst comparePlainObjects = (a: Record<string, any>, b: Record<string, any>): number => {\n // Create a merged list of all unique keys and sort it\n // const allKeys = [...new Set([...Object.keys(a), ...Object.keys(b)])].sort()\n\n // Compare values for keys in A that are also in B\n let differentKeys = false\n let leastDifferentKey: string | undefined\n let leastDifferentKeyResult: number = 0\n for (const key in a) {\n if (!(key in b)) differentKeys = true;\n else {\n // Both have the key, compare their values\n const result = compare(a[key], b[key])\n if (result !== 0) {\n if (!leastDifferentKey || leastDifferentKey > key) {\n leastDifferentKey = key\n leastDifferentKeyResult = result\n }\n }\n }\n }\n\n // if B had all As keys, we need to check if B has any keys that A doesn't have\n if (!differentKeys) {\n for (const key in b) {\n if (!(key in a)) { differentKeys = true; break }\n }\n }\n\n // if the keys are different, compare the keys\n if (differentKeys) {\n return compareArrays(Object.keys(a), Object.keys(b))\n }\n\n return leastDifferentKeyResult // All keys and values are equal\n}\n\nconst compareCustomComparableHelper = (a: any, b: any): number => {\n // Only check for custom methods if a is not null/undefined and is an object\n if (a !== null && a !== undefined && typeof a === 'object') {\n // Check if left operand supports any of the custom methods (highest priority)\n if (isFunction(a.compare)) return a.compare(b);\n if (isFunction(a.eq) && a?.eq(b)) return 0;\n if (isFunction(a.lt) && a?.lt(b)) return -1;\n if (isFunction(a.gt) && a?.gt(b)) return 1;\n if (isFunction(a.lte) && a?.lte(b)) return -1;\n if (isFunction(a.gte) && a?.gte(b)) return 1;\n }\n return NaN\n}\n\nconst compareCustomComparable = (a: any, b: any): number => {\n const customResult = compareCustomComparableHelper(a, b)\n if (!Number.isNaN(customResult)) return customResult\n return -compareCustomComparableHelper(b, a)\n}\n\nconst comparePrimitives = (a: any, b: any): number => {\n // Handle null\n if (a === null && b === null) return 0\n if (a === null) return -1\n if (b === null) return 1\n\n // Handle undefined\n if (a === undefined && b === undefined) return 0\n if (a === undefined) return 1\n if (b === undefined) return -1\n\n // Handle NaN\n if (Number.isNaN(a) && Number.isNaN(b)) return 0\n if (Number.isNaN(a)) return -1\n if (Number.isNaN(b)) return 1\n\n // Handle numbers - use subtraction for efficiency\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b\n }\n\n // Handle strings - use localeCompare for proper string comparison\n if (typeof a === 'string' && typeof b === 'string') {\n return a.localeCompare(b)\n }\n\n // Handle booleans - convert to numbers for comparison\n if (typeof a === 'boolean' && typeof b === 'boolean') {\n return Number(a) - Number(b)\n }\n\n // Return NaN for different types or incompatible comparisons\n if (typeof a !== typeof b) return NaN\n\n // For same types that aren't numbers, strings, or booleans, return NaN\n return NaN\n}\n\n/**\n * deep structural comparison\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns A number indicating the comparison result:\n * - **< 0**: `a` is less than `b`\n * - **== 0**: `a` is equal to `b` (deep structural equality)\n * - **> 0**: `a` is greater than `b`\n * - **NaN**: Values cannot be compared (incompatible types or custom comparison failed)\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const compare = (a: any, b: any): number => {\n if (a === b) return 0;\n // Handle custom comparable first\n const customResult = compareCustomComparable(a, b)\n if (!Number.isNaN(customResult)) return customResult\n\n // Handle arrays\n if (isArray(a) && isArray(b)) {\n return compareArrays(a, b)\n }\n\n // Handle plain objects\n if (isPlainObject(a) && isPlainObject(b)) {\n return comparePlainObjects(a, b)\n }\n\n // Handle primitives\n return comparePrimitives(a, b)\n}","import { compare } from './compare'\n\n/**\n * deep structural == test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are deeply equal (compare returns 0), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const eq = (a: any, b: any): boolean => compare(a, b) === 0;\n\n/**\n * deep structural != test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are not deeply equal (compare returns non-zero), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const neq = (a: any, b: any): boolean => compare(a, b) !== 0;\n\n/**\n * deep structural < test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is less than `b` (compare returns negative), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const lt = (a: any, b: any): boolean => compare(a, b) < 0;\n\n/**\n * deep structural > test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is greater than `b` (compare returns positive), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const gt = (a: any, b: any): boolean => compare(a, b) > 0;\n\n/**\n * deep structural <= test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is less than or equal to `b` (compare returns negative or zero), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const lte = (a: any, b: any): boolean => compare(a, b) <= 0;\n\n/**\n * deep structural >= test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is greater than or equal to `b` (compare returns positive or zero), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const gte = (a: any, b: any): boolean => compare(a, b) >= 0;\n"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,29 +1,30 @@
|
|
|
1
|
+
//#region src/compare.d.ts
|
|
1
2
|
interface CustomComparableInterface {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Compares `this` with `b`
|
|
5
|
+
* @param b - The value to compare `this` with
|
|
6
|
+
* @returns A number greater than zero if `this` is greater than `b`, less than zero if `this` is less than `b`, and zero if `this` is equal to `b`
|
|
7
|
+
*/
|
|
8
|
+
compare(b: any): number;
|
|
8
9
|
}
|
|
9
10
|
interface CustomEqualityInterface {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Checks if `this` equals `b`
|
|
13
|
+
* @param b - The value to compare `this` with
|
|
14
|
+
* @returns true if equal, false otherwise
|
|
15
|
+
*/
|
|
16
|
+
eq(b: any): boolean;
|
|
16
17
|
}
|
|
17
18
|
interface CustomInequalityInterface extends CustomEqualityInterface {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Checks if `this` is not equal to `b`
|
|
21
|
+
* @param b - The value to compare `this` with
|
|
22
|
+
* @returns true if not equal, false otherwise
|
|
23
|
+
*/
|
|
24
|
+
lt(b: any): boolean;
|
|
25
|
+
gt(b: any): boolean;
|
|
26
|
+
lte(b: any): boolean;
|
|
27
|
+
gte(b: any): boolean;
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
30
|
* deep structural comparison
|
|
@@ -39,7 +40,8 @@ interface CustomInequalityInterface extends CustomEqualityInterface {
|
|
|
39
40
|
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
40
41
|
*/
|
|
41
42
|
declare const compare: (a: any, b: any) => number;
|
|
42
|
-
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/equality.d.ts
|
|
43
45
|
/**
|
|
44
46
|
* deep structural == test
|
|
45
47
|
*
|
|
@@ -100,5 +102,6 @@ declare const lte: (a: any, b: any) => boolean;
|
|
|
100
102
|
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
101
103
|
*/
|
|
102
104
|
declare const gte: (a: any, b: any) => boolean;
|
|
103
|
-
|
|
104
|
-
export {
|
|
105
|
+
//#endregion
|
|
106
|
+
export { CustomComparableInterface, CustomEqualityInterface, CustomInequalityInterface, compare, eq, gt, gte, lt, lte, neq };
|
|
107
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -1,29 +1,30 @@
|
|
|
1
|
+
//#region src/compare.d.ts
|
|
1
2
|
interface CustomComparableInterface {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Compares `this` with `b`
|
|
5
|
+
* @param b - The value to compare `this` with
|
|
6
|
+
* @returns A number greater than zero if `this` is greater than `b`, less than zero if `this` is less than `b`, and zero if `this` is equal to `b`
|
|
7
|
+
*/
|
|
8
|
+
compare(b: any): number;
|
|
8
9
|
}
|
|
9
10
|
interface CustomEqualityInterface {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Checks if `this` equals `b`
|
|
13
|
+
* @param b - The value to compare `this` with
|
|
14
|
+
* @returns true if equal, false otherwise
|
|
15
|
+
*/
|
|
16
|
+
eq(b: any): boolean;
|
|
16
17
|
}
|
|
17
18
|
interface CustomInequalityInterface extends CustomEqualityInterface {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Checks if `this` is not equal to `b`
|
|
21
|
+
* @param b - The value to compare `this` with
|
|
22
|
+
* @returns true if not equal, false otherwise
|
|
23
|
+
*/
|
|
24
|
+
lt(b: any): boolean;
|
|
25
|
+
gt(b: any): boolean;
|
|
26
|
+
lte(b: any): boolean;
|
|
27
|
+
gte(b: any): boolean;
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
30
|
* deep structural comparison
|
|
@@ -39,7 +40,8 @@ interface CustomInequalityInterface extends CustomEqualityInterface {
|
|
|
39
40
|
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
40
41
|
*/
|
|
41
42
|
declare const compare: (a: any, b: any) => number;
|
|
42
|
-
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/equality.d.ts
|
|
43
45
|
/**
|
|
44
46
|
* deep structural == test
|
|
45
47
|
*
|
|
@@ -100,5 +102,6 @@ declare const lte: (a: any, b: any) => boolean;
|
|
|
100
102
|
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
101
103
|
*/
|
|
102
104
|
declare const gte: (a: any, b: any) => boolean;
|
|
103
|
-
|
|
104
|
-
export {
|
|
105
|
+
//#endregion
|
|
106
|
+
export { CustomComparableInterface, CustomEqualityInterface, CustomInequalityInterface, compare, eq, gt, gte, lt, lte, neq };
|
|
107
|
+
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { isArray, isFunction, isPlainObject } from "@art-suite/art-core-ts-types";
|
|
2
|
+
//#region src/compare.ts
|
|
3
|
+
const compareArrays = (a, b) => {
|
|
4
|
+
const minLength = Math.min(a.length, b.length);
|
|
5
|
+
for (let i = 0; i < minLength; i++) {
|
|
6
|
+
const result = compare(a[i], b[i]);
|
|
7
|
+
if (result !== 0) return result;
|
|
8
|
+
}
|
|
9
|
+
return a.length - b.length;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Compares two plain objects. If the keys are different, the two key sets are sorted and compared as arrays of strings.
|
|
13
|
+
* If the keys are the same, the values are compared recursively.
|
|
14
|
+
* @param a - The first object to compare
|
|
15
|
+
* @param b - The second object to compare
|
|
16
|
+
* @returns A number indicating the comparison result
|
|
17
|
+
*/
|
|
18
|
+
const comparePlainObjects = (a, b) => {
|
|
19
|
+
let differentKeys = false;
|
|
20
|
+
let leastDifferentKey;
|
|
21
|
+
let leastDifferentKeyResult = 0;
|
|
22
|
+
for (const key in a) if (!(key in b)) differentKeys = true;
|
|
23
|
+
else {
|
|
24
|
+
const result = compare(a[key], b[key]);
|
|
25
|
+
if (result !== 0) {
|
|
26
|
+
if (!leastDifferentKey || leastDifferentKey > key) {
|
|
27
|
+
leastDifferentKey = key;
|
|
28
|
+
leastDifferentKeyResult = result;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (!differentKeys) {
|
|
33
|
+
for (const key in b) if (!(key in a)) {
|
|
34
|
+
differentKeys = true;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (differentKeys) return compareArrays(Object.keys(a), Object.keys(b));
|
|
39
|
+
return leastDifferentKeyResult;
|
|
40
|
+
};
|
|
41
|
+
const compareCustomComparableHelper = (a, b) => {
|
|
42
|
+
if (a !== null && a !== void 0 && typeof a === "object") {
|
|
43
|
+
if (isFunction(a.compare)) return a.compare(b);
|
|
44
|
+
if (isFunction(a.eq) && a?.eq(b)) return 0;
|
|
45
|
+
if (isFunction(a.lt) && a?.lt(b)) return -1;
|
|
46
|
+
if (isFunction(a.gt) && a?.gt(b)) return 1;
|
|
47
|
+
if (isFunction(a.lte) && a?.lte(b)) return -1;
|
|
48
|
+
if (isFunction(a.gte) && a?.gte(b)) return 1;
|
|
49
|
+
}
|
|
50
|
+
return NaN;
|
|
51
|
+
};
|
|
52
|
+
const compareCustomComparable = (a, b) => {
|
|
53
|
+
const customResult = compareCustomComparableHelper(a, b);
|
|
54
|
+
if (!Number.isNaN(customResult)) return customResult;
|
|
55
|
+
return -compareCustomComparableHelper(b, a);
|
|
56
|
+
};
|
|
57
|
+
const comparePrimitives = (a, b) => {
|
|
58
|
+
if (a === null && b === null) return 0;
|
|
59
|
+
if (a === null) return -1;
|
|
60
|
+
if (b === null) return 1;
|
|
61
|
+
if (a === void 0 && b === void 0) return 0;
|
|
62
|
+
if (a === void 0) return 1;
|
|
63
|
+
if (b === void 0) return -1;
|
|
64
|
+
if (Number.isNaN(a) && Number.isNaN(b)) return 0;
|
|
65
|
+
if (Number.isNaN(a)) return -1;
|
|
66
|
+
if (Number.isNaN(b)) return 1;
|
|
67
|
+
if (typeof a === "number" && typeof b === "number") return a - b;
|
|
68
|
+
if (typeof a === "string" && typeof b === "string") return a.localeCompare(b);
|
|
69
|
+
if (typeof a === "boolean" && typeof b === "boolean") return Number(a) - Number(b);
|
|
70
|
+
if (typeof a !== typeof b) return NaN;
|
|
71
|
+
return NaN;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* deep structural comparison
|
|
75
|
+
*
|
|
76
|
+
* @param a - The first value to compare
|
|
77
|
+
* @param b - The second value to compare
|
|
78
|
+
* @returns A number indicating the comparison result:
|
|
79
|
+
* - **< 0**: `a` is less than `b`
|
|
80
|
+
* - **== 0**: `a` is equal to `b` (deep structural equality)
|
|
81
|
+
* - **> 0**: `a` is greater than `b`
|
|
82
|
+
* - **NaN**: Values cannot be compared (incompatible types or custom comparison failed)
|
|
83
|
+
*
|
|
84
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
85
|
+
*/
|
|
86
|
+
const compare = (a, b) => {
|
|
87
|
+
if (a === b) return 0;
|
|
88
|
+
const customResult = compareCustomComparable(a, b);
|
|
89
|
+
if (!Number.isNaN(customResult)) return customResult;
|
|
90
|
+
if (isArray(a) && isArray(b)) return compareArrays(a, b);
|
|
91
|
+
if (isPlainObject(a) && isPlainObject(b)) return comparePlainObjects(a, b);
|
|
92
|
+
return comparePrimitives(a, b);
|
|
93
|
+
};
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/equality.ts
|
|
96
|
+
/**
|
|
97
|
+
* deep structural == test
|
|
98
|
+
*
|
|
99
|
+
* @param a - The first value to compare
|
|
100
|
+
* @param b - The second value to compare
|
|
101
|
+
* @returns `true` if the values are deeply equal (compare returns 0), `false` otherwise
|
|
102
|
+
*
|
|
103
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
104
|
+
*/
|
|
105
|
+
const eq = (a, b) => compare(a, b) === 0;
|
|
106
|
+
/**
|
|
107
|
+
* deep structural != test
|
|
108
|
+
*
|
|
109
|
+
* @param a - The first value to compare
|
|
110
|
+
* @param b - The second value to compare
|
|
111
|
+
* @returns `true` if the values are not deeply equal (compare returns non-zero), `false` otherwise
|
|
112
|
+
*
|
|
113
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
114
|
+
*/
|
|
115
|
+
const neq = (a, b) => compare(a, b) !== 0;
|
|
116
|
+
/**
|
|
117
|
+
* deep structural < test
|
|
118
|
+
*
|
|
119
|
+
* @param a - The first value to compare
|
|
120
|
+
* @param b - The second value to compare
|
|
121
|
+
* @returns `true` if `a` is less than `b` (compare returns negative), `false` otherwise
|
|
122
|
+
*
|
|
123
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
124
|
+
*/
|
|
125
|
+
const lt = (a, b) => compare(a, b) < 0;
|
|
126
|
+
/**
|
|
127
|
+
* deep structural > test
|
|
128
|
+
*
|
|
129
|
+
* @param a - The first value to compare
|
|
130
|
+
* @param b - The second value to compare
|
|
131
|
+
* @returns `true` if `a` is greater than `b` (compare returns positive), `false` otherwise
|
|
132
|
+
*
|
|
133
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
134
|
+
*/
|
|
135
|
+
const gt = (a, b) => compare(a, b) > 0;
|
|
136
|
+
/**
|
|
137
|
+
* deep structural <= test
|
|
138
|
+
*
|
|
139
|
+
* @param a - The first value to compare
|
|
140
|
+
* @param b - The second value to compare
|
|
141
|
+
* @returns `true` if `a` is less than or equal to `b` (compare returns negative or zero), `false` otherwise
|
|
142
|
+
*
|
|
143
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
144
|
+
*/
|
|
145
|
+
const lte = (a, b) => compare(a, b) <= 0;
|
|
146
|
+
/**
|
|
147
|
+
* deep structural >= test
|
|
148
|
+
*
|
|
149
|
+
* @param a - The first value to compare
|
|
150
|
+
* @param b - The second value to compare
|
|
151
|
+
* @returns `true` if `a` is greater than or equal to `b` (compare returns positive or zero), `false` otherwise
|
|
152
|
+
*
|
|
153
|
+
* For more details on comparison behavior, see the art-core-ts-compare README.
|
|
154
|
+
*/
|
|
155
|
+
const gte = (a, b) => compare(a, b) >= 0;
|
|
156
|
+
//#endregion
|
|
157
|
+
export { compare, eq, gt, gte, lt, lte, neq };
|
|
158
|
+
|
|
159
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/compare.ts","../src/equality.ts"],"sourcesContent":["import { isArray, isPlainObject, isFunction } from '@art-suite/art-core-ts-types'\nimport { objectKeyCount } from '@art-suite/art-core-ts-containers'\n\nexport interface CustomComparableInterface {\n\n /**\n * Compares `this` with `b`\n * @param b - The value to compare `this` with\n * @returns A number greater than zero if `this` is greater than `b`, less than zero if `this` is less than `b`, and zero if `this` is equal to `b`\n */\n compare(b: any): number\n}\n\nexport interface CustomEqualityInterface {\n /**\n * Checks if `this` equals `b`\n * @param b - The value to compare `this` with\n * @returns true if equal, false otherwise\n */\n eq(b: any): boolean\n}\n\nexport interface CustomInequalityInterface extends CustomEqualityInterface {\n /**\n * Checks if `this` is not equal to `b`\n * @param b - The value to compare `this` with\n * @returns true if not equal, false otherwise\n */\n lt(b: any): boolean\n gt(b: any): boolean\n lte(b: any): boolean\n gte(b: any): boolean\n}\n\nconst compareArrays = (a: any[], b: any[]): number => {\n const minLength = Math.min(a.length, b.length)\n\n for (let i = 0; i < minLength; i++) {\n const result = compare(a[i], b[i])\n if (result !== 0) return result\n }\n\n return a.length - b.length\n}\n\n/**\n * Compares two plain objects. If the keys are different, the two key sets are sorted and compared as arrays of strings.\n * If the keys are the same, the values are compared recursively.\n * @param a - The first object to compare\n * @param b - The second object to compare\n * @returns A number indicating the comparison result\n */\nconst comparePlainObjects = (a: Record<string, any>, b: Record<string, any>): number => {\n // Create a merged list of all unique keys and sort it\n // const allKeys = [...new Set([...Object.keys(a), ...Object.keys(b)])].sort()\n\n // Compare values for keys in A that are also in B\n let differentKeys = false\n let leastDifferentKey: string | undefined\n let leastDifferentKeyResult: number = 0\n for (const key in a) {\n if (!(key in b)) differentKeys = true;\n else {\n // Both have the key, compare their values\n const result = compare(a[key], b[key])\n if (result !== 0) {\n if (!leastDifferentKey || leastDifferentKey > key) {\n leastDifferentKey = key\n leastDifferentKeyResult = result\n }\n }\n }\n }\n\n // if B had all As keys, we need to check if B has any keys that A doesn't have\n if (!differentKeys) {\n for (const key in b) {\n if (!(key in a)) { differentKeys = true; break }\n }\n }\n\n // if the keys are different, compare the keys\n if (differentKeys) {\n return compareArrays(Object.keys(a), Object.keys(b))\n }\n\n return leastDifferentKeyResult // All keys and values are equal\n}\n\nconst compareCustomComparableHelper = (a: any, b: any): number => {\n // Only check for custom methods if a is not null/undefined and is an object\n if (a !== null && a !== undefined && typeof a === 'object') {\n // Check if left operand supports any of the custom methods (highest priority)\n if (isFunction(a.compare)) return a.compare(b);\n if (isFunction(a.eq) && a?.eq(b)) return 0;\n if (isFunction(a.lt) && a?.lt(b)) return -1;\n if (isFunction(a.gt) && a?.gt(b)) return 1;\n if (isFunction(a.lte) && a?.lte(b)) return -1;\n if (isFunction(a.gte) && a?.gte(b)) return 1;\n }\n return NaN\n}\n\nconst compareCustomComparable = (a: any, b: any): number => {\n const customResult = compareCustomComparableHelper(a, b)\n if (!Number.isNaN(customResult)) return customResult\n return -compareCustomComparableHelper(b, a)\n}\n\nconst comparePrimitives = (a: any, b: any): number => {\n // Handle null\n if (a === null && b === null) return 0\n if (a === null) return -1\n if (b === null) return 1\n\n // Handle undefined\n if (a === undefined && b === undefined) return 0\n if (a === undefined) return 1\n if (b === undefined) return -1\n\n // Handle NaN\n if (Number.isNaN(a) && Number.isNaN(b)) return 0\n if (Number.isNaN(a)) return -1\n if (Number.isNaN(b)) return 1\n\n // Handle numbers - use subtraction for efficiency\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b\n }\n\n // Handle strings - use localeCompare for proper string comparison\n if (typeof a === 'string' && typeof b === 'string') {\n return a.localeCompare(b)\n }\n\n // Handle booleans - convert to numbers for comparison\n if (typeof a === 'boolean' && typeof b === 'boolean') {\n return Number(a) - Number(b)\n }\n\n // Return NaN for different types or incompatible comparisons\n if (typeof a !== typeof b) return NaN\n\n // For same types that aren't numbers, strings, or booleans, return NaN\n return NaN\n}\n\n/**\n * deep structural comparison\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns A number indicating the comparison result:\n * - **< 0**: `a` is less than `b`\n * - **== 0**: `a` is equal to `b` (deep structural equality)\n * - **> 0**: `a` is greater than `b`\n * - **NaN**: Values cannot be compared (incompatible types or custom comparison failed)\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const compare = (a: any, b: any): number => {\n if (a === b) return 0;\n // Handle custom comparable first\n const customResult = compareCustomComparable(a, b)\n if (!Number.isNaN(customResult)) return customResult\n\n // Handle arrays\n if (isArray(a) && isArray(b)) {\n return compareArrays(a, b)\n }\n\n // Handle plain objects\n if (isPlainObject(a) && isPlainObject(b)) {\n return comparePlainObjects(a, b)\n }\n\n // Handle primitives\n return comparePrimitives(a, b)\n}","import { compare } from './compare'\n\n/**\n * deep structural == test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are deeply equal (compare returns 0), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const eq = (a: any, b: any): boolean => compare(a, b) === 0;\n\n/**\n * deep structural != test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are not deeply equal (compare returns non-zero), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const neq = (a: any, b: any): boolean => compare(a, b) !== 0;\n\n/**\n * deep structural < test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is less than `b` (compare returns negative), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const lt = (a: any, b: any): boolean => compare(a, b) < 0;\n\n/**\n * deep structural > test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is greater than `b` (compare returns positive), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const gt = (a: any, b: any): boolean => compare(a, b) > 0;\n\n/**\n * deep structural <= test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is less than or equal to `b` (compare returns negative or zero), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const lte = (a: any, b: any): boolean => compare(a, b) <= 0;\n\n/**\n * deep structural >= test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is greater than or equal to `b` (compare returns positive or zero), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const gte = (a: any, b: any): boolean => compare(a, b) >= 0;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@art-suite/art-core-ts-compare",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "A TypeScript comparison utility library",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"repository": {
|
|
@@ -12,19 +12,19 @@
|
|
|
12
12
|
"type": "module",
|
|
13
13
|
"exports": {
|
|
14
14
|
".": {
|
|
15
|
-
"types": "./dist/index.d.
|
|
16
|
-
"import": "./dist/index.
|
|
15
|
+
"types": "./dist/index.d.mts",
|
|
16
|
+
"import": "./dist/index.mjs",
|
|
17
17
|
"require": "./dist/index.cjs"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
|
-
"main": "./dist/index.
|
|
21
|
-
"types": "./dist/index.d.
|
|
20
|
+
"main": "./dist/index.mjs",
|
|
21
|
+
"types": "./dist/index.d.mts",
|
|
22
22
|
"files": [
|
|
23
23
|
"dist"
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
26
|
"prebuild": "npm run clean",
|
|
27
|
-
"build": "npx sort-package-json;
|
|
27
|
+
"build": "npx sort-package-json;tsdown src/index.ts --format esm,cjs --dts --sourcemap",
|
|
28
28
|
"build:clean": "npm run clean && npm run build",
|
|
29
29
|
"check:types": "tsc --noEmit",
|
|
30
30
|
"check:types:fast": "tsc --noEmit --incremental",
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"test:watch": "vitest"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@art-suite/art-core-ts-containers": "^0.
|
|
40
|
-
"@art-suite/art-core-ts-types": "^0.
|
|
39
|
+
"@art-suite/art-core-ts-containers": "^1.0.0",
|
|
40
|
+
"@art-suite/art-core-ts-types": "^0.4.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@vitest/coverage-v8": "^4.0.
|
|
43
|
+
"@vitest/coverage-v8": "^4.0.18"
|
|
44
44
|
}
|
|
45
45
|
}
|
package/dist/index.js
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
// src/compare.ts
|
|
2
|
-
import { isArray, isPlainObject, isFunction } from "@art-suite/art-core-ts-types";
|
|
3
|
-
var compareArrays = (a, b) => {
|
|
4
|
-
const minLength = Math.min(a.length, b.length);
|
|
5
|
-
for (let i = 0; i < minLength; i++) {
|
|
6
|
-
const result = compare(a[i], b[i]);
|
|
7
|
-
if (result !== 0) return result;
|
|
8
|
-
}
|
|
9
|
-
return a.length - b.length;
|
|
10
|
-
};
|
|
11
|
-
var comparePlainObjects = (a, b) => {
|
|
12
|
-
let differentKeys = false;
|
|
13
|
-
let leastDifferentKey;
|
|
14
|
-
let leastDifferentKeyResult = 0;
|
|
15
|
-
for (const key in a) {
|
|
16
|
-
if (!(key in b)) differentKeys = true;
|
|
17
|
-
else {
|
|
18
|
-
const result = compare(a[key], b[key]);
|
|
19
|
-
if (result !== 0) {
|
|
20
|
-
if (!leastDifferentKey || leastDifferentKey > key) {
|
|
21
|
-
leastDifferentKey = key;
|
|
22
|
-
leastDifferentKeyResult = result;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
if (!differentKeys) {
|
|
28
|
-
for (const key in b) {
|
|
29
|
-
if (!(key in a)) {
|
|
30
|
-
differentKeys = true;
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
if (differentKeys) {
|
|
36
|
-
return compareArrays(Object.keys(a), Object.keys(b));
|
|
37
|
-
}
|
|
38
|
-
return leastDifferentKeyResult;
|
|
39
|
-
};
|
|
40
|
-
var compareCustomComparableHelper = (a, b) => {
|
|
41
|
-
if (a !== null && a !== void 0 && typeof a === "object") {
|
|
42
|
-
if (isFunction(a.compare)) return a.compare(b);
|
|
43
|
-
if (isFunction(a.eq) && a?.eq(b)) return 0;
|
|
44
|
-
if (isFunction(a.lt) && a?.lt(b)) return -1;
|
|
45
|
-
if (isFunction(a.gt) && a?.gt(b)) return 1;
|
|
46
|
-
if (isFunction(a.lte) && a?.lte(b)) return -1;
|
|
47
|
-
if (isFunction(a.gte) && a?.gte(b)) return 1;
|
|
48
|
-
}
|
|
49
|
-
return NaN;
|
|
50
|
-
};
|
|
51
|
-
var compareCustomComparable = (a, b) => {
|
|
52
|
-
const customResult = compareCustomComparableHelper(a, b);
|
|
53
|
-
if (!Number.isNaN(customResult)) return customResult;
|
|
54
|
-
return -compareCustomComparableHelper(b, a);
|
|
55
|
-
};
|
|
56
|
-
var comparePrimitives = (a, b) => {
|
|
57
|
-
if (a === null && b === null) return 0;
|
|
58
|
-
if (a === null) return -1;
|
|
59
|
-
if (b === null) return 1;
|
|
60
|
-
if (a === void 0 && b === void 0) return 0;
|
|
61
|
-
if (a === void 0) return 1;
|
|
62
|
-
if (b === void 0) return -1;
|
|
63
|
-
if (Number.isNaN(a) && Number.isNaN(b)) return 0;
|
|
64
|
-
if (Number.isNaN(a)) return -1;
|
|
65
|
-
if (Number.isNaN(b)) return 1;
|
|
66
|
-
if (typeof a === "number" && typeof b === "number") {
|
|
67
|
-
return a - b;
|
|
68
|
-
}
|
|
69
|
-
if (typeof a === "string" && typeof b === "string") {
|
|
70
|
-
return a.localeCompare(b);
|
|
71
|
-
}
|
|
72
|
-
if (typeof a === "boolean" && typeof b === "boolean") {
|
|
73
|
-
return Number(a) - Number(b);
|
|
74
|
-
}
|
|
75
|
-
if (typeof a !== typeof b) return NaN;
|
|
76
|
-
return NaN;
|
|
77
|
-
};
|
|
78
|
-
var compare = (a, b) => {
|
|
79
|
-
if (a === b) return 0;
|
|
80
|
-
const customResult = compareCustomComparable(a, b);
|
|
81
|
-
if (!Number.isNaN(customResult)) return customResult;
|
|
82
|
-
if (isArray(a) && isArray(b)) {
|
|
83
|
-
return compareArrays(a, b);
|
|
84
|
-
}
|
|
85
|
-
if (isPlainObject(a) && isPlainObject(b)) {
|
|
86
|
-
return comparePlainObjects(a, b);
|
|
87
|
-
}
|
|
88
|
-
return comparePrimitives(a, b);
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
// src/equality.ts
|
|
92
|
-
var eq = (a, b) => compare(a, b) === 0;
|
|
93
|
-
var neq = (a, b) => compare(a, b) !== 0;
|
|
94
|
-
var lt = (a, b) => compare(a, b) < 0;
|
|
95
|
-
var gt = (a, b) => compare(a, b) > 0;
|
|
96
|
-
var lte = (a, b) => compare(a, b) <= 0;
|
|
97
|
-
var gte = (a, b) => compare(a, b) >= 0;
|
|
98
|
-
export {
|
|
99
|
-
compare,
|
|
100
|
-
eq,
|
|
101
|
-
gt,
|
|
102
|
-
gte,
|
|
103
|
-
lt,
|
|
104
|
-
lte,
|
|
105
|
-
neq
|
|
106
|
-
};
|
|
107
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/compare.ts","../src/equality.ts"],"sourcesContent":["import { isArray, isPlainObject, isFunction } from '@art-suite/art-core-ts-types'\nimport { objectKeyCount } from '@art-suite/art-core-ts-containers'\n\nexport interface CustomComparableInterface {\n\n /**\n * Compares `this` with `b`\n * @param b - The value to compare `this` with\n * @returns A number greater than zero if `this` is greater than `b`, less than zero if `this` is less than `b`, and zero if `this` is equal to `b`\n */\n compare(b: any): number\n}\n\nexport interface CustomEqualityInterface {\n /**\n * Checks if `this` equals `b`\n * @param b - The value to compare `this` with\n * @returns true if equal, false otherwise\n */\n eq(b: any): boolean\n}\n\nexport interface CustomInequalityInterface extends CustomEqualityInterface {\n /**\n * Checks if `this` is not equal to `b`\n * @param b - The value to compare `this` with\n * @returns true if not equal, false otherwise\n */\n lt(b: any): boolean\n gt(b: any): boolean\n lte(b: any): boolean\n gte(b: any): boolean\n}\n\nconst compareArrays = (a: any[], b: any[]): number => {\n const minLength = Math.min(a.length, b.length)\n\n for (let i = 0; i < minLength; i++) {\n const result = compare(a[i], b[i])\n if (result !== 0) return result\n }\n\n return a.length - b.length\n}\n\n/**\n * Compares two plain objects. If the keys are different, the two key sets are sorted and compared as arrays of strings.\n * If the keys are the same, the values are compared recursively.\n * @param a - The first object to compare\n * @param b - The second object to compare\n * @returns A number indicating the comparison result\n */\nconst comparePlainObjects = (a: Record<string, any>, b: Record<string, any>): number => {\n // Create a merged list of all unique keys and sort it\n // const allKeys = [...new Set([...Object.keys(a), ...Object.keys(b)])].sort()\n\n // Compare values for keys in A that are also in B\n let differentKeys = false\n let leastDifferentKey: string | undefined\n let leastDifferentKeyResult: number = 0\n for (const key in a) {\n if (!(key in b)) differentKeys = true;\n else {\n // Both have the key, compare their values\n const result = compare(a[key], b[key])\n if (result !== 0) {\n if (!leastDifferentKey || leastDifferentKey > key) {\n leastDifferentKey = key\n leastDifferentKeyResult = result\n }\n }\n }\n }\n\n // if B had all As keys, we need to check if B has any keys that A doesn't have\n if (!differentKeys) {\n for (const key in b) {\n if (!(key in a)) { differentKeys = true; break }\n }\n }\n\n // if the keys are different, compare the keys\n if (differentKeys) {\n return compareArrays(Object.keys(a), Object.keys(b))\n }\n\n return leastDifferentKeyResult // All keys and values are equal\n}\n\nconst compareCustomComparableHelper = (a: any, b: any): number => {\n // Only check for custom methods if a is not null/undefined and is an object\n if (a !== null && a !== undefined && typeof a === 'object') {\n // Check if left operand supports any of the custom methods (highest priority)\n if (isFunction(a.compare)) return a.compare(b);\n if (isFunction(a.eq) && a?.eq(b)) return 0;\n if (isFunction(a.lt) && a?.lt(b)) return -1;\n if (isFunction(a.gt) && a?.gt(b)) return 1;\n if (isFunction(a.lte) && a?.lte(b)) return -1;\n if (isFunction(a.gte) && a?.gte(b)) return 1;\n }\n return NaN\n}\n\nconst compareCustomComparable = (a: any, b: any): number => {\n const customResult = compareCustomComparableHelper(a, b)\n if (!Number.isNaN(customResult)) return customResult\n return -compareCustomComparableHelper(b, a)\n}\n\nconst comparePrimitives = (a: any, b: any): number => {\n // Handle null\n if (a === null && b === null) return 0\n if (a === null) return -1\n if (b === null) return 1\n\n // Handle undefined\n if (a === undefined && b === undefined) return 0\n if (a === undefined) return 1\n if (b === undefined) return -1\n\n // Handle NaN\n if (Number.isNaN(a) && Number.isNaN(b)) return 0\n if (Number.isNaN(a)) return -1\n if (Number.isNaN(b)) return 1\n\n // Handle numbers - use subtraction for efficiency\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b\n }\n\n // Handle strings - use localeCompare for proper string comparison\n if (typeof a === 'string' && typeof b === 'string') {\n return a.localeCompare(b)\n }\n\n // Handle booleans - convert to numbers for comparison\n if (typeof a === 'boolean' && typeof b === 'boolean') {\n return Number(a) - Number(b)\n }\n\n // Return NaN for different types or incompatible comparisons\n if (typeof a !== typeof b) return NaN\n\n // For same types that aren't numbers, strings, or booleans, return NaN\n return NaN\n}\n\n/**\n * deep structural comparison\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns A number indicating the comparison result:\n * - **< 0**: `a` is less than `b`\n * - **== 0**: `a` is equal to `b` (deep structural equality)\n * - **> 0**: `a` is greater than `b`\n * - **NaN**: Values cannot be compared (incompatible types or custom comparison failed)\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const compare = (a: any, b: any): number => {\n if (a === b) return 0;\n // Handle custom comparable first\n const customResult = compareCustomComparable(a, b)\n if (!Number.isNaN(customResult)) return customResult\n\n // Handle arrays\n if (isArray(a) && isArray(b)) {\n return compareArrays(a, b)\n }\n\n // Handle plain objects\n if (isPlainObject(a) && isPlainObject(b)) {\n return comparePlainObjects(a, b)\n }\n\n // Handle primitives\n return comparePrimitives(a, b)\n}","import { compare } from './compare'\n\n/**\n * deep structural == test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are deeply equal (compare returns 0), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const eq = (a: any, b: any): boolean => compare(a, b) === 0;\n\n/**\n * deep structural != test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are not deeply equal (compare returns non-zero), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const neq = (a: any, b: any): boolean => compare(a, b) !== 0;\n\n/**\n * deep structural < test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is less than `b` (compare returns negative), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const lt = (a: any, b: any): boolean => compare(a, b) < 0;\n\n/**\n * deep structural > test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is greater than `b` (compare returns positive), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const gt = (a: any, b: any): boolean => compare(a, b) > 0;\n\n/**\n * deep structural <= test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is less than or equal to `b` (compare returns negative or zero), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const lte = (a: any, b: any): boolean => compare(a, b) <= 0;\n\n/**\n * deep structural >= test\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if `a` is greater than or equal to `b` (compare returns positive or zero), `false` otherwise\n *\n * For more details on comparison behavior, see the art-core-ts-compare README.\n */\nexport const gte = (a: any, b: any): boolean => compare(a, b) >= 0;\n"],"mappings":"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","names":[]}
|