@e280/stz 0.0.0-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/license +23 -0
- package/package.json +40 -0
- package/readme.md +85 -0
- package/s/clone/clone.test.ts +124 -0
- package/s/clone/clone.ts +41 -0
- package/s/concurrent.ts +12 -0
- package/s/data/anka.ts +66 -0
- package/s/data/barname/badge.ts +78 -0
- package/s/data/barname/barname.ts +62 -0
- package/s/data/barname/demo.ts +49 -0
- package/s/data/barname/index.ts +4 -0
- package/s/data/barname/utils/prefixes.ts +20 -0
- package/s/data/barname/utils/suffixes.ts +20 -0
- package/s/data/base58.ts +65 -0
- package/s/data/base64.ts +22 -0
- package/s/data/base64url.ts +27 -0
- package/s/data/bytes.ts +7 -0
- package/s/data/hex.ts +35 -0
- package/s/data/nomen/demo.ts +8 -0
- package/s/data/nomen/grammar.ts +41 -0
- package/s/data/nomen/index.ts +5 -0
- package/s/data/nomen/nomen.ts +34 -0
- package/s/data/nomen/presets/falrysk.ts +112 -0
- package/s/data/nomen/types.ts +9 -0
- package/s/data/txt.ts +11 -0
- package/s/deadline.ts +24 -0
- package/s/debounce/debounce.test.ts +73 -0
- package/s/debounce/debounce.ts +54 -0
- package/s/debounce/types.ts +8 -0
- package/s/dedupe.ts +5 -0
- package/s/deep/deep.test.ts +8 -0
- package/s/deep/deep.ts +11 -0
- package/s/deep/parts/equal.test.ts +124 -0
- package/s/deep/parts/equal.ts +49 -0
- package/s/deep/parts/freeze.ts +34 -0
- package/s/defer-promise.ts +29 -0
- package/s/escape-regex.ts +5 -0
- package/s/hat.ts +17 -0
- package/s/index.ts +23 -0
- package/s/is.ts +27 -0
- package/s/map-g.ts +52 -0
- package/s/nap.ts +5 -0
- package/s/ob.ts +66 -0
- package/s/pipe.ts +24 -0
- package/s/pubsub.ts +68 -0
- package/s/trash.ts +30 -0
- package/x/clone/clone.d.ts +1 -0
- package/x/clone/clone.js +26 -0
- package/x/clone/clone.js.map +1 -0
- package/x/clone/clone.test.d.ts +1 -0
- package/x/clone/clone.test.js +125 -0
- package/x/clone/clone.test.js.map +1 -0
- package/x/concurrent.d.ts +1 -0
- package/x/concurrent.js +7 -0
- package/x/concurrent.js.map +1 -0
- package/x/data/anka.d.ts +5 -0
- package/x/data/anka.js +53 -0
- package/x/data/anka.js.map +1 -0
- package/x/data/barname/badge.d.ts +25 -0
- package/x/data/barname/badge.js +64 -0
- package/x/data/barname/badge.js.map +1 -0
- package/x/data/barname/barname.d.ts +7 -0
- package/x/data/barname/barname.js +49 -0
- package/x/data/barname/barname.js.map +1 -0
- package/x/data/barname/demo.d.ts +1 -0
- package/x/data/barname/demo.js +45 -0
- package/x/data/barname/demo.js.map +1 -0
- package/x/data/barname/index.d.ts +2 -0
- package/x/data/barname/index.js +3 -0
- package/x/data/barname/index.js.map +1 -0
- package/x/data/barname/utils/prefixes.d.ts +1 -0
- package/x/data/barname/utils/prefixes.js +19 -0
- package/x/data/barname/utils/prefixes.js.map +1 -0
- package/x/data/barname/utils/suffixes.d.ts +1 -0
- package/x/data/barname/utils/suffixes.js +19 -0
- package/x/data/barname/utils/suffixes.js.map +1 -0
- package/x/data/base58.d.ts +5 -0
- package/x/data/base58.js +58 -0
- package/x/data/base58.js.map +1 -0
- package/x/data/base64.d.ts +5 -0
- package/x/data/base64.js +17 -0
- package/x/data/base64.js.map +1 -0
- package/x/data/base64url.d.ts +5 -0
- package/x/data/base64url.js +22 -0
- package/x/data/base64url.js.map +1 -0
- package/x/data/bytes.d.ts +3 -0
- package/x/data/bytes.js +6 -0
- package/x/data/bytes.js.map +1 -0
- package/x/data/hex.d.ts +6 -0
- package/x/data/hex.js +30 -0
- package/x/data/hex.js.map +1 -0
- package/x/data/nomen/demo.d.ts +1 -0
- package/x/data/nomen/demo.js +5 -0
- package/x/data/nomen/demo.js.map +1 -0
- package/x/data/nomen/grammar.d.ts +11 -0
- package/x/data/nomen/grammar.js +32 -0
- package/x/data/nomen/grammar.js.map +1 -0
- package/x/data/nomen/index.d.ts +3 -0
- package/x/data/nomen/index.js +4 -0
- package/x/data/nomen/index.js.map +1 -0
- package/x/data/nomen/nomen.d.ts +11 -0
- package/x/data/nomen/nomen.js +29 -0
- package/x/data/nomen/nomen.js.map +1 -0
- package/x/data/nomen/presets/falrysk.d.ts +5 -0
- package/x/data/nomen/presets/falrysk.js +99 -0
- package/x/data/nomen/presets/falrysk.js.map +1 -0
- package/x/data/nomen/types.d.ts +6 -0
- package/x/data/nomen/types.js +2 -0
- package/x/data/nomen/types.js.map +1 -0
- package/x/data/txt.d.ts +4 -0
- package/x/data/txt.js +9 -0
- package/x/data/txt.js.map +1 -0
- package/x/deadline.d.ts +6 -0
- package/x/deadline.js +17 -0
- package/x/deadline.js.map +1 -0
- package/x/debounce/debounce.d.ts +2 -0
- package/x/debounce/debounce.js +37 -0
- package/x/debounce/debounce.js.map +1 -0
- package/x/debounce/debounce.test.d.ts +1 -0
- package/x/debounce/debounce.test.js +75 -0
- package/x/debounce/debounce.test.js.map +1 -0
- package/x/debounce/types.d.ts +2 -0
- package/x/debounce/types.js +2 -0
- package/x/debounce/types.js.map +1 -0
- package/x/dedupe.d.ts +1 -0
- package/x/dedupe.js +4 -0
- package/x/dedupe.js.map +1 -0
- package/x/deep/deep.d.ts +7 -0
- package/x/deep/deep.js +9 -0
- package/x/deep/deep.js.map +1 -0
- package/x/deep/deep.test.d.ts +1 -0
- package/x/deep/deep.test.js +10 -0
- package/x/deep/deep.test.js.map +1 -0
- package/x/deep/parts/equal.d.ts +1 -0
- package/x/deep/parts/equal.js +39 -0
- package/x/deep/parts/equal.js.map +1 -0
- package/x/deep/parts/equal.test.d.ts +1 -0
- package/x/deep/parts/equal.test.js +126 -0
- package/x/deep/parts/equal.test.js.map +1 -0
- package/x/deep/parts/freeze.d.ts +1 -0
- package/x/deep/parts/freeze.js +24 -0
- package/x/deep/parts/freeze.js.map +1 -0
- package/x/defer-promise.d.ts +10 -0
- package/x/defer-promise.js +15 -0
- package/x/defer-promise.js.map +1 -0
- package/x/escape-regex.d.ts +1 -0
- package/x/escape-regex.js +4 -0
- package/x/escape-regex.js.map +1 -0
- package/x/hat.d.ts +6 -0
- package/x/hat.js +16 -0
- package/x/hat.js.map +1 -0
- package/x/index.d.ts +20 -0
- package/x/index.js +21 -0
- package/x/index.js.map +1 -0
- package/x/is.d.ts +10 -0
- package/x/is.js +11 -0
- package/x/is.js.map +1 -0
- package/x/map-g.d.ts +17 -0
- package/x/map-g.js +40 -0
- package/x/map-g.js.map +1 -0
- package/x/nap.d.ts +1 -0
- package/x/nap.js +2 -0
- package/x/nap.js.map +1 -0
- package/x/ob.d.ts +14 -0
- package/x/ob.js +21 -0
- package/x/ob.js.map +1 -0
- package/x/pipe.d.ts +8 -0
- package/x/pipe.js +16 -0
- package/x/pipe.js.map +1 -0
- package/x/pubsub.d.ts +18 -0
- package/x/pubsub.js +40 -0
- package/x/pubsub.js.map +1 -0
- package/x/trash.d.ts +14 -0
- package/x/trash.js +25 -0
- package/x/trash.js.map +1 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
//
|
|
2
|
+
// import {Suite, expect} from "cynic"
|
|
3
|
+
// import {deepEqual} from "./equal.js"
|
|
4
|
+
//
|
|
5
|
+
// export default <Suite>{
|
|
6
|
+
//
|
|
7
|
+
// async "compare primitive types"() {
|
|
8
|
+
// expect(deepEqual(123, 123)).equals(true)
|
|
9
|
+
// expect(deepEqual("abc", "abc")).equals(true)
|
|
10
|
+
// expect(deepEqual(true, true)).equals(true)
|
|
11
|
+
// expect(deepEqual(123, "123")).equals(false)
|
|
12
|
+
// expect(deepEqual(true, 1)).equals(false)
|
|
13
|
+
// },
|
|
14
|
+
//
|
|
15
|
+
// async "compare arrays"() {
|
|
16
|
+
// const array1 = [1, 2, 3]
|
|
17
|
+
// const array2 = [1, 2, 3]
|
|
18
|
+
// const array3 = [1, 2, 4]
|
|
19
|
+
// expect(deepEqual(array1, array2)).equals(true)
|
|
20
|
+
// expect(deepEqual(array1, array3)).equals(false)
|
|
21
|
+
// },
|
|
22
|
+
//
|
|
23
|
+
// async "compare plain objects"() {
|
|
24
|
+
// const obj1 = { foo: "bar", baz: 123 }
|
|
25
|
+
// const obj2 = { foo: "bar", baz: 123 }
|
|
26
|
+
// const obj3 = { foo: "bar", baz: 124 }
|
|
27
|
+
// expect(deepEqual(obj1, obj2)).equals(true)
|
|
28
|
+
// expect(deepEqual(obj1, obj3)).equals(false)
|
|
29
|
+
// },
|
|
30
|
+
//
|
|
31
|
+
// async "compare nested objects"() {
|
|
32
|
+
// const obj1 = { foo: "bar", inner: { baz: 123, deeper: { qux: true }}}
|
|
33
|
+
// const obj2 = { foo: "bar", inner: { baz: 123, deeper: { qux: true }}}
|
|
34
|
+
// const obj3 = { foo: "bar", inner: { baz: 124, deeper: { qux: true }}}
|
|
35
|
+
// expect(deepEqual(obj1, obj2)).equals(true)
|
|
36
|
+
// expect(deepEqual(obj1, obj3)).equals(false)
|
|
37
|
+
// },
|
|
38
|
+
//
|
|
39
|
+
// async "compare array of objects"() {
|
|
40
|
+
// const arr1 = [{ foo: "bar" }, { baz: 123 }, { qux: true }]
|
|
41
|
+
// const arr2 = [{ foo: "bar" }, { baz: 123 }, { qux: true }]
|
|
42
|
+
// const arr3 = [{ foo: "bar" }, { baz: 123 }, { qux: false }]
|
|
43
|
+
// expect(deepEqual(arr1, arr2)).equals(true)
|
|
44
|
+
// expect(deepEqual(arr1, arr3)).equals(false)
|
|
45
|
+
// },
|
|
46
|
+
//
|
|
47
|
+
// async "compare null and undefined"() {
|
|
48
|
+
// expect(deepEqual(null, null)).equals(true)
|
|
49
|
+
// expect(deepEqual(undefined, undefined)).equals(true)
|
|
50
|
+
// expect(deepEqual(null, undefined)).equals(false)
|
|
51
|
+
// },
|
|
52
|
+
//
|
|
53
|
+
// async "compare with nested arrays"() {
|
|
54
|
+
// const obj1 = { foo: "bar", array: [1, 2, [3, 4]] }
|
|
55
|
+
// const obj2 = { foo: "bar", array: [1, 2, [3, 4]] }
|
|
56
|
+
// const obj3 = { foo: "bar", array: [1, 2, [3, 5]] }
|
|
57
|
+
// expect(deepEqual(obj1, obj2)).equals(true)
|
|
58
|
+
// expect(deepEqual(obj1, obj3)).equals(false)
|
|
59
|
+
// },
|
|
60
|
+
//
|
|
61
|
+
// async "circularity is forbidden"() {
|
|
62
|
+
// const obj1 = {alpha: 1} as any
|
|
63
|
+
// const obj2 = {alpha: 1} as any
|
|
64
|
+
// obj1.bravo = obj1
|
|
65
|
+
// obj2.bravo = obj2
|
|
66
|
+
// expect(() => deepEqual(obj1, obj2)).throws()
|
|
67
|
+
// },
|
|
68
|
+
//
|
|
69
|
+
// async "duplicate references are allowed"() {
|
|
70
|
+
// const dupe = {a: 123}
|
|
71
|
+
// const obj1 = {alpha: 1, dupe}
|
|
72
|
+
// const obj2 = {alpha: 1, dupe}
|
|
73
|
+
// const obj3 = {alpha: 1, dupe: {a: 0}}
|
|
74
|
+
// expect(deepEqual(obj1, obj2)).equals(true)
|
|
75
|
+
// expect(deepEqual(obj1, obj3)).equals(false)
|
|
76
|
+
// },
|
|
77
|
+
//
|
|
78
|
+
// "maps and sets": {
|
|
79
|
+
// async "compare maps"() {
|
|
80
|
+
// const map1 = new Map([['key1', 'value1'], ['key2', 'value2']])
|
|
81
|
+
// const map2 = new Map([['key1', 'value1'], ['key2', 'value2']])
|
|
82
|
+
// const map3 = new Map([['key1', 'value1'], ['key2', 'value3']])
|
|
83
|
+
// expect(deepEqual(map1, map2)).equals(true)
|
|
84
|
+
// expect(deepEqual(map1, map3)).equals(false)
|
|
85
|
+
// },
|
|
86
|
+
//
|
|
87
|
+
// async "compare sets"() {
|
|
88
|
+
// const set1 = new Set([1, 2, 3])
|
|
89
|
+
// const set2 = new Set([1, 2, 3])
|
|
90
|
+
// const set3 = new Set([1, 2, 4])
|
|
91
|
+
// expect(deepEqual(set1, set2)).equals(true)
|
|
92
|
+
// expect(deepEqual(set1, set3)).equals(false)
|
|
93
|
+
// },
|
|
94
|
+
//
|
|
95
|
+
// async "compare nested maps and sets"() {
|
|
96
|
+
// const obj1 = { map: new Map([['key', new Set([1, 2, 3])]]) }
|
|
97
|
+
// const obj2 = { map: new Map([['key', new Set([1, 2, 3])]]) }
|
|
98
|
+
// const obj3 = { map: new Map([['key', new Set([1, 2, 4])]]) }
|
|
99
|
+
// expect(deepEqual(obj1, obj2)).equals(true)
|
|
100
|
+
// expect(deepEqual(obj1, obj3)).equals(false)
|
|
101
|
+
// },
|
|
102
|
+
//
|
|
103
|
+
// async "compare complex structures"() {
|
|
104
|
+
// const map1 = new Map([['set', new Set([{ a: 1 }, { b: 2 }])]])
|
|
105
|
+
// const map2 = new Map([['set', new Set([{ a: 1 }, { b: 2 }])]])
|
|
106
|
+
// const map3 = new Map([['set', new Set([{ a: 1 }, { b: 3 }])]])
|
|
107
|
+
// expect(deepEqual(map1, map2)).equals(true)
|
|
108
|
+
// expect(deepEqual(map1, map3)).equals(false)
|
|
109
|
+
// },
|
|
110
|
+
//
|
|
111
|
+
// async "compare edge cases"() {
|
|
112
|
+
// const emptyMap1 = new Map()
|
|
113
|
+
// const emptyMap2 = new Map()
|
|
114
|
+
// const emptySet1 = new Set()
|
|
115
|
+
// const emptySet2 = new Set()
|
|
116
|
+
// const mixedMap1 = new Map([['b', 2], ['a', 1]])
|
|
117
|
+
// const mixedMap2 = new Map([['a', 1], ['b', 2]])
|
|
118
|
+
// expect(deepEqual(emptyMap1, emptyMap2)).equals(true)
|
|
119
|
+
// expect(deepEqual(emptySet1, emptySet2)).equals(true)
|
|
120
|
+
// expect(deepEqual(mixedMap1, mixedMap2)).equals(true)
|
|
121
|
+
// },
|
|
122
|
+
// },
|
|
123
|
+
// }
|
|
124
|
+
//
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
import {is} from "../../is.js"
|
|
3
|
+
|
|
4
|
+
export const deepEqual = (alpha: any, bravo: any): boolean => {
|
|
5
|
+
|
|
6
|
+
function recurse(alpha: any, bravo: any, parents: object[]) {
|
|
7
|
+
if (!is.object(alpha) || !is.object(bravo))
|
|
8
|
+
return alpha === bravo
|
|
9
|
+
|
|
10
|
+
if (parents.includes(alpha))
|
|
11
|
+
throw new Error(`forbidden circularity detected in deep equal comparison`)
|
|
12
|
+
|
|
13
|
+
const newParents = [...parents, alpha]
|
|
14
|
+
|
|
15
|
+
if (alpha instanceof Map && bravo instanceof Map) {
|
|
16
|
+
if (alpha.size !== bravo.size)
|
|
17
|
+
return false
|
|
18
|
+
for (const [key, val] of alpha)
|
|
19
|
+
if (!bravo.has(key) || !recurse(val, bravo.get(key), newParents))
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
22
|
+
else if (alpha instanceof Set && bravo instanceof Set) {
|
|
23
|
+
if (alpha.size !== bravo.size)
|
|
24
|
+
return false
|
|
25
|
+
for (const item of alpha)
|
|
26
|
+
if (!Array.from(bravo).some(bItem => recurse(item, bItem, newParents)))
|
|
27
|
+
return false
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
const keys1 = Object.keys(alpha)
|
|
31
|
+
const keys2 = Object.keys(bravo)
|
|
32
|
+
|
|
33
|
+
if (keys1.length !== keys2.length)
|
|
34
|
+
return false
|
|
35
|
+
|
|
36
|
+
for (const key of keys1) {
|
|
37
|
+
if (!keys2.includes(key))
|
|
38
|
+
return false
|
|
39
|
+
if (!recurse(alpha[key], bravo[key], newParents))
|
|
40
|
+
return false
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return true
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return recurse(alpha, bravo, [])
|
|
48
|
+
}
|
|
49
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
import {is} from "../../is.js"
|
|
3
|
+
|
|
4
|
+
export function deepFreeze<X>(item: X): X {
|
|
5
|
+
|
|
6
|
+
function recurse(x: X, parents: object[]) {
|
|
7
|
+
if (!is.object(x) || parents.includes(x))
|
|
8
|
+
return x
|
|
9
|
+
|
|
10
|
+
const newParents = [...parents, x]
|
|
11
|
+
|
|
12
|
+
if (x instanceof Map)
|
|
13
|
+
for (const arr of x.entries())
|
|
14
|
+
for (const y of arr)
|
|
15
|
+
recurse(y, newParents)
|
|
16
|
+
|
|
17
|
+
else if (x instanceof Set)
|
|
18
|
+
for (const y of x)
|
|
19
|
+
recurse(y, newParents)
|
|
20
|
+
|
|
21
|
+
else if (Array.isArray(x))
|
|
22
|
+
for (const y of x)
|
|
23
|
+
recurse(y, newParents)
|
|
24
|
+
|
|
25
|
+
else
|
|
26
|
+
for (const y of Object.values(x))
|
|
27
|
+
recurse(y, newParents)
|
|
28
|
+
|
|
29
|
+
return Object.freeze(x)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return recurse(item, [])
|
|
33
|
+
}
|
|
34
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
|
|
2
|
+
/** a promise which can be resolved from the outside */
|
|
3
|
+
export type DeferredPromise<R> = {
|
|
4
|
+
promise: Promise<R>
|
|
5
|
+
resolve: (result: R) => void
|
|
6
|
+
reject: (reason: any) => void
|
|
7
|
+
|
|
8
|
+
/** ties the fate of this deferred promise to the outcome of the provided outsidePromise */
|
|
9
|
+
entangle: (outsidePromise: Promise<R>) => Promise<R>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** returns a deferred promise with exposed resolve and reject fns */
|
|
13
|
+
export function deferPromise<R>(): DeferredPromise<R> {
|
|
14
|
+
let resolve!: (result: R) => void
|
|
15
|
+
let reject!: (reason: any) => void
|
|
16
|
+
|
|
17
|
+
const promise = new Promise<R>((res, rej) => {
|
|
18
|
+
resolve = res
|
|
19
|
+
reject = rej
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
function entangle(outside: Promise<R>) {
|
|
23
|
+
outside.then(resolve).catch(reject)
|
|
24
|
+
return promise
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {promise, resolve, reject, entangle}
|
|
28
|
+
}
|
|
29
|
+
|
package/s/hat.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
export class Hat<T> {
|
|
3
|
+
#content: T[] = []
|
|
4
|
+
|
|
5
|
+
constructor(public items: T[]) {
|
|
6
|
+
this.#content = [...items]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
pull() {
|
|
10
|
+
if (this.#content.length === 0)
|
|
11
|
+
this.#content = [...this.items]
|
|
12
|
+
const index = Math.floor(Math.random() * this.#content.length)
|
|
13
|
+
const [item] = this.#content.splice(index, 1)
|
|
14
|
+
return item
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
package/s/index.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
export * from "./data/barname/index.js"
|
|
3
|
+
export * from "./data/base58.js"
|
|
4
|
+
export * from "./data/base64.js"
|
|
5
|
+
export * from "./data/base64url.js"
|
|
6
|
+
export * from "./data/bytes.js"
|
|
7
|
+
export * from "./data/hex.js"
|
|
8
|
+
export * from "./data/txt.js"
|
|
9
|
+
|
|
10
|
+
export * from "./concurrent.js"
|
|
11
|
+
export * from "./deadline.js"
|
|
12
|
+
export * from "./dedupe.js"
|
|
13
|
+
export * from "./defer-promise.js"
|
|
14
|
+
export * from "./escape-regex.js"
|
|
15
|
+
export * from "./hat.js"
|
|
16
|
+
export * from "./is.js"
|
|
17
|
+
export * from "./map-g.js"
|
|
18
|
+
export * from "./nap.js"
|
|
19
|
+
export * from "./ob.js"
|
|
20
|
+
export * from "./pipe.js"
|
|
21
|
+
export * from "./pubsub.js"
|
|
22
|
+
export * from "./trash.js"
|
|
23
|
+
|
package/s/is.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
export const is = {
|
|
3
|
+
available: <X>(x: X): x is NonNullable<X> =>
|
|
4
|
+
x !== undefined && x !== null,
|
|
5
|
+
|
|
6
|
+
unavailable: (x: any): x is (undefined | null) =>
|
|
7
|
+
x === undefined || x === null,
|
|
8
|
+
|
|
9
|
+
boolean: (x: any): x is boolean =>
|
|
10
|
+
typeof x === "boolean",
|
|
11
|
+
|
|
12
|
+
number: (x: any): x is number =>
|
|
13
|
+
typeof x === "number",
|
|
14
|
+
|
|
15
|
+
string: (x: any): x is string =>
|
|
16
|
+
typeof x === "string",
|
|
17
|
+
|
|
18
|
+
bigint: (x: any): x is bigint =>
|
|
19
|
+
typeof x === "bigint",
|
|
20
|
+
|
|
21
|
+
object: <X>(x: X): x is object & NonNullable<X> =>
|
|
22
|
+
typeof x === "object" && x !== null,
|
|
23
|
+
|
|
24
|
+
array: (x: any | any[]): x is any[] =>
|
|
25
|
+
Array.isArray(x),
|
|
26
|
+
}
|
|
27
|
+
|
package/s/map-g.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
|
|
2
|
+
/** js map, but with handy methods like `require` and `guarantee` */
|
|
3
|
+
export class MapG<K, V> extends Map<K, V> {
|
|
4
|
+
static require<K, V>(map: Map<K, V>, key: K) {
|
|
5
|
+
const value = map.get(key)
|
|
6
|
+
if (value === undefined)
|
|
7
|
+
throw new Error(`required key not found: "${key}"`)
|
|
8
|
+
return value
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static guarantee<K, V>(map: Map<K, V>, key: K, make: () => V) {
|
|
12
|
+
let value = map.get(key)
|
|
13
|
+
|
|
14
|
+
if (value === undefined) {
|
|
15
|
+
value = make()
|
|
16
|
+
map.set(key, value)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return value
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
array() {
|
|
23
|
+
return [...this]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
require(key: K) {
|
|
27
|
+
return MapG.require(this, key)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
guarantee(key: K, make: () => V) {
|
|
31
|
+
return MapG.guarantee(this, key, make)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type Identifiable<Id = any> = {id: Id}
|
|
36
|
+
|
|
37
|
+
/** js map but for things that have an `id` field */
|
|
38
|
+
export class PoolG<V extends Identifiable> extends MapG<V["id"], V> {
|
|
39
|
+
got(value: V) {
|
|
40
|
+
return this.has(value.id)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
add(value: V) {
|
|
44
|
+
this.set(value.id, value)
|
|
45
|
+
return value
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
remove(value: V) {
|
|
49
|
+
return this.delete(value.id)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
package/s/nap.ts
ADDED
package/s/ob.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
|
|
2
|
+
export function ob<Ob extends object>(o: Ob) {
|
|
3
|
+
return {
|
|
4
|
+
map: <Value>(transform: ObTransform<Ob, Value>) => (
|
|
5
|
+
obMap(o, transform)
|
|
6
|
+
),
|
|
7
|
+
filter: (predicate: ObPredicate<Ob>) => (
|
|
8
|
+
obFilter(o, predicate)
|
|
9
|
+
),
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
////////////
|
|
14
|
+
////////////
|
|
15
|
+
|
|
16
|
+
ob.pipe = Object.freeze({
|
|
17
|
+
map: <O extends {}, Value>(
|
|
18
|
+
transform: (value: O[keyof O], key: keyof O) => Value,
|
|
19
|
+
) => (
|
|
20
|
+
(o: O) => obMap(o, transform)
|
|
21
|
+
),
|
|
22
|
+
filter: <O extends {}>(
|
|
23
|
+
transform: (value: O[keyof O], key: keyof O) => boolean,
|
|
24
|
+
) => (
|
|
25
|
+
(o: O) => obFilter(o, transform) as {[key: string]: O[keyof O]}
|
|
26
|
+
),
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
////////////
|
|
30
|
+
////////////
|
|
31
|
+
|
|
32
|
+
export type ObTransform<Ob extends object, Value> = (
|
|
33
|
+
(value: Ob[keyof Ob], key: keyof Ob) => Value
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
export type ObPredicate<Ob extends object> = (
|
|
37
|
+
(value: Ob[keyof Ob], key: keyof Ob) => boolean
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
////////////
|
|
41
|
+
////////////
|
|
42
|
+
|
|
43
|
+
const obMap = <Ob extends object, Value>(
|
|
44
|
+
o: Ob,
|
|
45
|
+
transform: ObTransform<Ob, Value>,
|
|
46
|
+
) => {
|
|
47
|
+
|
|
48
|
+
return Object.fromEntries(
|
|
49
|
+
Object.entries(o).map(
|
|
50
|
+
([key, value]: any) => [key, transform(value, key)]
|
|
51
|
+
)
|
|
52
|
+
) as {[P in keyof Ob]: Value}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const obFilter = <Ob extends object>(
|
|
56
|
+
o: Ob,
|
|
57
|
+
predicate: ObPredicate<Ob>,
|
|
58
|
+
) => {
|
|
59
|
+
|
|
60
|
+
return Object.fromEntries(
|
|
61
|
+
Object.entries(o).filter(
|
|
62
|
+
([key, value]: any) => predicate(value, key)
|
|
63
|
+
)
|
|
64
|
+
) as {[P in keyof Ob]?: Ob[keyof Ob]}
|
|
65
|
+
}
|
|
66
|
+
|
package/s/pipe.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
export type PipeFun<I, O> = (input: I) => O
|
|
3
|
+
|
|
4
|
+
export class Pipe<I> {
|
|
5
|
+
|
|
6
|
+
static with<I>(input: I) {
|
|
7
|
+
return new this(input)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
#input: I
|
|
11
|
+
|
|
12
|
+
constructor(input: I) {
|
|
13
|
+
this.#input = input
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
to<O>(fun: PipeFun<I, O>) {
|
|
17
|
+
return new Pipe(fun(this.#input))
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
done() {
|
|
21
|
+
return this.#input
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
package/s/pubsub.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
|
|
2
|
+
import {deferPromise} from "./defer-promise.js"
|
|
3
|
+
|
|
4
|
+
export type Listener<A extends any[]> = (...a: A) => (void | Promise<void>)
|
|
5
|
+
|
|
6
|
+
export interface Xub<A extends any[] = []> {
|
|
7
|
+
pub(...a: A): Promise<void>
|
|
8
|
+
sub(fn: Listener<A>): () => void
|
|
9
|
+
once(): Promise<A>
|
|
10
|
+
clear(): void
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface Sub<A extends any[] = []> extends Xub<A> {
|
|
14
|
+
(fn: Listener<A>): () => void
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface Pub<A extends any[] = []> {
|
|
18
|
+
(...a: A): Promise<void>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function xub<A extends any[] = []>() {
|
|
22
|
+
const set = new Set<Listener<A>>()
|
|
23
|
+
|
|
24
|
+
function sub(fn: Listener<A>) {
|
|
25
|
+
set.add(fn)
|
|
26
|
+
return () => { set.delete(fn) }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function pub(...a: A) {
|
|
30
|
+
await Promise.all([...set].map(fn => fn(...a)))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function once() {
|
|
34
|
+
const {promise, resolve} = deferPromise<A>()
|
|
35
|
+
const unsubscribe = sub((...a) => {
|
|
36
|
+
resolve(a)
|
|
37
|
+
unsubscribe()
|
|
38
|
+
})
|
|
39
|
+
return promise
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function clear() {
|
|
43
|
+
set.clear()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
sub.pub = pub
|
|
47
|
+
sub.sub = sub
|
|
48
|
+
sub.once = once
|
|
49
|
+
sub.clear = clear
|
|
50
|
+
|
|
51
|
+
pub.pub = pub
|
|
52
|
+
pub.sub = sub
|
|
53
|
+
pub.once = once
|
|
54
|
+
pub.clear = clear
|
|
55
|
+
|
|
56
|
+
return [pub, sub] as [Pub<A>, Sub<A>]
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** create a subscriber fn that can be published to */
|
|
60
|
+
export function sub<A extends any[] = []>(): Sub<A> {
|
|
61
|
+
return xub<A>()[1]
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** create a publisher fn that can be subscribed to */
|
|
65
|
+
export function pub<A extends any[] = []>(): Pub<A> {
|
|
66
|
+
return xub<A>()[0]
|
|
67
|
+
}
|
|
68
|
+
|
package/s/trash.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
/** a trashcan where you can collect disposer fns, and dispose them all at once */
|
|
3
|
+
export class Trash {
|
|
4
|
+
#fns: (() => void)[] = []
|
|
5
|
+
|
|
6
|
+
/** add a disposer fn to the trashcan */
|
|
7
|
+
add(...fns: (() => void)[]) {
|
|
8
|
+
this.#fns.push(...fns)
|
|
9
|
+
return this
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** add a disposable object to the trashcan, and return the object */
|
|
13
|
+
disposable<X extends {dispose: () => void}>(x: X) {
|
|
14
|
+
return this.bag(x, () => x.dispose())
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** add an item's disposer fn, and return the item */
|
|
18
|
+
bag<X>(x: X, fn: (x: X) => void) {
|
|
19
|
+
this.add(() => fn(x))
|
|
20
|
+
return x
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** dispose of everything in the trashcan */
|
|
24
|
+
dispose() {
|
|
25
|
+
for (const fn of this.#fns.reverse())
|
|
26
|
+
fn()
|
|
27
|
+
this.#fns = []
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function clone<T>(data: T, refs?: Set<any>): T;
|
package/x/clone/clone.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function clone(data, refs = new Set()) {
|
|
2
|
+
if (refs.has(data))
|
|
3
|
+
throw new Error("cannot clone circular reference");
|
|
4
|
+
let copy = undefined;
|
|
5
|
+
if (typeof data === "function" || (data !== null && typeof data === "object")) {
|
|
6
|
+
refs.add(data);
|
|
7
|
+
if (Array.isArray(data))
|
|
8
|
+
copy = data.map(d => clone(d, new Set(refs)));
|
|
9
|
+
else if (data.constructor === Object)
|
|
10
|
+
copy = Object.fromEntries(Object.entries(data)
|
|
11
|
+
.map(([key, d]) => [key, clone(d, new Set(refs))]));
|
|
12
|
+
else if (data instanceof Map)
|
|
13
|
+
copy = new Map(Array.from(data, ([key, val]) => [key, clone(val, new Set(refs))]));
|
|
14
|
+
else if (data instanceof Set)
|
|
15
|
+
copy = new Set(Array.from(data, val => clone(val, new Set(refs))));
|
|
16
|
+
else if (data instanceof Date)
|
|
17
|
+
copy = new Date(data.getTime());
|
|
18
|
+
else
|
|
19
|
+
copy = data;
|
|
20
|
+
refs.delete(data); // Remove current data from refs once we're done with this branch of the object tree
|
|
21
|
+
}
|
|
22
|
+
else
|
|
23
|
+
copy = data;
|
|
24
|
+
return copy;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=clone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone.js","sourceRoot":"","sources":["../../s/clone/clone.ts"],"names":[],"mappings":"AACA,MAAM,UAAU,KAAK,CAAI,IAAO,EAAE,OAAO,IAAI,GAAG,EAAO;IAEtD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IAEnD,IAAI,IAAI,GAAG,SAAc,CAAA;IAEzB,IAAI,OAAO,IAAI,KAAK,UAAU,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,EAAE,CAAC;QAC/E,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAEd,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YACtB,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAM,CAAA;aAE9C,IAAI,IAAI,CAAC,WAAW,KAAK,MAAM;YACnC,IAAI,GAAG,MAAM,CAAC,WAAW,CACxB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;iBAClB,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAC9C,CAAA;aAEF,IAAI,IAAI,YAAY,GAAG;YAC3B,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAM,CAAA;aAEnF,IAAI,IAAI,YAAY,GAAG;YAC3B,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAM,CAAA;aAEnE,IAAI,IAAI,YAAY,IAAI;YAC5B,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAM,CAAA;;YAGpC,IAAI,GAAG,IAAI,CAAA;QAEZ,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA,CAAC,oFAAoF;IACvG,CAAC;;QAGA,IAAI,GAAG,IAAI,CAAA;IAEZ,OAAO,IAAI,CAAA;AACZ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|