@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.
Files changed (175) hide show
  1. package/license +23 -0
  2. package/package.json +40 -0
  3. package/readme.md +85 -0
  4. package/s/clone/clone.test.ts +124 -0
  5. package/s/clone/clone.ts +41 -0
  6. package/s/concurrent.ts +12 -0
  7. package/s/data/anka.ts +66 -0
  8. package/s/data/barname/badge.ts +78 -0
  9. package/s/data/barname/barname.ts +62 -0
  10. package/s/data/barname/demo.ts +49 -0
  11. package/s/data/barname/index.ts +4 -0
  12. package/s/data/barname/utils/prefixes.ts +20 -0
  13. package/s/data/barname/utils/suffixes.ts +20 -0
  14. package/s/data/base58.ts +65 -0
  15. package/s/data/base64.ts +22 -0
  16. package/s/data/base64url.ts +27 -0
  17. package/s/data/bytes.ts +7 -0
  18. package/s/data/hex.ts +35 -0
  19. package/s/data/nomen/demo.ts +8 -0
  20. package/s/data/nomen/grammar.ts +41 -0
  21. package/s/data/nomen/index.ts +5 -0
  22. package/s/data/nomen/nomen.ts +34 -0
  23. package/s/data/nomen/presets/falrysk.ts +112 -0
  24. package/s/data/nomen/types.ts +9 -0
  25. package/s/data/txt.ts +11 -0
  26. package/s/deadline.ts +24 -0
  27. package/s/debounce/debounce.test.ts +73 -0
  28. package/s/debounce/debounce.ts +54 -0
  29. package/s/debounce/types.ts +8 -0
  30. package/s/dedupe.ts +5 -0
  31. package/s/deep/deep.test.ts +8 -0
  32. package/s/deep/deep.ts +11 -0
  33. package/s/deep/parts/equal.test.ts +124 -0
  34. package/s/deep/parts/equal.ts +49 -0
  35. package/s/deep/parts/freeze.ts +34 -0
  36. package/s/defer-promise.ts +29 -0
  37. package/s/escape-regex.ts +5 -0
  38. package/s/hat.ts +17 -0
  39. package/s/index.ts +23 -0
  40. package/s/is.ts +27 -0
  41. package/s/map-g.ts +52 -0
  42. package/s/nap.ts +5 -0
  43. package/s/ob.ts +66 -0
  44. package/s/pipe.ts +24 -0
  45. package/s/pubsub.ts +68 -0
  46. package/s/trash.ts +30 -0
  47. package/x/clone/clone.d.ts +1 -0
  48. package/x/clone/clone.js +26 -0
  49. package/x/clone/clone.js.map +1 -0
  50. package/x/clone/clone.test.d.ts +1 -0
  51. package/x/clone/clone.test.js +125 -0
  52. package/x/clone/clone.test.js.map +1 -0
  53. package/x/concurrent.d.ts +1 -0
  54. package/x/concurrent.js +7 -0
  55. package/x/concurrent.js.map +1 -0
  56. package/x/data/anka.d.ts +5 -0
  57. package/x/data/anka.js +53 -0
  58. package/x/data/anka.js.map +1 -0
  59. package/x/data/barname/badge.d.ts +25 -0
  60. package/x/data/barname/badge.js +64 -0
  61. package/x/data/barname/badge.js.map +1 -0
  62. package/x/data/barname/barname.d.ts +7 -0
  63. package/x/data/barname/barname.js +49 -0
  64. package/x/data/barname/barname.js.map +1 -0
  65. package/x/data/barname/demo.d.ts +1 -0
  66. package/x/data/barname/demo.js +45 -0
  67. package/x/data/barname/demo.js.map +1 -0
  68. package/x/data/barname/index.d.ts +2 -0
  69. package/x/data/barname/index.js +3 -0
  70. package/x/data/barname/index.js.map +1 -0
  71. package/x/data/barname/utils/prefixes.d.ts +1 -0
  72. package/x/data/barname/utils/prefixes.js +19 -0
  73. package/x/data/barname/utils/prefixes.js.map +1 -0
  74. package/x/data/barname/utils/suffixes.d.ts +1 -0
  75. package/x/data/barname/utils/suffixes.js +19 -0
  76. package/x/data/barname/utils/suffixes.js.map +1 -0
  77. package/x/data/base58.d.ts +5 -0
  78. package/x/data/base58.js +58 -0
  79. package/x/data/base58.js.map +1 -0
  80. package/x/data/base64.d.ts +5 -0
  81. package/x/data/base64.js +17 -0
  82. package/x/data/base64.js.map +1 -0
  83. package/x/data/base64url.d.ts +5 -0
  84. package/x/data/base64url.js +22 -0
  85. package/x/data/base64url.js.map +1 -0
  86. package/x/data/bytes.d.ts +3 -0
  87. package/x/data/bytes.js +6 -0
  88. package/x/data/bytes.js.map +1 -0
  89. package/x/data/hex.d.ts +6 -0
  90. package/x/data/hex.js +30 -0
  91. package/x/data/hex.js.map +1 -0
  92. package/x/data/nomen/demo.d.ts +1 -0
  93. package/x/data/nomen/demo.js +5 -0
  94. package/x/data/nomen/demo.js.map +1 -0
  95. package/x/data/nomen/grammar.d.ts +11 -0
  96. package/x/data/nomen/grammar.js +32 -0
  97. package/x/data/nomen/grammar.js.map +1 -0
  98. package/x/data/nomen/index.d.ts +3 -0
  99. package/x/data/nomen/index.js +4 -0
  100. package/x/data/nomen/index.js.map +1 -0
  101. package/x/data/nomen/nomen.d.ts +11 -0
  102. package/x/data/nomen/nomen.js +29 -0
  103. package/x/data/nomen/nomen.js.map +1 -0
  104. package/x/data/nomen/presets/falrysk.d.ts +5 -0
  105. package/x/data/nomen/presets/falrysk.js +99 -0
  106. package/x/data/nomen/presets/falrysk.js.map +1 -0
  107. package/x/data/nomen/types.d.ts +6 -0
  108. package/x/data/nomen/types.js +2 -0
  109. package/x/data/nomen/types.js.map +1 -0
  110. package/x/data/txt.d.ts +4 -0
  111. package/x/data/txt.js +9 -0
  112. package/x/data/txt.js.map +1 -0
  113. package/x/deadline.d.ts +6 -0
  114. package/x/deadline.js +17 -0
  115. package/x/deadline.js.map +1 -0
  116. package/x/debounce/debounce.d.ts +2 -0
  117. package/x/debounce/debounce.js +37 -0
  118. package/x/debounce/debounce.js.map +1 -0
  119. package/x/debounce/debounce.test.d.ts +1 -0
  120. package/x/debounce/debounce.test.js +75 -0
  121. package/x/debounce/debounce.test.js.map +1 -0
  122. package/x/debounce/types.d.ts +2 -0
  123. package/x/debounce/types.js +2 -0
  124. package/x/debounce/types.js.map +1 -0
  125. package/x/dedupe.d.ts +1 -0
  126. package/x/dedupe.js +4 -0
  127. package/x/dedupe.js.map +1 -0
  128. package/x/deep/deep.d.ts +7 -0
  129. package/x/deep/deep.js +9 -0
  130. package/x/deep/deep.js.map +1 -0
  131. package/x/deep/deep.test.d.ts +1 -0
  132. package/x/deep/deep.test.js +10 -0
  133. package/x/deep/deep.test.js.map +1 -0
  134. package/x/deep/parts/equal.d.ts +1 -0
  135. package/x/deep/parts/equal.js +39 -0
  136. package/x/deep/parts/equal.js.map +1 -0
  137. package/x/deep/parts/equal.test.d.ts +1 -0
  138. package/x/deep/parts/equal.test.js +126 -0
  139. package/x/deep/parts/equal.test.js.map +1 -0
  140. package/x/deep/parts/freeze.d.ts +1 -0
  141. package/x/deep/parts/freeze.js +24 -0
  142. package/x/deep/parts/freeze.js.map +1 -0
  143. package/x/defer-promise.d.ts +10 -0
  144. package/x/defer-promise.js +15 -0
  145. package/x/defer-promise.js.map +1 -0
  146. package/x/escape-regex.d.ts +1 -0
  147. package/x/escape-regex.js +4 -0
  148. package/x/escape-regex.js.map +1 -0
  149. package/x/hat.d.ts +6 -0
  150. package/x/hat.js +16 -0
  151. package/x/hat.js.map +1 -0
  152. package/x/index.d.ts +20 -0
  153. package/x/index.js +21 -0
  154. package/x/index.js.map +1 -0
  155. package/x/is.d.ts +10 -0
  156. package/x/is.js +11 -0
  157. package/x/is.js.map +1 -0
  158. package/x/map-g.d.ts +17 -0
  159. package/x/map-g.js +40 -0
  160. package/x/map-g.js.map +1 -0
  161. package/x/nap.d.ts +1 -0
  162. package/x/nap.js +2 -0
  163. package/x/nap.js.map +1 -0
  164. package/x/ob.d.ts +14 -0
  165. package/x/ob.js +21 -0
  166. package/x/ob.js.map +1 -0
  167. package/x/pipe.d.ts +8 -0
  168. package/x/pipe.js +16 -0
  169. package/x/pipe.js.map +1 -0
  170. package/x/pubsub.d.ts +18 -0
  171. package/x/pubsub.js +40 -0
  172. package/x/pubsub.js.map +1 -0
  173. package/x/trash.d.ts +14 -0
  174. package/x/trash.js +25 -0
  175. 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
+
@@ -0,0 +1,5 @@
1
+
2
+ export function escapeRegex(subject: string) {
3
+ return subject.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
4
+ }
5
+
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
@@ -0,0 +1,5 @@
1
+
2
+ export const nap = (milliseconds: number = 0) => (
3
+ new Promise<void>(resolve => setTimeout(resolve, milliseconds))
4
+ )
5
+
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;
@@ -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 {};