@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 CHANGED
@@ -1,140 +1,166 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
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
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
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
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- compare: () => compare,
24
- eq: () => eq,
25
- gt: () => gt,
26
- gte: () => gte,
27
- lt: () => lt,
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
- var compareCustomComparable = (a, b) => {
84
- const customResult = compareCustomComparableHelper(a, b);
85
- if (!Number.isNaN(customResult)) return customResult;
86
- return -compareCustomComparableHelper(b, a);
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
- var comparePrimitives = (a, b) => {
89
- if (a === null && b === null) return 0;
90
- if (a === null) return -1;
91
- if (b === null) return 1;
92
- if (a === void 0 && b === void 0) return 0;
93
- if (a === void 0) return 1;
94
- if (b === void 0) return -1;
95
- if (Number.isNaN(a) && Number.isNaN(b)) return 0;
96
- if (Number.isNaN(a)) return -1;
97
- if (Number.isNaN(b)) return 1;
98
- if (typeof a === "number" && typeof b === "number") {
99
- return a - b;
100
- }
101
- if (typeof a === "string" && typeof b === "string") {
102
- return a.localeCompare(b);
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
- var compare = (a, b) => {
111
- if (a === b) return 0;
112
- const customResult = compareCustomComparable(a, b);
113
- if (!Number.isNaN(customResult)) return customResult;
114
- if ((0, import_art_core_ts_types.isArray)(a) && (0, import_art_core_ts_types.isArray)(b)) {
115
- return compareArrays(a, b);
116
- }
117
- if ((0, import_art_core_ts_types.isPlainObject)(a) && (0, import_art_core_ts_types.isPlainObject)(b)) {
118
- return comparePlainObjects(a, b);
119
- }
120
- return comparePrimitives(a, b);
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
@@ -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
- * Compares `this` with `b`
4
- * @param b - The value to compare `this` with
5
- * @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`
6
- */
7
- compare(b: any): number;
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
- * Checks if `this` equals `b`
12
- * @param b - The value to compare `this` with
13
- * @returns true if equal, false otherwise
14
- */
15
- eq(b: any): boolean;
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
- * Checks if `this` is not equal to `b`
20
- * @param b - The value to compare `this` with
21
- * @returns true if not equal, false otherwise
22
- */
23
- lt(b: any): boolean;
24
- gt(b: any): boolean;
25
- lte(b: any): boolean;
26
- gte(b: any): boolean;
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 { type CustomComparableInterface, type CustomEqualityInterface, type CustomInequalityInterface, compare, eq, gt, gte, lt, lte, neq };
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
- * Compares `this` with `b`
4
- * @param b - The value to compare `this` with
5
- * @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`
6
- */
7
- compare(b: any): number;
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
- * Checks if `this` equals `b`
12
- * @param b - The value to compare `this` with
13
- * @returns true if equal, false otherwise
14
- */
15
- eq(b: any): boolean;
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
- * Checks if `this` is not equal to `b`
20
- * @param b - The value to compare `this` with
21
- * @returns true if not equal, false otherwise
22
- */
23
- lt(b: any): boolean;
24
- gt(b: any): boolean;
25
- lte(b: any): boolean;
26
- gte(b: any): boolean;
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 { type CustomComparableInterface, type CustomEqualityInterface, type CustomInequalityInterface, compare, eq, gt, gte, lt, lte, neq };
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.0.11",
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.ts",
16
- "import": "./dist/index.js",
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.js",
21
- "types": "./dist/index.d.ts",
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;tsup src/index.ts --format esm,cjs --dts --sourcemap",
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.9.9",
40
- "@art-suite/art-core-ts-types": "^0.3.11"
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.5"
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":[]}