@isopodlabs/utilities 1.4.1
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 -0
- package/dist/CaseInsensitive.d.ts +22 -0
- package/dist/CaseInsensitive.js +58 -0
- package/dist/algorithm.d.ts +5 -0
- package/dist/algorithm.js +34 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +20 -0
- package/dist/iterator.d.ts +19 -0
- package/dist/iterator.js +120 -0
- package/dist/string.d.ts +28 -0
- package/dist/string.js +153 -0
- package/dist/utils.d.ts +33 -0
- package/dist/utils.js +109 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# @isopodlabs/utilities
|
|
2
|
+
|
|
3
|
+
This package provides a set of utilities for TypeScript.
|
|
4
|
+
|
|
5
|
+
## ☕ Support My Work
|
|
6
|
+
If you use this package, consider [buying me a tea](https://coff.ee/adrianstephens) to support future updates!
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
Here is a basic example of how to use the package:
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
import * as utils from '@isopodlabs/utilities';
|
|
14
|
+
````
|
|
15
|
+
|
|
16
|
+
**Interfaces**:
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
**Functions**:
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## License
|
|
23
|
+
|
|
24
|
+
This project is licensed under the MIT License.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare class CaseInsensitiveString {
|
|
2
|
+
private value;
|
|
3
|
+
constructor(value: string);
|
|
4
|
+
get length(): number;
|
|
5
|
+
toString(): string;
|
|
6
|
+
includes(searchString: string, position?: number): boolean;
|
|
7
|
+
startsWith(searchString: string, position?: number): boolean;
|
|
8
|
+
endsWith(searchString: string, position?: number): boolean;
|
|
9
|
+
indexOf(searchString: string, position?: number): number;
|
|
10
|
+
lastIndexOf(searchString: string, position?: number): number;
|
|
11
|
+
compare(other: string): 1 | -1 | 0;
|
|
12
|
+
}
|
|
13
|
+
export declare class CaseInsensitiveString2 extends CaseInsensitiveString {
|
|
14
|
+
private orig;
|
|
15
|
+
constructor(orig: string);
|
|
16
|
+
toString(): string;
|
|
17
|
+
}
|
|
18
|
+
export declare function String(value: string): CaseInsensitiveString;
|
|
19
|
+
export declare function String2(value: string): CaseInsensitiveString2;
|
|
20
|
+
export declare function compare(a: string, b: string): 1 | -1 | 0;
|
|
21
|
+
export declare function Record<T>(obj: Record<string, T>): Record<string, T>;
|
|
22
|
+
export declare function Record2<T>(obj: Record<string, T>): Record<string, T>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CaseInsensitiveString2 = exports.CaseInsensitiveString = void 0;
|
|
4
|
+
exports.String = String;
|
|
5
|
+
exports.String2 = String2;
|
|
6
|
+
exports.compare = compare;
|
|
7
|
+
exports.Record = Record;
|
|
8
|
+
exports.Record2 = Record2;
|
|
9
|
+
class CaseInsensitiveString {
|
|
10
|
+
value;
|
|
11
|
+
constructor(value) { this.value = value.toLowerCase(); }
|
|
12
|
+
get length() { return this.value.length; }
|
|
13
|
+
toString() { return this.value; }
|
|
14
|
+
includes(searchString, position) { return this.value.includes(searchString.toLowerCase(), position); }
|
|
15
|
+
startsWith(searchString, position) { return this.value.startsWith(searchString.toLowerCase(), position); }
|
|
16
|
+
endsWith(searchString, position) { return this.value.endsWith(searchString.toLowerCase(), position); }
|
|
17
|
+
indexOf(searchString, position) { return this.value.indexOf(searchString.toLowerCase(), position); }
|
|
18
|
+
lastIndexOf(searchString, position) { return this.value.lastIndexOf(searchString.toLowerCase(), position); }
|
|
19
|
+
compare(other) { const bi = other.toLowerCase(); return this.value < bi ? -1 : this.value > bi ? 1 : 0; }
|
|
20
|
+
}
|
|
21
|
+
exports.CaseInsensitiveString = CaseInsensitiveString;
|
|
22
|
+
// keeps original string
|
|
23
|
+
class CaseInsensitiveString2 extends CaseInsensitiveString {
|
|
24
|
+
orig;
|
|
25
|
+
constructor(orig) {
|
|
26
|
+
super(orig);
|
|
27
|
+
this.orig = orig;
|
|
28
|
+
}
|
|
29
|
+
toString() { return this.orig; }
|
|
30
|
+
}
|
|
31
|
+
exports.CaseInsensitiveString2 = CaseInsensitiveString2;
|
|
32
|
+
function String(value) {
|
|
33
|
+
return new CaseInsensitiveString(value);
|
|
34
|
+
}
|
|
35
|
+
function String2(value) {
|
|
36
|
+
return new CaseInsensitiveString2(value);
|
|
37
|
+
}
|
|
38
|
+
function compare(a, b) {
|
|
39
|
+
const ai = a.toUpperCase(), bi = b.toUpperCase();
|
|
40
|
+
return ai < bi ? -1 : ai > bi ? 1 : 0;
|
|
41
|
+
}
|
|
42
|
+
function Record(obj) {
|
|
43
|
+
return new Proxy(obj, {
|
|
44
|
+
get: (target, name) => target[name.toUpperCase()],
|
|
45
|
+
set: (target, name, value) => (target[name.toUpperCase()] = value, true),
|
|
46
|
+
has: (target, name) => name.toUpperCase() in target,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
// keeps original record
|
|
50
|
+
function Record2(obj) {
|
|
51
|
+
return new Proxy(Object.entries(obj).reduce((acc, [key, value]) => ((acc[key.toUpperCase()] = value), acc), {}), {
|
|
52
|
+
get: (target, name) => target[name.toUpperCase()],
|
|
53
|
+
set: (target, name, value) => (target[name.toUpperCase()] = value, true),
|
|
54
|
+
has: (target, name) => name.toUpperCase() in target,
|
|
55
|
+
ownKeys: (target) => Object.keys(obj),
|
|
56
|
+
getOwnPropertyDescriptor: (target, name) => Object.getOwnPropertyDescriptor(obj, name)
|
|
57
|
+
});
|
|
58
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
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 lowerBound<T>(array: T[], value: T, func: (a: T, b: T, i: number) => boolean): number;
|
|
4
|
+
export declare function argmin<T>(array: T[], func?: (i: T) => number): number;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.partition = partition;
|
|
4
|
+
exports.lowerBound = lowerBound;
|
|
5
|
+
exports.argmin = argmin;
|
|
6
|
+
function partition(array, func) {
|
|
7
|
+
const partitions = {};
|
|
8
|
+
for (const i of array)
|
|
9
|
+
(partitions[func(i)] ??= []).push(i);
|
|
10
|
+
return partitions;
|
|
11
|
+
}
|
|
12
|
+
function lowerBound(array, value, func) {
|
|
13
|
+
let i = 0;
|
|
14
|
+
for (let n = array.length; n; n >>= 1) {
|
|
15
|
+
const mid = i + (n >> 1);
|
|
16
|
+
if (func(array[mid], value, mid)) {
|
|
17
|
+
i = mid + 1;
|
|
18
|
+
--n;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return i;
|
|
22
|
+
}
|
|
23
|
+
function argmin(array, func) {
|
|
24
|
+
let mini = 0;
|
|
25
|
+
let minv = func ? func(array[0]) : array[0];
|
|
26
|
+
for (let i = 1; i < array.length; i++) {
|
|
27
|
+
const v = func ? func(array[i]) : array[i];
|
|
28
|
+
if (v < minv) {
|
|
29
|
+
mini = i;
|
|
30
|
+
minv = v;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return mini;
|
|
34
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./utils"), exports);
|
|
18
|
+
__exportStar(require("./iterator"), exports);
|
|
19
|
+
__exportStar(require("./string"), exports);
|
|
20
|
+
__exportStar(require("./algorithm"), exports);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type SpreadType<T> = T extends Iterable<infer U> ? U[] : never;
|
|
2
|
+
export declare function arrayAppend<T, U extends Iterable<T>>(array: T[], items: U): void;
|
|
3
|
+
export declare function arrayRemove<T>(array: T[], item: T): boolean;
|
|
4
|
+
export declare function arrayCompare<T>(arr1: T[], arr2: T[]): number;
|
|
5
|
+
export declare function arrayEqual<T>(arr1: T[], arr2: T[]): boolean;
|
|
6
|
+
export declare function arrayRotate<T>(array: T[], start: number, end: number, shift: number): void;
|
|
7
|
+
export declare function arrayReverse<T>(array: T[], start: number, end: number): void;
|
|
8
|
+
export declare function array_make<T>(n: number, constructor: new () => T): T[];
|
|
9
|
+
export declare function eachIterable<T>(iterable: Iterable<T> | undefined, func: (v: T, i: number) => void): void;
|
|
10
|
+
export declare function findIterable<T>(iterable: Iterable<T> | undefined, func: (v: T) => boolean): T | undefined;
|
|
11
|
+
export declare function mapIterable<T, U>(iterable: Iterable<T> | undefined, func: (v: T, i: number) => U): U[];
|
|
12
|
+
export declare function asyncMap<T, U>(iterable: Iterable<T> | undefined, func: (v: T, i: number) => Promise<U>): Promise<U[]>;
|
|
13
|
+
export declare function asyncReduce<T, U>(array: T[], func: (acc: U, v: T, i: number, array: T[]) => Promise<U>, initialValue: U): Promise<U>;
|
|
14
|
+
export declare function parallel(...fns: (() => any)[]): Promise<any[]>;
|
|
15
|
+
export declare function serial(...fns: (() => any)[]): Promise<any[]>;
|
|
16
|
+
export declare function filterIterable<T>(iterable: Iterable<T>, func: (v: T, i: number) => boolean): T[];
|
|
17
|
+
export declare function asyncFilter<T>(iterable: Iterable<T>, func: (v: T) => Promise<boolean>): Promise<T[]>;
|
|
18
|
+
export declare function mapObject<T, U>(obj: Record<string, T>, func: (x: [k: string, v: T]) => [k: string, v: U]): Record<string, U>;
|
|
19
|
+
export declare function filterObject<T>(obj: Record<string, T>, func: (x: [k: string, v: T]) => boolean): Record<string, T>;
|
package/dist/iterator.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.arrayAppend = arrayAppend;
|
|
4
|
+
exports.arrayRemove = arrayRemove;
|
|
5
|
+
exports.arrayCompare = arrayCompare;
|
|
6
|
+
exports.arrayEqual = arrayEqual;
|
|
7
|
+
exports.arrayRotate = arrayRotate;
|
|
8
|
+
exports.arrayReverse = arrayReverse;
|
|
9
|
+
exports.array_make = array_make;
|
|
10
|
+
exports.eachIterable = eachIterable;
|
|
11
|
+
exports.findIterable = findIterable;
|
|
12
|
+
exports.mapIterable = mapIterable;
|
|
13
|
+
exports.asyncMap = asyncMap;
|
|
14
|
+
exports.asyncReduce = asyncReduce;
|
|
15
|
+
exports.parallel = parallel;
|
|
16
|
+
exports.serial = serial;
|
|
17
|
+
exports.filterIterable = filterIterable;
|
|
18
|
+
exports.asyncFilter = asyncFilter;
|
|
19
|
+
exports.mapObject = mapObject;
|
|
20
|
+
exports.filterObject = filterObject;
|
|
21
|
+
const utils_1 = require("./utils");
|
|
22
|
+
function arrayAppend(array, items) {
|
|
23
|
+
for (const i of items)
|
|
24
|
+
array.push(i);
|
|
25
|
+
}
|
|
26
|
+
function arrayRemove(array, item) {
|
|
27
|
+
const index = array.indexOf(item);
|
|
28
|
+
if (index === -1)
|
|
29
|
+
return false;
|
|
30
|
+
array.splice(index, 1);
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
function arrayCompare(arr1, arr2) {
|
|
34
|
+
const length = Math.min(arr1.length, arr2.length);
|
|
35
|
+
for (let i = 0; i < length; i++) {
|
|
36
|
+
const r = (0, utils_1.compare)(arr1[i], arr2[i]);
|
|
37
|
+
if (r)
|
|
38
|
+
return r;
|
|
39
|
+
}
|
|
40
|
+
return arr1.length - arr2.length;
|
|
41
|
+
}
|
|
42
|
+
function arrayEqual(arr1, arr2) {
|
|
43
|
+
if (arr1.length !== arr2.length)
|
|
44
|
+
return false;
|
|
45
|
+
for (let i = 0; i < arr1.length; i++) {
|
|
46
|
+
if (arr1[i] !== arr2[i])
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
function arrayRotate(array, start, end, shift) {
|
|
52
|
+
const length = end - start;
|
|
53
|
+
if (length > 1 && shift % length) {
|
|
54
|
+
shift = ((shift % length) + length) % length;
|
|
55
|
+
arrayReverse(array, start, end - 1);
|
|
56
|
+
arrayReverse(array, start, start + shift - 1);
|
|
57
|
+
arrayReverse(array, start + shift, end - 1);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function arrayReverse(array, start, end) {
|
|
61
|
+
while (start < end) {
|
|
62
|
+
[array[start], array[end]] = [array[end], array[start]];
|
|
63
|
+
start++;
|
|
64
|
+
end--;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function array_make(n, constructor) {
|
|
68
|
+
return Array.from({ length: n }, () => new constructor);
|
|
69
|
+
}
|
|
70
|
+
function eachIterable(iterable, func) {
|
|
71
|
+
if (iterable) {
|
|
72
|
+
let i = 0;
|
|
73
|
+
for (const v of iterable)
|
|
74
|
+
func(v, i++);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function findIterable(iterable, func) {
|
|
78
|
+
if (iterable) {
|
|
79
|
+
for (const v of iterable) {
|
|
80
|
+
if (func(v))
|
|
81
|
+
return v;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function mapIterable(iterable, func) {
|
|
86
|
+
return iterable ? Array.from(iterable, func) : [];
|
|
87
|
+
}
|
|
88
|
+
async function asyncMap(iterable, func) {
|
|
89
|
+
return Promise.all(mapIterable(iterable, func));
|
|
90
|
+
}
|
|
91
|
+
async function asyncReduce(array, func, initialValue) {
|
|
92
|
+
return array.reduce(async (promise, v, i, array) => func(await promise, v, i, array), Promise.resolve(initialValue));
|
|
93
|
+
}
|
|
94
|
+
async function parallel(...fns) {
|
|
95
|
+
return asyncMap(fns, f => f());
|
|
96
|
+
}
|
|
97
|
+
async function serial(...fns) {
|
|
98
|
+
const results = [];
|
|
99
|
+
for (const f of fns)
|
|
100
|
+
results.push(await f());
|
|
101
|
+
return results;
|
|
102
|
+
}
|
|
103
|
+
function filterIterable(iterable, func) {
|
|
104
|
+
const array = [];
|
|
105
|
+
let i = 0;
|
|
106
|
+
for (const v of iterable)
|
|
107
|
+
if (func(v, i++))
|
|
108
|
+
array.push(v);
|
|
109
|
+
return array;
|
|
110
|
+
}
|
|
111
|
+
async function asyncFilter(iterable, func) {
|
|
112
|
+
const filters = await Promise.all(mapIterable(iterable, func));
|
|
113
|
+
return filterIterable(iterable, (_, i) => filters[i]);
|
|
114
|
+
}
|
|
115
|
+
function mapObject(obj, func) {
|
|
116
|
+
return Object.fromEntries(Object.entries(obj).map(x => func(x)));
|
|
117
|
+
}
|
|
118
|
+
function filterObject(obj, func) {
|
|
119
|
+
return Object.fromEntries(Object.entries(obj).filter(x => func(x)));
|
|
120
|
+
}
|
package/dist/string.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare function firstOf(value: string, find: string): number;
|
|
2
|
+
export declare function lastOf(value: string, find: string): number;
|
|
3
|
+
export declare function splitFirstOf(value: string, find: string): (string | undefined)[];
|
|
4
|
+
export declare function splitLastOf(value: string, find: string): (string | undefined)[];
|
|
5
|
+
export declare function trim0(value: string): string;
|
|
6
|
+
export declare function replace(value: string, re: RegExp, process: (match: RegExpExecArray) => string): string;
|
|
7
|
+
export declare function async_replace(value: string, re: RegExp, process: (match: RegExpExecArray) => Promise<string>): Promise<string>;
|
|
8
|
+
export declare function replace_back(value: string, re: RegExp, process: (match: RegExpExecArray, right: string) => string): string;
|
|
9
|
+
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
|
+
export declare function tag(strings: TemplateStringsArray, ...keys: any[]): (...values: any[]) => string;
|
|
12
|
+
export declare function previousChar(str: string, pos: number): string;
|
|
13
|
+
export declare function hasCustomToString(value: any): boolean;
|
|
14
|
+
export declare class StringParser {
|
|
15
|
+
subject: string;
|
|
16
|
+
pos: number;
|
|
17
|
+
constructor(subject: string, pos?: number);
|
|
18
|
+
remaining(): number;
|
|
19
|
+
remainder(): string;
|
|
20
|
+
processed(): string;
|
|
21
|
+
peek(): string;
|
|
22
|
+
peekn(n: number): string;
|
|
23
|
+
get(n: number): string;
|
|
24
|
+
skip(c: string): boolean;
|
|
25
|
+
expect(c: string): void;
|
|
26
|
+
match(re: RegExp): string | undefined;
|
|
27
|
+
exec(re: RegExp): RegExpExecArray | undefined;
|
|
28
|
+
}
|
package/dist/string.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
//-----------------------------------------------------------------------------
|
|
3
|
+
// strings
|
|
4
|
+
//-----------------------------------------------------------------------------
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.StringParser = void 0;
|
|
7
|
+
exports.firstOf = firstOf;
|
|
8
|
+
exports.lastOf = lastOf;
|
|
9
|
+
exports.splitFirstOf = splitFirstOf;
|
|
10
|
+
exports.splitLastOf = splitLastOf;
|
|
11
|
+
exports.trim0 = trim0;
|
|
12
|
+
exports.replace = replace;
|
|
13
|
+
exports.async_replace = async_replace;
|
|
14
|
+
exports.replace_back = replace_back;
|
|
15
|
+
exports.async_replace_back = async_replace_back;
|
|
16
|
+
exports.splitEvery = splitEvery;
|
|
17
|
+
exports.tag = tag;
|
|
18
|
+
exports.previousChar = previousChar;
|
|
19
|
+
exports.hasCustomToString = hasCustomToString;
|
|
20
|
+
function firstOf(value, find) {
|
|
21
|
+
let index = value.length;
|
|
22
|
+
for (const c of find) {
|
|
23
|
+
const i = value.indexOf(c);
|
|
24
|
+
if (i >= 0)
|
|
25
|
+
index = Math.min(i);
|
|
26
|
+
}
|
|
27
|
+
return index;
|
|
28
|
+
}
|
|
29
|
+
function lastOf(value, find) {
|
|
30
|
+
let index = -1;
|
|
31
|
+
for (const c of find)
|
|
32
|
+
index = Math.max(value.indexOf(c));
|
|
33
|
+
return index;
|
|
34
|
+
}
|
|
35
|
+
function splitFirstOf(value, find) {
|
|
36
|
+
const index = firstOf(value, find);
|
|
37
|
+
return index === -1 ? [undefined, value] : [value.substring(0, index), value.substring(index + 1)];
|
|
38
|
+
}
|
|
39
|
+
function splitLastOf(value, find) {
|
|
40
|
+
const index = lastOf(value, find);
|
|
41
|
+
return index === -1 ? [value, undefined] : [value.substring(0, index), value.substring(index + 1)];
|
|
42
|
+
}
|
|
43
|
+
function trim0(value) {
|
|
44
|
+
const index = value.indexOf('\0');
|
|
45
|
+
return index === -1 ? value : value.substring(0, index);
|
|
46
|
+
}
|
|
47
|
+
function replace(value, re, process) {
|
|
48
|
+
let m;
|
|
49
|
+
let result = "";
|
|
50
|
+
let i = 0;
|
|
51
|
+
while ((m = re.exec(value))) {
|
|
52
|
+
result += value.substring(i, m.index) + process(m);
|
|
53
|
+
i = re.lastIndex;
|
|
54
|
+
}
|
|
55
|
+
return result + value.substring(i);
|
|
56
|
+
}
|
|
57
|
+
async function async_replace(value, re, process) {
|
|
58
|
+
let m;
|
|
59
|
+
let result = "";
|
|
60
|
+
let i = 0;
|
|
61
|
+
while ((m = re.exec(value))) {
|
|
62
|
+
result += value.substring(i, m.index) + await process(m);
|
|
63
|
+
i = re.lastIndex;
|
|
64
|
+
}
|
|
65
|
+
return result + value.substring(i);
|
|
66
|
+
}
|
|
67
|
+
function replace_back(value, re, process) {
|
|
68
|
+
const start = re.lastIndex;
|
|
69
|
+
const m = re.exec(value);
|
|
70
|
+
if (m) {
|
|
71
|
+
const right = replace_back(value, re, process);
|
|
72
|
+
return value.substring(start, m.index) + process(m, right);
|
|
73
|
+
}
|
|
74
|
+
re.lastIndex = value.length;
|
|
75
|
+
return value.substring(start);
|
|
76
|
+
}
|
|
77
|
+
async function async_replace_back(value, re, process) {
|
|
78
|
+
const start = re.lastIndex;
|
|
79
|
+
const m = re.exec(value);
|
|
80
|
+
if (m) {
|
|
81
|
+
const right = await async_replace_back(value, re, process);
|
|
82
|
+
return value.substring(start, m.index) + await process(m, right);
|
|
83
|
+
}
|
|
84
|
+
re.lastIndex = value.length;
|
|
85
|
+
return value.substring(start);
|
|
86
|
+
}
|
|
87
|
+
function splitEvery(s, n) {
|
|
88
|
+
return Array.from({ length: Math.ceil(s.length / n) }, (_, i) => s.slice(i * n, (i + 1) * n));
|
|
89
|
+
}
|
|
90
|
+
function tag(strings, ...keys) {
|
|
91
|
+
return ((...values) => {
|
|
92
|
+
const dict = values.at(-1) || {};
|
|
93
|
+
return keys.map((key, i) => (Number.isInteger(key) ? values[key] : dict[key]) + strings[i + 1]).join('');
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function previousChar(str, pos) {
|
|
97
|
+
return pos === 0
|
|
98
|
+
? "\n"
|
|
99
|
+
// check for low surrogate (BMP)
|
|
100
|
+
: (str.charCodeAt(pos - 1) & 0xfc00) === 0xdc00 && (str.charCodeAt(pos - 2) & 0xfc00) === 0xd800
|
|
101
|
+
? str.slice(pos - 2, pos) : str.charAt(pos - 1);
|
|
102
|
+
}
|
|
103
|
+
function hasCustomToString(value) {
|
|
104
|
+
return value && value.toString !== Object.prototype.toString;
|
|
105
|
+
}
|
|
106
|
+
class StringParser {
|
|
107
|
+
subject;
|
|
108
|
+
pos;
|
|
109
|
+
constructor(subject, pos = 0) {
|
|
110
|
+
this.subject = subject;
|
|
111
|
+
this.pos = pos;
|
|
112
|
+
}
|
|
113
|
+
remaining() { return this.subject.length - this.pos; }
|
|
114
|
+
remainder() { return this.subject.slice(this.pos); }
|
|
115
|
+
processed() { return this.subject.slice(0, this.pos); }
|
|
116
|
+
peek() {
|
|
117
|
+
return this.subject[this.pos];
|
|
118
|
+
}
|
|
119
|
+
peekn(n) {
|
|
120
|
+
return this.subject.slice(this.pos, this.pos + n);
|
|
121
|
+
}
|
|
122
|
+
get(n) {
|
|
123
|
+
const pos = this.pos;
|
|
124
|
+
this.pos = Math.min(pos + n, this.subject.length);
|
|
125
|
+
return this.subject.slice(pos, this.pos);
|
|
126
|
+
}
|
|
127
|
+
skip(c) {
|
|
128
|
+
if (this.remainder().startsWith(c)) {
|
|
129
|
+
this.pos += c.length;
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
expect(c) {
|
|
135
|
+
if (!this.skip(c))
|
|
136
|
+
throw new Error(`Expected '${c}'`);
|
|
137
|
+
}
|
|
138
|
+
match(re) {
|
|
139
|
+
const m = re.exec(this.remainder());
|
|
140
|
+
if (m) {
|
|
141
|
+
this.pos += m.index + m[0].length;
|
|
142
|
+
return m[0];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
exec(re) {
|
|
146
|
+
const m = re.exec(this.remainder());
|
|
147
|
+
if (m) {
|
|
148
|
+
this.pos += m.index + m[0].length;
|
|
149
|
+
return m;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
exports.StringParser = StringParser;
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare class Lazy<T> {
|
|
2
|
+
private factory;
|
|
3
|
+
private _value;
|
|
4
|
+
constructor(factory: () => T);
|
|
5
|
+
get value(): T;
|
|
6
|
+
}
|
|
7
|
+
export declare class AsyncLazy<T> {
|
|
8
|
+
private factory;
|
|
9
|
+
private _value;
|
|
10
|
+
constructor(factory: () => Promise<T>);
|
|
11
|
+
get value(): (T & {}) | null;
|
|
12
|
+
}
|
|
13
|
+
export declare class CallCombiner0 {
|
|
14
|
+
private timeout;
|
|
15
|
+
combine(delay: number, func: () => void): void;
|
|
16
|
+
pending(): boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare class CallCombiner extends CallCombiner0 {
|
|
19
|
+
private func;
|
|
20
|
+
private delay;
|
|
21
|
+
constructor(func: () => void, delay: number);
|
|
22
|
+
trigger(): void;
|
|
23
|
+
}
|
|
24
|
+
export declare function makeCache<T>(load: (key: string) => T): {
|
|
25
|
+
get: (fullpath: string) => T;
|
|
26
|
+
remove: (fullpath: string) => void;
|
|
27
|
+
};
|
|
28
|
+
export declare function compare<T>(a: T, b: T): number;
|
|
29
|
+
export declare function reverse_compare<T>(a: T, b: T): number;
|
|
30
|
+
export declare function reverse<T, R>(func: (a: T, b: T) => R): (a: T, b: T) => R;
|
|
31
|
+
export declare function merge(...list: Record<string, any>[]): Record<string, any>;
|
|
32
|
+
export declare function isEmpty(obj: object): boolean;
|
|
33
|
+
export declare function clone<T extends object>(obj: T): T;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CallCombiner = exports.CallCombiner0 = exports.AsyncLazy = exports.Lazy = void 0;
|
|
4
|
+
exports.makeCache = makeCache;
|
|
5
|
+
exports.compare = compare;
|
|
6
|
+
exports.reverse_compare = reverse_compare;
|
|
7
|
+
exports.reverse = reverse;
|
|
8
|
+
exports.merge = merge;
|
|
9
|
+
exports.isEmpty = isEmpty;
|
|
10
|
+
exports.clone = clone;
|
|
11
|
+
class Lazy {
|
|
12
|
+
factory;
|
|
13
|
+
_value;
|
|
14
|
+
constructor(factory) {
|
|
15
|
+
this.factory = factory;
|
|
16
|
+
}
|
|
17
|
+
get value() {
|
|
18
|
+
if (this._value === undefined)
|
|
19
|
+
this._value = this.factory();
|
|
20
|
+
return this._value;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.Lazy = Lazy;
|
|
24
|
+
class AsyncLazy {
|
|
25
|
+
factory;
|
|
26
|
+
_value;
|
|
27
|
+
constructor(factory) {
|
|
28
|
+
this.factory = factory;
|
|
29
|
+
}
|
|
30
|
+
get value() {
|
|
31
|
+
if (this._value === undefined) {
|
|
32
|
+
this._value = null;
|
|
33
|
+
this.factory().then(v => this._value = v);
|
|
34
|
+
}
|
|
35
|
+
return this._value;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.AsyncLazy = AsyncLazy;
|
|
39
|
+
class CallCombiner0 {
|
|
40
|
+
timeout = null;
|
|
41
|
+
combine(delay, func) {
|
|
42
|
+
if (this.timeout)
|
|
43
|
+
clearTimeout(this.timeout);
|
|
44
|
+
this.timeout = setTimeout(() => {
|
|
45
|
+
this.timeout = null;
|
|
46
|
+
func();
|
|
47
|
+
}, delay);
|
|
48
|
+
}
|
|
49
|
+
pending() {
|
|
50
|
+
return !!this.timeout;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.CallCombiner0 = CallCombiner0;
|
|
54
|
+
class CallCombiner extends CallCombiner0 {
|
|
55
|
+
func;
|
|
56
|
+
delay;
|
|
57
|
+
constructor(func, delay) {
|
|
58
|
+
super();
|
|
59
|
+
this.func = func;
|
|
60
|
+
this.delay = delay;
|
|
61
|
+
}
|
|
62
|
+
trigger() {
|
|
63
|
+
super.combine(this.delay, this.func);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.CallCombiner = CallCombiner;
|
|
67
|
+
function makeCache(load) {
|
|
68
|
+
const cache = {};
|
|
69
|
+
return {
|
|
70
|
+
get: (fullpath) => {
|
|
71
|
+
if (!cache[fullpath])
|
|
72
|
+
cache[fullpath] = load(fullpath);
|
|
73
|
+
return cache[fullpath];
|
|
74
|
+
},
|
|
75
|
+
remove: (fullpath) => {
|
|
76
|
+
delete cache[fullpath];
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function compare(a, b) {
|
|
81
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
82
|
+
}
|
|
83
|
+
function reverse_compare(a, b) {
|
|
84
|
+
return compare(b, a);
|
|
85
|
+
}
|
|
86
|
+
function reverse(func) {
|
|
87
|
+
return (a, b) => func(b, a);
|
|
88
|
+
}
|
|
89
|
+
function merge(...list) {
|
|
90
|
+
function isObject(value) {
|
|
91
|
+
return typeof value === 'object' && value !== null;
|
|
92
|
+
}
|
|
93
|
+
function recurse(target, source) {
|
|
94
|
+
for (const key in source) {
|
|
95
|
+
if (isObject(source[key]) && isObject(target[key]))
|
|
96
|
+
recurse(target[key], source[key]);
|
|
97
|
+
else
|
|
98
|
+
target[key] = source[key];
|
|
99
|
+
}
|
|
100
|
+
return target;
|
|
101
|
+
}
|
|
102
|
+
return list.reduce((merged, r) => recurse(merged, r), {});
|
|
103
|
+
}
|
|
104
|
+
function isEmpty(obj) {
|
|
105
|
+
return Object.keys(obj).length === 0;
|
|
106
|
+
}
|
|
107
|
+
function clone(obj) {
|
|
108
|
+
return Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);
|
|
109
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@isopodlabs/utilities",
|
|
3
|
+
"version": "1.4.1",
|
|
4
|
+
"description": "Various typescript helpers.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"README.md"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"test": "echo \"No tests specified\" && exit 0"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"typescript",
|
|
16
|
+
"string",
|
|
17
|
+
"iterator",
|
|
18
|
+
"algorithm"
|
|
19
|
+
],
|
|
20
|
+
"author": "Adrian Stephens",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^22.13.8",
|
|
24
|
+
"eslint": "^9.21.0",
|
|
25
|
+
"typescript": "^5.8.2",
|
|
26
|
+
"typescript-eslint": "^8.26.0"
|
|
27
|
+
}
|
|
28
|
+
}
|