@inglorious/utils 5.0.0 → 5.1.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inglorious/utils",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "A set of general-purpose utility functions designed with functional programming principles in mind.",
|
|
5
5
|
"author": "Matteo Antony Mistretta <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
},
|
|
138
138
|
"sideEffects": false,
|
|
139
139
|
"devDependencies": {
|
|
140
|
-
"@inglorious/eslint-config": "1.1.
|
|
140
|
+
"@inglorious/eslint-config": "1.1.4",
|
|
141
141
|
"prettier": "^3.9.6",
|
|
142
142
|
"vite": "^8.2.2",
|
|
143
143
|
"vitest": "^5.0.0"
|
|
@@ -36,24 +36,6 @@ export const eucledianDistance = (a, b) =>
|
|
|
36
36
|
*/
|
|
37
37
|
export const manhattanDistance = (a, b) => abs(subtract(a.position, b.position))
|
|
38
38
|
|
|
39
|
-
/**
|
|
40
|
-
* Compares the cost of two nodes.
|
|
41
|
-
*
|
|
42
|
-
* @param {Node} a - The first node.
|
|
43
|
-
* @param {Node} b - The second node.
|
|
44
|
-
* @returns {number} - The difference in cost between the two nodes.
|
|
45
|
-
*/
|
|
46
|
-
const compareCost = (a, b) => b.cost - a.cost
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Compares the total cost of two nodes.
|
|
50
|
-
*
|
|
51
|
-
* @param {Node} a - The first node.
|
|
52
|
-
* @param {Node} b - The second node.
|
|
53
|
-
* @returns {number} - The difference in total cost between the two nodes.
|
|
54
|
-
*/
|
|
55
|
-
const compareTotalCost = (a, b) => b.totalCost - a.totalCost
|
|
56
|
-
|
|
57
39
|
/**
|
|
58
40
|
* Finds the shortest path in a graph from a start node to an end node using a heuristic.
|
|
59
41
|
*
|
|
@@ -148,3 +130,25 @@ function adaptGraph(graph) {
|
|
|
148
130
|
function createFindNode(nodes) {
|
|
149
131
|
return (id) => nodes.find((node) => node.id === id)
|
|
150
132
|
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Compares the cost of two nodes.
|
|
136
|
+
*
|
|
137
|
+
* @param {Node} a - The first node.
|
|
138
|
+
* @param {Node} b - The second node.
|
|
139
|
+
* @returns {number} - The difference in cost between the two nodes.
|
|
140
|
+
*/
|
|
141
|
+
function compareCost(a, b) {
|
|
142
|
+
return b.cost - a.cost
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Compares the total cost of two nodes.
|
|
147
|
+
*
|
|
148
|
+
* @param {Node} a - The first node.
|
|
149
|
+
* @param {Node} b - The second node.
|
|
150
|
+
* @returns {number} - The difference in total cost between the two nodes.
|
|
151
|
+
*/
|
|
152
|
+
function compareTotalCost(a, b) {
|
|
153
|
+
return b.totalCost - a.totalCost
|
|
154
|
+
}
|
|
@@ -8,57 +8,59 @@ const NEXT_KEY_OFFSET = 1
|
|
|
8
8
|
const NEXT_LEVEL = 2
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Creates a deep clone of a given value
|
|
12
|
-
* This is a modern and efficient way to deep-clone objects.
|
|
11
|
+
* Creates a deep clone of a given value.
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* Plain objects, arrays and primitives -- what state is nearly always made of -- are
|
|
14
|
+
* copied by hand, because a general algorithm pays for being one: across thousands of
|
|
15
|
+
* small objects, `structuredClone` takes about twice as long and a JSON round trip
|
|
16
|
+
* longer still. Vectors stay vectors, which neither of those keeps: the tag that marks
|
|
17
|
+
* one is not enumerable, so anything that copies only what it can see drops it.
|
|
17
18
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
19
|
+
* Anything else is handed to `structuredClone`, so a `Date` or a `Map` is still copied
|
|
20
|
+
* properly, and DOM nodes or class instances with non-cloneable internals still throw a
|
|
21
|
+
* `DataCloneError`. Functions are kept as they are rather than copied, since there is
|
|
22
|
+
* nothing in one to copy.
|
|
20
23
|
*
|
|
21
24
|
* This is similar to Lodash's `_.cloneDeep`.
|
|
22
25
|
*
|
|
23
26
|
* @template T
|
|
24
|
-
* @param {T}
|
|
27
|
+
* @param {T} value - The value to clone.
|
|
25
28
|
* @returns {T} A deep clone of the input value.
|
|
26
29
|
*/
|
|
27
|
-
export function clone(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
export function clone(value) {
|
|
31
|
+
// A vector holds numbers and nothing else, so it needs no copying below the top -- and
|
|
32
|
+
// building it in one go is noticeably cheaper than copying it and tagging the copy.
|
|
33
|
+
if (value?.__isVector__) {
|
|
34
|
+
return v(...value)
|
|
35
|
+
}
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* This is a helper function for `merge` and `extend`.
|
|
34
|
-
*
|
|
35
|
-
* @param {Object} target - The target object to merge into.
|
|
36
|
-
* @param {Object} source - The source object to merge from.
|
|
37
|
-
* @param {Function} [merger] - An optional function to customize merging behavior for specific keys.
|
|
38
|
-
* @returns {Object} - The modified target object.
|
|
39
|
-
*/
|
|
40
|
-
function deepMerge(target, source, merger) {
|
|
41
|
-
for (const [key, value] of Object.entries(source)) {
|
|
42
|
-
if (isFunction(merger)) {
|
|
43
|
-
const mergedValue = merger(target[key], value)
|
|
44
|
-
if (mergedValue !== undefined) {
|
|
45
|
-
target[key] = mergedValue
|
|
46
|
-
continue
|
|
47
|
-
}
|
|
48
|
-
}
|
|
37
|
+
if (isArray(value)) {
|
|
38
|
+
const copy = new Array(value.length)
|
|
49
39
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
} else if (isObject(value)) {
|
|
53
|
-
if (!isObject(target[key])) {
|
|
54
|
-
target[key] = {}
|
|
55
|
-
}
|
|
56
|
-
target[key] = deepMerge(target[key], value, merger)
|
|
57
|
-
} else {
|
|
58
|
-
target[key] = value
|
|
40
|
+
for (let index = 0; index < value.length; index++) {
|
|
41
|
+
copy[index] = clone(value[index])
|
|
59
42
|
}
|
|
43
|
+
|
|
44
|
+
return copy
|
|
60
45
|
}
|
|
61
|
-
|
|
46
|
+
|
|
47
|
+
if (value === null || typeof value !== "object") {
|
|
48
|
+
return value
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const prototype = Object.getPrototypeOf(value)
|
|
52
|
+
|
|
53
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
54
|
+
return structuredClone(value)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const copy = {}
|
|
58
|
+
|
|
59
|
+
for (const key in value) {
|
|
60
|
+
copy[key] = clone(value[key])
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return copy
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
/**
|
|
@@ -326,7 +328,7 @@ export function mergeWith(merger, target, ...sources) {
|
|
|
326
328
|
*
|
|
327
329
|
* **Important:** Unlike Immer, which uses structural sharing via proxies for
|
|
328
330
|
* high performance, this implementation performs a full deep clone of the base
|
|
329
|
-
* state on every call using `
|
|
331
|
+
* state on every call using `clone`. This can be
|
|
330
332
|
* inefficient for large or complex states. It is intended for simple use cases
|
|
331
333
|
* where the convenience of the API outweighs the performance cost.
|
|
332
334
|
*
|
|
@@ -480,3 +482,36 @@ ${" ".repeat(indentationLevel)}}`
|
|
|
480
482
|
|
|
481
483
|
return obj
|
|
482
484
|
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Recursively merges properties from a source object into a target object.
|
|
488
|
+
* This is a helper function for `merge` and `extend`.
|
|
489
|
+
*
|
|
490
|
+
* @param {Object} target - The target object to merge into.
|
|
491
|
+
* @param {Object} source - The source object to merge from.
|
|
492
|
+
* @param {Function} [merger] - An optional function to customize merging behavior for specific keys.
|
|
493
|
+
* @returns {Object} - The modified target object.
|
|
494
|
+
*/
|
|
495
|
+
function deepMerge(target, source, merger) {
|
|
496
|
+
for (const [key, value] of Object.entries(source)) {
|
|
497
|
+
if (isFunction(merger)) {
|
|
498
|
+
const mergedValue = merger(target[key], value)
|
|
499
|
+
if (mergedValue !== undefined) {
|
|
500
|
+
target[key] = mergedValue
|
|
501
|
+
continue
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
if (isArray(value)) {
|
|
506
|
+
target[key] = value
|
|
507
|
+
} else if (isObject(value)) {
|
|
508
|
+
if (!isObject(target[key])) {
|
|
509
|
+
target[key] = {}
|
|
510
|
+
}
|
|
511
|
+
target[key] = deepMerge(target[key], value, merger)
|
|
512
|
+
} else {
|
|
513
|
+
target[key] = value
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return target
|
|
517
|
+
}
|
|
@@ -71,9 +71,10 @@ export type DefaultsResult<T extends object, D extends object> = Omit<
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
|
-
* Creates a deep clone of a value.
|
|
74
|
+
* Creates a deep clone of a value. Plain data is copied by hand and vectors stay
|
|
75
|
+
* vectors; anything else goes through `structuredClone`.
|
|
75
76
|
*/
|
|
76
|
-
export function clone<T>(
|
|
77
|
+
export function clone<T>(value: T): T
|
|
77
78
|
|
|
78
79
|
/**
|
|
79
80
|
* Assigns default properties to a target in place.
|