atomirx 0.0.1

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 (121) hide show
  1. package/README.md +1666 -0
  2. package/coverage/base.css +224 -0
  3. package/coverage/block-navigation.js +87 -0
  4. package/coverage/clover.xml +1440 -0
  5. package/coverage/coverage-final.json +14 -0
  6. package/coverage/favicon.png +0 -0
  7. package/coverage/index.html +131 -0
  8. package/coverage/prettify.css +1 -0
  9. package/coverage/prettify.js +2 -0
  10. package/coverage/sort-arrow-sprite.png +0 -0
  11. package/coverage/sorter.js +210 -0
  12. package/coverage/src/core/atom.ts.html +889 -0
  13. package/coverage/src/core/batch.ts.html +223 -0
  14. package/coverage/src/core/define.ts.html +805 -0
  15. package/coverage/src/core/emitter.ts.html +919 -0
  16. package/coverage/src/core/equality.ts.html +631 -0
  17. package/coverage/src/core/hook.ts.html +460 -0
  18. package/coverage/src/core/index.html +281 -0
  19. package/coverage/src/core/isAtom.ts.html +100 -0
  20. package/coverage/src/core/isPromiseLike.ts.html +133 -0
  21. package/coverage/src/core/onCreateHook.ts.html +136 -0
  22. package/coverage/src/core/scheduleNotifyHook.ts.html +94 -0
  23. package/coverage/src/core/types.ts.html +523 -0
  24. package/coverage/src/core/withUse.ts.html +253 -0
  25. package/coverage/src/index.html +116 -0
  26. package/coverage/src/index.ts.html +106 -0
  27. package/dist/core/atom.d.ts +63 -0
  28. package/dist/core/atom.test.d.ts +1 -0
  29. package/dist/core/atomState.d.ts +104 -0
  30. package/dist/core/atomState.test.d.ts +1 -0
  31. package/dist/core/batch.d.ts +126 -0
  32. package/dist/core/batch.test.d.ts +1 -0
  33. package/dist/core/define.d.ts +173 -0
  34. package/dist/core/define.test.d.ts +1 -0
  35. package/dist/core/derived.d.ts +102 -0
  36. package/dist/core/derived.test.d.ts +1 -0
  37. package/dist/core/effect.d.ts +120 -0
  38. package/dist/core/effect.test.d.ts +1 -0
  39. package/dist/core/emitter.d.ts +237 -0
  40. package/dist/core/emitter.test.d.ts +1 -0
  41. package/dist/core/equality.d.ts +62 -0
  42. package/dist/core/equality.test.d.ts +1 -0
  43. package/dist/core/hook.d.ts +134 -0
  44. package/dist/core/hook.test.d.ts +1 -0
  45. package/dist/core/isAtom.d.ts +9 -0
  46. package/dist/core/isPromiseLike.d.ts +9 -0
  47. package/dist/core/isPromiseLike.test.d.ts +1 -0
  48. package/dist/core/onCreateHook.d.ts +79 -0
  49. package/dist/core/promiseCache.d.ts +134 -0
  50. package/dist/core/promiseCache.test.d.ts +1 -0
  51. package/dist/core/scheduleNotifyHook.d.ts +51 -0
  52. package/dist/core/select.d.ts +151 -0
  53. package/dist/core/selector.test.d.ts +1 -0
  54. package/dist/core/types.d.ts +279 -0
  55. package/dist/core/withUse.d.ts +38 -0
  56. package/dist/core/withUse.test.d.ts +1 -0
  57. package/dist/index-2ok7ilik.js +1217 -0
  58. package/dist/index-B_5SFzfl.cjs +1 -0
  59. package/dist/index.cjs +1 -0
  60. package/dist/index.d.ts +14 -0
  61. package/dist/index.js +20 -0
  62. package/dist/index.test.d.ts +1 -0
  63. package/dist/react/index.cjs +30 -0
  64. package/dist/react/index.d.ts +7 -0
  65. package/dist/react/index.js +823 -0
  66. package/dist/react/rx.d.ts +250 -0
  67. package/dist/react/rx.test.d.ts +1 -0
  68. package/dist/react/strictModeTest.d.ts +10 -0
  69. package/dist/react/useAction.d.ts +381 -0
  70. package/dist/react/useAction.test.d.ts +1 -0
  71. package/dist/react/useStable.d.ts +183 -0
  72. package/dist/react/useStable.test.d.ts +1 -0
  73. package/dist/react/useValue.d.ts +134 -0
  74. package/dist/react/useValue.test.d.ts +1 -0
  75. package/package.json +57 -0
  76. package/scripts/publish.js +198 -0
  77. package/src/core/atom.test.ts +369 -0
  78. package/src/core/atom.ts +189 -0
  79. package/src/core/atomState.test.ts +342 -0
  80. package/src/core/atomState.ts +256 -0
  81. package/src/core/batch.test.ts +257 -0
  82. package/src/core/batch.ts +172 -0
  83. package/src/core/define.test.ts +342 -0
  84. package/src/core/define.ts +243 -0
  85. package/src/core/derived.test.ts +381 -0
  86. package/src/core/derived.ts +339 -0
  87. package/src/core/effect.test.ts +196 -0
  88. package/src/core/effect.ts +184 -0
  89. package/src/core/emitter.test.ts +364 -0
  90. package/src/core/emitter.ts +392 -0
  91. package/src/core/equality.test.ts +392 -0
  92. package/src/core/equality.ts +182 -0
  93. package/src/core/hook.test.ts +227 -0
  94. package/src/core/hook.ts +177 -0
  95. package/src/core/isAtom.ts +27 -0
  96. package/src/core/isPromiseLike.test.ts +72 -0
  97. package/src/core/isPromiseLike.ts +16 -0
  98. package/src/core/onCreateHook.ts +92 -0
  99. package/src/core/promiseCache.test.ts +239 -0
  100. package/src/core/promiseCache.ts +279 -0
  101. package/src/core/scheduleNotifyHook.ts +53 -0
  102. package/src/core/select.ts +454 -0
  103. package/src/core/selector.test.ts +257 -0
  104. package/src/core/types.ts +311 -0
  105. package/src/core/withUse.test.ts +249 -0
  106. package/src/core/withUse.ts +56 -0
  107. package/src/index.test.ts +80 -0
  108. package/src/index.ts +51 -0
  109. package/src/react/index.ts +20 -0
  110. package/src/react/rx.test.tsx +416 -0
  111. package/src/react/rx.tsx +300 -0
  112. package/src/react/strictModeTest.tsx +71 -0
  113. package/src/react/useAction.test.ts +989 -0
  114. package/src/react/useAction.ts +605 -0
  115. package/src/react/useStable.test.ts +553 -0
  116. package/src/react/useStable.ts +288 -0
  117. package/src/react/useValue.test.ts +182 -0
  118. package/src/react/useValue.ts +261 -0
  119. package/tsconfig.json +9 -0
  120. package/v2.md +725 -0
  121. package/vite.config.ts +39 -0
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Hook that controls how atom change notifications are scheduled.
3
+ *
4
+ * ## Default Behavior
5
+ *
6
+ * By default, notifications are **synchronous** - listeners are called immediately
7
+ * when an atom's value changes:
8
+ *
9
+ * ```ts
10
+ * // Default: (fn) => fn() - immediate execution
11
+ * atom.set(newValue); // Listeners called immediately here
12
+ * ```
13
+ *
14
+ * ## Used by `batch()`
15
+ *
16
+ * The `batch()` function temporarily overrides this hook to defer notifications
17
+ * until all updates complete:
18
+ *
19
+ * ```ts
20
+ * batch(() => {
21
+ * a.set(1); // Notification deferred
22
+ * b.set(2); // Notification deferred
23
+ * });
24
+ * // All listeners called here (deduped)
25
+ * ```
26
+ *
27
+ * ## Custom Scheduling
28
+ *
29
+ * Can be overridden for custom scheduling strategies (e.g., microtask, RAF):
30
+ *
31
+ * ```ts
32
+ * // Schedule notifications as microtasks
33
+ * scheduleNotifyHook.override(() => (fn) => queueMicrotask(fn));
34
+ *
35
+ * // Schedule notifications on next animation frame
36
+ * scheduleNotifyHook.override(() => (fn) => requestAnimationFrame(fn));
37
+ *
38
+ * // Reset to default synchronous behavior
39
+ * scheduleNotifyHook.reset();
40
+ * ```
41
+ *
42
+ * ## API
43
+ *
44
+ * - `scheduleNotifyHook.current` - Get/set the current scheduler function
45
+ * - `scheduleNotifyHook.override(reducer)` - Override with custom scheduler (reducer receives previous)
46
+ * - `scheduleNotifyHook.reset()` - Reset to default synchronous behavior
47
+ * - `scheduleNotifyHook(reducer)` - Create a HookSetup for use with `hook.use()`
48
+ *
49
+ * @internal Used internally by atomState and batch. Not typically needed by users.
50
+ */
51
+ export declare const scheduleNotifyHook: import('./hook').Hook<(fn: VoidFunction) => void>;
@@ -0,0 +1,151 @@
1
+ import { Atom, AtomValue, SettledResult } from './types';
2
+ /**
3
+ * Result of a select computation.
4
+ *
5
+ * @template T - The type of the computed value
6
+ */
7
+ export interface SelectResult<T> {
8
+ /** The computed value (undefined if error or loading) */
9
+ value: T | undefined;
10
+ /** Error thrown during computation (undefined if success or loading) */
11
+ error: unknown;
12
+ /** Promise thrown during computation - indicates loading state */
13
+ promise: PromiseLike<unknown> | undefined;
14
+ /** Set of atoms that were accessed during computation */
15
+ dependencies: Set<Atom<unknown>>;
16
+ }
17
+ /**
18
+ * Context object passed to selector functions.
19
+ * Provides utilities for reading atoms and handling async operations.
20
+ */
21
+ export interface SelectContext {
22
+ /**
23
+ * Read the current value of an atom.
24
+ * Tracks the atom as a dependency.
25
+ *
26
+ * Suspense-like behavior using getAtomState():
27
+ * - If ready: returns value
28
+ * - If error: throws error
29
+ * - If loading: throws Promise (Suspense)
30
+ *
31
+ * @param atom - The atom to read
32
+ * @returns The atom's current value (Awaited<T>)
33
+ */
34
+ get<T>(atom: Atom<T>): Awaited<T>;
35
+ /**
36
+ * Wait for all atoms to resolve (like Promise.all).
37
+ * Variadic form - pass atoms as arguments.
38
+ *
39
+ * - If all atoms are ready → returns array of values
40
+ * - If any atom has error → throws that error
41
+ * - If any atom is loading (no fallback) → throws Promise
42
+ * - If loading with fallback → uses staleValue
43
+ *
44
+ * @param atoms - Atoms to wait for (variadic)
45
+ * @returns Array of resolved values (same order as input)
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * const [user, posts] = all(user$, posts$);
50
+ * ```
51
+ */
52
+ all<A extends Atom<unknown>[]>(...atoms: A): {
53
+ [K in keyof A]: AtomValue<A[K]>;
54
+ };
55
+ /**
56
+ * Return the first settled value (like Promise.race).
57
+ * Variadic form - pass atoms as arguments.
58
+ *
59
+ * - If any atom is ready → returns first ready value
60
+ * - If any atom has error → throws first error
61
+ * - If all atoms are loading → throws first Promise
62
+ *
63
+ * Note: race() does NOT use fallback - it's meant for first "real" settled value.
64
+ *
65
+ * @param atoms - Atoms to race (variadic)
66
+ * @returns First settled value
67
+ */
68
+ race<A extends Atom<unknown>[]>(...atoms: A): AtomValue<A[number]>;
69
+ /**
70
+ * Return the first ready value (like Promise.any).
71
+ * Variadic form - pass atoms as arguments.
72
+ *
73
+ * - If any atom is ready → returns first ready value
74
+ * - If all atoms have errors → throws AggregateError
75
+ * - If any loading (not all errored) → throws Promise
76
+ *
77
+ * Note: any() does NOT use fallback - it waits for a real ready value.
78
+ *
79
+ * @param atoms - Atoms to check (variadic)
80
+ * @returns First ready value
81
+ */
82
+ any<A extends Atom<unknown>[]>(...atoms: A): AtomValue<A[number]>;
83
+ /**
84
+ * Get all atom statuses when all are settled (like Promise.allSettled).
85
+ * Variadic form - pass atoms as arguments.
86
+ *
87
+ * - If all atoms are settled → returns array of statuses
88
+ * - If any atom is loading (no fallback) → throws Promise
89
+ * - If loading with fallback → { status: "ready", value: staleValue }
90
+ *
91
+ * @param atoms - Atoms to check (variadic)
92
+ * @returns Array of settled results
93
+ */
94
+ settled<A extends Atom<unknown>[]>(...atoms: A): {
95
+ [K in keyof A]: SettledResult<AtomValue<A[K]>>;
96
+ };
97
+ }
98
+ /**
99
+ * Selector function type for context-based API.
100
+ */
101
+ export type ContextSelectorFn<T> = (context: SelectContext) => T;
102
+ /**
103
+ * Custom error for when all atoms in `any()` are rejected.
104
+ */
105
+ export declare class AllAtomsRejectedError extends Error {
106
+ readonly errors: unknown[];
107
+ constructor(errors: unknown[], message?: string);
108
+ }
109
+ /**
110
+ * Selects/computes a value from atom(s) with dependency tracking.
111
+ *
112
+ * This is the core computation logic used by `derived()`. It:
113
+ * 1. Creates a context with `get`, `all`, `any`, `race`, `settled` utilities
114
+ * 2. Tracks which atoms are accessed during computation
115
+ * 3. Returns a result with value/error/promise and dependencies
116
+ *
117
+ * All context methods use `getAtomState()` internally.
118
+ *
119
+ * ## IMPORTANT: Selector Must Return Synchronous Value
120
+ *
121
+ * **The selector function MUST NOT return a Promise or PromiseLike value.**
122
+ *
123
+ * If your selector returns a Promise, it will throw an error. This is because:
124
+ * - `select()` is designed for synchronous derivation from atoms
125
+ * - Async atoms should be created using `atom(Promise)` directly
126
+ * - Use `get()` to read async atoms - it handles Suspense-style loading
127
+ *
128
+ * ```ts
129
+ * // ❌ WRONG - Don't return a Promise from selector
130
+ * select(({ get }) => fetch('/api/data'));
131
+ *
132
+ * // ✅ CORRECT - Create async atom and read with get()
133
+ * const data$ = atom(fetch('/api/data').then(r => r.json()));
134
+ * select(({ get }) => get(data$)); // Suspends until resolved
135
+ * ```
136
+ *
137
+ * @template T - The type of the computed value
138
+ * @param fn - Context-based selector function (must return sync value)
139
+ * @returns SelectResult with value, error, promise, and dependencies
140
+ * @throws Error if selector returns a Promise or PromiseLike
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * select(({ get, all }) => {
145
+ * const user = get(user$);
146
+ * const [posts, comments] = all(posts$, comments$);
147
+ * return { user, posts, comments };
148
+ * });
149
+ * ```
150
+ */
151
+ export declare function select<T>(fn: ContextSelectorFn<T>): SelectResult<T>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,279 @@
1
+ /**
2
+ * Generic function type that accepts any arguments and returns any value.
3
+ * Used internally for type-safe function handling.
4
+ */
5
+ export type AnyFunc = (...args: any[]) => any;
6
+ /**
7
+ * Unique symbol used to identify atom instances.
8
+ * Uses Symbol.for() to ensure the same symbol across different module instances.
9
+ */
10
+ export declare const SYMBOL_ATOM: unique symbol;
11
+ /**
12
+ * Symbol to identify derived atoms.
13
+ */
14
+ export declare const SYMBOL_DERIVED: unique symbol;
15
+ /**
16
+ * Interface for objects that support the `.use()` plugin pattern.
17
+ *
18
+ * The `.use()` method enables chainable transformations via plugins.
19
+ * Return type behavior:
20
+ * - `void` → returns original source (side-effect only)
21
+ * - Object with `.use` → returns as-is (already pipeable)
22
+ * - Object without `.use` → wraps with Pipeable
23
+ * - Primitive → returns directly (not chainable)
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const enhanced = atom(0)
28
+ * .use(source => ({ ...source, double: () => source.value * 2 }))
29
+ * .use(source => ({ ...source, triple: () => source.value * 3 }));
30
+ * ```
31
+ */
32
+ export interface Pipeable {
33
+ use<TNew = void>(plugin: (source: this) => TNew): void extends TNew ? this : TNew extends object ? TNew extends {
34
+ use: any;
35
+ } ? TNew : Pipeable & TNew : TNew;
36
+ }
37
+ /**
38
+ * Optional metadata for atoms.
39
+ */
40
+ export interface AtomMeta {
41
+ key?: string;
42
+ [key: string]: unknown;
43
+ }
44
+ /**
45
+ * Base interface for all atoms.
46
+ * Represents a reactive value container with subscription capability.
47
+ *
48
+ * @template T - The type of value stored in the atom
49
+ */
50
+ export interface Atom<T> {
51
+ /** Symbol marker to identify atom instances */
52
+ readonly [SYMBOL_ATOM]: true;
53
+ /** The current value */
54
+ readonly value: T;
55
+ /** Optional metadata for the atom */
56
+ readonly meta?: AtomMeta;
57
+ /**
58
+ * Subscribe to value changes.
59
+ * @param listener - Callback invoked when value changes
60
+ * @returns Unsubscribe function
61
+ */
62
+ on(listener: VoidFunction): VoidFunction;
63
+ }
64
+ /**
65
+ * A mutable atom that can be updated via `set()` and reset to initial state.
66
+ *
67
+ * MutableAtom is a raw storage container. It stores values as-is, including Promises.
68
+ * Unlike DerivedAtom, it does not automatically unwrap or track Promise states.
69
+ *
70
+ * @template T - The type of value stored in the atom
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * // Sync value
75
+ * const count = atom(0);
76
+ * count.set(5); // Direct value
77
+ * count.set(n => n + 1); // Reducer function
78
+ * count.reset(); // Back to 0
79
+ *
80
+ * // Async value (stores Promise as-is)
81
+ * const posts = atom(fetchPosts());
82
+ * posts.value; // Promise<Post[]>
83
+ * posts.set(fetchPosts()); // Store new Promise
84
+ * ```
85
+ */
86
+ export interface MutableAtom<T> extends Atom<T>, Pipeable {
87
+ /** Reset atom to its initial state (also clears dirty flag) */
88
+ reset(): void;
89
+ /**
90
+ * Update the atom's value.
91
+ *
92
+ * @param value - New value or reducer function (prev) => newValue
93
+ */
94
+ set(value: T | ((prev: T) => T)): void;
95
+ /**
96
+ * Returns `true` if the value has changed since initialization or last `reset()`.
97
+ *
98
+ * Useful for:
99
+ * - Tracking unsaved changes
100
+ * - Enabling/disabling save buttons
101
+ * - Detecting form modifications
102
+ *
103
+ * @example
104
+ * ```ts
105
+ * const form$ = atom({ name: "", email: "" });
106
+ *
107
+ * form$.dirty(); // false - just initialized
108
+ *
109
+ * form$.set({ name: "John", email: "" });
110
+ * form$.dirty(); // true - value changed
111
+ *
112
+ * form$.reset();
113
+ * form$.dirty(); // false - reset clears dirty flag
114
+ * ```
115
+ */
116
+ dirty(): boolean;
117
+ }
118
+ /**
119
+ * A derived (computed) atom that always returns Promise<T> for its value.
120
+ *
121
+ * DerivedAtom computes its value from other atoms. The computation is
122
+ * re-run whenever dependencies change. The `.value` always returns a Promise,
123
+ * even for synchronous computations.
124
+ *
125
+ * @template T - The resolved type of the computed value
126
+ * @template F - Whether fallback is provided (affects staleValue type)
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * // Without fallback
131
+ * const double$ = derived(({ get }) => get(count$) * 2);
132
+ * await double$.value; // number
133
+ * double$.staleValue; // number | undefined
134
+ * double$.state(); // { status: "ready", value: 10 }
135
+ *
136
+ * // With fallback - during loading
137
+ * const double$ = derived(({ get }) => get(count$) * 2, { fallback: 0 });
138
+ * double$.staleValue; // number (guaranteed)
139
+ * double$.state(); // { status: "loading", promise } during loading
140
+ * ```
141
+ */
142
+ export interface DerivedAtom<T, F extends boolean = false> extends Atom<Promise<T>> {
143
+ /** Symbol marker to identify derived atom instances */
144
+ readonly [SYMBOL_DERIVED]: true;
145
+ /** Re-run the computation */
146
+ refresh(): void;
147
+ /**
148
+ * Get the current state of the derived atom.
149
+ * Returns a discriminated union with status, value/error, and stale flag.
150
+ */
151
+ state(): AtomState<T>;
152
+ /**
153
+ * The stale value - fallback or last resolved value.
154
+ * - Without fallback: T | undefined
155
+ * - With fallback: T (guaranteed)
156
+ */
157
+ readonly staleValue: F extends true ? T : T | undefined;
158
+ }
159
+ /**
160
+ * Union type for any atom (mutable or derived).
161
+ */
162
+ export type AnyAtom<T> = MutableAtom<T> | DerivedAtom<T, boolean>;
163
+ /**
164
+ * Extract the value type from an atom.
165
+ * For DerivedAtom, returns the awaited type.
166
+ */
167
+ export type AtomValue<A> = A extends DerivedAtom<infer V, boolean> ? V : A extends Atom<infer V> ? Awaited<V> : never;
168
+ /**
169
+ * Represents the state of an atom as a discriminated union.
170
+ *
171
+ * Uses intuitive state terms:
172
+ * - `ready` - Value is available
173
+ * - `error` - Computation failed
174
+ * - `loading` - Waiting for async value
175
+ *
176
+ * @template T - The type of the atom's value
177
+ */
178
+ export type AtomState<T> = {
179
+ status: "ready";
180
+ value: T;
181
+ } | {
182
+ status: "error";
183
+ error: unknown;
184
+ } | {
185
+ status: "loading";
186
+ promise: Promise<T>;
187
+ };
188
+ /**
189
+ * Result type for settled operations.
190
+ */
191
+ export type SettledResult<T> = {
192
+ status: "ready";
193
+ value: T;
194
+ } | {
195
+ status: "error";
196
+ error: unknown;
197
+ };
198
+ /**
199
+ * Configuration options for creating a mutable atom.
200
+ *
201
+ * @template T - The type of value stored in the atom
202
+ */
203
+ export interface AtomOptions<T> {
204
+ /** Optional metadata for the atom */
205
+ meta?: MutableAtomMeta;
206
+ /** Equality strategy for change detection (default: "strict") */
207
+ equals?: Equality<T>;
208
+ }
209
+ export interface MutableAtomMeta extends AtomMeta {
210
+ }
211
+ export interface DerivedAtomMeta extends AtomMeta {
212
+ }
213
+ /**
214
+ * Configuration options for creating a derived atom.
215
+ *
216
+ * @template T - The type of the derived value
217
+ */
218
+ export interface DerivedOptions<T> {
219
+ /** Optional metadata for the atom */
220
+ meta?: DerivedAtomMeta;
221
+ /** Equality strategy for change detection (default: "strict") */
222
+ equals?: Equality<T>;
223
+ }
224
+ /**
225
+ * Configuration options for effects.
226
+ */
227
+ export interface EffectOptions {
228
+ /** Optional key for debugging */
229
+ key?: string;
230
+ /** Error handler for uncaught errors in the effect */
231
+ onError?: (error: Error) => void;
232
+ }
233
+ /**
234
+ * A function that returns a value when called.
235
+ * Used for lazy evaluation in derived atoms.
236
+ *
237
+ * @template T - The type of value returned
238
+ */
239
+ export type Getter<T> = () => T;
240
+ /**
241
+ * Built-in equality strategy names.
242
+ *
243
+ * Used with atoms to control when subscribers are notified:
244
+ * - `"strict"` - Object.is (default, fastest)
245
+ * - `"shallow"` - Compare object keys/array items with Object.is
246
+ * - `"shallow2"` - 2 levels deep
247
+ * - `"shallow3"` - 3 levels deep
248
+ * - `"deep"` - Full recursive comparison (slowest)
249
+ */
250
+ export type EqualityShorthand = "strict" | "shallow" | "shallow2" | "shallow3" | "deep";
251
+ /**
252
+ * Equality strategy for change detection.
253
+ *
254
+ * Can be a shorthand string or custom comparison function.
255
+ * Used by atoms to determine if value has "changed" -
256
+ * if equal, subscribers won't be notified.
257
+ *
258
+ * @template T - Type of values being compared
259
+ */
260
+ export type Equality<T = unknown> = EqualityShorthand | ((a: T, b: T) => boolean);
261
+ /**
262
+ * Prettify a type by adding all properties to the type.
263
+ * @template T - The type to prettify
264
+ */
265
+ export type Prettify<T> = {
266
+ [K in keyof T]: T[K];
267
+ } & {};
268
+ export interface ModuleMeta {
269
+ }
270
+ export type Listener<T> = (value: T) => void;
271
+ export type SingleOrMultipleListeners<T> = Listener<T> | Listener<T>[];
272
+ /**
273
+ * Type guard to check if a value is an Atom.
274
+ */
275
+ export declare function isAtom<T>(value: unknown): value is Atom<T>;
276
+ /**
277
+ * Type guard to check if a value is a DerivedAtom.
278
+ */
279
+ export declare function isDerived<T>(value: unknown): value is DerivedAtom<T, boolean>;
@@ -0,0 +1,38 @@
1
+ import { Pipeable } from './types';
2
+ /**
3
+ * Adds a chainable `.use()` method to any object, enabling plugin-based transformations.
4
+ *
5
+ * The `.use()` method accepts a plugin function that receives the source object
6
+ * and can return a transformed version. Supports several return patterns:
7
+ *
8
+ * - **Void/falsy**: Returns the original source unchanged (side-effect only plugins)
9
+ * - **Object/function with `.use`**: Returns as-is (already chainable)
10
+ * - **Object/function without `.use`**: Wraps with `withUse()` for continued chaining
11
+ * - **Primitive**: Returns the value directly
12
+ *
13
+ * @template TSource - The type of the source object being enhanced
14
+ * @param source - The object to add `.use()` method to
15
+ * @returns The source object with `.use()` method attached
16
+ *
17
+ * @example
18
+ * // Basic usage with atom tuple
19
+ * const mappable = withUse([signal, setter]);
20
+ * const transformed = mappable.use(([sig, set]) => ({
21
+ * sig,
22
+ * set: (v: string) => set(Number(v))
23
+ * }));
24
+ *
25
+ * @example
26
+ * // Chaining multiple transformations
27
+ * atom(0)
28
+ * .use(([sig, set]) => [sig, (v: number) => set(v * 2)])
29
+ * .use(([sig, set]) => [sig, (v: number) => set(v + 1)]);
30
+ *
31
+ * @example
32
+ * // Side-effect only plugin (returns void)
33
+ * mappable.use((source) => {
34
+ * console.log('Source:', source);
35
+ * // returns undefined - original source is returned
36
+ * });
37
+ */
38
+ export declare function withUse<TSource extends object>(source: TSource): TSource & Pipeable;
@@ -0,0 +1 @@
1
+ export {};