cmpstr 3.2.1 → 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/README.md +24 -18
- package/dist/CmpStr.esm.js +1904 -1211
- package/dist/CmpStr.esm.min.js +2 -3
- package/dist/CmpStr.umd.js +1924 -1236
- package/dist/CmpStr.umd.min.js +2 -3
- package/dist/cjs/CmpStr.cjs +134 -64
- package/dist/cjs/CmpStrAsync.cjs +60 -37
- package/dist/cjs/index.cjs +1 -2
- package/dist/cjs/metric/Cosine.cjs +1 -2
- package/dist/cjs/metric/DamerauLevenshtein.cjs +1 -2
- package/dist/cjs/metric/DiceSorensen.cjs +1 -2
- package/dist/cjs/metric/Hamming.cjs +5 -4
- package/dist/cjs/metric/Jaccard.cjs +1 -2
- package/dist/cjs/metric/JaroWinkler.cjs +1 -2
- package/dist/cjs/metric/LCS.cjs +1 -2
- package/dist/cjs/metric/Levenshtein.cjs +1 -2
- package/dist/cjs/metric/Metric.cjs +90 -53
- package/dist/cjs/metric/NeedlemanWunsch.cjs +1 -2
- package/dist/cjs/metric/QGram.cjs +1 -2
- package/dist/cjs/metric/SmithWaterman.cjs +1 -2
- package/dist/cjs/phonetic/Caverphone.cjs +1 -2
- package/dist/cjs/phonetic/Cologne.cjs +1 -2
- package/dist/cjs/phonetic/Metaphone.cjs +1 -2
- package/dist/cjs/phonetic/Phonetic.cjs +80 -48
- package/dist/cjs/phonetic/Soundex.cjs +1 -2
- package/dist/cjs/root.cjs +6 -3
- package/dist/cjs/utils/DeepMerge.cjs +109 -99
- package/dist/cjs/utils/DiffChecker.cjs +1 -2
- package/dist/cjs/utils/Errors.cjs +106 -0
- package/dist/cjs/utils/Filter.cjs +97 -37
- package/dist/cjs/utils/HashTable.cjs +44 -30
- package/dist/cjs/utils/Normalizer.cjs +84 -35
- package/dist/cjs/utils/OptionsValidator.cjs +211 -0
- package/dist/cjs/utils/Pool.cjs +57 -19
- package/dist/cjs/utils/Profiler.cjs +41 -28
- package/dist/cjs/utils/Registry.cjs +48 -24
- package/dist/cjs/utils/StructuredData.cjs +95 -57
- package/dist/cjs/utils/TextAnalyzer.cjs +1 -2
- package/dist/esm/CmpStr.mjs +133 -61
- package/dist/esm/CmpStrAsync.mjs +56 -33
- package/dist/esm/index.mjs +1 -2
- package/dist/esm/metric/Cosine.mjs +1 -2
- package/dist/esm/metric/DamerauLevenshtein.mjs +1 -2
- package/dist/esm/metric/DiceSorensen.mjs +1 -2
- package/dist/esm/metric/Hamming.mjs +5 -4
- package/dist/esm/metric/Jaccard.mjs +1 -2
- package/dist/esm/metric/JaroWinkler.mjs +1 -2
- package/dist/esm/metric/LCS.mjs +1 -2
- package/dist/esm/metric/Levenshtein.mjs +1 -2
- package/dist/esm/metric/Metric.mjs +92 -53
- package/dist/esm/metric/NeedlemanWunsch.mjs +1 -2
- package/dist/esm/metric/QGram.mjs +1 -2
- package/dist/esm/metric/SmithWaterman.mjs +1 -2
- package/dist/esm/phonetic/Caverphone.mjs +1 -2
- package/dist/esm/phonetic/Cologne.mjs +1 -2
- package/dist/esm/phonetic/Metaphone.mjs +1 -2
- package/dist/esm/phonetic/Phonetic.mjs +83 -48
- package/dist/esm/phonetic/Soundex.mjs +1 -2
- package/dist/esm/root.mjs +5 -4
- package/dist/esm/utils/DeepMerge.mjs +109 -95
- package/dist/esm/utils/DiffChecker.mjs +1 -2
- package/dist/esm/utils/Errors.mjs +106 -0
- package/dist/esm/utils/Filter.mjs +97 -37
- package/dist/esm/utils/HashTable.mjs +44 -30
- package/dist/esm/utils/Normalizer.mjs +84 -35
- package/dist/esm/utils/OptionsValidator.mjs +210 -0
- package/dist/esm/utils/Pool.mjs +53 -19
- package/dist/esm/utils/Profiler.mjs +41 -28
- package/dist/esm/utils/Registry.mjs +48 -24
- package/dist/esm/utils/StructuredData.mjs +95 -57
- package/dist/esm/utils/TextAnalyzer.mjs +1 -2
- package/dist/types/CmpStr.d.ts +25 -14
- package/dist/types/CmpStrAsync.d.ts +4 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/metric/Metric.d.ts +15 -14
- package/dist/types/phonetic/Phonetic.d.ts +7 -4
- package/dist/types/root.d.ts +4 -2
- package/dist/types/utils/DeepMerge.d.ts +80 -58
- package/dist/types/utils/Errors.d.ts +154 -0
- package/dist/types/utils/Filter.d.ts +8 -1
- package/dist/types/utils/HashTable.d.ts +12 -11
- package/dist/types/utils/Normalizer.d.ts +5 -1
- package/dist/types/utils/OptionsValidator.d.ts +193 -0
- package/dist/types/utils/Pool.d.ts +2 -0
- package/dist/types/utils/Profiler.d.ts +9 -28
- package/dist/types/utils/Registry.d.ts +3 -3
- package/dist/types/utils/StructuredData.d.ts +6 -1
- package/dist/types/utils/Types.d.ts +39 -1
- package/package.json +20 -11
- package/dist/CmpStr.esm.js.map +0 -1
- package/dist/CmpStr.esm.min.js.map +0 -1
- package/dist/CmpStr.umd.js.map +0 -1
- package/dist/CmpStr.umd.min.js.map +0 -1
- package/dist/cjs/CmpStr.cjs.map +0 -1
- package/dist/cjs/CmpStrAsync.cjs.map +0 -1
- package/dist/cjs/index.cjs.map +0 -1
- package/dist/cjs/metric/Cosine.cjs.map +0 -1
- package/dist/cjs/metric/DamerauLevenshtein.cjs.map +0 -1
- package/dist/cjs/metric/DiceSorensen.cjs.map +0 -1
- package/dist/cjs/metric/Hamming.cjs.map +0 -1
- package/dist/cjs/metric/Jaccard.cjs.map +0 -1
- package/dist/cjs/metric/JaroWinkler.cjs.map +0 -1
- package/dist/cjs/metric/LCS.cjs.map +0 -1
- package/dist/cjs/metric/Levenshtein.cjs.map +0 -1
- package/dist/cjs/metric/Metric.cjs.map +0 -1
- package/dist/cjs/metric/NeedlemanWunsch.cjs.map +0 -1
- package/dist/cjs/metric/QGram.cjs.map +0 -1
- package/dist/cjs/metric/SmithWaterman.cjs.map +0 -1
- package/dist/cjs/phonetic/Caverphone.cjs.map +0 -1
- package/dist/cjs/phonetic/Cologne.cjs.map +0 -1
- package/dist/cjs/phonetic/Metaphone.cjs.map +0 -1
- package/dist/cjs/phonetic/Phonetic.cjs.map +0 -1
- package/dist/cjs/phonetic/Soundex.cjs.map +0 -1
- package/dist/cjs/root.cjs.map +0 -1
- package/dist/cjs/utils/DeepMerge.cjs.map +0 -1
- package/dist/cjs/utils/DiffChecker.cjs.map +0 -1
- package/dist/cjs/utils/Filter.cjs.map +0 -1
- package/dist/cjs/utils/HashTable.cjs.map +0 -1
- package/dist/cjs/utils/Normalizer.cjs.map +0 -1
- package/dist/cjs/utils/Pool.cjs.map +0 -1
- package/dist/cjs/utils/Profiler.cjs.map +0 -1
- package/dist/cjs/utils/Registry.cjs.map +0 -1
- package/dist/cjs/utils/StructuredData.cjs.map +0 -1
- package/dist/cjs/utils/TextAnalyzer.cjs.map +0 -1
- package/dist/esm/CmpStr.mjs.map +0 -1
- package/dist/esm/CmpStrAsync.mjs.map +0 -1
- package/dist/esm/index.mjs.map +0 -1
- package/dist/esm/metric/Cosine.mjs.map +0 -1
- package/dist/esm/metric/DamerauLevenshtein.mjs.map +0 -1
- package/dist/esm/metric/DiceSorensen.mjs.map +0 -1
- package/dist/esm/metric/Hamming.mjs.map +0 -1
- package/dist/esm/metric/Jaccard.mjs.map +0 -1
- package/dist/esm/metric/JaroWinkler.mjs.map +0 -1
- package/dist/esm/metric/LCS.mjs.map +0 -1
- package/dist/esm/metric/Levenshtein.mjs.map +0 -1
- package/dist/esm/metric/Metric.mjs.map +0 -1
- package/dist/esm/metric/NeedlemanWunsch.mjs.map +0 -1
- package/dist/esm/metric/QGram.mjs.map +0 -1
- package/dist/esm/metric/SmithWaterman.mjs.map +0 -1
- package/dist/esm/phonetic/Caverphone.mjs.map +0 -1
- package/dist/esm/phonetic/Cologne.mjs.map +0 -1
- package/dist/esm/phonetic/Metaphone.mjs.map +0 -1
- package/dist/esm/phonetic/Phonetic.mjs.map +0 -1
- package/dist/esm/phonetic/Soundex.mjs.map +0 -1
- package/dist/esm/root.mjs.map +0 -1
- package/dist/esm/utils/DeepMerge.mjs.map +0 -1
- package/dist/esm/utils/DiffChecker.mjs.map +0 -1
- package/dist/esm/utils/Filter.mjs.map +0 -1
- package/dist/esm/utils/HashTable.mjs.map +0 -1
- package/dist/esm/utils/Normalizer.mjs.map +0 -1
- package/dist/esm/utils/Pool.mjs.map +0 -1
- package/dist/esm/utils/Profiler.mjs.map +0 -1
- package/dist/esm/utils/Registry.mjs.map +0 -1
- package/dist/esm/utils/StructuredData.mjs.map +0 -1
- package/dist/esm/utils/TextAnalyzer.mjs.map +0 -1
|
@@ -1,102 +1,116 @@
|
|
|
1
|
-
// CmpStr v3.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return parsed;
|
|
16
|
-
}
|
|
17
|
-
function get(t, path, fb) {
|
|
18
|
-
let o = t;
|
|
19
|
-
for (const k of parse(path)) {
|
|
20
|
-
if (o == null || !(k in o)) return fb;
|
|
21
|
-
o = o[k];
|
|
1
|
+
// CmpStr v3.3.0 build-3699f85-260318 by Paul Köhler @komed3 / MIT License
|
|
2
|
+
import { ErrorUtil } from './Errors.mjs';
|
|
3
|
+
|
|
4
|
+
class DeepMerge {
|
|
5
|
+
static BRACKET_PATTERN = /\[(\d+)]/g;
|
|
6
|
+
static PATH_CACHE = new Map();
|
|
7
|
+
static walk(obj, keys) {
|
|
8
|
+
let o = obj;
|
|
9
|
+
for (let i = 0; i < keys.length; i++) {
|
|
10
|
+
const k = keys[i];
|
|
11
|
+
if (o == null || !(k in o)) return { exists: false };
|
|
12
|
+
o = o[k];
|
|
13
|
+
}
|
|
14
|
+
return { exists: true, value: o };
|
|
22
15
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
16
|
+
static parse(p) {
|
|
17
|
+
const cached = DeepMerge.PATH_CACHE.get(p);
|
|
18
|
+
if (cached) return cached;
|
|
19
|
+
const parsed = p
|
|
20
|
+
.replace(DeepMerge.BRACKET_PATTERN, '.$1')
|
|
21
|
+
.split('.')
|
|
22
|
+
.map((s) => {
|
|
23
|
+
const n = Number(s);
|
|
24
|
+
return Number.isInteger(n) && String(n) === s ? n : s;
|
|
25
|
+
});
|
|
26
|
+
if (DeepMerge.PATH_CACHE.size > 2000) DeepMerge.PATH_CACHE.clear();
|
|
27
|
+
DeepMerge.PATH_CACHE.set(p, parsed);
|
|
28
|
+
return parsed;
|
|
30
29
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
function set(t, path, value) {
|
|
34
|
-
if (path === '') return value;
|
|
35
|
-
const keys = parse(path);
|
|
36
|
-
if (t !== undefined && (typeof t !== 'object' || t === null))
|
|
37
|
-
throw Error(`Cannot set property <${keys[0]}> of <${JSON.stringify(t)}>`);
|
|
38
|
-
const root = t ?? (typeof keys[0] === 'number' ? [] : Object.create(null));
|
|
39
|
-
let cur = root;
|
|
40
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
41
|
-
const k = keys[i];
|
|
42
|
-
let n = cur[k];
|
|
43
|
-
if (n != null && typeof n !== 'object')
|
|
44
|
-
throw Error(
|
|
45
|
-
`Cannot set property <${keys[i + 1]}> of <${JSON.stringify(n)}>`
|
|
46
|
-
);
|
|
47
|
-
if (n == null)
|
|
48
|
-
n = cur[k] = typeof keys[i + 1] === 'number' ? [] : Object.create(null);
|
|
49
|
-
cur = n;
|
|
30
|
+
static has(t, path) {
|
|
31
|
+
return DeepMerge.walk(t, DeepMerge.parse(path)).exists;
|
|
50
32
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
t
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
val,
|
|
73
|
-
mergeUndefined
|
|
33
|
+
static get(t, path, fb) {
|
|
34
|
+
const r = DeepMerge.walk(t, DeepMerge.parse(path));
|
|
35
|
+
return r.exists ? r.value : fb;
|
|
36
|
+
}
|
|
37
|
+
static set(t, path, value) {
|
|
38
|
+
if (path === '') return value;
|
|
39
|
+
const keys = DeepMerge.parse(path);
|
|
40
|
+
ErrorUtil.assert(
|
|
41
|
+
t === undefined || (typeof t === 'object' && t !== null),
|
|
42
|
+
`Cannot set property <${keys[0]}> of <${JSON.stringify(t)}>`,
|
|
43
|
+
{ path: keys[0], target: t }
|
|
44
|
+
);
|
|
45
|
+
const root = t ?? (typeof keys[0] === 'number' ? [] : Object.create(null));
|
|
46
|
+
let cur = root;
|
|
47
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
48
|
+
const k = keys[i];
|
|
49
|
+
let n = cur[k];
|
|
50
|
+
ErrorUtil.assert(
|
|
51
|
+
n == null || typeof n === 'object',
|
|
52
|
+
`Cannot set property <${keys[i + 1]}> of <${JSON.stringify(n)}>`,
|
|
53
|
+
{ path: keys.slice(0, i + 2), value: n }
|
|
74
54
|
);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
55
|
+
if (n == null)
|
|
56
|
+
n = cur[k] = typeof keys[i + 1] === 'number' ? [] : Object.create(null);
|
|
57
|
+
cur = n;
|
|
58
|
+
}
|
|
59
|
+
cur[keys[keys.length - 1]] = value;
|
|
60
|
+
return root;
|
|
61
|
+
}
|
|
62
|
+
static rmv(t, path, preserveEmpty = false) {
|
|
63
|
+
const keys = DeepMerge.parse(path);
|
|
64
|
+
const remove = (obj, i = 0) => {
|
|
65
|
+
const key = keys[i];
|
|
66
|
+
if (!obj || typeof obj !== 'object') return false;
|
|
67
|
+
if (i === keys.length - 1) return delete obj[key];
|
|
68
|
+
if (!remove(obj[key], i + 1)) return false;
|
|
69
|
+
if (!preserveEmpty) {
|
|
70
|
+
const val = obj[key];
|
|
71
|
+
let empty = true;
|
|
72
|
+
if (typeof val === 'object') {
|
|
73
|
+
if (Array.isArray(val))
|
|
74
|
+
for (let i = 0; i < val.length; i++) {
|
|
75
|
+
if (val[i] != null) {
|
|
76
|
+
empty = false;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else empty = false;
|
|
81
|
+
}
|
|
82
|
+
if (empty) delete obj[key];
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
};
|
|
86
|
+
remove(t);
|
|
87
|
+
return t;
|
|
88
|
+
}
|
|
89
|
+
static merge(
|
|
90
|
+
t = Object.create(null),
|
|
91
|
+
o = Object.create(null),
|
|
92
|
+
mergeUndefined = false
|
|
93
|
+
) {
|
|
94
|
+
const target = t ?? Object.create(null);
|
|
95
|
+
for (const k in o) {
|
|
96
|
+
const val = o[k];
|
|
97
|
+
if (!mergeUndefined && val === undefined) continue;
|
|
98
|
+
if (k === '__proto__' || k === 'constructor') continue;
|
|
99
|
+
if (val !== null && typeof val === 'object' && !Array.isArray(val)) {
|
|
100
|
+
const existing = target[k];
|
|
101
|
+
target[k] = DeepMerge.merge(
|
|
102
|
+
existing !== null &&
|
|
103
|
+
typeof existing === 'object' &&
|
|
104
|
+
!Array.isArray(existing)
|
|
105
|
+
? existing
|
|
106
|
+
: Object.create(null),
|
|
107
|
+
val,
|
|
108
|
+
mergeUndefined
|
|
109
|
+
);
|
|
110
|
+
} else target[k] = val;
|
|
94
111
|
}
|
|
95
|
-
return
|
|
96
|
-
}
|
|
97
|
-
remove(t);
|
|
98
|
-
return t;
|
|
112
|
+
return target;
|
|
113
|
+
}
|
|
99
114
|
}
|
|
100
115
|
|
|
101
|
-
export {
|
|
102
|
-
//# sourceMappingURL=DeepMerge.mjs.map
|
|
116
|
+
export { DeepMerge };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// CmpStr v3.
|
|
1
|
+
// CmpStr v3.3.0 build-3699f85-260318 by Paul Köhler @komed3 / MIT License
|
|
2
2
|
class DiffChecker {
|
|
3
3
|
a;
|
|
4
4
|
b;
|
|
@@ -295,4 +295,3 @@ class DiffChecker {
|
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
export { DiffChecker };
|
|
298
|
-
//# sourceMappingURL=DiffChecker.mjs.map
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// CmpStr v3.3.0 build-3699f85-260318 by Paul Köhler @komed3 / MIT License
|
|
2
|
+
class CmpStrError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
meta;
|
|
5
|
+
when = new Date().toISOString();
|
|
6
|
+
constructor(code, message, meta, cause) {
|
|
7
|
+
super(message, cause !== undefined ? { cause } : undefined);
|
|
8
|
+
this.name = this.constructor.name;
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.meta = meta;
|
|
11
|
+
if (typeof Error.captureStackTrace === 'function') {
|
|
12
|
+
Error.captureStackTrace(this, this.constructor);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
format(stack = false) {
|
|
16
|
+
const parts = [`${this.name} [${this.code}]`, this.message];
|
|
17
|
+
if (this.meta)
|
|
18
|
+
for (const _ in this.meta) {
|
|
19
|
+
parts.push(JSON.stringify(this.meta));
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
return (
|
|
23
|
+
parts.join(' - ') +
|
|
24
|
+
(stack && this.stack ? `\nStack Trace:\n${this.stack}` : '')
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
toString() {
|
|
28
|
+
return this.format(false);
|
|
29
|
+
}
|
|
30
|
+
toJSON(stack = false) {
|
|
31
|
+
return {
|
|
32
|
+
name: this.name,
|
|
33
|
+
code: this.code,
|
|
34
|
+
message: this.message,
|
|
35
|
+
meta: this.meta,
|
|
36
|
+
when: this.when,
|
|
37
|
+
cause:
|
|
38
|
+
this.cause instanceof Error
|
|
39
|
+
? {
|
|
40
|
+
name: this.cause.name,
|
|
41
|
+
message: this.cause.message,
|
|
42
|
+
stack: stack && this.cause.stack
|
|
43
|
+
}
|
|
44
|
+
: this.cause
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
class CmpStrValidationError extends CmpStrError {
|
|
49
|
+
constructor(message, meta, cause) {
|
|
50
|
+
super('E_VALIDATION', message, meta, cause);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
class CmpStrNotFoundError extends CmpStrError {
|
|
54
|
+
constructor(message, meta, cause) {
|
|
55
|
+
super('E_NOT_FOUND', message, meta, cause);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
class CmpStrUsageError extends CmpStrError {
|
|
59
|
+
constructor(message, meta, cause) {
|
|
60
|
+
super('E_USAGE', message, meta, cause);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
class CmpStrInternalError extends CmpStrError {
|
|
64
|
+
constructor(message, meta, cause) {
|
|
65
|
+
super('E_INTERNAL', message, meta, cause);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
class ErrorUtil {
|
|
69
|
+
static assert(condition, message, meta) {
|
|
70
|
+
if (!condition) throw new CmpStrUsageError(message, meta);
|
|
71
|
+
}
|
|
72
|
+
static rethrow(err, message, meta) {
|
|
73
|
+
if (err instanceof CmpStrError) throw err;
|
|
74
|
+
throw new CmpStrInternalError(message, meta, err);
|
|
75
|
+
}
|
|
76
|
+
static format(err) {
|
|
77
|
+
if (err instanceof CmpStrError) return err.toString();
|
|
78
|
+
if (err instanceof Error) return `${err.name}: ${err.message}`;
|
|
79
|
+
return String(err);
|
|
80
|
+
}
|
|
81
|
+
static wrap(fn, message, meta) {
|
|
82
|
+
try {
|
|
83
|
+
return fn();
|
|
84
|
+
} catch (err) {
|
|
85
|
+
if (err instanceof CmpStrError) throw err;
|
|
86
|
+
throw new CmpStrInternalError(message, meta, err);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
static async wrapAsync(fn, message, meta) {
|
|
90
|
+
try {
|
|
91
|
+
return await fn();
|
|
92
|
+
} catch (err) {
|
|
93
|
+
if (err instanceof CmpStrError) throw err;
|
|
94
|
+
throw new CmpStrInternalError(message, meta, err);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export {
|
|
100
|
+
CmpStrError,
|
|
101
|
+
CmpStrInternalError,
|
|
102
|
+
CmpStrNotFoundError,
|
|
103
|
+
CmpStrUsageError,
|
|
104
|
+
CmpStrValidationError,
|
|
105
|
+
ErrorUtil
|
|
106
|
+
};
|
|
@@ -1,47 +1,89 @@
|
|
|
1
|
-
// CmpStr v3.
|
|
1
|
+
// CmpStr v3.3.0 build-3699f85-260318 by Paul Köhler @komed3 / MIT License
|
|
2
|
+
import { ErrorUtil } from './Errors.mjs';
|
|
3
|
+
|
|
2
4
|
class Filter {
|
|
5
|
+
static IDENTITY = (s) => s;
|
|
3
6
|
static filters = new Map();
|
|
4
7
|
static pipeline = new Map();
|
|
5
|
-
static getPipeline(hook) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
static getPipeline(hook, force = false) {
|
|
9
|
+
return ErrorUtil.wrap(
|
|
10
|
+
() => {
|
|
11
|
+
if (!force) {
|
|
12
|
+
const cached = Filter.pipeline.get(hook);
|
|
13
|
+
if (cached) return cached;
|
|
14
|
+
}
|
|
15
|
+
const filter = Filter.filters.get(hook);
|
|
16
|
+
if (!filter) {
|
|
17
|
+
Filter.pipeline.set(hook, Filter.IDENTITY);
|
|
18
|
+
return Filter.IDENTITY;
|
|
19
|
+
}
|
|
20
|
+
const pipeline = [];
|
|
21
|
+
for (const f of filter.values()) if (f.active) pipeline.push(f);
|
|
22
|
+
pipeline.sort((a, b) => a.priority - b.priority);
|
|
23
|
+
const fn =
|
|
24
|
+
pipeline.length === 0
|
|
25
|
+
? Filter.IDENTITY
|
|
26
|
+
: (input) => {
|
|
27
|
+
let v = input;
|
|
28
|
+
for (let i = 0; i < pipeline.length; i++) v = pipeline[i].fn(v);
|
|
29
|
+
return v;
|
|
30
|
+
};
|
|
31
|
+
Filter.pipeline.set(hook, fn);
|
|
32
|
+
return fn;
|
|
33
|
+
},
|
|
34
|
+
`Error compiling filter pipeline for hook <${hook}>`,
|
|
35
|
+
{ hook }
|
|
36
|
+
);
|
|
17
37
|
}
|
|
18
38
|
static has(hook, id) {
|
|
19
39
|
return !!Filter.filters.get(hook)?.has(id);
|
|
20
40
|
}
|
|
21
41
|
static add(hook, id, fn, opt = {}) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
42
|
+
return ErrorUtil.wrap(
|
|
43
|
+
() => {
|
|
44
|
+
const { priority = 10, active = true, overrideable = true } = opt;
|
|
45
|
+
const filter = Filter.filters.get(hook) ?? new Map();
|
|
46
|
+
const index = filter.get(id);
|
|
47
|
+
if (index && !index.overrideable) return false;
|
|
48
|
+
if (
|
|
49
|
+
index &&
|
|
50
|
+
index.fn === fn &&
|
|
51
|
+
index.priority === priority &&
|
|
52
|
+
index.active === active
|
|
53
|
+
)
|
|
54
|
+
return true;
|
|
55
|
+
filter.set(id, { id, fn, priority, active, overrideable });
|
|
56
|
+
Filter.filters.set(hook, filter);
|
|
57
|
+
Filter.getPipeline(hook, true);
|
|
58
|
+
return true;
|
|
59
|
+
},
|
|
60
|
+
`Error adding filter <${id}> to hook <${hook}>`,
|
|
61
|
+
{ hook, id, opt }
|
|
62
|
+
);
|
|
30
63
|
}
|
|
31
64
|
static remove(hook, id) {
|
|
32
|
-
Filter.pipeline.delete(hook);
|
|
33
65
|
const filter = Filter.filters.get(hook);
|
|
34
|
-
|
|
66
|
+
if (!filter || !filter.delete(id)) return false;
|
|
67
|
+
Filter.getPipeline(hook, true);
|
|
68
|
+
return true;
|
|
35
69
|
}
|
|
36
70
|
static pause(hook, id) {
|
|
37
|
-
Filter.
|
|
38
|
-
|
|
39
|
-
|
|
71
|
+
const filter = Filter.filters.get(hook);
|
|
72
|
+
if (!filter) return false;
|
|
73
|
+
const f = filter.get(id);
|
|
74
|
+
if (!f || !f.active) return false;
|
|
75
|
+
f.active = false;
|
|
76
|
+
Filter.getPipeline(hook, true);
|
|
77
|
+
return true;
|
|
40
78
|
}
|
|
41
79
|
static resume(hook, id) {
|
|
42
|
-
Filter.
|
|
43
|
-
|
|
44
|
-
|
|
80
|
+
const filter = Filter.filters.get(hook);
|
|
81
|
+
if (!filter) return false;
|
|
82
|
+
const f = filter.get(id);
|
|
83
|
+
if (!f || f.active) return false;
|
|
84
|
+
f.active = true;
|
|
85
|
+
Filter.getPipeline(hook, true);
|
|
86
|
+
return true;
|
|
45
87
|
}
|
|
46
88
|
static list(hook, active = false) {
|
|
47
89
|
const filter = Filter.filters.get(hook);
|
|
@@ -51,17 +93,36 @@ class Filter {
|
|
|
51
93
|
return out;
|
|
52
94
|
}
|
|
53
95
|
static apply(hook, input) {
|
|
54
|
-
|
|
55
|
-
|
|
96
|
+
return ErrorUtil.wrap(
|
|
97
|
+
() => {
|
|
98
|
+
const fn = Filter.getPipeline(hook);
|
|
99
|
+
if (typeof input === 'string') return fn(input);
|
|
100
|
+
const arr = input;
|
|
101
|
+
const out = new Array(arr.length);
|
|
102
|
+
for (let i = 0; i < arr.length; i++) out[i] = fn(arr[i]);
|
|
103
|
+
return out;
|
|
104
|
+
},
|
|
105
|
+
`Error applying filters for hook <${hook}>`,
|
|
106
|
+
{ hook, input }
|
|
107
|
+
);
|
|
56
108
|
}
|
|
57
109
|
static async applyAsync(hook, input) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
110
|
+
return ErrorUtil.wrapAsync(
|
|
111
|
+
async () => {
|
|
112
|
+
const fn = Filter.getPipeline(hook);
|
|
113
|
+
if (typeof input === 'string') return Promise.resolve(fn(input));
|
|
114
|
+
const arr = input;
|
|
115
|
+
const out = new Array(arr.length);
|
|
116
|
+
for (let i = 0; i < arr.length; i++)
|
|
117
|
+
out[i] = Promise.resolve(fn(arr[i]));
|
|
118
|
+
return Promise.all(out);
|
|
119
|
+
},
|
|
120
|
+
`Error applying filters for hook <${hook}>`,
|
|
121
|
+
{ hook, input }
|
|
122
|
+
);
|
|
62
123
|
}
|
|
63
124
|
static clear(hook) {
|
|
64
|
-
Filter.
|
|
125
|
+
Filter.clearPipeline();
|
|
65
126
|
if (hook) Filter.filters.delete(hook);
|
|
66
127
|
else Filter.filters.clear();
|
|
67
128
|
}
|
|
@@ -71,4 +132,3 @@ class Filter {
|
|
|
71
132
|
}
|
|
72
133
|
|
|
73
134
|
export { Filter };
|
|
74
|
-
//# sourceMappingURL=Filter.mjs.map
|
|
@@ -1,28 +1,24 @@
|
|
|
1
|
-
// CmpStr v3.
|
|
1
|
+
// CmpStr v3.3.0 build-3699f85-260318 by Paul Köhler @komed3 / MIT License
|
|
2
2
|
class Hasher {
|
|
3
3
|
static FNV_PRIME = 0x01000193;
|
|
4
4
|
static HASH_OFFSET = 0x811c9dc5;
|
|
5
5
|
static fastFNV1a(str) {
|
|
6
6
|
const len = str.length;
|
|
7
|
+
const limit = len & -4;
|
|
7
8
|
let hash = this.HASH_OFFSET;
|
|
8
|
-
|
|
9
|
-
for (
|
|
10
|
-
const pos = i * 4;
|
|
9
|
+
let i = 0;
|
|
10
|
+
for (; i < limit; i += 4) {
|
|
11
11
|
const chunk =
|
|
12
|
-
str.charCodeAt(
|
|
13
|
-
(str.charCodeAt(
|
|
14
|
-
(str.charCodeAt(
|
|
15
|
-
(str.charCodeAt(
|
|
12
|
+
str.charCodeAt(i) |
|
|
13
|
+
(str.charCodeAt(i + 1) << 8) |
|
|
14
|
+
(str.charCodeAt(i + 2) << 16) |
|
|
15
|
+
(str.charCodeAt(i + 3) << 24);
|
|
16
16
|
hash ^= chunk;
|
|
17
17
|
hash = Math.imul(hash, this.FNV_PRIME);
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
for (let i = 0; i < remaining; i++) {
|
|
23
|
-
hash ^= str.charCodeAt(pos + i);
|
|
24
|
-
hash = Math.imul(hash, this.FNV_PRIME);
|
|
25
|
-
}
|
|
19
|
+
for (; i < len; i++) {
|
|
20
|
+
hash ^= str.charCodeAt(i);
|
|
21
|
+
hash = Math.imul(hash, this.FNV_PRIME);
|
|
26
22
|
}
|
|
27
23
|
hash ^= hash >>> 16;
|
|
28
24
|
hash *= 0x85ebca6b;
|
|
@@ -33,33 +29,51 @@ class Hasher {
|
|
|
33
29
|
}
|
|
34
30
|
}
|
|
35
31
|
class HashTable {
|
|
36
|
-
|
|
32
|
+
FIFO;
|
|
33
|
+
maxSize;
|
|
37
34
|
static MAX_LEN = 2048;
|
|
38
|
-
static TABLE_SIZE = 10_000;
|
|
39
35
|
table = new Map();
|
|
40
|
-
constructor(
|
|
41
|
-
this.
|
|
36
|
+
constructor(FIFO = true, maxSize = 10000) {
|
|
37
|
+
this.FIFO = FIFO;
|
|
38
|
+
this.maxSize = maxSize;
|
|
42
39
|
}
|
|
43
40
|
key(label, strs, sorted = false) {
|
|
44
|
-
|
|
45
|
-
const hashes =
|
|
46
|
-
|
|
41
|
+
const n = strs.length;
|
|
42
|
+
const hashes = new Array(n);
|
|
43
|
+
for (let i = 0; i < n; i++) {
|
|
44
|
+
const s = strs[i];
|
|
45
|
+
if (s.length > HashTable.MAX_LEN) return false;
|
|
46
|
+
hashes[i] = Hasher.fastFNV1a(s);
|
|
47
|
+
}
|
|
48
|
+
if (sorted) hashes.sort((a, b) => a - b);
|
|
49
|
+
let key = label;
|
|
50
|
+
for (let i = 0; i < hashes.length; i++) key += '-' + hashes[i];
|
|
51
|
+
return key;
|
|
52
|
+
}
|
|
53
|
+
has(key) {
|
|
54
|
+
return this.table.has(key);
|
|
55
|
+
}
|
|
56
|
+
get(key) {
|
|
57
|
+
return this.table.get(key);
|
|
47
58
|
}
|
|
48
|
-
has = (key) => this.table.has(key);
|
|
49
|
-
get = (key) => this.table.get(key);
|
|
50
59
|
set(key, entry, update = true) {
|
|
51
60
|
if (!update && this.table.has(key)) return false;
|
|
52
|
-
|
|
53
|
-
if (!this.
|
|
61
|
+
if (!this.table.has(key) && this.table.size >= this.maxSize) {
|
|
62
|
+
if (!this.FIFO) return false;
|
|
54
63
|
this.table.delete(this.table.keys().next().value);
|
|
55
64
|
}
|
|
56
65
|
this.table.set(key, entry);
|
|
57
66
|
return true;
|
|
58
67
|
}
|
|
59
|
-
delete
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
delete(key) {
|
|
69
|
+
return this.table.delete(key);
|
|
70
|
+
}
|
|
71
|
+
clear() {
|
|
72
|
+
this.table.clear();
|
|
73
|
+
}
|
|
74
|
+
size() {
|
|
75
|
+
return this.table.size;
|
|
76
|
+
}
|
|
62
77
|
}
|
|
63
78
|
|
|
64
79
|
export { HashTable, Hasher };
|
|
65
|
-
//# sourceMappingURL=HashTable.mjs.map
|