@but212/atom-effect 0.30.1 → 0.32.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.
Files changed (42) hide show
  1. package/README.md +21 -11
  2. package/dist/atom-effect.min.js +1 -1
  3. package/dist/atom-effect.min.js.map +1 -1
  4. package/dist/constants.d.ts +157 -0
  5. package/dist/constants.d.ts.map +1 -0
  6. package/dist/core/atom.d.ts +19 -0
  7. package/dist/core/atom.d.ts.map +1 -0
  8. package/dist/core/base.d.ts +136 -0
  9. package/dist/core/base.d.ts.map +1 -0
  10. package/dist/core/buffers.d.ts +113 -0
  11. package/dist/core/buffers.d.ts.map +1 -0
  12. package/dist/core/computed.d.ts +84 -0
  13. package/dist/core/computed.d.ts.map +1 -0
  14. package/dist/core/effect.d.ts +52 -0
  15. package/dist/core/effect.d.ts.map +1 -0
  16. package/dist/core/index.d.ts +8 -0
  17. package/dist/core/index.d.ts.map +1 -0
  18. package/dist/core/lens.d.ts +102 -0
  19. package/dist/core/lens.d.ts.map +1 -0
  20. package/dist/core/scheduler.d.ts +145 -0
  21. package/dist/core/scheduler.d.ts.map +1 -0
  22. package/dist/core/tracking.d.ts +123 -0
  23. package/dist/core/tracking.d.ts.map +1 -0
  24. package/dist/errors.d.ts +163 -0
  25. package/dist/errors.d.ts.map +1 -0
  26. package/dist/index.cjs +1 -1
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.ts +8 -510
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.mjs +1078 -913
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/symbols.d.ts +30 -0
  33. package/dist/symbols.d.ts.map +1 -0
  34. package/dist/types.d.ts +259 -0
  35. package/dist/types.d.ts.map +1 -0
  36. package/dist/utils/debug.d.ts +20 -0
  37. package/dist/utils/debug.d.ts.map +1 -0
  38. package/dist/utils/index.d.ts +13 -0
  39. package/dist/utils/index.d.ts.map +1 -0
  40. package/dist/utils/type-guards.d.ts +81 -0
  41. package/dist/utils/type-guards.d.ts.map +1 -0
  42. package/package.json +15 -14
package/dist/index.d.ts CHANGED
@@ -1,510 +1,8 @@
1
- /**
2
- * Async operation states for public API and high-level checks.
3
- */
4
- export declare const AsyncState: Readonly<{
5
- IDLE: "idle";
6
- PENDING: "pending";
7
- RESOLVED: "resolved";
8
- REJECTED: "rejected";
9
- }>;
10
-
11
- /**
12
- * Async state values.
13
- */
14
- export declare type AsyncStateType = (typeof AsyncState)[keyof typeof AsyncState];
15
-
16
- /**
17
- * Creates a reactive atom holding mutable state.
18
- *
19
- * @param initialValue - The initial value of the atom.
20
- * @param options - Configuration options (sync: boolean).
21
- */
22
- export declare function atom<T>(initialValue: T, options?: AtomOptions): WritableAtom<T>;
23
-
24
- /**
25
- * Base error class for the Atom system.
26
- * Designed for high performance, traceability, and cycle protection.
27
- */
28
- export declare class AtomError extends Error {
29
- readonly cause: unknown;
30
- readonly recoverable: boolean;
31
- readonly code?: string | undefined;
32
- readonly name: string;
33
- constructor(message: string, cause?: unknown, recoverable?: boolean, code?: string | undefined);
34
- /**
35
- * Returns the entire error chain as an array.
36
- * Includes the circular node if a cycle is detected.
37
- */
38
- getChain(): Array<AtomError | Error | unknown>;
39
- /**
40
- * Serializes the error to a structured object for logging.
41
- * Protected against circular references.
42
- */
43
- toJSON(seen?: Set<unknown>): AtomErrorJSON;
44
- /**
45
- * Internal helper to format wrapped messages consistently.
46
- */
47
- static format(source: string, context: string, message: string): string;
48
- }
49
-
50
- /**
51
- * Structured JSON representation of an AtomError.
52
- */
53
- declare interface AtomErrorJSON {
54
- name: string;
55
- message: string;
56
- code?: string | undefined;
57
- recoverable: boolean;
58
- stack?: string | undefined;
59
- cause?: unknown | undefined;
60
- }
61
-
62
- /**
63
- * Creates a two-way "lens" for a specific property path on an object-based atom.
64
- *
65
- * @example
66
- * const store = atom({ user: { name: 'Alice' } });
67
- * const nameLens = atomLens(store, 'user.name');
68
- * console.log(nameLens.value); // 'Alice'
69
- * nameLens.value = 'Bob'; // Updates store.user.name immutably
70
- */
71
- export declare function atomLens<T extends object, P extends Paths<T>>(atom: WritableAtom<T>, path: P): WritableAtom<PathValue<T, P>>;
72
-
73
- /**
74
- * Atom options.
75
- */
76
- export declare interface AtomOptions<T = unknown> {
77
- /** Optional name for debugging. */
78
- name?: string;
79
- /** If true, subscribers are notified synchronously. Default: false (microtask scheduled). */
80
- sync?: boolean;
81
- /** Equality check. */
82
- equal?: (a: T, b: T) => boolean;
83
- }
84
-
85
- /**
86
- * Groups multiple state updates into a single batch, delaying effects and computations
87
- * until the batch is closed.
88
- *
89
- * @param fn - The function containing state updates.
90
- * @returns The result of the function execution.
91
- * @throws {TypeError} If fn is not a function.
92
- */
93
- export declare function batch<T>(fn: () => T): T;
94
-
95
- /**
96
- * Global brand symbol for all reactive primitives.
97
- * Uses a bitwise mask for high-performance type identification.
98
- */
99
- declare const BRAND: unique symbol;
100
-
101
- /**
102
- * Composes an existing lens with a sub-path to create a deeper lens.
103
- */
104
- export declare const composeLens: <T extends object, P extends Paths<T>>(lens: WritableAtom<T>, path: P) => WritableAtom<PathValue<T, P>>;
105
-
106
- /**
107
- * Creates a computed value.
108
- * @param fn - Computation function
109
- * @param options - Options object
110
- */
111
- export declare function computed<T>(fn: () => T, options?: ComputedOptions<T>): ComputedAtom<T>;
112
-
113
- export declare function computed<T>(fn: () => Promise<T>, options: ComputedOptions<T> & {
114
- defaultValue: T;
115
- }): ComputedAtom<T>;
116
-
117
- /**
118
- * Computed atom interface.
119
- */
120
- export declare interface ComputedAtom<T = unknown> extends ReadonlyAtom<T>, Disposable_2 {
121
- /* Excluded from this release type: [BRAND] */
122
- readonly state: AsyncStateType;
123
- readonly hasError: boolean;
124
- readonly lastError: Error | null;
125
- readonly isPending: boolean;
126
- readonly isResolved: boolean;
127
- readonly isValid: boolean;
128
- /** List of errors encountered during computation. */
129
- readonly errors: readonly Error[];
130
- /** Invalidates atom. */
131
- invalidate(): void;
132
- dispose(): void;
133
- [Symbol.dispose](): void;
134
- }
135
-
136
- /** Thrown when a computation fails. */
137
- export declare class ComputedError extends AtomError {
138
- readonly name = "ComputedError";
139
- }
140
-
141
- /**
142
- * Computed options.
143
- */
144
- export declare interface ComputedOptions<T = unknown> {
145
- /** Optional name for debugging. */
146
- name?: string;
147
- /** Equality check. */
148
- equal?: (a: T, b: T) => boolean;
149
- /** Initial value. */
150
- defaultValue?: T;
151
- /** Lazy evaluation. */
152
- lazy?: boolean;
153
- /** Error handler. */
154
- onError?: (error: Error) => void;
155
- }
156
-
157
- /**
158
- * Debugging thresholds.
159
- */
160
- export declare const DEBUG_CONFIG: Readonly<{
161
- WARN_INFINITE_LOOP: true;
162
- EFFECT_FREQUENCY_WINDOW: 1000;
163
- LOOP_THRESHOLD: 100;
164
- }>;
165
-
166
- declare interface DebugConfig {
167
- enabled: boolean;
168
- warnInfiniteLoop: boolean;
169
- warn(condition: boolean, message: string): void;
170
- attachDebugInfo(obj: object, type: string, id: number, customName?: string): void;
171
- getDebugName(obj: object | null | undefined): string | undefined;
172
- getDebugType(obj: object | null | undefined): string | undefined;
173
- trackUpdate(id: DependencyId, name?: string): void;
174
- registerNode(node: object & {
175
- id: DependencyId;
176
- }): void;
177
- dumpGraph(): Record<string, unknown>[];
178
- }
179
-
180
- /**
181
- * Dependency interface.
182
- * Core contract for reactive nodes. All properties are required to ensure
183
- * high-performance access within the engine.
184
- *
185
- * @remarks
186
- * Internal fields (`version`, `flags`, `_lastSeenEpoch`) are part of the
187
- * engine contract between reactive nodes and must not be mutated externally.
188
- */
189
- export declare interface Dependency<T = unknown> {
190
- /* Excluded from this release type: [BRAND] */
191
- readonly id: DependencyId;
192
- /* Excluded from this release type: version */
193
- /* Excluded from this release type: flags */
194
- /* Excluded from this release type: _lastSeenEpoch */
195
- /* Excluded from this release type: isComputed */
196
- /* Excluded from this release type: hasError */
197
- /**
198
- * Adds a subscriber to this dependency.
199
- * The listener may optionally receive the new and previous values.
200
- * @param listener - A callback or Subscriber object.
201
- */
202
- subscribe(listener: ((newValue?: T, oldValue?: T) => void) | Subscriber): () => void;
203
- /**
204
- * Non-reactive read of the current value.
205
- */
206
- peek(): T;
207
- /**
208
- * Current value accessor.
209
- */
210
- readonly value: T;
211
- }
212
-
213
- /**
214
- * Dependency ID.
215
- */
216
- declare type DependencyId = number;
217
-
218
- /**
219
- * Custom Disposable interface for explicit resource management.
220
- */
221
- declare interface Disposable_2 {
222
- /**
223
- * Cleans up the object and releases resources.
224
- */
225
- dispose(): void;
226
- /**
227
- * Support for explicit resource management (TS 5.2+).
228
- */
229
- [Symbol.dispose](): void;
230
- }
231
- export { Disposable_2 as Disposable }
232
-
233
- /**
234
- * Creates and starts an effect.
235
- *
236
- * @param fn - Effect function.
237
- * @param options - Configuration options.
238
- * @returns Effect instance.
239
- */
240
- export declare function effect(fn: EffectFunction, options?: EffectOptions): EffectObject;
241
-
242
- /**
243
- * Effect cleanup function.
244
- */
245
- export declare type EffectCleanup = () => void;
246
-
247
- /** Thrown when an effect execution or cleanup fails. */
248
- export declare class EffectError extends AtomError {
249
- readonly name = "EffectError";
250
- constructor(message: string, cause?: unknown, recoverable?: boolean, code?: string);
251
- }
252
-
253
- /**
254
- * Effect function type.
255
- * Sync effects can return a cleanup function.
256
- * Async effects can return a promise that resolves to a cleanup function or void.
257
- */
258
- export declare type EffectFunction = () => (void | EffectCleanup) | Promise<void | EffectCleanup>;
259
-
260
- export declare interface EffectObject extends Disposable_2 {
261
- /* Excluded from this release type: [BRAND] */
262
- dispose(): void;
263
- [Symbol.dispose](): void;
264
- run(): void;
265
- readonly isDisposed: boolean;
266
- readonly executionCount: number;
267
- readonly isExecuting: boolean;
268
- }
269
-
270
- export declare interface EffectOptions {
271
- name?: string;
272
- sync?: boolean;
273
- maxExecutionsPerSecond?: number;
274
- maxExecutionsPerFlush?: number;
275
- onError?: (error: unknown) => void;
276
- }
277
-
278
- /**
279
- * Helper to retrieve a nested value from an object/array at a given path.
280
- */
281
- export declare function getPathValue(source: unknown, parts: string[]): unknown;
282
-
283
- /** Global scheduler instance. */
284
- export declare const globalScheduler: Scheduler_2;
285
-
286
- /**
287
- * Readonly atom check.
288
- */
289
- export declare function isAtom(obj: unknown): obj is ReadonlyAtom;
290
-
291
- /**
292
- * Computed atom check.
293
- */
294
- export declare function isComputed(obj: unknown): obj is ComputedAtom;
295
-
296
- /**
297
- * Effect object check.
298
- */
299
- export declare function isEffect(obj: unknown): obj is EffectObject;
300
-
301
- /**
302
- * Creates a lens factory bound to a specific atom.
303
- */
304
- export declare const lensFor: <T extends object>(atom: WritableAtom<T>) => <P extends Paths<T>>(path: P) => WritableAtom<PathValue<T, P>>;
305
-
306
- /** Max recursion depth for dot-paths. */
307
- declare type MaxDepth = 8;
308
-
309
- /**
310
- * Generates a union of all possible dot-separated paths for a given type T.
311
- * Excludes prototype methods and stops at TerminalTypes.
312
- *
313
- * Used for `atomLens` to provide IDE autocomplete and type safety when
314
- * zooming into deeply nested reactive objects.
315
- */
316
- export declare type Paths<T, D extends unknown[] = []> = D['length'] extends MaxDepth ? never : T extends TerminalTypes ? never : T extends object ? {
317
- [K in keyof T & (string | number)]: T[K] extends Function ? never : NonNullable<T[K]> extends object ? `${K}` | `${K}.${Paths<NonNullable<T[K]>, [...D, 1]>}` : `${K}`;
318
- }[keyof T & (string | number)] : never;
319
-
320
- /**
321
- * Resolves the type of a value at a specific dot-path P within type T.
322
- * Uses NonNullable to correctly handle optional (?) or nullable properties.
323
- *
324
- * Works in tandem with `Paths<T>` to ensure that lensed atoms have
325
- * the correct inferred type for the member they point to.
326
- */
327
- export declare type PathValue<T, P extends string> = P extends `${infer K}.${infer Rest}` ? StringKeyToNumber<K> extends keyof NonNullable<T> ? PathValue<NonNullable<NonNullable<T>[StringKeyToNumber<K> & keyof NonNullable<T>]>, Rest> : never : StringKeyToNumber<P> extends keyof NonNullable<T> ? NonNullable<T>[StringKeyToNumber<P> & keyof NonNullable<T>] : never;
328
-
329
- /**
330
- * Readonly atom interface.
331
- */
332
- export declare interface ReadonlyAtom<T = unknown> {
333
- /* Excluded from this release type: [BRAND] */
334
- /** The current value of the atom. */
335
- readonly value: T;
336
- /**
337
- * Subscribes to value changes.
338
- * @param listener - Function called when value changes.
339
- * @returns Unsubscribe function.
340
- */
341
- subscribe(listener: ((newValue?: T, oldValue?: T) => void) | Subscriber): () => void;
342
- /**
343
- * Non-reactive read.
344
- */
345
- peek(): T;
346
- /**
347
- * Returns the number of active subscribers.
348
- */
349
- subscriberCount(): number;
350
- }
351
-
352
- /**
353
- * The global debug singleton instance.
354
- * Automatically switches between development and production implementations
355
- * based on the environment configuration (IS_DEV).
356
- *
357
- * In production, this becomes a lightweight object with empty methods,
358
- * allowing engines to inline or ignore calls, effectively providing zero overhead.
359
- *
360
- * @public
361
- */
362
- export declare const runtimeDebug: DebugConfig;
363
-
364
- /**
365
- * Core Scheduler that manages asynchronous and synchronous task execution.
366
- *
367
- * Features:
368
- * - Double buffering for stable queue processing.
369
- * - Automatic job deduplication via Epoch tagging.
370
- * - Nested batching support with automatic coalescence.
371
- * - Microsecond-level scheduling via queueMicrotask.
372
- */
373
- declare class Scheduler_2 {
374
- /** Double buffer to allow scheduling new jobs while processing the current queue. */
375
- private _queueBuffer;
376
- /** Pointer to the currently active buffer for ingestion. */
377
- private _bufferIndex;
378
- /** Current size of the active ingestion buffer. */
379
- private _size;
380
- /** Current internal epoch for job tagging. */
381
- private _epoch;
382
- /** Flag indicating the scheduler is currently draining a microtask loop. */
383
- private _isProcessing;
384
- /** Flag indicating a synchronous flush (batch end) is currently active. */
385
- private _isFlushingSync;
386
- /** Number of active nested batch contexts. */
387
- private _batchDepth;
388
- /** Temporary holding area for jobs scheduled during an active batch or sync flush. */
389
- private _batchQueue;
390
- /** Current number of jobs in the batch holding area. */
391
- private _batchQueueSize;
392
- /** Maximum allowed internal loop iterations before assuming an infinite loop. */
393
- private _maxFlushIterations;
394
- /** Optional callback fired when the scheduler drops jobs due to overflow. */
395
- onOverflow: ((droppedCount: number) => void) | null;
396
- private readonly _boundRunLoop;
397
- /** Returns the total number of pending jobs (active + batched). */
398
- get queueSize(): number;
399
- /** Returns true if the scheduler is currently within a `batch()` scope. */
400
- get isBatching(): boolean;
401
- /**
402
- * Schedules a job for execution.
403
- * Jobs are deduplicated based on the current epoch; if the same job is scheduled twice
404
- * in the same epoch, the second call is ignored.
405
- *
406
- * @param callback - The task to be executed.
407
- */
408
- schedule(callback: SchedulerJob): void;
409
- /** Initiates an asynchronous flush via microtask. */
410
- private _flush;
411
- /** Internal microtask execution loop. */
412
- private _runLoop;
413
- /** Internal synchronous flush typically triggered at the end of a batch. */
414
- _flushSync(): void;
415
- /**
416
- * Merges the temporal batch queue into the main active buffer.
417
- * Increments the epoch to allow previously executed jobs to be re-scheduled if needed.
418
- */
419
- private _mergeBatchQueue;
420
- /**
421
- * Continuous loop that drains both main and batch queues.
422
- * Processes until all queues are empty or max iterations reached.
423
- */
424
- private _drainQueue;
425
- /** Executes all jobs currently in the primary buffer and swaps buffers. */
426
- private _processQueue;
427
- /** Resets the scheduler state on infinite loop detection and notifies via onOverflow. */
428
- private _handleFlushOverflow;
429
- /** Enters a new batching depth. */
430
- startBatch(): void;
431
- /**
432
- * Decrements batching depth. If depth reaches 0, triggers a synchronous flush
433
- * to apply all coherent updates collected during the batch.
434
- */
435
- endBatch(): void;
436
- /** Configures the maximum safety iterations for the flush loop. */
437
- setMaxFlushIterations(max: number): void;
438
- }
439
-
440
- /**
441
- * Scheduler configuration.
442
- */
443
- export declare const SCHEDULER_CONFIG: Readonly<{
444
- MAX_EXECUTIONS_PER_SECOND: 1000;
445
- MAX_EXECUTIONS_PER_EFFECT: 100;
446
- MAX_EXECUTIONS_PER_FLUSH: 10000;
447
- MAX_FLUSH_ITERATIONS: 1000;
448
- MIN_FLUSH_ITERATIONS: 10;
449
- BATCH_QUEUE_SHRINK_THRESHOLD: 1000;
450
- }>;
451
-
452
- /** Thrown by the execution engine or scheduler. */
453
- export declare class SchedulerError extends AtomError {
454
- readonly name = "SchedulerError";
455
- constructor(message: string, cause?: unknown, recoverable?: boolean, code?: string);
456
- }
457
-
458
- /** Union type representing any valid schedulable task. */
459
- declare type SchedulerJob = SchedulerJobFunction | SchedulerJobObject;
460
-
461
- /** Represents a job that can be executed by the scheduler via a function interface. */
462
- declare interface SchedulerJobFunction {
463
- (): void;
464
- /** Internal tracking for deduplication within the same epoch. */
465
- _nextEpoch?: number | undefined;
466
- }
467
-
468
- declare interface SchedulerJobObject {
469
- execute(): void;
470
- /** Internal tracking for deduplication within the same epoch. */
471
- _nextEpoch?: number | undefined;
472
- }
473
-
474
- /**
475
- * Internal recursive helper for creating deep immutable copies with structural sharing.
476
- * Only clones nodes along the path where changes occur.
477
- */
478
- export declare function setDeepValue(obj: unknown, keys: string[], index: number, value: unknown): unknown;
479
-
480
- /** Helper to convert numeric string to number for array indexing. */
481
- declare type StringKeyToNumber<S extends string> = S extends `${infer N extends number}` ? N : S;
482
-
483
- declare interface Subscriber {
484
- execute(): void;
485
- }
486
-
487
- /** Types that should be treated as terminals (no further path exploration). */
488
- declare type TerminalTypes = Date | RegExp | Map<unknown, unknown> | Set<unknown> | Promise<unknown> | Function;
489
-
490
- /**
491
- * Executes a function without dependency tracking.
492
- *
493
- * @param fn - Function to execute.
494
- * @returns Result of `fn`.
495
- */
496
- export declare function untracked<T>(fn: () => T): T;
497
-
498
- /**
499
- * Writable atom interface.
500
- */
501
- export declare interface WritableAtom<T = unknown> extends ReadonlyAtom<T>, Disposable_2 {
502
- value: T;
503
- /**
504
- * Cleans up the atom and releases resources.
505
- */
506
- dispose(): void;
507
- [Symbol.dispose](): void;
508
- }
509
-
510
- export { }
1
+ export { AsyncState, IS_DEV, SCHEDULER_CONFIG } from './constants';
2
+ export type { Paths, PathValue } from './core';
3
+ export { aeNextTick, atom, atomLens, batch, composeLens, computed, effect, getPathValue, lensFor, mergeAtoms, mergeLenses, scheduler as globalScheduler, setDeepValue, untracked, } from './core';
4
+ export { AtomError, ComputedError, EffectError, SchedulerError, } from './errors';
5
+ export { BRAND, BrandFlags } from './symbols';
6
+ export type { AsyncStateType, AtomOptions, ComputedAtom, ComputedOptions, Dependency, Disposable, EffectCleanup, EffectFunction, EffectObject, EffectOptions, MergedDependencyValue, ReadonlyAtom, WritableAtom, } from './types';
7
+ export { debug as runtimeDebug, isAtom, isComputed, isEffect, isPromise, isWritable, } from './utils';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,EACL,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,WAAW,EACX,QAAQ,EACR,MAAM,EACN,YAAY,EACZ,OAAO,EACP,UAAU,EACV,WAAW,EACX,SAAS,IAAI,eAAe,EAC5B,YAAY,EACZ,SAAS,GACV,MAAM,QAAQ,CAAC;AAChB,OAAO,EACL,SAAS,EACT,aAAa,EACb,WAAW,EACX,cAAc,GACf,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EACV,cAAc,EACd,WAAW,EACX,YAAY,EACZ,eAAe,EACf,UAAU,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,aAAa,EACb,qBAAqB,EACrB,YAAY,EACZ,YAAY,GACb,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,KAAK,IAAI,YAAY,EACrB,MAAM,EACN,UAAU,EACV,QAAQ,EACR,SAAS,EACT,UAAU,GACX,MAAM,SAAS,CAAC"}