import { A as Suspensable, M as Volatile, S as ReadableAtom, p as Atom, t as QueryCache } from "./query-cache-sfUY26Qc.mjs"; import * as Effect from "effect/Effect"; import * as Schema from "effect/Schema"; import * as Stream from "effect/Stream"; import * as Scope from "effect/Scope"; //#region src/infrastructure/mutation-core.d.ts /** The observable state of a mutation — what `yield* m.state` reads. */ interface MutationState { readonly status: 'idle' | 'pending' | 'success' | 'error'; /** The typed failure of the last run, if it failed. */ readonly error: E | undefined; /** The value of the last successful run. */ readonly data: A | undefined; } /** How a mutation is configured beyond its effect. */ interface MutationOptions { /** * Apply an optimistic change immediately (before the effect settles) and * return a rollback thunk that restores the prior state. effract calls the * rollback if the effect fails, so the pre-optimistic state is restored * exactly. */ readonly optimistic?: (input: Input) => () => void; /** Run on success, with the value and the input (e.g. to reconcile local state). */ readonly onSuccess?: (value: A, input: Input) => void; /** Query tags to invalidate on success — matching queries reload. */ readonly invalidates?: ReadonlyArray; } /** * A mutation handle: `run` fires it, `state` is a reactive atom a REC reads * with `yield*` (re-rendering on every transition), `reset` returns to idle. * `state` is read-only to consumers — only the mutation itself writes it. */ interface Mutation { readonly run: (input: Input) => void; readonly state: ReadableAtom, never, L>; readonly reset: () => void; } /** * Construct a {@link Mutation} — label first, like `atom(label, initial)`; the * state atom is named `` `${label}.state` `` (what `RendersOn`, the devtools * trace, and the render ledger report). The effect's requirements `R` are * captured from the constructing context (the service's own `make`), and the * {@link QueryCache} requirement is provided automatically by `mount`. */ declare const mutation: (label: L, run: (input: Input) => Effect.Effect, options?: MutationOptions) => Effect.Effect, never, QueryCache | R>; //#endregion //#region src/infrastructure/reactivity-core.d.ts /** Read an atom inside an `observe`/`` selector, subscribing to it. */ type Read = (atom: ReadableAtom) => A; /** * Run `writes` as one atomic notification wave: atoms may be `set` many times * inside, but subscribers (and the derived atoms and components downstream) are * notified once, after it returns. Returns whatever `writes` returns. * * ```ts * batch(() => { * first.set('Ada'); * last.set('Lovelace'); * }); // one re-render, not two * ``` * * **Synchronous-only, single-flight.** `batchDepth` is module-global mutable * state, so an `await` inside `writes` would leave the batch *open* across the * suspension point — coalescing every unrelated write until it resumes, and on a * server interleaving with other requests' writes. So `writes` must be * synchronous: do the async work first, then `batch` the synchronous writes it * produced. In development this is enforced — a `writes` that returns a `Promise` * (an `async` function, or an awaited value) throws, rather than silently * corrupting the batch depth. */ declare const batch: (writes: () => A) => A; /** * A writable atom that can cross the wire: it carries a stable `serialKey` and a * `Schema` for encode/decode, so its server-computed value can seed the client * (see {@link dehydrate} / {@link hydrate}). Everything else is an ordinary atom * — including the render channel: `V`/`L` ride along exactly as on {@link Atom}, * and the serial key doubles as the label `L`. */ interface SerializableAtom extends Atom { readonly serialKey: string; /** Schema-encode the current value (the shape that crosses the wire). */ readonly encode: () => unknown; /** Schema-decode `encoded` and set it — how a hydrated value seeds the atom. */ readonly hydrate: (encoded: unknown) => void; } /** * Create a writable reactive atom (`atom('count', 0)` — label first, like a * service Tag), plus `atom.fromStream(label, stream, initial)` to bridge an * Effect `Stream` into one (born {@link Volatile} — discharge with `defer` or * `.hot()`) and `atom.serializable(key, initial, schema)` for state that crosses * the wire (the key is the label). */ declare const atom: ((label: L, initial: A) => Atom) & { fromStream: (label: L, stream: Stream.Stream, initial: A) => Effect.Effect, never, R | Scope.Scope>; serializable: (key: L, initial: A, schema: Schema.Codec) => SerializableAtom; }; /** * A keyed collection of atoms — one lazily-created, memoised atom per key, so * per-entity state (a row, a cart line, a todo) is a family lookup rather than * one giant atom you slice. `family(key)` returns the same atom for equal keys; * `make` builds a fresh one the first time a key is seen. `forget`/`clear` drop * cached entries (e.g. when an entity is deleted). Non-primitive keys need a * `keyOf` to reduce them to a stable map key. * * Label first, like `atom(label, initial)`: the label names the *family*, and a * member that is itself an atom gets the runtime name `` `label(key)` `` — so * the devtools trace attributes a write to `quantities(sku-1)`, not `atom17`. * * ```ts * const quantities = atomFamily('quantities', (id: string) => atom(id, 1)); * quantities('sku-1').update((n) => n + 1); // independent per id * ``` */ interface AtomFamily { (key: K): A; /** Drop the cached atom for `key` (the next lookup makes a fresh one). */ forget(key: K): void; /** Drop every cached atom. */ clear(): void; } /** * Opt-in reclamation policy for an {@link atomFamily} keyed by unbounded dynamic * keys (a per-visited id/route), which would otherwise grow without bound. * * - `'unreferenced'` — drop an entry once its atom's last subscriber unsubscribes * (a component reading it via `yield*`/`useAtomValue` counts). Requires the * created value to be subscribable (an atom/derived); any other value is never * reclaimed by this policy. Eviction is deferred a microtask so a StrictMode * unsubscribe→resubscribe keeps the entry. * - `{ maxSize }` — a bounded LRU: keep at most `maxSize` entries, evicting the * least-recently-accessed when the cap is exceeded. */ type AtomFamilyGc = 'unreferenced' | { readonly maxSize: number; }; /** Options for {@link atomFamily}. A bare `keyOf` function is still accepted. */ interface AtomFamilyOptions { /** Reduce a non-primitive key to a stable map key. */ readonly keyOf?: (key: K) => unknown; /** Opt-in reclamation; absent means every entry is kept (strong — the default). */ readonly gc?: AtomFamilyGc; } declare const atomFamily: (label: L, make: (key: K) => A, optionsOrKeyOf?: AtomFamilyOptions | ((key: K) => unknown)) => AtomFamily; /** * Any readable source a `derive` may draw from — value, volatility and label * erased. The tuple constraint below recovers all three per position. */ type AnySource = ReadableAtom; /** The value each source atom in the tuple holds, position by position. */ type ValuesOfTuple> = { readonly [K in keyof T]: T[K] extends ReadableAtom ? A : never }; /** * The union of the sources' volatility — {@link Volatile} if *any* source is * volatile, `never` once none is. A derive of a volatile atom stays volatile. */ type VolatilityOfTuple> = { [K in keyof T]: T[K] extends ReadableAtom ? V : never }[number]; /** * The union of the sources' label literals — a derived value re-renders its * readers exactly when one of its sources changes, so its `RendersOn` set is * the union of theirs. */ type LabelsOfTuple> = { [K in keyof T]: T[K] extends ReadableAtom ? L : never }[number]; /** * An *async derived* value over **explicit sources**: `f` receives the sources' * values and returns an `Effect`, and the result reads in a REC with `yield*` * like any other atom — but it *suspends* while the effect runs, re-runs when a * source atom changes (keyed by the source values, so an unchanged source is not * refetched), and contributes the same loading obligation `S` (plus the effect's * `E`/`R`) that {@link query} does. And like every derive, it inherits the * sources' labels and volatility. Async derivation, still expressed as data in * the Effect world: * * ```ts * const price = derive.effect([sku], ([s]) => fetchPrice(s)); // suspends; refetches on sku change * // in a REC: const p = yield* price; // .suspense(...) must handle the loading * ``` * * It owns no interpreter machinery of its own — yielding it drives, in order, a * subscription (so the component re-renders when a source changes) and a keyed * `query` (so it suspends and refetches). Both are ordinary yieldables, so the * `E`/`R`/`S` channels flow exactly as a hand-written `query` would — and the * `V`/`L` render channel flows through the subscription. */ interface AsyncDerived { [Symbol.iterator](): Iterator | ReadableAtom, V, L>, A>; } /** * Create a *derived* atom from *several* atoms — **explicit sources**: * `derive([a, b], ([x, y]) => x + y)`. The tuple is the subscription set *and* * the type-level fact: labels and volatility flow through with zero annotation. * `derive.writable(sources, f, write)` adds a two-way variant; `derive.effect(sources, f)` * an async, suspending one. Single source? Prefer the `a.derive(f)` method. */ declare const derive: (, B>(sources: T, f: (values: ValuesOfTuple) => B) => ReadableAtom, LabelsOfTuple>) & { writable: , B>(sources: T, f: (values: ValuesOfTuple) => B, write: (value: B) => void) => Atom, LabelsOfTuple>; effect: , A, E, R>(sources: T, f: (values: ValuesOfTuple) => Effect.Effect) => AsyncDerived, LabelsOfTuple>; }; /** * Discharge a volatile atom **at the read**: `defer(a)` strips the * {@link Volatile} obligation (the label stays) by lagging the read behind * React's urgent work — on the client the wrapper is read through * `useDeferredValue`, so a burst of emissions coalesces instead of storming the * tree; on the server it is a plain read (there are no re-renders to schedule). * The other discharge is `.hot()` on the REC — the deliberate acknowledgment * that a subtree is *meant* to render at source frequency; prefer `defer` when * the UI can lag a frame. * * ```ts * const price = yield* defer(ticker.price); // V discharged; label 'price' kept * ``` * * Wrappers are memoised per source atom, so `defer(a)` inside a REC body is * stable across renders (same identity, same subscription, same hook order). * A `.derive` of a deferred atom is itself deferred — the lag survives * projection, which is what keeps its `V = never` honest. */ declare const defer: (source: ReadableAtom) => ReadableAtom; //#endregion export { Read as a, atomFamily as c, derive as d, Mutation as f, mutation as h, AtomFamilyOptions as i, batch as l, MutationState as m, AtomFamily as n, SerializableAtom as o, MutationOptions as p, AtomFamilyGc as r, atom as s, AsyncDerived as t, defer as u };