effectweb 0.2.3 → 0.3.1

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.
Files changed (77) hide show
  1. package/README.md +93 -1
  2. package/dist/AsyncContent.d.ts +2 -2
  3. package/dist/AsyncContent.js +7 -4
  4. package/dist/actions.d.ts +4 -3
  5. package/dist/actions.js +1 -0
  6. package/dist/boundary.d.ts +11 -0
  7. package/dist/boundary.js +66 -0
  8. package/dist/cache-internals.d.ts +18 -0
  9. package/dist/cache-internals.js +11 -0
  10. package/dist/cache.d.ts +35 -16
  11. package/dist/cache.js +258 -37
  12. package/dist/collection.d.ts +10 -9
  13. package/dist/collection.js +32 -6
  14. package/dist/component.d.ts +11 -7
  15. package/dist/component.js +70 -10
  16. package/dist/diagnostics.d.ts +25 -0
  17. package/dist/diagnostics.js +167 -1
  18. package/dist/dom-attributes.json +71 -0
  19. package/dist/dom.d.ts +44 -15
  20. package/dist/dom.js +493 -89
  21. package/dist/effectEvent.d.ts +2 -1
  22. package/dist/effectEvent.js +4 -1
  23. package/dist/form.d.ts +61 -0
  24. package/dist/form.js +98 -0
  25. package/dist/html-attributes.d.ts +602 -0
  26. package/dist/html-attributes.js +1 -0
  27. package/dist/http.d.ts +5 -0
  28. package/dist/http.js +7 -0
  29. package/dist/index.d.ts +16 -11
  30. package/dist/index.js +11 -6
  31. package/dist/infinite-query.d.ts +42 -0
  32. package/dist/infinite-query.js +150 -0
  33. package/dist/intrinsic.d.ts +2 -0
  34. package/dist/intrinsic.js +120 -0
  35. package/dist/jsx.d.ts +165 -33
  36. package/dist/jsx.js +2 -1
  37. package/dist/keyed-tasks.d.ts +29 -0
  38. package/dist/keyed-tasks.js +97 -0
  39. package/dist/lazy.d.ts +23 -0
  40. package/dist/lazy.js +66 -0
  41. package/dist/load.d.ts +3 -3
  42. package/dist/mount.d.ts +11 -12
  43. package/dist/mount.js +30 -14
  44. package/dist/owner.d.ts +14 -10
  45. package/dist/owner.js +66 -39
  46. package/dist/pages.d.ts +28 -26
  47. package/dist/pages.js +19 -11
  48. package/dist/program.d.ts +29 -9
  49. package/dist/program.js +204 -61
  50. package/dist/query-internals.d.ts +13 -0
  51. package/dist/query-internals.js +10 -0
  52. package/dist/query.d.ts +30 -19
  53. package/dist/query.js +64 -5
  54. package/dist/resource.d.ts +4 -10
  55. package/dist/resource.js +14 -5
  56. package/dist/runtime.d.ts +1 -2
  57. package/dist/runtime.js +3 -3
  58. package/dist/session.d.ts +12 -15
  59. package/dist/session.js +25 -13
  60. package/dist/settlement.d.ts +7 -0
  61. package/dist/settlement.js +27 -0
  62. package/dist/share.d.ts +5 -4
  63. package/dist/share.js +5 -44
  64. package/dist/sharing.d.ts +6 -0
  65. package/dist/sharing.js +96 -0
  66. package/dist/slotIdentity.d.ts +1 -0
  67. package/dist/slotIdentity.js +2 -0
  68. package/dist/snapshot.d.ts +16 -5
  69. package/dist/snapshot.js +34 -27
  70. package/dist/svg-attributes.d.ts +12 -0
  71. package/dist/svg-attributes.js +1 -0
  72. package/dist/task.d.ts +9 -8
  73. package/dist/task.js +75 -47
  74. package/dist/tasks.d.ts +20 -15
  75. package/dist/tasks.js +40 -25
  76. package/dist/testing.d.ts +10 -14
  77. package/package.json +13 -1
package/README.md CHANGED
@@ -6,4 +6,96 @@ Use with `@effectweb/compiler/vite` and Effect `4.0.0-rc.112`. The package inclu
6
6
 
7
7
  See [setup and example](https://github.com/DerpyCrabs/EffectWeb#vite-setup).
8
8
 
9
- Early API; runtime and compiler versions advance together. Client-side only. Persistence and multi-tab coordination belong to the application.
9
+ Runtime and compiler versions advance together. Client-side only. Persistence and multi-tab coordination belong to the application.
10
+
11
+ ## Query identity and account ownership
12
+
13
+ A query definition has its own identity. Within one cache, all request arguments form its key automatically:
14
+
15
+ ```ts
16
+ const page = query({
17
+ name: 'message-page',
18
+ load: (args: { accountId: string; threadId: string; cursor?: string }) =>
19
+ api.messages(args.accountId, args.threadId, args.cursor),
20
+ });
21
+ ```
22
+
23
+ Request arguments use the same canonical encoding for cache lookup, prefetch, writes, invalidation, and `queryResource.select`. Object property order is ignored; array order matters. Strings, finite numbers, booleans, `null`, and explicit `undefined` are supported recursively in dense arrays and plain objects. Missing properties differ from properties containing `undefined`, and `0` differs from `-0`. Functions, symbols, bigint, nonfinite numbers, cycles, class instances, accessors, nonenumerable properties, sparse arrays, and arrays with extra properties throw `TypeError`. Repeated references to the same plain object are supported. Published argument objects are frozen and are not cloned.
24
+
25
+ Pass every load-relevant value as an argument, including account, filters, pagination, locale, and permissions when they affect the result. Custom `key` projections are rejected. Provide service instances through the Effect environment instead of query arguments. Separate query definitions do not share entries even if their names and arguments match. `select(undefined)` disables selection; an explicit `undefined` inside an argument object remains part of its identity. A query without arguments uses `true` for selection and prefetch.
26
+
27
+ Give authenticated data an account lifetime:
28
+
29
+ ```ts
30
+ const account = modelOwner({ accountId }, { runtime });
31
+ const cache = account.own(makeQueryCache(runtime));
32
+ const messages = observeQuery(account, cache, page, (result) => {
33
+ // Publish the immutable result into application state.
34
+ });
35
+ messages.select({ accountId, threadId });
36
+
37
+ // Sign out or switch account: dispose this lifetime, then create the next one.
38
+ account.dispose();
39
+ ```
40
+
41
+ Independent caches isolate account data even when services derive authentication from their environment. If an application deliberately reuses a cache across accounts, include account identity in every authenticated query key and call `cache.resetResources()` at the boundary before selecting the new account. Reset interrupts old resources and returns existing query observers to their initial state; select again to enter the new generation. Disposing only a query observer releases its subscription; it does not erase shared cached values. Own shared caches at the account or application scope, not in individual views.
42
+
43
+ Use `cache.setQueryData(query, args, value)` to seed or replace a cached success, and `cache.updateQueryData(query, args, update)` to change an existing success. The updater receives readonly data; returning `undefined` skips the write. Both publish to current observers and supersede pending loads for those arguments. Use `setQueryData` to store a successful `undefined` value. Query definitions and cache registries are opaque; use the public cache and observation methods.
44
+
45
+ ## Write concurrency
46
+
47
+ `modelOwner.run(slot, effect, policy)` and `defineTasks(owner, definitions)` support these policies:
48
+
49
+ | Policy | Behavior for an occupied slot |
50
+ | --------------- | ----------------------------------------------------------------------- |
51
+ | `drop` | Ignore the new request. |
52
+ | `replace` | Cancel active work and discard pending requests; start the new request. |
53
+ | `parallel` | Start the new request alongside active work. |
54
+ | `queue` | Append the request; run it after earlier work finishes. |
55
+ | `latest-queued` | Keep active work; replace all pending requests with the newest request. |
56
+
57
+ Every command requires an explicit `policy`. Create stable operation identities with `commandSlot('save')`; equal diagnostic names do not share a slot. Component `defineTasks(...).tasks(...)` and `taskComponent` support all except `parallel`, since their single result slot represents serial work. Command mapping and runtime service provisioning preserve the policy. Actions sharing a slot share concurrency and cancellation. A queued request waits for every active request in that slot if policies are mixed; keep a consistent policy per slot for predictable write behavior.
58
+
59
+ Use `queue` when each accepted operation matters, such as appending messages. Use `latest-queued` when saving complete document snapshots and only the newest pending snapshot matters:
60
+
61
+ ```ts
62
+ const writes = defineTasks(owner, {
63
+ save: { policy: 'latest-queued', run: (document: Snapshot<Document>) => storage.save(document) },
64
+ });
65
+
66
+ writes.save(owner.read().document);
67
+ ```
68
+
69
+ Component tasks capture the model snapshot and input when `Run` is submitted, including requests that wait in a queue. Editing fields afterward does not replace that captured model. Controller tasks retain their supplied arguments; their factories execute when work starts. Pass `owner.read()` data as arguments to capture submission state, or read inside the Effect when execution-time state is intended. Effects and inputs are retained, not deep-cloned; keep supplied data immutable. Dropped and coalesced pending factories are never invoked.
70
+
71
+ Queue progress continues after successes, typed failures, or defects. Component results remain `waiting` while more work is pending, publish each settlement, and retain the latest successful value if a later write fails. Action failures use the owner's error reporter. `cancel`, component reset or identity change, and disposal discard pending requests and interrupt active work; stale command completions cannot publish afterward. `awaitIdle` includes pending work. Cancellation cannot undo an external write that already completed. Transactions admit their whole command batch before starting Effects, so replacements and cancellation can remove superseded work without executing it.
72
+
73
+ ## Lazy views and portals
74
+
75
+ `lazyView(() => fromPromise(() => import('./Reader').then((module) => module.Reader)))` loads a view when mounted. It accepts typed `pending` and `failure` views and a `runtime` when the loader requires services. Each unresolved placement owns its load; unmounting interrupts it. Successful definitions are cached for future mounts. Render a lazy view through `ViewBinding` with its current model and sender.
76
+
77
+ `<Portal mount={model.dialogHost}>...</Portal>` renders into a supplied HTML or SVG element. Omitting `mount` uses the document body. Portal content retains its owner, events, and cleanup; changing between HTML and SVG targets rebuilds content in the correct namespace.
78
+
79
+ ## Inspect source dependencies
80
+
81
+ Mount a development panel before mounting the application so it sees initial evaluations:
82
+
83
+ ```ts
84
+ import { mountBindingInspector } from 'effectweb/diagnostics';
85
+
86
+ const removeInspector = mountBindingInspector(document.querySelector<HTMLElement>('#inspector')!);
87
+ // Mount the application here. On teardown or HMR:
88
+ // removeInspector();
89
+ ```
90
+
91
+ The live, filterable table shows original file/line/column, source expressions, inferred snapshot dependencies, the latest changed dependency names, and derive/binding evaluation counts. It uses development compiler metadata; production builds emit none. Counts include initial evaluations, aggregate instances of the same source expression, and measure evaluations rather than actual DOM writes. Change reasons use reference/value equality, without retaining previous or next values.
92
+
93
+ For custom tooling, `inspectBindings({ limit: 200 })` returns `entries()`, `subscribe(listener)`, `clear()`, and `dispose()`. Entries are immutable metadata, newest first, with at most 1000 source records. Least recently updated sources are evicted and start fresh if seen again. `dispose()` unsubscribes and clears retained metadata. `mountBindingInspector(element, inspector)` can share an inspector; removing that panel leaves the supplied inspector running. Low-level `observeBindings` remains available.
94
+
95
+ The inspector covers instrumented derivations and text/attribute bindings; it is not a snapshot recorder, time-travel debugger, or complete profile of branch/list reconciliation. Source labels describe the compiler's inferred dependencies, not a proof that an opaque helper has no hidden state.
96
+
97
+ ## Immutable inputs and outputs
98
+
99
+ Published `Snapshot<T>` values are recursively readonly, including nested arrays/tuples and async success data. View/slot composition, component inputs, owner patches, and task field updates accept readonly branches without casts. Query cache reads, subscriptions, and prefetch publish the same readonly data. Plain objects and arrays are frozen before publication in every build; snapshot protection cannot be disabled.
100
+
101
+ Functions, Effects, DOM nodes, and explicitly marked service classes retain their own API. See the [authoring guide](https://github.com/DerpyCrabs/EffectWeb/blob/main/docs/authoring.md) for migration examples, `SnapshotOpaque`, state ownership, form composition, and reconciling async loads with live updates.
@@ -13,8 +13,8 @@ export interface AsyncContentProps<A, E> {
13
13
  }
14
14
  type Props = AsyncContentProps<unknown, unknown>;
15
15
  /** Presentation only: resource owners choose identity, loading, caching and cancellation. */
16
- export declare const AsyncContent: {
17
- <A, E>(props: AsyncContentProps<A, E>): JSX.Element;
16
+ export declare const AsyncContent: JSX.ComponentType & {
17
+ <A, E>(this: never, props: AsyncContentProps<A, E>): JSX.Element;
18
18
  readonly build: View<Props, never>["build"];
19
19
  };
20
20
  export {};
@@ -1,9 +1,11 @@
1
1
  import * as _ew_dom from "./dom.js";
2
+ import { commandSlot } from "./program.js";
2
3
  import { Cause, Effect, Option } from "effect";
3
4
  import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
4
5
  import { component } from "./component.js";
5
6
  import { view } from "./index.js";
6
7
  import { effectCommand } from "./program.js";
8
+ const commandPending = commandSlot("pending");
7
9
  const implementation = component({
8
10
  init: (props) => ({
9
11
  props,
@@ -19,7 +21,7 @@ const implementation = component({
19
21
  pending: false,
20
22
  visible: false
21
23
  },
22
- cancel: ["pending"]
24
+ cancel: [commandPending]
23
25
  };
24
26
  if (model.pending && model.props.pendingDelay === props.pendingDelay)
25
27
  return { model: {
@@ -33,8 +35,9 @@ const implementation = component({
33
35
  pending: true,
34
36
  visible: delay === 0
35
37
  },
36
- cancel: ["pending"],
37
- commands: delay === 0 ? [] : [effectCommand("pending", () => Effect.sleep(delay), {
38
+ cancel: [commandPending],
39
+ commands: delay === 0 ? [] : [effectCommand(commandPending, () => Effect.sleep(delay), {
40
+ policy: "replace",
38
41
  onSuccess: () => ({ type: "ShowPending" }),
39
42
  onFailure: () => ({ type: "ShowPending" })
40
43
  })]
@@ -47,7 +50,7 @@ const implementation = component({
47
50
  view: /* @__PURE__ */ _ew_dom.compiled((_ew_scope_1, _ew_parent_2, _ew_before_3) => {
48
51
  const _ew_derived_4 = _ew_scope_1.derive(() => [_ew_scope_1.value?.props], () => {
49
52
  const _ew_capture_6 = _ew_scope_1.value;
50
- return _ew_capture_6.props;
53
+ return _ew_dom.intrinsic(_ew_dom.intrinsic(_ew_capture_6, ["props", "content"], "@slot"), ["props", "failure"], "@slot").props;
51
54
  });
52
55
  const _ew_derived_7 = _ew_scope_1.derive(() => [_ew_derived_4()?.result], () => {
53
56
  const _ew_capture_9 = _ew_derived_4();
package/dist/actions.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Send, Transition } from './program.js';
2
- type Handler<Model> = (model: Model, ...args: never[]) => Transition<Model, unknown>;
2
+ import type { Snapshot } from './snapshot.js';
3
+ type Handler<Model, R> = (model: Snapshot<Model>, ...args: never[]) => Transition<Model, unknown, R>;
3
4
  type Arguments<F> = F extends (model: never, ...args: infer Args) => unknown ? Args : never;
4
5
  type HandlerMessage<Handlers> = {
5
6
  [Name in keyof Handlers]: {
@@ -18,9 +19,9 @@ type Creators<Handlers> = {
18
19
  type Dispatch<Handlers> = {
19
20
  [Name in keyof Handlers]: (...args: Arguments<Handlers[Name]>) => void;
20
21
  };
21
- export declare function defineActions<Model>(): <Handlers extends Record<string, Handler<Model>>>(handlers: Handlers) => {
22
+ export declare function defineActions<Model, R = never>(): <Handlers extends Record<string, Handler<Model, R>>>(handlers: Handlers) => {
22
23
  message: Creators<Handlers>;
23
24
  bind(this: void, send: Send<HandlerMessage<Handlers>>): Dispatch<Handlers>;
24
- update(this: void, model: Model, action: HandlerMessage<Handlers>): ReturnType<Handlers[keyof Handlers]>;
25
+ update(this: void, model: Snapshot<Model>, action: HandlerMessage<Handlers>): ReturnType<Handlers[keyof Handlers]>;
25
26
  };
26
27
  export {};
package/dist/actions.js CHANGED
@@ -23,6 +23,7 @@ export function defineActions() {
23
23
  if (!Object.hasOwn(handlers, action.type))
24
24
  throw new Error(`Unknown action: ${String(action.type)}`);
25
25
  const handler = handlers[action.type];
26
+ // oxlint-disable-next-line typescript/no-unsafe-return -- The indexed handler and ReturnType refer to the same validated generic member.
26
27
  return handler(model, ...action.args);
27
28
  },
28
29
  };
@@ -0,0 +1,11 @@
1
+ import { type View } from './dom.js';
2
+ import { type ReportError } from './errors.js';
3
+ import { type Snapshot } from './snapshot.js';
4
+ export declare function errorBoundary<Model, Message>(content: View<Model, Message>, options: {
5
+ readonly fallback: View<{
6
+ readonly model: NoInfer<Model>;
7
+ readonly error: unknown;
8
+ }, NoInfer<Message>>;
9
+ readonly reset?: (model: Snapshot<NoInfer<Model>>) => unknown;
10
+ readonly onError?: ReportError;
11
+ }): View<Model, Message>;
@@ -0,0 +1,66 @@
1
+ import { child, compiled, viewRegion } from './dom.js';
2
+ import { reportError, reportSafely } from './errors.js';
3
+ import { protectSnapshot } from './snapshot.js';
4
+ export function errorBoundary(content, options) {
5
+ return compiled((scope, parent, before) => {
6
+ let failed = false;
7
+ let error;
8
+ let generation = 0;
9
+ let reset = options.reset?.(scope.value);
10
+ const fallback = compiled((scope, parent, before) => {
11
+ child(scope, parent, before, options.fallback, () => [scope.value], () => protectSnapshot({ model: scope.value, error }), scope.send);
12
+ });
13
+ const region = { manual: true, report: scope.report };
14
+ const render = viewRegion(scope, parent, before, region);
15
+ function showFallback() {
16
+ if (scope.disposed || !failed)
17
+ return;
18
+ region.report = scope.report;
19
+ try {
20
+ render(fallback);
21
+ }
22
+ catch (error) {
23
+ reportSafely(scope.report, error);
24
+ }
25
+ }
26
+ function fail(cause, attempt) {
27
+ if (scope.disposed || attempt !== generation) {
28
+ reportSafely(options.onError ?? reportError, cause);
29
+ return;
30
+ }
31
+ failed = true;
32
+ error = cause;
33
+ const token = ++generation;
34
+ render(undefined);
35
+ reportSafely(options.onError ?? reportError, cause);
36
+ queueMicrotask(() => {
37
+ if (token === generation)
38
+ showFallback();
39
+ });
40
+ }
41
+ const update = () => {
42
+ const next = options.reset?.(scope.value);
43
+ if (!Object.is(reset, next)) {
44
+ reset = next;
45
+ generation++;
46
+ render(undefined);
47
+ failed = false;
48
+ error = undefined;
49
+ }
50
+ if (failed)
51
+ showFallback();
52
+ else {
53
+ const attempt = generation;
54
+ region.report = (cause) => fail(cause, attempt);
55
+ try {
56
+ render(content);
57
+ }
58
+ catch (error) {
59
+ fail(error, attempt);
60
+ }
61
+ }
62
+ };
63
+ scope.jobs.push(update);
64
+ update();
65
+ });
66
+ }
@@ -0,0 +1,18 @@
1
+ import type * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
2
+ import type * as Atom from 'effect/unstable/reactivity/Atom';
3
+ import type * as AtomRegistry from 'effect/unstable/reactivity/AtomRegistry';
4
+ import type { QueryCache } from './cache.js';
5
+ import type { Query } from './query.js';
6
+ import type { Snapshot } from './snapshot.js';
7
+ export interface CacheInternals<R> {
8
+ refresh(atom: Atom.Atom<unknown>): void;
9
+ readonly disposed: () => boolean;
10
+ revision<Args, A, E>(definition: Query<Args, A, E, R>, args: Args | Snapshot<Args>): number | undefined;
11
+ retain(atom: Atom.Atom<unknown>): () => void;
12
+ readonly registry: AtomRegistry.AtomRegistry;
13
+ readonly generation: Atom.Writable<number>;
14
+ query<Args, A, E>(definition: Query<Args, A, E, R>, args: Args | Snapshot<Args>): Atom.Atom<AsyncResult.AsyncResult<Snapshot<A>, E>>;
15
+ }
16
+ export declare function registerCache<R>(cache: QueryCache<R>, internals: CacheInternals<R>): void;
17
+ /** Private implementation access; deliberately absent from package exports. */
18
+ export declare function cacheInternals<R>(cache: QueryCache<R>): CacheInternals<R>;
@@ -0,0 +1,11 @@
1
+ const caches = new WeakMap();
2
+ export function registerCache(cache, internals) {
3
+ caches.set(cache, internals);
4
+ }
5
+ /** Private implementation access; deliberately absent from package exports. */
6
+ export function cacheInternals(cache) {
7
+ const internals = caches.get(cache);
8
+ if (!internals)
9
+ throw new TypeError('Use makeQueryCache() to create a cache.');
10
+ return internals;
11
+ }
package/dist/cache.d.ts CHANGED
@@ -1,22 +1,41 @@
1
+ import { type Snapshot } from './snapshot.js';
1
2
  import { Effect } from 'effect';
2
- import * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
3
- import * as Atom from 'effect/unstable/reactivity/Atom';
4
- import * as AtomRegistry from 'effect/unstable/reactivity/AtomRegistry';
5
- import type { Query } from './query.js';
3
+ import { type Query, type QueryGroup } from './query.js';
6
4
  import type { UiRuntime } from './runtime.js';
7
5
  export { loadEffect, type UiLoad } from './load.js';
8
6
  export { shareValue } from './share.js';
9
- export declare function makeQueryCache(): QueryCache<never>;
10
- export declare function makeQueryCache<R>(runtime: UiRuntime<R>): QueryCache<R>;
11
- declare function createQueryCache<R>(runtime?: UiRuntime<R>): {
12
- registry: AtomRegistry.AtomRegistry;
13
- generation: Atom.Writable<number, number>;
14
- resource<A, E = unknown>(key: string, load: () => Effect.Effect<A, E>): Atom.Atom<AsyncResult.AsyncResult<A, E>>;
15
- query: <Args, A, E>(definition: Query<Args, A, E, R>, args: Args) => Atom.Atom<AsyncResult.AsyncResult<A, E>>;
16
- prefetch<Args, A, E>(definition: Query<Args, A, E, R>, args: Args): Effect.Effect<A, E>;
17
- invalidateQuery<Args, A, E>(definition: Query<Args, A, E, R>, ...selected: [] | [Args]): void;
18
- invalidate(prefix: string): void;
7
+ export interface QueryCacheOptions {
8
+ readonly retention?: number;
9
+ readonly unused?: 'retain' | 'cancel' | undefined;
10
+ }
11
+ export declare function makeQueryCache(options?: QueryCacheOptions): QueryCache<never>;
12
+ export declare function makeQueryCache<R>(runtime: UiRuntime<R>, options?: QueryCacheOptions): QueryCache<R>;
13
+ /** A cache owns one registry and the query resources published through it. */
14
+ export interface QueryCache<R = never> {
15
+ batch(work: () => void): void;
16
+ getQueryData<Args, A, E>(definition: Query<Args, A, E, R>, args: NoInfer<Args> | Snapshot<NoInfer<Args>>): Snapshot<A> | undefined;
17
+ invalidateWhere<Args, A, E>(definition: Query<Args, A, E, R>, predicate: (args: Snapshot<Args>) => boolean): void;
18
+ invalidateGroup(group: QueryGroup): void;
19
+ /** Cancel requests while retaining the last success. Explicit refresh restarts them. */
20
+ cancelQuery<Args, A, E>(definition: Query<Args, A, E, R>, ...selected: [] | [NoInfer<Args> | Snapshot<NoInfer<Args>>]): void;
21
+ /** Clear cached data and cancel requests; a subsequent selection or refresh reloads. */
22
+ removeQuery<Args, A, E>(definition: Query<Args, A, E, R>, ...selected: [] | [NoInfer<Args> | Snapshot<NoInfer<Args>>]): void;
23
+ prefetch<Args, A, E>(definition: Query<Args, A, E, R>, args: NoInfer<Args> | Snapshot<NoInfer<Args>>, options?: {
24
+ readonly refresh?: boolean;
25
+ }): Effect.Effect<Snapshot<A>, E>;
26
+ /** Publish a protected success, including undefined, and supersede any pending load for this key. */
27
+ setQueryData<Args, A, E>(definition: Query<Args, A, E, R>, args: NoInfer<Args> | Snapshot<NoInfer<Args>>, value: NoInfer<A> | Snapshot<NoInfer<A>>): Snapshot<A>;
28
+ /**
29
+ * Update an existing success, including one retained during refresh or failure, and supersede its load.
30
+ * No success or an undefined updater return skips the write. Use setQueryData to seed or store undefined.
31
+ * Updaters run synchronously on readonly data; a throw leaves the cached value unchanged.
32
+ */
33
+ updateQueryData<Args, A, E>(definition: Query<Args, A, E, R>, args: NoInfer<Args> | Snapshot<NoInfer<Args>>, update: (previous: Snapshot<A>) => NoInfer<A> | Snapshot<NoInfer<A>> | undefined): Snapshot<A> | undefined;
34
+ invalidateQuery<Args, A, E>(definition: Query<Args, A, E, R>, ...selected: [] | [NoInfer<Args> | Snapshot<NoInfer<Args>>]): void;
35
+ /** Observe account resets without exposing registry mutation. */
36
+ onReset(listener: () => void): () => void;
19
37
  resetResources(): void;
38
+ /** Interrupt every request and wait for its finalizers, including previously canceled requests. */
39
+ close(): Promise<void>;
20
40
  dispose(): void;
21
- };
22
- export type QueryCache<R = never> = ReturnType<typeof createQueryCache<R>>;
41
+ }