atomirx 0.0.4 → 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 +2 -2
- package/coverage/src/core/onCreateHook.ts.html +72 -70
- package/dist/core/derived.d.ts +15 -2
- package/dist/core/effect.d.ts +6 -2
- 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/onErrorHook.test.d.ts +1 -0
- package/dist/core/types.d.ts +52 -3
- package/dist/core/withReady.d.ts +46 -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 +3 -1
- package/dist/index.js +12 -11
- package/dist/react/index.cjs +9 -9
- package/dist/react/index.js +76 -75
- package/package.json +1 -1
- package/src/core/atom.ts +1 -1
- package/src/core/define.test.ts +12 -11
- package/src/core/define.ts +1 -1
- package/src/core/derived.test.ts +179 -0
- package/src/core/derived.ts +51 -8
- package/src/core/effect.test.ts +395 -9
- package/src/core/effect.ts +56 -29
- 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/types.ts +53 -3
- package/src/core/withReady.test.ts +174 -0
- package/src/core/withReady.ts +91 -27
- package/src/index.ts +10 -1
- package/dist/index-CqO6BDwj.cjs +0 -1
- package/dist/index-D8RDOTB_.js +0 -1319
package/README.md
CHANGED
|
@@ -1543,7 +1543,7 @@ The `onCreateHook` receives different info objects based on what's being created
|
|
|
1543
1543
|
|
|
1544
1544
|
```typescript
|
|
1545
1545
|
// Mutable atom
|
|
1546
|
-
interface
|
|
1546
|
+
interface MutableCreateInfo {
|
|
1547
1547
|
type: "mutable";
|
|
1548
1548
|
key: string | undefined;
|
|
1549
1549
|
meta: AtomMeta | undefined;
|
|
@@ -1551,7 +1551,7 @@ interface MutableAtomCreateInfo {
|
|
|
1551
1551
|
}
|
|
1552
1552
|
|
|
1553
1553
|
// Derived atom
|
|
1554
|
-
interface
|
|
1554
|
+
interface DerivedCreateInfo {
|
|
1555
1555
|
type: "derived";
|
|
1556
1556
|
key: string | undefined;
|
|
1557
1557
|
meta: AtomMeta | undefined;
|
|
@@ -1,68 +1,64 @@
|
|
|
1
|
-
|
|
2
1
|
<!doctype html>
|
|
3
2
|
<html lang="en">
|
|
4
|
-
|
|
5
|
-
<head>
|
|
3
|
+
<head>
|
|
6
4
|
<title>Code coverage report for src/core/onCreateHook.ts</title>
|
|
7
5
|
<meta charset="utf-8" />
|
|
8
6
|
<link rel="stylesheet" href="../../prettify.css" />
|
|
9
7
|
<link rel="stylesheet" href="../../base.css" />
|
|
10
8
|
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
|
|
11
9
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12
|
-
<style type=
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
<style type="text/css">
|
|
11
|
+
.coverage-summary .sorter {
|
|
12
|
+
background-image: url(../../sort-arrow-sprite.png);
|
|
13
|
+
}
|
|
16
14
|
</style>
|
|
17
|
-
</head>
|
|
18
|
-
|
|
19
|
-
<body>
|
|
20
|
-
<div class=
|
|
21
|
-
|
|
22
|
-
<h1
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
</
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
</
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
</div>
|
|
51
|
-
|
|
52
|
-
|
|
15
|
+
</head>
|
|
16
|
+
|
|
17
|
+
<body>
|
|
18
|
+
<div class="wrapper">
|
|
19
|
+
<div class="pad1">
|
|
20
|
+
<h1>
|
|
21
|
+
<a href="../../index.html">All files</a> /
|
|
22
|
+
<a href="index.html">src/core</a> onCreateHook.ts
|
|
23
|
+
</h1>
|
|
24
|
+
<div class="clearfix">
|
|
25
|
+
<div class="fl pad1y space-right2">
|
|
26
|
+
<span class="strong">100% </span>
|
|
27
|
+
<span class="quiet">Statements</span>
|
|
28
|
+
<span class="fraction">17/17</span>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div class="fl pad1y space-right2">
|
|
32
|
+
<span class="strong">100% </span>
|
|
33
|
+
<span class="quiet">Branches</span>
|
|
34
|
+
<span class="fraction">0/0</span>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div class="fl pad1y space-right2">
|
|
38
|
+
<span class="strong">100% </span>
|
|
39
|
+
<span class="quiet">Functions</span>
|
|
40
|
+
<span class="fraction">0/0</span>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<div class="fl pad1y space-right2">
|
|
44
|
+
<span class="strong">100% </span>
|
|
45
|
+
<span class="quiet">Lines</span>
|
|
46
|
+
<span class="fraction">17/17</span>
|
|
47
|
+
</div>
|
|
53
48
|
</div>
|
|
54
49
|
<p class="quiet">
|
|
55
|
-
|
|
50
|
+
Press <em>n</em> or <em>j</em> to go to the next uncovered block,
|
|
51
|
+
<em>b</em>, <em>p</em> or <em>k</em> for the previous block.
|
|
56
52
|
</p>
|
|
57
53
|
<template id="filterTemplate">
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
<div class="quiet">
|
|
55
|
+
Filter:
|
|
56
|
+
<input type="search" id="fileSearch" />
|
|
57
|
+
</div>
|
|
62
58
|
</template>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
</div>
|
|
60
|
+
<div class="status-line high"></div>
|
|
61
|
+
<pre><table class="coverage">
|
|
66
62
|
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
|
67
63
|
<a name='L2'></a><a href='#L2'>2</a>
|
|
68
64
|
<a name='L3'></a><a href='#L3'>3</a>
|
|
@@ -100,7 +96,7 @@
|
|
|
100
96
|
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { hook } from "./hook";
|
|
101
97
|
import { MutableAtom } from "./types";
|
|
102
98
|
|
|
103
|
-
export interface
|
|
99
|
+
export interface CreateInfo {
|
|
104
100
|
type: "atom";
|
|
105
101
|
key: string | undefined;
|
|
106
102
|
atom: MutableAtom<any>;
|
|
@@ -113,24 +109,30 @@ export interface ModuleCreateInfo {
|
|
|
113
109
|
}
|
|
114
110
|
|
|
115
111
|
export const onCreateHook =
|
|
116
|
-
hook<(info:
|
|
112
|
+
hook<(info: CreateInfo | ModuleCreateInfo) => void>();
|
|
117
113
|
</pre></td></tr></table></pre>
|
|
118
114
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
115
|
+
<div class="push"></div>
|
|
116
|
+
<!-- for sticky footer -->
|
|
117
|
+
</div>
|
|
118
|
+
<!-- /wrapper -->
|
|
119
|
+
<div class="footer quiet pad2 space-top1 center small">
|
|
120
|
+
Code coverage generated by
|
|
121
|
+
<a
|
|
122
|
+
href="https://istanbul.js.org/"
|
|
123
|
+
target="_blank"
|
|
124
|
+
rel="noopener noreferrer"
|
|
125
|
+
>istanbul</a
|
|
126
|
+
>
|
|
127
|
+
at 2026-01-16T14:35:38.788Z
|
|
128
|
+
</div>
|
|
129
|
+
<script src="../../prettify.js"></script>
|
|
130
|
+
<script>
|
|
131
|
+
window.onload = function () {
|
|
132
|
+
prettyPrint();
|
|
133
|
+
};
|
|
134
|
+
</script>
|
|
135
|
+
<script src="../../sorter.js"></script>
|
|
136
|
+
<script src="../../block-navigation.js"></script>
|
|
137
|
+
</body>
|
|
135
138
|
</html>
|
|
136
|
-
|
package/dist/core/derived.d.ts
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
|
+
import { CreateInfo } from './onCreateHook';
|
|
1
2
|
import { ReactiveSelector, SelectContext } from './select';
|
|
2
3
|
import { DerivedAtom, DerivedOptions } from './types';
|
|
3
4
|
import { WithReadySelectContext } from './withReady';
|
|
5
|
+
/**
|
|
6
|
+
* Internal options for derived atoms.
|
|
7
|
+
* These are not part of the public API.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export interface DerivedInternalOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Override the error source for onErrorHook.
|
|
13
|
+
* Used by effect() to attribute errors to the effect instead of the internal derived.
|
|
14
|
+
*/
|
|
15
|
+
_errorSource?: CreateInfo;
|
|
16
|
+
}
|
|
4
17
|
/**
|
|
5
18
|
* Context object passed to derived atom selector functions.
|
|
6
19
|
* Provides utilities for reading atoms: `{ read, all, any, race, settled }`.
|
|
@@ -130,7 +143,7 @@ export interface DerivedContext extends SelectContext, WithReadySelectContext {
|
|
|
130
143
|
* data$.refresh(); // Re-run computation
|
|
131
144
|
* ```
|
|
132
145
|
*/
|
|
133
|
-
export declare function derived<T>(fn: ReactiveSelector<T, DerivedContext>, options?: DerivedOptions<T>): DerivedAtom<T, false>;
|
|
146
|
+
export declare function derived<T>(fn: ReactiveSelector<T, DerivedContext>, options?: DerivedOptions<T> & DerivedInternalOptions): DerivedAtom<T, false>;
|
|
134
147
|
export declare function derived<T>(fn: ReactiveSelector<T, DerivedContext>, options: DerivedOptions<T> & {
|
|
135
148
|
fallback: T;
|
|
136
|
-
}): DerivedAtom<T, true>;
|
|
149
|
+
} & DerivedInternalOptions): DerivedAtom<T, true>;
|
package/dist/core/effect.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactiveSelector, SelectContext } from './select';
|
|
2
|
-
import { EffectOptions } from './types';
|
|
2
|
+
import { EffectMeta, EffectOptions } from './types';
|
|
3
3
|
import { WithReadySelectContext } from './withReady';
|
|
4
4
|
/**
|
|
5
5
|
* Context object passed to effect functions.
|
|
@@ -22,6 +22,10 @@ export interface EffectContext extends SelectContext, WithReadySelectContext {
|
|
|
22
22
|
*/
|
|
23
23
|
onCleanup: (cleanup: VoidFunction) => void;
|
|
24
24
|
}
|
|
25
|
+
export interface Effect {
|
|
26
|
+
dispose: VoidFunction;
|
|
27
|
+
meta?: EffectMeta;
|
|
28
|
+
}
|
|
25
29
|
/**
|
|
26
30
|
* Creates a side-effect that runs when accessed atom(s) change.
|
|
27
31
|
*
|
|
@@ -113,4 +117,4 @@ export interface EffectContext extends SelectContext, WithReadySelectContext {
|
|
|
113
117
|
* @returns Dispose function to stop the effect and run final cleanup
|
|
114
118
|
* @throws Error if effect function returns a Promise
|
|
115
119
|
*/
|
|
116
|
-
export declare function effect(fn: ReactiveSelector<void, EffectContext>,
|
|
120
|
+
export declare function effect(fn: ReactiveSelector<void, EffectContext>, options?: EffectOptions): Effect;
|
package/dist/core/hook.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ export interface Hook<T> {
|
|
|
54
54
|
/**
|
|
55
55
|
* Current value of the hook. Direct property access for fast reads.
|
|
56
56
|
*/
|
|
57
|
-
current: T;
|
|
57
|
+
readonly current: T;
|
|
58
58
|
/**
|
|
59
59
|
* Override the current value using a reducer.
|
|
60
60
|
* The reducer receives the previous value and returns the next value.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Effect } from './effect';
|
|
2
|
+
import { MutableAtomMeta, DerivedAtomMeta, MutableAtom, DerivedAtom, ModuleMeta, EffectMeta } from './types';
|
|
2
3
|
/**
|
|
3
4
|
* Information provided when a mutable atom is created.
|
|
4
5
|
*/
|
|
5
|
-
export interface
|
|
6
|
+
export interface MutableInfo {
|
|
6
7
|
/** Discriminator for mutable atoms */
|
|
7
8
|
type: "mutable";
|
|
8
9
|
/** Optional key from atom options (for debugging/devtools) */
|
|
@@ -10,12 +11,12 @@ export interface MutableAtomCreateInfo {
|
|
|
10
11
|
/** Optional metadata from atom options */
|
|
11
12
|
meta: MutableAtomMeta | undefined;
|
|
12
13
|
/** The created mutable atom instance */
|
|
13
|
-
|
|
14
|
+
instance: MutableAtom<unknown>;
|
|
14
15
|
}
|
|
15
16
|
/**
|
|
16
17
|
* Information provided when a derived atom is created.
|
|
17
18
|
*/
|
|
18
|
-
export interface
|
|
19
|
+
export interface DerivedInfo {
|
|
19
20
|
/** Discriminator for derived atoms */
|
|
20
21
|
type: "derived";
|
|
21
22
|
/** Optional key from derived options (for debugging/devtools) */
|
|
@@ -23,16 +24,29 @@ export interface DerivedAtomCreateInfo {
|
|
|
23
24
|
/** Optional metadata from derived options */
|
|
24
25
|
meta: DerivedAtomMeta | undefined;
|
|
25
26
|
/** The created derived atom instance */
|
|
26
|
-
|
|
27
|
+
instance: DerivedAtom<unknown, boolean>;
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
|
-
*
|
|
30
|
+
* Information provided when an effect is created.
|
|
30
31
|
*/
|
|
31
|
-
export
|
|
32
|
+
export interface EffectInfo {
|
|
33
|
+
/** Discriminator for effects */
|
|
34
|
+
type: "effect";
|
|
35
|
+
/** Optional key from effect options (for debugging/devtools) */
|
|
36
|
+
key: string | undefined;
|
|
37
|
+
/** Optional metadata from effect options */
|
|
38
|
+
meta: EffectMeta | undefined;
|
|
39
|
+
/** The created effect instance */
|
|
40
|
+
instance: Effect;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Union type for atom/derived/effect creation info.
|
|
44
|
+
*/
|
|
45
|
+
export type CreateInfo = MutableInfo | DerivedInfo | EffectInfo;
|
|
32
46
|
/**
|
|
33
47
|
* Information provided when a module (via define()) is created.
|
|
34
48
|
*/
|
|
35
|
-
export interface
|
|
49
|
+
export interface ModuleInfo {
|
|
36
50
|
/** Discriminator for modules */
|
|
37
51
|
type: "module";
|
|
38
52
|
/** Optional key from define options (for debugging/devtools) */
|
|
@@ -40,7 +54,7 @@ export interface ModuleCreateInfo {
|
|
|
40
54
|
/** Optional metadata from define options */
|
|
41
55
|
meta: ModuleMeta | undefined;
|
|
42
56
|
/** The created module instance */
|
|
43
|
-
|
|
57
|
+
instance: unknown;
|
|
44
58
|
}
|
|
45
59
|
/**
|
|
46
60
|
* Global hook that fires whenever an atom or module is created.
|
|
@@ -50,30 +64,30 @@ export interface ModuleCreateInfo {
|
|
|
50
64
|
* - **Debugging** - log atom creation for troubleshooting
|
|
51
65
|
* - **Testing** - verify expected atoms are created
|
|
52
66
|
*
|
|
67
|
+
* **IMPORTANT**: Always use `.override()` to preserve the hook chain.
|
|
68
|
+
* Direct assignment to `.current` will break existing handlers.
|
|
69
|
+
*
|
|
53
70
|
* @example Basic logging
|
|
54
71
|
* ```ts
|
|
55
|
-
* onCreateHook.
|
|
72
|
+
* onCreateHook.override((prev) => (info) => {
|
|
73
|
+
* prev?.(info); // call existing handlers first
|
|
56
74
|
* console.log(`Created ${info.type}: ${info.key ?? "anonymous"}`);
|
|
57
|
-
* };
|
|
75
|
+
* });
|
|
58
76
|
* ```
|
|
59
77
|
*
|
|
60
78
|
* @example DevTools integration
|
|
61
79
|
* ```ts
|
|
62
|
-
* const
|
|
63
|
-
* const modules = new Map();
|
|
80
|
+
* const registry = new Map();
|
|
64
81
|
*
|
|
65
|
-
* onCreateHook.
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* atoms.set(info.key, info.atom);
|
|
70
|
-
* }
|
|
71
|
-
* };
|
|
82
|
+
* onCreateHook.override((prev) => (info) => {
|
|
83
|
+
* prev?.(info); // preserve chain
|
|
84
|
+
* registry.set(info.key, info.instance);
|
|
85
|
+
* });
|
|
72
86
|
* ```
|
|
73
87
|
*
|
|
74
|
-
* @example
|
|
88
|
+
* @example Reset to default (disable all handlers)
|
|
75
89
|
* ```ts
|
|
76
|
-
* onCreateHook.
|
|
90
|
+
* onCreateHook.reset();
|
|
77
91
|
* ```
|
|
78
92
|
*/
|
|
79
|
-
export declare const onCreateHook: import('./hook').Hook<((info:
|
|
93
|
+
export declare const onCreateHook: import('./hook').Hook<((info: CreateInfo | ModuleInfo) => void) | undefined>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { CreateInfo } from './onCreateHook';
|
|
2
|
+
/**
|
|
3
|
+
* Information provided when an error occurs in an atom, derived, or effect.
|
|
4
|
+
*/
|
|
5
|
+
export interface ErrorInfo {
|
|
6
|
+
/** The source that produced the error (atom, derived, or effect) */
|
|
7
|
+
source: CreateInfo;
|
|
8
|
+
/** The error that was thrown */
|
|
9
|
+
error: unknown;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Global hook that fires whenever an error occurs in a derived atom or effect.
|
|
13
|
+
*
|
|
14
|
+
* This is useful for:
|
|
15
|
+
* - **Global error logging** - capture all errors in one place
|
|
16
|
+
* - **Error monitoring** - send errors to monitoring services (Sentry, etc.)
|
|
17
|
+
* - **DevTools integration** - show errors in developer tools
|
|
18
|
+
* - **Debugging** - track which atoms/effects are failing
|
|
19
|
+
*
|
|
20
|
+
* **IMPORTANT**: Always use `.override()` to preserve the hook chain.
|
|
21
|
+
* Direct assignment to `.current` will break existing handlers.
|
|
22
|
+
*
|
|
23
|
+
* @example Basic logging
|
|
24
|
+
* ```ts
|
|
25
|
+
* onErrorHook.override((prev) => (info) => {
|
|
26
|
+
* prev?.(info); // call existing handlers first
|
|
27
|
+
* console.error(`Error in ${info.source.type}: ${info.source.key ?? "anonymous"}`, info.error);
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example Send to monitoring service
|
|
32
|
+
* ```ts
|
|
33
|
+
* onErrorHook.override((prev) => (info) => {
|
|
34
|
+
* prev?.(info); // preserve chain
|
|
35
|
+
* Sentry.captureException(info.error, {
|
|
36
|
+
* tags: {
|
|
37
|
+
* source_type: info.source.type,
|
|
38
|
+
* source_key: info.source.key,
|
|
39
|
+
* },
|
|
40
|
+
* });
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @example Reset to default (disable all handlers)
|
|
45
|
+
* ```ts
|
|
46
|
+
* onErrorHook.reset();
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare const onErrorHook: import('./hook').Hook<((info: ErrorInfo) => void) | undefined>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/core/types.d.ts
CHANGED
|
@@ -37,9 +37,8 @@ export interface Pipeable {
|
|
|
37
37
|
/**
|
|
38
38
|
* Optional metadata for atoms.
|
|
39
39
|
*/
|
|
40
|
-
export interface AtomMeta {
|
|
40
|
+
export interface AtomMeta extends AtomirxMeta {
|
|
41
41
|
key?: string;
|
|
42
|
-
[key: string]: unknown;
|
|
43
42
|
}
|
|
44
43
|
/**
|
|
45
44
|
* Base interface for all atoms.
|
|
@@ -266,12 +265,62 @@ export interface DerivedOptions<T> {
|
|
|
266
265
|
meta?: DerivedAtomMeta;
|
|
267
266
|
/** Equality strategy for change detection (default: "strict") */
|
|
268
267
|
equals?: Equality<T>;
|
|
268
|
+
/**
|
|
269
|
+
* Callback invoked when the derived computation throws an error.
|
|
270
|
+
* This is called for actual errors, NOT for Promise throws (Suspense).
|
|
271
|
+
*
|
|
272
|
+
* @param error - The error thrown during computation
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```ts
|
|
276
|
+
* const data$ = derived(
|
|
277
|
+
* ({ read }) => {
|
|
278
|
+
* const raw = read(source$);
|
|
279
|
+
* return JSON.parse(raw); // May throw SyntaxError
|
|
280
|
+
* },
|
|
281
|
+
* {
|
|
282
|
+
* onError: (error) => {
|
|
283
|
+
* console.error('Derived computation failed:', error);
|
|
284
|
+
* reportToSentry(error);
|
|
285
|
+
* }
|
|
286
|
+
* }
|
|
287
|
+
* );
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
onError?: (error: unknown) => void;
|
|
269
291
|
}
|
|
270
292
|
/**
|
|
271
293
|
* Configuration options for effects.
|
|
272
294
|
*/
|
|
273
295
|
export interface EffectOptions {
|
|
274
|
-
|
|
296
|
+
meta?: EffectMeta;
|
|
297
|
+
/**
|
|
298
|
+
* Callback invoked when the effect computation throws an error.
|
|
299
|
+
* This is called for actual errors, NOT for Promise throws (Suspense).
|
|
300
|
+
*
|
|
301
|
+
* @param error - The error thrown during effect execution
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* ```ts
|
|
305
|
+
* effect(
|
|
306
|
+
* ({ read }) => {
|
|
307
|
+
* const data = read(source$);
|
|
308
|
+
* riskyOperation(data); // May throw
|
|
309
|
+
* },
|
|
310
|
+
* {
|
|
311
|
+
* onError: (error) => {
|
|
312
|
+
* console.error('Effect failed:', error);
|
|
313
|
+
* showErrorNotification(error);
|
|
314
|
+
* }
|
|
315
|
+
* }
|
|
316
|
+
* );
|
|
317
|
+
* ```
|
|
318
|
+
*/
|
|
319
|
+
onError?: (error: unknown) => void;
|
|
320
|
+
}
|
|
321
|
+
export interface AtomirxMeta {
|
|
322
|
+
}
|
|
323
|
+
export interface EffectMeta extends AtomirxMeta {
|
|
275
324
|
key?: string;
|
|
276
325
|
}
|
|
277
326
|
/**
|
package/dist/core/withReady.d.ts
CHANGED
|
@@ -49,6 +49,52 @@ export interface WithReadySelectContext {
|
|
|
49
49
|
* ```
|
|
50
50
|
*/
|
|
51
51
|
ready<T, R>(atom: Atom<T>, selector: (current: Awaited<T>) => R): R extends PromiseLike<any> ? never : Exclude<R, null | undefined>;
|
|
52
|
+
/**
|
|
53
|
+
* Execute a function and wait for its result to be non-null/non-undefined.
|
|
54
|
+
*
|
|
55
|
+
* If the function returns null/undefined, the computation suspends until
|
|
56
|
+
* re-executed with a non-null result.
|
|
57
|
+
*
|
|
58
|
+
* **IMPORTANT: Only use in `derived()` or `effect()` context**
|
|
59
|
+
*
|
|
60
|
+
* **NOTE:** This overload is designed for use with async combinators like
|
|
61
|
+
* `all()`, `race()`, `any()`, `settled()` where promises come from stable
|
|
62
|
+
* atom sources. It does NOT support dynamic promise creation (returning a
|
|
63
|
+
* new Promise from the callback). For async selectors that return promises,
|
|
64
|
+
* use `ready(atom$, selector?)` instead.
|
|
65
|
+
*
|
|
66
|
+
* @param fn - Synchronous function to execute and wait for
|
|
67
|
+
* @returns The non-null result (excludes null | undefined)
|
|
68
|
+
* @throws {Error} If the callback returns a Promise
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* // Wait for a computed value to be ready
|
|
73
|
+
* const result$ = derived(({ ready, read }) => {
|
|
74
|
+
* const value = ready(() => computeExpensiveValue(read(input$)));
|
|
75
|
+
* return `Result: ${value}`;
|
|
76
|
+
* });
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* // Use with async combinators (all, race, any, settled)
|
|
82
|
+
* const combined$ = derived(({ ready, all }) => {
|
|
83
|
+
* const [user, posts] = ready(() => all(user$, posts$));
|
|
84
|
+
* return { user, posts };
|
|
85
|
+
* });
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* // For async selectors, use ready(atom$, selector?) instead:
|
|
91
|
+
* const data$ = derived(({ ready }) => {
|
|
92
|
+
* const data = ready(source$, (val) => fetchData(val.id));
|
|
93
|
+
* return data;
|
|
94
|
+
* });
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
ready<T>(fn: () => T): T extends PromiseLike<any> ? never : Exclude<Awaited<T>, null | undefined>;
|
|
52
98
|
}
|
|
53
99
|
/**
|
|
54
100
|
* Plugin that adds `ready()` method to a SelectContext.
|