cmpstr 3.2.2 → 3.3.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/CmpStr.esm.js +2149 -1721
- package/dist/CmpStr.esm.min.js +2 -2
- package/dist/CmpStr.umd.js +2028 -1604
- package/dist/CmpStr.umd.min.js +2 -2
- package/dist/cjs/CmpStr.cjs +100 -51
- package/dist/cjs/CmpStrAsync.cjs +35 -18
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/metric/Cosine.cjs +1 -1
- package/dist/cjs/metric/DamerauLevenshtein.cjs +1 -1
- package/dist/cjs/metric/DiceSorensen.cjs +1 -1
- package/dist/cjs/metric/Hamming.cjs +1 -1
- package/dist/cjs/metric/Jaccard.cjs +1 -1
- package/dist/cjs/metric/JaroWinkler.cjs +1 -1
- package/dist/cjs/metric/LCS.cjs +1 -1
- package/dist/cjs/metric/Levenshtein.cjs +1 -1
- package/dist/cjs/metric/Metric.cjs +40 -22
- package/dist/cjs/metric/NeedlemanWunsch.cjs +1 -1
- package/dist/cjs/metric/QGram.cjs +1 -1
- package/dist/cjs/metric/SmithWaterman.cjs +1 -1
- package/dist/cjs/phonetic/Caverphone.cjs +1 -1
- package/dist/cjs/phonetic/Cologne.cjs +1 -1
- package/dist/cjs/phonetic/Metaphone.cjs +1 -1
- package/dist/cjs/phonetic/Phonetic.cjs +27 -15
- package/dist/cjs/phonetic/Soundex.cjs +1 -1
- package/dist/cjs/root.cjs +4 -2
- package/dist/cjs/utils/DeepMerge.cjs +102 -97
- package/dist/cjs/utils/DiffChecker.cjs +1 -1
- package/dist/cjs/utils/Errors.cjs +22 -19
- package/dist/cjs/utils/Filter.cjs +59 -24
- package/dist/cjs/utils/HashTable.cjs +44 -29
- package/dist/cjs/utils/Normalizer.cjs +57 -28
- package/dist/cjs/utils/OptionsValidator.cjs +211 -0
- package/dist/cjs/utils/Pool.cjs +27 -13
- package/dist/cjs/utils/Profiler.cjs +41 -27
- package/dist/cjs/utils/Registry.cjs +5 -5
- package/dist/cjs/utils/StructuredData.cjs +83 -53
- package/dist/cjs/utils/TextAnalyzer.cjs +1 -1
- package/dist/esm/CmpStr.mjs +101 -52
- package/dist/esm/CmpStrAsync.mjs +35 -18
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/metric/Cosine.mjs +1 -1
- package/dist/esm/metric/DamerauLevenshtein.mjs +1 -1
- package/dist/esm/metric/DiceSorensen.mjs +1 -1
- package/dist/esm/metric/Hamming.mjs +1 -1
- package/dist/esm/metric/Jaccard.mjs +1 -1
- package/dist/esm/metric/JaroWinkler.mjs +1 -1
- package/dist/esm/metric/LCS.mjs +1 -1
- package/dist/esm/metric/Levenshtein.mjs +1 -1
- package/dist/esm/metric/Metric.mjs +40 -22
- package/dist/esm/metric/NeedlemanWunsch.mjs +1 -1
- package/dist/esm/metric/QGram.mjs +1 -1
- package/dist/esm/metric/SmithWaterman.mjs +1 -1
- package/dist/esm/phonetic/Caverphone.mjs +1 -1
- package/dist/esm/phonetic/Cologne.mjs +1 -1
- package/dist/esm/phonetic/Metaphone.mjs +1 -1
- package/dist/esm/phonetic/Phonetic.mjs +30 -15
- package/dist/esm/phonetic/Soundex.mjs +1 -1
- package/dist/esm/root.mjs +3 -3
- package/dist/esm/utils/DeepMerge.mjs +103 -94
- package/dist/esm/utils/DiffChecker.mjs +1 -1
- package/dist/esm/utils/Errors.mjs +22 -19
- package/dist/esm/utils/Filter.mjs +59 -24
- package/dist/esm/utils/HashTable.mjs +44 -29
- package/dist/esm/utils/Normalizer.mjs +57 -28
- package/dist/esm/utils/OptionsValidator.mjs +210 -0
- package/dist/esm/utils/Pool.mjs +27 -13
- package/dist/esm/utils/Profiler.mjs +41 -27
- package/dist/esm/utils/Registry.mjs +5 -5
- package/dist/esm/utils/StructuredData.mjs +83 -53
- package/dist/esm/utils/TextAnalyzer.mjs +1 -1
- package/dist/types/CmpStr.d.ts +22 -15
- package/dist/types/CmpStrAsync.d.ts +3 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/metric/Metric.d.ts +9 -9
- package/dist/types/phonetic/Phonetic.d.ts +4 -3
- package/dist/types/root.d.ts +3 -2
- package/dist/types/utils/DeepMerge.d.ts +80 -58
- package/dist/types/utils/Errors.d.ts +25 -8
- package/dist/types/utils/Filter.d.ts +4 -1
- package/dist/types/utils/HashTable.d.ts +12 -11
- package/dist/types/utils/Normalizer.d.ts +2 -1
- package/dist/types/utils/OptionsValidator.d.ts +193 -0
- package/dist/types/utils/Profiler.d.ts +9 -28
- package/dist/types/utils/StructuredData.d.ts +3 -0
- package/dist/types/utils/Types.d.ts +13 -1
- package/package.json +14 -5
package/dist/cjs/metric/LCS.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// CmpStr v3.
|
|
1
|
+
// CmpStr v3.3.0 build-3699f85-260318 by Paul Köhler @komed3 / MIT License
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var Errors = require('../utils/Errors.cjs');
|
|
@@ -18,9 +18,15 @@ class Metric {
|
|
|
18
18
|
optKey;
|
|
19
19
|
symmetric;
|
|
20
20
|
results;
|
|
21
|
-
static clear
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
static clear() {
|
|
22
|
+
this.cache.clear();
|
|
23
|
+
}
|
|
24
|
+
static swap(a, b, m, n) {
|
|
25
|
+
return m > n ? [b, a, n, m] : [a, b, m, n];
|
|
26
|
+
}
|
|
27
|
+
static clamp(res) {
|
|
28
|
+
return Math.max(0, Math.min(1, res));
|
|
29
|
+
}
|
|
24
30
|
constructor(metric, a, b, opt = {}, symmetric = false) {
|
|
25
31
|
this.metric = metric;
|
|
26
32
|
this.a = Array.isArray(a) ? a : [a];
|
|
@@ -59,13 +65,13 @@ class Metric {
|
|
|
59
65
|
if (!result) {
|
|
60
66
|
result = profiler.run(() => {
|
|
61
67
|
if (this.symmetric) [A, B, m, n] = Metric.swap(A, B, m, n);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
this.optKey;
|
|
68
|
+
let key = Metric.cache.key(this.metric, [A, B], this.symmetric);
|
|
69
|
+
if (key) key += this.optKey;
|
|
65
70
|
return (
|
|
66
71
|
Metric.cache.get(key || '') ??
|
|
67
72
|
(() => {
|
|
68
|
-
const
|
|
73
|
+
const maxLen = m > n ? m : n;
|
|
74
|
+
const res = this.compute(A, B, m, n, maxLen);
|
|
69
75
|
if (key) Metric.cache.set(key, res);
|
|
70
76
|
return res;
|
|
71
77
|
})()
|
|
@@ -74,8 +80,8 @@ class Metric {
|
|
|
74
80
|
}
|
|
75
81
|
return {
|
|
76
82
|
metric: this.metric,
|
|
77
|
-
a: this.origA[i]
|
|
78
|
-
b: this.origB[j]
|
|
83
|
+
a: this.origA.length > i ? this.origA[i] : a,
|
|
84
|
+
b: this.origB.length > j ? this.origB[j] : b,
|
|
79
85
|
...result
|
|
80
86
|
};
|
|
81
87
|
},
|
|
@@ -94,11 +100,11 @@ class Metric {
|
|
|
94
100
|
this.results = results;
|
|
95
101
|
}
|
|
96
102
|
async runBatchAsync() {
|
|
97
|
-
const
|
|
103
|
+
const tasks = [];
|
|
98
104
|
for (let i = 0; i < this.a.length; i++)
|
|
99
105
|
for (let j = 0; j < this.b.length; j++)
|
|
100
|
-
|
|
101
|
-
this.results =
|
|
106
|
+
tasks.push(this.runSingleAsync(i, j));
|
|
107
|
+
this.results = await Promise.all(tasks);
|
|
102
108
|
}
|
|
103
109
|
runPairwise() {
|
|
104
110
|
const results = [];
|
|
@@ -106,18 +112,22 @@ class Metric {
|
|
|
106
112
|
this.results = results;
|
|
107
113
|
}
|
|
108
114
|
async runPairwiseAsync() {
|
|
109
|
-
const
|
|
115
|
+
const tasks = [];
|
|
110
116
|
for (let i = 0; i < this.a.length; i++)
|
|
111
|
-
|
|
112
|
-
this.results =
|
|
117
|
+
tasks.push(this.runSingleAsync(i, i));
|
|
118
|
+
this.results = await Promise.all(tasks);
|
|
113
119
|
}
|
|
114
120
|
setOriginal(a, b) {
|
|
115
121
|
if (a) this.origA = Array.isArray(a) ? a : [a];
|
|
116
122
|
if (b) this.origB = Array.isArray(b) ? b : [b];
|
|
117
123
|
return this;
|
|
118
124
|
}
|
|
119
|
-
isBatch
|
|
120
|
-
|
|
125
|
+
isBatch() {
|
|
126
|
+
return this.a.length > 1 || this.b.length > 1;
|
|
127
|
+
}
|
|
128
|
+
isSingle() {
|
|
129
|
+
return !this.isBatch();
|
|
130
|
+
}
|
|
121
131
|
isPairwise(safe = false) {
|
|
122
132
|
return this.isBatch() && this.a.length === this.b.length
|
|
123
133
|
? true
|
|
@@ -129,9 +139,15 @@ class Metric {
|
|
|
129
139
|
);
|
|
130
140
|
})();
|
|
131
141
|
}
|
|
132
|
-
isSymmetrical
|
|
133
|
-
|
|
134
|
-
|
|
142
|
+
isSymmetrical() {
|
|
143
|
+
return this.symmetric;
|
|
144
|
+
}
|
|
145
|
+
whichMode(mode) {
|
|
146
|
+
return mode ?? this.options.mode ?? 'default';
|
|
147
|
+
}
|
|
148
|
+
clear() {
|
|
149
|
+
this.results = undefined;
|
|
150
|
+
}
|
|
135
151
|
run(mode, clear = true) {
|
|
136
152
|
if (clear) this.clear();
|
|
137
153
|
switch (this.whichMode(mode)) {
|
|
@@ -176,7 +192,9 @@ class Metric {
|
|
|
176
192
|
);
|
|
177
193
|
}
|
|
178
194
|
}
|
|
179
|
-
getMetricName
|
|
195
|
+
getMetricName() {
|
|
196
|
+
return this.metric;
|
|
197
|
+
}
|
|
180
198
|
getResults() {
|
|
181
199
|
Errors.ErrorUtil.assert(
|
|
182
200
|
this.results !== undefined,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// CmpStr v3.
|
|
1
|
+
// CmpStr v3.3.0 build-3699f85-260318 by Paul Köhler @komed3 / MIT License
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var DeepMerge = require('../utils/DeepMerge.cjs');
|
|
@@ -15,7 +15,10 @@ class Phonetic {
|
|
|
15
15
|
options;
|
|
16
16
|
optKey;
|
|
17
17
|
map;
|
|
18
|
-
|
|
18
|
+
ignoreSet;
|
|
19
|
+
static clear() {
|
|
20
|
+
this.cache.clear();
|
|
21
|
+
}
|
|
19
22
|
constructor(algo, opt = {}) {
|
|
20
23
|
const defaults = this.constructor.default ?? {};
|
|
21
24
|
const mapId = opt.map ?? defaults.map;
|
|
@@ -30,8 +33,8 @@ class Phonetic {
|
|
|
30
33
|
`Requested mapping <${mapId}> is not declared`,
|
|
31
34
|
{ algo, mapId }
|
|
32
35
|
);
|
|
33
|
-
this.options = DeepMerge.merge(
|
|
34
|
-
DeepMerge.merge(defaults, map.options ?? {}),
|
|
36
|
+
this.options = DeepMerge.DeepMerge.merge(
|
|
37
|
+
DeepMerge.DeepMerge.merge(defaults, map.options ?? {}),
|
|
35
38
|
opt
|
|
36
39
|
);
|
|
37
40
|
this.optKey = HashTable.Hasher.fastFNV1a(
|
|
@@ -39,28 +42,32 @@ class Phonetic {
|
|
|
39
42
|
).toString();
|
|
40
43
|
this.algo = algo;
|
|
41
44
|
this.map = map;
|
|
45
|
+
this.ignoreSet = new Set(map.ignore ?? []);
|
|
42
46
|
}
|
|
43
47
|
applyPattern(word) {
|
|
44
48
|
const { patterns = [] } = this.map;
|
|
45
|
-
if (!patterns
|
|
49
|
+
if (!patterns.length) return word;
|
|
46
50
|
for (const { pattern, replace, all = false } of patterns) {
|
|
47
|
-
word =
|
|
51
|
+
word = all
|
|
52
|
+
? word.replaceAll(pattern, replace)
|
|
53
|
+
: word.replace(pattern, replace);
|
|
48
54
|
}
|
|
49
55
|
return word;
|
|
50
56
|
}
|
|
51
57
|
applyRules(char, i, chars, charLen) {
|
|
52
58
|
const { ruleset = [] } = this.map;
|
|
53
|
-
if (!ruleset
|
|
59
|
+
if (!ruleset.length) return undefined;
|
|
54
60
|
const prev = chars[i - 1] || '',
|
|
55
61
|
prev2 = chars[i - 2] || '';
|
|
56
62
|
const next = chars[i + 1] || '',
|
|
57
63
|
next2 = chars[i + 2] || '';
|
|
64
|
+
const str = chars.join('');
|
|
58
65
|
for (const rule of ruleset) {
|
|
59
66
|
if (rule.char && rule.char !== char) continue;
|
|
60
67
|
if (rule.position === 'start' && i !== 0) continue;
|
|
61
68
|
if (rule.position === 'middle' && (i === 0 || i === charLen - 1))
|
|
62
69
|
continue;
|
|
63
|
-
if (rule.position === 'end' && i !== charLen) continue;
|
|
70
|
+
if (rule.position === 'end' && i !== charLen - 1) continue;
|
|
64
71
|
if (rule.prev && !rule.prev.includes(prev)) continue;
|
|
65
72
|
if (rule.prevNot && rule.prevNot.includes(prev)) continue;
|
|
66
73
|
if (rule.prev2 && !rule.prev2.includes(prev2)) continue;
|
|
@@ -71,12 +78,12 @@ class Phonetic {
|
|
|
71
78
|
if (rule.next2Not && rule.next2Not.includes(next2)) continue;
|
|
72
79
|
if (
|
|
73
80
|
rule.leading &&
|
|
74
|
-
!rule.leading.includes(
|
|
81
|
+
!rule.leading.includes(str.slice(0, rule.leading.length))
|
|
75
82
|
)
|
|
76
83
|
continue;
|
|
77
84
|
if (
|
|
78
85
|
rule.trailing &&
|
|
79
|
-
!rule.trailing.includes(
|
|
86
|
+
!rule.trailing.includes(str.slice(-rule.trailing.length))
|
|
80
87
|
)
|
|
81
88
|
continue;
|
|
82
89
|
if (rule.match && !rule.match.every((c, j) => chars[i + j] === c))
|
|
@@ -86,7 +93,7 @@ class Phonetic {
|
|
|
86
93
|
return undefined;
|
|
87
94
|
}
|
|
88
95
|
encode(word) {
|
|
89
|
-
const { map = {}
|
|
96
|
+
const { map = {} } = this.map;
|
|
90
97
|
word = this.applyPattern(word);
|
|
91
98
|
const chars = this.word2Chars(word);
|
|
92
99
|
const charLen = chars.length;
|
|
@@ -94,7 +101,7 @@ class Phonetic {
|
|
|
94
101
|
lastCode = null;
|
|
95
102
|
for (let i = 0; i < charLen; i++) {
|
|
96
103
|
const char = chars[i];
|
|
97
|
-
if (
|
|
104
|
+
if (this.ignoreSet.has(char)) continue;
|
|
98
105
|
const mapped = this.mapChar(char, i, chars, charLen, lastCode, map);
|
|
99
106
|
if (mapped === undefined) continue;
|
|
100
107
|
((code += mapped), (lastCode = mapped));
|
|
@@ -113,7 +120,9 @@ class Phonetic {
|
|
|
113
120
|
? input
|
|
114
121
|
: (input + pad.repeat(length)).slice(0, length);
|
|
115
122
|
}
|
|
116
|
-
word2Chars
|
|
123
|
+
word2Chars(word) {
|
|
124
|
+
return Array.from(word.toLowerCase());
|
|
125
|
+
}
|
|
117
126
|
exitEarly(code, i) {
|
|
118
127
|
const { length = -1 } = this.options;
|
|
119
128
|
return length > 0 && code.length >= length;
|
|
@@ -126,7 +135,8 @@ class Phonetic {
|
|
|
126
135
|
() => {
|
|
127
136
|
const index = [];
|
|
128
137
|
for (const word of words) {
|
|
129
|
-
|
|
138
|
+
let key = Phonetic.cache.key(this.algo, [word]);
|
|
139
|
+
if (key) key += this.optKey;
|
|
130
140
|
const code =
|
|
131
141
|
Phonetic.cache.get(key || '') ??
|
|
132
142
|
(() => {
|
|
@@ -164,7 +174,9 @@ class Phonetic {
|
|
|
164
174
|
{ algo: this.algo, words }
|
|
165
175
|
);
|
|
166
176
|
}
|
|
167
|
-
getAlgoName
|
|
177
|
+
getAlgoName() {
|
|
178
|
+
return this.algo;
|
|
179
|
+
}
|
|
168
180
|
getIndex(input) {
|
|
169
181
|
const { delimiter = ' ' } = this.options;
|
|
170
182
|
return profiler.run(() =>
|
package/dist/cjs/root.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// CmpStr v3.
|
|
1
|
+
// CmpStr v3.3.0 build-3699f85-260318 by Paul Köhler @komed3 / MIT License
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var CmpStr = require('./CmpStr.cjs');
|
|
@@ -27,6 +27,7 @@ var DeepMerge = require('./utils/DeepMerge.cjs');
|
|
|
27
27
|
var Errors = require('./utils/Errors.cjs');
|
|
28
28
|
var Filter = require('./utils/Filter.cjs');
|
|
29
29
|
var HashTable = require('./utils/HashTable.cjs');
|
|
30
|
+
var OptionsValidator = require('./utils/OptionsValidator.cjs');
|
|
30
31
|
var Pool = require('./utils/Pool.cjs');
|
|
31
32
|
var Profiler = require('./utils/Profiler.cjs');
|
|
32
33
|
var StructuredData = require('./utils/StructuredData.cjs');
|
|
@@ -41,11 +42,12 @@ exports.MetricRegistry = Metric.MetricRegistry;
|
|
|
41
42
|
exports.Phonetic = Phonetic.Phonetic;
|
|
42
43
|
exports.PhoneticMappingRegistry = Phonetic.PhoneticMappingRegistry;
|
|
43
44
|
exports.PhoneticRegistry = Phonetic.PhoneticRegistry;
|
|
44
|
-
exports.DeepMerge = DeepMerge;
|
|
45
|
+
exports.DeepMerge = DeepMerge.DeepMerge;
|
|
45
46
|
exports.CmpStrError = Errors;
|
|
46
47
|
exports.Filter = Filter.Filter;
|
|
47
48
|
exports.HashTable = HashTable.HashTable;
|
|
48
49
|
exports.Hasher = HashTable.Hasher;
|
|
50
|
+
exports.OptionsValidator = OptionsValidator.OptionsValidator;
|
|
49
51
|
exports.Pool = Pool.Pool;
|
|
50
52
|
exports.Profiler = Profiler.Profiler;
|
|
51
53
|
exports.StructuredData = StructuredData.StructuredData;
|
|
@@ -1,113 +1,118 @@
|
|
|
1
|
-
// CmpStr v3.
|
|
1
|
+
// CmpStr v3.3.0 build-3699f85-260318 by Paul Köhler @komed3 / MIT License
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var Errors = require('./Errors.cjs');
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
});
|
|
18
|
-
PATH_CACHE.set(p, parsed);
|
|
19
|
-
return parsed;
|
|
20
|
-
}
|
|
21
|
-
function get(t, path, fb) {
|
|
22
|
-
let o = t;
|
|
23
|
-
for (const k of parse(path)) {
|
|
24
|
-
if (o == null || !(k in o)) return fb;
|
|
25
|
-
o = o[k];
|
|
6
|
+
class DeepMerge {
|
|
7
|
+
static BRACKET_PATTERN = /\[(\d+)]/g;
|
|
8
|
+
static PATH_CACHE = new Map();
|
|
9
|
+
static walk(obj, keys) {
|
|
10
|
+
let o = obj;
|
|
11
|
+
for (let i = 0; i < keys.length; i++) {
|
|
12
|
+
const k = keys[i];
|
|
13
|
+
if (o == null || !(k in o)) return { exists: false };
|
|
14
|
+
o = o[k];
|
|
15
|
+
}
|
|
16
|
+
return { exists: true, value: o };
|
|
26
17
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
18
|
+
static parse(p) {
|
|
19
|
+
const cached = DeepMerge.PATH_CACHE.get(p);
|
|
20
|
+
if (cached) return cached;
|
|
21
|
+
const parsed = p
|
|
22
|
+
.replace(DeepMerge.BRACKET_PATTERN, '.$1')
|
|
23
|
+
.split('.')
|
|
24
|
+
.map((s) => {
|
|
25
|
+
const n = Number(s);
|
|
26
|
+
return Number.isInteger(n) && String(n) === s ? n : s;
|
|
27
|
+
});
|
|
28
|
+
if (DeepMerge.PATH_CACHE.size > 2000) DeepMerge.PATH_CACHE.clear();
|
|
29
|
+
DeepMerge.PATH_CACHE.set(p, parsed);
|
|
30
|
+
return parsed;
|
|
34
31
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
static has(t, path) {
|
|
33
|
+
return DeepMerge.walk(t, DeepMerge.parse(path)).exists;
|
|
34
|
+
}
|
|
35
|
+
static get(t, path, fb) {
|
|
36
|
+
const r = DeepMerge.walk(t, DeepMerge.parse(path));
|
|
37
|
+
return r.exists ? r.value : fb;
|
|
38
|
+
}
|
|
39
|
+
static set(t, path, value) {
|
|
40
|
+
if (path === '') return value;
|
|
41
|
+
const keys = DeepMerge.parse(path);
|
|
42
|
+
Errors.ErrorUtil.assert(
|
|
43
|
+
t === undefined || (typeof t === 'object' && t !== null),
|
|
42
44
|
`Cannot set property <${keys[0]}> of <${JSON.stringify(t)}>`,
|
|
43
45
|
{ path: keys[0], target: t }
|
|
44
46
|
);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
const root = t ?? (typeof keys[0] === 'number' ? [] : Object.create(null));
|
|
48
|
+
let cur = root;
|
|
49
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
50
|
+
const k = keys[i];
|
|
51
|
+
let n = cur[k];
|
|
52
|
+
Errors.ErrorUtil.assert(
|
|
53
|
+
n == null || typeof n === 'object',
|
|
52
54
|
`Cannot set property <${keys[i + 1]}> of <${JSON.stringify(n)}>`,
|
|
53
55
|
{ path: keys.slice(0, i + 2), value: n }
|
|
54
56
|
);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
if (n == null)
|
|
58
|
+
n = cur[k] = typeof keys[i + 1] === 'number' ? [] : Object.create(null);
|
|
59
|
+
cur = n;
|
|
60
|
+
}
|
|
61
|
+
cur[keys[keys.length - 1]] = value;
|
|
62
|
+
return root;
|
|
58
63
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
64
|
+
static rmv(t, path, preserveEmpty = false) {
|
|
65
|
+
const keys = DeepMerge.parse(path);
|
|
66
|
+
const remove = (obj, i = 0) => {
|
|
67
|
+
const key = keys[i];
|
|
68
|
+
if (!obj || typeof obj !== 'object') return false;
|
|
69
|
+
if (i === keys.length - 1) return delete obj[key];
|
|
70
|
+
if (!remove(obj[key], i + 1)) return false;
|
|
71
|
+
if (!preserveEmpty) {
|
|
72
|
+
const val = obj[key];
|
|
73
|
+
let empty = true;
|
|
74
|
+
if (typeof val === 'object') {
|
|
75
|
+
if (Array.isArray(val))
|
|
76
|
+
for (let i = 0; i < val.length; i++) {
|
|
77
|
+
if (val[i] != null) {
|
|
78
|
+
empty = false;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else empty = false;
|
|
83
|
+
}
|
|
84
|
+
if (empty) delete obj[key];
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
};
|
|
88
|
+
remove(t);
|
|
89
|
+
return t;
|
|
90
|
+
}
|
|
91
|
+
static merge(
|
|
92
|
+
t = Object.create(null),
|
|
93
|
+
o = Object.create(null),
|
|
94
|
+
mergeUndefined = false
|
|
95
|
+
) {
|
|
96
|
+
const target = t ?? Object.create(null);
|
|
97
|
+
for (const k in o) {
|
|
98
|
+
const val = o[k];
|
|
99
|
+
if (!mergeUndefined && val === undefined) continue;
|
|
100
|
+
if (k === '__proto__' || k === 'constructor') continue;
|
|
101
|
+
if (val !== null && typeof val === 'object' && !Array.isArray(val)) {
|
|
102
|
+
const existing = target[k];
|
|
103
|
+
target[k] = DeepMerge.merge(
|
|
104
|
+
existing !== null &&
|
|
105
|
+
typeof existing === 'object' &&
|
|
106
|
+
!Array.isArray(existing)
|
|
107
|
+
? existing
|
|
108
|
+
: Object.create(null),
|
|
109
|
+
val,
|
|
110
|
+
mergeUndefined
|
|
111
|
+
);
|
|
112
|
+
} else target[k] = val;
|
|
102
113
|
}
|
|
103
|
-
return
|
|
104
|
-
}
|
|
105
|
-
remove(t);
|
|
106
|
-
return t;
|
|
114
|
+
return target;
|
|
115
|
+
}
|
|
107
116
|
}
|
|
108
117
|
|
|
109
|
-
exports.
|
|
110
|
-
exports.has = has;
|
|
111
|
-
exports.merge = merge;
|
|
112
|
-
exports.rmv = rmv;
|
|
113
|
-
exports.set = set;
|
|
118
|
+
exports.DeepMerge = DeepMerge;
|