@oscarpalmer/atoms 0.167.0 → 0.169.0
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/array/index.d.mts +1 -2
- package/dist/array/index.mjs +1 -2
- package/dist/array/sort.d.mts +29 -5
- package/dist/array/sort.mjs +27 -14
- package/dist/index.d.mts +122 -98
- package/dist/index.mjs +228 -212
- package/dist/internal/is.d.mts +8 -2
- package/dist/internal/is.mjs +10 -1
- package/dist/internal/value/equal.mjs +9 -17
- package/dist/is.d.mts +1 -8
- package/dist/is.mjs +1 -10
- package/dist/sized/map.mjs +13 -7
- package/dist/sized/set.mjs +4 -4
- package/dist/value/clone.mjs +17 -14
- package/dist/value/diff.mjs +10 -9
- package/package.json +6 -2
- package/src/array/index.ts +0 -1
- package/src/array/sort.ts +100 -63
- package/src/index.ts +1 -0
- package/src/internal/is.ts +19 -1
- package/src/internal/value/equal.ts +21 -24
- package/src/is.ts +1 -11
- package/src/sized/map.ts +17 -11
- package/src/sized/set.ts +6 -5
- package/src/value/clone.ts +39 -23
- package/src/value/diff.ts +15 -16
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import {isPrimitive} from '../is';
|
|
1
2
|
import type {ArrayOrPlainObject, Constructor, PlainObject, TypedArray} from '../../models';
|
|
2
|
-
import {chunk} from '../array/chunk';
|
|
3
3
|
import {isPlainObject, isTypedArray} from '../is';
|
|
4
4
|
import {getCompareHandlers} from './handlers';
|
|
5
5
|
|
|
@@ -122,21 +122,11 @@ function equalArray(first: unknown[], second: unknown[], options: Options): bool
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
const
|
|
125
|
+
const end = length - offset;
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
for (let chunkIndex = 0; chunkIndex < chunksLength; chunkIndex += 1) {
|
|
132
|
-
const firstChunk = firstChunks[chunkIndex];
|
|
133
|
-
const secondChunk = secondChunks[chunkIndex];
|
|
134
|
-
const chunkLength = firstChunk.length;
|
|
135
|
-
|
|
136
|
-
for (let index = 0; index < chunkLength; index += 1) {
|
|
137
|
-
if (!equalValue(firstChunk[index], secondChunk[index], options)) {
|
|
138
|
-
return false;
|
|
139
|
-
}
|
|
127
|
+
for (let index = offset; index < end; index += 1) {
|
|
128
|
+
if (!equalValue(first[index], second[index], options)) {
|
|
129
|
+
return false;
|
|
140
130
|
}
|
|
141
131
|
}
|
|
142
132
|
|
|
@@ -167,16 +157,11 @@ function equalMap(
|
|
|
167
157
|
}
|
|
168
158
|
|
|
169
159
|
const firstKeys = [...first.keys()];
|
|
170
|
-
const secondKeys = [...second.keys()];
|
|
171
|
-
|
|
172
|
-
if (firstKeys.some(key => !secondKeys.includes(key))) {
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
160
|
|
|
176
161
|
for (let index = 0; index < size; index += 1) {
|
|
177
162
|
const key = firstKeys[index];
|
|
178
163
|
|
|
179
|
-
if (!equalValue(first.get(key), second.get(key), options)) {
|
|
164
|
+
if (!second.has(key) || !equalValue(first.get(key), second.get(key), options)) {
|
|
180
165
|
return false;
|
|
181
166
|
}
|
|
182
167
|
}
|
|
@@ -197,16 +182,22 @@ function equalPlainObject(
|
|
|
197
182
|
secondKeys = secondKeys.filter(key => filterKey(key, options));
|
|
198
183
|
}
|
|
199
184
|
|
|
185
|
+
const useSet = secondKeys.length >= MINIMUM_LENGTH_FOR_SET;
|
|
186
|
+
const secondSet = useSet ? new Set(secondKeys) : undefined;
|
|
187
|
+
|
|
200
188
|
const {length} = firstKeys;
|
|
201
189
|
|
|
202
|
-
if (length !== secondKeys.length
|
|
190
|
+
if (length !== secondKeys.length) {
|
|
203
191
|
return false;
|
|
204
192
|
}
|
|
205
193
|
|
|
206
194
|
for (let index = 0; index < length; index += 1) {
|
|
207
195
|
const key = firstKeys[index];
|
|
208
196
|
|
|
209
|
-
if (
|
|
197
|
+
if (
|
|
198
|
+
!(secondSet?.has(key) ?? secondKeys.includes(key)) ||
|
|
199
|
+
!equalValue(first[key as never], second[key as never], options)
|
|
200
|
+
) {
|
|
210
201
|
return false;
|
|
211
202
|
}
|
|
212
203
|
}
|
|
@@ -246,7 +237,11 @@ function equalSet(first: Set<unknown>, second: Set<unknown>, options: Options):
|
|
|
246
237
|
for (let index = 0; index < size; index += 1) {
|
|
247
238
|
const firstValue = firstValues[index];
|
|
248
239
|
|
|
249
|
-
if (
|
|
240
|
+
if (
|
|
241
|
+
isPrimitive(firstValue)
|
|
242
|
+
? !second.has(firstValue)
|
|
243
|
+
: !secondValues.some(secondValue => equalValue(firstValue, secondValue, options))
|
|
244
|
+
) {
|
|
250
245
|
return false;
|
|
251
246
|
}
|
|
252
247
|
}
|
|
@@ -439,4 +434,6 @@ const ERROR_PROPERTIES: string[] = ['name', 'message'];
|
|
|
439
434
|
|
|
440
435
|
const EXPRESSION_PROPERTIES: string[] = ['source', 'flags'];
|
|
441
436
|
|
|
437
|
+
const MINIMUM_LENGTH_FOR_SET = 16;
|
|
438
|
+
|
|
442
439
|
// #endregion
|
package/src/is.ts
CHANGED
|
@@ -88,21 +88,10 @@ export function isObject(value: unknown): value is object {
|
|
|
88
88
|
return (typeof value === 'object' && value !== null) || typeof value === 'function';
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
/**
|
|
92
|
-
* - Is the value a primitive value?
|
|
93
|
-
* @param value Value to check
|
|
94
|
-
* @returns `true` if the value matches, otherwise `false`
|
|
95
|
-
*/
|
|
96
|
-
export function isPrimitive(value: unknown): value is Primitive {
|
|
97
|
-
return value == null || EXPRESSION_PRIMITIVE.test(typeof value);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
91
|
// #endregion
|
|
101
92
|
|
|
102
93
|
// #region Variables
|
|
103
94
|
|
|
104
|
-
const EXPRESSION_PRIMITIVE = /^(bigint|boolean|number|string|symbol)$/;
|
|
105
|
-
|
|
106
95
|
const EXPRESSION_WHITESPACE = /^\s*$/;
|
|
107
96
|
|
|
108
97
|
// #endregion
|
|
@@ -116,6 +105,7 @@ export {
|
|
|
116
105
|
isKey,
|
|
117
106
|
isNumber,
|
|
118
107
|
isPlainObject,
|
|
108
|
+
isPrimitive,
|
|
119
109
|
isTypedArray,
|
|
120
110
|
} from './internal/is';
|
|
121
111
|
|
package/src/sized/map.ts
CHANGED
|
@@ -17,7 +17,7 @@ export class SizedMap<SizedKey = unknown, SizedValue = unknown> extends Map<Size
|
|
|
17
17
|
* Is the Map full?
|
|
18
18
|
*/
|
|
19
19
|
get full(): boolean {
|
|
20
|
-
return
|
|
20
|
+
return super.size >= this.#maximumSize;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
get maximum(): number {
|
|
@@ -75,26 +75,32 @@ export class SizedMap<SizedKey = unknown, SizedValue = unknown> extends Map<Size
|
|
|
75
75
|
* @inheritdoc
|
|
76
76
|
*/
|
|
77
77
|
override get(key: SizedKey): SizedValue | undefined {
|
|
78
|
-
|
|
78
|
+
if (super.has(key)) {
|
|
79
|
+
const value = super.get(key) as SizedValue;
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
this.set(key, value as SizedValue);
|
|
82
|
-
}
|
|
81
|
+
this.#setValue(key, value, true);
|
|
83
82
|
|
|
84
|
-
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
88
|
* @inheritdoc
|
|
89
89
|
*/
|
|
90
90
|
override set(key: SizedKey, value: SizedValue): this {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
return this.#setValue(key, value, super.has(key));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#setValue(key: SizedKey, value: SizedValue, has: boolean): this {
|
|
95
|
+
if (has) {
|
|
96
|
+
super.delete(key);
|
|
97
|
+
} else if (super.size >= this.#maximumSize) {
|
|
98
|
+
super.delete(super.keys().next().value as SizedKey);
|
|
95
99
|
}
|
|
96
100
|
|
|
97
|
-
|
|
101
|
+
super.set(key, value);
|
|
102
|
+
|
|
103
|
+
return this;
|
|
98
104
|
}
|
|
99
105
|
}
|
|
100
106
|
|
package/src/sized/set.ts
CHANGED
|
@@ -71,10 +71,10 @@ export class SizedSet<Value = unknown> extends Set<Value> {
|
|
|
71
71
|
* @inheritdoc
|
|
72
72
|
*/
|
|
73
73
|
override add(value: Value): this {
|
|
74
|
-
if (
|
|
75
|
-
|
|
74
|
+
if (super.has(value)) {
|
|
75
|
+
super.delete(value);
|
|
76
76
|
} else if (this.size >= this.#maximumSize) {
|
|
77
|
-
|
|
77
|
+
super.delete(this.values().next().value as Value);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
return super.add(value);
|
|
@@ -87,9 +87,10 @@ export class SizedSet<Value = unknown> extends Set<Value> {
|
|
|
87
87
|
* @returns Found value if it exists, otherwise `undefined`
|
|
88
88
|
*/
|
|
89
89
|
get(value: Value, update?: boolean): Value | undefined {
|
|
90
|
-
if (
|
|
90
|
+
if (super.has(value)) {
|
|
91
91
|
if (update ?? false) {
|
|
92
|
-
|
|
92
|
+
super.delete(value);
|
|
93
|
+
|
|
93
94
|
this.add(value);
|
|
94
95
|
}
|
|
95
96
|
|
package/src/value/clone.ts
CHANGED
|
@@ -86,36 +86,28 @@ function cloneDataView(
|
|
|
86
86
|
return cloned;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
function
|
|
90
|
-
|
|
89
|
+
function cloneMap(
|
|
90
|
+
map: Map<unknown, unknown>,
|
|
91
91
|
depth: number,
|
|
92
92
|
references: WeakMap<WeakKey, unknown>,
|
|
93
|
-
):
|
|
93
|
+
): Map<unknown, unknown> {
|
|
94
94
|
if (depth >= MAX_CLONE_DEPTH) {
|
|
95
|
-
return
|
|
95
|
+
return map;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
const
|
|
99
|
-
const
|
|
100
|
-
const entries = [...value.entries()];
|
|
101
|
-
const {length} = entries;
|
|
98
|
+
const cloned = new Map<unknown, unknown>();
|
|
99
|
+
const entries = map.entries();
|
|
102
100
|
|
|
103
|
-
for (
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
cloneValue(entry[0], depth + 1, references),
|
|
109
|
-
cloneValue(entry[1], depth + 1, references),
|
|
110
|
-
);
|
|
111
|
-
} else {
|
|
112
|
-
(cloned as Set<unknown>).add(cloneValue(entry[0], depth + 1, references));
|
|
113
|
-
}
|
|
101
|
+
for (const entry of entries) {
|
|
102
|
+
cloned.set(
|
|
103
|
+
cloneValue(entry[0], depth + 1, references),
|
|
104
|
+
cloneValue(entry[1], depth + 1, references),
|
|
105
|
+
);
|
|
114
106
|
}
|
|
115
107
|
|
|
116
|
-
references.set(
|
|
108
|
+
references.set(map, cloned);
|
|
117
109
|
|
|
118
|
-
return cloned
|
|
110
|
+
return cloned;
|
|
119
111
|
}
|
|
120
112
|
|
|
121
113
|
function cloneNode(node: Node, depth: number, references: WeakMap<WeakKey, unknown>): Node {
|
|
@@ -172,6 +164,28 @@ function cloneRegularExpression(
|
|
|
172
164
|
return cloned;
|
|
173
165
|
}
|
|
174
166
|
|
|
167
|
+
function cloneSet(
|
|
168
|
+
set: Set<unknown>,
|
|
169
|
+
depth: number,
|
|
170
|
+
references: WeakMap<WeakKey, unknown>,
|
|
171
|
+
): Set<unknown> {
|
|
172
|
+
if (depth >= MAX_CLONE_DEPTH) {
|
|
173
|
+
return set;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const cloned = new Set<unknown>();
|
|
177
|
+
const values = [...set.values()];
|
|
178
|
+
const {length} = values;
|
|
179
|
+
|
|
180
|
+
for (let index = 0; index < length; index += 1) {
|
|
181
|
+
cloned.add(cloneValue(values[index], depth + 1, references));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
references.set(set, cloned);
|
|
185
|
+
|
|
186
|
+
return cloned;
|
|
187
|
+
}
|
|
188
|
+
|
|
175
189
|
function cloneTypedArray(
|
|
176
190
|
value: TypedArray,
|
|
177
191
|
depth: number,
|
|
@@ -227,12 +241,14 @@ function cloneValue(value: unknown, depth: number, references: WeakMap<WeakKey,
|
|
|
227
241
|
return cloneRegularExpression(value, depth, references);
|
|
228
242
|
|
|
229
243
|
case value instanceof Map:
|
|
230
|
-
|
|
231
|
-
return cloneMapOrSet(value, depth, references);
|
|
244
|
+
return cloneMap(value, depth, references);
|
|
232
245
|
|
|
233
246
|
case value instanceof Node:
|
|
234
247
|
return cloneNode(value, depth, references);
|
|
235
248
|
|
|
249
|
+
case value instanceof Set:
|
|
250
|
+
return cloneSet(value, depth, references);
|
|
251
|
+
|
|
236
252
|
case isArrayOrPlainObject(value):
|
|
237
253
|
return clonePlainObject(value, depth, references);
|
|
238
254
|
|
package/src/value/diff.ts
CHANGED
|
@@ -57,8 +57,8 @@ type KeyedDiffValue = {
|
|
|
57
57
|
type Parameters = {
|
|
58
58
|
changes: KeyedDiffValue[];
|
|
59
59
|
key: PropertyKey;
|
|
60
|
+
options: Required<DiffOptions>;
|
|
60
61
|
values: {first: unknown; second: unknown};
|
|
61
|
-
relaxedNullish: boolean;
|
|
62
62
|
prefix?: string;
|
|
63
63
|
};
|
|
64
64
|
|
|
@@ -106,7 +106,7 @@ export function diff<First, Second = First>(
|
|
|
106
106
|
return diffResult;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
const diffs = getDiffs(first, second, relaxedNullish);
|
|
109
|
+
const diffs = getDiffs(first, second, {relaxedNullish});
|
|
110
110
|
|
|
111
111
|
const {length} = diffs;
|
|
112
112
|
|
|
@@ -127,7 +127,7 @@ function getChanges(
|
|
|
127
127
|
changes: KeyedDiffValue[],
|
|
128
128
|
first: unknown,
|
|
129
129
|
second: unknown,
|
|
130
|
-
|
|
130
|
+
options: Required<DiffOptions>,
|
|
131
131
|
prefix?: string,
|
|
132
132
|
): KeyedDiffValue[] {
|
|
133
133
|
const checked = new Set<PropertyKey>();
|
|
@@ -151,7 +151,7 @@ function getChanges(
|
|
|
151
151
|
setChanges({
|
|
152
152
|
changes,
|
|
153
153
|
key,
|
|
154
|
-
|
|
154
|
+
options,
|
|
155
155
|
prefix,
|
|
156
156
|
values: {first, second},
|
|
157
157
|
});
|
|
@@ -164,7 +164,7 @@ function getChanges(
|
|
|
164
164
|
function getDiffs(
|
|
165
165
|
first: unknown,
|
|
166
166
|
second: unknown,
|
|
167
|
-
|
|
167
|
+
options: Required<DiffOptions>,
|
|
168
168
|
prefix?: string,
|
|
169
169
|
): KeyedDiffValue[] {
|
|
170
170
|
const changes: KeyedDiffValue[] = [];
|
|
@@ -184,31 +184,30 @@ function getDiffs(
|
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
return getChanges(changes, first, second,
|
|
187
|
+
return getChanges(changes, first, second, options, prefix);
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
function setChanges(parameters: Parameters): void {
|
|
191
|
-
const {changes, key, prefix,
|
|
191
|
+
const {changes, key, prefix, options, values} = parameters;
|
|
192
192
|
|
|
193
|
-
const
|
|
194
|
-
|
|
193
|
+
const prefixed = join([prefix, key], '.');
|
|
194
|
+
|
|
195
|
+
const from: unknown = values.first?.[key as never];
|
|
196
|
+
const to: unknown = values.second?.[key as never];
|
|
195
197
|
|
|
196
|
-
|
|
198
|
+
const nested = isArrayOrPlainObject(from) || isArrayOrPlainObject(to);
|
|
199
|
+
const diffs = nested ? getDiffs(from, to, options, prefixed) : [];
|
|
200
|
+
|
|
201
|
+
if (nested ? diffs.length === 0 : equal(from, to, options)) {
|
|
197
202
|
return;
|
|
198
203
|
}
|
|
199
204
|
|
|
200
|
-
const prefixed = join([prefix, key], '.');
|
|
201
|
-
|
|
202
205
|
const change = {
|
|
203
206
|
from,
|
|
204
207
|
to,
|
|
205
208
|
key: prefixed,
|
|
206
209
|
};
|
|
207
210
|
|
|
208
|
-
const nested = isArrayOrPlainObject(from) || isArrayOrPlainObject(to);
|
|
209
|
-
|
|
210
|
-
const diffs = nested ? getDiffs(from, to, relaxedNullish, prefixed) : [];
|
|
211
|
-
|
|
212
211
|
changes.push(change);
|
|
213
212
|
|
|
214
213
|
const diffsLength = diffs.length;
|