mutts 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -17
- package/dist/browser.cjs +3111 -0
- package/dist/browser.cjs.map +1 -0
- package/dist/browser.d.ts +1391 -1
- package/dist/browser.esm.js +264 -35
- package/dist/browser.esm.js.map +1 -1
- package/dist/chunks/async-browser-lvzLOCgk.cjs +297 -0
- package/dist/chunks/async-browser-lvzLOCgk.cjs.map +1 -0
- package/dist/chunks/async-core-CRLKP3l-.cjs +29 -0
- package/dist/chunks/async-core-CRLKP3l-.cjs.map +1 -0
- package/dist/chunks/async-node-C3DeIb0y.cjs +96 -0
- package/dist/chunks/async-node-C3DeIb0y.cjs.map +1 -0
- package/dist/chunks/index-2vea86wD.esm.js +3011 -0
- package/dist/chunks/index-2vea86wD.esm.js.map +1 -0
- package/dist/chunks/index-CtA2AWl3.esm.js +4376 -0
- package/dist/chunks/index-CtA2AWl3.esm.js.map +1 -0
- package/dist/chunks/index-VTO-b2vR.cjs +4461 -0
- package/dist/chunks/index-VTO-b2vR.cjs.map +1 -0
- package/dist/debug/debug.d.ts +122 -0
- package/dist/debug/debug.d.ts.map +1 -0
- package/dist/debug/index.d.ts +4 -0
- package/dist/debug/index.d.ts.map +1 -0
- package/dist/debug/lineage-panel.d.ts +5 -0
- package/dist/debug/lineage-panel.d.ts.map +1 -0
- package/dist/debug/lineage.d.ts +79 -0
- package/dist/debug/lineage.d.ts.map +1 -0
- package/dist/debug.cjs +35 -0
- package/dist/debug.cjs.map +1 -0
- package/dist/debug.d.ts +209 -0
- package/dist/debug.esm.js +2 -0
- package/dist/debug.esm.js.map +1 -0
- package/dist/devtools/devtool/devtools.d.ts +1 -0
- package/dist/devtools/devtool/devtools.d.ts.map +1 -0
- package/dist/devtools/devtool/panel.d.ts +2 -0
- package/dist/devtools/devtool/panel.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/mutts.umd.js +1 -1
- package/dist/mutts.umd.js.map +1 -1
- package/dist/mutts.umd.min.js +1 -1
- package/dist/mutts.umd.min.js.map +1 -1
- package/dist/node.cjs +107 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.ts +2 -2
- package/dist/node.esm.js +86 -33
- package/dist/node.esm.js.map +1 -1
- package/dist/src/async/browser.d.ts +2 -0
- package/dist/src/async/browser.d.ts.map +1 -0
- package/dist/src/async/index.d.ts +19 -0
- package/dist/src/async/index.d.ts.map +1 -0
- package/dist/src/async/node.d.ts +2 -0
- package/dist/src/async/node.d.ts.map +1 -0
- package/dist/src/decorator.d.ts +106 -0
- package/dist/src/decorator.d.ts.map +1 -0
- package/dist/src/destroyable.d.ts +87 -0
- package/dist/src/destroyable.d.ts.map +1 -0
- package/dist/src/entry-browser.d.ts +3 -0
- package/dist/src/entry-browser.d.ts.map +1 -0
- package/dist/src/entry-node.d.ts +3 -0
- package/dist/src/entry-node.d.ts.map +1 -0
- package/dist/src/eventful.d.ts +20 -0
- package/dist/src/eventful.d.ts.map +1 -0
- package/dist/src/flavored.d.ts +33 -0
- package/dist/src/flavored.d.ts.map +1 -0
- package/dist/src/index.d.ts +14 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/indexable.d.ts +243 -0
- package/dist/src/indexable.d.ts.map +1 -0
- package/dist/src/introspection.d.ts +27 -0
- package/dist/src/introspection.d.ts.map +1 -0
- package/dist/src/iterableWeak.d.ts +53 -0
- package/dist/src/iterableWeak.d.ts.map +1 -0
- package/dist/src/mixins.d.ts +25 -0
- package/dist/src/mixins.d.ts.map +1 -0
- package/dist/src/promiseChain.d.ts +20 -0
- package/dist/src/promiseChain.d.ts.map +1 -0
- package/dist/src/reactive/array.d.ts +48 -0
- package/dist/src/reactive/array.d.ts.map +1 -0
- package/dist/src/reactive/buffer.d.ts +120 -0
- package/dist/src/reactive/buffer.d.ts.map +1 -0
- package/dist/src/reactive/change.d.ts +29 -0
- package/dist/src/reactive/change.d.ts.map +1 -0
- package/dist/src/reactive/deep-touch.d.ts +28 -0
- package/dist/src/reactive/deep-touch.d.ts.map +1 -0
- package/dist/src/reactive/deep-watch-state.d.ts +25 -0
- package/dist/src/reactive/deep-watch-state.d.ts.map +1 -0
- package/dist/src/reactive/deep-watch.d.ts +20 -0
- package/dist/src/reactive/deep-watch.d.ts.map +1 -0
- package/dist/src/reactive/describe.d.ts +12 -0
- package/dist/src/reactive/describe.d.ts.map +1 -0
- package/dist/src/reactive/effect-context.d.ts +34 -0
- package/dist/src/reactive/effect-context.d.ts.map +1 -0
- package/dist/src/reactive/effects.d.ts +164 -0
- package/dist/src/reactive/effects.d.ts.map +1 -0
- package/dist/src/reactive/index.d.ts +19 -0
- package/dist/src/reactive/index.d.ts.map +1 -0
- package/dist/src/reactive/map.d.ts +28 -0
- package/dist/src/reactive/map.d.ts.map +1 -0
- package/dist/src/reactive/memoize.d.ts +28 -0
- package/dist/src/reactive/memoize.d.ts.map +1 -0
- package/dist/src/reactive/non-reactive-state.d.ts +9 -0
- package/dist/src/reactive/non-reactive-state.d.ts.map +1 -0
- package/dist/src/reactive/non-reactive.d.ts +11 -0
- package/dist/src/reactive/non-reactive.d.ts.map +1 -0
- package/dist/src/reactive/project.d.ts +40 -0
- package/dist/src/reactive/project.d.ts.map +1 -0
- package/dist/src/reactive/proxy-state.d.ts +8 -0
- package/dist/src/reactive/proxy-state.d.ts.map +1 -0
- package/dist/src/reactive/proxy.d.ts +23 -0
- package/dist/src/reactive/proxy.d.ts.map +1 -0
- package/dist/src/reactive/record.d.ts +115 -0
- package/dist/src/reactive/record.d.ts.map +1 -0
- package/dist/src/reactive/register.d.ts +125 -0
- package/dist/src/reactive/register.d.ts.map +1 -0
- package/dist/src/reactive/registry.d.ts +21 -0
- package/dist/src/reactive/registry.d.ts.map +1 -0
- package/dist/src/reactive/set.d.ts +26 -0
- package/dist/src/reactive/set.d.ts.map +1 -0
- package/dist/src/reactive/tracking.d.ts +7 -0
- package/dist/src/reactive/tracking.d.ts.map +1 -0
- package/dist/src/reactive/types.d.ts +424 -0
- package/dist/src/reactive/types.d.ts.map +1 -0
- package/dist/src/reactive/watch.d.ts +48 -0
- package/dist/src/reactive/watch.d.ts.map +1 -0
- package/dist/src/std-decorators.d.ts +45 -0
- package/dist/src/std-decorators.d.ts.map +1 -0
- package/dist/src/utils.d.ts +49 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/zone.d.ts +40 -0
- package/dist/src/zone.d.ts.map +1 -0
- package/dist/types-DaHFfhlN.d.ts +414 -0
- package/docs/ai/api-reference.md +1 -1
- package/docs/ai/manual.md +443 -17
- package/docs/events.md +57 -2
- package/docs/flavored.md +210 -0
- package/docs/reactive/advanced.md +2 -3
- package/docs/reactive/attend.md +143 -0
- package/docs/reactive/collections.md +55 -0
- package/docs/reactive/core.md +120 -4
- package/docs/reactive/debugging.md +8 -10
- package/docs/reactive/describe.md +85 -0
- package/docs/reactive/error-handling.md +121 -0
- package/docs/reactive/project.md +1 -1
- package/docs/reactive/scan.md +215 -0
- package/docs/reactive.md +2 -0
- package/docs/std-decorators.md +171 -52
- package/docs/zone.md +9 -6
- package/package.json +44 -27
- package/src/async/browser.ts +277 -41
- package/src/async/index.ts +23 -4
- package/src/async/node.ts +78 -32
- package/src/entry-browser.ts +5 -0
- package/src/entry-node.ts +5 -0
- package/src/eventful.ts +82 -49
- package/src/flavored.ts +106 -0
- package/src/index.d.ts +12 -9
- package/src/index.ts +2 -1
- package/src/introspection.ts +1 -1
- package/src/reactive/array.ts +160 -80
- package/src/reactive/buffer.ts +187 -27
- package/src/reactive/change.ts +16 -23
- package/src/reactive/deep-touch.ts +19 -14
- package/src/reactive/deep-watch-state.ts +3 -3
- package/src/reactive/deep-watch.ts +7 -4
- package/src/reactive/describe.ts +39 -0
- package/src/reactive/effect-context.ts +71 -6
- package/src/reactive/effects.ts +445 -393
- package/src/reactive/index.ts +12 -14
- package/src/reactive/map.ts +8 -24
- package/src/reactive/memoize.ts +26 -3
- package/src/reactive/project.md +107 -0
- package/src/reactive/project.ts +48 -71
- package/src/reactive/proxy.ts +21 -3
- package/src/reactive/record.ts +30 -45
- package/src/reactive/register.ts +138 -19
- package/src/reactive/registry.ts +22 -9
- package/src/reactive/set.ts +7 -20
- package/src/reactive/tracking.ts +9 -12
- package/src/reactive/types.ts +104 -24
- package/src/reactive/{interface.ts → watch.ts} +29 -59
- package/src/std-decorators.ts +56 -17
- package/src/utils.ts +3 -4
- package/src/zone.ts +43 -28
- package/dist/browser.js +0 -161
- package/dist/browser.js.map +0 -1
- package/dist/chunks/index-BFYK02LG.js +0 -6378
- package/dist/chunks/index-BFYK02LG.js.map +0 -1
- package/dist/chunks/index-CNR6QRUl.esm.js +0 -6291
- package/dist/chunks/index-CNR6QRUl.esm.js.map +0 -1
- package/dist/node.js +0 -136
- package/dist/node.js.map +0 -1
- package/src/reactive/debug.ts +0 -517
package/docs/std-decorators.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
# Standard decorators
|
|
3
3
|
|
|
4
4
|
A TypeScript library that provides standard decorators that should stop being re-implemented for the 50th time
|
|
@@ -189,13 +189,13 @@ When the decorator is applied to a non-getter method:
|
|
|
189
189
|
3. **Memory overhead**: Cached values are stored indefinitely
|
|
190
190
|
4. **Getter-only**: Can only be applied to getter methods, not setters or regular methods
|
|
191
191
|
|
|
192
|
-
##
|
|
192
|
+
## Descriptor
|
|
193
193
|
|
|
194
|
-
The `
|
|
194
|
+
The `descriptor` decorator provides a clean, reusable way to configure property descriptors (enumerable, configurable, writable) for class properties. This decorator uses a functional approach that makes it easy to create reusable descriptor configurations.
|
|
195
195
|
|
|
196
196
|
## API Reference
|
|
197
197
|
|
|
198
|
-
### `
|
|
198
|
+
### `descriptor(descriptor: PropertyDescriptor): <T>(...properties: (keyof T)[]) => GenericClassDecorator<T>`
|
|
199
199
|
|
|
200
200
|
A function that creates a decorator to configure property descriptors for specified properties.
|
|
201
201
|
|
|
@@ -207,29 +207,68 @@ A function that creates a decorator to configure property descriptors for specif
|
|
|
207
207
|
|
|
208
208
|
**Returns:** A function that takes property names and returns a class decorator
|
|
209
209
|
|
|
210
|
+
**Flavors:**
|
|
211
|
+
The `descriptor` function is flavored with the following chainable properties:
|
|
212
|
+
- `.enumerable` - Sets enumerable to true
|
|
213
|
+
- `.hidden` - Sets enumerable to false
|
|
214
|
+
- `.configurable` - Sets configurable to true
|
|
215
|
+
- `.frozen` - Sets configurable to false
|
|
216
|
+
- `.writable` - Sets writable to true
|
|
217
|
+
- `.readonly` - Sets writable to false
|
|
218
|
+
|
|
210
219
|
**Usage Pattern:**
|
|
211
220
|
```typescript
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
221
|
+
// Using flavors for single properties
|
|
222
|
+
@descriptor.readonly('id', 'createdAt')
|
|
223
|
+
@descriptor.hidden('_private')
|
|
224
|
+
class MyClass { }
|
|
215
225
|
|
|
216
|
-
|
|
217
|
-
@
|
|
218
|
-
@locked('critical')
|
|
226
|
+
// For multiple descriptor properties on the same property, use object syntax
|
|
227
|
+
@descriptor({ writable: false, enumerable: false, configurable: false })('secret')
|
|
219
228
|
class MyClass { }
|
|
229
|
+
|
|
230
|
+
// Note: Stacking multiple flavored decorators on the same property is not recommended
|
|
231
|
+
// as each decorator creates a new subclass and only the last applied takes effect
|
|
220
232
|
```
|
|
221
233
|
|
|
222
234
|
## Usage Examples
|
|
223
235
|
|
|
236
|
+
### Using Flavors
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
import { descriptor } from 'mutts/std-decorators'
|
|
240
|
+
|
|
241
|
+
// Use flavors directly for cleaner syntax
|
|
242
|
+
@descriptor.readonly('id', 'createdAt')
|
|
243
|
+
@descriptor.hidden('_private', '_cache')
|
|
244
|
+
@descriptor.frozen('critical')
|
|
245
|
+
class User {
|
|
246
|
+
id: string = 'user-123'
|
|
247
|
+
name: string = 'John'
|
|
248
|
+
_private: string = 'secret'
|
|
249
|
+
_cache: Map<string, any> = new Map()
|
|
250
|
+
createdAt: Date = new Date()
|
|
251
|
+
critical: string = 'locked'
|
|
252
|
+
|
|
253
|
+
constructor(name: string) {
|
|
254
|
+
this.name = name
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const user = new User('Alice')
|
|
259
|
+
console.log(Object.keys(user)) // ['name', 'createdAt'] - only enumerable properties
|
|
260
|
+
// user.id = 'new-id' // TypeError: Cannot assign to read only property 'id'
|
|
261
|
+
```
|
|
262
|
+
|
|
224
263
|
### Creating Reusable Decorators
|
|
225
264
|
|
|
226
265
|
```typescript
|
|
227
|
-
import {
|
|
266
|
+
import { descriptor } from 'mutts/std-decorators'
|
|
228
267
|
|
|
229
268
|
// Create reusable descriptor configurations
|
|
230
|
-
const readonly =
|
|
231
|
-
const hidden =
|
|
232
|
-
const locked =
|
|
269
|
+
const readonly = descriptor.readonly
|
|
270
|
+
const hidden = descriptor.hidden
|
|
271
|
+
const locked = descriptor.frozen
|
|
233
272
|
|
|
234
273
|
// Use them on classes
|
|
235
274
|
@readonly('id', 'createdAt')
|
|
@@ -255,11 +294,10 @@ console.log(Object.keys(user)) // ['id', 'name', 'createdAt', 'critical'] - only
|
|
|
255
294
|
### Making Properties Non-Enumerable
|
|
256
295
|
|
|
257
296
|
```typescript
|
|
258
|
-
import {
|
|
259
|
-
|
|
260
|
-
const hidden = describe({ enumerable: false })
|
|
297
|
+
import { descriptor } from 'mutts/std-decorators'
|
|
261
298
|
|
|
262
|
-
|
|
299
|
+
// Use the hidden flavor directly
|
|
300
|
+
@descriptor.hidden('_internal', '_cache', 'debug')
|
|
263
301
|
class CacheManager {
|
|
264
302
|
public data: any[] = []
|
|
265
303
|
_internal: Map<string, any> = new Map()
|
|
@@ -280,13 +318,10 @@ console.log(Object.getOwnPropertyNames(cache)) // ['data', '_internal', '_cache'
|
|
|
280
318
|
### Read-Only Properties
|
|
281
319
|
|
|
282
320
|
```typescript
|
|
283
|
-
import {
|
|
321
|
+
import { descriptor } from 'mutts/std-decorators'
|
|
284
322
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
@readonly('createdAt', 'version')
|
|
289
|
-
@readonlyLocked('id')
|
|
323
|
+
// Use flavors for read-only properties
|
|
324
|
+
@descriptor.readonly('createdAt', 'version')
|
|
290
325
|
class Document {
|
|
291
326
|
id: string
|
|
292
327
|
title: string
|
|
@@ -306,25 +341,41 @@ class Document {
|
|
|
306
341
|
}
|
|
307
342
|
|
|
308
343
|
const doc = new Document('doc-1', 'My Document')
|
|
309
|
-
// doc.id = 'new-id' // TypeError: Cannot assign to read only property 'id'
|
|
310
344
|
// doc.createdAt = new Date() // TypeError: Cannot assign to read only property 'createdAt'
|
|
345
|
+
// doc.version = 2 // TypeError: Cannot assign to read only property 'version'
|
|
311
346
|
doc.updateTitle('Updated Title') // This works
|
|
312
347
|
```
|
|
313
348
|
|
|
314
|
-
###
|
|
349
|
+
### Combining Multiple Flavors
|
|
315
350
|
|
|
316
351
|
```typescript
|
|
317
|
-
import {
|
|
352
|
+
import { descriptor } from 'mutts/std-decorators'
|
|
318
353
|
|
|
319
|
-
|
|
320
|
-
|
|
354
|
+
// Stack multiple flavored decorators
|
|
355
|
+
@descriptor.readonly('secret')
|
|
356
|
+
@descriptor.hidden('secret')
|
|
357
|
+
@descriptor.frozen('secret')
|
|
358
|
+
class SecureData {
|
|
359
|
+
public info: string = 'public'
|
|
360
|
+
secret: string = 'top secret'
|
|
361
|
+
}
|
|
321
362
|
|
|
322
|
-
|
|
323
|
-
|
|
363
|
+
const data = new SecureData()
|
|
364
|
+
// data.secret = 'leaked' // TypeError: Cannot assign to read only property 'secret'
|
|
365
|
+
console.log(Object.keys(data)) // ['info'] - secret is not enumerable
|
|
366
|
+
// Object.defineProperty(data, 'secret', { value: 'new' }) // TypeError: Cannot redefine property
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Configuration Control
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
import { descriptor } from 'mutts/std-decorators'
|
|
373
|
+
|
|
374
|
+
// Use flavors for configuration control
|
|
375
|
+
@descriptor.frozen('_sealed')
|
|
324
376
|
class SecureObject {
|
|
325
377
|
public data: any
|
|
326
378
|
_sealed: string = 'cannot be reconfigured'
|
|
327
|
-
_frozen: string = 'cannot be changed or reconfigured'
|
|
328
379
|
|
|
329
380
|
constructor(data: any) {
|
|
330
381
|
this.data = data
|
|
@@ -333,41 +384,41 @@ class SecureObject {
|
|
|
333
384
|
|
|
334
385
|
const obj = new SecureObject({ key: 'value' })
|
|
335
386
|
// Object.defineProperty(obj, '_sealed', { value: 'new' }) // TypeError: Cannot redefine property
|
|
336
|
-
// Object.defineProperty(obj, '_frozen', { value: 'new' }) // TypeError: Cannot redefine property
|
|
337
387
|
```
|
|
338
388
|
|
|
339
389
|
## Implementation Details
|
|
340
390
|
|
|
341
391
|
### Functional Approach
|
|
342
392
|
|
|
343
|
-
The `
|
|
393
|
+
The `descriptor` function uses a flavored approach that provides direct access to common configurations:
|
|
344
394
|
|
|
345
395
|
```typescript
|
|
346
|
-
//
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
// Apply to multiple classes with different properties
|
|
351
|
-
@readonly('id', 'createdAt')
|
|
396
|
+
// Use flavors directly for cleaner syntax
|
|
397
|
+
@descriptor.readonly('id', 'createdAt')
|
|
398
|
+
@descriptor.hidden('internal')
|
|
352
399
|
class User { }
|
|
353
400
|
|
|
401
|
+
// Or create reusable aliases
|
|
402
|
+
const readonly = descriptor.readonly
|
|
403
|
+
const hidden = descriptor.hidden
|
|
404
|
+
|
|
354
405
|
@readonly('version', 'buildDate')
|
|
355
406
|
class Package { }
|
|
356
407
|
```
|
|
357
408
|
|
|
358
409
|
### Common Decorator Patterns
|
|
359
410
|
|
|
360
|
-
The
|
|
411
|
+
The flavored approach makes it easy to create common decorator patterns:
|
|
361
412
|
|
|
362
413
|
```typescript
|
|
363
|
-
import {
|
|
414
|
+
import { descriptor } from './std-decorators'
|
|
364
415
|
|
|
365
|
-
// Common reusable decorators
|
|
366
|
-
export const readonly =
|
|
367
|
-
export const hidden =
|
|
368
|
-
export const locked =
|
|
369
|
-
export const frozen =
|
|
370
|
-
export const private =
|
|
416
|
+
// Common reusable decorators using flavors
|
|
417
|
+
export const readonly = descriptor.readonly
|
|
418
|
+
export const hidden = descriptor.hidden
|
|
419
|
+
export const locked = descriptor.frozen
|
|
420
|
+
export const frozen = (() => descriptor.readonly.frozen)()
|
|
421
|
+
export const private = (() => descriptor.hidden.frozen)()
|
|
371
422
|
|
|
372
423
|
// Usage examples
|
|
373
424
|
@readonly('id', 'createdAt')
|
|
@@ -389,7 +440,7 @@ The decorator merges the provided descriptor configuration with the existing pro
|
|
|
389
440
|
|
|
390
441
|
```typescript
|
|
391
442
|
// Original property might have { enumerable: true, writable: true, configurable: true }
|
|
392
|
-
// After @readonly('prop')
|
|
443
|
+
// After @descriptor.readonly('prop')
|
|
393
444
|
// Final descriptor: { enumerable: true, writable: false, configurable: true }
|
|
394
445
|
```
|
|
395
446
|
|
|
@@ -399,9 +450,9 @@ The property descriptor configuration is applied in the constructor after callin
|
|
|
399
450
|
|
|
400
451
|
## Best Practices
|
|
401
452
|
|
|
402
|
-
1. **
|
|
403
|
-
2. **
|
|
404
|
-
3. **Combine multiple decorators**: Stack multiple
|
|
453
|
+
1. **Use flavors directly**: Prefer `descriptor.readonly` over creating aliases for simple cases
|
|
454
|
+
2. **Create reusable aliases**: For complex or frequently used combinations, create aliases
|
|
455
|
+
3. **Combine multiple decorators**: Stack multiple flavored decorators for complex configurations
|
|
405
456
|
4. **Use for encapsulation**: Hide internal properties from enumeration
|
|
406
457
|
5. **Control immutability**: Make critical properties read-only
|
|
407
458
|
6. **Prevent reconfiguration**: Lock important properties from being modified
|
|
@@ -551,6 +602,74 @@ deprecated.warn = (target, propertyKey, message?) => {
|
|
|
551
602
|
4. **Document migration paths**: Provide clear upgrade instructions
|
|
552
603
|
5. **Monitor usage**: Track which deprecated features are still being used
|
|
553
604
|
|
|
605
|
+
## Debounce
|
|
606
|
+
|
|
607
|
+
The `debounce` decorator delays the execution of a method until a specified amount of time has passed since the last time it was called. This is useful for handling rapid events like keystrokes or window resizing.
|
|
608
|
+
|
|
609
|
+
## API Reference
|
|
610
|
+
|
|
611
|
+
### `@debounce(delay: number)`
|
|
612
|
+
|
|
613
|
+
A decorator that debounces a method.
|
|
614
|
+
|
|
615
|
+
**Parameters:**
|
|
616
|
+
- `delay`: The delay in milliseconds to wait before executing the method.
|
|
617
|
+
|
|
618
|
+
**Returns:** A method decorator.
|
|
619
|
+
|
|
620
|
+
## Usage Example
|
|
621
|
+
|
|
622
|
+
```typescript
|
|
623
|
+
import { debounce } from 'mutts/std-decorators'
|
|
624
|
+
|
|
625
|
+
class SearchComponent {
|
|
626
|
+
@debounce(300)
|
|
627
|
+
onSearch(query: string) {
|
|
628
|
+
// This will only run after 300ms of inactivity
|
|
629
|
+
console.log(`Searching for: ${query}`)
|
|
630
|
+
this.performApiCall(query)
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
performApiCall(query: string) {
|
|
634
|
+
// ...
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
## Throttle
|
|
640
|
+
|
|
641
|
+
The `throttle` decorator limits the execution of a method to at most once every specified amount of time. This is useful for rate-limiting expensive operations like scroll handlers or animations.
|
|
642
|
+
|
|
643
|
+
## API Reference
|
|
644
|
+
|
|
645
|
+
### `@throttle(delay: number)`
|
|
646
|
+
|
|
647
|
+
A decorator that throttles a method.
|
|
648
|
+
|
|
649
|
+
**Parameters:**
|
|
650
|
+
- `delay`: The time interval in milliseconds.
|
|
651
|
+
|
|
652
|
+
**Returns:** A method decorator.
|
|
653
|
+
|
|
654
|
+
## Usage Example
|
|
655
|
+
|
|
656
|
+
```typescript
|
|
657
|
+
import { throttle } from 'mutts/std-decorators'
|
|
658
|
+
|
|
659
|
+
class ScrollHandler {
|
|
660
|
+
@throttle(100)
|
|
661
|
+
onScroll(event: Event) {
|
|
662
|
+
// This will run at most once every 100ms
|
|
663
|
+
console.log('Scroll event processed')
|
|
664
|
+
this.updateUI()
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
updateUI() {
|
|
668
|
+
// ...
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
```
|
|
672
|
+
|
|
554
673
|
## Related
|
|
555
674
|
|
|
556
675
|
- [JavaScript Decorators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Decorators)
|
package/docs/zone.md
CHANGED
|
@@ -21,20 +21,17 @@ console.log(myZone.active); // undefined
|
|
|
21
21
|
|
|
22
22
|
## Async Propagation
|
|
23
23
|
|
|
24
|
-
By default, zones are lost when an async operation yields control (e.g., after `await`). To fix this, `
|
|
24
|
+
By default, zones are lost when an async operation yields control (e.g., after `await`). To fix this, register zones in `asyncZone` — the global `ZoneAggregator` — which automatically preserves context across async boundaries via `asyncHooks`.
|
|
25
25
|
|
|
26
26
|
```typescript
|
|
27
|
-
import {
|
|
27
|
+
import { asyncZone, Zone } from 'mutts/zone';
|
|
28
28
|
|
|
29
29
|
const requestId = new Zone<string>();
|
|
30
30
|
|
|
31
31
|
// 1. Tell the global aggregator to track this zone
|
|
32
32
|
asyncZone.add(requestId);
|
|
33
33
|
|
|
34
|
-
// 2.
|
|
35
|
-
configureAsyncZone();
|
|
36
|
-
|
|
37
|
-
// 3. Usage
|
|
34
|
+
// 2. Usage
|
|
38
35
|
requestId.with("req-123", async () => {
|
|
39
36
|
await somePromise();
|
|
40
37
|
// Context is automatically preserved across await!
|
|
@@ -42,6 +39,12 @@ requestId.with("req-123", async () => {
|
|
|
42
39
|
});
|
|
43
40
|
```
|
|
44
41
|
|
|
42
|
+
> [!WARNING]
|
|
43
|
+
> **Browser Limitations**: In browser environments (where `AsyncLocalStorage` is unavailable), `mutts` relies on monkey-patching global async primitives (Promise, setTimeout, etc.) to propagate zones. This is generally less robust than Node.js's `async_hooks` and may fail to track context across:
|
|
44
|
+
> * Native `async/await` boundaries in some modern browsers if not transpiled.
|
|
45
|
+
> * Concurrent modifications to global prototypes by other libraries.
|
|
46
|
+
|
|
47
|
+
|
|
45
48
|
## Core API
|
|
46
49
|
|
|
47
50
|
### `AZone<T>` (Abstract)
|
package/package.json
CHANGED
|
@@ -1,50 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mutts",
|
|
3
3
|
"description": "Modern UTility TS: A collection of TypeScript utilities",
|
|
4
|
-
"version": "1.0.
|
|
5
|
-
"main": "dist/browser.
|
|
4
|
+
"version": "1.0.9",
|
|
5
|
+
"main": "dist/browser.cjs",
|
|
6
6
|
"module": "dist/browser.esm.js",
|
|
7
7
|
"types": "dist/browser.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
+
"test-node": {
|
|
11
|
+
"import": "./src/entry-node.ts"
|
|
12
|
+
},
|
|
13
|
+
"test-browser": {
|
|
14
|
+
"import": "./src/entry-browser.ts"
|
|
15
|
+
},
|
|
10
16
|
"node": {
|
|
11
17
|
"types": "./dist/node.d.ts",
|
|
12
18
|
"import": "./dist/node.esm.js",
|
|
13
|
-
"require": "./dist/node.
|
|
19
|
+
"require": "./dist/node.cjs"
|
|
14
20
|
},
|
|
15
21
|
"default": {
|
|
16
22
|
"types": "./dist/browser.d.ts",
|
|
17
23
|
"import": "./dist/browser.esm.js",
|
|
18
|
-
"require": "./dist/browser.
|
|
24
|
+
"require": "./dist/browser.cjs"
|
|
19
25
|
}
|
|
20
26
|
},
|
|
21
27
|
"./browser": {
|
|
22
28
|
"types": "./dist/browser.d.ts",
|
|
23
29
|
"import": "./dist/browser.esm.js",
|
|
24
|
-
"require": "./dist/browser.
|
|
30
|
+
"require": "./dist/browser.cjs"
|
|
25
31
|
},
|
|
26
32
|
"./node": {
|
|
27
33
|
"types": "./dist/node.d.ts",
|
|
28
34
|
"import": "./dist/node.esm.js",
|
|
29
|
-
"require": "./dist/node.
|
|
35
|
+
"require": "./dist/node.cjs"
|
|
30
36
|
},
|
|
31
37
|
"./src": {
|
|
32
38
|
"node": {
|
|
33
|
-
"types": "./src/
|
|
34
|
-
"import": "./src/
|
|
39
|
+
"types": "./src/entry-node.ts",
|
|
40
|
+
"import": "./src/entry-node.ts"
|
|
35
41
|
},
|
|
36
42
|
"default": {
|
|
37
|
-
"types": "./src/
|
|
38
|
-
"import": "./src/
|
|
43
|
+
"types": "./src/entry-browser.ts",
|
|
44
|
+
"import": "./src/entry-browser.ts"
|
|
39
45
|
}
|
|
40
46
|
},
|
|
41
47
|
"./src/browser": {
|
|
42
|
-
"types": "./src/
|
|
43
|
-
"import": "./src/
|
|
48
|
+
"types": "./src/entry-browser.ts",
|
|
49
|
+
"import": "./src/entry-browser.ts"
|
|
44
50
|
},
|
|
45
51
|
"./src/node": {
|
|
46
|
-
"types": "./src/
|
|
47
|
-
"import": "./src/
|
|
52
|
+
"types": "./src/entry-node.ts",
|
|
53
|
+
"import": "./src/entry-node.ts"
|
|
54
|
+
},
|
|
55
|
+
"./debug": {
|
|
56
|
+
"types": "./dist/debug.d.ts",
|
|
57
|
+
"import": "./dist/debug.esm.js",
|
|
58
|
+
"require": "./dist/debug.cjs"
|
|
48
59
|
}
|
|
49
60
|
},
|
|
50
61
|
"files": [
|
|
@@ -59,14 +70,20 @@
|
|
|
59
70
|
"build": "npm run build:js && npm run build:devtools",
|
|
60
71
|
"build:watch": "rollup -c --watch",
|
|
61
72
|
"prepublishOnly": "npm run build",
|
|
62
|
-
"test": "
|
|
63
|
-
"test:
|
|
64
|
-
"test:
|
|
65
|
-
"test:
|
|
66
|
-
"test:
|
|
67
|
-
"test:
|
|
68
|
-
"test:
|
|
69
|
-
"test:
|
|
73
|
+
"test": "npm run test:node && npm run test:browser",
|
|
74
|
+
"test:node": "TEST_ENV=node NODE_OPTIONS='--expose-gc' vitest run",
|
|
75
|
+
"test:browser": "TEST_ENV=browser vitest run --browser",
|
|
76
|
+
"test:zone:node": "TEST_ENV=node vitest run tests/zone.test.ts",
|
|
77
|
+
"test:zone:browser": "TEST_ENV=browser vitest run tests/zone.test.ts",
|
|
78
|
+
"test:async:node": "TEST_ENV=node vitest run tests/async-hook.test.ts",
|
|
79
|
+
"test:async:browser": "TEST_ENV=browser vitest run tests/async-hook.test.ts",
|
|
80
|
+
"test:coverage": "TEST_ENV=node vitest run --coverage",
|
|
81
|
+
"test:coverage:watch": "TEST_ENV=node vitest run --coverage --watch",
|
|
82
|
+
"test:legacy": "TEST_ENV=node TSCONFIG=tsconfig.legacy.json vitest run --detectOpenHandles",
|
|
83
|
+
"test:modern": "TEST_ENV=node TSCONFIG=tsconfig.modern.json vitest run --detectOpenHandles",
|
|
84
|
+
"test:profile": "RUN_PROFILING=1 NODE_OPTIONS=--expose-gc vitest run",
|
|
85
|
+
"test:profile:benchmark": "RUN_PROFILING=1 NODE_OPTIONS=--expose-gc vitest run -t benchmark",
|
|
86
|
+
"test:profile:detailed": "RUN_PROFILING=1 node --prof node_modules/vitest/vitest.mjs --no-coverage",
|
|
70
87
|
"benchmark:save": "tsx tests/profiling/benchmark.ts save",
|
|
71
88
|
"benchmark:compare": "tsx tests/profiling/benchmark.ts compare",
|
|
72
89
|
"benchmark:list": "tsx tests/profiling/benchmark.ts list",
|
|
@@ -102,25 +119,25 @@
|
|
|
102
119
|
},
|
|
103
120
|
"devDependencies": {
|
|
104
121
|
"@biomejs/biome": "^2.0.6",
|
|
105
|
-
"@jest/globals": "^30.2.0",
|
|
106
122
|
"@rollup/plugin-commonjs": "^28.0.6",
|
|
107
123
|
"@rollup/plugin-json": "^6.1.0",
|
|
108
124
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
109
125
|
"@rollup/plugin-terser": "^0.4.4",
|
|
110
126
|
"@rollup/plugin-typescript": "^12.1.4",
|
|
111
|
-
"@types/jest": "^30.0.0",
|
|
112
127
|
"@types/node": "^22.10.10",
|
|
113
|
-
"
|
|
128
|
+
"@vitest/browser": "^4.0.18",
|
|
129
|
+
"@vitest/browser-playwright": "^4.0.18",
|
|
130
|
+
"playwright": "^1.58.1",
|
|
114
131
|
"rollup": "^4.52.2",
|
|
115
132
|
"rollup-plugin-copy": "^3.5.0",
|
|
116
133
|
"rollup-plugin-dts": "^6.2.3",
|
|
117
134
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
118
|
-
"ts-jest": "^29.4.0",
|
|
119
135
|
"ts-node": "^10.9.2",
|
|
120
136
|
"tslib": "^2.8.1",
|
|
121
137
|
"tsx": "^4.20.4",
|
|
122
138
|
"typescript": "^5.8.3",
|
|
123
|
-
"vis-network": "^9.1.9"
|
|
139
|
+
"vis-network": "^9.1.9",
|
|
140
|
+
"vitest": "^4.0.18"
|
|
124
141
|
},
|
|
125
142
|
"packageManager": "pnpm@10.7.1+sha512.2d92c86b7928dc8284f53494fb4201f983da65f0fb4f0d40baafa5cf628fa31dae3e5968f12466f17df7e97310e30f343a648baea1b9b350685dafafffdf5808"
|
|
126
143
|
}
|