tspo 1.0.0 → 1.0.2
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/README.md +7 -1
- package/dist/cjs/tspo.js +66 -14
- package/dist/cjs/utils/compare.js +11 -5
- package/dist/cjs/utils/copy.js +52 -9
- package/dist/cjs/utils/iterate.js +19 -12
- package/dist/esm/tspo.js +66 -14
- package/dist/esm/utils/compare.js +11 -5
- package/dist/esm/utils/copy.js +52 -9
- package/dist/esm/utils/iterate.js +19 -12
- package/dist/types/tspo.d.ts +4 -4
- package/dist/types/utility-types.d.ts +3 -3
- package/dist/types/utils/copy.d.ts +6 -2
- package/dist/types/utils/iterate.d.ts +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# tspo
|
|
1
|
+
# 🟦 tspo
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/tspo)
|
|
4
4
|
[](https://www.npmjs.com/package/tspo)
|
|
@@ -6,4 +6,10 @@
|
|
|
6
6
|
[](https://bundlephobia.com/package/tspo)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
|
|
9
|
+
> `tspo (TypeScript Plain Object)` is a collection of utilities for handling both runtime and compile-time behavior for plain-objects.
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<img src="https://raw.githubusercontent.com/seanpmaxwell/tspo/master/screenshot.png" alt="tspo screenshot" />
|
|
13
|
+
</p>
|
|
14
|
+
|
|
9
15
|
Please refer to the official <a href="https://github.com/seanpmaxwell/tspo">github repo</a> for the most up-to-date documentation.
|
package/dist/cjs/tspo.js
CHANGED
|
@@ -2,20 +2,43 @@ import isPlainObject, {} from './isPlainObject.js';
|
|
|
2
2
|
import compare from './utils/compare.js';
|
|
3
3
|
import copy from './utils/copy.js';
|
|
4
4
|
import iterate from './utils/iterate.js';
|
|
5
|
+
const hop = Object.prototype.hasOwnProperty;
|
|
5
6
|
function omit(obj, keys) {
|
|
6
|
-
const retVal = {}
|
|
7
|
+
const retVal = {};
|
|
8
|
+
const dict = obj;
|
|
9
|
+
if (Array.isArray(keys)) {
|
|
10
|
+
const set = new Set(keys);
|
|
11
|
+
for (const key in obj) {
|
|
12
|
+
if (!set.has(key)) {
|
|
13
|
+
retVal[key] = dict[key];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return retVal;
|
|
17
|
+
}
|
|
18
|
+
const omittedKey = keys;
|
|
7
19
|
for (const key in obj) {
|
|
8
|
-
if (
|
|
9
|
-
retVal[key] =
|
|
20
|
+
if (key !== omittedKey) {
|
|
21
|
+
retVal[key] = dict[key];
|
|
10
22
|
}
|
|
11
23
|
}
|
|
12
24
|
return retVal;
|
|
13
25
|
}
|
|
14
26
|
function pick(obj, keys) {
|
|
15
|
-
const retVal = {}
|
|
27
|
+
const retVal = {};
|
|
28
|
+
const dict = obj;
|
|
29
|
+
if (Array.isArray(keys)) {
|
|
30
|
+
const set = new Set(keys);
|
|
31
|
+
for (const key in obj) {
|
|
32
|
+
if (set.has(key)) {
|
|
33
|
+
retVal[key] = dict[key];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return retVal;
|
|
37
|
+
}
|
|
38
|
+
const pickedKey = keys;
|
|
16
39
|
for (const key in obj) {
|
|
17
|
-
if (
|
|
18
|
-
retVal[key] =
|
|
40
|
+
if (key === pickedKey) {
|
|
41
|
+
retVal[key] = dict[key];
|
|
19
42
|
}
|
|
20
43
|
}
|
|
21
44
|
return retVal;
|
|
@@ -61,17 +84,23 @@ function reverseIndex(obj, value) {
|
|
|
61
84
|
return retVal;
|
|
62
85
|
}
|
|
63
86
|
function safeReverseIndex(obj, value) {
|
|
64
|
-
|
|
87
|
+
let found = false;
|
|
88
|
+
let retVal;
|
|
65
89
|
for (const key in obj) {
|
|
66
90
|
if (obj[key] === value) {
|
|
67
|
-
|
|
91
|
+
if (found) {
|
|
92
|
+
throw new Error('.safeReverseIndex found 0 or more than 1 keys for value: ' +
|
|
93
|
+
String(value));
|
|
94
|
+
}
|
|
95
|
+
found = true;
|
|
96
|
+
retVal = key;
|
|
68
97
|
}
|
|
69
98
|
}
|
|
70
|
-
if (
|
|
99
|
+
if (!found) {
|
|
71
100
|
throw new Error('.safeReverseIndex found 0 or more than 1 keys for value: ' +
|
|
72
101
|
String(value));
|
|
73
102
|
}
|
|
74
|
-
return retVal
|
|
103
|
+
return retVal;
|
|
75
104
|
}
|
|
76
105
|
function isKey(obj, arg) {
|
|
77
106
|
const keyArr = Array.isArray(arg) ? arg : [arg];
|
|
@@ -82,9 +111,23 @@ function isKey(obj, arg) {
|
|
|
82
111
|
return true;
|
|
83
112
|
}
|
|
84
113
|
function isValue(obj, arg) {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
114
|
+
const dict = obj;
|
|
115
|
+
if (!Array.isArray(arg)) {
|
|
116
|
+
for (const key in obj) {
|
|
117
|
+
if (hop.call(obj, key) && sameValueZero(dict[key], arg))
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
for (const val of arg) {
|
|
123
|
+
let found = false;
|
|
124
|
+
for (const key in obj) {
|
|
125
|
+
if (hop.call(obj, key) && sameValueZero(dict[key], val)) {
|
|
126
|
+
found = true;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (!found)
|
|
88
131
|
return false;
|
|
89
132
|
}
|
|
90
133
|
return true;
|
|
@@ -99,7 +142,16 @@ function entries(obj) {
|
|
|
99
142
|
return Object.entries(obj);
|
|
100
143
|
}
|
|
101
144
|
function firstEntry(obj) {
|
|
102
|
-
|
|
145
|
+
const dict = obj;
|
|
146
|
+
for (const key in obj) {
|
|
147
|
+
if (hop.call(obj, key)) {
|
|
148
|
+
return [key, dict[key]];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
function sameValueZero(a, b) {
|
|
154
|
+
return a === b || (a !== a && b !== b);
|
|
103
155
|
}
|
|
104
156
|
function toDict(obj) {
|
|
105
157
|
if (!isPlainObject(obj)) {
|
|
@@ -7,16 +7,22 @@ function compare(a, b) {
|
|
|
7
7
|
return comparePlainObjects(a, b);
|
|
8
8
|
}
|
|
9
9
|
function comparePlainObjects(a, b) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
let aSize = 0;
|
|
11
|
+
for (const key in a) {
|
|
12
|
+
if (!hop.call(a, key))
|
|
13
|
+
continue;
|
|
14
|
+
aSize++;
|
|
14
15
|
if (!hop.call(b, key))
|
|
15
16
|
return false;
|
|
16
17
|
if (!compareValue(a[key], b[key]))
|
|
17
18
|
return false;
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
+
let bSize = 0;
|
|
21
|
+
for (const key in b) {
|
|
22
|
+
if (hop.call(b, key))
|
|
23
|
+
bSize++;
|
|
24
|
+
}
|
|
25
|
+
return aSize === bSize;
|
|
20
26
|
}
|
|
21
27
|
function compareValue(a, b) {
|
|
22
28
|
if (Object.is(a, b))
|
package/dist/cjs/utils/copy.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import isPlainObject, {} from '../isPlainObject.js';
|
|
2
|
-
import {} from '../utility-types.js';
|
|
3
2
|
const hop = Object.prototype.hasOwnProperty;
|
|
4
3
|
function copy(value, options) {
|
|
5
4
|
if (!isPlainObject(value)) {
|
|
6
5
|
throw new TypeError('copy only accepts a plain-object as the root value');
|
|
7
6
|
}
|
|
8
7
|
const resetDates = options?.resetDates === true;
|
|
9
|
-
|
|
8
|
+
const deepCloneAll = options?.deepCloneAll === true;
|
|
9
|
+
return clonePlainObject(value, Object.getPrototypeOf(value), resetDates, deepCloneAll);
|
|
10
10
|
}
|
|
11
|
-
function clonePlainObject(source, proto, resetDates) {
|
|
11
|
+
function clonePlainObject(source, proto, resetDates, deepCloneAll) {
|
|
12
12
|
const out = proto === null ? Object.create(null) : {};
|
|
13
13
|
for (const key in source) {
|
|
14
14
|
if (!hop.call(source, key))
|
|
15
15
|
continue;
|
|
16
|
-
out[key] = cloneValue(source[key], resetDates);
|
|
16
|
+
out[key] = cloneValue(source[key], resetDates, deepCloneAll);
|
|
17
17
|
}
|
|
18
18
|
return out;
|
|
19
19
|
}
|
|
20
|
-
function cloneValue(value, resetDates) {
|
|
20
|
+
function cloneValue(value, resetDates, deepCloneAll) {
|
|
21
21
|
if (isPlainObject(value)) {
|
|
22
|
-
return clonePlainObject(value, Object.getPrototypeOf(value), resetDates);
|
|
22
|
+
return clonePlainObject(value, Object.getPrototypeOf(value), resetDates, deepCloneAll);
|
|
23
23
|
}
|
|
24
24
|
if (Array.isArray(value)) {
|
|
25
|
-
return cloneArray(value, resetDates);
|
|
25
|
+
return cloneArray(value, resetDates, deepCloneAll);
|
|
26
26
|
}
|
|
27
27
|
if (value instanceof Date) {
|
|
28
28
|
if (resetDates) {
|
|
@@ -31,15 +31,18 @@ function cloneValue(value, resetDates) {
|
|
|
31
31
|
return new Date(value.getTime());
|
|
32
32
|
}
|
|
33
33
|
if (typeof value === 'object' && value !== null) {
|
|
34
|
+
if (deepCloneAll) {
|
|
35
|
+
return cloneNonPlainDeep(value, resetDates);
|
|
36
|
+
}
|
|
34
37
|
return cloneNonPlainShallow(value);
|
|
35
38
|
}
|
|
36
39
|
return value;
|
|
37
40
|
}
|
|
38
|
-
function cloneArray(source, resetDates) {
|
|
41
|
+
function cloneArray(source, resetDates, deepCloneAll) {
|
|
39
42
|
const len = source.length;
|
|
40
43
|
const out = new Array(len);
|
|
41
44
|
for (let i = 0; i < len; i++) {
|
|
42
|
-
out[i] = cloneValue(source[i], resetDates);
|
|
45
|
+
out[i] = cloneValue(source[i], resetDates, deepCloneAll);
|
|
43
46
|
}
|
|
44
47
|
return out;
|
|
45
48
|
}
|
|
@@ -72,4 +75,44 @@ function cloneNonPlainShallow(value) {
|
|
|
72
75
|
}
|
|
73
76
|
return out;
|
|
74
77
|
}
|
|
78
|
+
function cloneNonPlainDeep(value, resetDates) {
|
|
79
|
+
if (value instanceof RegExp) {
|
|
80
|
+
const re = new RegExp(value.source, value.flags);
|
|
81
|
+
re.lastIndex = value.lastIndex;
|
|
82
|
+
return re;
|
|
83
|
+
}
|
|
84
|
+
if (value instanceof Map) {
|
|
85
|
+
const out = new Map();
|
|
86
|
+
for (const [key, val] of value) {
|
|
87
|
+
out.set(cloneValue(key, resetDates, true), cloneValue(val, resetDates, true));
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
if (value instanceof Set) {
|
|
92
|
+
const out = new Set();
|
|
93
|
+
for (const entry of value) {
|
|
94
|
+
out.add(cloneValue(entry, resetDates, true));
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
if (ArrayBuffer.isView(value)) {
|
|
99
|
+
const anyVal = value;
|
|
100
|
+
if (typeof anyVal.slice === 'function')
|
|
101
|
+
return anyVal.slice();
|
|
102
|
+
if (value instanceof DataView) {
|
|
103
|
+
return new DataView(value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength));
|
|
104
|
+
}
|
|
105
|
+
return new anyVal.constructor(value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength));
|
|
106
|
+
}
|
|
107
|
+
if (value instanceof ArrayBuffer)
|
|
108
|
+
return value.slice(0);
|
|
109
|
+
const proto = Object.getPrototypeOf(value);
|
|
110
|
+
const out = Object.create(proto);
|
|
111
|
+
for (const key in value) {
|
|
112
|
+
if (!hop.call(value, key))
|
|
113
|
+
continue;
|
|
114
|
+
out[key] = cloneValue(value[key], resetDates, true);
|
|
115
|
+
}
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
75
118
|
export default copy;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import isPlainObject, {} from '../isPlainObject.js';
|
|
2
|
+
const hop = Object.prototype.hasOwnProperty;
|
|
2
3
|
function iterate(root, cb) {
|
|
3
4
|
if (!isPlainObject(root))
|
|
4
5
|
return;
|
|
@@ -6,25 +7,31 @@ function iterate(root, cb) {
|
|
|
6
7
|
}
|
|
7
8
|
function iterateHelper(node, path, cb) {
|
|
8
9
|
if (Array.isArray(node)) {
|
|
9
|
-
let i = 0;
|
|
10
|
-
|
|
10
|
+
for (let i = 0; i < node.length; i++) {
|
|
11
|
+
const value = node[i];
|
|
12
|
+
cb({ parent: node, key: i, value, path: copyPath(path) });
|
|
11
13
|
if (isPlainObject(value) || Array.isArray(value)) {
|
|
12
|
-
|
|
14
|
+
path.push(i);
|
|
15
|
+
iterateHelper(value, path, cb);
|
|
16
|
+
path.pop();
|
|
13
17
|
}
|
|
14
|
-
else {
|
|
15
|
-
cb({ parent: node, key, value, path });
|
|
16
|
-
}
|
|
17
|
-
i++;
|
|
18
18
|
}
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
const dict = node;
|
|
22
|
+
for (const key in dict) {
|
|
23
|
+
if (!hop.call(dict, key))
|
|
24
|
+
continue;
|
|
25
|
+
const value = dict[key];
|
|
26
|
+
cb({ parent: dict, key, value, path: copyPath(path) });
|
|
22
27
|
if (isPlainObject(value) || Array.isArray(value)) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
cb({ parent: node, key, value, path });
|
|
28
|
+
path.push(key);
|
|
29
|
+
iterateHelper(value, path, cb);
|
|
30
|
+
path.pop();
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
}
|
|
34
|
+
function copyPath(path) {
|
|
35
|
+
return path.slice();
|
|
36
|
+
}
|
|
30
37
|
export default iterate;
|
package/dist/esm/tspo.js
CHANGED
|
@@ -2,20 +2,43 @@ import isPlainObject, {} from './isPlainObject.js';
|
|
|
2
2
|
import compare from './utils/compare.js';
|
|
3
3
|
import copy from './utils/copy.js';
|
|
4
4
|
import iterate from './utils/iterate.js';
|
|
5
|
+
const hop = Object.prototype.hasOwnProperty;
|
|
5
6
|
function omit(obj, keys) {
|
|
6
|
-
const retVal = {}
|
|
7
|
+
const retVal = {};
|
|
8
|
+
const dict = obj;
|
|
9
|
+
if (Array.isArray(keys)) {
|
|
10
|
+
const set = new Set(keys);
|
|
11
|
+
for (const key in obj) {
|
|
12
|
+
if (!set.has(key)) {
|
|
13
|
+
retVal[key] = dict[key];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return retVal;
|
|
17
|
+
}
|
|
18
|
+
const omittedKey = keys;
|
|
7
19
|
for (const key in obj) {
|
|
8
|
-
if (
|
|
9
|
-
retVal[key] =
|
|
20
|
+
if (key !== omittedKey) {
|
|
21
|
+
retVal[key] = dict[key];
|
|
10
22
|
}
|
|
11
23
|
}
|
|
12
24
|
return retVal;
|
|
13
25
|
}
|
|
14
26
|
function pick(obj, keys) {
|
|
15
|
-
const retVal = {}
|
|
27
|
+
const retVal = {};
|
|
28
|
+
const dict = obj;
|
|
29
|
+
if (Array.isArray(keys)) {
|
|
30
|
+
const set = new Set(keys);
|
|
31
|
+
for (const key in obj) {
|
|
32
|
+
if (set.has(key)) {
|
|
33
|
+
retVal[key] = dict[key];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return retVal;
|
|
37
|
+
}
|
|
38
|
+
const pickedKey = keys;
|
|
16
39
|
for (const key in obj) {
|
|
17
|
-
if (
|
|
18
|
-
retVal[key] =
|
|
40
|
+
if (key === pickedKey) {
|
|
41
|
+
retVal[key] = dict[key];
|
|
19
42
|
}
|
|
20
43
|
}
|
|
21
44
|
return retVal;
|
|
@@ -61,17 +84,23 @@ function reverseIndex(obj, value) {
|
|
|
61
84
|
return retVal;
|
|
62
85
|
}
|
|
63
86
|
function safeReverseIndex(obj, value) {
|
|
64
|
-
|
|
87
|
+
let found = false;
|
|
88
|
+
let retVal;
|
|
65
89
|
for (const key in obj) {
|
|
66
90
|
if (obj[key] === value) {
|
|
67
|
-
|
|
91
|
+
if (found) {
|
|
92
|
+
throw new Error('.safeReverseIndex found 0 or more than 1 keys for value: ' +
|
|
93
|
+
String(value));
|
|
94
|
+
}
|
|
95
|
+
found = true;
|
|
96
|
+
retVal = key;
|
|
68
97
|
}
|
|
69
98
|
}
|
|
70
|
-
if (
|
|
99
|
+
if (!found) {
|
|
71
100
|
throw new Error('.safeReverseIndex found 0 or more than 1 keys for value: ' +
|
|
72
101
|
String(value));
|
|
73
102
|
}
|
|
74
|
-
return retVal
|
|
103
|
+
return retVal;
|
|
75
104
|
}
|
|
76
105
|
function isKey(obj, arg) {
|
|
77
106
|
const keyArr = Array.isArray(arg) ? arg : [arg];
|
|
@@ -82,9 +111,23 @@ function isKey(obj, arg) {
|
|
|
82
111
|
return true;
|
|
83
112
|
}
|
|
84
113
|
function isValue(obj, arg) {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
114
|
+
const dict = obj;
|
|
115
|
+
if (!Array.isArray(arg)) {
|
|
116
|
+
for (const key in obj) {
|
|
117
|
+
if (hop.call(obj, key) && sameValueZero(dict[key], arg))
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
for (const val of arg) {
|
|
123
|
+
let found = false;
|
|
124
|
+
for (const key in obj) {
|
|
125
|
+
if (hop.call(obj, key) && sameValueZero(dict[key], val)) {
|
|
126
|
+
found = true;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (!found)
|
|
88
131
|
return false;
|
|
89
132
|
}
|
|
90
133
|
return true;
|
|
@@ -99,7 +142,16 @@ function entries(obj) {
|
|
|
99
142
|
return Object.entries(obj);
|
|
100
143
|
}
|
|
101
144
|
function firstEntry(obj) {
|
|
102
|
-
|
|
145
|
+
const dict = obj;
|
|
146
|
+
for (const key in obj) {
|
|
147
|
+
if (hop.call(obj, key)) {
|
|
148
|
+
return [key, dict[key]];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
function sameValueZero(a, b) {
|
|
154
|
+
return a === b || (a !== a && b !== b);
|
|
103
155
|
}
|
|
104
156
|
function toDict(obj) {
|
|
105
157
|
if (!isPlainObject(obj)) {
|
|
@@ -7,16 +7,22 @@ function compare(a, b) {
|
|
|
7
7
|
return comparePlainObjects(a, b);
|
|
8
8
|
}
|
|
9
9
|
function comparePlainObjects(a, b) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
let aSize = 0;
|
|
11
|
+
for (const key in a) {
|
|
12
|
+
if (!hop.call(a, key))
|
|
13
|
+
continue;
|
|
14
|
+
aSize++;
|
|
14
15
|
if (!hop.call(b, key))
|
|
15
16
|
return false;
|
|
16
17
|
if (!compareValue(a[key], b[key]))
|
|
17
18
|
return false;
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
+
let bSize = 0;
|
|
21
|
+
for (const key in b) {
|
|
22
|
+
if (hop.call(b, key))
|
|
23
|
+
bSize++;
|
|
24
|
+
}
|
|
25
|
+
return aSize === bSize;
|
|
20
26
|
}
|
|
21
27
|
function compareValue(a, b) {
|
|
22
28
|
if (Object.is(a, b))
|
package/dist/esm/utils/copy.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import isPlainObject, {} from '../isPlainObject.js';
|
|
2
|
-
import {} from '../utility-types.js';
|
|
3
2
|
const hop = Object.prototype.hasOwnProperty;
|
|
4
3
|
function copy(value, options) {
|
|
5
4
|
if (!isPlainObject(value)) {
|
|
6
5
|
throw new TypeError('copy only accepts a plain-object as the root value');
|
|
7
6
|
}
|
|
8
7
|
const resetDates = options?.resetDates === true;
|
|
9
|
-
|
|
8
|
+
const deepCloneAll = options?.deepCloneAll === true;
|
|
9
|
+
return clonePlainObject(value, Object.getPrototypeOf(value), resetDates, deepCloneAll);
|
|
10
10
|
}
|
|
11
|
-
function clonePlainObject(source, proto, resetDates) {
|
|
11
|
+
function clonePlainObject(source, proto, resetDates, deepCloneAll) {
|
|
12
12
|
const out = proto === null ? Object.create(null) : {};
|
|
13
13
|
for (const key in source) {
|
|
14
14
|
if (!hop.call(source, key))
|
|
15
15
|
continue;
|
|
16
|
-
out[key] = cloneValue(source[key], resetDates);
|
|
16
|
+
out[key] = cloneValue(source[key], resetDates, deepCloneAll);
|
|
17
17
|
}
|
|
18
18
|
return out;
|
|
19
19
|
}
|
|
20
|
-
function cloneValue(value, resetDates) {
|
|
20
|
+
function cloneValue(value, resetDates, deepCloneAll) {
|
|
21
21
|
if (isPlainObject(value)) {
|
|
22
|
-
return clonePlainObject(value, Object.getPrototypeOf(value), resetDates);
|
|
22
|
+
return clonePlainObject(value, Object.getPrototypeOf(value), resetDates, deepCloneAll);
|
|
23
23
|
}
|
|
24
24
|
if (Array.isArray(value)) {
|
|
25
|
-
return cloneArray(value, resetDates);
|
|
25
|
+
return cloneArray(value, resetDates, deepCloneAll);
|
|
26
26
|
}
|
|
27
27
|
if (value instanceof Date) {
|
|
28
28
|
if (resetDates) {
|
|
@@ -31,15 +31,18 @@ function cloneValue(value, resetDates) {
|
|
|
31
31
|
return new Date(value.getTime());
|
|
32
32
|
}
|
|
33
33
|
if (typeof value === 'object' && value !== null) {
|
|
34
|
+
if (deepCloneAll) {
|
|
35
|
+
return cloneNonPlainDeep(value, resetDates);
|
|
36
|
+
}
|
|
34
37
|
return cloneNonPlainShallow(value);
|
|
35
38
|
}
|
|
36
39
|
return value;
|
|
37
40
|
}
|
|
38
|
-
function cloneArray(source, resetDates) {
|
|
41
|
+
function cloneArray(source, resetDates, deepCloneAll) {
|
|
39
42
|
const len = source.length;
|
|
40
43
|
const out = new Array(len);
|
|
41
44
|
for (let i = 0; i < len; i++) {
|
|
42
|
-
out[i] = cloneValue(source[i], resetDates);
|
|
45
|
+
out[i] = cloneValue(source[i], resetDates, deepCloneAll);
|
|
43
46
|
}
|
|
44
47
|
return out;
|
|
45
48
|
}
|
|
@@ -72,4 +75,44 @@ function cloneNonPlainShallow(value) {
|
|
|
72
75
|
}
|
|
73
76
|
return out;
|
|
74
77
|
}
|
|
78
|
+
function cloneNonPlainDeep(value, resetDates) {
|
|
79
|
+
if (value instanceof RegExp) {
|
|
80
|
+
const re = new RegExp(value.source, value.flags);
|
|
81
|
+
re.lastIndex = value.lastIndex;
|
|
82
|
+
return re;
|
|
83
|
+
}
|
|
84
|
+
if (value instanceof Map) {
|
|
85
|
+
const out = new Map();
|
|
86
|
+
for (const [key, val] of value) {
|
|
87
|
+
out.set(cloneValue(key, resetDates, true), cloneValue(val, resetDates, true));
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
if (value instanceof Set) {
|
|
92
|
+
const out = new Set();
|
|
93
|
+
for (const entry of value) {
|
|
94
|
+
out.add(cloneValue(entry, resetDates, true));
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
if (ArrayBuffer.isView(value)) {
|
|
99
|
+
const anyVal = value;
|
|
100
|
+
if (typeof anyVal.slice === 'function')
|
|
101
|
+
return anyVal.slice();
|
|
102
|
+
if (value instanceof DataView) {
|
|
103
|
+
return new DataView(value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength));
|
|
104
|
+
}
|
|
105
|
+
return new anyVal.constructor(value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength));
|
|
106
|
+
}
|
|
107
|
+
if (value instanceof ArrayBuffer)
|
|
108
|
+
return value.slice(0);
|
|
109
|
+
const proto = Object.getPrototypeOf(value);
|
|
110
|
+
const out = Object.create(proto);
|
|
111
|
+
for (const key in value) {
|
|
112
|
+
if (!hop.call(value, key))
|
|
113
|
+
continue;
|
|
114
|
+
out[key] = cloneValue(value[key], resetDates, true);
|
|
115
|
+
}
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
75
118
|
export default copy;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import isPlainObject, {} from '../isPlainObject.js';
|
|
2
|
+
const hop = Object.prototype.hasOwnProperty;
|
|
2
3
|
function iterate(root, cb) {
|
|
3
4
|
if (!isPlainObject(root))
|
|
4
5
|
return;
|
|
@@ -6,25 +7,31 @@ function iterate(root, cb) {
|
|
|
6
7
|
}
|
|
7
8
|
function iterateHelper(node, path, cb) {
|
|
8
9
|
if (Array.isArray(node)) {
|
|
9
|
-
let i = 0;
|
|
10
|
-
|
|
10
|
+
for (let i = 0; i < node.length; i++) {
|
|
11
|
+
const value = node[i];
|
|
12
|
+
cb({ parent: node, key: i, value, path: copyPath(path) });
|
|
11
13
|
if (isPlainObject(value) || Array.isArray(value)) {
|
|
12
|
-
|
|
14
|
+
path.push(i);
|
|
15
|
+
iterateHelper(value, path, cb);
|
|
16
|
+
path.pop();
|
|
13
17
|
}
|
|
14
|
-
else {
|
|
15
|
-
cb({ parent: node, key, value, path });
|
|
16
|
-
}
|
|
17
|
-
i++;
|
|
18
18
|
}
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
const dict = node;
|
|
22
|
+
for (const key in dict) {
|
|
23
|
+
if (!hop.call(dict, key))
|
|
24
|
+
continue;
|
|
25
|
+
const value = dict[key];
|
|
26
|
+
cb({ parent: dict, key, value, path: copyPath(path) });
|
|
22
27
|
if (isPlainObject(value) || Array.isArray(value)) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
cb({ parent: node, key, value, path });
|
|
28
|
+
path.push(key);
|
|
29
|
+
iterateHelper(value, path, cb);
|
|
30
|
+
path.pop();
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
}
|
|
34
|
+
function copyPath(path) {
|
|
35
|
+
return path.slice();
|
|
36
|
+
}
|
|
30
37
|
export default iterate;
|
package/dist/types/tspo.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import isPlainObject, { type Dict, type PlainObject } from './isPlainObject.js';
|
|
2
|
-
import type { DeepWiden, EntriesTuple, KeysParam, KeyTuple, KeyUnion,
|
|
2
|
+
import type { DeepWiden, EntriesTuple, Entry, KeysParam, KeyTuple, KeyUnion, OmitKeys, PickKeys, SetToNever, ValueTuple } from './utility-types.js';
|
|
3
3
|
import compare from './utils/compare.js';
|
|
4
4
|
import copy from './utils/copy.js';
|
|
5
5
|
import iterate from './utils/iterate.js';
|
|
@@ -23,12 +23,12 @@ declare function pick<T extends PlainObject, K extends KeysParam<T>>(obj: T, key
|
|
|
23
23
|
/**
|
|
24
24
|
* Merge two object together and return a new type.
|
|
25
25
|
*/
|
|
26
|
-
declare function merge<T extends PlainObject, U extends PlainObject>(a: T, b: U): CollapseType<
|
|
26
|
+
declare function merge<T extends PlainObject, U extends PlainObject>(a: T, b: U): CollapseType<Omit<T, keyof U> & U>;
|
|
27
27
|
/**
|
|
28
28
|
* Fill the missing entries in a partial, will the values from a 'defaults'
|
|
29
29
|
* object.
|
|
30
30
|
*/
|
|
31
|
-
declare function fill<const T extends object>(defaults: T, partial?: Partial<DeepWiden<T>>): CollapseType<
|
|
31
|
+
declare function fill<const T extends object>(defaults: T, partial?: Partial<DeepWiden<T>>): CollapseType<DeepWiden<T>>;
|
|
32
32
|
/**
|
|
33
33
|
* Append one object to another, modifying the reference to the original
|
|
34
34
|
* object.
|
|
@@ -81,7 +81,7 @@ declare function entries<T extends object>(obj: T): EntriesTuple<T>;
|
|
|
81
81
|
/**
|
|
82
82
|
* Get a type-safe array of the object e
|
|
83
83
|
*/
|
|
84
|
-
declare function firstEntry<T extends object
|
|
84
|
+
declare function firstEntry<T extends object>(obj: T): Entry<T>;
|
|
85
85
|
/**
|
|
86
86
|
* Check if something is a plain
|
|
87
87
|
*/
|
|
@@ -2,9 +2,9 @@ export type KeysParam<T extends object> = keyof T | (keyof T)[];
|
|
|
2
2
|
export type KeyUnion<T extends object, K extends KeysParam<T>> = K extends (keyof T)[] ? K[number] : K;
|
|
3
3
|
export type OmitKeys<T extends object, K extends KeysParam<T>> = Omit<T, KeyUnion<T, K>>;
|
|
4
4
|
export type PickKeys<T extends object, K extends KeysParam<T>> = Pick<T, KeyUnion<T, K>>;
|
|
5
|
-
export type
|
|
6
|
-
|
|
7
|
-
};
|
|
5
|
+
export type Entry<T extends object> = T extends object ? {
|
|
6
|
+
[K in keyof T]-?: [K, T[K]];
|
|
7
|
+
}[keyof T] : never;
|
|
8
8
|
export type SetToNever<T, K extends PropertyKey> = T & {
|
|
9
9
|
[P in K]: never;
|
|
10
10
|
};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { type PlainObject } from '../isPlainObject.js';
|
|
2
|
-
import { type Mutable } from '../utility-types.js';
|
|
3
2
|
type CopyOptions = {
|
|
4
3
|
resetDates?: boolean;
|
|
4
|
+
deepCloneAll?: boolean;
|
|
5
|
+
};
|
|
6
|
+
type Mutable<T> = {
|
|
7
|
+
-readonly [K in keyof T]: T[K];
|
|
5
8
|
};
|
|
6
9
|
/**
|
|
7
10
|
* Deep clones ONLY plain-objects (incl. null-prototype).
|
|
@@ -10,7 +13,8 @@ type CopyOptions = {
|
|
|
10
13
|
* - Recursion descends only into plain-objects and arrays.
|
|
11
14
|
* - Nested Date values are copied by epoch.
|
|
12
15
|
* - `resetDates` resets all nested Date values to current time.
|
|
13
|
-
* - Other nested non-plain objects are shallow-cloned.
|
|
16
|
+
* - Other nested non-plain objects are shallow-cloned by default.
|
|
17
|
+
* - `deepCloneAll` deep-clones all nested object values.
|
|
14
18
|
*/
|
|
15
19
|
declare function copy<T extends PlainObject>(value: T, options?: CopyOptions): Mutable<T>;
|
|
16
20
|
export default copy;
|
|
@@ -16,10 +16,10 @@ type IterateCb = (args: {
|
|
|
16
16
|
******************************************************************************/
|
|
17
17
|
/**
|
|
18
18
|
* Recursively walks plain-objects and arrays, and calls a callback for
|
|
19
|
-
* every key
|
|
19
|
+
* every key before descending into nested values.
|
|
20
20
|
*
|
|
21
21
|
* - Descends into a value if it is a plain-object or array.
|
|
22
|
-
* - Fires callback for every
|
|
22
|
+
* - Fires callback for every entry (including plain-objects/arrays).
|
|
23
23
|
*/
|
|
24
24
|
declare function iterate(root: unknown, cb: IterateCb): void;
|
|
25
25
|
/******************************************************************************
|