raf-effect-atom 0.0.0 → 0.2.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/CHANGELOG.md +122 -0
- package/README.md +17 -11
- package/dist/Handle.d.mts +90 -0
- package/dist/Hooks.d.mts +37 -16
- package/dist/Hooks.mjs +38 -22
- package/dist/Loader.d.mts +64 -24
- package/dist/Loader.mjs +96 -32
- package/dist/Next.d.mts +76 -12
- package/dist/Next.mjs +60 -12
- package/dist/NextClient.d.mts +4 -5
- package/dist/NextClient.mjs +4 -5
- package/dist/ReactHydration.d.mts +1 -1
- package/dist/ReactHydration.mjs +1 -1
- package/dist/ReactRouter.d.mts +32 -1
- package/dist/ReactRouter.mjs +28 -6
- package/dist/RequestRegistry.d.mts +64 -8
- package/dist/RequestRegistry.mjs +43 -9
- package/dist/TanStackRouter.d.mts +13 -2
- package/dist/TanStackRouter.mjs +13 -3
- package/dist/Waterfalls.d.mts +10 -9
- package/dist/Waterfalls.mjs +13 -9
- package/dist/index.d.mts +3 -2
- package/dist/internal/handles.mjs +22 -0
- package/dist/internal/next.mjs +23 -14
- package/dist/internal/registry.mjs +1 -1
- package/dist/internal/seeds.d.mts +3 -0
- package/dist/internal/seeds.mjs +56 -0
- package/dist/internal/waterfalls.mjs +1 -1
- package/package.json +2 -2
package/dist/Loader.d.mts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ArgsOf, ErrorOf, Handle, LoadedHandle, Source, SuccessOf } from "./Handle.mjs";
|
|
2
2
|
import * as Context from "effect/Context";
|
|
3
3
|
import * as Duration from "effect/Duration";
|
|
4
4
|
import * as Effect from "effect/Effect";
|
|
5
5
|
import * as AsyncResult from "effect/reactivity/AsyncResult";
|
|
6
6
|
import * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
7
7
|
declare namespace Loader_d_exports {
|
|
8
|
-
export { LeaseTTL, Loader, SettledResult, ensure, fetch, make, prefetch };
|
|
8
|
+
export { LeaseTTL, Loader, SettledResult, ensure, fetch, make, prefetch, result };
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
11
|
* A settled `AsyncResult`: what `ensure` and `fetch` return.
|
|
@@ -31,7 +31,7 @@ export type SettledResult<A, E> = AsyncResult.Failure<A, E> | AsyncResult.Succes
|
|
|
31
31
|
*/
|
|
32
32
|
export declare const LeaseTTL: Context.Reference<Duration.Duration>;
|
|
33
33
|
/**
|
|
34
|
-
* Starts
|
|
34
|
+
* Starts a source's atom without waiting for it, and returns its handle.
|
|
35
35
|
*
|
|
36
36
|
* **When to use**
|
|
37
37
|
*
|
|
@@ -41,7 +41,9 @@ export declare const LeaseTTL: Context.Reference<Duration.Duration>;
|
|
|
41
41
|
* **Details**
|
|
42
42
|
*
|
|
43
43
|
* Starts the atom if it isn't in the registry, and leaves it alone if it is.
|
|
44
|
-
* Takes a lease either way.
|
|
44
|
+
* Takes a lease either way. The component that reads the handle suspends
|
|
45
|
+
* until the result settles. On a request registry whose async seed is still
|
|
46
|
+
* running, it waits for the seed first.
|
|
45
47
|
*
|
|
46
48
|
* **Example**
|
|
47
49
|
*
|
|
@@ -49,17 +51,17 @@ export declare const LeaseTTL: Context.Reference<Duration.Duration>;
|
|
|
49
51
|
* import { Effect } from "effect"
|
|
50
52
|
* import { Loader } from "raf-effect-atom"
|
|
51
53
|
*
|
|
52
|
-
* const program = Loader.prefetch(
|
|
54
|
+
* const program = Loader.prefetch(commentPage, issueId, 0)
|
|
53
55
|
* ```
|
|
54
56
|
*
|
|
55
57
|
* @stability unstable
|
|
56
58
|
* @category verbs
|
|
57
59
|
* @since 0.1.0
|
|
58
60
|
*/
|
|
59
|
-
export declare const prefetch: <
|
|
61
|
+
export declare const prefetch: <S extends Source>(source: S, ...args: ArgsOf<S>) => Effect.Effect<Handle<S>, never, AtomRegistry.AtomRegistry>;
|
|
60
62
|
/**
|
|
61
|
-
* Starts
|
|
62
|
-
*
|
|
63
|
+
* Starts a source's atom, waits only while it has no result, and returns a
|
|
64
|
+
* handle whose reader renders without suspending.
|
|
63
65
|
*
|
|
64
66
|
* **When to use**
|
|
65
67
|
*
|
|
@@ -68,10 +70,11 @@ export declare const prefetch: <A, E>(atom: Atom.Atom<AsyncResult.AsyncResult<A,
|
|
|
68
70
|
*
|
|
69
71
|
* **Details**
|
|
70
72
|
*
|
|
71
|
-
* An atom with a result returns
|
|
73
|
+
* An atom with a result returns at once, without refetching. On a request
|
|
72
74
|
* registry, it also waits out a refresh in flight, so the server never
|
|
73
|
-
* renders a result that's about to change. A typed failure
|
|
74
|
-
*
|
|
75
|
+
* renders a result that's about to change. A typed failure settles it like
|
|
76
|
+
* a success: `result` returns it. A defect or an interruption fails the
|
|
77
|
+
* Effect.
|
|
75
78
|
*
|
|
76
79
|
* **Example**
|
|
77
80
|
*
|
|
@@ -81,7 +84,8 @@ export declare const prefetch: <A, E>(atom: Atom.Atom<AsyncResult.AsyncResult<A,
|
|
|
81
84
|
* import { Loader } from "raf-effect-atom"
|
|
82
85
|
*
|
|
83
86
|
* const program = Effect.gen(function* () {
|
|
84
|
-
* const
|
|
87
|
+
* const handle = yield* Loader.ensure(issue, 1)
|
|
88
|
+
* const result = Loader.result(handle)
|
|
85
89
|
* return AsyncResult.isSuccess(result) ? result.value.title : "missing"
|
|
86
90
|
* })
|
|
87
91
|
* ```
|
|
@@ -90,10 +94,11 @@ export declare const prefetch: <A, E>(atom: Atom.Atom<AsyncResult.AsyncResult<A,
|
|
|
90
94
|
* @category verbs
|
|
91
95
|
* @since 0.1.0
|
|
92
96
|
*/
|
|
93
|
-
export declare const ensure: <
|
|
97
|
+
export declare const ensure: <S extends Source>(source: S, ...args: ArgsOf<S>) => Effect.Effect<LoadedHandle<S>, never, AtomRegistry.AtomRegistry>;
|
|
94
98
|
/**
|
|
95
|
-
* Starts
|
|
96
|
-
*
|
|
99
|
+
* Starts a source's atom, or refreshes it if it has a result, waits for the
|
|
100
|
+
* new result to settle, and returns a handle whose reader renders without
|
|
101
|
+
* suspending.
|
|
97
102
|
*
|
|
98
103
|
* **When to use**
|
|
99
104
|
*
|
|
@@ -102,14 +107,45 @@ export declare const ensure: <A, E>(atom: Atom.Atom<AsyncResult.AsyncResult<A, E
|
|
|
102
107
|
*
|
|
103
108
|
* **Details**
|
|
104
109
|
*
|
|
105
|
-
* Waits until the result settles and isn't refreshing. A typed failure
|
|
106
|
-
*
|
|
110
|
+
* Waits until the result settles and isn't refreshing. A typed failure
|
|
111
|
+
* settles it like a success: `result` returns it. A defect or an
|
|
112
|
+
* interruption fails the Effect.
|
|
107
113
|
*
|
|
108
114
|
* @stability unstable
|
|
109
115
|
* @category verbs
|
|
110
116
|
* @since 0.1.0
|
|
111
117
|
*/
|
|
112
|
-
export declare const fetch: <
|
|
118
|
+
export declare const fetch: <S extends Source>(source: S, ...args: ArgsOf<S>) => Effect.Effect<LoadedHandle<S>, never, AtomRegistry.AtomRegistry>;
|
|
119
|
+
/**
|
|
120
|
+
* Returns the settled result `ensure` or `fetch` waited for.
|
|
121
|
+
*
|
|
122
|
+
* **When to use**
|
|
123
|
+
*
|
|
124
|
+
* Use in the loader that ran the verb, to branch on the result: redirect on
|
|
125
|
+
* a tag, or build another atom's arguments from it. Components read the
|
|
126
|
+
* handle with `useAtomResult`, which follows the registry.
|
|
127
|
+
*
|
|
128
|
+
* **Gotchas**
|
|
129
|
+
*
|
|
130
|
+
* Only the handle object the verb returned has it: a handle that crossed
|
|
131
|
+
* the network, as loader data or a server component's prop, is a copy, and
|
|
132
|
+
* this throws for it.
|
|
133
|
+
*
|
|
134
|
+
* **Example**
|
|
135
|
+
*
|
|
136
|
+
* ```ts
|
|
137
|
+
* import { AsyncResult } from "effect/reactivity"
|
|
138
|
+
* import { Loader } from "raf-effect-atom"
|
|
139
|
+
*
|
|
140
|
+
* const handle = await atoms.ensure(issue, id)
|
|
141
|
+
* const error = AsyncResult.error(Loader.result(handle))
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* @stability unstable
|
|
145
|
+
* @category getters
|
|
146
|
+
* @since 0.1.0
|
|
147
|
+
*/
|
|
148
|
+
export declare const result: <S extends Source>(handle: LoadedHandle<S>) => SettledResult<SuccessOf<S>, ErrorOf<S>>;
|
|
113
149
|
/**
|
|
114
150
|
* The loader verbs as Promises over one registry, as the framework
|
|
115
151
|
* integrations put them on the router context.
|
|
@@ -120,11 +156,15 @@ export declare const fetch: <A, E>(atom: Atom.Atom<AsyncResult.AsyncResult<A, E>
|
|
|
120
156
|
*/
|
|
121
157
|
export interface Loader {
|
|
122
158
|
/** {@link ensure}, as a Promise that rejects only on a defect. */
|
|
123
|
-
readonly ensure: <
|
|
159
|
+
readonly ensure: <S extends Source>(source: S, ...args: ArgsOf<S>) => Promise<LoadedHandle<S>>;
|
|
124
160
|
/** {@link fetch}, as a Promise that rejects only on a defect. */
|
|
125
|
-
readonly fetch: <
|
|
126
|
-
/**
|
|
127
|
-
|
|
161
|
+
readonly fetch: <S extends Source>(source: S, ...args: ArgsOf<S>) => Promise<LoadedHandle<S>>;
|
|
162
|
+
/**
|
|
163
|
+
* {@link prefetch}, run at once. On a request registry whose async seed is
|
|
164
|
+
* still running, it returns the handle at once and starts the atom once
|
|
165
|
+
* the seed resolves.
|
|
166
|
+
*/
|
|
167
|
+
readonly prefetch: <S extends Source>(source: S, ...args: ArgsOf<S>) => Handle<S>;
|
|
128
168
|
}
|
|
129
169
|
/**
|
|
130
170
|
* Creates the Promise verbs over one registry.
|
|
@@ -143,8 +183,8 @@ export interface Loader {
|
|
|
143
183
|
* import { Loader, RequestRegistry } from "raf-effect-atom"
|
|
144
184
|
*
|
|
145
185
|
* const loader = Loader.make(RequestRegistry.make())
|
|
146
|
-
* loader.prefetch(
|
|
147
|
-
* const
|
|
186
|
+
* const comments = loader.prefetch(commentPage, 1, 0)
|
|
187
|
+
* const issueHandle = await loader.ensure(issue, 1)
|
|
148
188
|
* ```
|
|
149
189
|
*
|
|
150
190
|
* @stability unstable
|
package/dist/Loader.mjs
CHANGED
|
@@ -2,6 +2,8 @@ import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
|
|
|
2
2
|
import { hydrated } from "./Hydration.mjs";
|
|
3
3
|
import { isDevelopment } from "./internal/development.mjs";
|
|
4
4
|
import { keyOf, take } from "./internal/leases.mjs";
|
|
5
|
+
import { atomOf, loaded as loaded$1, make as make$1 } from "./internal/handles.mjs";
|
|
6
|
+
import { afterSeed, pending } from "./internal/seeds.mjs";
|
|
5
7
|
import { isRequestRegistry } from "./RequestRegistry.mjs";
|
|
6
8
|
import * as Atom from "effect/reactivity/Atom";
|
|
7
9
|
import * as Predicate from "effect/Predicate";
|
|
@@ -17,9 +19,11 @@ import * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
|
17
19
|
* Starts atoms from route loaders, before anything renders, so nothing
|
|
18
20
|
* waterfalls.
|
|
19
21
|
*
|
|
20
|
-
* Each verb
|
|
21
|
-
*
|
|
22
|
-
*
|
|
22
|
+
* Each verb takes a source, an atom family or an `AsyncResult` atom, with its
|
|
23
|
+
* arguments. It starts the atom in the registry, takes a lease on it, so the
|
|
24
|
+
* registry's idle TTL can't evict it before the route renders and
|
|
25
|
+
* `useAtomResult` takes it over, and returns its handle for the component
|
|
26
|
+
* that reads it:
|
|
23
27
|
*
|
|
24
28
|
* | Verb | Starts the atom | Waits | Has a value already |
|
|
25
29
|
* | ---------- | ------------------------------- | ----------------------------- | --------------------- |
|
|
@@ -27,9 +31,10 @@ import * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
|
27
31
|
* | `ensure` | if it isn't in the registry | only while it's `Initial` | returns it at once |
|
|
28
32
|
* | `fetch` | if it isn't, or refreshes it | until the new result settles | refreshes, then waits |
|
|
29
33
|
*
|
|
30
|
-
* Typed failures don't reject: `ensure` and `fetch`
|
|
31
|
-
* `AsyncResult`, so a loader can redirect on a
|
|
32
|
-
* boundary render the failure. Only defects and
|
|
34
|
+
* Typed failures don't reject: `ensure` and `fetch` settle on them, and
|
|
35
|
+
* `result` returns the settled `AsyncResult`, so a loader can redirect on a
|
|
36
|
+
* tag and otherwise let a boundary render the failure. Only defects and
|
|
37
|
+
* interruptions reject.
|
|
33
38
|
*
|
|
34
39
|
* The verbs are Effects that need the `AtomRegistry`; `make` gives the same
|
|
35
40
|
* verbs as Promises over one registry, for loaders that are async functions.
|
|
@@ -42,7 +47,8 @@ var Loader_exports = /* @__PURE__ */ __exportAll({
|
|
|
42
47
|
ensure: () => ensure,
|
|
43
48
|
fetch: () => fetch,
|
|
44
49
|
make: () => make,
|
|
45
|
-
prefetch: () => prefetch
|
|
50
|
+
prefetch: () => prefetch,
|
|
51
|
+
result: () => result
|
|
46
52
|
});
|
|
47
53
|
/**
|
|
48
54
|
* How long a loader's lease keeps an atom mounted when no component takes it
|
|
@@ -61,6 +67,8 @@ var Loader_exports = /* @__PURE__ */ __exportAll({
|
|
|
61
67
|
const LeaseTTL = Context.Reference("raf-effect-atom/Loader/LeaseTTL", { defaultValue: () => Duration.seconds(30) });
|
|
62
68
|
const start = Effect.fnUntraced(function* (atom) {
|
|
63
69
|
const registry = yield* AtomRegistry.AtomRegistry;
|
|
70
|
+
const seed = pending(registry);
|
|
71
|
+
if (seed !== void 0) yield* Effect.promise(() => seed);
|
|
64
72
|
const request = isRequestRegistry(registry);
|
|
65
73
|
if (request && !Atom.isSerializable(atom) && (yield* isDevelopment)) return yield* Effect.die(/* @__PURE__ */ new Error(`raf-effect-atom: a loader started ${String(atom)}, which isn't serializable, so the browser would request it again. Give it a serialization key, such as AtomRpc's serializationKey option.`));
|
|
66
74
|
const ttl = request ? void 0 : Duration.toMillis(yield* LeaseTTL);
|
|
@@ -98,7 +106,7 @@ const rejectDefects = (result) => {
|
|
|
98
106
|
return Effect.succeed(result);
|
|
99
107
|
};
|
|
100
108
|
/**
|
|
101
|
-
* Starts
|
|
109
|
+
* Starts a source's atom without waiting for it, and returns its handle.
|
|
102
110
|
*
|
|
103
111
|
* **When to use**
|
|
104
112
|
*
|
|
@@ -108,7 +116,9 @@ const rejectDefects = (result) => {
|
|
|
108
116
|
* **Details**
|
|
109
117
|
*
|
|
110
118
|
* Starts the atom if it isn't in the registry, and leaves it alone if it is.
|
|
111
|
-
* Takes a lease either way.
|
|
119
|
+
* Takes a lease either way. The component that reads the handle suspends
|
|
120
|
+
* until the result settles. On a request registry whose async seed is still
|
|
121
|
+
* running, it waits for the seed first.
|
|
112
122
|
*
|
|
113
123
|
* **Example**
|
|
114
124
|
*
|
|
@@ -116,19 +126,26 @@ const rejectDefects = (result) => {
|
|
|
116
126
|
* import { Effect } from "effect"
|
|
117
127
|
* import { Loader } from "raf-effect-atom"
|
|
118
128
|
*
|
|
119
|
-
* const program = Loader.prefetch(
|
|
129
|
+
* const program = Loader.prefetch(commentPage, issueId, 0)
|
|
120
130
|
* ```
|
|
121
131
|
*
|
|
122
132
|
* @stability unstable
|
|
123
133
|
* @category verbs
|
|
124
134
|
* @since 0.1.0
|
|
125
135
|
*/
|
|
126
|
-
const prefetch = Effect.
|
|
136
|
+
const prefetch = (source, ...args) => Effect.gen(function* () {
|
|
137
|
+
const atom = atomOf(source, args);
|
|
127
138
|
yield* start(atom);
|
|
139
|
+
return make$1(args, atom);
|
|
128
140
|
});
|
|
141
|
+
const loaded = (args, atom, result) => {
|
|
142
|
+
const handle = loaded$1(args, atom);
|
|
143
|
+
results.set(handle, result);
|
|
144
|
+
return handle;
|
|
145
|
+
};
|
|
129
146
|
/**
|
|
130
|
-
* Starts
|
|
131
|
-
*
|
|
147
|
+
* Starts a source's atom, waits only while it has no result, and returns a
|
|
148
|
+
* handle whose reader renders without suspending.
|
|
132
149
|
*
|
|
133
150
|
* **When to use**
|
|
134
151
|
*
|
|
@@ -137,10 +154,11 @@ const prefetch = Effect.fnUntraced(function* (atom) {
|
|
|
137
154
|
*
|
|
138
155
|
* **Details**
|
|
139
156
|
*
|
|
140
|
-
* An atom with a result returns
|
|
157
|
+
* An atom with a result returns at once, without refetching. On a request
|
|
141
158
|
* registry, it also waits out a refresh in flight, so the server never
|
|
142
|
-
* renders a result that's about to change. A typed failure
|
|
143
|
-
*
|
|
159
|
+
* renders a result that's about to change. A typed failure settles it like
|
|
160
|
+
* a success: `result` returns it. A defect or an interruption fails the
|
|
161
|
+
* Effect.
|
|
144
162
|
*
|
|
145
163
|
* **Example**
|
|
146
164
|
*
|
|
@@ -150,7 +168,8 @@ const prefetch = Effect.fnUntraced(function* (atom) {
|
|
|
150
168
|
* import { Loader } from "raf-effect-atom"
|
|
151
169
|
*
|
|
152
170
|
* const program = Effect.gen(function* () {
|
|
153
|
-
* const
|
|
171
|
+
* const handle = yield* Loader.ensure(issue, 1)
|
|
172
|
+
* const result = Loader.result(handle)
|
|
154
173
|
* return AsyncResult.isSuccess(result) ? result.value.title : "missing"
|
|
155
174
|
* })
|
|
156
175
|
* ```
|
|
@@ -159,13 +178,16 @@ const prefetch = Effect.fnUntraced(function* (atom) {
|
|
|
159
178
|
* @category verbs
|
|
160
179
|
* @since 0.1.0
|
|
161
180
|
*/
|
|
162
|
-
const ensure = Effect.
|
|
181
|
+
const ensure = (source, ...args) => Effect.gen(function* () {
|
|
182
|
+
const atom = atomOf(source, args);
|
|
163
183
|
const started = yield* start(atom);
|
|
164
|
-
|
|
184
|
+
const result = yield* settled(started.registry, started.target, started.request ? isSettled : AsyncResult.isNotInitial);
|
|
185
|
+
return loaded(args, atom, result);
|
|
165
186
|
});
|
|
166
187
|
/**
|
|
167
|
-
* Starts
|
|
168
|
-
*
|
|
188
|
+
* Starts a source's atom, or refreshes it if it has a result, waits for the
|
|
189
|
+
* new result to settle, and returns a handle whose reader renders without
|
|
190
|
+
* suspending.
|
|
169
191
|
*
|
|
170
192
|
* **When to use**
|
|
171
193
|
*
|
|
@@ -174,22 +196,60 @@ const ensure = Effect.fnUntraced(function* (atom) {
|
|
|
174
196
|
*
|
|
175
197
|
* **Details**
|
|
176
198
|
*
|
|
177
|
-
* Waits until the result settles and isn't refreshing. A typed failure
|
|
178
|
-
*
|
|
199
|
+
* Waits until the result settles and isn't refreshing. A typed failure
|
|
200
|
+
* settles it like a success: `result` returns it. A defect or an
|
|
201
|
+
* interruption fails the Effect.
|
|
179
202
|
*
|
|
180
203
|
* @stability unstable
|
|
181
204
|
* @category verbs
|
|
182
205
|
* @since 0.1.0
|
|
183
206
|
*/
|
|
184
|
-
const fetch = Effect.
|
|
207
|
+
const fetch = (source, ...args) => Effect.gen(function* () {
|
|
208
|
+
const atom = atomOf(source, args);
|
|
185
209
|
const started = yield* start(atom);
|
|
186
210
|
const { registry, target } = started;
|
|
187
211
|
if (started.existed && isSettled(registry.get(target))) {
|
|
188
212
|
const node = registry.getNodes().get(keyOf(target));
|
|
189
213
|
registry.refresh(node?.atom ?? target);
|
|
190
214
|
}
|
|
191
|
-
|
|
215
|
+
const result = yield* settled(registry, target, isSettled);
|
|
216
|
+
return loaded(args, atom, result);
|
|
192
217
|
});
|
|
218
|
+
const results = /* @__PURE__ */ new WeakMap();
|
|
219
|
+
/**
|
|
220
|
+
* Returns the settled result `ensure` or `fetch` waited for.
|
|
221
|
+
*
|
|
222
|
+
* **When to use**
|
|
223
|
+
*
|
|
224
|
+
* Use in the loader that ran the verb, to branch on the result: redirect on
|
|
225
|
+
* a tag, or build another atom's arguments from it. Components read the
|
|
226
|
+
* handle with `useAtomResult`, which follows the registry.
|
|
227
|
+
*
|
|
228
|
+
* **Gotchas**
|
|
229
|
+
*
|
|
230
|
+
* Only the handle object the verb returned has it: a handle that crossed
|
|
231
|
+
* the network, as loader data or a server component's prop, is a copy, and
|
|
232
|
+
* this throws for it.
|
|
233
|
+
*
|
|
234
|
+
* **Example**
|
|
235
|
+
*
|
|
236
|
+
* ```ts
|
|
237
|
+
* import { AsyncResult } from "effect/reactivity"
|
|
238
|
+
* import { Loader } from "raf-effect-atom"
|
|
239
|
+
*
|
|
240
|
+
* const handle = await atoms.ensure(issue, id)
|
|
241
|
+
* const error = AsyncResult.error(Loader.result(handle))
|
|
242
|
+
* ```
|
|
243
|
+
*
|
|
244
|
+
* @stability unstable
|
|
245
|
+
* @category getters
|
|
246
|
+
* @since 0.1.0
|
|
247
|
+
*/
|
|
248
|
+
const result = (handle) => {
|
|
249
|
+
const settledResult = results.get(handle);
|
|
250
|
+
if (settledResult === void 0) throw new Error("raf-effect-atom: Loader.result got a handle that no ensure or fetch returned here. Only the code that ran the verb has its result: a handle that crossed the network is a copy. Read it with useAtomResult instead.");
|
|
251
|
+
return settledResult;
|
|
252
|
+
};
|
|
193
253
|
/**
|
|
194
254
|
* Creates the Promise verbs over one registry.
|
|
195
255
|
*
|
|
@@ -207,8 +267,8 @@ const fetch = Effect.fnUntraced(function* (atom) {
|
|
|
207
267
|
* import { Loader, RequestRegistry } from "raf-effect-atom"
|
|
208
268
|
*
|
|
209
269
|
* const loader = Loader.make(RequestRegistry.make())
|
|
210
|
-
* loader.prefetch(
|
|
211
|
-
* const
|
|
270
|
+
* const comments = loader.prefetch(commentPage, 1, 0)
|
|
271
|
+
* const issueHandle = await loader.ensure(issue, 1)
|
|
212
272
|
* ```
|
|
213
273
|
*
|
|
214
274
|
* @stability unstable
|
|
@@ -222,11 +282,15 @@ const make = (registry, options) => {
|
|
|
222
282
|
return leaseTTL === void 0 ? provided : Effect.provideService(provided, LeaseTTL, leaseTTL);
|
|
223
283
|
};
|
|
224
284
|
return {
|
|
225
|
-
ensure: (
|
|
226
|
-
fetch: (
|
|
227
|
-
prefetch: (
|
|
228
|
-
|
|
285
|
+
ensure: (source, ...args) => Effect.runPromise(provide(ensure(source, ...args))),
|
|
286
|
+
fetch: (source, ...args) => Effect.runPromise(provide(fetch(source, ...args))),
|
|
287
|
+
prefetch: (source, ...args) => {
|
|
288
|
+
const atom = atomOf(source, args);
|
|
289
|
+
afterSeed(registry, () => {
|
|
290
|
+
Effect.runSync(provide(start(atom)));
|
|
291
|
+
});
|
|
292
|
+
return make$1(args, atom);
|
|
229
293
|
}
|
|
230
294
|
};
|
|
231
295
|
};
|
|
232
|
-
export { LeaseTTL, Loader_exports, ensure, fetch, make, prefetch };
|
|
296
|
+
export { LeaseTTL, Loader_exports, ensure, fetch, make, prefetch, result };
|
package/dist/Next.d.mts
CHANGED
|
@@ -1,10 +1,65 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ArgsOf, Handle, LoadedHandle, Source } from "./Handle.mjs";
|
|
2
|
+
import { Loader } from "./Loader.mjs";
|
|
3
|
+
import { Options } from "./RequestRegistry.mjs";
|
|
2
4
|
import { HydrateAtoms } from "./NextClient.mjs";
|
|
3
5
|
import { RegistryProvider } from "./RegistryProvider.mjs";
|
|
4
|
-
import * as Atom from "effect/reactivity/Atom";
|
|
5
6
|
import * as EffectHydration from "effect/reactivity/Hydration";
|
|
6
|
-
import * as AsyncResult from "effect/reactivity/AsyncResult";
|
|
7
7
|
import * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
8
|
+
/**
|
|
9
|
+
* The loader verbs over the request registry of the server render in
|
|
10
|
+
* progress, with its registry and `dehydrate`.
|
|
11
|
+
*
|
|
12
|
+
* @stability unstable
|
|
13
|
+
* @category models
|
|
14
|
+
* @since 0.2.0
|
|
15
|
+
*/
|
|
16
|
+
export interface RequestAtoms extends Loader {
|
|
17
|
+
/**
|
|
18
|
+
* `Hydration.dehydrate` on the request's registry, for `HydrateAtoms`,
|
|
19
|
+
* once its seed has settled.
|
|
20
|
+
*/
|
|
21
|
+
readonly dehydrate: () => Promise<Array<EffectHydration.DehydratedAtom>>;
|
|
22
|
+
/** The request registry of the server render in progress. */
|
|
23
|
+
readonly getRegistry: () => AtomRegistry.AtomRegistry;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates the verbs, `getRegistry` and `dehydrate` over a request registry
|
|
27
|
+
* that `seed` prepares.
|
|
28
|
+
*
|
|
29
|
+
* **When to use**
|
|
30
|
+
*
|
|
31
|
+
* Use when the request's atoms need something from the request before they
|
|
32
|
+
* run, such as an RPC protocol that forwards the page request's cookie. Make
|
|
33
|
+
* them once, in a server-only module, and call the verbs on them instead of
|
|
34
|
+
* the ones `raf-effect-atom/next` exports.
|
|
35
|
+
*
|
|
36
|
+
* **Details**
|
|
37
|
+
*
|
|
38
|
+
* The seed runs on each request's registry when a server component first
|
|
39
|
+
* uses it. It can be async, as `headers()` is: `ensure` and `fetch` wait
|
|
40
|
+
* for it, `prefetch` returns its handle at once and starts the atom once the
|
|
41
|
+
* seed resolves, and `dehydrate` waits for both.
|
|
42
|
+
*
|
|
43
|
+
* **Example**
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* // src/atoms.server.ts
|
|
47
|
+
* import "server-only"
|
|
48
|
+
* import { headers } from "next/headers"
|
|
49
|
+
* import { makeRequestAtoms } from "raf-effect-atom/next"
|
|
50
|
+
*
|
|
51
|
+
* export const atoms = makeRequestAtoms({
|
|
52
|
+
* seed: async (registry) => {
|
|
53
|
+
* registry.set(requestCookie, (await headers()).get("cookie") ?? undefined)
|
|
54
|
+
* }
|
|
55
|
+
* })
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @stability unstable
|
|
59
|
+
* @category constructors
|
|
60
|
+
* @since 0.2.0
|
|
61
|
+
*/
|
|
62
|
+
export declare const makeRequestAtoms: (options?: Options) => RequestAtoms;
|
|
8
63
|
/**
|
|
9
64
|
* Returns the request registry of the server render in progress.
|
|
10
65
|
*
|
|
@@ -25,31 +80,32 @@ import * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
|
25
80
|
*/
|
|
26
81
|
export declare const getRegistry: () => AtomRegistry.AtomRegistry;
|
|
27
82
|
/**
|
|
28
|
-
* `Loader.prefetch` on the request's registry: starts
|
|
83
|
+
* `Loader.prefetch` on the request's registry: starts a source's atom, to
|
|
84
|
+
* stream it, and returns its handle.
|
|
29
85
|
*
|
|
30
86
|
* @stability unstable
|
|
31
87
|
* @category verbs
|
|
32
88
|
* @since 0.1.0
|
|
33
89
|
*/
|
|
34
|
-
export declare const prefetch: <
|
|
90
|
+
export declare const prefetch: <S extends Source>(source: S, ...args: ArgsOf<S>) => Handle<S>;
|
|
35
91
|
/**
|
|
36
|
-
* `Loader.ensure` on the request's registry: starts
|
|
37
|
-
*
|
|
92
|
+
* `Loader.ensure` on the request's registry: starts a source's atom, waits
|
|
93
|
+
* for its result, and returns its handle.
|
|
38
94
|
*
|
|
39
95
|
* @stability unstable
|
|
40
96
|
* @category verbs
|
|
41
97
|
* @since 0.1.0
|
|
42
98
|
*/
|
|
43
|
-
export declare const ensure: <
|
|
99
|
+
export declare const ensure: <S extends Source>(source: S, ...args: ArgsOf<S>) => Promise<LoadedHandle<S>>;
|
|
44
100
|
/**
|
|
45
|
-
* `Loader.fetch` on the request's registry: starts or refreshes
|
|
46
|
-
*
|
|
101
|
+
* `Loader.fetch` on the request's registry: starts or refreshes a source's
|
|
102
|
+
* atom, waits for the new result, and returns its handle.
|
|
47
103
|
*
|
|
48
104
|
* @stability unstable
|
|
49
105
|
* @category verbs
|
|
50
106
|
* @since 0.1.0
|
|
51
107
|
*/
|
|
52
|
-
export declare const fetch: <
|
|
108
|
+
export declare const fetch: <S extends Source>(source: S, ...args: ArgsOf<S>) => Promise<LoadedHandle<S>>;
|
|
53
109
|
/**
|
|
54
110
|
* `Hydration.dehydrate` on the request's registry, for `HydrateAtoms`.
|
|
55
111
|
*
|
|
@@ -58,9 +114,17 @@ export declare const fetch: <A, E>(atom: Atom.Atom<AsyncResult.AsyncResult<A, E>
|
|
|
58
114
|
* Includes the atoms started so far, so call it after the server component's
|
|
59
115
|
* verbs. Each `HydrateAtoms` hydrates what its own `dehydrate()` saw.
|
|
60
116
|
*
|
|
117
|
+
* **Example**
|
|
118
|
+
*
|
|
119
|
+
* ```tsx
|
|
120
|
+
* <HydrateAtoms state={await dehydrate()}>
|
|
121
|
+
* <Issue issue={handle} />
|
|
122
|
+
* </HydrateAtoms>
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
61
125
|
* @stability unstable
|
|
62
126
|
* @category dehydration
|
|
63
127
|
* @since 0.1.0
|
|
64
128
|
*/
|
|
65
|
-
export declare const dehydrate: () => Array<EffectHydration.DehydratedAtom
|
|
129
|
+
export declare const dehydrate: () => Promise<Array<EffectHydration.DehydratedAtom>>;
|
|
66
130
|
export { HydrateAtoms, RegistryProvider };
|
package/dist/Next.mjs
CHANGED
|
@@ -1,8 +1,47 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { make } from "./internal/next.mjs";
|
|
2
2
|
import { HydrateAtoms } from "./NextClient.mjs";
|
|
3
3
|
import { RegistryProvider } from "./RegistryProvider.mjs";
|
|
4
4
|
// src/Next.ts
|
|
5
5
|
/**
|
|
6
|
+
* Creates the verbs, `getRegistry` and `dehydrate` over a request registry
|
|
7
|
+
* that `seed` prepares.
|
|
8
|
+
*
|
|
9
|
+
* **When to use**
|
|
10
|
+
*
|
|
11
|
+
* Use when the request's atoms need something from the request before they
|
|
12
|
+
* run, such as an RPC protocol that forwards the page request's cookie. Make
|
|
13
|
+
* them once, in a server-only module, and call the verbs on them instead of
|
|
14
|
+
* the ones `raf-effect-atom/next` exports.
|
|
15
|
+
*
|
|
16
|
+
* **Details**
|
|
17
|
+
*
|
|
18
|
+
* The seed runs on each request's registry when a server component first
|
|
19
|
+
* uses it. It can be async, as `headers()` is: `ensure` and `fetch` wait
|
|
20
|
+
* for it, `prefetch` returns its handle at once and starts the atom once the
|
|
21
|
+
* seed resolves, and `dehydrate` waits for both.
|
|
22
|
+
*
|
|
23
|
+
* **Example**
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* // src/atoms.server.ts
|
|
27
|
+
* import "server-only"
|
|
28
|
+
* import { headers } from "next/headers"
|
|
29
|
+
* import { makeRequestAtoms } from "raf-effect-atom/next"
|
|
30
|
+
*
|
|
31
|
+
* export const atoms = makeRequestAtoms({
|
|
32
|
+
* seed: async (registry) => {
|
|
33
|
+
* registry.set(requestCookie, (await headers()).get("cookie") ?? undefined)
|
|
34
|
+
* }
|
|
35
|
+
* })
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @stability unstable
|
|
39
|
+
* @category constructors
|
|
40
|
+
* @since 0.2.0
|
|
41
|
+
*/
|
|
42
|
+
const makeRequestAtoms = make;
|
|
43
|
+
const atoms = make();
|
|
44
|
+
/**
|
|
6
45
|
* Returns the request registry of the server render in progress.
|
|
7
46
|
*
|
|
8
47
|
* **Details**
|
|
@@ -20,33 +59,34 @@ import { RegistryProvider } from "./RegistryProvider.mjs";
|
|
|
20
59
|
* @category registry
|
|
21
60
|
* @since 0.1.0
|
|
22
61
|
*/
|
|
23
|
-
const getRegistry = getRegistry
|
|
62
|
+
const getRegistry = atoms.getRegistry;
|
|
24
63
|
/**
|
|
25
|
-
* `Loader.prefetch` on the request's registry: starts
|
|
64
|
+
* `Loader.prefetch` on the request's registry: starts a source's atom, to
|
|
65
|
+
* stream it, and returns its handle.
|
|
26
66
|
*
|
|
27
67
|
* @stability unstable
|
|
28
68
|
* @category verbs
|
|
29
69
|
* @since 0.1.0
|
|
30
70
|
*/
|
|
31
|
-
const prefetch = prefetch
|
|
71
|
+
const prefetch = atoms.prefetch;
|
|
32
72
|
/**
|
|
33
|
-
* `Loader.ensure` on the request's registry: starts
|
|
34
|
-
*
|
|
73
|
+
* `Loader.ensure` on the request's registry: starts a source's atom, waits
|
|
74
|
+
* for its result, and returns its handle.
|
|
35
75
|
*
|
|
36
76
|
* @stability unstable
|
|
37
77
|
* @category verbs
|
|
38
78
|
* @since 0.1.0
|
|
39
79
|
*/
|
|
40
|
-
const ensure = ensure
|
|
80
|
+
const ensure = atoms.ensure;
|
|
41
81
|
/**
|
|
42
|
-
* `Loader.fetch` on the request's registry: starts or refreshes
|
|
43
|
-
*
|
|
82
|
+
* `Loader.fetch` on the request's registry: starts or refreshes a source's
|
|
83
|
+
* atom, waits for the new result, and returns its handle.
|
|
44
84
|
*
|
|
45
85
|
* @stability unstable
|
|
46
86
|
* @category verbs
|
|
47
87
|
* @since 0.1.0
|
|
48
88
|
*/
|
|
49
|
-
const fetch = fetch
|
|
89
|
+
const fetch = atoms.fetch;
|
|
50
90
|
/**
|
|
51
91
|
* `Hydration.dehydrate` on the request's registry, for `HydrateAtoms`.
|
|
52
92
|
*
|
|
@@ -55,9 +95,17 @@ const fetch = fetch$1;
|
|
|
55
95
|
* Includes the atoms started so far, so call it after the server component's
|
|
56
96
|
* verbs. Each `HydrateAtoms` hydrates what its own `dehydrate()` saw.
|
|
57
97
|
*
|
|
98
|
+
* **Example**
|
|
99
|
+
*
|
|
100
|
+
* ```tsx
|
|
101
|
+
* <HydrateAtoms state={await dehydrate()}>
|
|
102
|
+
* <Issue issue={handle} />
|
|
103
|
+
* </HydrateAtoms>
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
58
106
|
* @stability unstable
|
|
59
107
|
* @category dehydration
|
|
60
108
|
* @since 0.1.0
|
|
61
109
|
*/
|
|
62
|
-
const dehydrate = dehydrate
|
|
63
|
-
export { HydrateAtoms, RegistryProvider, dehydrate, ensure, fetch, getRegistry, prefetch };
|
|
110
|
+
const dehydrate = atoms.dehydrate;
|
|
111
|
+
export { HydrateAtoms, RegistryProvider, dehydrate, ensure, fetch, getRegistry, makeRequestAtoms, prefetch };
|