mutts 1.0.5 → 1.0.6
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 +1 -0
- package/dist/chunks/{_tslib-Mzh1rNsX.esm.js → _tslib-MCKDzsSq.esm.js} +2 -2
- package/dist/chunks/_tslib-MCKDzsSq.esm.js.map +1 -0
- package/dist/chunks/decorator-BGILvPtN.esm.js +627 -0
- package/dist/chunks/decorator-BGILvPtN.esm.js.map +1 -0
- package/dist/chunks/decorator-BQ2eBTCj.js +651 -0
- package/dist/chunks/decorator-BQ2eBTCj.js.map +1 -0
- package/dist/chunks/{index-Cvxdw6Ax.js → index-CDCOjzTy.js} +396 -500
- package/dist/chunks/index-CDCOjzTy.js.map +1 -0
- package/dist/chunks/{index-qiWwozOc.esm.js → index-DiP0RXoZ.esm.js} +301 -403
- package/dist/chunks/index-DiP0RXoZ.esm.js.map +1 -0
- package/dist/decorator.d.ts +3 -3
- package/dist/decorator.esm.js +1 -1
- package/dist/decorator.js +1 -1
- package/dist/destroyable.esm.js +4 -4
- package/dist/destroyable.esm.js.map +1 -1
- package/dist/destroyable.js +4 -4
- package/dist/destroyable.js.map +1 -1
- package/dist/devtools/panel.js.map +1 -1
- package/dist/eventful.esm.js +1 -1
- package/dist/index.esm.js +48 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +48 -4
- package/dist/index.js.map +1 -1
- 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/reactive.d.ts +25 -0
- package/dist/reactive.esm.js +3 -3
- package/dist/reactive.js +4 -4
- package/dist/std-decorators.d.ts +1 -1
- package/dist/std-decorators.esm.js +10 -10
- package/dist/std-decorators.esm.js.map +1 -1
- package/dist/std-decorators.js +10 -10
- package/dist/std-decorators.js.map +1 -1
- package/docs/ai/manual.md +14 -95
- package/docs/reactive/advanced.md +6 -107
- package/docs/reactive/debugging.md +158 -0
- package/docs/reactive.md +6 -5
- package/package.json +16 -66
- package/src/decorator.ts +11 -9
- package/src/destroyable.ts +3 -3
- package/src/index.ts +46 -0
- package/src/reactive/change.ts +1 -1
- package/src/reactive/debug.ts +1 -1
- package/src/reactive/deep-touch.ts +1 -1
- package/src/reactive/deep-watch.ts +1 -1
- package/src/reactive/effect-context.ts +2 -2
- package/src/reactive/effects.ts +44 -16
- package/src/reactive/index.ts +1 -1
- package/src/reactive/interface.ts +9 -8
- package/src/reactive/memoize.ts +77 -31
- package/src/reactive/proxy.ts +4 -4
- package/src/reactive/registry.ts +67 -0
- package/src/reactive/tracking.ts +12 -41
- package/src/reactive/types.ts +37 -0
- package/src/std-decorators.ts +9 -9
- package/src/utils.ts +141 -0
- package/dist/chunks/_tslib-Mzh1rNsX.esm.js.map +0 -1
- package/dist/chunks/decorator-DLvrD0UF.js +0 -265
- package/dist/chunks/decorator-DLvrD0UF.js.map +0 -1
- package/dist/chunks/decorator-DqiszP7i.esm.js +0 -253
- package/dist/chunks/decorator-DqiszP7i.esm.js.map +0 -1
- package/dist/chunks/index-Cvxdw6Ax.js.map +0 -1
- package/dist/chunks/index-qiWwozOc.esm.js.map +0 -1
package/dist/reactive.d.ts
CHANGED
|
@@ -218,6 +218,26 @@ declare const options: {
|
|
|
218
218
|
* @default 'throw'
|
|
219
219
|
*/
|
|
220
220
|
maxEffectReaction: "throw" | "debug" | "warn";
|
|
221
|
+
/**
|
|
222
|
+
* Callback called when a memoization discrepancy is detected (debug only)
|
|
223
|
+
* When defined, memoized functions will run a second time (untracked) to verify consistency.
|
|
224
|
+
* If the untracked run returns a different value than the cached one, this callback is triggered.
|
|
225
|
+
*
|
|
226
|
+
* This is the primary tool for detecting missing reactive dependencies in computed values.
|
|
227
|
+
*
|
|
228
|
+
* @param cached - The value currently in the memoization cache
|
|
229
|
+
* @param fresh - The value obtained by re-running the function untracked
|
|
230
|
+
* @param fn - The memoized function itself
|
|
231
|
+
* @param args - Arguments passed to the function
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```typescript
|
|
235
|
+
* reactiveOptions.onMemoizationDiscrepancy = (cached, fresh, fn, args) => {
|
|
236
|
+
* throw new Error(`Memoization discrepancy in ${fn.name}!`);
|
|
237
|
+
* };
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
onMemoizationDiscrepancy: ((cached: any, fresh: any, fn: Function, args: any[], cause: "calculation" | "comparison") => void) | undefined;
|
|
221
241
|
/**
|
|
222
242
|
* How to handle cycles detected in effect batches
|
|
223
243
|
* - 'throw': Throw an error with cycle information (default, recommended for development)
|
|
@@ -227,6 +247,11 @@ declare const options: {
|
|
|
227
247
|
* @default 'throw'
|
|
228
248
|
*/
|
|
229
249
|
cycleHandling: "throw" | "warn" | "break" | "strict";
|
|
250
|
+
/**
|
|
251
|
+
* Internal flag used by memoization discrepancy detector to avoid counting calls in tests
|
|
252
|
+
* @warning Do not modify this flag manually, this flag is given by the engine
|
|
253
|
+
*/
|
|
254
|
+
isVerificationRun: boolean;
|
|
230
255
|
/**
|
|
231
256
|
* Maximum depth for deep watching traversal
|
|
232
257
|
* Used to prevent infinite recursion in circular references
|
package/dist/reactive.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
|
|
1
|
+
export { R as ReactiveBase, b as ReadOnlyError, c as Register, d as addBatchCleanup, e as atomic, f as batch, g as biDi, h as buildReactivityGraph, i as cleanedBy, j as cleanup, k as deepWatch, l as defer, m as derived, n as effect, o as enableDevTools, p as getActivationLog, q as getActiveEffect, r as getActiveProjection, s as getState, t as immutables, u as isDevtoolsEnabled, v as isNonReactive, w as isReactive, x as isZoneEnabled, y as mapped, z as memoize, B as organize, C as organized, D as profileInfo, E as project, F as reactive, G as reduced, H as register, J as registerEffectForDebug, K as registerNativeReactivity, L as registerObjectForDebug, M as root, N as setEffectName, O as setObjectName, P as setZoneEnabled, Q as touched, S as touched1, T as trackEffect, U as unreactive, V as untracked, W as unwrap, X as watch } from './chunks/index-DiP0RXoZ.esm.js';
|
|
2
|
+
export { R as ReactiveError, o as reactiveOptions } from './chunks/decorator-BGILvPtN.esm.js';
|
|
3
3
|
import './indexable.esm.js';
|
|
4
|
-
import './chunks/_tslib-
|
|
4
|
+
import './chunks/_tslib-MCKDzsSq.esm.js';
|
|
5
5
|
//# sourceMappingURL=reactive.esm.js.map
|
package/dist/reactive.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var reactive = require('./chunks/index-
|
|
4
|
-
require('./chunks/decorator-
|
|
3
|
+
var reactive = require('./chunks/index-CDCOjzTy.js');
|
|
4
|
+
var decorator = require('./chunks/decorator-BQ2eBTCj.js');
|
|
5
5
|
require('./indexable.js');
|
|
6
6
|
require('./chunks/_tslib-BgjropY9.js');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
exports.ReactiveBase = reactive.ReactiveBase;
|
|
11
|
-
exports.ReactiveError = reactive.ReactiveError;
|
|
12
11
|
exports.ReadOnlyError = reactive.ReadOnlyError;
|
|
13
12
|
exports.Register = reactive.Register;
|
|
14
13
|
exports.addBatchCleanup = reactive.addBatchCleanup;
|
|
@@ -39,7 +38,6 @@ exports.organized = reactive.organized;
|
|
|
39
38
|
exports.profileInfo = reactive.profileInfo;
|
|
40
39
|
exports.project = reactive.project;
|
|
41
40
|
exports.reactive = reactive.reactive;
|
|
42
|
-
exports.reactiveOptions = reactive.options;
|
|
43
41
|
exports.reduced = reactive.reduced;
|
|
44
42
|
exports.register = reactive.register;
|
|
45
43
|
exports.registerEffectForDebug = reactive.registerEffectForDebug;
|
|
@@ -56,4 +54,6 @@ exports.unreactive = reactive.unreactive;
|
|
|
56
54
|
exports.untracked = reactive.untracked;
|
|
57
55
|
exports.unwrap = reactive.unwrap;
|
|
58
56
|
exports.watch = reactive.watch;
|
|
57
|
+
exports.ReactiveError = decorator.ReactiveError;
|
|
58
|
+
exports.reactiveOptions = decorator.options;
|
|
59
59
|
//# sourceMappingURL=reactive.js.map
|
package/dist/std-decorators.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LegacyPropertyDecorator, ModernGetterDecorator, ModernAccessorDecorator,
|
|
1
|
+
import { LegacyPropertyDecorator, ModernGetterDecorator, ModernAccessorDecorator, ModernMethodDecorator, LegacyClassDecorator, ModernClassDecorator, ModernSetterDecorator, GenericClassDecorator } from './decorator.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Decorator that caches the result of a getter method and only recomputes when dependencies change
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as decorator } from './chunks/decorator-
|
|
1
|
+
import { d as decorator } from './chunks/decorator-BGILvPtN.esm.js';
|
|
2
2
|
|
|
3
3
|
// In order to avoid async re-entrance, we could use zone.js or something like that.
|
|
4
4
|
const syncCalculating = [];
|
|
@@ -7,7 +7,7 @@ const syncCalculating = [];
|
|
|
7
7
|
* Prevents circular dependencies and provides automatic cache invalidation
|
|
8
8
|
*/
|
|
9
9
|
const cached = decorator({
|
|
10
|
-
getter(original, propertyKey) {
|
|
10
|
+
getter(original, _target, propertyKey) {
|
|
11
11
|
return function () {
|
|
12
12
|
const alreadyCalculating = syncCalculating.findIndex((c) => c.object === this && c.prop === propertyKey);
|
|
13
13
|
if (alreadyCalculating > -1)
|
|
@@ -70,19 +70,19 @@ function describe(descriptor) {
|
|
|
70
70
|
* Provides warning messages when deprecated items are used
|
|
71
71
|
*/
|
|
72
72
|
const deprecated = Object.assign(decorator({
|
|
73
|
-
method(original, propertyKey) {
|
|
73
|
+
method(original, _target, propertyKey) {
|
|
74
74
|
return function (...args) {
|
|
75
75
|
deprecated.warn(this, propertyKey);
|
|
76
76
|
return original.apply(this, args);
|
|
77
77
|
};
|
|
78
78
|
},
|
|
79
|
-
getter(original, propertyKey) {
|
|
79
|
+
getter(original, _target, propertyKey) {
|
|
80
80
|
return function () {
|
|
81
81
|
deprecated.warn(this, propertyKey);
|
|
82
82
|
return original.call(this);
|
|
83
83
|
};
|
|
84
84
|
},
|
|
85
|
-
setter(original, propertyKey) {
|
|
85
|
+
setter(original, _target, propertyKey) {
|
|
86
86
|
return function (value) {
|
|
87
87
|
deprecated.warn(this, propertyKey);
|
|
88
88
|
return original.call(this, value);
|
|
@@ -98,19 +98,19 @@ const deprecated = Object.assign(decorator({
|
|
|
98
98
|
},
|
|
99
99
|
default(message) {
|
|
100
100
|
return decorator({
|
|
101
|
-
method(original, propertyKey) {
|
|
101
|
+
method(original, _target, propertyKey) {
|
|
102
102
|
return function (...args) {
|
|
103
103
|
deprecated.warn(this, propertyKey, message);
|
|
104
104
|
return original.apply(this, args);
|
|
105
105
|
};
|
|
106
106
|
},
|
|
107
|
-
getter(original, propertyKey) {
|
|
107
|
+
getter(original, _target, propertyKey) {
|
|
108
108
|
return function () {
|
|
109
109
|
deprecated.warn(this, propertyKey, message);
|
|
110
110
|
return original.call(this);
|
|
111
111
|
};
|
|
112
112
|
},
|
|
113
|
-
setter(original, propertyKey) {
|
|
113
|
+
setter(original, _target, propertyKey) {
|
|
114
114
|
return function (value) {
|
|
115
115
|
deprecated.warn(this, propertyKey, message);
|
|
116
116
|
return original.call(this, value);
|
|
@@ -139,7 +139,7 @@ const deprecated = Object.assign(decorator({
|
|
|
139
139
|
*/
|
|
140
140
|
function debounce(delay) {
|
|
141
141
|
return decorator({
|
|
142
|
-
method(original, _propertyKey) {
|
|
142
|
+
method(original, _target, _propertyKey) {
|
|
143
143
|
let timeoutId = null;
|
|
144
144
|
return function (...args) {
|
|
145
145
|
// Clear existing timeout
|
|
@@ -162,7 +162,7 @@ function debounce(delay) {
|
|
|
162
162
|
*/
|
|
163
163
|
function throttle(delay) {
|
|
164
164
|
return decorator({
|
|
165
|
-
method(original, _propertyKey) {
|
|
165
|
+
method(original, _target, _propertyKey) {
|
|
166
166
|
let lastCallTime = 0;
|
|
167
167
|
let timeoutId = null;
|
|
168
168
|
return function (...args) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"std-decorators.esm.js","sources":["../src/std-decorators.ts"],"sourcesContent":["import { decorator, type GenericClassDecorator } from './decorator'\n\n// In order to avoid async re-entrance, we could use zone.js or something like that.\nconst syncCalculating: { object: object; prop: PropertyKey }[] = []\n/**\n * Decorator that caches the result of a getter method and only recomputes when dependencies change\n * Prevents circular dependencies and provides automatic cache invalidation\n */\nexport const cached = decorator({\n\tgetter(original, propertyKey) {\n\t\treturn function (this: any) {\n\t\t\tconst alreadyCalculating = syncCalculating.findIndex(\n\t\t\t\t(c) => c.object === this && c.prop === propertyKey\n\t\t\t)\n\t\t\tif (alreadyCalculating > -1)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Circular dependency detected: ${syncCalculating\n\t\t\t\t\t\t.slice(alreadyCalculating)\n\t\t\t\t\t\t.map((c) => `${c.object.constructor.name}.${String(c.prop)}`)\n\t\t\t\t\t\t.join(' -> ')} -> again`\n\t\t\t\t)\n\t\t\tsyncCalculating.push({ object: this, prop: propertyKey })\n\t\t\ttry {\n\t\t\t\tconst rv = original.call(this)\n\t\t\t\tcache(this, propertyKey, rv)\n\t\t\t\treturn rv\n\t\t\t} finally {\n\t\t\t\tsyncCalculating.pop()\n\t\t\t}\n\t\t}\n\t},\n})\n\n/**\n * Checks if a property is cached (has a cached value)\n * @param object - The object to check\n * @param propertyKey - The property key to check\n * @returns True if the property has a cached value\n */\nexport function isCached(object: Object, propertyKey: PropertyKey) {\n\treturn !!Object.getOwnPropertyDescriptor(object, propertyKey)\n}\n\n/**\n * Caches a value for a property on an object\n * @param object - The object to cache the value on\n * @param propertyKey - The property key to cache\n * @param value - The value to cache\n */\nexport function cache(object: Object, propertyKey: PropertyKey, value: any) {\n\tObject.defineProperty(object, propertyKey, { value })\n}\n\n/**\n * Creates a decorator that modifies property descriptors for specified properties\n * @param descriptor - The descriptor properties to apply\n * @returns A class decorator that applies the descriptor to specified properties\n */\nexport function describe(descriptor: {\n\tenumerable?: boolean\n\tconfigurable?: boolean // Not modifiable once the property has been defined ?\n\twritable?: boolean\n}) {\n\treturn <T>(...properties: (keyof T)[]): GenericClassDecorator<T> =>\n\t\t(Base) => {\n\t\t\treturn class extends Base {\n\t\t\t\tconstructor(...args: any[]) {\n\t\t\t\t\tsuper(...args)\n\t\t\t\t\tfor (const key of properties) {\n\t\t\t\t\t\tObject.defineProperty(this, key, {\n\t\t\t\t\t\t\t...Object.getOwnPropertyDescriptor(this, key),\n\t\t\t\t\t\t\t...descriptor,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n}\n\n/**\n * Decorator that marks methods, properties, or classes as deprecated\n * Provides warning messages when deprecated items are used\n */\nexport const deprecated = Object.assign(\n\tdecorator({\n\t\tmethod(original, propertyKey) {\n\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\tdeprecated.warn(this, propertyKey)\n\t\t\t\treturn original.apply(this, args)\n\t\t\t}\n\t\t},\n\t\tgetter(original, propertyKey) {\n\t\t\treturn function (this: any) {\n\t\t\t\tdeprecated.warn(this, propertyKey)\n\t\t\t\treturn original.call(this)\n\t\t\t}\n\t\t},\n\t\tsetter(original, propertyKey) {\n\t\t\treturn function (this: any, value: any) {\n\t\t\t\tdeprecated.warn(this, propertyKey)\n\t\t\t\treturn original.call(this, value)\n\t\t\t}\n\t\t},\n\t\tclass(original) {\n\t\t\treturn class extends original {\n\t\t\t\tconstructor(...args: any[]) {\n\t\t\t\t\tsuper(...args)\n\t\t\t\t\tdeprecated.warn(this, 'constructor')\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tdefault(message: string) {\n\t\t\treturn decorator({\n\t\t\t\tmethod(original, propertyKey) {\n\t\t\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\t\t\tdeprecated.warn(this, propertyKey, message)\n\t\t\t\t\t\treturn original.apply(this, args)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tgetter(original, propertyKey) {\n\t\t\t\t\treturn function (this: any) {\n\t\t\t\t\t\tdeprecated.warn(this, propertyKey, message)\n\t\t\t\t\t\treturn original.call(this)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsetter(original, propertyKey) {\n\t\t\t\t\treturn function (this: any, value: any) {\n\t\t\t\t\t\tdeprecated.warn(this, propertyKey, message)\n\t\t\t\t\t\treturn original.call(this, value)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tclass(original) {\n\t\t\t\t\treturn class extends original {\n\t\t\t\t\t\tconstructor(...args: any[]) {\n\t\t\t\t\t\t\tsuper(...args)\n\t\t\t\t\t\t\tdeprecated.warn(this, 'constructor', message)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t})\n\t\t},\n\t}),\n\t{\n\t\twarn: (target: any, propertyKey: PropertyKey, message?: string) => {\n\t\t\t// biome-ignore lint/suspicious/noConsole: To be overridden\n\t\t\tconsole.warn(\n\t\t\t\t`${target.constructor.name}.${String(propertyKey)} is deprecated${message ? `: ${message}` : ''}`\n\t\t\t)\n\t\t},\n\t}\n)\n\n/**\n * Creates a debounced method decorator that delays execution until after the delay period has passed\n * @param delay - The delay in milliseconds\n * @returns A method decorator that debounces method calls\n */\nexport function debounce(delay: number) {\n\treturn decorator({\n\t\tmethod(original, _propertyKey) {\n\t\t\tlet timeoutId: ReturnType<typeof setTimeout> | null = null\n\n\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\t// Clear existing timeout\n\t\t\t\tif (timeoutId) {\n\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t}\n\n\t\t\t\t// Set new timeout\n\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\toriginal.apply(this, args)\n\t\t\t\t\ttimeoutId = null\n\t\t\t\t}, delay)\n\t\t\t}\n\t\t},\n\t})\n}\n\n/**\n * Creates a throttled method decorator that limits execution to once per delay period\n * @param delay - The delay in milliseconds\n * @returns A method decorator that throttles method calls\n */\nexport function throttle(delay: number) {\n\treturn decorator({\n\t\tmethod(original, _propertyKey) {\n\t\t\tlet lastCallTime = 0\n\t\t\tlet timeoutId: ReturnType<typeof setTimeout> | null = null\n\n\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\tconst now = Date.now()\n\n\t\t\t\t// If enough time has passed since last call, execute immediately\n\t\t\t\tif (now - lastCallTime >= delay) {\n\t\t\t\t\t// Clear any pending timeout since we're executing now\n\t\t\t\t\tif (timeoutId) {\n\t\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t\t\ttimeoutId = null\n\t\t\t\t\t}\n\t\t\t\t\tlastCallTime = now\n\t\t\t\t\treturn original.apply(this, args)\n\t\t\t\t}\n\n\t\t\t\t// Otherwise, schedule execution for when the delay period ends\n\t\t\t\tif (!timeoutId) {\n\t\t\t\t\tconst remainingTime = delay - (now - lastCallTime)\n\t\t\t\t\tconst scheduledArgs = [...args] // Capture args at scheduling time\n\t\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\t\tlastCallTime = Date.now()\n\t\t\t\t\t\toriginal.apply(this, scheduledArgs)\n\t\t\t\t\t\ttimeoutId = null\n\t\t\t\t\t}, remainingTime)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t})\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"std-decorators.esm.js","sources":["../src/std-decorators.ts"],"sourcesContent":["import { decorator, type GenericClassDecorator } from './decorator'\n\n// In order to avoid async re-entrance, we could use zone.js or something like that.\nconst syncCalculating: { object: object; prop: PropertyKey }[] = []\n/**\n * Decorator that caches the result of a getter method and only recomputes when dependencies change\n * Prevents circular dependencies and provides automatic cache invalidation\n */\nexport const cached = decorator({\n\tgetter(original, _target, propertyKey) {\n\t\treturn function (this: any) {\n\t\t\tconst alreadyCalculating = syncCalculating.findIndex(\n\t\t\t\t(c) => c.object === this && c.prop === propertyKey\n\t\t\t)\n\t\t\tif (alreadyCalculating > -1)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Circular dependency detected: ${syncCalculating\n\t\t\t\t\t\t.slice(alreadyCalculating)\n\t\t\t\t\t\t.map((c) => `${c.object.constructor.name}.${String(c.prop)}`)\n\t\t\t\t\t\t.join(' -> ')} -> again`\n\t\t\t\t)\n\t\t\tsyncCalculating.push({ object: this, prop: propertyKey })\n\t\t\ttry {\n\t\t\t\tconst rv = original.call(this)\n\t\t\t\tcache(this, propertyKey, rv)\n\t\t\t\treturn rv\n\t\t\t} finally {\n\t\t\t\tsyncCalculating.pop()\n\t\t\t}\n\t\t}\n\t},\n})\n\n/**\n * Checks if a property is cached (has a cached value)\n * @param object - The object to check\n * @param propertyKey - The property key to check\n * @returns True if the property has a cached value\n */\nexport function isCached(object: Object, propertyKey: PropertyKey) {\n\treturn !!Object.getOwnPropertyDescriptor(object, propertyKey)\n}\n\n/**\n * Caches a value for a property on an object\n * @param object - The object to cache the value on\n * @param propertyKey - The property key to cache\n * @param value - The value to cache\n */\nexport function cache(object: Object, propertyKey: PropertyKey, value: any) {\n\tObject.defineProperty(object, propertyKey, { value })\n}\n\n/**\n * Creates a decorator that modifies property descriptors for specified properties\n * @param descriptor - The descriptor properties to apply\n * @returns A class decorator that applies the descriptor to specified properties\n */\nexport function describe(descriptor: {\n\tenumerable?: boolean\n\tconfigurable?: boolean // Not modifiable once the property has been defined ?\n\twritable?: boolean\n}) {\n\treturn <T>(...properties: (keyof T)[]): GenericClassDecorator<T> =>\n\t\t(Base) => {\n\t\t\treturn class extends Base {\n\t\t\t\tconstructor(...args: any[]) {\n\t\t\t\t\tsuper(...args)\n\t\t\t\t\tfor (const key of properties) {\n\t\t\t\t\t\tObject.defineProperty(this, key, {\n\t\t\t\t\t\t\t...Object.getOwnPropertyDescriptor(this, key),\n\t\t\t\t\t\t\t...descriptor,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n}\n\n/**\n * Decorator that marks methods, properties, or classes as deprecated\n * Provides warning messages when deprecated items are used\n */\nexport const deprecated = Object.assign(\n\tdecorator({\n\t\tmethod(original, _target, propertyKey) {\n\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\tdeprecated.warn(this, propertyKey)\n\t\t\t\treturn original.apply(this, args)\n\t\t\t}\n\t\t},\n\t\tgetter(original, _target, propertyKey) {\n\t\t\treturn function (this: any) {\n\t\t\t\tdeprecated.warn(this, propertyKey)\n\t\t\t\treturn original.call(this)\n\t\t\t}\n\t\t},\n\t\tsetter(original, _target, propertyKey) {\n\t\t\treturn function (this: any, value: any) {\n\t\t\t\tdeprecated.warn(this, propertyKey)\n\t\t\t\treturn original.call(this, value)\n\t\t\t}\n\t\t},\n\t\tclass(original) {\n\t\t\treturn class extends original {\n\t\t\t\tconstructor(...args: any[]) {\n\t\t\t\t\tsuper(...args)\n\t\t\t\t\tdeprecated.warn(this, 'constructor')\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tdefault(message: string) {\n\t\t\treturn decorator({\n\t\t\t\tmethod(original, _target, propertyKey) {\n\t\t\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\t\t\tdeprecated.warn(this, propertyKey, message)\n\t\t\t\t\t\treturn original.apply(this, args)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tgetter(original, _target, propertyKey) {\n\t\t\t\t\treturn function (this: any) {\n\t\t\t\t\t\tdeprecated.warn(this, propertyKey, message)\n\t\t\t\t\t\treturn original.call(this)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsetter(original, _target, propertyKey) {\n\t\t\t\t\treturn function (this: any, value: any) {\n\t\t\t\t\t\tdeprecated.warn(this, propertyKey, message)\n\t\t\t\t\t\treturn original.call(this, value)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tclass(original) {\n\t\t\t\t\treturn class extends original {\n\t\t\t\t\t\tconstructor(...args: any[]) {\n\t\t\t\t\t\t\tsuper(...args)\n\t\t\t\t\t\t\tdeprecated.warn(this, 'constructor', message)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t})\n\t\t},\n\t}),\n\t{\n\t\twarn: (target: any, propertyKey: PropertyKey, message?: string) => {\n\t\t\t// biome-ignore lint/suspicious/noConsole: To be overridden\n\t\t\tconsole.warn(\n\t\t\t\t`${target.constructor.name}.${String(propertyKey)} is deprecated${message ? `: ${message}` : ''}`\n\t\t\t)\n\t\t},\n\t}\n)\n\n/**\n * Creates a debounced method decorator that delays execution until after the delay period has passed\n * @param delay - The delay in milliseconds\n * @returns A method decorator that debounces method calls\n */\nexport function debounce(delay: number) {\n\treturn decorator({\n\t\tmethod(original, _target, _propertyKey) {\n\t\t\tlet timeoutId: ReturnType<typeof setTimeout> | null = null\n\n\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\t// Clear existing timeout\n\t\t\t\tif (timeoutId) {\n\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t}\n\n\t\t\t\t// Set new timeout\n\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\toriginal.apply(this, args)\n\t\t\t\t\ttimeoutId = null\n\t\t\t\t}, delay)\n\t\t\t}\n\t\t},\n\t})\n}\n\n/**\n * Creates a throttled method decorator that limits execution to once per delay period\n * @param delay - The delay in milliseconds\n * @returns A method decorator that throttles method calls\n */\nexport function throttle(delay: number) {\n\treturn decorator({\n\t\tmethod(original, _target, _propertyKey) {\n\t\t\tlet lastCallTime = 0\n\t\t\tlet timeoutId: ReturnType<typeof setTimeout> | null = null\n\n\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\tconst now = Date.now()\n\n\t\t\t\t// If enough time has passed since last call, execute immediately\n\t\t\t\tif (now - lastCallTime >= delay) {\n\t\t\t\t\t// Clear any pending timeout since we're executing now\n\t\t\t\t\tif (timeoutId) {\n\t\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t\t\ttimeoutId = null\n\t\t\t\t\t}\n\t\t\t\t\tlastCallTime = now\n\t\t\t\t\treturn original.apply(this, args)\n\t\t\t\t}\n\n\t\t\t\t// Otherwise, schedule execution for when the delay period ends\n\t\t\t\tif (!timeoutId) {\n\t\t\t\t\tconst remainingTime = delay - (now - lastCallTime)\n\t\t\t\t\tconst scheduledArgs = [...args] // Capture args at scheduling time\n\t\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\t\tlastCallTime = Date.now()\n\t\t\t\t\t\toriginal.apply(this, scheduledArgs)\n\t\t\t\t\t\ttimeoutId = null\n\t\t\t\t\t}, remainingTime)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t})\n}\n"],"names":[],"mappings":";;AAEA;AACA,MAAM,eAAe,GAA4C,EAAE;AACnE;;;AAGG;AACI,MAAM,MAAM,GAAG,SAAS,CAAC;AAC/B,IAAA,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAA;QACpC,OAAO,YAAA;YACN,MAAM,kBAAkB,GAAG,eAAe,CAAC,SAAS,CACnD,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,CAClD;YACD,IAAI,kBAAkB,GAAG,EAAE;AAC1B,gBAAA,MAAM,IAAI,KAAK,CACd,CAAA,8BAAA,EAAiC;qBAC/B,KAAK,CAAC,kBAAkB;qBACxB,GAAG,CAAC,CAAC,CAAC,KAAK,CAAA,EAAG,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA,CAAE;AAC3D,qBAAA,IAAI,CAAC,MAAM,CAAC,CAAA,SAAA,CAAW,CACzB;AACF,YAAA,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AACzD,YAAA,IAAI;gBACH,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;AAC9B,gBAAA,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC;AAC5B,gBAAA,OAAO,EAAE;YACV;oBAAU;gBACT,eAAe,CAAC,GAAG,EAAE;YACtB;AACD,QAAA,CAAC;IACF,CAAC;AACD,CAAA;AAED;;;;;AAKG;AACG,SAAU,QAAQ,CAAC,MAAc,EAAE,WAAwB,EAAA;IAChE,OAAO,CAAC,CAAC,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAE,WAAW,CAAC;AAC9D;AAEA;;;;;AAKG;SACa,KAAK,CAAC,MAAc,EAAE,WAAwB,EAAE,KAAU,EAAA;IACzE,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,CAAC;AACtD;AAEA;;;;AAIG;AACG,SAAU,QAAQ,CAAC,UAIxB,EAAA;IACA,OAAO,CAAI,GAAG,UAAuB,KACpC,CAAC,IAAI,KAAI;QACR,OAAO,cAAc,IAAI,CAAA;AACxB,YAAA,WAAA,CAAY,GAAG,IAAW,EAAA;AACzB,gBAAA,KAAK,CAAC,GAAG,IAAI,CAAC;AACd,gBAAA,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;AAC7B,oBAAA,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE;AAChC,wBAAA,GAAG,MAAM,CAAC,wBAAwB,CAAC,IAAI,EAAE,GAAG,CAAC;AAC7C,wBAAA,GAAG,UAAU;AACb,qBAAA,CAAC;gBACH;YACD;SACA;AACF,IAAA,CAAC;AACH;AAEA;;;AAGG;MACU,UAAU,GAAG,MAAM,CAAC,MAAM,CACtC,SAAS,CAAC;AACT,IAAA,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAA;QACpC,OAAO,UAAqB,GAAG,IAAW,EAAA;AACzC,YAAA,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC;YAClC,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC;AAClC,QAAA,CAAC;IACF,CAAC;AACD,IAAA,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAA;QACpC,OAAO,YAAA;AACN,YAAA,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC;AAClC,YAAA,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;AAC3B,QAAA,CAAC;IACF,CAAC;AACD,IAAA,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAA;AACpC,QAAA,OAAO,UAAqB,KAAU,EAAA;AACrC,YAAA,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC;YAClC,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;AAClC,QAAA,CAAC;IACF,CAAC;AACD,IAAA,KAAK,CAAC,QAAQ,EAAA;QACb,OAAO,cAAc,QAAQ,CAAA;AAC5B,YAAA,WAAA,CAAY,GAAG,IAAW,EAAA;AACzB,gBAAA,KAAK,CAAC,GAAG,IAAI,CAAC;AACd,gBAAA,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC;YACrC;SACA;IACF,CAAC;AACD,IAAA,OAAO,CAAC,OAAe,EAAA;AACtB,QAAA,OAAO,SAAS,CAAC;AAChB,YAAA,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAA;gBACpC,OAAO,UAAqB,GAAG,IAAW,EAAA;oBACzC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC;oBAC3C,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC;AAClC,gBAAA,CAAC;YACF,CAAC;AACD,YAAA,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAA;gBACpC,OAAO,YAAA;oBACN,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC;AAC3C,oBAAA,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;AAC3B,gBAAA,CAAC;YACF,CAAC;AACD,YAAA,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAA;AACpC,gBAAA,OAAO,UAAqB,KAAU,EAAA;oBACrC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC;oBAC3C,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;AAClC,gBAAA,CAAC;YACF,CAAC;AACD,YAAA,KAAK,CAAC,QAAQ,EAAA;gBACb,OAAO,cAAc,QAAQ,CAAA;AAC5B,oBAAA,WAAA,CAAY,GAAG,IAAW,EAAA;AACzB,wBAAA,KAAK,CAAC,GAAG,IAAI,CAAC;wBACd,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC;oBAC9C;iBACA;YACF,CAAC;AACD,SAAA,CAAC;IACH,CAAC;AACD,CAAA,CAAC,EACF;IACC,IAAI,EAAE,CAAC,MAAW,EAAE,WAAwB,EAAE,OAAgB,KAAI;;AAEjE,QAAA,OAAO,CAAC,IAAI,CACX,CAAA,EAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAA,CAAA,EAAI,MAAM,CAAC,WAAW,CAAC,CAAA,cAAA,EAAiB,OAAO,GAAG,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,GAAG,EAAE,CAAA,CAAE,CACjG;IACF,CAAC;AACD,CAAA;AAGF;;;;AAIG;AACG,SAAU,QAAQ,CAAC,KAAa,EAAA;AACrC,IAAA,OAAO,SAAS,CAAC;AAChB,QAAA,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAA;YACrC,IAAI,SAAS,GAAyC,IAAI;YAE1D,OAAO,UAAqB,GAAG,IAAW,EAAA;;gBAEzC,IAAI,SAAS,EAAE;oBACd,YAAY,CAAC,SAAS,CAAC;gBACxB;;AAGA,gBAAA,SAAS,GAAG,UAAU,CAAC,MAAK;AAC3B,oBAAA,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC;oBAC1B,SAAS,GAAG,IAAI;gBACjB,CAAC,EAAE,KAAK,CAAC;AACV,YAAA,CAAC;QACF,CAAC;AACD,KAAA,CAAC;AACH;AAEA;;;;AAIG;AACG,SAAU,QAAQ,CAAC,KAAa,EAAA;AACrC,IAAA,OAAO,SAAS,CAAC;AAChB,QAAA,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAA;YACrC,IAAI,YAAY,GAAG,CAAC;YACpB,IAAI,SAAS,GAAyC,IAAI;YAE1D,OAAO,UAAqB,GAAG,IAAW,EAAA;AACzC,gBAAA,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;;AAGtB,gBAAA,IAAI,GAAG,GAAG,YAAY,IAAI,KAAK,EAAE;;oBAEhC,IAAI,SAAS,EAAE;wBACd,YAAY,CAAC,SAAS,CAAC;wBACvB,SAAS,GAAG,IAAI;oBACjB;oBACA,YAAY,GAAG,GAAG;oBAClB,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC;gBAClC;;gBAGA,IAAI,CAAC,SAAS,EAAE;oBACf,MAAM,aAAa,GAAG,KAAK,IAAI,GAAG,GAAG,YAAY,CAAC;oBAClD,MAAM,aAAa,GAAG,CAAC,GAAG,IAAI,CAAC,CAAA;AAC/B,oBAAA,SAAS,GAAG,UAAU,CAAC,MAAK;AAC3B,wBAAA,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE;AACzB,wBAAA,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,aAAa,CAAC;wBACnC,SAAS,GAAG,IAAI;oBACjB,CAAC,EAAE,aAAa,CAAC;gBAClB;AACD,YAAA,CAAC;QACF,CAAC;AACD,KAAA,CAAC;AACH;;;;"}
|
package/dist/std-decorators.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var decorator = require('./chunks/decorator-
|
|
3
|
+
var decorator = require('./chunks/decorator-BQ2eBTCj.js');
|
|
4
4
|
|
|
5
5
|
// In order to avoid async re-entrance, we could use zone.js or something like that.
|
|
6
6
|
const syncCalculating = [];
|
|
@@ -9,7 +9,7 @@ const syncCalculating = [];
|
|
|
9
9
|
* Prevents circular dependencies and provides automatic cache invalidation
|
|
10
10
|
*/
|
|
11
11
|
const cached = decorator.decorator({
|
|
12
|
-
getter(original, propertyKey) {
|
|
12
|
+
getter(original, _target, propertyKey) {
|
|
13
13
|
return function () {
|
|
14
14
|
const alreadyCalculating = syncCalculating.findIndex((c) => c.object === this && c.prop === propertyKey);
|
|
15
15
|
if (alreadyCalculating > -1)
|
|
@@ -72,19 +72,19 @@ function describe(descriptor) {
|
|
|
72
72
|
* Provides warning messages when deprecated items are used
|
|
73
73
|
*/
|
|
74
74
|
const deprecated = Object.assign(decorator.decorator({
|
|
75
|
-
method(original, propertyKey) {
|
|
75
|
+
method(original, _target, propertyKey) {
|
|
76
76
|
return function (...args) {
|
|
77
77
|
deprecated.warn(this, propertyKey);
|
|
78
78
|
return original.apply(this, args);
|
|
79
79
|
};
|
|
80
80
|
},
|
|
81
|
-
getter(original, propertyKey) {
|
|
81
|
+
getter(original, _target, propertyKey) {
|
|
82
82
|
return function () {
|
|
83
83
|
deprecated.warn(this, propertyKey);
|
|
84
84
|
return original.call(this);
|
|
85
85
|
};
|
|
86
86
|
},
|
|
87
|
-
setter(original, propertyKey) {
|
|
87
|
+
setter(original, _target, propertyKey) {
|
|
88
88
|
return function (value) {
|
|
89
89
|
deprecated.warn(this, propertyKey);
|
|
90
90
|
return original.call(this, value);
|
|
@@ -100,19 +100,19 @@ const deprecated = Object.assign(decorator.decorator({
|
|
|
100
100
|
},
|
|
101
101
|
default(message) {
|
|
102
102
|
return decorator.decorator({
|
|
103
|
-
method(original, propertyKey) {
|
|
103
|
+
method(original, _target, propertyKey) {
|
|
104
104
|
return function (...args) {
|
|
105
105
|
deprecated.warn(this, propertyKey, message);
|
|
106
106
|
return original.apply(this, args);
|
|
107
107
|
};
|
|
108
108
|
},
|
|
109
|
-
getter(original, propertyKey) {
|
|
109
|
+
getter(original, _target, propertyKey) {
|
|
110
110
|
return function () {
|
|
111
111
|
deprecated.warn(this, propertyKey, message);
|
|
112
112
|
return original.call(this);
|
|
113
113
|
};
|
|
114
114
|
},
|
|
115
|
-
setter(original, propertyKey) {
|
|
115
|
+
setter(original, _target, propertyKey) {
|
|
116
116
|
return function (value) {
|
|
117
117
|
deprecated.warn(this, propertyKey, message);
|
|
118
118
|
return original.call(this, value);
|
|
@@ -141,7 +141,7 @@ const deprecated = Object.assign(decorator.decorator({
|
|
|
141
141
|
*/
|
|
142
142
|
function debounce(delay) {
|
|
143
143
|
return decorator.decorator({
|
|
144
|
-
method(original, _propertyKey) {
|
|
144
|
+
method(original, _target, _propertyKey) {
|
|
145
145
|
let timeoutId = null;
|
|
146
146
|
return function (...args) {
|
|
147
147
|
// Clear existing timeout
|
|
@@ -164,7 +164,7 @@ function debounce(delay) {
|
|
|
164
164
|
*/
|
|
165
165
|
function throttle(delay) {
|
|
166
166
|
return decorator.decorator({
|
|
167
|
-
method(original, _propertyKey) {
|
|
167
|
+
method(original, _target, _propertyKey) {
|
|
168
168
|
let lastCallTime = 0;
|
|
169
169
|
let timeoutId = null;
|
|
170
170
|
return function (...args) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"std-decorators.js","sources":["../src/std-decorators.ts"],"sourcesContent":["import { decorator, type GenericClassDecorator } from './decorator'\n\n// In order to avoid async re-entrance, we could use zone.js or something like that.\nconst syncCalculating: { object: object; prop: PropertyKey }[] = []\n/**\n * Decorator that caches the result of a getter method and only recomputes when dependencies change\n * Prevents circular dependencies and provides automatic cache invalidation\n */\nexport const cached = decorator({\n\tgetter(original, propertyKey) {\n\t\treturn function (this: any) {\n\t\t\tconst alreadyCalculating = syncCalculating.findIndex(\n\t\t\t\t(c) => c.object === this && c.prop === propertyKey\n\t\t\t)\n\t\t\tif (alreadyCalculating > -1)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Circular dependency detected: ${syncCalculating\n\t\t\t\t\t\t.slice(alreadyCalculating)\n\t\t\t\t\t\t.map((c) => `${c.object.constructor.name}.${String(c.prop)}`)\n\t\t\t\t\t\t.join(' -> ')} -> again`\n\t\t\t\t)\n\t\t\tsyncCalculating.push({ object: this, prop: propertyKey })\n\t\t\ttry {\n\t\t\t\tconst rv = original.call(this)\n\t\t\t\tcache(this, propertyKey, rv)\n\t\t\t\treturn rv\n\t\t\t} finally {\n\t\t\t\tsyncCalculating.pop()\n\t\t\t}\n\t\t}\n\t},\n})\n\n/**\n * Checks if a property is cached (has a cached value)\n * @param object - The object to check\n * @param propertyKey - The property key to check\n * @returns True if the property has a cached value\n */\nexport function isCached(object: Object, propertyKey: PropertyKey) {\n\treturn !!Object.getOwnPropertyDescriptor(object, propertyKey)\n}\n\n/**\n * Caches a value for a property on an object\n * @param object - The object to cache the value on\n * @param propertyKey - The property key to cache\n * @param value - The value to cache\n */\nexport function cache(object: Object, propertyKey: PropertyKey, value: any) {\n\tObject.defineProperty(object, propertyKey, { value })\n}\n\n/**\n * Creates a decorator that modifies property descriptors for specified properties\n * @param descriptor - The descriptor properties to apply\n * @returns A class decorator that applies the descriptor to specified properties\n */\nexport function describe(descriptor: {\n\tenumerable?: boolean\n\tconfigurable?: boolean // Not modifiable once the property has been defined ?\n\twritable?: boolean\n}) {\n\treturn <T>(...properties: (keyof T)[]): GenericClassDecorator<T> =>\n\t\t(Base) => {\n\t\t\treturn class extends Base {\n\t\t\t\tconstructor(...args: any[]) {\n\t\t\t\t\tsuper(...args)\n\t\t\t\t\tfor (const key of properties) {\n\t\t\t\t\t\tObject.defineProperty(this, key, {\n\t\t\t\t\t\t\t...Object.getOwnPropertyDescriptor(this, key),\n\t\t\t\t\t\t\t...descriptor,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n}\n\n/**\n * Decorator that marks methods, properties, or classes as deprecated\n * Provides warning messages when deprecated items are used\n */\nexport const deprecated = Object.assign(\n\tdecorator({\n\t\tmethod(original, propertyKey) {\n\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\tdeprecated.warn(this, propertyKey)\n\t\t\t\treturn original.apply(this, args)\n\t\t\t}\n\t\t},\n\t\tgetter(original, propertyKey) {\n\t\t\treturn function (this: any) {\n\t\t\t\tdeprecated.warn(this, propertyKey)\n\t\t\t\treturn original.call(this)\n\t\t\t}\n\t\t},\n\t\tsetter(original, propertyKey) {\n\t\t\treturn function (this: any, value: any) {\n\t\t\t\tdeprecated.warn(this, propertyKey)\n\t\t\t\treturn original.call(this, value)\n\t\t\t}\n\t\t},\n\t\tclass(original) {\n\t\t\treturn class extends original {\n\t\t\t\tconstructor(...args: any[]) {\n\t\t\t\t\tsuper(...args)\n\t\t\t\t\tdeprecated.warn(this, 'constructor')\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tdefault(message: string) {\n\t\t\treturn decorator({\n\t\t\t\tmethod(original, propertyKey) {\n\t\t\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\t\t\tdeprecated.warn(this, propertyKey, message)\n\t\t\t\t\t\treturn original.apply(this, args)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tgetter(original, propertyKey) {\n\t\t\t\t\treturn function (this: any) {\n\t\t\t\t\t\tdeprecated.warn(this, propertyKey, message)\n\t\t\t\t\t\treturn original.call(this)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsetter(original, propertyKey) {\n\t\t\t\t\treturn function (this: any, value: any) {\n\t\t\t\t\t\tdeprecated.warn(this, propertyKey, message)\n\t\t\t\t\t\treturn original.call(this, value)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tclass(original) {\n\t\t\t\t\treturn class extends original {\n\t\t\t\t\t\tconstructor(...args: any[]) {\n\t\t\t\t\t\t\tsuper(...args)\n\t\t\t\t\t\t\tdeprecated.warn(this, 'constructor', message)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t})\n\t\t},\n\t}),\n\t{\n\t\twarn: (target: any, propertyKey: PropertyKey, message?: string) => {\n\t\t\t// biome-ignore lint/suspicious/noConsole: To be overridden\n\t\t\tconsole.warn(\n\t\t\t\t`${target.constructor.name}.${String(propertyKey)} is deprecated${message ? `: ${message}` : ''}`\n\t\t\t)\n\t\t},\n\t}\n)\n\n/**\n * Creates a debounced method decorator that delays execution until after the delay period has passed\n * @param delay - The delay in milliseconds\n * @returns A method decorator that debounces method calls\n */\nexport function debounce(delay: number) {\n\treturn decorator({\n\t\tmethod(original, _propertyKey) {\n\t\t\tlet timeoutId: ReturnType<typeof setTimeout> | null = null\n\n\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\t// Clear existing timeout\n\t\t\t\tif (timeoutId) {\n\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t}\n\n\t\t\t\t// Set new timeout\n\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\toriginal.apply(this, args)\n\t\t\t\t\ttimeoutId = null\n\t\t\t\t}, delay)\n\t\t\t}\n\t\t},\n\t})\n}\n\n/**\n * Creates a throttled method decorator that limits execution to once per delay period\n * @param delay - The delay in milliseconds\n * @returns A method decorator that throttles method calls\n */\nexport function throttle(delay: number) {\n\treturn decorator({\n\t\tmethod(original, _propertyKey) {\n\t\t\tlet lastCallTime = 0\n\t\t\tlet timeoutId: ReturnType<typeof setTimeout> | null = null\n\n\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\tconst now = Date.now()\n\n\t\t\t\t// If enough time has passed since last call, execute immediately\n\t\t\t\tif (now - lastCallTime >= delay) {\n\t\t\t\t\t// Clear any pending timeout since we're executing now\n\t\t\t\t\tif (timeoutId) {\n\t\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t\t\ttimeoutId = null\n\t\t\t\t\t}\n\t\t\t\t\tlastCallTime = now\n\t\t\t\t\treturn original.apply(this, args)\n\t\t\t\t}\n\n\t\t\t\t// Otherwise, schedule execution for when the delay period ends\n\t\t\t\tif (!timeoutId) {\n\t\t\t\t\tconst remainingTime = delay - (now - lastCallTime)\n\t\t\t\t\tconst scheduledArgs = [...args] // Capture args at scheduling time\n\t\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\t\tlastCallTime = Date.now()\n\t\t\t\t\t\toriginal.apply(this, scheduledArgs)\n\t\t\t\t\t\ttimeoutId = null\n\t\t\t\t\t}, remainingTime)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t})\n}\n"],"names":["decorator"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"std-decorators.js","sources":["../src/std-decorators.ts"],"sourcesContent":["import { decorator, type GenericClassDecorator } from './decorator'\n\n// In order to avoid async re-entrance, we could use zone.js or something like that.\nconst syncCalculating: { object: object; prop: PropertyKey }[] = []\n/**\n * Decorator that caches the result of a getter method and only recomputes when dependencies change\n * Prevents circular dependencies and provides automatic cache invalidation\n */\nexport const cached = decorator({\n\tgetter(original, _target, propertyKey) {\n\t\treturn function (this: any) {\n\t\t\tconst alreadyCalculating = syncCalculating.findIndex(\n\t\t\t\t(c) => c.object === this && c.prop === propertyKey\n\t\t\t)\n\t\t\tif (alreadyCalculating > -1)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Circular dependency detected: ${syncCalculating\n\t\t\t\t\t\t.slice(alreadyCalculating)\n\t\t\t\t\t\t.map((c) => `${c.object.constructor.name}.${String(c.prop)}`)\n\t\t\t\t\t\t.join(' -> ')} -> again`\n\t\t\t\t)\n\t\t\tsyncCalculating.push({ object: this, prop: propertyKey })\n\t\t\ttry {\n\t\t\t\tconst rv = original.call(this)\n\t\t\t\tcache(this, propertyKey, rv)\n\t\t\t\treturn rv\n\t\t\t} finally {\n\t\t\t\tsyncCalculating.pop()\n\t\t\t}\n\t\t}\n\t},\n})\n\n/**\n * Checks if a property is cached (has a cached value)\n * @param object - The object to check\n * @param propertyKey - The property key to check\n * @returns True if the property has a cached value\n */\nexport function isCached(object: Object, propertyKey: PropertyKey) {\n\treturn !!Object.getOwnPropertyDescriptor(object, propertyKey)\n}\n\n/**\n * Caches a value for a property on an object\n * @param object - The object to cache the value on\n * @param propertyKey - The property key to cache\n * @param value - The value to cache\n */\nexport function cache(object: Object, propertyKey: PropertyKey, value: any) {\n\tObject.defineProperty(object, propertyKey, { value })\n}\n\n/**\n * Creates a decorator that modifies property descriptors for specified properties\n * @param descriptor - The descriptor properties to apply\n * @returns A class decorator that applies the descriptor to specified properties\n */\nexport function describe(descriptor: {\n\tenumerable?: boolean\n\tconfigurable?: boolean // Not modifiable once the property has been defined ?\n\twritable?: boolean\n}) {\n\treturn <T>(...properties: (keyof T)[]): GenericClassDecorator<T> =>\n\t\t(Base) => {\n\t\t\treturn class extends Base {\n\t\t\t\tconstructor(...args: any[]) {\n\t\t\t\t\tsuper(...args)\n\t\t\t\t\tfor (const key of properties) {\n\t\t\t\t\t\tObject.defineProperty(this, key, {\n\t\t\t\t\t\t\t...Object.getOwnPropertyDescriptor(this, key),\n\t\t\t\t\t\t\t...descriptor,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n}\n\n/**\n * Decorator that marks methods, properties, or classes as deprecated\n * Provides warning messages when deprecated items are used\n */\nexport const deprecated = Object.assign(\n\tdecorator({\n\t\tmethod(original, _target, propertyKey) {\n\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\tdeprecated.warn(this, propertyKey)\n\t\t\t\treturn original.apply(this, args)\n\t\t\t}\n\t\t},\n\t\tgetter(original, _target, propertyKey) {\n\t\t\treturn function (this: any) {\n\t\t\t\tdeprecated.warn(this, propertyKey)\n\t\t\t\treturn original.call(this)\n\t\t\t}\n\t\t},\n\t\tsetter(original, _target, propertyKey) {\n\t\t\treturn function (this: any, value: any) {\n\t\t\t\tdeprecated.warn(this, propertyKey)\n\t\t\t\treturn original.call(this, value)\n\t\t\t}\n\t\t},\n\t\tclass(original) {\n\t\t\treturn class extends original {\n\t\t\t\tconstructor(...args: any[]) {\n\t\t\t\t\tsuper(...args)\n\t\t\t\t\tdeprecated.warn(this, 'constructor')\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tdefault(message: string) {\n\t\t\treturn decorator({\n\t\t\t\tmethod(original, _target, propertyKey) {\n\t\t\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\t\t\tdeprecated.warn(this, propertyKey, message)\n\t\t\t\t\t\treturn original.apply(this, args)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tgetter(original, _target, propertyKey) {\n\t\t\t\t\treturn function (this: any) {\n\t\t\t\t\t\tdeprecated.warn(this, propertyKey, message)\n\t\t\t\t\t\treturn original.call(this)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsetter(original, _target, propertyKey) {\n\t\t\t\t\treturn function (this: any, value: any) {\n\t\t\t\t\t\tdeprecated.warn(this, propertyKey, message)\n\t\t\t\t\t\treturn original.call(this, value)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tclass(original) {\n\t\t\t\t\treturn class extends original {\n\t\t\t\t\t\tconstructor(...args: any[]) {\n\t\t\t\t\t\t\tsuper(...args)\n\t\t\t\t\t\t\tdeprecated.warn(this, 'constructor', message)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t})\n\t\t},\n\t}),\n\t{\n\t\twarn: (target: any, propertyKey: PropertyKey, message?: string) => {\n\t\t\t// biome-ignore lint/suspicious/noConsole: To be overridden\n\t\t\tconsole.warn(\n\t\t\t\t`${target.constructor.name}.${String(propertyKey)} is deprecated${message ? `: ${message}` : ''}`\n\t\t\t)\n\t\t},\n\t}\n)\n\n/**\n * Creates a debounced method decorator that delays execution until after the delay period has passed\n * @param delay - The delay in milliseconds\n * @returns A method decorator that debounces method calls\n */\nexport function debounce(delay: number) {\n\treturn decorator({\n\t\tmethod(original, _target, _propertyKey) {\n\t\t\tlet timeoutId: ReturnType<typeof setTimeout> | null = null\n\n\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\t// Clear existing timeout\n\t\t\t\tif (timeoutId) {\n\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t}\n\n\t\t\t\t// Set new timeout\n\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\toriginal.apply(this, args)\n\t\t\t\t\ttimeoutId = null\n\t\t\t\t}, delay)\n\t\t\t}\n\t\t},\n\t})\n}\n\n/**\n * Creates a throttled method decorator that limits execution to once per delay period\n * @param delay - The delay in milliseconds\n * @returns A method decorator that throttles method calls\n */\nexport function throttle(delay: number) {\n\treturn decorator({\n\t\tmethod(original, _target, _propertyKey) {\n\t\t\tlet lastCallTime = 0\n\t\t\tlet timeoutId: ReturnType<typeof setTimeout> | null = null\n\n\t\t\treturn function (this: any, ...args: any[]) {\n\t\t\t\tconst now = Date.now()\n\n\t\t\t\t// If enough time has passed since last call, execute immediately\n\t\t\t\tif (now - lastCallTime >= delay) {\n\t\t\t\t\t// Clear any pending timeout since we're executing now\n\t\t\t\t\tif (timeoutId) {\n\t\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t\t\ttimeoutId = null\n\t\t\t\t\t}\n\t\t\t\t\tlastCallTime = now\n\t\t\t\t\treturn original.apply(this, args)\n\t\t\t\t}\n\n\t\t\t\t// Otherwise, schedule execution for when the delay period ends\n\t\t\t\tif (!timeoutId) {\n\t\t\t\t\tconst remainingTime = delay - (now - lastCallTime)\n\t\t\t\t\tconst scheduledArgs = [...args] // Capture args at scheduling time\n\t\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\t\tlastCallTime = Date.now()\n\t\t\t\t\t\toriginal.apply(this, scheduledArgs)\n\t\t\t\t\t\ttimeoutId = null\n\t\t\t\t\t}, remainingTime)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t})\n}\n"],"names":["decorator"],"mappings":"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"}
|
package/docs/ai/manual.md
CHANGED
|
@@ -2,104 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
> [!IMPORTANT]
|
|
4
4
|
> **Identity**: You are an AI Agent. This document is written for **YOU**.
|
|
5
|
-
> **Purpose**: This file defines the protocols
|
|
6
|
-
>
|
|
7
|
-
> For exact TypeScript signatures of the entire library, consult the **[API Reference for Agents](./api-reference.md)**.
|
|
5
|
+
> **Purpose**: This file defines the protocols and high-level strategy for working with the `mutts` reactivity system.
|
|
8
6
|
|
|
9
|
-
## 1.
|
|
10
|
-
|
|
7
|
+
## 1. Technical Documentation
|
|
8
|
+
Do not rely on outdated internal knowledge. Use the current documentation as your primary source of truth:
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
```typescript
|
|
15
|
-
import { enableIntrospection, options } from 'mutts/introspection'
|
|
10
|
+
- **[Debugging Tools](../reactive/debugging.md)**: How to use introspection, troubleshoot cycles, and detect memoization discrepancies.
|
|
11
|
+
- **[API Reference](./api-reference.md)**: Exact TypeScript signatures for library functions.
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
```
|
|
13
|
+
## 2. Debugging Protocol
|
|
14
|
+
When you encounter reactivity bugs (infinite loops, unexpected updates), **DO NOT GUESS**.
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
import { getDependencyGraph } from 'mutts/introspection'
|
|
16
|
+
1. **Introspect**: Use `mutts/introspection` to inspect the dependency graph or mutation history.
|
|
17
|
+
2. **Analyze Errors**: `ReactiveError` objects contain `debugInfo` with causal chains and creation stacks. Use them to trace the fault.
|
|
18
|
+
3. **Verify**: Use `reactiveOptions.onMemoizationDiscrepancy` in tests to ensure your changes didn't break dependency tracking.
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
**
|
|
20
|
+
## 3. Architecture Constraints
|
|
21
|
+
1. **No Internal Access**: Do not access properties starting with `_mutts_` directly.
|
|
22
|
+
2. **Explicit Naming**: Always name your effects (`effect(fn, { name: '...' })`) to make future debugging easier for yourself or other agents.
|
|
23
|
+
3. **Affirmative State**: Prefer derived state and effects over imperative event-driven updates.
|
|
30
24
|
|
|
31
|
-
### Mutation History
|
|
32
|
-
Understanding "What just happened".
|
|
33
|
-
```typescript
|
|
34
|
-
import { getMutationHistory } from 'mutts/introspection'
|
|
35
|
-
|
|
36
|
-
const history = getMutationHistory()
|
|
37
|
-
/*
|
|
38
|
-
Returns Array<{
|
|
39
|
-
id: number,
|
|
40
|
-
type: 'set' | 'add' | 'delete',
|
|
41
|
-
prop: string | symbol,
|
|
42
|
-
oldValue: any,
|
|
43
|
-
newValue: any,
|
|
44
|
-
objectName: string, // "Human readable name"
|
|
45
|
-
source: string, // "Effect X" or "External"
|
|
46
|
-
timestamp: number
|
|
47
|
-
}>
|
|
48
|
-
*/
|
|
49
|
-
```
|
|
50
|
-
**Agent Protocol**: When diagnosing "why is this value wrong?", check the *last mutation* of that property in history.
|
|
51
|
-
|
|
52
|
-
## 2. Structured Error Handling
|
|
53
|
-
`mutts` throws `ReactiveError` instances. These are designed to be machine-parseable.
|
|
54
|
-
|
|
55
|
-
### ReactiveErrorCode
|
|
56
|
-
Always check `error.debugInfo.code`.
|
|
57
|
-
```typescript
|
|
58
|
-
enum ReactiveErrorCode {
|
|
59
|
-
CycleDetected = 'CYCLE_DETECTED',
|
|
60
|
-
MaxDepthExceeded = 'MAX_DEPTH_EXCEEDED',
|
|
61
|
-
MaxReactionExceeded = 'MAX_REACTION_EXCEEDED',
|
|
62
|
-
WriteInComputed = 'WRITE_IN_COMPUTED',
|
|
63
|
-
TrackingError = 'TRACKING_ERROR'
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### Debugging Protocols
|
|
68
|
-
|
|
69
|
-
#### Protocol: Handling `CycleDetected` / `MaxDepthExceeded`
|
|
70
|
-
**Symptom**: `ReactiveError` with code `CycleDetected` or `MaxDepthExceeded`.
|
|
71
|
-
**Action**:
|
|
72
|
-
1. Read `error.debugInfo.cycle` (Array of effect names).
|
|
73
|
-
2. **CRITICAL**: Read `error.debugInfo.causalChain`.
|
|
74
|
-
* It tells you the *logical path*: `Effect A` -> (modifies `x`) -> `Effect B` -> (modifies `y`) -> `Effect A`.
|
|
75
|
-
3. **CRITICAL**: Read `error.debugInfo.creationStack`.
|
|
76
|
-
* This gives you the **File path and Line number** where the problematic effect was defined.
|
|
77
|
-
|
|
78
|
-
**Example Error Object**:
|
|
79
|
-
```json
|
|
80
|
-
{
|
|
81
|
-
"message": "[reactive] Max effect chain reached...",
|
|
82
|
-
"debugInfo": {
|
|
83
|
-
"code": "MAX_DEPTH_EXCEEDED",
|
|
84
|
-
"causalChain": [
|
|
85
|
-
"Effect(Anonymous) -> (set 'count') -> Effect(Display)",
|
|
86
|
-
"Effect(Display) -> (set 'dummy') -> Effect(Anonymous)"
|
|
87
|
-
],
|
|
88
|
-
"creationStack": " at tests/my-test.ts:45:10\n at ...",
|
|
89
|
-
"cycle": ["Effect(Anonymous)", "Effect(Display)"]
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## 3. Strict Mode
|
|
95
|
-
If you are writing new code that might be complex, verify it with "Strict Mode".
|
|
96
|
-
This forces a graph check *before* execution, preventing infinite loops from hanging the runtime.
|
|
97
|
-
```typescript
|
|
98
|
-
import { options } from 'mutts/introspection'
|
|
99
|
-
options.cycleHandling = 'strict'
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## 4. Architecture Constraints for Agents
|
|
103
|
-
1. **Do not** access properties starting with `_mutts_` directly unless instructed. These are internal implementation details.
|
|
104
|
-
2. **Do not** rely on `batchQueue` global state in your reasoning; it is ephemeral.
|
|
105
|
-
3. **Do** name your effects when possible (`effect(() => {}, { name: 'MyEffect' })`) to make your own future debugging easier.
|
|
@@ -1167,114 +1167,13 @@ Pair `memoize()` with [`mapped()`](#mapped) to keep derived array elements stabl
|
|
|
1167
1167
|
|
|
1168
1168
|
## Debugging and Development
|
|
1169
1169
|
|
|
1170
|
-
|
|
1170
|
+
The `mutts` reactive system includes built-in tools for troubleshooting complex dependency graphs and identifying performance bottlenecks.
|
|
1171
1171
|
|
|
1172
|
-
|
|
1172
|
+
For a full guide on debugging, including cycle detection and memoization discrepancy tools, see the dedicated **[Debugging Tools](./debugging.md)** documentation.
|
|
1173
1173
|
|
|
1174
|
-
|
|
1174
|
+
### Quick Summary
|
|
1175
1175
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
import { reactiveOptions } from 'mutts/reactive'
|
|
1180
|
-
|
|
1181
|
-
// Options: 'throw' (default), 'warn', or 'break'
|
|
1182
|
-
reactiveOptions.cycleHandling = 'warn' // Warn instead of throwing
|
|
1183
|
-
reactiveOptions.cycleHandling = 'break' // Silently break the cycle
|
|
1184
|
-
```
|
|
1185
|
-
|
|
1186
|
-
**Cycle handling modes:**
|
|
1187
|
-
|
|
1188
|
-
- **`'throw'`** (default): Throws a `ReactiveError` with a detailed cycle path when a cycle is detected
|
|
1189
|
-
- **`'warn'`**: Logs a warning message with the cycle path but continues execution (breaks the cycle)
|
|
1190
|
-
- **`'break'`**: Silently breaks the cycle without any message
|
|
1191
|
-
- **`'strict'`**: Checks the graph BEFORE execution. Prevents infinite loops at the source (higher overhead).
|
|
1192
|
-
|
|
1193
|
-
#### Cycle Error Messages
|
|
1194
|
-
|
|
1195
|
-
When a cycle is detected, the error message includes the full cycle path showing which effects form the cycle:
|
|
1196
|
-
|
|
1197
|
-
```typescript
|
|
1198
|
-
const state = reactive({ a: 0, b: 0, c: 0 })
|
|
1199
|
-
|
|
1200
|
-
effect(() => {
|
|
1201
|
-
state.b = state.a + 1 // Effect A
|
|
1202
|
-
})
|
|
1203
|
-
|
|
1204
|
-
effect(() => {
|
|
1205
|
-
state.c = state.b + 1 // Effect B
|
|
1206
|
-
})
|
|
1207
|
-
|
|
1208
|
-
// This will throw with a detailed cycle path
|
|
1209
|
-
try {
|
|
1210
|
-
effect(() => {
|
|
1211
|
-
state.a = state.c + 1 // Effect C - creates cycle: A → B → C → A
|
|
1212
|
-
})
|
|
1213
|
-
} catch (e) {
|
|
1214
|
-
console.error(e.message)
|
|
1215
|
-
// "[reactive] Cycle detected: effectA → effectB → effectC → effectA"
|
|
1216
|
-
}
|
|
1217
|
-
```
|
|
1218
|
-
|
|
1219
|
-
The cycle path shows the sequence of effects that form the circular dependency, making it easier to identify and fix the issue.
|
|
1220
|
-
|
|
1221
|
-
#### Common Cycle Patterns
|
|
1222
|
-
|
|
1223
|
-
**Direct cycle:**
|
|
1224
|
-
```typescript
|
|
1225
|
-
const state = reactive({ a: 0, b: 0 })
|
|
1226
|
-
|
|
1227
|
-
effect(() => {
|
|
1228
|
-
state.b = state.a + 1 // Effect A
|
|
1229
|
-
})
|
|
1230
|
-
|
|
1231
|
-
effect(() => {
|
|
1232
|
-
state.a = state.b + 1 // Effect B - creates cycle: A → B → A
|
|
1233
|
-
})
|
|
1234
|
-
```
|
|
1235
|
-
|
|
1236
|
-
**Indirect cycle:**
|
|
1237
|
-
```typescript
|
|
1238
|
-
const state = reactive({ a: 0, b: 0, c: 0 })
|
|
1239
|
-
|
|
1240
|
-
effect(() => {
|
|
1241
|
-
state.b = state.a + 1 // Effect A
|
|
1242
|
-
})
|
|
1243
|
-
|
|
1244
|
-
effect(() => {
|
|
1245
|
-
state.c = state.b + 1 // Effect B
|
|
1246
|
-
})
|
|
1247
|
-
|
|
1248
|
-
effect(() => {
|
|
1249
|
-
state.a = state.c + 1 // Effect C - creates cycle: A → B → C → A
|
|
1250
|
-
})
|
|
1251
|
-
```
|
|
1252
|
-
|
|
1253
|
-
#### Preventing Cycles
|
|
1254
|
-
|
|
1255
|
-
To avoid cycles, consider:
|
|
1256
|
-
|
|
1257
|
-
1. **Separate read and write effects**: Don't have an effect that both reads and writes the same reactive properties
|
|
1258
|
-
2. **Use `untracked()`**: For operations that shouldn't create dependencies
|
|
1259
|
-
3. **Use `atomic()`**: To batch operations and prevent intermediate triggers
|
|
1260
|
-
4. **Restructure logic**: Break circular dependencies by introducing intermediate state or computed values
|
|
1261
|
-
|
|
1262
|
-
**Example - Using `untracked()` to break cycles:**
|
|
1263
|
-
```typescript
|
|
1264
|
-
const state = reactive({ count: 0 })
|
|
1265
|
-
|
|
1266
|
-
effect(() => {
|
|
1267
|
-
// Read count
|
|
1268
|
-
const current = state.count
|
|
1269
|
-
|
|
1270
|
-
// Write to count without creating a dependency cycle
|
|
1271
|
-
untracked(() => {
|
|
1272
|
-
if (current < 10) {
|
|
1273
|
-
state.count = current + 1
|
|
1274
|
-
}
|
|
1275
|
-
})
|
|
1276
|
-
})
|
|
1277
|
-
```
|
|
1278
|
-
|
|
1279
|
-
**Note:** Self-loops (an effect reading and writing the same property, like `obj.prop++`) are automatically ignored and do not create dependency relationships or cycles.
|
|
1176
|
+
- **Cycle Detection**: Automatically catch circular dependencies via `reactiveOptions.cycleHandling`.
|
|
1177
|
+
- **Memoization Discrepancy**: Detect "missing dependencies" by running computations twice during development using `reactiveOptions.onMemoizationDiscrepancy`.
|
|
1178
|
+
- **Global Hooks**: Use `reactiveOptions.touched`, `enter`, and `leave` to observe system activity.
|
|
1280
1179
|
|