atomirx 0.0.2 → 0.0.5
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 +868 -161
- package/coverage/src/core/onCreateHook.ts.html +72 -70
- package/dist/core/atom.d.ts +83 -6
- package/dist/core/batch.d.ts +3 -3
- package/dist/core/derived.d.ts +69 -22
- package/dist/core/effect.d.ts +52 -52
- package/dist/core/getAtomState.d.ts +29 -0
- package/dist/core/hook.d.ts +1 -1
- package/dist/core/onCreateHook.d.ts +37 -23
- package/dist/core/onErrorHook.d.ts +49 -0
- package/dist/core/promiseCache.d.ts +23 -32
- package/dist/core/select.d.ts +208 -29
- package/dist/core/types.d.ts +107 -22
- package/dist/core/withReady.d.ts +115 -0
- package/dist/core/withReady.test.d.ts +1 -0
- package/dist/index-CBVj1kSj.js +1350 -0
- package/dist/index-Cxk9v0um.cjs +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +12 -8
- package/dist/index.js +18 -15
- package/dist/react/index.cjs +10 -10
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +422 -377
- package/dist/react/rx.d.ts +114 -25
- package/dist/react/useAction.d.ts +5 -4
- package/dist/react/{useValue.d.ts → useSelector.d.ts} +56 -25
- package/dist/react/useSelector.test.d.ts +1 -0
- package/package.json +1 -1
- package/src/core/atom.test.ts +307 -43
- package/src/core/atom.ts +144 -22
- package/src/core/batch.test.ts +10 -10
- package/src/core/batch.ts +3 -3
- package/src/core/define.test.ts +12 -11
- package/src/core/define.ts +1 -1
- package/src/core/derived.test.ts +906 -72
- package/src/core/derived.ts +192 -81
- package/src/core/effect.test.ts +651 -45
- package/src/core/effect.ts +102 -98
- package/src/core/getAtomState.ts +69 -0
- package/src/core/hook.test.ts +5 -5
- package/src/core/hook.ts +1 -1
- package/src/core/onCreateHook.ts +38 -23
- package/src/core/onErrorHook.test.ts +350 -0
- package/src/core/onErrorHook.ts +52 -0
- package/src/core/promiseCache.test.ts +5 -3
- package/src/core/promiseCache.ts +76 -71
- package/src/core/select.ts +405 -130
- package/src/core/selector.test.ts +574 -32
- package/src/core/types.ts +107 -29
- package/src/core/withReady.test.ts +534 -0
- package/src/core/withReady.ts +191 -0
- package/src/core/withUse.ts +1 -1
- package/src/index.test.ts +4 -4
- package/src/index.ts +21 -7
- package/src/react/index.ts +2 -1
- package/src/react/rx.test.tsx +173 -18
- package/src/react/rx.tsx +274 -43
- package/src/react/useAction.test.ts +12 -14
- package/src/react/useAction.ts +11 -9
- package/src/react/{useValue.test.ts → useSelector.test.ts} +16 -16
- package/src/react/{useValue.ts → useSelector.ts} +64 -33
- package/v2.md +44 -44
- package/dist/index-2ok7ilik.js +0 -1217
- package/dist/index-B_5SFzfl.cjs +0 -1
- /package/dist/{react/useValue.test.d.ts → core/onErrorHook.test.d.ts} +0 -0
package/src/core/types.ts
CHANGED
|
@@ -28,8 +28,8 @@ export const SYMBOL_DERIVED = Symbol.for("atomirx.derived");
|
|
|
28
28
|
* @example
|
|
29
29
|
* ```ts
|
|
30
30
|
* const enhanced = atom(0)
|
|
31
|
-
* .use(source => ({ ...source, double: () => source.
|
|
32
|
-
* .use(source => ({ ...source, triple: () => source.
|
|
31
|
+
* .use(source => ({ ...source, double: () => source.get() * 2 }))
|
|
32
|
+
* .use(source => ({ ...source, triple: () => source.get() * 3 }));
|
|
33
33
|
* ```
|
|
34
34
|
*/
|
|
35
35
|
export interface Pipeable {
|
|
@@ -47,9 +47,8 @@ export interface Pipeable {
|
|
|
47
47
|
/**
|
|
48
48
|
* Optional metadata for atoms.
|
|
49
49
|
*/
|
|
50
|
-
export interface AtomMeta {
|
|
50
|
+
export interface AtomMeta extends AtomirxMeta {
|
|
51
51
|
key?: string;
|
|
52
|
-
[key: string]: unknown;
|
|
53
52
|
}
|
|
54
53
|
|
|
55
54
|
/**
|
|
@@ -61,10 +60,13 @@ export interface AtomMeta {
|
|
|
61
60
|
export interface Atom<T> {
|
|
62
61
|
/** Symbol marker to identify atom instances */
|
|
63
62
|
readonly [SYMBOL_ATOM]: true;
|
|
64
|
-
|
|
65
|
-
readonly value: T;
|
|
63
|
+
|
|
66
64
|
/** Optional metadata for the atom */
|
|
67
65
|
readonly meta?: AtomMeta;
|
|
66
|
+
|
|
67
|
+
/** Get the current value */
|
|
68
|
+
get(): T;
|
|
69
|
+
|
|
68
70
|
/**
|
|
69
71
|
* Subscribe to value changes.
|
|
70
72
|
* @param listener - Callback invoked when value changes
|
|
@@ -91,7 +93,7 @@ export interface Atom<T> {
|
|
|
91
93
|
*
|
|
92
94
|
* // Async value (stores Promise as-is)
|
|
93
95
|
* const posts = atom(fetchPosts());
|
|
94
|
-
* posts.
|
|
96
|
+
* posts.get(); // Promise<Post[]>
|
|
95
97
|
* posts.set(fetchPosts()); // Store new Promise
|
|
96
98
|
* ```
|
|
97
99
|
*/
|
|
@@ -132,7 +134,7 @@ export interface MutableAtom<T> extends Atom<T>, Pipeable {
|
|
|
132
134
|
* A derived (computed) atom that always returns Promise<T> for its value.
|
|
133
135
|
*
|
|
134
136
|
* DerivedAtom computes its value from other atoms. The computation is
|
|
135
|
-
* re-run whenever dependencies change. The `.
|
|
137
|
+
* re-run whenever dependencies change. The `.get()` always returns a Promise,
|
|
136
138
|
* even for synchronous computations.
|
|
137
139
|
*
|
|
138
140
|
* @template T - The resolved type of the computed value
|
|
@@ -141,13 +143,13 @@ export interface MutableAtom<T> extends Atom<T>, Pipeable {
|
|
|
141
143
|
* @example
|
|
142
144
|
* ```ts
|
|
143
145
|
* // Without fallback
|
|
144
|
-
* const double$ = derived(({
|
|
145
|
-
* await double$.
|
|
146
|
+
* const double$ = derived(({ read }) => read(count$) * 2);
|
|
147
|
+
* await double$.get(); // number
|
|
146
148
|
* double$.staleValue; // number | undefined
|
|
147
149
|
* double$.state(); // { status: "ready", value: 10 }
|
|
148
150
|
*
|
|
149
151
|
* // With fallback - during loading
|
|
150
|
-
* const double$ = derived(({
|
|
152
|
+
* const double$ = derived(({ read }) => read(count$) * 2, { fallback: 0 });
|
|
151
153
|
* double$.staleValue; // number (guaranteed)
|
|
152
154
|
* double$.state(); // { status: "loading", promise } during loading
|
|
153
155
|
* ```
|
|
@@ -199,9 +201,48 @@ export type AtomValue<A> =
|
|
|
199
201
|
* @template T - The type of the atom's value
|
|
200
202
|
*/
|
|
201
203
|
export type AtomState<T> =
|
|
202
|
-
| { status: "ready"; value: T }
|
|
203
|
-
| { status: "error"; error: unknown }
|
|
204
|
-
| {
|
|
204
|
+
| { status: "ready"; value: T; error?: undefined; promise?: undefined }
|
|
205
|
+
| { status: "error"; error: unknown; value?: undefined; promise?: undefined }
|
|
206
|
+
| {
|
|
207
|
+
status: "loading";
|
|
208
|
+
promise: Promise<T>;
|
|
209
|
+
value?: undefined;
|
|
210
|
+
error?: undefined;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Result type for SelectContext.state() - simplified AtomState without promise.
|
|
215
|
+
*
|
|
216
|
+
* All properties (`status`, `value`, `error`) are always present:
|
|
217
|
+
* - `value` is `T` when ready, `undefined` otherwise
|
|
218
|
+
* - `error` is the error when errored, `undefined` otherwise
|
|
219
|
+
*
|
|
220
|
+
* This enables easy destructuring without type narrowing:
|
|
221
|
+
* ```ts
|
|
222
|
+
* const { status, value, error } = state(atom$);
|
|
223
|
+
* ```
|
|
224
|
+
*
|
|
225
|
+
* Equality comparisons work correctly (no promise reference issues).
|
|
226
|
+
*/
|
|
227
|
+
export type SelectStateResult<T> =
|
|
228
|
+
| { status: "ready"; value: T; error: undefined }
|
|
229
|
+
| { status: "error"; value: undefined; error: unknown }
|
|
230
|
+
| { status: "loading"; value: undefined; error: undefined };
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Result type for race() and any() - includes winning key.
|
|
234
|
+
*
|
|
235
|
+
* @template K - The key type (string literal union)
|
|
236
|
+
* @template V - The value type
|
|
237
|
+
*/
|
|
238
|
+
export type KeyedResult<K extends string, V> = {
|
|
239
|
+
/** The key that won the race/any */
|
|
240
|
+
key: K;
|
|
241
|
+
/** The resolved value */
|
|
242
|
+
value: V;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
export type AtomPlugin = <T extends Atom<any>>(atom: T) => T | void;
|
|
205
246
|
|
|
206
247
|
/**
|
|
207
248
|
* Result type for settled operations.
|
|
@@ -236,16 +277,65 @@ export interface DerivedOptions<T> {
|
|
|
236
277
|
meta?: DerivedAtomMeta;
|
|
237
278
|
/** Equality strategy for change detection (default: "strict") */
|
|
238
279
|
equals?: Equality<T>;
|
|
280
|
+
/**
|
|
281
|
+
* Callback invoked when the derived computation throws an error.
|
|
282
|
+
* This is called for actual errors, NOT for Promise throws (Suspense).
|
|
283
|
+
*
|
|
284
|
+
* @param error - The error thrown during computation
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```ts
|
|
288
|
+
* const data$ = derived(
|
|
289
|
+
* ({ read }) => {
|
|
290
|
+
* const raw = read(source$);
|
|
291
|
+
* return JSON.parse(raw); // May throw SyntaxError
|
|
292
|
+
* },
|
|
293
|
+
* {
|
|
294
|
+
* onError: (error) => {
|
|
295
|
+
* console.error('Derived computation failed:', error);
|
|
296
|
+
* reportToSentry(error);
|
|
297
|
+
* }
|
|
298
|
+
* }
|
|
299
|
+
* );
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
onError?: (error: unknown) => void;
|
|
239
303
|
}
|
|
240
304
|
|
|
241
305
|
/**
|
|
242
306
|
* Configuration options for effects.
|
|
243
307
|
*/
|
|
244
308
|
export interface EffectOptions {
|
|
245
|
-
|
|
309
|
+
meta?: EffectMeta;
|
|
310
|
+
/**
|
|
311
|
+
* Callback invoked when the effect computation throws an error.
|
|
312
|
+
* This is called for actual errors, NOT for Promise throws (Suspense).
|
|
313
|
+
*
|
|
314
|
+
* @param error - The error thrown during effect execution
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```ts
|
|
318
|
+
* effect(
|
|
319
|
+
* ({ read }) => {
|
|
320
|
+
* const data = read(source$);
|
|
321
|
+
* riskyOperation(data); // May throw
|
|
322
|
+
* },
|
|
323
|
+
* {
|
|
324
|
+
* onError: (error) => {
|
|
325
|
+
* console.error('Effect failed:', error);
|
|
326
|
+
* showErrorNotification(error);
|
|
327
|
+
* }
|
|
328
|
+
* }
|
|
329
|
+
* );
|
|
330
|
+
* ```
|
|
331
|
+
*/
|
|
332
|
+
onError?: (error: unknown) => void;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export interface AtomirxMeta {}
|
|
336
|
+
|
|
337
|
+
export interface EffectMeta extends AtomirxMeta {
|
|
246
338
|
key?: string;
|
|
247
|
-
/** Error handler for uncaught errors in the effect */
|
|
248
|
-
onError?: (error: Error) => void;
|
|
249
339
|
}
|
|
250
340
|
|
|
251
341
|
/**
|
|
@@ -297,15 +387,3 @@ export interface ModuleMeta {}
|
|
|
297
387
|
export type Listener<T> = (value: T) => void;
|
|
298
388
|
|
|
299
389
|
export type SingleOrMultipleListeners<T> = Listener<T> | Listener<T>[];
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Type guard to check if a value is an Atom.
|
|
303
|
-
*/
|
|
304
|
-
export declare function isAtom<T>(value: unknown): value is Atom<T>;
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Type guard to check if a value is a DerivedAtom.
|
|
308
|
-
*/
|
|
309
|
-
export declare function isDerived<T>(
|
|
310
|
-
value: unknown
|
|
311
|
-
): value is DerivedAtom<T, boolean>;
|