raf-effect-atom 0.0.0-stage → 0.1.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/dist/Next.mjs ADDED
@@ -0,0 +1,64 @@
1
+ import { dehydrate as dehydrate$1, ensure as ensure$1, fetch as fetch$1, getRegistry as getRegistry$1, prefetch as prefetch$1 } from "./internal/next.mjs";
2
+ import { HydrateAtoms } from "./NextClient.mjs";
3
+ import { RegistryProvider } from "./RegistryProvider.mjs";
4
+ // src/Next.ts
5
+ /**
6
+ * Returns the request registry of the server render in progress.
7
+ *
8
+ * **Details**
9
+ *
10
+ * Made once per request through React's `cache`, and disposed through
11
+ * `cacheSignal` when React finishes the render, after the last streamed
12
+ * result has been sent.
13
+ *
14
+ * **Gotchas**
15
+ *
16
+ * Only server components share it: outside a server component render,
17
+ * `cache` doesn't cache, so each call makes a new registry.
18
+ *
19
+ * @stability unstable
20
+ * @category registry
21
+ * @since 0.1.0
22
+ */
23
+ const getRegistry = getRegistry$1;
24
+ /**
25
+ * `Loader.prefetch` on the request's registry: starts a source's atom, to
26
+ * stream it, and returns its handle.
27
+ *
28
+ * @stability unstable
29
+ * @category verbs
30
+ * @since 0.1.0
31
+ */
32
+ const prefetch = prefetch$1;
33
+ /**
34
+ * `Loader.ensure` on the request's registry: starts a source's atom, waits
35
+ * for its result, and returns its handle.
36
+ *
37
+ * @stability unstable
38
+ * @category verbs
39
+ * @since 0.1.0
40
+ */
41
+ const ensure = ensure$1;
42
+ /**
43
+ * `Loader.fetch` on the request's registry: starts or refreshes a source's
44
+ * atom, waits for the new result, and returns its handle.
45
+ *
46
+ * @stability unstable
47
+ * @category verbs
48
+ * @since 0.1.0
49
+ */
50
+ const fetch = fetch$1;
51
+ /**
52
+ * `Hydration.dehydrate` on the request's registry, for `HydrateAtoms`.
53
+ *
54
+ * **Gotchas**
55
+ *
56
+ * Includes the atoms started so far, so call it after the server component's
57
+ * verbs. Each `HydrateAtoms` hydrates what its own `dehydrate()` saw.
58
+ *
59
+ * @stability unstable
60
+ * @category dehydration
61
+ * @since 0.1.0
62
+ */
63
+ const dehydrate = dehydrate$1;
64
+ export { HydrateAtoms, RegistryProvider, dehydrate, ensure, fetch, getRegistry, prefetch };
@@ -0,0 +1,32 @@
1
+ import { HydrationBoundaryProps } from "./ReactHydration.mjs";
2
+ import * as React from "react";
3
+ /**
4
+ * Hydrates the state a server component dehydrated with `dehydrate()`,
5
+ * streamed results included.
6
+ *
7
+ * **Details**
8
+ *
9
+ * React serializes the state's promises with the server component's
10
+ * payload, so a result still loading streams in when it settles, and
11
+ * `useAtomResult` waits for it instead of requesting it again.
12
+ *
13
+ * **Example**
14
+ *
15
+ * ```tsx
16
+ * import { dehydrate, ensure, HydrateAtoms } from "raf-effect-atom/next"
17
+ *
18
+ * export default async function IssuePage(props: { params: Promise<{ id: string }> }) {
19
+ * const handle = await ensure(issue, Number((await props.params).id))
20
+ * return (
21
+ * <HydrateAtoms state={dehydrate()}>
22
+ * <Issue issue={handle} />
23
+ * </HydrateAtoms>
24
+ * )
25
+ * }
26
+ * ```
27
+ *
28
+ * @stability unstable
29
+ * @category components
30
+ * @since 0.1.0
31
+ */
32
+ export declare const HydrateAtoms: (props: HydrationBoundaryProps) => React.ReactNode;
@@ -0,0 +1,44 @@
1
+ "use client";
2
+ import { HydrationBoundary } from "./ReactHydration.mjs";
3
+ import { jsx } from "react/jsx-runtime";
4
+ // src/NextClient.tsx
5
+ /**
6
+ * The client components of `raf-effect-atom/next`.
7
+ *
8
+ * @stability unstable
9
+ * @since 0.1.0
10
+ */
11
+ /**
12
+ * Hydrates the state a server component dehydrated with `dehydrate()`,
13
+ * streamed results included.
14
+ *
15
+ * **Details**
16
+ *
17
+ * React serializes the state's promises with the server component's
18
+ * payload, so a result still loading streams in when it settles, and
19
+ * `useAtomResult` waits for it instead of requesting it again.
20
+ *
21
+ * **Example**
22
+ *
23
+ * ```tsx
24
+ * import { dehydrate, ensure, HydrateAtoms } from "raf-effect-atom/next"
25
+ *
26
+ * export default async function IssuePage(props: { params: Promise<{ id: string }> }) {
27
+ * const handle = await ensure(issue, Number((await props.params).id))
28
+ * return (
29
+ * <HydrateAtoms state={dehydrate()}>
30
+ * <Issue issue={handle} />
31
+ * </HydrateAtoms>
32
+ * )
33
+ * }
34
+ * ```
35
+ *
36
+ * @stability unstable
37
+ * @category components
38
+ * @since 0.1.0
39
+ */
40
+ const HydrateAtoms = (props) => /* @__PURE__ */ jsx(HydrationBoundary, {
41
+ state: props.state,
42
+ children: props.children
43
+ });
44
+ export { HydrateAtoms };
@@ -0,0 +1,52 @@
1
+ import * as Hydration from "effect/reactivity/Hydration";
2
+ import * as React from "react";
3
+ /**
4
+ * Props for `HydrationBoundary`.
5
+ *
6
+ * @stability unstable
7
+ * @category models
8
+ * @since 0.1.0
9
+ */
10
+ export interface HydrationBoundaryProps {
11
+ readonly children?: React.ReactNode | undefined;
12
+ /** The state `Hydration.dehydrate` returned on the server. */
13
+ readonly state?: Iterable<Hydration.DehydratedAtom> | undefined;
14
+ }
15
+ /**
16
+ * Hydrates the state a server registry dehydrated, streamed results
17
+ * included.
18
+ *
19
+ * **When to use**
20
+ *
21
+ * Use where the server's state reaches the React tree as a prop, such as
22
+ * React Server Components props or a React Router loader's data. A router
23
+ * that hydrates before rendering calls `Hydration.hydrate` instead.
24
+ *
25
+ * **Details**
26
+ *
27
+ * Settled values go to `@effect/atom-react`'s `HydrationBoundary`, which
28
+ * hydrates new atoms during render and existing ones after commit. Each
29
+ * streamed result is held until it arrives, so `useAtomResult` waits for it
30
+ * instead of requesting it again.
31
+ *
32
+ * During server rendering, when `state` is the array `dehydrate` returned,
33
+ * as React Router passes a loader's data to the server render, the children
34
+ * read the registry it came from instead of a copy. The loaders' atoms are
35
+ * there, so an `effect-atom-boundary` boundary sees their failures before
36
+ * its children read them and renders its handler on the server.
37
+ *
38
+ * **Example**
39
+ *
40
+ * ```tsx
41
+ * import { HydrationBoundary } from "raf-effect-atom"
42
+ *
43
+ * <HydrationBoundary state={loaderData.atoms}>
44
+ * <IssuePage issue={loaderData.issue} />
45
+ * </HydrationBoundary>
46
+ * ```
47
+ *
48
+ * @stability unstable
49
+ * @category components
50
+ * @since 0.1.0
51
+ */
52
+ export declare const HydrationBoundary: (props: HydrationBoundaryProps) => React.ReactNode;
@@ -0,0 +1,71 @@
1
+ "use client";
2
+ import { split } from "./internal/pending.mjs";
3
+ import { sourceOf } from "./internal/sources.mjs";
4
+ import { isServer } from "./internal/registry.mjs";
5
+ import { HydrationBoundary, RegistryContext } from "@effect/atom-react";
6
+ import * as React from "react";
7
+ import { jsx } from "react/jsx-runtime";
8
+ // src/ReactHydration.tsx
9
+ /**
10
+ * Applies a server registry's dehydrated state to the nearest
11
+ * `RegistryContext`, while rendering.
12
+ *
13
+ * @stability unstable
14
+ * @since 0.1.0
15
+ */
16
+ /**
17
+ * Hydrates the state a server registry dehydrated, streamed results
18
+ * included.
19
+ *
20
+ * **When to use**
21
+ *
22
+ * Use where the server's state reaches the React tree as a prop, such as
23
+ * React Server Components props or a React Router loader's data. A router
24
+ * that hydrates before rendering calls `Hydration.hydrate` instead.
25
+ *
26
+ * **Details**
27
+ *
28
+ * Settled values go to `@effect/atom-react`'s `HydrationBoundary`, which
29
+ * hydrates new atoms during render and existing ones after commit. Each
30
+ * streamed result is held until it arrives, so `useAtomResult` waits for it
31
+ * instead of requesting it again.
32
+ *
33
+ * During server rendering, when `state` is the array `dehydrate` returned,
34
+ * as React Router passes a loader's data to the server render, the children
35
+ * read the registry it came from instead of a copy. The loaders' atoms are
36
+ * there, so an `effect-atom-boundary` boundary sees their failures before
37
+ * its children read them and renders its handler on the server.
38
+ *
39
+ * **Example**
40
+ *
41
+ * ```tsx
42
+ * import { HydrationBoundary } from "raf-effect-atom"
43
+ *
44
+ * <HydrationBoundary state={loaderData.atoms}>
45
+ * <IssuePage issue={loaderData.issue} />
46
+ * </HydrationBoundary>
47
+ * ```
48
+ *
49
+ * @stability unstable
50
+ * @category components
51
+ * @since 0.1.0
52
+ */
53
+ const HydrationBoundary$1 = (props) => {
54
+ const context = React.useContext(RegistryContext);
55
+ const state = props.state;
56
+ const source = isServer() ? sourceOf(state) : void 0;
57
+ const registry = source ?? context;
58
+ const settled = React.useMemo(() => state === void 0 || source !== void 0 ? void 0 : split(registry, state), [
59
+ registry,
60
+ source,
61
+ state
62
+ ]);
63
+ return /* @__PURE__ */ jsx(RegistryContext.Provider, {
64
+ value: registry,
65
+ children: /* @__PURE__ */ jsx(HydrationBoundary, {
66
+ state: settled,
67
+ children: props.children
68
+ })
69
+ });
70
+ };
71
+ export { HydrationBoundary$1 as HydrationBoundary };
@@ -0,0 +1,63 @@
1
+ import { RegistryProvider } from "./RegistryProvider.mjs";
2
+ import { Loader } from "./Loader.mjs";
3
+ import * as EffectHydration from "effect/reactivity/Hydration";
4
+ import * as AtomRegistry from "effect/reactivity/AtomRegistry";
5
+ /**
6
+ * One request's registry, with the loader verbs over it.
7
+ *
8
+ * @stability unstable
9
+ * @category models
10
+ * @since 0.1.0
11
+ */
12
+ export interface RequestAtoms extends Loader {
13
+ /** `Hydration.dehydrate` on the request's registry, for loader data. */
14
+ readonly dehydrate: () => Array<EffectHydration.DehydratedAtom>;
15
+ readonly registry: AtomRegistry.AtomRegistry;
16
+ }
17
+ /**
18
+ * The router context `atomsMiddleware` sets: what `react-router`'s
19
+ * `createContext<RequestAtoms>()` returns.
20
+ *
21
+ * @stability unstable
22
+ * @category models
23
+ * @since 0.1.0
24
+ */
25
+ export interface AtomsContext {
26
+ readonly defaultValue?: RequestAtoms | undefined;
27
+ }
28
+ /**
29
+ * The parts of React Router's middleware arguments `atomsMiddleware` uses.
30
+ *
31
+ * @stability unstable
32
+ * @category models
33
+ * @since 0.1.0
34
+ */
35
+ export interface MiddlewareArgs {
36
+ readonly context: {
37
+ readonly set: (context: AtomsContext, value: RequestAtoms) => void;
38
+ };
39
+ }
40
+ /**
41
+ * Creates a root middleware that gives each server request its own
42
+ * registry, under the given router context.
43
+ *
44
+ * **Details**
45
+ *
46
+ * The registry is disposed once the response's body has been sent, or the
47
+ * client has gone: loader data streams its pending promises after the
48
+ * middleware returns, so the atoms behind them must keep running until
49
+ * then. When `next` doesn't return a `Response`, as Data Mode's
50
+ * `query` can, the registry is left to be collected with the request.
51
+ *
52
+ * **Gotchas**
53
+ *
54
+ * It's server middleware: export it as the root route's `middleware`, not
55
+ * `clientMiddleware`. In the browser, the root's `RegistryProvider` holds
56
+ * the registry.
57
+ *
58
+ * @stability unstable
59
+ * @category integrations
60
+ * @since 0.1.0
61
+ */
62
+ export declare const atomsMiddleware: (context: AtomsContext) => <Result>(args: MiddlewareArgs, next: () => Promise<Result>) => Promise<Result>;
63
+ export { RegistryProvider };
@@ -0,0 +1,116 @@
1
+ import { dehydrate } from "./Hydration.mjs";
2
+ import { make } from "./RequestRegistry.mjs";
3
+ import { make as make$1 } from "./Loader.mjs";
4
+ import { RegistryProvider } from "./RegistryProvider.mjs";
5
+ import * as Predicate from "effect/Predicate";
6
+ // src/ReactRouter.ts
7
+ /**
8
+ * Connects the loader verbs to React Router's Framework Mode.
9
+ *
10
+ * A root `middleware` gives each server request its own registry, under a
11
+ * router context the app creates. Loaders start atoms with its verbs and
12
+ * return its `dehydrate()` with their data; the route component hydrates it
13
+ * with `HydrationBoundary`, inside the root's `RegistryProvider`. Nothing is
14
+ * imported from `react-router`.
15
+ *
16
+ * **Example**
17
+ *
18
+ * ```tsx
19
+ * // app/atoms.ts
20
+ * import { createContext } from "react-router"
21
+ * import type { RequestAtoms } from "raf-effect-atom/react-router"
22
+ *
23
+ * export const atomsContext = createContext<RequestAtoms>()
24
+ *
25
+ * // app/root.tsx
26
+ * import { atomsMiddleware } from "raf-effect-atom/react-router"
27
+ *
28
+ * export const middleware = [atomsMiddleware(atomsContext)]
29
+ *
30
+ * // app/routes/issue.tsx
31
+ * export async function loader(args: Route.LoaderArgs) {
32
+ * const atoms = args.context.get(atomsContext)
33
+ * const handle = await atoms.ensure(issue, Number(args.params.id))
34
+ * return { atoms: atoms.dehydrate(), issue: handle }
35
+ * }
36
+ *
37
+ * export default function IssueRoute(props: Route.ComponentProps) {
38
+ * return (
39
+ * <HydrationBoundary state={props.loaderData.atoms}>
40
+ * <Issue issue={props.loaderData.issue} />
41
+ * </HydrationBoundary>
42
+ * )
43
+ * }
44
+ * ```
45
+ *
46
+ * @stability unstable
47
+ * @since 0.1.0
48
+ */
49
+ /**
50
+ * Creates a root middleware that gives each server request its own
51
+ * registry, under the given router context.
52
+ *
53
+ * **Details**
54
+ *
55
+ * The registry is disposed once the response's body has been sent, or the
56
+ * client has gone: loader data streams its pending promises after the
57
+ * middleware returns, so the atoms behind them must keep running until
58
+ * then. When `next` doesn't return a `Response`, as Data Mode's
59
+ * `query` can, the registry is left to be collected with the request.
60
+ *
61
+ * **Gotchas**
62
+ *
63
+ * It's server middleware: export it as the root route's `middleware`, not
64
+ * `clientMiddleware`. In the browser, the root's `RegistryProvider` holds
65
+ * the registry.
66
+ *
67
+ * @stability unstable
68
+ * @category integrations
69
+ * @since 0.1.0
70
+ */
71
+ const atomsMiddleware = (context) => async (args, next) => {
72
+ const registry = make();
73
+ const loader = make$1(registry);
74
+ args.context.set(context, {
75
+ ...loader,
76
+ dehydrate: () => dehydrate(registry),
77
+ registry
78
+ });
79
+ let result;
80
+ try {
81
+ result = await next();
82
+ } catch (error) {
83
+ registry.dispose();
84
+ throw error;
85
+ }
86
+ if (!isResponse(result)) return result;
87
+ const body = result.body;
88
+ if (body === null) {
89
+ registry.dispose();
90
+ return result;
91
+ }
92
+ return new Response(disposeAfter(body, registry), result);
93
+ };
94
+ const isResponse = (value) => Predicate.hasProperty(value, "body") && Predicate.hasProperty(value, "headers") && Predicate.hasProperty(value, "status");
95
+ const disposeAfter = (body, registry) => {
96
+ const reader = body.getReader();
97
+ return new ReadableStream({
98
+ cancel: async (reason) => {
99
+ registry.dispose();
100
+ await reader.cancel(reason);
101
+ },
102
+ pull: async (controller) => {
103
+ try {
104
+ const chunk = await reader.read();
105
+ if (chunk.done) {
106
+ registry.dispose();
107
+ controller.close();
108
+ } else controller.enqueue(chunk.value);
109
+ } catch (error) {
110
+ registry.dispose();
111
+ controller.error(error);
112
+ }
113
+ }
114
+ });
115
+ };
116
+ export { RegistryProvider, atomsMiddleware };
@@ -0,0 +1,40 @@
1
+ import * as React from "react";
2
+ /**
3
+ * Provides the app's registry: a request registry while the framework
4
+ * renders the app on the server, and one registry for the page's lifetime
5
+ * in the browser.
6
+ *
7
+ * **When to use**
8
+ *
9
+ * Put it in the root layout, around `children`, in place of
10
+ * `@effect/atom-react`'s `RegistryProvider`, which would share one registry
11
+ * between requests' server renders.
12
+ *
13
+ * **Details**
14
+ *
15
+ * `defaultIdleTTL` is how many milliseconds the browser's registry keeps an
16
+ * atom no component reads, 400 by default, as `@effect/atom-react`'s default
17
+ * registry does. An atom's own `Atom.setIdleTTL` or `Atom.keepAlive` wins.
18
+ * It's read once, when the registry is made. The server's request registry
19
+ * lives for one request, so it has none.
20
+ *
21
+ * **Example**
22
+ *
23
+ * ```tsx
24
+ * import { RegistryProvider } from "raf-effect-atom/next" // or "raf-effect-atom/react-router"
25
+ *
26
+ * export default function RootLayout(props: { children: React.ReactNode }) {
27
+ * return (
28
+ * <RegistryProvider defaultIdleTTL={60_000}>{props.children}</RegistryProvider>
29
+ * )
30
+ * }
31
+ * ```
32
+ *
33
+ * @stability unstable
34
+ * @category components
35
+ * @since 0.1.0
36
+ */
37
+ export declare const RegistryProvider: (props: {
38
+ readonly children?: React.ReactNode | undefined;
39
+ readonly defaultIdleTTL?: number | undefined;
40
+ }) => React.ReactNode;
@@ -0,0 +1,55 @@
1
+ "use client";
2
+ import { make } from "./internal/registry.mjs";
3
+ import { RegistryContext } from "@effect/atom-react";
4
+ import * as React from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ // src/RegistryProvider.tsx
7
+ /**
8
+ * The registry provider shared by the Next.js and React Router integrations.
9
+ *
10
+ * @stability unstable
11
+ * @since 0.1.0
12
+ */
13
+ /**
14
+ * Provides the app's registry: a request registry while the framework
15
+ * renders the app on the server, and one registry for the page's lifetime
16
+ * in the browser.
17
+ *
18
+ * **When to use**
19
+ *
20
+ * Put it in the root layout, around `children`, in place of
21
+ * `@effect/atom-react`'s `RegistryProvider`, which would share one registry
22
+ * between requests' server renders.
23
+ *
24
+ * **Details**
25
+ *
26
+ * `defaultIdleTTL` is how many milliseconds the browser's registry keeps an
27
+ * atom no component reads, 400 by default, as `@effect/atom-react`'s default
28
+ * registry does. An atom's own `Atom.setIdleTTL` or `Atom.keepAlive` wins.
29
+ * It's read once, when the registry is made. The server's request registry
30
+ * lives for one request, so it has none.
31
+ *
32
+ * **Example**
33
+ *
34
+ * ```tsx
35
+ * import { RegistryProvider } from "raf-effect-atom/next" // or "raf-effect-atom/react-router"
36
+ *
37
+ * export default function RootLayout(props: { children: React.ReactNode }) {
38
+ * return (
39
+ * <RegistryProvider defaultIdleTTL={60_000}>{props.children}</RegistryProvider>
40
+ * )
41
+ * }
42
+ * ```
43
+ *
44
+ * @stability unstable
45
+ * @category components
46
+ * @since 0.1.0
47
+ */
48
+ const RegistryProvider = (props) => {
49
+ const [registry] = React.useState(() => make({ defaultIdleTTL: props.defaultIdleTTL }));
50
+ return /* @__PURE__ */ jsx(RegistryContext.Provider, {
51
+ value: registry,
52
+ children: props.children
53
+ });
54
+ };
55
+ export { RegistryProvider };
@@ -0,0 +1,54 @@
1
+ import * as AtomRegistry from "effect/reactivity/AtomRegistry";
2
+ import * as Layer from "effect/Layer";
3
+ declare namespace RequestRegistry_d_exports {
4
+ export { isRequestRegistry, layer, make };
5
+ }
6
+ /**
7
+ * Creates the registry for one server request.
8
+ *
9
+ * **Details**
10
+ *
11
+ * It's an ordinary `AtomRegistry`, marked as a request registry. On a
12
+ * request registry, `ensure` waits like `fetch` does, nothing revalidates in
13
+ * the background, and a loader's lease lasts until the registry is disposed.
14
+ * In development, the loader verbs refuse an atom that isn't serializable,
15
+ * because the browser would request it again.
16
+ *
17
+ * **Example**
18
+ *
19
+ * ```ts
20
+ * import { RequestRegistry } from "raf-effect-atom"
21
+ *
22
+ * const registry = RequestRegistry.make()
23
+ * ```
24
+ *
25
+ * @stability unstable
26
+ * @category constructors
27
+ * @since 0.1.0
28
+ */
29
+ export declare const make: () => AtomRegistry.AtomRegistry;
30
+ /**
31
+ * A layer that provides a request registry as the `AtomRegistry`, disposed
32
+ * when the layer's scope closes.
33
+ *
34
+ * **When to use**
35
+ *
36
+ * Use when the request is handled in Effect, around the loaders' verbs and
37
+ * `dehydrate`.
38
+ *
39
+ * @see {@link make} for the registry it provides
40
+ *
41
+ * @stability unstable
42
+ * @category layers
43
+ * @since 0.1.0
44
+ */
45
+ export declare const layer: Layer.Layer<AtomRegistry.AtomRegistry>;
46
+ /**
47
+ * Returns whether a registry was made by `make`, for one server request.
48
+ *
49
+ * @stability unstable
50
+ * @category guards
51
+ * @since 0.1.0
52
+ */
53
+ export declare const isRequestRegistry: (registry: AtomRegistry.AtomRegistry) => boolean;
54
+ export { RequestRegistry_d_exports };
@@ -0,0 +1,76 @@
1
+ import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
2
+ import * as Effect from "effect/Effect";
3
+ import * as AtomRegistry from "effect/reactivity/AtomRegistry";
4
+ import * as Layer from "effect/Layer";
5
+ // src/RequestRegistry.ts
6
+ /**
7
+ * A registry per server request.
8
+ *
9
+ * `@effect/atom-react`'s default `RegistryContext` is one registry for the
10
+ * whole module, which on a server would share one user's results with every
11
+ * other request. Each framework integration makes a request registry with
12
+ * `make`, provides it through `RegistryContext`, and dehydrates it into the
13
+ * response.
14
+ *
15
+ * @stability unstable
16
+ * @since 0.1.0
17
+ */
18
+ var RequestRegistry_exports = /* @__PURE__ */ __exportAll({
19
+ isRequestRegistry: () => isRequestRegistry,
20
+ layer: () => layer,
21
+ make: () => make
22
+ });
23
+ const requestRegistries = /* @__PURE__ */ new WeakSet();
24
+ /**
25
+ * Creates the registry for one server request.
26
+ *
27
+ * **Details**
28
+ *
29
+ * It's an ordinary `AtomRegistry`, marked as a request registry. On a
30
+ * request registry, `ensure` waits like `fetch` does, nothing revalidates in
31
+ * the background, and a loader's lease lasts until the registry is disposed.
32
+ * In development, the loader verbs refuse an atom that isn't serializable,
33
+ * because the browser would request it again.
34
+ *
35
+ * **Example**
36
+ *
37
+ * ```ts
38
+ * import { RequestRegistry } from "raf-effect-atom"
39
+ *
40
+ * const registry = RequestRegistry.make()
41
+ * ```
42
+ *
43
+ * @stability unstable
44
+ * @category constructors
45
+ * @since 0.1.0
46
+ */
47
+ const make = () => {
48
+ const registry = AtomRegistry.make();
49
+ requestRegistries.add(registry);
50
+ return registry;
51
+ };
52
+ /**
53
+ * A layer that provides a request registry as the `AtomRegistry`, disposed
54
+ * when the layer's scope closes.
55
+ *
56
+ * **When to use**
57
+ *
58
+ * Use when the request is handled in Effect, around the loaders' verbs and
59
+ * `dehydrate`.
60
+ *
61
+ * @see {@link make} for the registry it provides
62
+ *
63
+ * @stability unstable
64
+ * @category layers
65
+ * @since 0.1.0
66
+ */
67
+ const layer = Layer.effect(AtomRegistry.AtomRegistry, Effect.acquireRelease(Effect.sync(() => make()), (registry) => Effect.sync(() => registry.dispose())));
68
+ /**
69
+ * Returns whether a registry was made by `make`, for one server request.
70
+ *
71
+ * @stability unstable
72
+ * @category guards
73
+ * @since 0.1.0
74
+ */
75
+ const isRequestRegistry = (registry) => requestRegistries.has(registry);
76
+ export { RequestRegistry_exports, isRequestRegistry, layer, make };