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/decorator.ts DELETED
@@ -1,272 +0,0 @@
1
- // biome-ignore-all lint/suspicious/noConfusingVoidType: We *love* voids
2
- // Standardized decorator system that works with both Legacy and Modern decorators
3
-
4
- import { isConstructor } from './utils'
5
-
6
- /**
7
- * Error thrown when decorator operations fail
8
- */
9
- export class DecoratorError extends Error {
10
- constructor(message: string) {
11
- super(message)
12
- this.name = 'DecoratorException'
13
- }
14
- }
15
- //#region all decorator types
16
-
17
- // Used for get/set and method decorators
18
- /**
19
- * Legacy property decorator type for methods, getters, and setters
20
- */
21
- export type LegacyPropertyDecorator<T> = (
22
- target: T,
23
- name: string | symbol,
24
- descriptor: PropertyDescriptor
25
- ) => any
26
-
27
- /**
28
- * Legacy class decorator type
29
- */
30
- export type LegacyClassDecorator<T> = (target: T) => any
31
-
32
- /**
33
- * Modern method decorator type
34
- */
35
- export type ModernMethodDecorator<T> = (target: T, context: ClassMethodDecoratorContext) => any
36
-
37
- /**
38
- * Modern getter decorator type
39
- */
40
- export type ModernGetterDecorator<T> = (target: T, context: ClassGetterDecoratorContext) => any
41
-
42
- /**
43
- * Modern setter decorator type
44
- */
45
- export type ModernSetterDecorator<T> = (target: T, context: ClassSetterDecoratorContext) => any
46
-
47
- /**
48
- * Modern accessor decorator type
49
- */
50
- export type ModernAccessorDecorator<T> = (target: T, context: ClassAccessorDecoratorContext) => any
51
-
52
- /**
53
- * Modern class decorator type
54
- */
55
- export type ModernClassDecorator<T> = (target: T, context: ClassDecoratorContext) => any
56
-
57
- //#endregion
58
-
59
- type DDMethod<T> = (
60
- original: (this: T, ...args: any[]) => any,
61
- target: any,
62
- name: PropertyKey
63
- ) => ((this: T, ...args: any[]) => any) | void
64
-
65
- type DDGetter<T> = (
66
- original: (this: T) => any,
67
- target: any,
68
- name: PropertyKey
69
- ) => ((this: T) => any) | void
70
-
71
- type DDSetter<T> = (
72
- original: (this: T, value: any) => void,
73
- target: any,
74
- name: PropertyKey
75
- ) => ((this: T, value: any) => void) | void
76
-
77
- type DDClass<T> = <Ctor extends new (...args: any[]) => T = new (...args: any[]) => T>(
78
- target: Ctor
79
- ) => Ctor | void
80
- /**
81
- * Description object for creating decorators that work with both Legacy and Modern decorator proposals
82
- */
83
- export interface DecoratorDescription<T> {
84
- /** Handler for method decorators */
85
- method?: DDMethod<T>
86
- /** Handler for class decorators */
87
- class?: DDClass<T>
88
- /** Handler for getter decorators */
89
- getter?: DDGetter<T>
90
- /** Handler for setter decorators */
91
- setter?: DDSetter<T>
92
- /** Default handler for any decorator type not explicitly defined */
93
- default?: (...args: any[]) => any
94
- }
95
-
96
- /**
97
- * Type for decorators that work with both Legacy and Modern decorator proposals
98
- * Automatically infers the correct decorator type based on the description
99
- */
100
- export type Decorator<T, Description extends DecoratorDescription<T>> = (Description extends {
101
- method: DDMethod<T>
102
- }
103
- ? LegacyPropertyDecorator<T> & ModernMethodDecorator<T>
104
- : unknown) &
105
- (Description extends { class: DDClass<new (...args: any[]) => T> }
106
- ? LegacyClassDecorator<new (...args: any[]) => T> &
107
- ModernClassDecorator<new (...args: any[]) => T>
108
- : unknown) &
109
- (Description extends { getter: DDGetter<T> }
110
- ? LegacyPropertyDecorator<T> & ModernGetterDecorator<T> & ModernAccessorDecorator<T>
111
- : unknown) &
112
- (Description extends { setter: DDSetter<T> }
113
- ? LegacyPropertyDecorator<T> & ModernSetterDecorator<T> & ModernAccessorDecorator<T>
114
- : unknown) &
115
- (Description extends { default: infer Signature } ? Signature : unknown)
116
-
117
- /**
118
- * Factory type for creating decorators that work with both Legacy and Modern decorator proposals
119
- */
120
- export type DecoratorFactory<T> = <Description extends DecoratorDescription<T>>(
121
- description: Description
122
- ) => (Description extends { method: DDMethod<T> }
123
- ? LegacyPropertyDecorator<T> & ModernMethodDecorator<T>
124
- : unknown) &
125
- (Description extends { class: DDClass<new (...args: any[]) => T> }
126
- ? LegacyClassDecorator<new (...args: any[]) => T> &
127
- ModernClassDecorator<new (...args: any[]) => T>
128
- : unknown) &
129
- (Description extends { getter: DDGetter<T> }
130
- ? LegacyPropertyDecorator<T> & ModernGetterDecorator<T> & ModernAccessorDecorator<T>
131
- : unknown) &
132
- (Description extends { setter: DDSetter<T> }
133
- ? LegacyPropertyDecorator<T> & ModernSetterDecorator<T> & ModernAccessorDecorator<T>
134
- : unknown) &
135
- (Description extends { default: infer Signature } ? Signature : unknown)
136
-
137
- /**
138
- * Creates a decorator that works with Legacy decorator proposals
139
- * @param description - The decorator description object
140
- * @returns A decorator function compatible with Legacy decorators
141
- */
142
- export function legacyDecorator<T = any>(description: DecoratorDescription<T>): any {
143
- return function (
144
- this: any,
145
- target: any,
146
- propertyKey?: PropertyKey,
147
- descriptor?: PropertyDescriptor,
148
- ...args: any[]
149
- ) {
150
- if (propertyKey === undefined) {
151
- if (isConstructor(target)) {
152
- if (!('class' in description)) throw new Error('Decorator cannot be applied to a class')
153
- return description.class!(target)
154
- }
155
- } else if (typeof target === 'object' && ['string', 'symbol'].includes(typeof propertyKey)) {
156
- if (!descriptor) throw new Error('Decorator cannot be applied to a field')
157
- else if (typeof descriptor === 'object' && 'configurable' in descriptor) {
158
- if ('get' in descriptor || 'set' in descriptor) {
159
- if (!('getter' in description || 'setter' in description))
160
- throw new Error('Decorator cannot be applied to a getter or setter')
161
- if ('getter' in description) {
162
- const newGetter = description.getter!(descriptor.get as any, target, propertyKey)
163
- if (newGetter) descriptor.get = newGetter
164
- }
165
- if ('setter' in description) {
166
- const newSetter = description.setter!(descriptor.set as any, target, propertyKey)
167
- if (newSetter) descriptor.set = newSetter
168
- }
169
- return descriptor
170
- } else if (typeof descriptor.value === 'function') {
171
- if (!('method' in description)) throw new Error('Decorator cannot be applied to a method')
172
- const newMethod = description.method!(descriptor.value, target, propertyKey)
173
- if (newMethod) descriptor.value = newMethod
174
- return descriptor
175
- }
176
- }
177
- }
178
- if (!('default' in description))
179
- throw new Error('Decorator do not have a default implementation')
180
- return description.default!.call(this, target, propertyKey, descriptor, ...args)
181
- }
182
- }
183
-
184
- /**
185
- * Creates a decorator that works with Modern decorator proposals
186
- * @param description - The decorator description object
187
- * @returns A decorator function compatible with Modern decorators
188
- */
189
- export function modernDecorator<T = any>(description: DecoratorDescription<T>): any {
190
- /*return function (target: any, context?: DecoratorContext, ...args: any[]) {*/
191
- return function (this: any, target: any, context?: DecoratorContext, ...args: any[]) {
192
- if (!context?.kind || typeof context.kind !== 'string') {
193
- if (!('default' in description))
194
- throw new Error('Decorator do not have a default implementation')
195
- return description.default!.call(this, target, context, ...args)
196
- }
197
- switch (context.kind) {
198
- case 'class':
199
- if (!('class' in description)) throw new Error('Decorator cannot be applied to a class')
200
- return description.class!(target)
201
- case 'field':
202
- throw new Error('Decorator cannot be applied to a field')
203
- case 'getter':
204
- if (!('getter' in description)) throw new Error('Decorator cannot be applied to a getter')
205
- return description.getter!(target, target, context.name)
206
- case 'setter':
207
- if (!('setter' in description)) throw new Error('Decorator cannot be applied to a setter')
208
- return description.setter!(target, target, context.name)
209
- case 'method':
210
- if (!('method' in description)) throw new Error('Decorator cannot be applied to a method')
211
- return description.method!(target, target, context.name)
212
- case 'accessor': {
213
- if (!('getter' in description || 'setter' in description))
214
- throw new Error('Decorator cannot be applied to a getter or setter')
215
- const rv: Partial<ClassAccessorDecoratorResult<any, any>> = {}
216
- if ('getter' in description) {
217
- const newGetter = description.getter!(target.get, target, context.name)
218
- if (newGetter) rv.get = newGetter
219
- }
220
- if ('setter' in description) {
221
- const newSetter = description.setter!(target.set, target, context.name)
222
- if (newSetter) rv.set = newSetter
223
- }
224
- return rv
225
- }
226
- //return description.accessor?.(target, context.name, target)
227
- }
228
- }
229
- }
230
-
231
- /**
232
- * Detects if the decorator is being called in modern (Modern) or legacy (Legacy) mode
233
- * based on the arguments passed to the decorator function
234
- */
235
- function detectDecoratorMode(
236
- _target: any,
237
- contextOrKey?: any,
238
- _descriptor?: any
239
- ): 'modern' | 'legacy' {
240
- // Modern decorators have a context object as the second parameter
241
- // Legacy decorators have a string/symbol key as the second parameter
242
- if (
243
- typeof contextOrKey === 'object' &&
244
- contextOrKey !== null &&
245
- typeof contextOrKey.kind === 'string'
246
- ) {
247
- return 'modern'
248
- }
249
- return 'legacy'
250
- }
251
-
252
- /**
253
- * Main decorator factory that automatically detects and works with both Legacy and Modern decorator proposals
254
- * @param description - The decorator description object
255
- * @returns A decorator that works in both Legacy and Modern environments
256
- */
257
- export const decorator: DecoratorFactory<any> = (description: DecoratorDescription<any>) => {
258
- const modern = modernDecorator(description)
259
- const legacy = legacyDecorator(description)
260
- return ((target: any, contextOrKey?: any, ...args: any[]) => {
261
- const mode = detectDecoratorMode(target, contextOrKey, args[0])
262
- return mode === 'modern'
263
- ? modern(target, contextOrKey, ...args)
264
- : legacy(target, contextOrKey, ...args)
265
- }) as any
266
- }
267
-
268
- /**
269
- * Generic class decorator type that works with both Legacy and Modern decorator proposals
270
- */
271
- export type GenericClassDecorator<T> = LegacyClassDecorator<abstract new (...args: any[]) => T> &
272
- ModernClassDecorator<abstract new (...args: any[]) => T>
@@ -1,199 +0,0 @@
1
- import { decorator } from './decorator'
2
-
3
- // Integrated with `using` statement via Symbol.dispose
4
- const fr = new FinalizationRegistry<() => void>((f) => f())
5
- /**
6
- * Symbol for marking destructor methods
7
- */
8
- export const destructor = Symbol('destructor')
9
- /**
10
- * Symbol for accessing allocated values in destroyable objects
11
- */
12
- export const allocatedValues = Symbol('allocated')
13
- /**
14
- * Error thrown when attempting to access a destroyed object
15
- */
16
- export class DestructionError extends Error {
17
- static throw<_T = void>(msg: string) {
18
- return () => {
19
- throw new DestructionError(msg)
20
- }
21
- }
22
- constructor(msg: string) {
23
- super(`Object is destroyed. ${msg}`)
24
- this.name = 'DestroyedAccessError'
25
- }
26
- }
27
- const destroyedHandler = {
28
- [Symbol.toStringTag]: 'MutTs Destroyable',
29
- get: DestructionError.throw('Cannot access destroyed object'),
30
- set: DestructionError.throw('Cannot access destroyed object'),
31
- } as const
32
-
33
- abstract class AbstractDestroyable<Allocated> {
34
- abstract [destructor](allocated: Allocated): void
35
- [Symbol.dispose](): void {
36
- this[destructor](this as unknown as Allocated)
37
- }
38
- }
39
-
40
- interface Destructor<Allocated> {
41
- destructor(allocated: Allocated): void
42
- }
43
-
44
- /**
45
- * Creates a destroyable class with a base class and destructor object
46
- * @param base - The base class to extend
47
- * @param destructorObj - Object containing the destructor method
48
- * @returns A destroyable class with static destroy and isDestroyable methods
49
- */
50
- export function Destroyable<
51
- T extends new (
52
- ...args: any[]
53
- ) => any,
54
- Allocated extends Partial<InstanceType<T>>,
55
- >(
56
- base: T,
57
- destructorObj: Destructor<Allocated>
58
- ): (new (
59
- ...args: ConstructorParameters<T>
60
- ) => InstanceType<T> & { [allocatedValues]: Allocated }) & {
61
- destroy(obj: InstanceType<T>): boolean
62
- isDestroyable(obj: InstanceType<T>): boolean
63
- }
64
-
65
- /**
66
- * Creates a destroyable class with only a destructor object (no base class)
67
- * @param destructorObj - Object containing the destructor method
68
- * @returns A destroyable class with static destroy and isDestroyable methods
69
- */
70
- export function Destroyable<Allocated extends Record<PropertyKey, any> = Record<PropertyKey, any>>(
71
- destructorObj: Destructor<Allocated>
72
- ): (new () => { [allocatedValues]: Allocated }) & {
73
- destroy(obj: any): boolean
74
- isDestroyable(obj: any): boolean
75
- }
76
-
77
- /**
78
- * Creates a destroyable class with a base class (requires [destructor] method)
79
- * @param base - The base class to extend
80
- * @returns A destroyable class with static destroy and isDestroyable methods
81
- */
82
- export function Destroyable<
83
- T extends new (
84
- ...args: any[]
85
- ) => any,
86
- Allocated extends Record<PropertyKey, any> = Record<PropertyKey, any>,
87
- >(
88
- base: T
89
- ): (new (
90
- ...args: ConstructorParameters<T>
91
- ) => AbstractDestroyable<Allocated> & InstanceType<T> & { [allocatedValues]: Allocated }) & {
92
- destroy(obj: InstanceType<T>): boolean
93
- isDestroyable(obj: InstanceType<T>): boolean
94
- }
95
-
96
- /**
97
- * Creates an abstract destroyable base class
98
- * @returns An abstract destroyable class with static destroy and isDestroyable methods
99
- */
100
- export function Destroyable<
101
- Allocated extends Record<PropertyKey, any> = Record<PropertyKey, any>,
102
- >(): abstract new () => (AbstractDestroyable<Allocated> & {
103
- [allocatedValues]: Allocated
104
- }) & {
105
- destroy(obj: any): boolean
106
- isDestroyable(obj: any): boolean
107
- }
108
-
109
- export function Destroyable<
110
- T extends new (
111
- ...args: any[]
112
- ) => any,
113
- Allocated extends Record<PropertyKey, any> = Record<PropertyKey, any>,
114
- >(base?: T | Destructor<Allocated>, destructorObj?: Destructor<Allocated>) {
115
- if (base && typeof base !== 'function') {
116
- destructorObj = base as Destructor<Allocated>
117
- base = undefined
118
- }
119
- if (!base) {
120
- base = class {} as T
121
- }
122
-
123
- return class Destroyable extends (base as T) {
124
- static readonly destructors = new WeakMap<any, () => void>()
125
- static destroy(obj: Destroyable) {
126
- const destructor = Destroyable.destructors.get(obj)
127
- if (!destructor) return false
128
- fr.unregister(obj[allocatedValues])
129
- Destroyable.destructors.delete(obj)
130
- Object.setPrototypeOf(obj, new Proxy({}, destroyedHandler))
131
- // Clear all own properties
132
- for (const key of Object.getOwnPropertyNames(obj)) {
133
- delete (obj as any)[key]
134
- }
135
- destructor()
136
- return true
137
- }
138
- static isDestroyable(obj: Destroyable) {
139
- return Destroyable.destructors.has(obj)
140
- }
141
-
142
- [forwardProperties]!: PropertyKey[]
143
- readonly [allocatedValues]: Allocated
144
- constructor(...args: any[]) {
145
- super(...args)
146
- const allocated = {} as Allocated
147
- this[allocatedValues] = allocated
148
- // @ts-expect-error `this` is an AbstractDestroyable
149
- const myDestructor = destructorObj?.destructor ?? this[destructor]
150
- if (!myDestructor) {
151
- throw new DestructionError('Destructor is not defined')
152
- }
153
- function destruction() {
154
- myDestructor(allocated)
155
- }
156
- Destroyable.destructors.set(this, destruction)
157
- fr.register(this, destruction, allocated)
158
- }
159
- }
160
- }
161
-
162
- const forwardProperties = Symbol('forwardProperties')
163
- /**
164
- * Decorator that marks properties to be stored in the allocated object and passed to the destructor
165
- * Use with accessor properties or explicit get/set pairs
166
- */
167
- export const allocated = decorator({
168
- setter(original, _target, propertyKey) {
169
- return function (value) {
170
- this[allocatedValues][propertyKey] = value
171
- return original.call(this, value)
172
- }
173
- },
174
- })
175
-
176
- /**
177
- * Registers a callback to be called when an object is garbage collected
178
- * @param cb - The callback function to execute on garbage collection
179
- * @returns The object whose reference can be collected
180
- */
181
- export function callOnGC(cb: () => void) {
182
- let called = false
183
- const forward = () => {
184
- if (called) return
185
- called = true
186
- cb()
187
- }
188
- fr.register(forward, cb, cb)
189
- return forward
190
- }
191
-
192
- /**
193
- * Context Manager Protocol for `using` statement integration
194
- * Provides automatic resource cleanup when used with the `using` statement
195
- */
196
- export interface ContextManager<T = any> {
197
- [Symbol.dispose](): void
198
- value?: T
199
- }
@@ -1,5 +0,0 @@
1
- // Import environment-specific patches first (SIDE EFFECTS)
2
- import './async/browser'
3
-
4
- // Then export the library
5
- export * from './index'
package/src/entry-node.ts DELETED
@@ -1,5 +0,0 @@
1
- // Import environment-specific patches first (SIDE EFFECTS)
2
- import './async/node'
3
-
4
- // Then export the library
5
- export * from './index'
package/src/eventful.ts DELETED
@@ -1,110 +0,0 @@
1
- /**
2
- * Base type for event maps - all event handlers must be functions
3
- */
4
- export type EventsBase = Record<string, (...args: any[]) => void>
5
-
6
- const events = Symbol('events')
7
- const hooks = Symbol('hooks')
8
-
9
- const eventBehavior = {
10
- on<EventType extends keyof EventsBase>(
11
- eventOrEvents: EventType | Partial<EventsBase>,
12
- cb?: EventsBase[EventType]
13
- ): () => void {
14
- if (typeof eventOrEvents === 'object') {
15
- for (const e of Object.keys(eventOrEvents) as (keyof EventsBase)[]) {
16
- this.on(e, eventOrEvents[e]!)
17
- }
18
- } else if (cb !== undefined) {
19
- const callbacks = this[events].get(eventOrEvents) ?? new Set<EventsBase[EventType]>()
20
- if (!callbacks.has(cb)) callbacks.add(cb)
21
- this[events].set(eventOrEvents, callbacks)
22
- }
23
- return () => this.off(eventOrEvents, cb)
24
- },
25
- off<EventType extends keyof EventsBase>(
26
- eventOrEvents: EventType | Partial<EventsBase>,
27
- cb?: EventsBase[EventType]
28
- ): void {
29
- if (typeof eventOrEvents === 'object') {
30
- for (const e of Object.keys(eventOrEvents) as (keyof EventsBase)[]) {
31
- this.off(e, eventOrEvents[e])
32
- }
33
- } else if (cb !== null && cb !== undefined) {
34
- const callbacks = this[events].get(eventOrEvents)
35
- if (callbacks) {
36
- callbacks.delete(cb)
37
- if (!callbacks.size) this[events].delete(eventOrEvents)
38
- }
39
- } else {
40
- // Remove all listeners for this event
41
- this[events].delete(eventOrEvents)
42
- }
43
- },
44
- emit<EventType extends keyof EventsBase>(
45
- event: EventType,
46
- ...args: Parameters<EventsBase[EventType]>
47
- ) {
48
- const callbacks = this[events].get(event)
49
- if (callbacks) for (const cb of callbacks) cb.apply(this, args)
50
- for (const cb of this[hooks]) cb.call(this, event, ...args)
51
- },
52
- }
53
-
54
- function perEvent(
55
- eventful: Eventful<any>,
56
- fct: (event: string, ...args: any[]) => void,
57
- use?: 'use'
58
- ) {
59
- const cache = new Map<string, (...args: any[]) => any>()
60
- return new Proxy(fct, {
61
- get(target, prop: PropertyKey) {
62
- if (typeof prop !== 'string') return target[prop]
63
- if (use && !eventful[events].has(prop) && !eventful[hooks].size) return () => {}
64
-
65
- // Return cached function or create and cache
66
- let cached = cache.get(prop)
67
- if (!cached) {
68
- cached = (...args: any[]) => fct.apply(eventful, [prop, ...args])
69
- cache.set(prop, cached)
70
- }
71
- return cached
72
- },
73
- })
74
- }
75
-
76
- /**
77
- * A type-safe event system that provides a clean API for event handling
78
- * @template Events - The event map defining event names and their handler signatures
79
- */
80
- export class Eventful<Events extends EventsBase> {
81
- private readonly [events] = new Map<keyof Events, Set<(...args: any[]) => void>>()
82
- private readonly [hooks] = new Set<(...args: any[]) => void>()
83
-
84
- public hook(
85
- cb: <EventType extends keyof Events>(
86
- event: EventType,
87
- ...args: Parameters<Events[EventType]>
88
- ) => void
89
- ): () => void {
90
- this[hooks].add(cb)
91
- return () => {
92
- this[hooks].delete(cb)
93
- }
94
- }
95
-
96
- public on = perEvent(this, eventBehavior.on) as ((events: Partial<Events>) => void) &
97
- (<EventType extends keyof Events>(event: EventType, cb: Events[EventType]) => () => void) & {
98
- [event in keyof Events]: (cb: Events[event]) => () => void
99
- }
100
- public off = perEvent(this, eventBehavior.off) as ((events: Partial<Events>) => void) &
101
- (<EventType extends keyof Events>(event: EventType, cb?: Events[EventType]) => void) & {
102
- [event in keyof Events]: (cb?: Events[event]) => void
103
- }
104
-
105
- public emit = perEvent(this, eventBehavior.emit, 'use') as (<EventType extends keyof Events>(
106
- event: EventType,
107
- ...args: Parameters<Events[EventType]>
108
- ) => void) &
109
- Events
110
- }
package/src/flavored.ts DELETED
@@ -1,106 +0,0 @@
1
- /**
2
- * Creates a flavored (extensible) version of a function with chainable property modifiers.
3
- *
4
- * Each property defined in `flavors` returns a new flavored function that transforms
5
- * how the original function is called. This enables a fluent API where properties
6
- * create specialized variants of the base function.
7
- *
8
- * @param fn - The base function to flavor
9
- * @param flavors - Object defining the flavor properties (getters or methods)
10
- * @returns A proxy of the function with the flavor properties attached
11
- *
12
- * @example
13
- * ```typescript
14
- * function greet(name: string, options?: { loud?: boolean }) {
15
- * const greeting = `Hello, ${name}!`
16
- * return options?.loud ? greeting.toUpperCase() : greeting
17
- * }
18
- *
19
- * const flavoredGreet = flavored(greet, {
20
- * get loud() {
21
- * return createFlavor(this, (name, opts) => [name, { ...opts, loud: true }])
22
- * }
23
- * })
24
- *
25
- * flavoredGreet('World') // "Hello, World!"
26
- * flavoredGreet.loud('World') // "HELLO, WORLD!"
27
- * ```
28
- */
29
- import { named } from './utils'
30
-
31
- /**
32
- * Creates a flavored (extensible) version of a function with chainable property modifiers.
33
- */
34
- export function flavored<T extends (...args: any[]) => any, F extends Record<string, any>>(
35
- fn: T,
36
- flavors: F
37
- ): T & F {
38
- // Store flavors for recursive flavoring
39
- ;(fn as any).flavors = flavors
40
-
41
- return new Proxy(fn, {
42
- get(target, prop, receiver) {
43
- if (prop in flavors) {
44
- return Reflect.get(flavors, prop, receiver)
45
- }
46
- return (target as any)[prop]
47
- },
48
- }) as T & F
49
- }
50
-
51
- /**
52
- * Creates a new flavored function that transforms arguments before calling the base.
53
- *
54
- * @param fn - The base flavored function
55
- * @param transform - Function that receives the original arguments and returns transformed arguments
56
- * @returns A new flavored function with the transformation applied
57
- *
58
- * @example
59
- * ```typescript
60
- * const loudGreet = createFlavor(greet, (name, opts) => [name, { ...opts, loud: true }])
61
- * ```
62
- */
63
- export function createFlavor<T extends (...args: any[]) => any>(
64
- fn: T,
65
- transform: (...args: Parameters<T>) => Parameters<T>,
66
- name?: string
67
- ): T {
68
- const fct = function flavorWrapper(this: any, ...args: Parameters<T>) {
69
- return fn.apply(this, transform(...args))
70
- }
71
- if (name) named(name, fct)
72
-
73
- return flavored(fct as any as T, (fn as any).flavors || {})
74
- }
75
-
76
- /**
77
- * Creates a new flavored function that merges options objects.
78
- * Useful when the last argument is an options object that should be merged.
79
- *
80
- * @param fn - The base flavored function
81
- * @param defaultOptions - Options to merge with the provided options
82
- * @returns A new flavored function with merged options
83
- *
84
- * @example
85
- * ```typescript
86
- * const opaqueEffect = flavorOptions(effect, { opaque: true })
87
- * const namedEffect = flavorOptions(effect, { name: 'myEffect' })
88
- * ```
89
- */
90
- export function flavorOptions<T extends (...args: any[]) => any>(
91
- fn: T,
92
- defaultOptions: Record<string, any>,
93
- name?: string
94
- ): T {
95
- const fct = function flavorOptionsWrapper(this: any, ...args: any[]) {
96
- const lastArg = args[args.length - 1]
97
- const mergedArgs =
98
- lastArg !== undefined && typeof lastArg === 'object'
99
- ? [...args.slice(0, -1), { ...defaultOptions, ...lastArg }]
100
- : [...args, defaultOptions]
101
- return fn.apply(this, mergedArgs)
102
- }
103
- if (name) named(name, fct)
104
-
105
- return flavored(fct as any as T, (fn as any).flavors || {})
106
- }