@but212/atom-effect 0.3.3 → 0.5.0
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 +13 -83
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +139 -25
- package/dist/index.mjs +442 -323
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
package/dist/index.d.ts
CHANGED
|
@@ -2,25 +2,35 @@
|
|
|
2
2
|
* Async computation states for computed atoms
|
|
3
3
|
*/
|
|
4
4
|
export declare const AsyncState: {
|
|
5
|
-
IDLE: "idle";
|
|
6
|
-
PENDING: "pending";
|
|
7
|
-
RESOLVED: "resolved";
|
|
8
|
-
REJECTED: "rejected";
|
|
5
|
+
readonly IDLE: "idle";
|
|
6
|
+
readonly PENDING: "pending";
|
|
7
|
+
readonly RESOLVED: "resolved";
|
|
8
|
+
readonly REJECTED: "rejected";
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
/** Type derived from AsyncState constant values */
|
|
12
|
+
export declare type AsyncStateType = (typeof AsyncState)[keyof typeof AsyncState];
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Creates a reactive atom holding mutable state.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
16
|
+
*
|
|
17
|
+
* Atoms are the building blocks of reactive state. When an atom's value changes,
|
|
18
|
+
* any effects or computed atoms that depend on it will be automatically re-executed.
|
|
19
|
+
*
|
|
20
|
+
* @param initialValue - The initial value of the atom.
|
|
21
|
+
* @param options - Configuration options.
|
|
22
|
+
* @param options.sync - If true, notifications are delivered synchronously when the value changes.
|
|
23
|
+
* @returns A writable atom object.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* const count = atom(0);
|
|
28
|
+
* count.value = 1; // Notifies subscribers
|
|
29
|
+
* console.log(count.value); // 1
|
|
30
|
+
* ```
|
|
17
31
|
*/
|
|
18
32
|
export declare function atom<T>(initialValue: T, options?: AtomOptions): WritableAtom<T>;
|
|
19
33
|
|
|
20
|
-
/**
|
|
21
|
-
* @fileoverview Error class hierarchy for atom-effect library
|
|
22
|
-
* @description Structured error classes with cause tracking and recoverability flags
|
|
23
|
-
*/
|
|
24
34
|
/**
|
|
25
35
|
* Base error class for all atom-effect errors
|
|
26
36
|
*
|
|
@@ -50,7 +60,9 @@ export declare class AtomError extends Error {
|
|
|
50
60
|
constructor(message: string, cause?: Error | null, recoverable?: boolean);
|
|
51
61
|
}
|
|
52
62
|
|
|
63
|
+
/** Configuration options for creating an atom. */
|
|
53
64
|
export declare interface AtomOptions {
|
|
65
|
+
/** If true, the atom will notify its subscribers synchronously when its value changes. */
|
|
54
66
|
sync?: boolean;
|
|
55
67
|
}
|
|
56
68
|
|
|
@@ -65,7 +77,7 @@ export declare interface AtomOptions {
|
|
|
65
77
|
* @param callback - The function containing batched updates
|
|
66
78
|
* @returns The result of the callback function
|
|
67
79
|
* @throws {AtomError} If the callback is not a function
|
|
68
|
-
* @throws
|
|
80
|
+
* @throws Propagates any error thrown by the callback function
|
|
69
81
|
*
|
|
70
82
|
* @example
|
|
71
83
|
* ```typescript
|
|
@@ -85,6 +97,15 @@ export declare interface AtomOptions {
|
|
|
85
97
|
*/
|
|
86
98
|
export declare function batch<T>(callback: () => T): T;
|
|
87
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Generic Branded Type helper.
|
|
102
|
+
* T: The base type (e.g., number, string)
|
|
103
|
+
* Brand: The unique brand tag
|
|
104
|
+
*/
|
|
105
|
+
export declare type Branded<T, Brand> = T & {
|
|
106
|
+
readonly __brand: Brand;
|
|
107
|
+
};
|
|
108
|
+
|
|
88
109
|
/**
|
|
89
110
|
* Creates a computed value with automatic dependency tracking.
|
|
90
111
|
* Supports sync/async computations with caching and lazy evaluation.
|
|
@@ -97,13 +118,21 @@ export declare function computed<T>(fn: () => Promise<T>, options: ComputedOptio
|
|
|
97
118
|
defaultValue: T;
|
|
98
119
|
}): ComputedAtom<T>;
|
|
99
120
|
|
|
121
|
+
/** Represents a reactive atom whose value is derived from other reactive state. */
|
|
100
122
|
export declare interface ComputedAtom<T = unknown> extends ReadonlyAtom<T> {
|
|
123
|
+
/** Current asynchronous state of the computation. */
|
|
101
124
|
readonly state: AsyncStateType;
|
|
125
|
+
/** true if the last computation attempt failed. */
|
|
102
126
|
readonly hasError: boolean;
|
|
127
|
+
/** The error object from the last failed computation, if any. */
|
|
103
128
|
readonly lastError: Error | null;
|
|
129
|
+
/** true if an asynchronous computation is currently in progress. */
|
|
104
130
|
readonly isPending: boolean;
|
|
131
|
+
/** true if the computation has successfully completed and has a value. */
|
|
105
132
|
readonly isResolved: boolean;
|
|
133
|
+
/** Manually invalidates the cached value, forcing recomputation on next access. */
|
|
106
134
|
invalidate(): void;
|
|
135
|
+
/** Disposed of the computed atom and its subscriptions. */
|
|
107
136
|
dispose(): void;
|
|
108
137
|
}
|
|
109
138
|
|
|
@@ -122,10 +151,15 @@ export declare class ComputedError extends AtomError {
|
|
|
122
151
|
constructor(message: string, cause?: Error | null);
|
|
123
152
|
}
|
|
124
153
|
|
|
154
|
+
/** Configuration options for creating a computed atom. */
|
|
125
155
|
export declare interface ComputedOptions<T = unknown> {
|
|
156
|
+
/** Optional custom equality check for values. Defaults to `Object.is`. */
|
|
126
157
|
equal?: (a: T, b: T) => boolean;
|
|
158
|
+
/** Initial value to return while an async computation is pending. */
|
|
127
159
|
defaultValue?: T;
|
|
160
|
+
/** If true, the computation is deferred until the value is first accessed. */
|
|
128
161
|
lazy?: boolean;
|
|
162
|
+
/** Optional error handler for computation failures. */
|
|
129
163
|
onError?: (error: Error) => void;
|
|
130
164
|
}
|
|
131
165
|
|
|
@@ -153,17 +187,20 @@ export declare interface DebugConfig {
|
|
|
153
187
|
maxDependencies: number;
|
|
154
188
|
warnInfiniteLoop: boolean;
|
|
155
189
|
warn(condition: boolean, message: string): void;
|
|
156
|
-
|
|
190
|
+
/** Checks for circular dependencies between reactive nodes */
|
|
191
|
+
checkCircular(dep: Dependency, current: object): void;
|
|
157
192
|
attachDebugInfo(obj: object, type: string, id: number): void;
|
|
158
|
-
|
|
159
|
-
|
|
193
|
+
/** Returns debug name if available (requires obj to have DEBUG_NAME symbol) */
|
|
194
|
+
getDebugName(obj: object | null | undefined): string | undefined;
|
|
195
|
+
/** Returns debug type if available (requires obj to have DEBUG_TYPE symbol) */
|
|
196
|
+
getDebugType(obj: object | null | undefined): string | undefined;
|
|
160
197
|
}
|
|
161
198
|
|
|
162
199
|
/**
|
|
163
200
|
* Interface for subscribable dependencies
|
|
164
201
|
*/
|
|
165
202
|
export declare interface Dependency {
|
|
166
|
-
readonly id:
|
|
203
|
+
readonly id: DependencyId;
|
|
167
204
|
version: number;
|
|
168
205
|
/**
|
|
169
206
|
* Last epoch seen by this dependency (used for invalidation)
|
|
@@ -195,10 +232,33 @@ export declare interface DependencyEntry<T extends object = Dependency> {
|
|
|
195
232
|
}
|
|
196
233
|
|
|
197
234
|
/**
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
|
|
201
|
-
|
|
235
|
+
* Unique identifier for reactive dependencies (Atoms, Computed, Effects).
|
|
236
|
+
* Base type is number.
|
|
237
|
+
*/
|
|
238
|
+
export declare type DependencyId = Branded<number, 'DependencyId'>;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Creates a reactive effect that re-executes when its dependencies change.
|
|
242
|
+
*
|
|
243
|
+
* An effect automatically tracks any reactive state (atoms, computed) accessed during its execution.
|
|
244
|
+
* When those dependencies change, the effect is scheduled for re-execution.
|
|
245
|
+
*
|
|
246
|
+
* @param fn - The effect function to execute. Can return a cleanup function or a Promise that resolves to one.
|
|
247
|
+
* @param options - Configuration options for the effect.
|
|
248
|
+
* @param options.sync - If true, the effect runs synchronously when dependencies change. Defaults to false (scheduled).
|
|
249
|
+
* @param options.maxExecutionsPerSecond - Rate limiting for the effect.
|
|
250
|
+
* @param options.trackModifications - If true, warns when an effect modifies its own dependencies.
|
|
251
|
+
* @returns An object representing the effect with `run()` and `dispose()` methods.
|
|
252
|
+
* @throws {EffectError} If `fn` is not a function.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```ts
|
|
256
|
+
* const count = atom(0);
|
|
257
|
+
* const stop = effect(() => {
|
|
258
|
+
* console.log('Count changed:', count.value);
|
|
259
|
+
* return () => console.log('Cleaning up...');
|
|
260
|
+
* });
|
|
261
|
+
* ```
|
|
202
262
|
*/
|
|
203
263
|
export declare function effect(fn: EffectFunction, options?: EffectOptions): EffectObject;
|
|
204
264
|
|
|
@@ -217,26 +277,43 @@ export declare class EffectError extends AtomError {
|
|
|
217
277
|
constructor(message: string, cause?: Error | null);
|
|
218
278
|
}
|
|
219
279
|
|
|
280
|
+
/**
|
|
281
|
+
* A function to be executed by an effect.
|
|
282
|
+
* Can optionally return a cleanup function or a Promise that resolves to one.
|
|
283
|
+
*/
|
|
220
284
|
export declare type EffectFunction = () => void | (() => void) | Promise<undefined | (() => void)>;
|
|
221
285
|
|
|
286
|
+
/** Represents a running effect instance. */
|
|
222
287
|
export declare interface EffectObject {
|
|
288
|
+
/** Stops the effect and unsubscribes from all dependencies. */
|
|
223
289
|
dispose(): void;
|
|
290
|
+
/** Manually triggers an execution of the effect. */
|
|
224
291
|
run(): void;
|
|
292
|
+
/** true if the effect has been disposed. */
|
|
225
293
|
readonly isDisposed: boolean;
|
|
294
|
+
/** Number of times the effect has executed. */
|
|
226
295
|
readonly executionCount: number;
|
|
227
296
|
}
|
|
228
297
|
|
|
298
|
+
/** Configuration options for creating an effect. */
|
|
229
299
|
export declare interface EffectOptions {
|
|
300
|
+
/** If true, the effect runs synchronously whenever its dependencies change. */
|
|
230
301
|
sync?: boolean;
|
|
302
|
+
/** Maximum number of executions allowed per second for rate limiting. */
|
|
231
303
|
maxExecutionsPerSecond?: number;
|
|
304
|
+
/** Maximum number of executions allowed per scheduler flush for loop detection. */
|
|
232
305
|
maxExecutionsPerFlush?: number;
|
|
306
|
+
/** If true, enables detection and warning for effects that modify their own dependencies. */
|
|
233
307
|
trackModifications?: boolean;
|
|
234
308
|
}
|
|
235
309
|
|
|
310
|
+
/** Checks if the given object is a ReadonlyAtom. */
|
|
236
311
|
export declare function isAtom(obj: unknown): obj is ReadonlyAtom;
|
|
237
312
|
|
|
313
|
+
/** Checks if the given object is a ComputedAtom. */
|
|
238
314
|
export declare function isComputed(obj: unknown): obj is ComputedAtom;
|
|
239
315
|
|
|
316
|
+
/** Checks if the given object is an EffectObject. */
|
|
240
317
|
export declare function isEffect(obj: unknown): obj is EffectObject;
|
|
241
318
|
|
|
242
319
|
/**
|
|
@@ -257,15 +334,24 @@ export declare interface Poolable {
|
|
|
257
334
|
reset(): void;
|
|
258
335
|
}
|
|
259
336
|
|
|
337
|
+
/** Represents a read-only reactive atom. */
|
|
260
338
|
export declare interface ReadonlyAtom<T = unknown> {
|
|
339
|
+
/** The current value of the atom. Accessing this tracks it as a dependency. */
|
|
261
340
|
readonly value: T;
|
|
341
|
+
/**
|
|
342
|
+
* Subscribes a listener function to changes in the atom's value.
|
|
343
|
+
* @param listener - Callback receiving both the new and old values.
|
|
344
|
+
* @returns An unsubscribe function.
|
|
345
|
+
*/
|
|
262
346
|
subscribe(listener: (newValue?: T, oldValue?: T) => void): () => void;
|
|
347
|
+
/** Returns the current value without registering it as a dependency. */
|
|
263
348
|
peek(): T;
|
|
264
349
|
}
|
|
265
350
|
|
|
266
351
|
/**
|
|
267
|
-
* Scheduler for reactive updates
|
|
268
|
-
*
|
|
352
|
+
* Scheduler for reactive updates.
|
|
353
|
+
* Manages the execution of effects and computed updates using batching and double-buffering.
|
|
354
|
+
* Supports both asynchronous (microtask-based) and synchronous (manual or batch-end) flushing.
|
|
269
355
|
*/
|
|
270
356
|
declare class Scheduler {
|
|
271
357
|
private queueA;
|
|
@@ -281,11 +367,31 @@ declare class Scheduler {
|
|
|
281
367
|
private isFlushingSync;
|
|
282
368
|
private maxFlushIterations;
|
|
283
369
|
get phase(): SchedulerPhase;
|
|
370
|
+
/**
|
|
371
|
+
* Schedules a task for execution.
|
|
372
|
+
* Tasks are deduplicated within the same flush cycle using epoch tracking.
|
|
373
|
+
* @param callback - The function to execute.
|
|
374
|
+
* @throws {SchedulerError} If the callback is not a function.
|
|
375
|
+
*/
|
|
284
376
|
schedule(callback: SchedulerJob): void;
|
|
285
377
|
private flush;
|
|
286
378
|
private flushSync;
|
|
379
|
+
private _mergeBatchQueue;
|
|
380
|
+
private _drainQueue;
|
|
381
|
+
private _processCurrentQueue;
|
|
382
|
+
private _handleFlushOverflow;
|
|
383
|
+
private _processJobs;
|
|
384
|
+
/** Starts a new batch of updates. Updates will be deferred until endBatch is called. */
|
|
287
385
|
startBatch(): void;
|
|
386
|
+
/**
|
|
387
|
+
* Ends the current batch. If the batch depth reaches zero, all pending updates are flushed synchronously.
|
|
388
|
+
*/
|
|
288
389
|
endBatch(): void;
|
|
390
|
+
/**
|
|
391
|
+
* Configures the maximum number of iterations allowed during a synchronous flush.
|
|
392
|
+
* Used to prevent infinite loops.
|
|
393
|
+
* @param max - Maximum iterations count.
|
|
394
|
+
*/
|
|
289
395
|
setMaxFlushIterations(max: number): void;
|
|
290
396
|
}
|
|
291
397
|
|
|
@@ -310,6 +416,10 @@ export declare const SCHEDULER_CONFIG: {
|
|
|
310
416
|
* Increased from 1000 to 5000 based on evaluation report
|
|
311
417
|
*/
|
|
312
418
|
readonly MAX_EXECUTIONS_PER_FLUSH: 5000;
|
|
419
|
+
/** Maximum iterations for synchronous flush loop to prevent infinite loops */
|
|
420
|
+
readonly MAX_FLUSH_ITERATIONS: 1000;
|
|
421
|
+
/** Minimum allowed value for max flush iterations */
|
|
422
|
+
readonly MIN_FLUSH_ITERATIONS: 10;
|
|
313
423
|
};
|
|
314
424
|
|
|
315
425
|
/**
|
|
@@ -327,9 +437,10 @@ export declare class SchedulerError extends AtomError {
|
|
|
327
437
|
constructor(message: string, cause?: Error | null);
|
|
328
438
|
}
|
|
329
439
|
|
|
330
|
-
declare
|
|
440
|
+
declare interface SchedulerJob {
|
|
441
|
+
(): void;
|
|
331
442
|
_nextEpoch?: number;
|
|
332
|
-
}
|
|
443
|
+
}
|
|
333
444
|
|
|
334
445
|
declare enum SchedulerPhase {
|
|
335
446
|
IDLE = 0,
|
|
@@ -360,7 +471,7 @@ export declare type TransformFunction<T, U> = (value: T) => U;
|
|
|
360
471
|
* @param fn - The function to execute without tracking
|
|
361
472
|
* @returns The result of the executed function
|
|
362
473
|
* @throws {AtomError} If the callback is not a function
|
|
363
|
-
* @throws
|
|
474
|
+
* @throws Propagates any error thrown by the callback function
|
|
364
475
|
*
|
|
365
476
|
* @example
|
|
366
477
|
* ```typescript
|
|
@@ -374,8 +485,11 @@ export declare type TransformFunction<T, U> = (value: T) => U;
|
|
|
374
485
|
*/
|
|
375
486
|
export declare function untracked<T>(fn: () => T): T;
|
|
376
487
|
|
|
488
|
+
/** Represents a writable reactive atom. */
|
|
377
489
|
export declare interface WritableAtom<T = unknown> extends ReadonlyAtom<T> {
|
|
490
|
+
/** The current value of the atom. Setting this will trigger notifications if the value changes. */
|
|
378
491
|
value: T;
|
|
492
|
+
/** Disposes of the atom and releases associated resources. */
|
|
379
493
|
dispose(): void;
|
|
380
494
|
}
|
|
381
495
|
|