@isopodlabs/utilities 1.8.0 → 1.10.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 +346 -27
- package/dist/array.d.ts +5 -0
- package/dist/array.js +45 -4
- package/dist/async.d.ts +1 -0
- package/dist/async.js +5 -0
- package/dist/bits.js +3 -1
- package/dist/glob.d.ts +3 -3
- package/dist/glob.js +9 -8
- package/dist/index.d.ts +47 -3
- package/dist/index.js +160 -4
- package/dist/insensitive.d.ts +12 -11
- package/dist/insensitive.js +5 -4
- package/dist/iterator.d.ts +3 -0
- package/dist/iterator.js +8 -0
- package/dist/obj.d.ts +5 -0
- package/dist/obj.js +35 -0
- package/dist/string.d.ts +3 -2
- package/dist/string.js +24 -14
- package/package.json +2 -1
- package/dist/algorithm.d.ts +0 -9
- package/dist/algorithm.js +0 -54
- package/dist/object.d.ts +0 -33
- package/dist/object.js +0 -119
package/README.md
CHANGED
|
@@ -1,27 +1,346 @@
|
|
|
1
|
-
# @isopodlabs/utilities
|
|
2
|
-
[](https://www.npmjs.com/package/@isopodlabs/utilities)
|
|
3
|
-
[](https://github.com/adrianstephens/ts-utilities)
|
|
4
|
-
[](LICENSE.txt)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
##
|
|
9
|
-
If you use this package, consider [buying me a cup of tea](https://coff.ee/adrianstephens) to support future updates!
|
|
10
|
-
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
1
|
+
# @isopodlabs/utilities
|
|
2
|
+
[](https://www.npmjs.com/package/@isopodlabs/utilities)
|
|
3
|
+
[](https://github.com/adrianstephens/ts-utilities)
|
|
4
|
+
[](LICENSE.txt)
|
|
5
|
+
|
|
6
|
+
A comprehensive collection of TypeScript utilities for common programming tasks, including array/object manipulation, async operations, bit manipulation, string processing, and more.
|
|
7
|
+
|
|
8
|
+
## Support My Work
|
|
9
|
+
If you use this package, consider [buying me a cup of tea](https://coff.ee/adrianstephens) to support future updates!
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @isopodlabs/utilities
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import * as utils from '@isopodlabs/utilities';
|
|
21
|
+
import { DeferredPromise, regex } from '@isopodlabs/utilities';
|
|
22
|
+
import * as glob from '@isopodlabs/utilities/glob';
|
|
23
|
+
import * as insensitive from '@isopodlabs/utilities/insensitive';
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Core Features
|
|
27
|
+
|
|
28
|
+
### Async Utilities (`async`)
|
|
29
|
+
|
|
30
|
+
Utilities for working with async operations on iterables:
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { async } from '@isopodlabs/utilities';
|
|
34
|
+
|
|
35
|
+
// Parallel async map
|
|
36
|
+
const results = await async.map([1, 2, 3], async (n) => n * 2);
|
|
37
|
+
|
|
38
|
+
// Serial async map (one at a time)
|
|
39
|
+
const results = await async.mapSerial([1, 2, 3], async (n) => n * 2);
|
|
40
|
+
|
|
41
|
+
// Async reduce
|
|
42
|
+
const sum = await async.reduce([1, 2, 3], async (acc, n) => acc + n, 0);
|
|
43
|
+
|
|
44
|
+
// Async filter
|
|
45
|
+
const evens = await async.filter([1, 2, 3, 4], async (n) => n % 2 === 0);
|
|
46
|
+
|
|
47
|
+
// Async map object
|
|
48
|
+
const mapped = await async.mapObject(
|
|
49
|
+
{ a: 1, b: 2 },
|
|
50
|
+
async ([k, v]) => [k, v * 2]
|
|
51
|
+
);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Array Utilities (`array`)
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { array } from '@isopodlabs/utilities';
|
|
58
|
+
|
|
59
|
+
// Remove element from array
|
|
60
|
+
const arr = [1, 2, 3, 2];
|
|
61
|
+
array.remove(arr, 2); // returns true, arr is now [1, 3, 2]
|
|
62
|
+
|
|
63
|
+
// Compare arrays
|
|
64
|
+
array.compare([1, 2], [1, 3]); // returns -1
|
|
65
|
+
|
|
66
|
+
// Check equality
|
|
67
|
+
array.equal([1, 2, 3], [1, 2, 3]); // returns true
|
|
68
|
+
|
|
69
|
+
// Reverse in place
|
|
70
|
+
array.reverse(arr, 0, arr.length - 1);
|
|
71
|
+
|
|
72
|
+
// Rotate elements
|
|
73
|
+
array.rotate(arr, 0, arr.length, 1);
|
|
74
|
+
|
|
75
|
+
// Create array of instances
|
|
76
|
+
const instances = array.make(5, MyClass);
|
|
77
|
+
|
|
78
|
+
// Lazy slice generator
|
|
79
|
+
for (const item of array.lazySlice([1, 2, 3, 4, 5], 1, 4)) {
|
|
80
|
+
console.log(item);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Algorithm Utilities
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { partition, lowerBound, min, max, argmin, argmax } from '@isopodlabs/utilities';
|
|
88
|
+
|
|
89
|
+
// Partition by predicate
|
|
90
|
+
const { true: evens, false: odds } = partition([1, 2, 3, 4], n => n % 2 === 0);
|
|
91
|
+
|
|
92
|
+
// Binary search lower bound
|
|
93
|
+
const index = lowerBound([1, 2, 4, 5], 3);
|
|
94
|
+
|
|
95
|
+
// Find minimum/maximum
|
|
96
|
+
const minimum = min([3, 1, 4, 1, 5]);
|
|
97
|
+
const maximum = max([3, 1, 4, 1, 5]);
|
|
98
|
+
|
|
99
|
+
// Find index of min/max
|
|
100
|
+
const minIndex = argmin([3, 1, 4, 1, 5]);
|
|
101
|
+
const maxIndex = argmax([3, 1, 4, 1, 5]);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Iterator Utilities
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { map, filter, reduce, find, forEach } from '@isopodlabs/utilities';
|
|
108
|
+
|
|
109
|
+
// Map over any iterable
|
|
110
|
+
const doubled = map([1, 2, 3], n => n * 2);
|
|
111
|
+
|
|
112
|
+
// Filter iterable
|
|
113
|
+
const evens = filter([1, 2, 3, 4], n => n % 2 === 0);
|
|
114
|
+
|
|
115
|
+
// Reduce iterable
|
|
116
|
+
const sum = reduce([1, 2, 3], (acc, n) => acc + n, 0);
|
|
117
|
+
|
|
118
|
+
// Find first match
|
|
119
|
+
const first = find([1, 2, 3], n => n > 1); // returns 2
|
|
120
|
+
|
|
121
|
+
// ForEach with index
|
|
122
|
+
forEach([1, 2, 3], (n, i) => console.log(`${i}: ${n}`));
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Object Utilities
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { obj } from '@isopodlabs/utilities';
|
|
129
|
+
|
|
130
|
+
// Map object values
|
|
131
|
+
const doubled = obj.map({ a: 1, b: 2 }, ([k, v]) => [k, v * 2]);
|
|
132
|
+
|
|
133
|
+
// Filter object entries
|
|
134
|
+
const filtered = obj.filter({ a: 1, b: 2, c: 3 }, ([k, v]) => v > 1);
|
|
135
|
+
|
|
136
|
+
// Deep merge objects
|
|
137
|
+
const merged = obj.merge({ a: 1, b: { c: 2 } }, { b: { d: 3 } });
|
|
138
|
+
|
|
139
|
+
// Clone object with prototype
|
|
140
|
+
const copy = obj.clone(original);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
### String Utilities
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
import { replace, async_replace, splitFirstOf, splitLastOf, StringParser } from '@isopodlabs/utilities';
|
|
148
|
+
|
|
149
|
+
// Advanced replace with callback
|
|
150
|
+
const result = replace('hello world', /\w+/g, m => m[0].toUpperCase());
|
|
151
|
+
|
|
152
|
+
// Async replace
|
|
153
|
+
const result = await async_replace('hello world', /\w+/g, async m => m[0].toUpperCase());
|
|
154
|
+
|
|
155
|
+
// Split on first/last occurrence
|
|
156
|
+
const [before, after] = splitFirstOf('a.b.c', '.');
|
|
157
|
+
const [before, after] = splitLastOf('a.b.c', '.');
|
|
158
|
+
|
|
159
|
+
// String parser
|
|
160
|
+
const parser = new StringParser('hello world');
|
|
161
|
+
parser.skip('hello '); // returns true
|
|
162
|
+
parser.match(/\w+/); // returns 'world'
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Bit Manipulation (`bits`)
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { bits } from '@isopodlabs/utilities';
|
|
169
|
+
|
|
170
|
+
// Find lowest set bit index
|
|
171
|
+
const index = bits.lowestSet32(0b1010); // returns 1
|
|
172
|
+
|
|
173
|
+
// Find highest set bit index
|
|
174
|
+
const index = bits.highestSet32(0b1010); // returns 4
|
|
175
|
+
|
|
176
|
+
// Count set bits
|
|
177
|
+
const count = bits.countSet32(0b1011); // returns 3
|
|
178
|
+
|
|
179
|
+
// Find nth set bit
|
|
180
|
+
const index = bits.nthSet32(0b10101, 2); // finds 3rd set bit
|
|
181
|
+
|
|
182
|
+
// Works with BigInt too
|
|
183
|
+
const high = bits.highestSet(12345678901234567890n);
|
|
184
|
+
const count = bits.countSet(12345678901234567890n);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Glob Patterns (`glob`)
|
|
188
|
+
|
|
189
|
+
Convert glob patterns to regular expressions:
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import { glob } from '@isopodlabs/utilities';
|
|
193
|
+
|
|
194
|
+
// Parse glob to regex string
|
|
195
|
+
const pattern = glob.parse('src/**/*.ts');
|
|
196
|
+
|
|
197
|
+
// Create regex from glob
|
|
198
|
+
const re = glob.toRe('*.js');
|
|
199
|
+
|
|
200
|
+
// Multiple globs
|
|
201
|
+
const re = glob.toReMulti(['*.js', '*.ts']);
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Case-Insensitive Utilities (`insensitive`)
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
import { insensitive } from '@isopodlabs/utilities';
|
|
208
|
+
|
|
209
|
+
// Case-insensitive string
|
|
210
|
+
const str = insensitive.String('Hello');
|
|
211
|
+
str.includes('HELLO'); // true
|
|
212
|
+
|
|
213
|
+
// Case-insensitive map
|
|
214
|
+
const map = new insensitive.Map([['Key', 'value']]);
|
|
215
|
+
map.get('key'); // 'value'
|
|
216
|
+
map.get('KEY'); // 'value'
|
|
217
|
+
|
|
218
|
+
// Case-insensitive set
|
|
219
|
+
const set = new insensitive.Set(['Hello', 'World']);
|
|
220
|
+
set.has('hello'); // true
|
|
221
|
+
|
|
222
|
+
// Case-insensitive record
|
|
223
|
+
const rec = insensitive.Record({ Name: 'John' });
|
|
224
|
+
rec['name']; // 'John'
|
|
225
|
+
|
|
226
|
+
// Preserve original case
|
|
227
|
+
const rec2 = insensitive.Record2({ Name: 'John' });
|
|
228
|
+
Object.keys(rec2); // ['Name']
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Additional Utilities
|
|
232
|
+
|
|
233
|
+
#### `Lazy`
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
import { Lazy, CallCombiner, makeCache } from '@isopodlabs/utilities';
|
|
237
|
+
|
|
238
|
+
// Lazy evaluation
|
|
239
|
+
const lazy = new Lazy(() => expensiveComputation());
|
|
240
|
+
const value = lazy.value; // only computed once
|
|
241
|
+
|
|
242
|
+
// Combine rapid calls
|
|
243
|
+
const combiner = new CallCombiner(() => console.log('done'), 100);
|
|
244
|
+
combiner.trigger(); // will only call after 100ms of no triggers
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### `Simple cache`
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
import { makeCache } from '@isopodlabs/utilities';
|
|
252
|
+
|
|
253
|
+
// Simple cache
|
|
254
|
+
const cache = makeCache(key => loadExpensiveData(key));
|
|
255
|
+
const data = cache.get('mykey');
|
|
256
|
+
cache.remove('mykey');
|
|
257
|
+
cache.clear();
|
|
258
|
+
|
|
259
|
+
// Set operations
|
|
260
|
+
const united = union(new Set([1, 2]), new Set([2, 3]));
|
|
261
|
+
const [remaining, removed] = difference(new Set([1, 2, 3]), new Set([2, 4]));
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### `DeferredPromise`
|
|
265
|
+
|
|
266
|
+
A promise that can be resolved/rejected externally:
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
import { DeferredPromise } from '@isopodlabs/utilities';
|
|
270
|
+
|
|
271
|
+
const deferred = new DeferredPromise<number>();
|
|
272
|
+
deferred.then(value => console.log(value));
|
|
273
|
+
|
|
274
|
+
// Later...
|
|
275
|
+
deferred.resolve(42);
|
|
276
|
+
|
|
277
|
+
// Reset and reuse
|
|
278
|
+
deferred.reset();
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
#### Regex Template Tag
|
|
282
|
+
|
|
283
|
+
Create readable regular expressions:
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
import { regex } from '@isopodlabs/utilities';
|
|
287
|
+
|
|
288
|
+
// Multi-line regex with comments
|
|
289
|
+
const re = regex`
|
|
290
|
+
\d+ # one or more digits
|
|
291
|
+
\. # decimal point
|
|
292
|
+
\d{2} # exactly 2 digits
|
|
293
|
+
`;
|
|
294
|
+
|
|
295
|
+
// With custom flags
|
|
296
|
+
const re = regex('i')`hello|world`;
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
#### Parallel/Serial Execution
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
import { parallel, serial } from '@isopodlabs/utilities';
|
|
303
|
+
|
|
304
|
+
// Run functions in parallel
|
|
305
|
+
const results = await parallel(
|
|
306
|
+
() => fetchA(),
|
|
307
|
+
() => fetchB(),
|
|
308
|
+
() => fetchC()
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
// Run functions serially
|
|
312
|
+
const results = await serial(
|
|
313
|
+
() => fetchA(),
|
|
314
|
+
() => fetchB(),
|
|
315
|
+
() => fetchC()
|
|
316
|
+
);
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## API Reference
|
|
320
|
+
|
|
321
|
+
### Exported Namespaces
|
|
322
|
+
- `obj` - Object utilities
|
|
323
|
+
- `glob` - Glob pattern utilities
|
|
324
|
+
- `bits` - Bit manipulation utilities
|
|
325
|
+
- `array` - Array utilities
|
|
326
|
+
- `async` - Async iterator utilities
|
|
327
|
+
- `insensitive` - Case-insensitive string/collection utilities
|
|
328
|
+
|
|
329
|
+
### Exported Functions
|
|
330
|
+
- Generic: `compare`, `reverse`, `union`, `difference`
|
|
331
|
+
- Algorithm: `partition`, `lowerBound`, `min`, `max`, `argmin`, `argmax`
|
|
332
|
+
- Iterator: `map`, `filter`, `reduce`, `find`, `forEach`
|
|
333
|
+
- Object: `map`, `filter`, `merge`, `clone`,
|
|
334
|
+
- String: `replace`, `async_replace`, `splitFirstOf`, `splitLastOf`, `trim0`, `previousChar`, `tag`
|
|
335
|
+
- Execution: `parallel`, `serial`
|
|
336
|
+
- Regex: `regex`, `reDup`
|
|
337
|
+
|
|
338
|
+
### Exported Classes
|
|
339
|
+
- `DeferredPromise` - Externally resolvable promise
|
|
340
|
+
- `Lazy` - Lazy evaluation wrapper
|
|
341
|
+
- `CallCombiner` - Debounce/combine rapid calls
|
|
342
|
+
- `StringParser` - String parsing helper
|
|
343
|
+
|
|
344
|
+
## License
|
|
345
|
+
|
|
346
|
+
This project is licensed under the MIT License.
|
package/dist/array.d.ts
CHANGED
|
@@ -5,3 +5,8 @@ export declare function reverse<T>(array: T[], start: number, end: number): void
|
|
|
5
5
|
export declare function rotate<T>(array: T[], start: number, end: number, shift: number): void;
|
|
6
6
|
export declare function make<T>(n: number, constructor: new () => T): T[];
|
|
7
7
|
export declare function lazySlice<T>(array: T[], start?: number, end?: number): Generator<T>;
|
|
8
|
+
export declare function lowerBound<T>(array: T[], value: T, func?: (a: T, b: T, i: number) => boolean): number;
|
|
9
|
+
export declare function argmin<T>(array: T[], func?: (a: T, b: T) => number): number;
|
|
10
|
+
export declare function min<T>(array: T[], func?: (a: T, b: T) => number): T;
|
|
11
|
+
export declare function argmax<T>(array: T[], func?: (a: T, b: T) => number): number;
|
|
12
|
+
export declare function max<T>(array: T[], func?: (a: T, b: T) => number): T;
|
package/dist/array.js
CHANGED
|
@@ -7,7 +7,12 @@ exports.reverse = reverse;
|
|
|
7
7
|
exports.rotate = rotate;
|
|
8
8
|
exports.make = make;
|
|
9
9
|
exports.lazySlice = lazySlice;
|
|
10
|
-
|
|
10
|
+
exports.lowerBound = lowerBound;
|
|
11
|
+
exports.argmin = argmin;
|
|
12
|
+
exports.min = min;
|
|
13
|
+
exports.argmax = argmax;
|
|
14
|
+
exports.max = max;
|
|
15
|
+
const index_1 = require("./index");
|
|
11
16
|
//-----------------------------------------------------------------------------
|
|
12
17
|
// array
|
|
13
18
|
//-----------------------------------------------------------------------------
|
|
@@ -22,7 +27,7 @@ function remove(array, item) {
|
|
|
22
27
|
function compare(arr1, arr2) {
|
|
23
28
|
const length = Math.min(arr1.length, arr2.length);
|
|
24
29
|
for (let i = 0; i < length; i++) {
|
|
25
|
-
const r = (0,
|
|
30
|
+
const r = (0, index_1.compare)(arr1[i], arr2[i]);
|
|
26
31
|
if (r)
|
|
27
32
|
return r;
|
|
28
33
|
}
|
|
@@ -54,7 +59,7 @@ function rotate(array, start, end, shift) {
|
|
|
54
59
|
}
|
|
55
60
|
}
|
|
56
61
|
function make(n, constructor) {
|
|
57
|
-
return Array.from({ length: n }, () => new constructor);
|
|
62
|
+
return Array.from({ length: n }, () => new constructor());
|
|
58
63
|
}
|
|
59
64
|
function* lazySlice(array, start, end) {
|
|
60
65
|
const len = array.length;
|
|
@@ -67,9 +72,45 @@ function* lazySlice(array, start, end) {
|
|
|
67
72
|
if (end === undefined)
|
|
68
73
|
end = len;
|
|
69
74
|
else if (end < 0)
|
|
70
|
-
end = Math.max(len +
|
|
75
|
+
end = Math.max(len + end, 0);
|
|
71
76
|
else
|
|
72
77
|
end = Math.min(end, len);
|
|
73
78
|
for (let i = start; i < end; i++)
|
|
74
79
|
yield array[i];
|
|
75
80
|
}
|
|
81
|
+
function lowerBound(array, value, func = index_1.less) {
|
|
82
|
+
let i = 0;
|
|
83
|
+
for (let n = array.length; n; n >>= 1) {
|
|
84
|
+
const mid = i + (n >> 1);
|
|
85
|
+
if (func(array[mid], value, mid)) {
|
|
86
|
+
i = mid + 1;
|
|
87
|
+
--n;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return i;
|
|
91
|
+
}
|
|
92
|
+
function argmin(array, func = index_1.compare) {
|
|
93
|
+
let mini = 0;
|
|
94
|
+
for (let i = 1; i < array.length; i++) {
|
|
95
|
+
const v = func(array[i], array[mini]);
|
|
96
|
+
if (v < 0)
|
|
97
|
+
mini = i;
|
|
98
|
+
}
|
|
99
|
+
return mini;
|
|
100
|
+
}
|
|
101
|
+
function min(array, func = index_1.compare) {
|
|
102
|
+
return array[argmin(array, func)];
|
|
103
|
+
}
|
|
104
|
+
function argmax(array, func = index_1.compare) {
|
|
105
|
+
let maxi = 0;
|
|
106
|
+
for (let i = 1; i < array.length; i++) {
|
|
107
|
+
const v = func(array[i], array[maxi]);
|
|
108
|
+
if (v > 0)
|
|
109
|
+
maxi = i;
|
|
110
|
+
}
|
|
111
|
+
return maxi;
|
|
112
|
+
}
|
|
113
|
+
function max(array, func = index_1.compare) {
|
|
114
|
+
return array[argmax(array, func)];
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=array.js.map
|
package/dist/async.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare function map<T, U>(iterable: Iterable<T> | undefined, func: (v: T, i: number) => Promise<U>): Promise<U[]>;
|
|
2
|
+
export declare function mapObject<T, U>(obj: Record<string, T>, func: (x: [k: string, v: T]) => Promise<[k: string, v: U]>): Promise<Record<string, U>>;
|
|
2
3
|
export declare function mapSerial<T, U>(iterable: Iterable<T> | undefined, func: (v: T, i: number) => Promise<U>): Promise<U[]>;
|
|
3
4
|
export declare function reduce<T, U>(iterable: Iterable<T>, func: (acc: U, v: T, i: number, iterable: Iterable<T>) => Promise<U>, initialValue: U): Promise<U>;
|
|
4
5
|
export declare function filter<T>(iterable: Iterable<T>, func: (v: T) => Promise<unknown>): Promise<T[]>;
|
package/dist/async.js
CHANGED
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.map = map;
|
|
37
|
+
exports.mapObject = mapObject;
|
|
37
38
|
exports.mapSerial = mapSerial;
|
|
38
39
|
exports.reduce = reduce;
|
|
39
40
|
exports.filter = filter;
|
|
@@ -45,6 +46,9 @@ const iterator = __importStar(require("./iterator"));
|
|
|
45
46
|
async function map(iterable, func) {
|
|
46
47
|
return Promise.all(iterator.map(iterable, func));
|
|
47
48
|
}
|
|
49
|
+
async function mapObject(obj, func) {
|
|
50
|
+
return Object.fromEntries(await Promise.all(Object.entries(obj).map(x => func(x))));
|
|
51
|
+
}
|
|
48
52
|
async function mapSerial(iterable, func) {
|
|
49
53
|
const results = [];
|
|
50
54
|
let i = 0;
|
|
@@ -63,3 +67,4 @@ async function filter(iterable, func) {
|
|
|
63
67
|
const filters = await map(iterable, func);
|
|
64
68
|
return iterator.filter(iterable, (_, i) => filters[i]);
|
|
65
69
|
}
|
|
70
|
+
//# sourceMappingURL=async.js.map
|
package/dist/bits.js
CHANGED
|
@@ -249,8 +249,9 @@ function nthSet(x, i) {
|
|
|
249
249
|
return n;
|
|
250
250
|
}
|
|
251
251
|
function reverse(x) {
|
|
252
|
-
if (
|
|
252
|
+
if (x < 0x100000000)
|
|
253
253
|
return reverse32(Number(x));
|
|
254
|
+
x = BigInt(x);
|
|
254
255
|
let k = 5;
|
|
255
256
|
for (let t = x >> 32n; t;)
|
|
256
257
|
t >>= BigInt(1 << k++);
|
|
@@ -1323,3 +1324,4 @@ class SparseBits2 extends SparseBits {
|
|
|
1323
1324
|
}
|
|
1324
1325
|
exports.SparseBits2 = SparseBits2;
|
|
1325
1326
|
;
|
|
1327
|
+
//# sourceMappingURL=bits.js.map
|
package/dist/glob.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare function
|
|
1
|
+
export declare function parse(glob: string): string;
|
|
2
2
|
export declare function anchoredRe(re: string): RegExp;
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
3
|
+
export declare function toRe(glob: string): RegExp;
|
|
4
|
+
export declare function toReMulti(globs: string[]): RegExp;
|
package/dist/glob.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.parse = parse;
|
|
4
4
|
exports.anchoredRe = anchoredRe;
|
|
5
|
-
exports.
|
|
6
|
-
exports.
|
|
5
|
+
exports.toRe = toRe;
|
|
6
|
+
exports.toReMulti = toReMulti;
|
|
7
7
|
const posixClasses = {
|
|
8
8
|
alnum: '\\p{L}\\p{Nl}\\p{Nd}',
|
|
9
9
|
alpha: '\\p{L}\\p{Nl}',
|
|
@@ -23,7 +23,7 @@ const posixClasses = {
|
|
|
23
23
|
//-----------------------------------------------------------------------------
|
|
24
24
|
// Glob pattern to regex
|
|
25
25
|
//-----------------------------------------------------------------------------
|
|
26
|
-
function
|
|
26
|
+
function parse(glob) {
|
|
27
27
|
let result = '';
|
|
28
28
|
let depth = 0;
|
|
29
29
|
for (let i = 0; i < glob.length; ++i) {
|
|
@@ -104,9 +104,10 @@ function parseGlob(glob) {
|
|
|
104
104
|
function anchoredRe(re) {
|
|
105
105
|
return new RegExp(`^${re}$`);
|
|
106
106
|
}
|
|
107
|
-
function
|
|
108
|
-
return anchoredRe(
|
|
107
|
+
function toRe(glob) {
|
|
108
|
+
return anchoredRe(parse(glob));
|
|
109
109
|
}
|
|
110
|
-
function
|
|
111
|
-
return anchoredRe(globs.map(
|
|
110
|
+
function toReMulti(globs) {
|
|
111
|
+
return anchoredRe(globs.map(parse).join('|'));
|
|
112
112
|
}
|
|
113
|
+
//# sourceMappingURL=glob.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,55 @@
|
|
|
1
|
-
export * from './object';
|
|
2
1
|
export * from './iterator';
|
|
3
2
|
export * from './string';
|
|
4
|
-
export
|
|
5
|
-
export
|
|
3
|
+
export { lowerBound, argmin, min, argmax, max } from './array';
|
|
4
|
+
export { partition } from './iterator';
|
|
5
|
+
export * as obj from './obj';
|
|
6
|
+
export * as glob from './glob';
|
|
6
7
|
export * as bits from './bits';
|
|
7
8
|
export * as array from './array';
|
|
8
9
|
export * as async from './async';
|
|
9
10
|
export * as insensitive from './insensitive';
|
|
11
|
+
export declare function compare<T>(a: T, b: T): number;
|
|
12
|
+
export declare function less<T>(a: T, b: T): boolean;
|
|
13
|
+
export declare function reverse_compare<T>(a: T, b: T): number;
|
|
14
|
+
export declare function reverse<T, R>(func: (a: T, b: T) => R): (a: T, b: T) => R;
|
|
10
15
|
export declare function parallel(...fns: (() => any)[]): Promise<any[]>;
|
|
11
16
|
export declare function serial(...fns: (() => any)[]): Promise<any[]>;
|
|
17
|
+
export declare function union<T>(a: Set<T>, b: Set<T>): Set<T>;
|
|
18
|
+
export declare function difference<T>(a: Set<T>, b: Set<T>): [Set<T>, Set<T>];
|
|
19
|
+
export declare function regex(strings: TemplateStringsArray, ...args: any[]): RegExp;
|
|
20
|
+
export declare function regex(flags: string): (strings: TemplateStringsArray, ...args: any[]) => RegExp;
|
|
21
|
+
export declare function reDup(re: RegExp): RegExp;
|
|
22
|
+
export declare class DeferredPromise<T> {
|
|
23
|
+
private promise;
|
|
24
|
+
private resolver?;
|
|
25
|
+
private rejecter?;
|
|
26
|
+
constructor(t?: T);
|
|
27
|
+
resolve(value: T): void;
|
|
28
|
+
reset(): void;
|
|
29
|
+
then<T2 = void>(onfulfilled?: (t: T) => T2 | PromiseLike<T2>): Promise<T2>;
|
|
30
|
+
reject(error: any): void;
|
|
31
|
+
}
|
|
32
|
+
export declare class Lazy<T> {
|
|
33
|
+
private factory;
|
|
34
|
+
private _value;
|
|
35
|
+
constructor(factory: () => T);
|
|
36
|
+
get value(): T;
|
|
37
|
+
then<U>(this: T extends Promise<infer _R> ? Lazy<T> : never, onFulfilled: (value: T extends Promise<infer R> ? R : never) => U): Promise<U>;
|
|
38
|
+
}
|
|
39
|
+
export declare function Memoize<T>(func: () => T): () => T;
|
|
40
|
+
export declare class CallCombiner0 {
|
|
41
|
+
private timeout?;
|
|
42
|
+
combine(delay: number, func: () => void): void;
|
|
43
|
+
pending(): boolean;
|
|
44
|
+
}
|
|
45
|
+
export declare class CallCombiner extends CallCombiner0 {
|
|
46
|
+
private func;
|
|
47
|
+
private delay;
|
|
48
|
+
constructor(func: () => void, delay: number);
|
|
49
|
+
trigger(): void;
|
|
50
|
+
}
|
|
51
|
+
export declare function makeCache<T>(load: (key: string) => T): {
|
|
52
|
+
get: (key: string) => T;
|
|
53
|
+
remove: (key: string) => boolean;
|
|
54
|
+
clear: () => void;
|
|
55
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -36,22 +36,178 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
36
36
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.insensitive = exports.async = exports.array = exports.bits = void 0;
|
|
39
|
+
exports.CallCombiner = exports.CallCombiner0 = exports.Lazy = exports.DeferredPromise = exports.insensitive = exports.async = exports.array = exports.bits = exports.glob = exports.obj = exports.partition = exports.max = exports.argmax = exports.min = exports.argmin = exports.lowerBound = void 0;
|
|
40
|
+
exports.compare = compare;
|
|
41
|
+
exports.less = less;
|
|
42
|
+
exports.reverse_compare = reverse_compare;
|
|
43
|
+
exports.reverse = reverse;
|
|
40
44
|
exports.parallel = parallel;
|
|
41
45
|
exports.serial = serial;
|
|
46
|
+
exports.union = union;
|
|
47
|
+
exports.difference = difference;
|
|
48
|
+
exports.regex = regex;
|
|
49
|
+
exports.reDup = reDup;
|
|
50
|
+
exports.Memoize = Memoize;
|
|
51
|
+
exports.makeCache = makeCache;
|
|
42
52
|
const async = __importStar(require("./async"));
|
|
43
|
-
__exportStar(require("./object"), exports);
|
|
44
53
|
__exportStar(require("./iterator"), exports);
|
|
45
54
|
__exportStar(require("./string"), exports);
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
var array_1 = require("./array");
|
|
56
|
+
Object.defineProperty(exports, "lowerBound", { enumerable: true, get: function () { return array_1.lowerBound; } });
|
|
57
|
+
Object.defineProperty(exports, "argmin", { enumerable: true, get: function () { return array_1.argmin; } });
|
|
58
|
+
Object.defineProperty(exports, "min", { enumerable: true, get: function () { return array_1.min; } });
|
|
59
|
+
Object.defineProperty(exports, "argmax", { enumerable: true, get: function () { return array_1.argmax; } });
|
|
60
|
+
Object.defineProperty(exports, "max", { enumerable: true, get: function () { return array_1.max; } });
|
|
61
|
+
var iterator_1 = require("./iterator");
|
|
62
|
+
Object.defineProperty(exports, "partition", { enumerable: true, get: function () { return iterator_1.partition; } });
|
|
63
|
+
exports.obj = __importStar(require("./obj"));
|
|
64
|
+
exports.glob = __importStar(require("./glob"));
|
|
48
65
|
exports.bits = __importStar(require("./bits"));
|
|
49
66
|
exports.array = __importStar(require("./array"));
|
|
50
67
|
exports.async = __importStar(require("./async"));
|
|
51
68
|
exports.insensitive = __importStar(require("./insensitive"));
|
|
69
|
+
//-----------------------------------------------------------------------------
|
|
70
|
+
// handy generic functions
|
|
71
|
+
//-----------------------------------------------------------------------------
|
|
72
|
+
function compare(a, b) {
|
|
73
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
74
|
+
}
|
|
75
|
+
function less(a, b) {
|
|
76
|
+
return a < b;
|
|
77
|
+
}
|
|
78
|
+
function reverse_compare(a, b) {
|
|
79
|
+
return compare(b, a);
|
|
80
|
+
}
|
|
81
|
+
function reverse(func) {
|
|
82
|
+
return (a, b) => func(b, a);
|
|
83
|
+
}
|
|
52
84
|
async function parallel(...fns) {
|
|
53
85
|
return async.map(fns, f => f());
|
|
54
86
|
}
|
|
55
87
|
async function serial(...fns) {
|
|
56
88
|
return async.mapSerial(fns, f => f());
|
|
57
89
|
}
|
|
90
|
+
//-----------------------------------------------------------------------------
|
|
91
|
+
// set helpers
|
|
92
|
+
//-----------------------------------------------------------------------------
|
|
93
|
+
function union(a, b) {
|
|
94
|
+
return new Set([...a, ...b]);
|
|
95
|
+
}
|
|
96
|
+
function difference(a, b) {
|
|
97
|
+
const remaining = new Set(a);
|
|
98
|
+
const removed = new Set();
|
|
99
|
+
for (const item of b) {
|
|
100
|
+
if (remaining.delete(item))
|
|
101
|
+
removed.add(item);
|
|
102
|
+
}
|
|
103
|
+
return [remaining, removed];
|
|
104
|
+
}
|
|
105
|
+
function regex(param, ...args) {
|
|
106
|
+
const flags = typeof param === 'string' ? param : 'g';
|
|
107
|
+
if (typeof param === 'string')
|
|
108
|
+
return inner;
|
|
109
|
+
return inner(param, ...args);
|
|
110
|
+
function inner(strings, ...args) {
|
|
111
|
+
const s = strings.raw.reduce((s, str, i) => s + str + (args[i] || ''), '');
|
|
112
|
+
const lines = s.split('\n');
|
|
113
|
+
return new RegExp(lines.map(line => line.split('#')[0].trim()).join(''), flags);
|
|
114
|
+
}
|
|
115
|
+
;
|
|
116
|
+
}
|
|
117
|
+
function reDup(re) { return new RegExp(re.source, re.flags); }
|
|
118
|
+
//-----------------------------------------------------------------------------
|
|
119
|
+
// handy classes and functions
|
|
120
|
+
//-----------------------------------------------------------------------------
|
|
121
|
+
class DeferredPromise {
|
|
122
|
+
promise;
|
|
123
|
+
resolver;
|
|
124
|
+
rejecter;
|
|
125
|
+
constructor(t) {
|
|
126
|
+
this.promise = t === undefined ? new Promise((resolve, reject) => {
|
|
127
|
+
this.resolver = resolve;
|
|
128
|
+
this.rejecter = reject;
|
|
129
|
+
}) : Promise.resolve(t);
|
|
130
|
+
}
|
|
131
|
+
resolve(value) {
|
|
132
|
+
if (this.resolver) {
|
|
133
|
+
this.resolver(value);
|
|
134
|
+
this.resolver = undefined;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
reset() {
|
|
138
|
+
this.promise = new Promise((resolve, reject) => {
|
|
139
|
+
this.resolver = resolve;
|
|
140
|
+
this.rejecter = reject;
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
then(onfulfilled) {
|
|
144
|
+
return this.promise.then(onfulfilled);
|
|
145
|
+
}
|
|
146
|
+
reject(error) {
|
|
147
|
+
if (this.rejecter)
|
|
148
|
+
this.rejecter(error);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.DeferredPromise = DeferredPromise;
|
|
152
|
+
class Lazy {
|
|
153
|
+
factory;
|
|
154
|
+
_value;
|
|
155
|
+
constructor(factory) {
|
|
156
|
+
this.factory = factory;
|
|
157
|
+
}
|
|
158
|
+
get value() {
|
|
159
|
+
if (this._value === undefined)
|
|
160
|
+
this._value = this.factory();
|
|
161
|
+
return this._value;
|
|
162
|
+
}
|
|
163
|
+
// Add 'then' method only when T is a Promise
|
|
164
|
+
then(onFulfilled) {
|
|
165
|
+
return this.value.then(onFulfilled);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
exports.Lazy = Lazy;
|
|
169
|
+
function Memoize(func) {
|
|
170
|
+
const lazy = new Lazy(func);
|
|
171
|
+
return () => lazy.value;
|
|
172
|
+
}
|
|
173
|
+
class CallCombiner0 {
|
|
174
|
+
timeout;
|
|
175
|
+
combine(delay, func) {
|
|
176
|
+
if (this.timeout)
|
|
177
|
+
clearTimeout(this.timeout);
|
|
178
|
+
this.timeout = setTimeout(() => {
|
|
179
|
+
this.timeout = undefined;
|
|
180
|
+
func();
|
|
181
|
+
}, delay);
|
|
182
|
+
}
|
|
183
|
+
pending() {
|
|
184
|
+
return !!this.timeout;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
exports.CallCombiner0 = CallCombiner0;
|
|
188
|
+
class CallCombiner extends CallCombiner0 {
|
|
189
|
+
func;
|
|
190
|
+
delay;
|
|
191
|
+
constructor(func, delay) {
|
|
192
|
+
super();
|
|
193
|
+
this.func = func;
|
|
194
|
+
this.delay = delay;
|
|
195
|
+
}
|
|
196
|
+
trigger() {
|
|
197
|
+
super.combine(this.delay, this.func);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
exports.CallCombiner = CallCombiner;
|
|
201
|
+
function makeCache(load) {
|
|
202
|
+
const cache = {};
|
|
203
|
+
return {
|
|
204
|
+
get: (key) => {
|
|
205
|
+
if (!cache[key])
|
|
206
|
+
cache[key] = load(key);
|
|
207
|
+
return cache[key];
|
|
208
|
+
},
|
|
209
|
+
remove: (key) => delete cache[key],
|
|
210
|
+
clear: () => Object.keys(cache).forEach(k => delete cache[k]),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=index.js.map
|
package/dist/insensitive.d.ts
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
type string2 = string | istring;
|
|
2
|
+
declare class istring {
|
|
2
3
|
private value;
|
|
3
4
|
constructor(value: string);
|
|
4
5
|
get length(): number;
|
|
5
6
|
toString(): string;
|
|
6
7
|
toUpperCase(): string;
|
|
7
8
|
toLowerCase(): string;
|
|
8
|
-
includes(searchString:
|
|
9
|
-
startsWith(searchString:
|
|
10
|
-
endsWith(searchString:
|
|
11
|
-
indexOf(searchString:
|
|
12
|
-
lastIndexOf(searchString:
|
|
13
|
-
compare(other:
|
|
9
|
+
includes(searchString: string2, position?: number): boolean;
|
|
10
|
+
startsWith(searchString: string2, position?: number): boolean;
|
|
11
|
+
endsWith(searchString: string2, position?: number): boolean;
|
|
12
|
+
indexOf(searchString: string2, position?: number): number;
|
|
13
|
+
lastIndexOf(searchString: string2, position?: number): number;
|
|
14
|
+
compare(other: string2): 0 | 1 | -1;
|
|
14
15
|
}
|
|
15
|
-
declare class
|
|
16
|
+
declare class istring2 extends istring {
|
|
16
17
|
private orig;
|
|
17
18
|
constructor(orig: string);
|
|
18
19
|
toString(): string;
|
|
19
20
|
}
|
|
20
|
-
export declare function String(value: string):
|
|
21
|
-
export declare function String2(value: string):
|
|
22
|
-
export declare function compare(a:
|
|
21
|
+
export declare function String(value: string): istring;
|
|
22
|
+
export declare function String2(value: string): istring2;
|
|
23
|
+
export declare function compare(a: string2, b: string2): 0 | 1 | -1;
|
|
23
24
|
export declare function Record<T>(obj: Record<string, T>): Record<string, T>;
|
|
24
25
|
export declare function Record2<T>(obj: Record<string, T>): Record<string, T>;
|
|
25
26
|
export declare class Map<T> extends globalThis.Map<string, T> {
|
package/dist/insensitive.js
CHANGED
|
@@ -6,7 +6,7 @@ exports.String2 = String2;
|
|
|
6
6
|
exports.compare = compare;
|
|
7
7
|
exports.Record = Record;
|
|
8
8
|
exports.Record2 = Record2;
|
|
9
|
-
class
|
|
9
|
+
class istring {
|
|
10
10
|
value;
|
|
11
11
|
constructor(value) { this.value = value.toUpperCase(); }
|
|
12
12
|
get length() { return this.value.length; }
|
|
@@ -21,7 +21,7 @@ class CaseInsensitiveString {
|
|
|
21
21
|
compare(other) { const bi = other.toUpperCase(); return this.value < bi ? -1 : this.value > bi ? 1 : 0; }
|
|
22
22
|
}
|
|
23
23
|
// keeps original string
|
|
24
|
-
class
|
|
24
|
+
class istring2 extends istring {
|
|
25
25
|
orig;
|
|
26
26
|
constructor(orig) {
|
|
27
27
|
super(orig);
|
|
@@ -30,10 +30,10 @@ class CaseInsensitiveString2 extends CaseInsensitiveString {
|
|
|
30
30
|
toString() { return this.orig; }
|
|
31
31
|
}
|
|
32
32
|
function String(value) {
|
|
33
|
-
return new
|
|
33
|
+
return new istring(value);
|
|
34
34
|
}
|
|
35
35
|
function String2(value) {
|
|
36
|
-
return new
|
|
36
|
+
return new istring2(value);
|
|
37
37
|
}
|
|
38
38
|
function compare(a, b) {
|
|
39
39
|
const ai = a.toUpperCase(), bi = b.toUpperCase();
|
|
@@ -77,3 +77,4 @@ class Set extends globalThis.Set {
|
|
|
77
77
|
has(value) { return super.has(value.toUpperCase()); }
|
|
78
78
|
}
|
|
79
79
|
exports.Set = Set;
|
|
80
|
+
//# sourceMappingURL=insensitive.js.map
|
package/dist/iterator.d.ts
CHANGED
|
@@ -5,3 +5,6 @@ export declare function find<T>(iterable: Iterable<T> | undefined, func: (v: T)
|
|
|
5
5
|
export declare function map<T, U>(iterable: Iterable<T> | undefined, func: (v: T, i: number) => U): U[];
|
|
6
6
|
export declare function reduce<T, U>(iterable: Iterable<T>, func: (acc: U, v: T, i: number, iterable: Iterable<T>) => U, initialValue: U): U;
|
|
7
7
|
export declare function filter<T>(iterable: Iterable<T>, func: (v: T, i: number) => unknown): T[];
|
|
8
|
+
type PartitionIndex<U> = U extends boolean ? 'true' | 'false' : U;
|
|
9
|
+
export declare function partition<T, U extends keyof any | boolean>(array: Iterable<T>, func: (v: T) => U): Record<PartitionIndex<U>, T[]>;
|
|
10
|
+
export {};
|
package/dist/iterator.js
CHANGED
|
@@ -39,6 +39,7 @@ exports.find = find;
|
|
|
39
39
|
exports.map = map;
|
|
40
40
|
exports.reduce = reduce;
|
|
41
41
|
exports.filter = filter;
|
|
42
|
+
exports.partition = partition;
|
|
42
43
|
const array = __importStar(require("./array"));
|
|
43
44
|
function remove(iterable, item) {
|
|
44
45
|
return array.remove(Array.from(iterable), item);
|
|
@@ -76,3 +77,10 @@ function filter(iterable, func) {
|
|
|
76
77
|
array.push(v);
|
|
77
78
|
return array;
|
|
78
79
|
}
|
|
80
|
+
function partition(array, func) {
|
|
81
|
+
const partitions = {};
|
|
82
|
+
for (const i of array)
|
|
83
|
+
(partitions[func(i)] ??= []).push(i);
|
|
84
|
+
return partitions;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=iterator.js.map
|
package/dist/obj.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function map<T, U>(obj: Record<string, T>, func: (x: [k: string, v: T]) => [k: string, v: U]): Record<string, U>;
|
|
2
|
+
export declare function filter<T>(obj: Record<string, T>, func: (x: [k: string, v: T]) => boolean): Record<string, T>;
|
|
3
|
+
export declare function merge(...list: Record<string, any>[]): Record<string, any>;
|
|
4
|
+
export declare function isEmpty(obj: object): boolean;
|
|
5
|
+
export declare function clone<T extends object>(obj: T): T;
|
package/dist/obj.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.map = map;
|
|
4
|
+
exports.filter = filter;
|
|
5
|
+
exports.merge = merge;
|
|
6
|
+
exports.isEmpty = isEmpty;
|
|
7
|
+
exports.clone = clone;
|
|
8
|
+
function map(obj, func) {
|
|
9
|
+
return Object.fromEntries(Object.entries(obj).map(x => func(x)));
|
|
10
|
+
}
|
|
11
|
+
function filter(obj, func) {
|
|
12
|
+
return Object.fromEntries(Object.entries(obj).filter(x => func(x)));
|
|
13
|
+
}
|
|
14
|
+
function merge(...list) {
|
|
15
|
+
function isObject(value) {
|
|
16
|
+
return typeof value === 'object' && value !== null;
|
|
17
|
+
}
|
|
18
|
+
function recurse(target, source) {
|
|
19
|
+
for (const key in source) {
|
|
20
|
+
if (isObject(source[key]) && isObject(target[key]))
|
|
21
|
+
recurse(target[key], source[key]);
|
|
22
|
+
else
|
|
23
|
+
target[key] = source[key];
|
|
24
|
+
}
|
|
25
|
+
return target;
|
|
26
|
+
}
|
|
27
|
+
return list.reduce((merged, r) => recurse(merged, r), {});
|
|
28
|
+
}
|
|
29
|
+
function isEmpty(obj) {
|
|
30
|
+
return Object.keys(obj).length === 0;
|
|
31
|
+
}
|
|
32
|
+
function clone(obj) {
|
|
33
|
+
return Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=obj.js.map
|
package/dist/string.d.ts
CHANGED
|
@@ -2,12 +2,13 @@ export declare function firstOf(value: string, find: string): number;
|
|
|
2
2
|
export declare function lastOf(value: string, find: string): number;
|
|
3
3
|
export declare function splitFirstOf(value: string, find: string): (string | undefined)[];
|
|
4
4
|
export declare function splitLastOf(value: string, find: string): (string | undefined)[];
|
|
5
|
+
export declare function splitEvery(s: string, n: number): string[];
|
|
5
6
|
export declare function trim0(value: string): string;
|
|
6
7
|
export declare function replace(value: string, re: RegExp, process: (match: RegExpExecArray) => string): string;
|
|
7
8
|
export declare function async_replace(value: string, re: RegExp, process: (match: RegExpExecArray) => Promise<string>): Promise<string>;
|
|
9
|
+
export declare function async_replace_async(value: string, re: RegExp, process: (match: RegExpExecArray) => Promise<string>): Promise<string>;
|
|
8
10
|
export declare function replace_back(value: string, re: RegExp, process: (match: RegExpExecArray, right: string) => string): string;
|
|
9
11
|
export declare function async_replace_back(value: string, re: RegExp, process: (match: RegExpExecArray, right: string) => Promise<string>): Promise<string>;
|
|
10
|
-
export declare function splitEvery(s: string, n: number): string[];
|
|
11
12
|
export declare function tag(strings: TemplateStringsArray, ...keys: any[]): (...values: any[]) => string;
|
|
12
13
|
export declare function previousChar(str: string, pos: number): string;
|
|
13
14
|
export declare function hasCustomToString(value: any): boolean;
|
|
@@ -23,6 +24,6 @@ export declare class StringParser {
|
|
|
23
24
|
get(n: number): string;
|
|
24
25
|
skip(c: string): boolean;
|
|
25
26
|
expect(c: string): void;
|
|
26
|
-
match(re: RegExp): string | undefined;
|
|
27
27
|
exec(re: RegExp): RegExpExecArray | undefined;
|
|
28
|
+
match(re: RegExp): string | undefined;
|
|
28
29
|
}
|
package/dist/string.js
CHANGED
|
@@ -8,12 +8,13 @@ exports.firstOf = firstOf;
|
|
|
8
8
|
exports.lastOf = lastOf;
|
|
9
9
|
exports.splitFirstOf = splitFirstOf;
|
|
10
10
|
exports.splitLastOf = splitLastOf;
|
|
11
|
+
exports.splitEvery = splitEvery;
|
|
11
12
|
exports.trim0 = trim0;
|
|
12
13
|
exports.replace = replace;
|
|
13
14
|
exports.async_replace = async_replace;
|
|
15
|
+
exports.async_replace_async = async_replace_async;
|
|
14
16
|
exports.replace_back = replace_back;
|
|
15
17
|
exports.async_replace_back = async_replace_back;
|
|
16
|
-
exports.splitEvery = splitEvery;
|
|
17
18
|
exports.tag = tag;
|
|
18
19
|
exports.previousChar = previousChar;
|
|
19
20
|
exports.hasCustomToString = hasCustomToString;
|
|
@@ -40,6 +41,9 @@ function splitLastOf(value, find) {
|
|
|
40
41
|
const index = lastOf(value, find);
|
|
41
42
|
return index === -1 ? [value, undefined] : [value.substring(0, index), value.substring(index + 1)];
|
|
42
43
|
}
|
|
44
|
+
function splitEvery(s, n) {
|
|
45
|
+
return Array.from({ length: Math.ceil(s.length / n) }, (_, i) => s.slice(i * n, (i + 1) * n));
|
|
46
|
+
}
|
|
43
47
|
function trim0(value) {
|
|
44
48
|
const index = value.indexOf('\0');
|
|
45
49
|
return index === -1 ? value : value.substring(0, index);
|
|
@@ -54,17 +58,29 @@ function replace(value, re, process) {
|
|
|
54
58
|
return result + value.substring(i);
|
|
55
59
|
}
|
|
56
60
|
/*
|
|
57
|
-
export async function async_replace(value: string, re: RegExp, process: (match: RegExpExecArray)=>Promise<string
|
|
61
|
+
export async function async_replace<T = undefined>(value: string, re: RegExp, process: (match: RegExpExecArray, right: (context?: T)=>Promise<string>, context?: T)=>Promise<string>, context?: T): Promise<string> {
|
|
62
|
+
const right = async (context?: T) => async_replace(value, re, process, context);
|
|
58
63
|
let result = "";
|
|
59
|
-
let i =
|
|
64
|
+
let i = re.lastIndex;
|
|
60
65
|
for (let m; (m = re.exec(value));) {
|
|
61
|
-
result += value.substring(i, m.index) + await process(m);
|
|
66
|
+
result += value.substring(i, m.index) + await process(m, right, context);
|
|
62
67
|
i = re.lastIndex;
|
|
63
68
|
}
|
|
69
|
+
re.lastIndex = value.length;
|
|
64
70
|
return result + value.substring(i);
|
|
65
71
|
}
|
|
66
72
|
*/
|
|
67
73
|
async function async_replace(value, re, process) {
|
|
74
|
+
let result = "";
|
|
75
|
+
let i = re.lastIndex;
|
|
76
|
+
for (let m; (m = re.exec(value));) {
|
|
77
|
+
result += value.substring(i, m.index) + await process(m);
|
|
78
|
+
i = re.lastIndex;
|
|
79
|
+
}
|
|
80
|
+
re.lastIndex = value.length;
|
|
81
|
+
return result + value.substring(i);
|
|
82
|
+
}
|
|
83
|
+
async function async_replace_async(value, re, process) {
|
|
68
84
|
const combine = async (m) => value.substring(i, m.index) + await process(m);
|
|
69
85
|
const promises = [];
|
|
70
86
|
let i = 0;
|
|
@@ -94,9 +110,6 @@ async function async_replace_back(value, re, process) {
|
|
|
94
110
|
re.lastIndex = value.length;
|
|
95
111
|
return value.substring(start);
|
|
96
112
|
}
|
|
97
|
-
function splitEvery(s, n) {
|
|
98
|
-
return Array.from({ length: Math.ceil(s.length / n) }, (_, i) => s.slice(i * n, (i + 1) * n));
|
|
99
|
-
}
|
|
100
113
|
function tag(strings, ...keys) {
|
|
101
114
|
return (...values) => {
|
|
102
115
|
const dict = values.at(-1) || {};
|
|
@@ -145,13 +158,6 @@ class StringParser {
|
|
|
145
158
|
if (!this.skip(c))
|
|
146
159
|
throw new Error(`Expected '${c}'`);
|
|
147
160
|
}
|
|
148
|
-
match(re) {
|
|
149
|
-
const m = re.exec(this.remainder());
|
|
150
|
-
if (m) {
|
|
151
|
-
this.pos += m.index + m[0].length;
|
|
152
|
-
return m[0];
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
161
|
exec(re) {
|
|
156
162
|
const m = re.exec(this.remainder());
|
|
157
163
|
if (m) {
|
|
@@ -159,5 +165,9 @@ class StringParser {
|
|
|
159
165
|
return m;
|
|
160
166
|
}
|
|
161
167
|
}
|
|
168
|
+
match(re) {
|
|
169
|
+
return this.exec(re)?.[0];
|
|
170
|
+
}
|
|
162
171
|
}
|
|
163
172
|
exports.StringParser = StringParser;
|
|
173
|
+
//# sourceMappingURL=string.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@isopodlabs/utilities",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Various typescript helpers.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "tsc",
|
|
20
|
+
"watch": "tsc -watch -p ./",
|
|
20
21
|
"lint": "eslint \"src/**/*.ts\""
|
|
21
22
|
},
|
|
22
23
|
"keywords": [
|
package/dist/algorithm.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
type PartitionIndex<U> = U extends boolean ? 'true' | 'false' : U;
|
|
2
|
-
export declare function partition<T, U extends keyof any | boolean>(array: Iterable<T>, func: (v: T) => U): Record<PartitionIndex<U>, T[]>;
|
|
3
|
-
export declare function less<T>(a: T, b: T): boolean;
|
|
4
|
-
export declare function lowerBound<T>(array: T[], value: T, func?: (a: T, b: T, i: number) => boolean): number;
|
|
5
|
-
export declare function argmin<T>(array: T[], func?: (a: T, b: T) => number): number;
|
|
6
|
-
export declare function min<T>(array: T[], func?: (a: T, b: T) => number): T;
|
|
7
|
-
export declare function argmax<T>(array: T[], func?: (a: T, b: T) => number): number;
|
|
8
|
-
export declare function max<T>(array: T[], func?: (a: T, b: T) => number): T;
|
|
9
|
-
export {};
|
package/dist/algorithm.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.partition = partition;
|
|
4
|
-
exports.less = less;
|
|
5
|
-
exports.lowerBound = lowerBound;
|
|
6
|
-
exports.argmin = argmin;
|
|
7
|
-
exports.min = min;
|
|
8
|
-
exports.argmax = argmax;
|
|
9
|
-
exports.max = max;
|
|
10
|
-
const object_1 = require("./object");
|
|
11
|
-
function partition(array, func) {
|
|
12
|
-
const partitions = {};
|
|
13
|
-
for (const i of array)
|
|
14
|
-
(partitions[func(i)] ??= []).push(i);
|
|
15
|
-
return partitions;
|
|
16
|
-
}
|
|
17
|
-
function less(a, b) {
|
|
18
|
-
return a < b;
|
|
19
|
-
}
|
|
20
|
-
function lowerBound(array, value, func = less) {
|
|
21
|
-
let i = 0;
|
|
22
|
-
for (let n = array.length; n; n >>= 1) {
|
|
23
|
-
const mid = i + (n >> 1);
|
|
24
|
-
if (func(array[mid], value, mid)) {
|
|
25
|
-
i = mid + 1;
|
|
26
|
-
--n;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return i;
|
|
30
|
-
}
|
|
31
|
-
function argmin(array, func = object_1.compare) {
|
|
32
|
-
let mini = 0;
|
|
33
|
-
for (let i = 1; i < array.length; i++) {
|
|
34
|
-
const v = func(array[i], array[mini]);
|
|
35
|
-
if (v < 0)
|
|
36
|
-
mini = i;
|
|
37
|
-
}
|
|
38
|
-
return mini;
|
|
39
|
-
}
|
|
40
|
-
function min(array, func = object_1.compare) {
|
|
41
|
-
return array[argmin(array, func)];
|
|
42
|
-
}
|
|
43
|
-
function argmax(array, func = object_1.compare) {
|
|
44
|
-
let maxi = 0;
|
|
45
|
-
for (let i = 1; i < array.length; i++) {
|
|
46
|
-
const v = func(array[i], array[maxi]);
|
|
47
|
-
if (v > 0)
|
|
48
|
-
maxi = i;
|
|
49
|
-
}
|
|
50
|
-
return maxi;
|
|
51
|
-
}
|
|
52
|
-
function max(array, func = object_1.compare) {
|
|
53
|
-
return array[argmax(array, func)];
|
|
54
|
-
}
|
package/dist/object.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export declare function mapObject<T, U>(obj: Record<string, T>, func: (x: [k: string, v: T]) => [k: string, v: U]): Record<string, U>;
|
|
2
|
-
export declare function filterObject<T>(obj: Record<string, T>, func: (x: [k: string, v: T]) => boolean): Record<string, T>;
|
|
3
|
-
export declare function merge(...list: Record<string, any>[]): Record<string, any>;
|
|
4
|
-
export declare function isEmpty(obj: object): boolean;
|
|
5
|
-
export declare function clone<T extends object>(obj: T): T;
|
|
6
|
-
export declare function compare<T>(a: T, b: T): number;
|
|
7
|
-
export declare function reverse_compare<T>(a: T, b: T): number;
|
|
8
|
-
export declare function reverse<T, R>(func: (a: T, b: T) => R): (a: T, b: T) => R;
|
|
9
|
-
export declare class Lazy<T> {
|
|
10
|
-
private factory;
|
|
11
|
-
private _value;
|
|
12
|
-
constructor(factory: () => T);
|
|
13
|
-
get value(): T;
|
|
14
|
-
then<U>(this: T extends Promise<infer _R> ? Lazy<T> : never, onFulfilled: (value: T extends Promise<infer R> ? R : never) => U): Promise<U>;
|
|
15
|
-
}
|
|
16
|
-
export declare class CallCombiner0 {
|
|
17
|
-
private timeout?;
|
|
18
|
-
combine(delay: number, func: () => void): void;
|
|
19
|
-
pending(): boolean;
|
|
20
|
-
}
|
|
21
|
-
export declare class CallCombiner extends CallCombiner0 {
|
|
22
|
-
private func;
|
|
23
|
-
private delay;
|
|
24
|
-
constructor(func: () => void, delay: number);
|
|
25
|
-
trigger(): void;
|
|
26
|
-
}
|
|
27
|
-
export declare function makeCache<T>(load: (key: string) => T): {
|
|
28
|
-
get: (fullpath: string) => T;
|
|
29
|
-
remove: (fullpath: string) => boolean;
|
|
30
|
-
clear: () => void;
|
|
31
|
-
};
|
|
32
|
-
export declare function union<T>(a: Set<T>, b: Set<T>): Set<T>;
|
|
33
|
-
export declare function difference<T>(a: Set<T>, b: Set<T>): [Set<T>, Set<T>];
|
package/dist/object.js
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CallCombiner = exports.CallCombiner0 = exports.Lazy = void 0;
|
|
4
|
-
exports.mapObject = mapObject;
|
|
5
|
-
exports.filterObject = filterObject;
|
|
6
|
-
exports.merge = merge;
|
|
7
|
-
exports.isEmpty = isEmpty;
|
|
8
|
-
exports.clone = clone;
|
|
9
|
-
exports.compare = compare;
|
|
10
|
-
exports.reverse_compare = reverse_compare;
|
|
11
|
-
exports.reverse = reverse;
|
|
12
|
-
exports.makeCache = makeCache;
|
|
13
|
-
exports.union = union;
|
|
14
|
-
exports.difference = difference;
|
|
15
|
-
function mapObject(obj, func) {
|
|
16
|
-
return Object.fromEntries(Object.entries(obj).map(x => func(x)));
|
|
17
|
-
}
|
|
18
|
-
function filterObject(obj, func) {
|
|
19
|
-
return Object.fromEntries(Object.entries(obj).filter(x => func(x)));
|
|
20
|
-
}
|
|
21
|
-
function merge(...list) {
|
|
22
|
-
function isObject(value) {
|
|
23
|
-
return typeof value === 'object' && value !== null;
|
|
24
|
-
}
|
|
25
|
-
function recurse(target, source) {
|
|
26
|
-
for (const key in source) {
|
|
27
|
-
if (isObject(source[key]) && isObject(target[key]))
|
|
28
|
-
recurse(target[key], source[key]);
|
|
29
|
-
else
|
|
30
|
-
target[key] = source[key];
|
|
31
|
-
}
|
|
32
|
-
return target;
|
|
33
|
-
}
|
|
34
|
-
return list.reduce((merged, r) => recurse(merged, r), {});
|
|
35
|
-
}
|
|
36
|
-
function isEmpty(obj) {
|
|
37
|
-
return Object.keys(obj).length === 0;
|
|
38
|
-
}
|
|
39
|
-
function clone(obj) {
|
|
40
|
-
return Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);
|
|
41
|
-
}
|
|
42
|
-
function compare(a, b) {
|
|
43
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
44
|
-
}
|
|
45
|
-
function reverse_compare(a, b) {
|
|
46
|
-
return compare(b, a);
|
|
47
|
-
}
|
|
48
|
-
function reverse(func) {
|
|
49
|
-
return (a, b) => func(b, a);
|
|
50
|
-
}
|
|
51
|
-
class Lazy {
|
|
52
|
-
factory;
|
|
53
|
-
_value;
|
|
54
|
-
constructor(factory) {
|
|
55
|
-
this.factory = factory;
|
|
56
|
-
}
|
|
57
|
-
get value() {
|
|
58
|
-
if (this._value === undefined)
|
|
59
|
-
this._value = this.factory();
|
|
60
|
-
return this._value;
|
|
61
|
-
}
|
|
62
|
-
// Add 'then' method only when T is a Promise
|
|
63
|
-
then(onFulfilled) {
|
|
64
|
-
return this.value.then(onFulfilled);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
exports.Lazy = Lazy;
|
|
68
|
-
class CallCombiner0 {
|
|
69
|
-
timeout;
|
|
70
|
-
combine(delay, func) {
|
|
71
|
-
if (this.timeout)
|
|
72
|
-
clearTimeout(this.timeout);
|
|
73
|
-
this.timeout = setTimeout(() => {
|
|
74
|
-
this.timeout = undefined;
|
|
75
|
-
func();
|
|
76
|
-
}, delay);
|
|
77
|
-
}
|
|
78
|
-
pending() {
|
|
79
|
-
return !!this.timeout;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
exports.CallCombiner0 = CallCombiner0;
|
|
83
|
-
class CallCombiner extends CallCombiner0 {
|
|
84
|
-
func;
|
|
85
|
-
delay;
|
|
86
|
-
constructor(func, delay) {
|
|
87
|
-
super();
|
|
88
|
-
this.func = func;
|
|
89
|
-
this.delay = delay;
|
|
90
|
-
}
|
|
91
|
-
trigger() {
|
|
92
|
-
super.combine(this.delay, this.func);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
exports.CallCombiner = CallCombiner;
|
|
96
|
-
function makeCache(load) {
|
|
97
|
-
const cache = {};
|
|
98
|
-
return {
|
|
99
|
-
get: (fullpath) => {
|
|
100
|
-
if (!cache[fullpath])
|
|
101
|
-
cache[fullpath] = load(fullpath);
|
|
102
|
-
return cache[fullpath];
|
|
103
|
-
},
|
|
104
|
-
remove: (fullpath) => delete cache[fullpath],
|
|
105
|
-
clear: () => Object.keys(cache).forEach(k => delete cache[k]),
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
function union(a, b) {
|
|
109
|
-
return new Set([...a, ...b]);
|
|
110
|
-
}
|
|
111
|
-
function difference(a, b) {
|
|
112
|
-
const remaining = new Set(a);
|
|
113
|
-
const removed = new Set();
|
|
114
|
-
for (const item of b) {
|
|
115
|
-
if (remaining.delete(item))
|
|
116
|
-
removed.add(item);
|
|
117
|
-
}
|
|
118
|
-
return [remaining, removed];
|
|
119
|
-
}
|