mutts 1.0.6 → 1.0.7

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 (110) hide show
  1. package/README.md +1 -1
  2. package/dist/browser.d.ts +2 -0
  3. package/dist/browser.esm.js +70 -0
  4. package/dist/browser.esm.js.map +1 -0
  5. package/dist/browser.js +161 -0
  6. package/dist/browser.js.map +1 -0
  7. package/dist/chunks/{index-CDCOjzTy.js → index-BFYK02LG.js} +5760 -4338
  8. package/dist/chunks/index-BFYK02LG.js.map +1 -0
  9. package/dist/chunks/{index-DiP0RXoZ.esm.js → index-CNR6QRUl.esm.js} +5440 -4054
  10. package/dist/chunks/index-CNR6QRUl.esm.js.map +1 -0
  11. package/dist/devtools/panel.js.map +1 -1
  12. package/dist/mutts.umd.js +1 -1
  13. package/dist/mutts.umd.js.map +1 -1
  14. package/dist/mutts.umd.min.js +1 -1
  15. package/dist/mutts.umd.min.js.map +1 -1
  16. package/dist/node.d.ts +2 -0
  17. package/dist/node.esm.js +45 -0
  18. package/dist/node.esm.js.map +1 -0
  19. package/dist/node.js +136 -0
  20. package/dist/node.js.map +1 -0
  21. package/docs/ai/api-reference.md +0 -2
  22. package/docs/reactive/advanced.md +2 -5
  23. package/docs/reactive/collections.md +0 -125
  24. package/docs/reactive/core.md +27 -24
  25. package/docs/reactive/debugging.md +12 -2
  26. package/docs/reactive/project.md +1 -1
  27. package/docs/reactive/scan.md +78 -0
  28. package/docs/reactive.md +2 -1
  29. package/docs/std-decorators.md +1 -0
  30. package/docs/zone.md +88 -0
  31. package/package.json +42 -10
  32. package/src/async/browser.ts +87 -0
  33. package/src/async/index.ts +8 -0
  34. package/src/async/node.ts +46 -0
  35. package/src/decorator.ts +5 -1
  36. package/src/destroyable.ts +1 -1
  37. package/src/index.ts +22 -14
  38. package/src/indexable.ts +42 -0
  39. package/src/mixins.ts +2 -2
  40. package/src/reactive/array.ts +149 -141
  41. package/src/reactive/buffer.ts +168 -0
  42. package/src/reactive/change.ts +2 -2
  43. package/src/reactive/effect-context.ts +15 -91
  44. package/src/reactive/effects.ts +119 -179
  45. package/src/reactive/index.ts +10 -13
  46. package/src/reactive/interface.ts +19 -33
  47. package/src/reactive/map.ts +48 -61
  48. package/src/reactive/memoize.ts +19 -9
  49. package/src/reactive/project.ts +43 -22
  50. package/src/reactive/proxy.ts +16 -41
  51. package/src/reactive/record.ts +3 -3
  52. package/src/reactive/register.ts +5 -7
  53. package/src/reactive/registry.ts +9 -17
  54. package/src/reactive/set.ts +42 -56
  55. package/src/reactive/tracking.ts +1 -29
  56. package/src/reactive/types.ts +46 -23
  57. package/src/utils.ts +80 -37
  58. package/src/zone.ts +127 -0
  59. package/dist/chunks/_tslib-BgjropY9.js +0 -81
  60. package/dist/chunks/_tslib-BgjropY9.js.map +0 -1
  61. package/dist/chunks/_tslib-MCKDzsSq.esm.js +0 -75
  62. package/dist/chunks/_tslib-MCKDzsSq.esm.js.map +0 -1
  63. package/dist/chunks/decorator-BGILvPtN.esm.js +0 -627
  64. package/dist/chunks/decorator-BGILvPtN.esm.js.map +0 -1
  65. package/dist/chunks/decorator-BQ2eBTCj.js +0 -651
  66. package/dist/chunks/decorator-BQ2eBTCj.js.map +0 -1
  67. package/dist/chunks/index-CDCOjzTy.js.map +0 -1
  68. package/dist/chunks/index-DiP0RXoZ.esm.js.map +0 -1
  69. package/dist/decorator.d.ts +0 -107
  70. package/dist/decorator.esm.js +0 -2
  71. package/dist/decorator.esm.js.map +0 -1
  72. package/dist/decorator.js +0 -11
  73. package/dist/decorator.js.map +0 -1
  74. package/dist/destroyable.d.ts +0 -90
  75. package/dist/destroyable.esm.js +0 -109
  76. package/dist/destroyable.esm.js.map +0 -1
  77. package/dist/destroyable.js +0 -116
  78. package/dist/destroyable.js.map +0 -1
  79. package/dist/eventful.d.ts +0 -20
  80. package/dist/eventful.esm.js +0 -66
  81. package/dist/eventful.esm.js.map +0 -1
  82. package/dist/eventful.js +0 -68
  83. package/dist/eventful.js.map +0 -1
  84. package/dist/index.d.ts +0 -19
  85. package/dist/index.esm.js +0 -53
  86. package/dist/index.esm.js.map +0 -1
  87. package/dist/index.js +0 -139
  88. package/dist/index.js.map +0 -1
  89. package/dist/indexable.d.ts +0 -243
  90. package/dist/indexable.esm.js +0 -285
  91. package/dist/indexable.esm.js.map +0 -1
  92. package/dist/indexable.js +0 -291
  93. package/dist/indexable.js.map +0 -1
  94. package/dist/promiseChain.d.ts +0 -21
  95. package/dist/promiseChain.esm.js +0 -78
  96. package/dist/promiseChain.esm.js.map +0 -1
  97. package/dist/promiseChain.js +0 -80
  98. package/dist/promiseChain.js.map +0 -1
  99. package/dist/reactive.d.ts +0 -910
  100. package/dist/reactive.esm.js +0 -5
  101. package/dist/reactive.esm.js.map +0 -1
  102. package/dist/reactive.js +0 -59
  103. package/dist/reactive.js.map +0 -1
  104. package/dist/std-decorators.d.ts +0 -52
  105. package/dist/std-decorators.esm.js +0 -196
  106. package/dist/std-decorators.esm.js.map +0 -1
  107. package/dist/std-decorators.js +0 -204
  108. package/dist/std-decorators.js.map +0 -1
  109. package/src/reactive/mapped.ts +0 -129
  110. package/src/reactive/zone.ts +0 -208
@@ -1,627 +0,0 @@
1
- // biome-ignore-all lint/suspicious/noConfusingVoidType: Type 'void' is not assignable to type 'ScopedCallback | undefined'.
2
- // Argument of type '() => void' is not assignable to parameter of type '(dep: DependencyFunction) => ScopedCallback | undefined'.
3
- // Track native reactivity
4
- const nativeReactive = Symbol('native-reactive');
5
- /**
6
- * Symbol to mark individual objects as non-reactive
7
- */
8
- const nonReactiveMark = Symbol('non-reactive');
9
- /**
10
- * Symbol to mark class properties as non-reactive
11
- */
12
- const unreactiveProperties = Symbol('unreactive-properties');
13
- /**
14
- * Symbol for prototype forwarding in reactive objects
15
- */
16
- const prototypeForwarding = Symbol('prototype-forwarding');
17
- /**
18
- * Symbol representing all properties in reactive tracking
19
- */
20
- const allProps = Symbol('all-props');
21
- /**
22
- * Symbol for accessing projection information on reactive objects
23
- */
24
- const projectionInfo = Symbol('projection-info');
25
- /**
26
- * Symbol to check if an effect is stopped
27
- */
28
- const stopped = Symbol('stopped');
29
- /**
30
- * Symbol to access effect cleanup function
31
- */
32
- const cleanup = Symbol('cleanup');
33
- // Symbol to mark functions with their root function
34
- const rootFunction = Symbol('root-function');
35
- /**
36
- * Structured error codes for machine-readable diagnosis
37
- */
38
- var ReactiveErrorCode;
39
- (function (ReactiveErrorCode) {
40
- ReactiveErrorCode["CycleDetected"] = "CYCLE_DETECTED";
41
- ReactiveErrorCode["MaxDepthExceeded"] = "MAX_DEPTH_EXCEEDED";
42
- ReactiveErrorCode["MaxReactionExceeded"] = "MAX_REACTION_EXCEEDED";
43
- ReactiveErrorCode["WriteInComputed"] = "WRITE_IN_COMPUTED";
44
- ReactiveErrorCode["TrackingError"] = "TRACKING_ERROR";
45
- })(ReactiveErrorCode || (ReactiveErrorCode = {}));
46
- /**
47
- * Error class for reactive system errors
48
- */
49
- class ReactiveError extends Error {
50
- constructor(message, debugInfo) {
51
- super(message);
52
- this.debugInfo = debugInfo;
53
- this.name = 'ReactiveError';
54
- }
55
- }
56
- // biome-ignore-start lint/correctness/noUnusedFunctionParameters: Interface declaration with empty defaults
57
- /**
58
- * Global options for the reactive system
59
- */
60
- const options = {
61
- /**
62
- * Debug purpose: called when an effect is entered
63
- * @param effect - The effect that is entered
64
- */
65
- enter: (_effect) => { },
66
- /**
67
- * Debug purpose: called when an effect is left
68
- * @param effect - The effect that is left
69
- */
70
- leave: (_effect) => { },
71
- /**
72
- * Debug purpose: called when an effect is chained
73
- * @param target - The effect that is being triggered
74
- * @param caller - The effect that is calling the target
75
- */
76
- chain: (_targets, _caller) => { },
77
- /**
78
- * Debug purpose: called when an effect chain is started
79
- * @param target - The effect that is being triggered
80
- */
81
- beginChain: (_targets) => { },
82
- /**
83
- * Debug purpose: called when an effect chain is ended
84
- */
85
- endChain: () => { },
86
- garbageCollected: (_fn) => { },
87
- /**
88
- * Debug purpose: called when an object is touched
89
- * @param obj - The object that is touched
90
- * @param evolution - The type of change
91
- * @param props - The properties that changed
92
- * @param deps - The dependencies that changed
93
- */
94
- touched: (_obj, _evolution, _props, _deps) => { },
95
- /**
96
- * Debug purpose: called when an effect is skipped because it's already running
97
- * @param effect - The effect that is already running
98
- * @param runningChain - The array of effects from the detected one to the currently running one
99
- */
100
- skipRunningEffect: (_effect, _runningChain) => { },
101
- /**
102
- * Debug purpose: maximum effect chain (like call stack max depth)
103
- * Used to prevent infinite loops
104
- * @default 100
105
- */
106
- maxEffectChain: 100,
107
- /**
108
- * Maximum number of times an effect can be triggered by the same cause in a single batch
109
- * Used to detect aggressive re-computation or infinite loops
110
- * @default 10
111
- */
112
- maxTriggerPerBatch: 10,
113
- /**
114
- * Debug purpose: maximum effect reaction (like call stack max depth)
115
- * Used to prevent infinite loops
116
- * @default 'throw'
117
- */
118
- maxEffectReaction: 'throw',
119
- /**
120
- * Callback called when a memoization discrepancy is detected (debug only)
121
- * When defined, memoized functions will run a second time (untracked) to verify consistency.
122
- * If the untracked run returns a different value than the cached one, this callback is triggered.
123
- *
124
- * This is the primary tool for detecting missing reactive dependencies in computed values.
125
- *
126
- * @param cached - The value currently in the memoization cache
127
- * @param fresh - The value obtained by re-running the function untracked
128
- * @param fn - The memoized function itself
129
- * @param args - Arguments passed to the function
130
- *
131
- * @example
132
- * ```typescript
133
- * reactiveOptions.onMemoizationDiscrepancy = (cached, fresh, fn, args) => {
134
- * throw new Error(`Memoization discrepancy in ${fn.name}!`);
135
- * };
136
- * ```
137
- */
138
- onMemoizationDiscrepancy: undefined,
139
- /**
140
- * How to handle cycles detected in effect batches
141
- * - 'throw': Throw an error with cycle information (default, recommended for development)
142
- * - 'warn': Log a warning and break the cycle by executing one effect
143
- * - 'break': Silently break the cycle by executing one effect (recommended for production)
144
- * - 'strict': Prevent cycle creation by checking graph before execution (throws error)
145
- * @default 'throw'
146
- */
147
- cycleHandling: 'throw',
148
- /**
149
- * Internal flag used by memoization discrepancy detector to avoid counting calls in tests
150
- * @warning Do not modify this flag manually, this flag is given by the engine
151
- */
152
- isVerificationRun: false,
153
- /**
154
- * Maximum depth for deep watching traversal
155
- * Used to prevent infinite recursion in circular references
156
- * @default 100
157
- */
158
- maxDeepWatchDepth: 100,
159
- /**
160
- * Only react on instance members modification (not inherited properties)
161
- * For instance, do not track class methods
162
- * @default true
163
- */
164
- instanceMembers: true,
165
- /**
166
- * Ignore accessors (getters and setters) and only track direct properties
167
- * @default true
168
- */
169
- ignoreAccessors: true,
170
- /**
171
- * Enable recursive touching when objects with the same prototype are replaced
172
- * When enabled, replacing an object with another of the same prototype triggers
173
- * recursive diffing instead of notifying parent effects
174
- * @default true
175
- */
176
- recursiveTouching: true,
177
- /**
178
- * Default async execution mode for effects that return Promises
179
- * - 'cancel': Cancel previous async execution when dependencies change (default, enables async zone)
180
- * - 'queue': Queue next execution to run after current completes (enables async zone)
181
- * - 'ignore': Ignore new executions while async work is running (enables async zone)
182
- * - false: Disable async zone and async mode handling (effects run concurrently)
183
- *
184
- * **When truthy:** Enables async zone (Promise.prototype wrapping) for automatic context
185
- * preservation in Promise callbacks. Warning: This modifies Promise.prototype globally.
186
- * Only enable if no other library modifies Promise.prototype.
187
- *
188
- * **When false:** Async zone is disabled. Use `tracked()` manually in Promise callbacks.
189
- *
190
- * Can be overridden per-effect via EffectOptions
191
- * @default 'cancel'
192
- */
193
- asyncMode: 'cancel',
194
- // biome-ignore lint/suspicious/noConsole: This is the whole point here
195
- warn: (...args) => console.warn(...args),
196
- /**
197
- * Configuration for the introspection system
198
- */
199
- introspection: {
200
- /**
201
- * Whether to keep a history of mutations for debugging
202
- * @default false
203
- */
204
- enableHistory: false,
205
- /**
206
- * Number of mutations to keep in history
207
- * @default 50
208
- */
209
- historySize: 50,
210
- },
211
- /**
212
- * Configuration for zone hooks - control which async APIs are hooked
213
- * Each option controls whether the corresponding async API is wrapped to preserve effect context
214
- * Only applies when asyncMode is enabled (truthy)
215
- */
216
- zones: {
217
- /**
218
- * Hook setTimeout to preserve effect context
219
- * @default true
220
- */
221
- setTimeout: true,
222
- /**
223
- * Hook setInterval to preserve effect context
224
- * @default true
225
- */
226
- setInterval: true,
227
- /**
228
- * Hook requestAnimationFrame (runs in untracked context when hooked)
229
- * @default true
230
- */
231
- requestAnimationFrame: true,
232
- /**
233
- * Hook queueMicrotask to preserve effect context
234
- * @default true
235
- */
236
- queueMicrotask: true,
237
- },
238
- };
239
-
240
- /**
241
- * Combines multiple arrays into an array of tuples, stopping at the shortest array length
242
- * @param args - Arrays to zip together
243
- * @returns Array of tuples containing elements from each input array
244
- */
245
- function zip(...args) {
246
- if (!args.length)
247
- return [];
248
- const minLength = Math.min(...args.map((arr) => arr.length));
249
- const result = [];
250
- for (let i = 0; i < minLength; i++) {
251
- const tuple = args.map((arr) => arr[i]);
252
- result.push(tuple);
253
- }
254
- return result;
255
- }
256
- /**
257
- * Checks if two arrays are strictly equal (shallow comparison)
258
- * @param a - First value
259
- * @param b - Second value
260
- * @returns True if arrays are equal or values are strictly equal
261
- */
262
- function arrayEquals(a, b) {
263
- if (a === b)
264
- return true;
265
- if (!Array.isArray(a) || !Array.isArray(b))
266
- return false;
267
- if (a.length !== b.length)
268
- return false;
269
- for (let i = 0; i < a.length; i++) {
270
- if (a[i] !== b[i])
271
- return false;
272
- }
273
- return true;
274
- }
275
- const nativeConstructors = new Set([
276
- Object,
277
- Array,
278
- Date,
279
- Function,
280
- Set,
281
- Map,
282
- WeakMap,
283
- WeakSet,
284
- Promise,
285
- Error,
286
- TypeError,
287
- ReferenceError,
288
- SyntaxError,
289
- RangeError,
290
- URIError,
291
- EvalError,
292
- Reflect,
293
- Proxy,
294
- RegExp,
295
- String,
296
- Number,
297
- Boolean,
298
- ]);
299
- /**
300
- * Checks if a function is a constructor (class or constructor function)
301
- * @param fn - The function to check
302
- * @returns True if the function is a constructor
303
- */
304
- function isConstructor(fn) {
305
- return (fn &&
306
- typeof fn === 'function' &&
307
- (nativeConstructors.has(fn) || fn.toString?.().startsWith('class ')));
308
- }
309
- /**
310
- * Renames a function with a new name
311
- * @param fct - The function to rename
312
- * @param name - The new name for the function
313
- * @returns The function with the new name
314
- */
315
- function renamed(fct, name) {
316
- return Object.defineProperties(fct, {
317
- name: {
318
- value: name,
319
- },
320
- });
321
- }
322
- function ReflectGet(obj, prop, receiver) {
323
- // Check if Node is available and obj is an instance of Node
324
- if (typeof Node !== 'undefined' && obj instanceof Node)
325
- return obj[prop];
326
- return Reflect.get(obj, prop, receiver);
327
- }
328
- function ReflectSet(obj, prop, value, receiver) {
329
- // Check if Node is available and obj is an instance of Node
330
- if (typeof Node !== 'undefined' && obj instanceof Node) {
331
- obj[prop] = value;
332
- return true;
333
- }
334
- if (!(obj instanceof Object) && !Reflect.has(obj, prop)) {
335
- Object.defineProperty(obj, prop, {
336
- value,
337
- configurable: true,
338
- writable: true,
339
- enumerable: true,
340
- });
341
- return true;
342
- }
343
- return Reflect.set(obj, prop, value, receiver);
344
- }
345
- function isOwnAccessor(obj, prop) {
346
- const opd = Object.getOwnPropertyDescriptor(obj, prop);
347
- return !!(opd?.get || opd?.set);
348
- }
349
- /**
350
- * Deeply compares two values.
351
- * For objects, compares prototypes with === and then own properties recursively.
352
- * Uses a cache to handle circular references.
353
- * @param a - First value
354
- * @param b - Second value
355
- * @param cache - Map for circular reference protection (internal use)
356
- * @returns True if values are deeply equal
357
- */
358
- function deepCompare(a, b, cache = new Map()) {
359
- // Unwrap mutts proxies if present
360
- while (a && typeof a === 'object' && prototypeForwarding in a) {
361
- a = a[prototypeForwarding];
362
- }
363
- while (b && typeof b === 'object' && prototypeForwarding in b) {
364
- b = b[prototypeForwarding];
365
- }
366
- if (a === b)
367
- return true;
368
- if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) {
369
- return a === b;
370
- }
371
- // Prototype check
372
- const protoA = Object.getPrototypeOf(a);
373
- const protoB = Object.getPrototypeOf(b);
374
- if (protoA !== protoB) {
375
- console.warn(`[deepCompare] prototype mismatch:`, { nameA: a?.constructor?.name, nameB: b?.constructor?.name });
376
- return false;
377
- }
378
- // Circular reference protection
379
- let compared = cache.get(a);
380
- if (compared?.has(b))
381
- return true;
382
- if (!compared) {
383
- compared = new Set();
384
- cache.set(a, compared);
385
- }
386
- compared.add(b);
387
- // Handle specific object types
388
- if (Array.isArray(a)) {
389
- if (!Array.isArray(b)) {
390
- console.warn(`[deepCompare] B is not an array`);
391
- return false;
392
- }
393
- if (a.length !== b.length) {
394
- console.warn(`[deepCompare] array length mismatch:`, { lenA: a.length, lenB: b.length });
395
- return false;
396
- }
397
- for (let i = 0; i < a.length; i++) {
398
- if (!deepCompare(a[i], b[i], cache)) {
399
- console.warn(`[deepCompare] array element mismatch at index ${i}`);
400
- return false;
401
- }
402
- }
403
- return true;
404
- }
405
- if (a instanceof Date) {
406
- const match = b instanceof Date && a.getTime() === b.getTime();
407
- if (!match)
408
- console.warn(`[deepCompare] Date mismatch`);
409
- return match;
410
- }
411
- if (a instanceof RegExp) {
412
- const match = b instanceof RegExp && a.toString() === b.toString();
413
- if (!match)
414
- console.warn(`[deepCompare] RegExp mismatch`);
415
- return match;
416
- }
417
- if (a instanceof Set) {
418
- if (!(b instanceof Set) || a.size !== b.size) {
419
- console.warn(`[deepCompare] Set size mismatch`);
420
- return false;
421
- }
422
- for (const val of a) {
423
- let found = false;
424
- for (const bVal of b) {
425
- if (deepCompare(val, bVal, cache)) {
426
- found = true;
427
- break;
428
- }
429
- }
430
- if (!found) {
431
- console.warn(`[deepCompare] missing Set element`);
432
- return false;
433
- }
434
- }
435
- return true;
436
- }
437
- if (a instanceof Map) {
438
- if (!(b instanceof Map) || a.size !== b.size) {
439
- console.warn(`[deepCompare] Map size mismatch`);
440
- return false;
441
- }
442
- for (const [key, val] of a) {
443
- if (!b.has(key)) {
444
- let foundMatch = false;
445
- for (const [bKey, bVal] of b) {
446
- if (deepCompare(key, bKey, cache) && deepCompare(val, bVal, cache)) {
447
- foundMatch = true;
448
- break;
449
- }
450
- }
451
- if (!foundMatch) {
452
- console.warn(`[deepCompare] missing Map key`);
453
- return false;
454
- }
455
- }
456
- else {
457
- if (!deepCompare(val, b.get(key), cache)) {
458
- console.warn(`[deepCompare] Map value mismatch for key`);
459
- return false;
460
- }
461
- }
462
- }
463
- return true;
464
- }
465
- // Compare own properties
466
- const keysA = Object.keys(a);
467
- const keysB = Object.keys(b);
468
- if (keysA.length !== keysB.length) {
469
- console.warn(`[deepCompare] keys length mismatch:`, { lenA: keysA.length, lenB: keysB.length, keysA, keysB, a, b });
470
- return false;
471
- }
472
- for (const key of keysA) {
473
- if (!Object.prototype.hasOwnProperty.call(b, key)) {
474
- console.warn(`[deepCompare] missing key ${String(key)} in B`);
475
- return false;
476
- }
477
- if (!deepCompare(a[key], b[key], cache)) {
478
- console.warn(`[deepCompare] value mismatch for key ${String(key)}:`, { valA: a[key], valB: b[key] });
479
- return false;
480
- }
481
- }
482
- return true;
483
- }
484
-
485
- // biome-ignore-all lint/suspicious/noConfusingVoidType: We *love* voids
486
- // Standardized decorator system that works with both Legacy and Modern decorators
487
- /**
488
- * Error thrown when decorator operations fail
489
- */
490
- class DecoratorError extends Error {
491
- constructor(message) {
492
- super(message);
493
- this.name = 'DecoratorException';
494
- }
495
- }
496
- /**
497
- * Creates a decorator that works with Legacy decorator proposals
498
- * @param description - The decorator description object
499
- * @returns A decorator function compatible with Legacy decorators
500
- */
501
- function legacyDecorator(description) {
502
- return function (target, propertyKey, descriptor, ...args) {
503
- if (propertyKey === undefined) {
504
- if (isConstructor(target)) {
505
- if (!('class' in description))
506
- throw new Error('Decorator cannot be applied to a class');
507
- return description.class(target);
508
- }
509
- }
510
- else if (typeof target === 'object' && ['string', 'symbol'].includes(typeof propertyKey)) {
511
- if (!descriptor)
512
- throw new Error('Decorator cannot be applied to a field');
513
- else if (typeof descriptor === 'object' && 'configurable' in descriptor) {
514
- if ('get' in descriptor || 'set' in descriptor) {
515
- if (!('getter' in description || 'setter' in description))
516
- throw new Error('Decorator cannot be applied to a getter or setter');
517
- if ('getter' in description) {
518
- const newGetter = description.getter(descriptor.get, target, propertyKey);
519
- if (newGetter)
520
- descriptor.get = newGetter;
521
- }
522
- if ('setter' in description) {
523
- const newSetter = description.setter(descriptor.set, target, propertyKey);
524
- if (newSetter)
525
- descriptor.set = newSetter;
526
- }
527
- return descriptor;
528
- }
529
- else if (typeof descriptor.value === 'function') {
530
- if (!('method' in description))
531
- throw new Error('Decorator cannot be applied to a method');
532
- const newMethod = description.method(descriptor.value, target, propertyKey);
533
- if (newMethod)
534
- descriptor.value = newMethod;
535
- return descriptor;
536
- }
537
- }
538
- }
539
- if (!('default' in description))
540
- throw new Error('Decorator do not have a default implementation');
541
- return description.default.call(this, target, propertyKey, descriptor, ...args);
542
- };
543
- }
544
- /**
545
- * Creates a decorator that works with Modern decorator proposals
546
- * @param description - The decorator description object
547
- * @returns A decorator function compatible with Modern decorators
548
- */
549
- function modernDecorator(description) {
550
- /*return function (target: any, context?: DecoratorContext, ...args: any[]) {*/
551
- return function (target, context, ...args) {
552
- if (!context?.kind || typeof context.kind !== 'string') {
553
- if (!('default' in description))
554
- throw new Error('Decorator do not have a default implementation');
555
- return description.default.call(this, target, context, ...args);
556
- }
557
- switch (context.kind) {
558
- case 'class':
559
- if (!('class' in description))
560
- throw new Error('Decorator cannot be applied to a class');
561
- return description.class(target);
562
- case 'field':
563
- throw new Error('Decorator cannot be applied to a field');
564
- case 'getter':
565
- if (!('getter' in description))
566
- throw new Error('Decorator cannot be applied to a getter');
567
- return description.getter(target, target, context.name);
568
- case 'setter':
569
- if (!('setter' in description))
570
- throw new Error('Decorator cannot be applied to a setter');
571
- return description.setter(target, target, context.name);
572
- case 'method':
573
- if (!('method' in description))
574
- throw new Error('Decorator cannot be applied to a method');
575
- return description.method(target, target, context.name);
576
- case 'accessor': {
577
- if (!('getter' in description || 'setter' in description))
578
- throw new Error('Decorator cannot be applied to a getter or setter');
579
- const rv = {};
580
- if ('getter' in description) {
581
- const newGetter = description.getter(target.get, target, context.name);
582
- if (newGetter)
583
- rv.get = newGetter;
584
- }
585
- if ('setter' in description) {
586
- const newSetter = description.setter(target.set, target, context.name);
587
- if (newSetter)
588
- rv.set = newSetter;
589
- }
590
- return rv;
591
- }
592
- //return description.accessor?.(target, context.name, target)
593
- }
594
- };
595
- }
596
- /**
597
- * Detects if the decorator is being called in modern (Modern) or legacy (Legacy) mode
598
- * based on the arguments passed to the decorator function
599
- */
600
- function detectDecoratorMode(_target, contextOrKey, _descriptor) {
601
- // Modern decorators have a context object as the second parameter
602
- // Legacy decorators have a string/symbol key as the second parameter
603
- if (typeof contextOrKey === 'object' &&
604
- contextOrKey !== null &&
605
- typeof contextOrKey.kind === 'string') {
606
- return 'modern';
607
- }
608
- return 'legacy';
609
- }
610
- /**
611
- * Main decorator factory that automatically detects and works with both Legacy and Modern decorator proposals
612
- * @param description - The decorator description object
613
- * @returns A decorator that works in both Legacy and Modern environments
614
- */
615
- const decorator = (description) => {
616
- const modern = modernDecorator(description);
617
- const legacy = legacyDecorator(description);
618
- return ((target, contextOrKey, ...args) => {
619
- const mode = detectDecoratorMode(target, contextOrKey, args[0]);
620
- return mode === 'modern'
621
- ? modern(target, contextOrKey, ...args)
622
- : legacy(target, contextOrKey, ...args);
623
- });
624
- };
625
-
626
- export { DecoratorError as D, ReactiveError as R, ReflectGet as a, ReflectSet as b, arrayEquals as c, decorator as d, deepCompare as e, isOwnAccessor as f, rootFunction as g, allProps as h, isConstructor as i, ReactiveErrorCode as j, cleanup as k, legacyDecorator as l, modernDecorator as m, nonReactiveMark as n, options as o, nativeReactive as p, prototypeForwarding as q, renamed as r, stopped as s, projectionInfo as t, unreactiveProperties as u, zip as z };
627
- //# sourceMappingURL=decorator-BGILvPtN.esm.js.map