mutts 1.0.9 → 1.0.11

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 (206) hide show
  1. package/README.md +60 -35
  2. package/dist/browser.cjs +1333 -1760
  3. package/dist/browser.cjs.map +1 -1
  4. package/dist/browser.d.ts +2 -1392
  5. package/dist/browser.dev.cjs +114 -0
  6. package/dist/browser.dev.cjs.map +1 -0
  7. package/dist/browser.dev.d.ts +2 -0
  8. package/dist/browser.dev.esm.js +5 -0
  9. package/dist/browser.dev.esm.js.map +1 -0
  10. package/dist/browser.esm.js +18 -97
  11. package/dist/browser.esm.js.map +1 -1
  12. package/dist/chunks/{async-browser-lvzLOCgk.cjs → async-browser-Dgr5CreQ.cjs} +16 -95
  13. package/dist/chunks/async-browser-Dgr5CreQ.cjs.map +1 -0
  14. package/dist/chunks/{async-node-C3DeIb0y.cjs → async-node-3PrbVAbB.cjs} +3 -1
  15. package/dist/chunks/async-node-3PrbVAbB.cjs.map +1 -0
  16. package/dist/chunks/index-Sf74wXTV.esm.js +2577 -0
  17. package/dist/chunks/index-Sf74wXTV.esm.js.map +1 -0
  18. package/dist/chunks/node-Bo7WU5S2.esm.js +96 -0
  19. package/dist/chunks/node-Bo7WU5S2.esm.js.map +1 -0
  20. package/dist/chunks/{index-VTO-b2vR.cjs → proxy-Cc79Lrzj.cjs} +2593 -3216
  21. package/dist/chunks/proxy-Cc79Lrzj.cjs.map +1 -0
  22. package/dist/chunks/{index-CtA2AWl3.esm.js → proxy-D2C49sXH.esm.js} +2570 -3174
  23. package/dist/chunks/proxy-D2C49sXH.esm.js.map +1 -0
  24. package/dist/debug.cjs +987 -28
  25. package/dist/debug.cjs.map +1 -1
  26. package/dist/debug.d.ts +37 -38
  27. package/dist/debug.esm.js +963 -1
  28. package/dist/debug.esm.js.map +1 -1
  29. package/dist/devtools/manifest.json +1 -1
  30. package/dist/devtools/panel.html +1 -1
  31. package/dist/devtools/panel.js +107 -94
  32. package/dist/devtools/panel.js.map +1 -1
  33. package/dist/index.d.ts +1322 -1
  34. package/dist/mutts.umd.js +6647 -1
  35. package/dist/mutts.umd.js.map +1 -1
  36. package/dist/mutts.umd.min.js +1 -1
  37. package/dist/mutts.umd.min.js.map +1 -1
  38. package/dist/node.cjs +69 -63
  39. package/dist/node.cjs.map +1 -1
  40. package/dist/node.d.ts +2 -2
  41. package/dist/node.dev.cjs +114 -0
  42. package/dist/node.dev.cjs.map +1 -0
  43. package/dist/node.dev.d.ts +2 -0
  44. package/dist/node.dev.esm.js +6 -0
  45. package/dist/node.dev.esm.js.map +1 -0
  46. package/dist/node.esm.js +4 -97
  47. package/dist/node.esm.js.map +1 -1
  48. package/dist/{types-DaHFfhlN.d.ts → types-Bx2PhORg.d.ts} +134 -88
  49. package/docs/ai/api-reference.md +11 -32
  50. package/docs/ai/manual.md +297 -239
  51. package/docs/reactive/advanced.md +318 -9
  52. package/docs/reactive/attend.md +2 -4
  53. package/docs/reactive/collections.md +22 -187
  54. package/docs/reactive/core.md +223 -131
  55. package/docs/reactive/debugging.md +119 -12
  56. package/docs/reactive/error-handling.md +10 -10
  57. package/docs/reactive/resource.md +125 -0
  58. package/docs/reactive.md +3 -4
  59. package/docs/utils.md +70 -0
  60. package/docs/zone.md +1 -1
  61. package/package.json +76 -38
  62. package/dist/chunks/async-browser-lvzLOCgk.cjs.map +0 -1
  63. package/dist/chunks/async-node-C3DeIb0y.cjs.map +0 -1
  64. package/dist/chunks/index-2vea86wD.esm.js +0 -3011
  65. package/dist/chunks/index-2vea86wD.esm.js.map +0 -1
  66. package/dist/chunks/index-CtA2AWl3.esm.js.map +0 -1
  67. package/dist/chunks/index-VTO-b2vR.cjs.map +0 -1
  68. package/dist/debug/debug.d.ts +0 -122
  69. package/dist/debug/debug.d.ts.map +0 -1
  70. package/dist/debug/index.d.ts +0 -4
  71. package/dist/debug/index.d.ts.map +0 -1
  72. package/dist/debug/lineage-panel.d.ts +0 -5
  73. package/dist/debug/lineage-panel.d.ts.map +0 -1
  74. package/dist/debug/lineage.d.ts +0 -79
  75. package/dist/debug/lineage.d.ts.map +0 -1
  76. package/dist/src/async/browser.d.ts +0 -2
  77. package/dist/src/async/browser.d.ts.map +0 -1
  78. package/dist/src/async/index.d.ts +0 -19
  79. package/dist/src/async/index.d.ts.map +0 -1
  80. package/dist/src/async/node.d.ts +0 -2
  81. package/dist/src/async/node.d.ts.map +0 -1
  82. package/dist/src/decorator.d.ts +0 -106
  83. package/dist/src/decorator.d.ts.map +0 -1
  84. package/dist/src/destroyable.d.ts +0 -87
  85. package/dist/src/destroyable.d.ts.map +0 -1
  86. package/dist/src/entry-browser.d.ts +0 -3
  87. package/dist/src/entry-browser.d.ts.map +0 -1
  88. package/dist/src/entry-node.d.ts +0 -3
  89. package/dist/src/entry-node.d.ts.map +0 -1
  90. package/dist/src/eventful.d.ts +0 -20
  91. package/dist/src/eventful.d.ts.map +0 -1
  92. package/dist/src/flavored.d.ts +0 -33
  93. package/dist/src/flavored.d.ts.map +0 -1
  94. package/dist/src/index.d.ts +0 -14
  95. package/dist/src/index.d.ts.map +0 -1
  96. package/dist/src/indexable.d.ts +0 -243
  97. package/dist/src/indexable.d.ts.map +0 -1
  98. package/dist/src/introspection.d.ts +0 -27
  99. package/dist/src/introspection.d.ts.map +0 -1
  100. package/dist/src/iterableWeak.d.ts +0 -53
  101. package/dist/src/iterableWeak.d.ts.map +0 -1
  102. package/dist/src/mixins.d.ts +0 -25
  103. package/dist/src/mixins.d.ts.map +0 -1
  104. package/dist/src/promiseChain.d.ts +0 -20
  105. package/dist/src/promiseChain.d.ts.map +0 -1
  106. package/dist/src/reactive/array.d.ts +0 -48
  107. package/dist/src/reactive/array.d.ts.map +0 -1
  108. package/dist/src/reactive/buffer.d.ts +0 -120
  109. package/dist/src/reactive/buffer.d.ts.map +0 -1
  110. package/dist/src/reactive/change.d.ts +0 -29
  111. package/dist/src/reactive/change.d.ts.map +0 -1
  112. package/dist/src/reactive/deep-touch.d.ts +0 -28
  113. package/dist/src/reactive/deep-touch.d.ts.map +0 -1
  114. package/dist/src/reactive/deep-watch-state.d.ts +0 -25
  115. package/dist/src/reactive/deep-watch-state.d.ts.map +0 -1
  116. package/dist/src/reactive/deep-watch.d.ts +0 -20
  117. package/dist/src/reactive/deep-watch.d.ts.map +0 -1
  118. package/dist/src/reactive/describe.d.ts +0 -12
  119. package/dist/src/reactive/describe.d.ts.map +0 -1
  120. package/dist/src/reactive/effect-context.d.ts +0 -34
  121. package/dist/src/reactive/effect-context.d.ts.map +0 -1
  122. package/dist/src/reactive/effects.d.ts +0 -164
  123. package/dist/src/reactive/effects.d.ts.map +0 -1
  124. package/dist/src/reactive/index.d.ts +0 -19
  125. package/dist/src/reactive/index.d.ts.map +0 -1
  126. package/dist/src/reactive/map.d.ts +0 -28
  127. package/dist/src/reactive/map.d.ts.map +0 -1
  128. package/dist/src/reactive/memoize.d.ts +0 -28
  129. package/dist/src/reactive/memoize.d.ts.map +0 -1
  130. package/dist/src/reactive/non-reactive-state.d.ts +0 -9
  131. package/dist/src/reactive/non-reactive-state.d.ts.map +0 -1
  132. package/dist/src/reactive/non-reactive.d.ts +0 -11
  133. package/dist/src/reactive/non-reactive.d.ts.map +0 -1
  134. package/dist/src/reactive/project.d.ts +0 -40
  135. package/dist/src/reactive/project.d.ts.map +0 -1
  136. package/dist/src/reactive/proxy-state.d.ts +0 -8
  137. package/dist/src/reactive/proxy-state.d.ts.map +0 -1
  138. package/dist/src/reactive/proxy.d.ts +0 -23
  139. package/dist/src/reactive/proxy.d.ts.map +0 -1
  140. package/dist/src/reactive/record.d.ts +0 -115
  141. package/dist/src/reactive/record.d.ts.map +0 -1
  142. package/dist/src/reactive/register.d.ts +0 -125
  143. package/dist/src/reactive/register.d.ts.map +0 -1
  144. package/dist/src/reactive/registry.d.ts +0 -21
  145. package/dist/src/reactive/registry.d.ts.map +0 -1
  146. package/dist/src/reactive/set.d.ts +0 -26
  147. package/dist/src/reactive/set.d.ts.map +0 -1
  148. package/dist/src/reactive/tracking.d.ts +0 -7
  149. package/dist/src/reactive/tracking.d.ts.map +0 -1
  150. package/dist/src/reactive/types.d.ts +0 -424
  151. package/dist/src/reactive/types.d.ts.map +0 -1
  152. package/dist/src/reactive/watch.d.ts +0 -48
  153. package/dist/src/reactive/watch.d.ts.map +0 -1
  154. package/dist/src/std-decorators.d.ts +0 -45
  155. package/dist/src/std-decorators.d.ts.map +0 -1
  156. package/dist/src/utils.d.ts +0 -49
  157. package/dist/src/utils.d.ts.map +0 -1
  158. package/dist/src/zone.d.ts +0 -40
  159. package/dist/src/zone.d.ts.map +0 -1
  160. package/docs/reactive/describe.md +0 -85
  161. package/docs/reactive/project.md +0 -93
  162. package/docs/reactive/scan.md +0 -293
  163. package/src/async/browser.ts +0 -323
  164. package/src/async/index.ts +0 -27
  165. package/src/async/node.ts +0 -92
  166. package/src/decorator.ts +0 -272
  167. package/src/destroyable.ts +0 -199
  168. package/src/entry-browser.ts +0 -5
  169. package/src/entry-node.ts +0 -5
  170. package/src/eventful.ts +0 -110
  171. package/src/flavored.ts +0 -106
  172. package/src/index.d.ts +0 -12
  173. package/src/index.ts +0 -64
  174. package/src/indexable.ts +0 -526
  175. package/src/introspection.ts +0 -59
  176. package/src/iterableWeak.ts +0 -233
  177. package/src/mixins.ts +0 -123
  178. package/src/promiseChain.ts +0 -110
  179. package/src/reactive/array.ts +0 -500
  180. package/src/reactive/buffer.ts +0 -328
  181. package/src/reactive/change.ts +0 -131
  182. package/src/reactive/deep-touch.ts +0 -273
  183. package/src/reactive/deep-watch-state.ts +0 -82
  184. package/src/reactive/deep-watch.ts +0 -171
  185. package/src/reactive/describe.ts +0 -39
  186. package/src/reactive/effect-context.ts +0 -83
  187. package/src/reactive/effects.ts +0 -1434
  188. package/src/reactive/index.ts +0 -72
  189. package/src/reactive/map.ts +0 -142
  190. package/src/reactive/memoize.ts +0 -186
  191. package/src/reactive/non-reactive-state.ts +0 -49
  192. package/src/reactive/non-reactive.ts +0 -43
  193. package/src/reactive/project.md +0 -107
  194. package/src/reactive/project.ts +0 -430
  195. package/src/reactive/proxy-state.ts +0 -27
  196. package/src/reactive/proxy.ts +0 -282
  197. package/src/reactive/record.ts +0 -181
  198. package/src/reactive/register.ts +0 -538
  199. package/src/reactive/registry.ts +0 -72
  200. package/src/reactive/set.ts +0 -117
  201. package/src/reactive/tracking.ts +0 -41
  202. package/src/reactive/types.ts +0 -520
  203. package/src/reactive/watch.ts +0 -180
  204. package/src/std-decorators.ts +0 -256
  205. package/src/utils.ts +0 -300
  206. package/src/zone.ts +0 -142
package/src/utils.ts DELETED
@@ -1,300 +0,0 @@
1
- type ElementTypes<T extends readonly unknown[]> = {
2
- [K in keyof T]: T[K] extends readonly (infer U)[] ? U : T[K]
3
- }
4
-
5
- /**
6
- * Combines multiple arrays into an array of tuples, stopping at the shortest array length
7
- * @param args - Arrays to zip together
8
- * @returns Array of tuples containing elements from each input array
9
- */
10
- export function zip<T extends (readonly unknown[])[]>(...args: T): ElementTypes<T>[] {
11
- if (!args.length) return []
12
- const minLength = Math.min(...args.map((arr) => arr.length))
13
- const result: ElementTypes<T>[] = []
14
-
15
- for (let i = 0; i < minLength; i++) {
16
- const tuple = args.map((arr) => arr[i]) as ElementTypes<T>
17
- result.push(tuple)
18
- }
19
-
20
- return result
21
- }
22
-
23
- /**
24
- * Checks if two arrays are strictly equal (shallow comparison)
25
- * @param a - First value
26
- * @param b - Second value
27
- * @returns True if arrays are equal or values are strictly equal
28
- */
29
- export function arrayEquals(a: any, b: any): boolean {
30
- if (a === b) return true
31
- if (!Array.isArray(a) || !Array.isArray(b)) return false
32
- if (a.length !== b.length) return false
33
- for (let i = 0; i < a.length; i++) {
34
- if (a[i] !== b[i]) return false
35
- }
36
- return true
37
- }
38
-
39
- const nativeConstructors = new Set<Function>([
40
- Object,
41
- Array,
42
- Date,
43
- Function,
44
- Set,
45
- Map,
46
- WeakMap,
47
- WeakSet,
48
- Promise,
49
- Error,
50
- TypeError,
51
- ReferenceError,
52
- SyntaxError,
53
- RangeError,
54
- URIError,
55
- EvalError,
56
- Reflect,
57
- Proxy,
58
- RegExp,
59
- String,
60
- Number,
61
- Boolean,
62
- ] as Function[])
63
- /**
64
- * Checks if a function is a constructor (class or constructor function)
65
- * @param fn - The function to check
66
- * @returns True if the function is a constructor
67
- */
68
- export function isConstructor(fn: Function): boolean {
69
- return (
70
- fn &&
71
- typeof fn === 'function' &&
72
- (nativeConstructors.has(fn) || fn.toString?.().startsWith('class '))
73
- )
74
- }
75
-
76
- /**
77
- * Renames a function with a new name
78
- * @param fct - The function to rename
79
- * @param name - The new name for the function
80
- * @returns The function with the new name
81
- */
82
- export function renamed<F extends Function>(fct: F, name: string): F {
83
- return Object.defineProperties(fct, {
84
- name: {
85
- value: name,
86
- },
87
- })
88
- }
89
- export const FoolProof = {
90
- get(obj: any, prop: any, receiver: any) {
91
- // Check if Node is available and obj is an instance of Node
92
- if (typeof Node !== 'undefined' && obj instanceof Node) return (obj as any)[prop]
93
- return Reflect.get(obj, prop, receiver)
94
- },
95
- set(obj: any, prop: any, value: any, receiver: any) {
96
- // Check if Node is available and obj is an instance of Node
97
- if (typeof Node !== 'undefined' && obj instanceof Node) {
98
- ;(obj as any)[prop] = value
99
- return true
100
- }
101
- if (!(obj instanceof Object) && !Reflect.has(obj, prop)) {
102
- Object.defineProperty(obj, prop, {
103
- value,
104
- configurable: true,
105
- writable: true,
106
- enumerable: true,
107
- })
108
- return true
109
- }
110
- return Reflect.set(obj, prop, value, receiver)
111
- },
112
- }
113
-
114
- export function isOwnAccessor(obj: any, prop: any) {
115
- const opd = Object.getOwnPropertyDescriptor(obj, prop)
116
- return !!(opd?.get || opd?.set)
117
- }
118
-
119
- /**
120
- * Deeply compares two values.
121
- * For objects, compares prototypes with === and then own properties recursively.
122
- * Uses a cache to handle circular references.
123
- * @param a - First value
124
- * @param b - Second value
125
- * @param cache - Map for circular reference protection (internal use)
126
- * @returns True if values are deeply equal
127
- */
128
- export function deepCompare(a: any, b: any, cache = new Map<object, Set<object>>()): boolean {
129
- if (a === b) return true
130
-
131
- if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) {
132
- return a === b
133
- }
134
-
135
- // Prototype check
136
- const protoA = Object.getPrototypeOf(a)
137
- const protoB = Object.getPrototypeOf(b)
138
- if (protoA !== protoB) {
139
- console.warn(`[deepCompare] prototype mismatch:`, {
140
- nameA: a?.constructor?.name,
141
- nameB: b?.constructor?.name,
142
- })
143
- return false
144
- }
145
- // Circular reference protection
146
- let compared = cache.get(a)
147
- if (compared?.has(b)) return true
148
- if (!compared) {
149
- compared = new Set()
150
- cache.set(a, compared)
151
- }
152
- compared.add(b)
153
-
154
- // Handle specific object types
155
- if (Array.isArray(a)) {
156
- if (!Array.isArray(b)) {
157
- console.warn(`[deepCompare] B is not an array`)
158
- return false
159
- }
160
- if (a.length !== b.length) {
161
- console.warn(`[deepCompare] array length mismatch:`, { lenA: a.length, lenB: b.length })
162
- return false
163
- }
164
- for (let i = 0; i < a.length; i++) {
165
- if (!deepCompare(a[i], b[i], cache)) {
166
- console.warn(`[deepCompare] array element mismatch at index ${i}`)
167
- return false
168
- }
169
- }
170
- return true
171
- }
172
-
173
- if (a instanceof Date) {
174
- const match = b instanceof Date && a.getTime() === b.getTime()
175
- if (!match) console.warn(`[deepCompare] Date mismatch`)
176
- return match
177
- }
178
- if (a instanceof RegExp) {
179
- const match = b instanceof RegExp && a.toString() === b.toString()
180
- if (!match) console.warn(`[deepCompare] RegExp mismatch`)
181
- return match
182
- }
183
- if (a instanceof Set) {
184
- if (!(b instanceof Set) || a.size !== b.size) {
185
- console.warn(`[deepCompare] Set size mismatch`)
186
- return false
187
- }
188
- for (const val of a) {
189
- let found = false
190
- for (const bVal of b) {
191
- if (deepCompare(val, bVal, cache)) {
192
- found = true
193
- break
194
- }
195
- }
196
- if (!found) {
197
- console.warn(`[deepCompare] missing Set element`)
198
- return false
199
- }
200
- }
201
- return true
202
- }
203
- if (a instanceof Map) {
204
- if (!(b instanceof Map) || a.size !== b.size) {
205
- console.warn(`[deepCompare] Map size mismatch`)
206
- return false
207
- }
208
- for (const [key, val] of a) {
209
- if (!b.has(key)) {
210
- let foundMatch = false
211
- for (const [bKey, bVal] of b) {
212
- if (deepCompare(key, bKey, cache) && deepCompare(val, bVal, cache)) {
213
- foundMatch = true
214
- break
215
- }
216
- }
217
- if (!foundMatch) {
218
- console.warn(`[deepCompare] missing Map key`)
219
- return false
220
- }
221
- } else {
222
- if (!deepCompare(val, b.get(key), cache)) {
223
- console.warn(`[deepCompare] Map value mismatch for key`)
224
- return false
225
- }
226
- }
227
- }
228
- return true
229
- }
230
-
231
- // Compare own properties
232
- const keysA = Object.keys(a)
233
- const keysB = Object.keys(b)
234
- if (keysA.length !== keysB.length) {
235
- console.warn(`[deepCompare] keys length mismatch:`, {
236
- lenA: keysA.length,
237
- lenB: keysB.length,
238
- keysA,
239
- keysB,
240
- a,
241
- b,
242
- })
243
- return false
244
- }
245
-
246
- for (const key of keysA) {
247
- if (!Object.hasOwn(b, key)) {
248
- console.warn(`[deepCompare] missing key ${String(key)} in B`)
249
- return false
250
- }
251
- if (!deepCompare(a[key], b[key], cache)) {
252
- console.warn(`[deepCompare] value mismatch for key ${String(key)}:`, {
253
- valA: a[key],
254
- valB: b[key],
255
- })
256
- return false
257
- }
258
- }
259
-
260
- return true
261
- }
262
-
263
- const contentRefs = new WeakMap<object, any>()
264
- export function contentRef(container: object) {
265
- if (!contentRefs.has(container))
266
- contentRefs.set(
267
- container,
268
- Object.seal(
269
- Object.create(null, {
270
- contentOf: { value: container, writable: false, configurable: false },
271
- })
272
- )
273
- )
274
- return contentRefs.get(container)
275
- }
276
-
277
- export function tag<T extends object>(name: string, obj: T): T {
278
- Object.defineProperties(obj, {
279
- [Symbol.toStringTag]: {
280
- value: name,
281
- writable: false,
282
- configurable: false,
283
- },
284
- toString: {
285
- value: () => name,
286
- writable: false,
287
- configurable: false,
288
- },
289
- })
290
- return obj
291
- }
292
-
293
- export function named<T extends Function>(name: string, fn: T): T {
294
- Object.defineProperty(fn, 'name', {
295
- value: fn.name ? `${fn.name}::${name}` : name,
296
- writable: false,
297
- configurable: true,
298
- })
299
- return fn
300
- }
package/src/zone.ts DELETED
@@ -1,142 +0,0 @@
1
- import { asyncHooks } from './async'
2
- import { named, tag } from './utils'
3
-
4
- interface InternalZoneUse<T> {
5
- enter(value?: T): unknown
6
- leave(entered: unknown): void
7
- }
8
- function isu<T>(z: AZone<T> | InternalZoneUse<T>): InternalZoneUse<T> {
9
- return z as InternalZoneUse<T>
10
- }
11
- export abstract class AZone<T> {
12
- abstract active?: T
13
- protected enter(value?: T): unknown {
14
- const prev = this.active
15
- this.active = value
16
- return prev
17
- }
18
- protected leave(entered: unknown): void {
19
- this.active = entered as T | undefined
20
- }
21
- with<R>(value: T | undefined, fn: () => R): R {
22
- const entered = this.enter(value)
23
- let res: R
24
- try {
25
- res = fn()
26
- } finally {
27
- this.leave(entered)
28
- }
29
- // [HACK]: Sanitization
30
- // See BROWSER_ASYNC_POLYFILL.md
31
- return asyncHooks.sanitizePromise(res) as R
32
- }
33
- root<R>(fn: () => R): R {
34
- const prev = this.enter()
35
- try {
36
- return fn()
37
- } finally {
38
- this.leave(prev)
39
- }
40
- }
41
- get zoned(): FunctionWrapper {
42
- const active = this.active
43
- return named(`${this}@${active}`, (fn) => this.with(active, fn))
44
- }
45
- }
46
-
47
- export type FunctionWrapper = <R>(fn: () => R) => R
48
-
49
- export class Zone<T> extends AZone<T> {
50
- active: T | undefined
51
- }
52
-
53
- type HistoryValue<T> = { present: T | undefined; history: Set<T> }
54
- export class ZoneHistory<T> extends AZone<HistoryValue<T>> {
55
- private history = new Set<T>()
56
- public readonly present: AZone<T>
57
- public has(value: T): boolean {
58
- return this.history.has(value)
59
- }
60
- public some(predicate: (value: T) => boolean): boolean {
61
- for (const value of this.history) if (predicate(value)) return true
62
- return false
63
- }
64
- constructor(private controlled: AZone<T> = new Zone<T>()) {
65
- super()
66
- const self = this
67
- this.present = Object.create(
68
- controlled,
69
- Object.getOwnPropertyDescriptors({
70
- get active() {
71
- return controlled.active
72
- },
73
- set active(value: T | undefined) {
74
- controlled.active = value
75
- },
76
- enter(value?: T) {
77
- if (value && self.history.has(value))
78
- throw new Error('ZoneHistory: re-entering historical zone')
79
- if (value !== undefined) self.history.add(value)
80
- return { added: value, entered: isu(controlled).enter(value) }
81
- },
82
- leave(entered: { added: T | undefined; entered: unknown }) {
83
- if (entered.added !== undefined) self.history.delete(entered.added)
84
- return isu(controlled).leave(entered.entered)
85
- },
86
- })
87
- )
88
- }
89
- get active() {
90
- return { present: this.controlled.active, history: new Set(this.history) }
91
- }
92
- set active(value: HistoryValue<T> | undefined) {
93
- this.history = value?.history ? new Set(value.history) : new Set()
94
- this.controlled.active = value?.present
95
- }
96
- }
97
-
98
- export class ZoneAggregator extends AZone<Map<AZone<unknown>, unknown>> {
99
- #zones = new Set<AZone<unknown>>()
100
- constructor(...zones: AZone<unknown>[]) {
101
- super()
102
- for (const z of zones) this.#zones.add(z)
103
- }
104
- get active(): Map<AZone<unknown>, unknown> | undefined {
105
- const rv = new Map<AZone<unknown>, unknown>()
106
- for (const z of this.#zones) if (z.active !== undefined) rv.set(z, z.active)
107
- return rv
108
- }
109
- set active(value: Map<AZone<unknown>, unknown> | undefined) {
110
- for (const z of this.#zones) z.active = value?.get(z)
111
- }
112
- enter(value?: Map<AZone<unknown>, unknown> | undefined) {
113
- const entered = new Map<AZone<unknown>, unknown>()
114
- for (const z of this.#zones) {
115
- const v = value?.get(z)
116
- entered.set(z, isu(z).enter(v))
117
- }
118
- return entered
119
- }
120
- leave(entered: Map<AZone<unknown>, unknown>): void {
121
- for (const z of this.#zones) isu(z).leave(entered.get(z))
122
- }
123
- add(z: AZone<unknown>) {
124
- this.#zones.add(z)
125
- }
126
- delete(z: AZone<unknown>) {
127
- this.#zones.delete(z)
128
- }
129
- clear() {
130
- this.#zones.clear()
131
- }
132
- }
133
-
134
- export const asyncZone = tag('async', new ZoneAggregator())
135
- asyncHooks.addHook(() => {
136
- const zone = asyncZone.active
137
- return () => {
138
- const prev = asyncZone.active
139
- asyncZone.active = zone
140
- return () => (asyncZone.active = prev)
141
- }
142
- })