@wizhut_tech/wizjs 0.1.5 → 0.2.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/.github/workflows/release.yml +59 -0
- package/__tests__/internal_exceptions.test.js +29 -0
- package/__tests__/io_files.test.js +41 -0
- package/__tests__/lang_arrays.test.js +44 -2
- package/__tests__/lang_checks.test.js +63 -2
- package/__tests__/lang_collections.test.js +90 -0
- package/__tests__/lang_flow.test.js +49 -0
- package/__tests__/lang_functools.test.js +123 -2
- package/__tests__/lang_itertools.test.js +210 -3
- package/__tests__/lang_objects.test.js +71 -0
- package/__tests__/math_numbers.test.js +40 -1
- package/__tests__/package_exports.test.js +79 -0
- package/docs/lang_arrays.md +4 -1
- package/docs/lang_checks.md +4 -0
- package/docs/lang_collections.md +24 -0
- package/docs/lang_functools.md +8 -1
- package/docs/lang_itertools.md +20 -1
- package/docs/lang_objects.md +5 -0
- package/docs/math_numbers.md +4 -1
- package/index.js +5 -1
- package/package.json +15 -2
- package/readme.md +22 -3
- package/src/io/files.js +1 -1
- package/src/lang/arrays.js +74 -3
- package/src/lang/checks.js +42 -2
- package/src/lang/collections.js +191 -0
- package/src/lang/functools.js +135 -2
- package/src/lang/itertools.js +511 -8
- package/src/lang/objects.js +123 -0
- package/src/math/numbers.js +59 -2
- package/CLAUDE.md +0 -54
package/src/lang/arrays.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
const { isNil } = require('./checks.js');
|
|
1
|
+
const { isNil, isArray } = require('./checks.js');
|
|
2
|
+
const { toInteger } = require('../math/numbers.js');
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
function compact(arr) {
|
|
@@ -42,8 +43,78 @@ function accumulate(arr, operator, initial=0) {
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
|
|
46
|
+
function unique(arr) {
|
|
47
|
+
if (isNil(arr)) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const seen = new Set();
|
|
52
|
+
const result = [];
|
|
53
|
+
|
|
54
|
+
for (let i = 0; i < arr.length; i++) {
|
|
55
|
+
const value = arr[i];
|
|
56
|
+
|
|
57
|
+
if (seen.has(value)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
seen.add(value);
|
|
62
|
+
result.push(value);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
function chunk(arr, size) {
|
|
70
|
+
if (isNil(arr)) {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const n = toInteger(size);
|
|
75
|
+
|
|
76
|
+
if (n < 1) {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const result = [];
|
|
81
|
+
|
|
82
|
+
for (let i = 0; i < arr.length; i += n) {
|
|
83
|
+
result.push(Array.prototype.slice.call(arr, i, i + n));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
function flatten(arr) {
|
|
91
|
+
if (isNil(arr)) {
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const result = [];
|
|
96
|
+
|
|
97
|
+
for (let i = 0; i < arr.length; i++) {
|
|
98
|
+
const item = arr[i];
|
|
99
|
+
|
|
100
|
+
if (isArray(item)) {
|
|
101
|
+
for (let j = 0; j < item.length; j++) {
|
|
102
|
+
result.push(item[j]);
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
result.push(item);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
|
|
45
113
|
module.exports = {
|
|
46
114
|
compact,
|
|
47
115
|
accumulate,
|
|
48
|
-
Operator
|
|
49
|
-
|
|
116
|
+
Operator,
|
|
117
|
+
unique,
|
|
118
|
+
chunk,
|
|
119
|
+
flatten
|
|
120
|
+
}
|
package/src/lang/checks.js
CHANGED
|
@@ -30,10 +30,50 @@ function isNumber(value) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
|
|
33
|
+
function isBoolean(value) {
|
|
34
|
+
return typeof value === 'boolean';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
function isFunction(value) {
|
|
39
|
+
return typeof value === 'function';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
function isInteger(value) {
|
|
44
|
+
return Number.isInteger(value);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
function isEmpty(value) {
|
|
49
|
+
if (isNil(value)) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (isString(value) || isArray(value)) {
|
|
54
|
+
return value.length === 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (value instanceof Map || value instanceof Set) {
|
|
58
|
+
return value.size === 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (isObject(value)) {
|
|
62
|
+
return Object.keys(value).length === 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
33
69
|
module.exports = {
|
|
34
70
|
isNil,
|
|
35
71
|
isArray,
|
|
36
72
|
isObject,
|
|
37
73
|
isString,
|
|
38
|
-
isNumber
|
|
39
|
-
|
|
74
|
+
isNumber,
|
|
75
|
+
isBoolean,
|
|
76
|
+
isFunction,
|
|
77
|
+
isInteger,
|
|
78
|
+
isEmpty
|
|
79
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
const { isNil, isObject, isFunction } = require('./checks.js');
|
|
2
|
+
const { toInteger } = require('../math/numbers.js');
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Counter {
|
|
6
|
+
constructor(source) {
|
|
7
|
+
this._map = new Map();
|
|
8
|
+
|
|
9
|
+
if (isNil(source)) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (source instanceof Counter) {
|
|
14
|
+
for (const [item, n] of source.entries()) {
|
|
15
|
+
this._map.set(item, n);
|
|
16
|
+
}
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (source instanceof Map) {
|
|
21
|
+
for (const [item, n] of source) {
|
|
22
|
+
this.add(item, n);
|
|
23
|
+
}
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (typeof source[Symbol.iterator] === 'function') {
|
|
28
|
+
for (const item of source) {
|
|
29
|
+
this.add(item, 1);
|
|
30
|
+
}
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (isObject(source)) {
|
|
35
|
+
const keys = Object.keys(source);
|
|
36
|
+
|
|
37
|
+
for (let i = 0; i < keys.length; i++) {
|
|
38
|
+
this.add(keys[i], source[keys[i]]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
add(item, n) {
|
|
44
|
+
const delta = n === undefined ? 1 : Number(n);
|
|
45
|
+
const next = (this._map.has(item) ? this._map.get(item) : 0) + delta;
|
|
46
|
+
this._map.set(item, next);
|
|
47
|
+
return next;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get(item) {
|
|
51
|
+
if (!this._map.has(item)) {
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return this._map.get(item);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
set(item, n) {
|
|
59
|
+
this._map.set(item, Number(n));
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
delete(item) {
|
|
64
|
+
return this._map.delete(item);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
mostCommon(n) {
|
|
68
|
+
const entries = [];
|
|
69
|
+
|
|
70
|
+
for (const pair of this._map.entries()) {
|
|
71
|
+
entries.push(pair);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
entries.sort((a, b) => b[1] - a[1]);
|
|
75
|
+
|
|
76
|
+
if (n === undefined || n === null) {
|
|
77
|
+
return entries;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const count = toInteger(n);
|
|
81
|
+
|
|
82
|
+
if (count < 1) {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return entries.slice(0, count);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
total() {
|
|
90
|
+
let sum = 0;
|
|
91
|
+
|
|
92
|
+
for (const v of this._map.values()) {
|
|
93
|
+
sum += v;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return sum;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
get size() {
|
|
100
|
+
return this._map.size;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
entries() {
|
|
104
|
+
return this._map.entries();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
keys() {
|
|
108
|
+
return this._map.keys();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
values() {
|
|
112
|
+
return this._map.values();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
*elements() {
|
|
116
|
+
for (const [item, count] of this._map) {
|
|
117
|
+
const times = count > 0 ? toInteger(count) : 0;
|
|
118
|
+
|
|
119
|
+
for (let i = 0; i < times; i++) {
|
|
120
|
+
yield item;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
[Symbol.iterator]() {
|
|
126
|
+
return this._map.keys();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class DefaultDict {
|
|
132
|
+
constructor(factory) {
|
|
133
|
+
this._factory = isFunction(factory) ? factory : null;
|
|
134
|
+
this._data = new Map();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
get(key) {
|
|
138
|
+
if (!this._data.has(key)) {
|
|
139
|
+
if (this._factory === null) {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
this._data.set(key, this._factory());
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return this._data.get(key);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
peek(key, defaultValue) {
|
|
150
|
+
if (!this._data.has(key)) {
|
|
151
|
+
return defaultValue;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return this._data.get(key);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
set(key, value) {
|
|
158
|
+
this._data.set(key, value);
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
has(key) {
|
|
163
|
+
return this._data.has(key);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
delete(key) {
|
|
167
|
+
return this._data.delete(key);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
get size() {
|
|
171
|
+
return this._data.size;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
entries() {
|
|
175
|
+
return this._data.entries();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
keys() {
|
|
179
|
+
return this._data.keys();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
values() {
|
|
183
|
+
return this._data.values();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
module.exports = {
|
|
189
|
+
Counter,
|
|
190
|
+
DefaultDict
|
|
191
|
+
};
|
package/src/lang/functools.js
CHANGED
|
@@ -1,10 +1,143 @@
|
|
|
1
1
|
|
|
2
|
+
const { isNil, isFunction } = require('./checks.js');
|
|
3
|
+
|
|
2
4
|
|
|
3
5
|
function reflexive(arg) {
|
|
4
6
|
return arg;
|
|
5
7
|
}
|
|
6
8
|
|
|
7
9
|
|
|
10
|
+
function partial(fn, ...preset) {
|
|
11
|
+
return function partiallyApplied(...rest) {
|
|
12
|
+
return fn.apply(this, preset.concat(rest));
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
function compose(...fns) {
|
|
18
|
+
if (fns.length === 0) {
|
|
19
|
+
return reflexive;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return function composed(...args) {
|
|
23
|
+
let result = fns[fns.length - 1].apply(this, args);
|
|
24
|
+
|
|
25
|
+
for (let i = fns.length - 2; i >= 0; i--) {
|
|
26
|
+
result = fns[i].call(this, result);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return result;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
function once(fn) {
|
|
35
|
+
let called = false;
|
|
36
|
+
let result;
|
|
37
|
+
|
|
38
|
+
return function onceWrapped(...args) {
|
|
39
|
+
if (called) {
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
called = true;
|
|
44
|
+
result = fn.apply(this, args);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
const MEMO_RESULT = Symbol('memoize.result');
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
function memoize(fn, resolver) {
|
|
54
|
+
const cache = new Map();
|
|
55
|
+
|
|
56
|
+
const memoized = function memoized(...args) {
|
|
57
|
+
if (resolver) {
|
|
58
|
+
const key = resolver.apply(this, args);
|
|
59
|
+
|
|
60
|
+
if (cache.has(key)) {
|
|
61
|
+
return cache.get(key);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const result = fn.apply(this, args);
|
|
65
|
+
cache.set(key, result);
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let node = cache;
|
|
70
|
+
|
|
71
|
+
for (let i = 0; i < args.length; i++) {
|
|
72
|
+
const arg = args[i];
|
|
73
|
+
|
|
74
|
+
if (!node.has(arg)) {
|
|
75
|
+
node.set(arg, new Map());
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
node = node.get(arg);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (node.has(MEMO_RESULT)) {
|
|
82
|
+
return node.get(MEMO_RESULT);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const result = fn.apply(this, args);
|
|
86
|
+
node.set(MEMO_RESULT, result);
|
|
87
|
+
return result;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
memoized.cache = cache;
|
|
91
|
+
return memoized;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
function reduce(fn, iterable, initializer) {
|
|
96
|
+
if (!isFunction(fn) || isNil(iterable) || typeof iterable[Symbol.iterator] !== 'function') {
|
|
97
|
+
if (arguments.length >= 3) {
|
|
98
|
+
return initializer;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
throw new TypeError('reduce() of empty iterable with no initial value');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const iterator = iterable[Symbol.iterator]();
|
|
105
|
+
let acc;
|
|
106
|
+
let started = arguments.length >= 3;
|
|
107
|
+
|
|
108
|
+
if (started) {
|
|
109
|
+
acc = initializer;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
while (true) {
|
|
113
|
+
const next = iterator.next();
|
|
114
|
+
|
|
115
|
+
if (next.done) {
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!started) {
|
|
120
|
+
acc = next.value;
|
|
121
|
+
started = true;
|
|
122
|
+
} else {
|
|
123
|
+
acc = fn(acc, next.value);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!started) {
|
|
128
|
+
throw new TypeError('reduce() of empty iterable with no initial value');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return acc;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
8
135
|
module.exports = {
|
|
9
|
-
reflexive
|
|
10
|
-
|
|
136
|
+
reflexive,
|
|
137
|
+
partial,
|
|
138
|
+
compose,
|
|
139
|
+
once,
|
|
140
|
+
memoize,
|
|
141
|
+
cache: memoize,
|
|
142
|
+
reduce
|
|
143
|
+
}
|