@confect/react 10.0.0-next.20 → 10.0.0-next.22

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 CHANGED
@@ -1,5 +1,85 @@
1
1
  # @confect/react
2
2
 
3
+ ## 10.0.0-next.22
4
+
5
+ ### Minor Changes
6
+
7
+ - 6cc5834: Add experimental stream querying with reactive pagination, configurable middleware policies, and broader tracing.
8
+
9
+ ### Stream queries and pagination
10
+
11
+ Create composable Effect streams with `reader.table(...).stream(index, range?, order?)` and `QueryStream` from `@confect/server`. Merge, filter, map, join, deduplicate, narrow, and reverse queries without losing cursor pagination. Order keys and directions are checked by the type system. Joins support left-join placeholders through `onEmpty`, and effectful filters and maps support ordered concurrency. Reversing a distinct stream preserves its chosen representatives.
12
+
13
+ `QueryStream.paginate` resumes from indexed cursor bounds and supports pinned page ranges, automatic split recommendations, and `maximumRowsRead`/`maximumBytesRead` budgets that count underlying query-stream reads, including filtered documents. Byte counts are estimates. If a budget prevents safe progress or splitting, pagination fails with `ReadBudgetExceededError`; increase the budget or reduce the query's read requirements.
14
+
15
+ Use React's new `useStreamPaginatedQuery` for these queries:
16
+
17
+ ```ts
18
+ import { useStreamPaginatedQuery } from "@confect/react";
19
+
20
+ const { results, status, loadMore } = useStreamPaginatedQuery(
21
+ refs.public.notes.feed,
22
+ {},
23
+ {
24
+ initialNumItems: 10,
25
+ maximumRowsRead: 1000,
26
+ maximumBytesRead: 512 * 1024,
27
+ },
28
+ );
29
+ ```
30
+
31
+ The hook pins loaded pages to fixed ranges, splits oversized or budget-limited pages, and restarts pagination on invalid cursors. Foldkit's `PaginatedQuery` also supports stream queries and preserves page ranges when navigating back and forward, avoiding skipped or repeated documents as data changes.
32
+
33
+ Stream cursors expose their order-key values. Do not paginate publicly over sensitive indexed fields unless they are pinned with `eq`. All `QueryStream` APIs are experimental.
34
+
35
+ ### Middleware options
36
+
37
+ Declare a lazy `options` schema on `MiddlewareSpec.MiddlewareSpec`, then pass typed values with `.middleware(Policy, options)` on functions or groups. Options are validated without coercion during codegen and server registration; keep schemas and values client-safe because generated refs carry them.
38
+
39
+ The same policy can be attached repeatedly with non-equivalent options. Every attachment runs, with group policies before function policies. Equivalent options and duplicate policies without options are rejected. Register implementations against the same spec used for attachments.
40
+
41
+ ### Breaking changes
42
+
43
+ Middleware callbacks passed to `MiddlewareImpl.make` or `MiddlewareImpl.makeByFunctionType` receive invocation metadata under `invocation`. To migrate, nest destructuring of `name`, `functionType`, `functionVisibility`, and decoded `args`:
44
+
45
+ **Before:**
46
+
47
+ ```ts
48
+ (effect, { name, args }) => effect;
49
+ ```
50
+
51
+ **After:**
52
+
53
+ ```ts
54
+ (effect, { invocation: { name, args } }) => effect;
55
+ ```
56
+
57
+ Middleware with an options schema also receives `options` alongside `invocation`; middleware without one keeps its single-argument attachment API and receives only `{ invocation }`.
58
+
59
+ ### Fixes and tracing
60
+ - Preserve `ConvexError.data` when a handler throws a `ConvexError` inside an Effect instead of returning it as a typed failure.
61
+ - Add named tracing spans for JavaScript client calls, server function execution, database writes and pagination, `QueryStream.unique`/`QueryStream.paginate`, and `confect codegen`/`confect dev` code-generation passes.
62
+
63
+ ### Patch Changes
64
+
65
+ - 9f4e2c0: Require `effect@^4.0.0-rc.113` across `@confect/*` and raise `@confect/server`'s optional `@effect/platform-node` peer to the same range. Upgrade Effect alongside Confect; existing Confect call sites are unchanged.
66
+
67
+ Effect's own APIs include breaking renames: use `Config.String` instead of `Config.string`, and `LanguageModel.LanguageModel` instead of `LanguageModel.Service` when annotating the result of `AiGatewayLanguageModel.make`. See the [Effect RC 113 release notes](https://github.com/Effect-TS/effect/releases/tag/effect%404.0.0-rc.113) for the complete migration guidance.
68
+
69
+ - 90c80e9: Require `effect@^4.0.0-rc.115` across `@confect/*` and `@effect/platform-node@^4.0.0-rc.115` when using `@confect/server`'s optional Node integration. Upgrade these dependencies alongside Confect; existing Confect call sites are unchanged.
70
+ - f721d2c: Remove spaces around em dashes and separator slashes in API documentation and `confect codegen` diagnostics.
71
+
72
+ ## 10.0.0-next.21
73
+
74
+ ### Major Changes
75
+
76
+ - a6425c5: Raise the minimum supported Node.js version to 24.
77
+
78
+ ### Breaking Changes
79
+ - `engines.node` is now `>=24` on every `@confect/*` package, raised from `>=22`.
80
+
81
+ Node 22 has entered maintenance, so Confect now targets Node 24, the active LTS line. To migrate, move the Node version your project builds and runs on to 24 or later—on Node 22, installing `@confect/*` now fails your package manager's engine check. No API changes accompany the raise: code already running on Node 24 needs no edits.
82
+
3
83
  ## 10.0.0-next.20
4
84
 
5
85
  ## 10.0.0-next.19
@@ -23,14 +103,14 @@
23
103
  Breaking changes for users:
24
104
 
25
105
  - **Schemas** follow Effect v4's Schema API: `Schema.Union([a, b])` (array form), `Schema.Literals([...])` for literal unions, `Schema.optionalKey` in place of `optionalWith({ exact: true })`, and checks like `Schema.String.check(Schema.isMaxLength(...))` in place of piped filters.
26
- - **Option-returning functions** must use a codec with a serializable encoded form, such as `Schema.OptionFromNullOr(...)` — v4's `Schema.Option` encodes to an `Option` instance, which is not a Convex value.
27
- - **Table schemas** may now be transformations (`Schema.decodeTo` chains, `Schema.encodeKeys`), branded structs, suspended schemas, or unions of these — Convex's system fields are carried through the whole encoding chain. Schemas that do not resolve to an object shape at every step (such as `Schema.Class`) are rejected with a descriptive error when the table is defined.
106
+ - **Option-returning functions** must use a codec with a serializable encoded form, such as `Schema.OptionFromNullOr(...)`—v4's `Schema.Option` encodes to an `Option` instance, which is not a Convex value.
107
+ - **Table schemas** may now be transformations (`Schema.decodeTo` chains, `Schema.encodeKeys`), branded structs, suspended schemas, or unions of these—Convex's system fields are carried through the whole encoding chain. Schemas that do not resolve to an object shape at every step (such as `Schema.Class`) are rejected with a descriptive error when the table is defined.
28
108
  - **Clients**: decode failures surface as `SchemaError` rather than `ParseError` in `@confect/js` and `@confect/react`, and `@confect/react`'s `useMutation`/`useAction` handles with an `error` schema now resolve to `Result` (v4's replacement for `Either`).
29
- - **HTTP** is now mounted through the renamed `HttpRouter` module (formerly `HttpApi`). `HttpRouter.make(routes)` takes a single route-registering `Layer` composed from Effect's own `effect/unstable/http` and `effect/unstable/httpapi` modules — `HttpApiBuilder.layer(api)` (with group handler layers supplied via `Layer.provide`; a missing group is a compile-time error), `HttpApiScalar.layer` for docs, `HttpRouter.add` for plain routes, and `HttpRouter.middleware(fn, { global: true })` for middleware, merged with `Layer.mergeAll`. The per-path-prefix record and its `api`/`apiLive`/`middleware`/`scalar` options are gone; Confect registers one catch-all Convex HTTP action at `/`, and plain Convex routes added to the returned router still take precedence. Handlers, middleware, and route-layer construction all run with Confect's Convex-aware `ConfigProvider` in context.
109
+ - **HTTP** is now mounted through the renamed `HttpRouter` module (formerly `HttpApi`). `HttpRouter.make(routes)` takes a single route-registering `Layer` composed from Effect's own `effect/unstable/http` and `effect/unstable/httpapi` modules—`HttpApiBuilder.layer(api)` (with group handler layers supplied via `Layer.provide`; a missing group is a compile-time error), `HttpApiScalar.layer` for docs, `HttpRouter.add` for plain routes, and `HttpRouter.middleware(fn, { global: true })` for middleware, merged with `Layer.mergeAll`. The per-path-prefix record and its `api`/`apiLive`/`middleware`/`scalar` options are gone; Confect registers one catch-all Convex HTTP action at `/`, and plain Convex routes added to the returned router still take precedence. Handlers, middleware, and route-layer construction all run with Confect's Convex-aware `ConfigProvider` in context.
30
110
  - **Node actions** use `effect/unstable/process` (`ChildProcessSpawner`) and `@effect/platform-node`'s `NodeServices` in place of `@effect/platform` `Command`/`NodeContext`.
31
111
  - **Configuration**: Confect's Convex-aware `ConfigProvider` treats empty-string environment variables as missing values (matching Effect v4's built-in providers), so `Config.withDefault` and `Config.option` recover from them.
32
112
  - **CLI**: a malformed `convex.json` now fails codegen with a descriptive error instead of being silently ignored.
33
- - Confect queries no longer stub the global `Date.now`. Queries run with a `Clock` whose unsafe accessors return constants, so Effect-internal reads (log timestamps, spans) never evict a query from Convex's cache; explicit time reads — `Clock.currentTimeMillis`/`currentTimeNanos` or a raw `Date.now()` call — opt the query out and evict as they honestly should.
113
+ - Confect queries no longer stub the global `Date.now`. Queries run with a `Clock` whose unsafe accessors return constants, so Effect-internal reads (log timestamps, spans) never evict a query from Convex's cache; explicit time reads—`Clock.currentTimeMillis`/`currentTimeNanos` or a raw `Date.now()` call—opt the query out and evict as they honestly should.
34
114
 
35
115
  ### Patch Changes
36
116
 
@@ -45,9 +125,9 @@
45
125
  - Raise the required `effect` peer version to `^4.0.0-beta.102` (from `^4.0.0-beta.101`), and `@confect/server`'s optional `@effect/platform-node` peer version likewise.
46
126
  - Raise the required `effect` peer version to `^4.0.0-beta.105` (from `^4.0.0-beta.102`), and `@confect/server`'s optional `@effect/platform-node` peer version likewise.
47
127
 
48
- `beta.103` separates wall-clock time from monotonic elapsed time: `Clock.Clock` now also requires `monotonicTimeNanos` and `monotonicTimeNanosUnsafe`, so a custom `Clock` provided to a Confect function has to supply both. Effects that measure elapsed time — `Effect.timed`, duration metrics, `Sink.withDuration` — read the monotonic accessors instead of the wall clock, and continue to report a zero duration inside queries and mutations, where Confect pins the unsafe accessors to constants to keep Convex's query cache from evicting on every logged span.
128
+ `beta.103` separates wall-clock time from monotonic elapsed time: `Clock.Clock` now also requires `monotonicTimeNanos` and `monotonicTimeNanosUnsafe`, so a custom `Clock` provided to a Confect function has to supply both. Effects that measure elapsed time—`Effect.timed`, duration metrics, `Sink.withDuration`—read the monotonic accessors instead of the wall clock, and continue to report a zero duration inside queries and mutations, where Confect pins the unsafe accessors to constants to keep Convex's query cache from evicting on every logged span.
49
129
 
50
- `beta.103` also moves synchronous Effect runs off `setImmediate`/`setTimeout` and onto the microtask queue, which Convex's query and mutation isolate permits. Confect no longer suppresses cooperative fiber yielding for the synchronous work it performs while your modules load — registration and schema-to-validator compilation — and relies on that scheduling instead. Neither the "Can't use `setTimeout` in queries and mutations" crash nor any other consumer-visible behavior changes, but this is the area to look at if module loading starts misbehaving.
130
+ `beta.103` also moves synchronous Effect runs off `setImmediate`/`setTimeout` and onto the microtask queue, which Convex's query and mutation isolate permits. Confect no longer suppresses cooperative fiber yielding for the synchronous work it performs while your modules load—registration and schema-to-validator compilation—and relies on that scheduling instead. Neither the "Can't use `setTimeout` in queries and mutations" crash nor any other consumer-visible behavior changes, but this is the area to look at if module loading starts misbehaving.
51
131
 
52
132
  `beta.104` renames Effect's schema error constructors to match their `Data` counterparts, which affects any error schema you declare for a Confect function:
53
133
 
@@ -69,7 +149,7 @@
69
149
  ) {}
70
150
  ```
71
151
 
72
- `Schema.ErrorClass` is likewise now `Schema.Error`; the schema for JavaScript `Error` instances that previously went by `Schema.Error` is now `Schema.ErrorInstance`, and `Schema.ErrorReviver` is now `Schema.ErrorInstanceReviver`. Confect's own error types — `DocumentDecodeError`, `BlobNotFoundError`, and the rest — are unchanged in name, shape, and message.
152
+ `Schema.ErrorClass` is likewise now `Schema.Error`; the schema for JavaScript `Error` instances that previously went by `Schema.Error` is now `Schema.ErrorInstance`, and `Schema.ErrorReviver` is now `Schema.ErrorInstanceReviver`. Confect's own error types—`DocumentDecodeError`, `BlobNotFoundError`, and the rest—are unchanged in name, shape, and message.
73
153
 
74
154
  `beta.105` restructures how schema validation failures are reported, but not on the path Confect puts you on: decode and encode failures still surface as `Schema.SchemaError` with a formatted `message`, so error text from `@confect/js`, `@confect/react`, and document decoding is unchanged.
75
155
 
@@ -97,13 +177,13 @@
97
177
 
98
178
  - Raise the required `effect` peer version to `^4.0.0-beta.107` (from `^4.0.0-beta.106`), and `@confect/server`'s optional `@effect/platform-node` peer version likewise.
99
179
 
100
- `beta.107` is a patch-only Effect release, so no Confect API changes and no call-site edits are needed — upgrade `effect` alongside `@confect/*` and everything you have written keeps compiling. Your table, argument, and returns schemas still produce the same Convex validators.
180
+ `beta.107` is a patch-only Effect release, so no Confect API changes and no call-site edits are needed—upgrade `effect` alongside `@confect/*` and everything you have written keeps compiling. Your table, argument, and returns schemas still produce the same Convex validators.
101
181
 
102
- Two Effect fixes are worth knowing about if they touch your code. HTTP actions written with `HttpRouter` now collect uploaded file contents far faster on large multipart bodies, and a file part whose stream is cut short — because a parser limit was exceeded or the request body ended early — now fails instead of hanging. Separately, `Duration` values that are equal now hash equally, so a `Duration` used as a `HashMap` key or a `HashSet` member is found regardless of which constructor built it.
182
+ Two Effect fixes are worth knowing about if they touch your code. HTTP actions written with `HttpRouter` now collect uploaded file contents far faster on large multipart bodies, and a file part whose stream is cut short—because a parser limit was exceeded or the request body ended early—now fails instead of hanging. Separately, `Duration` values that are equal now hash equally, so a `Duration` used as a `HashMap` key or a `HashSet` member is found regardless of which constructor built it.
103
183
 
104
184
  - Raise the required `effect` peer version to `^4.0.0-beta.98` (from `^4.0.0-beta.97`).
105
185
 
106
- `effect`'s `SchemaError` is now exposed as its own public module (`effect/SchemaError`), which changes the import path TypeScript picks when Confect emits `.d.ts` declarations that reference `Schema.SchemaError` (for example in generated `services.d.ts`). Existing `Schema.SchemaError` / `Schema.isSchemaError` usage is unaffected — this is purely a declaration-emit detail that consumers relying on generated types may notice.
186
+ `effect`'s `SchemaError` is now exposed as its own public module (`effect/SchemaError`), which changes the import path TypeScript picks when Confect emits `.d.ts` declarations that reference `Schema.SchemaError` (for example in generated `services.d.ts`). Existing `Schema.SchemaError`/`Schema.isSchemaError` usage is unaffected—this is purely a declaration-emit detail that consumers relying on generated types may notice.
107
187
 
108
188
  - Raise the required `effect` peer version to `^4.0.0-beta.99` (from `^4.0.0-beta.98`).
109
189
 
@@ -127,7 +207,7 @@
127
207
 
128
208
  Also worth knowing if you serve an `HttpApi`: a query parameter declared as an array now decodes correctly when a request supplies exactly one value for it.
129
209
 
130
- One internal change rides along. Queries and mutations that run long enough to trigger a cooperative fiber yield now take that yield from Effect's own scheduler, which `rc.108` made usable inside Convex's isolate for the first time. The underlying microtask primitive is identical, so behavior should not change — but it is the thing to look at if a long-running query or mutation regresses on this release.
210
+ One internal change rides along. Queries and mutations that run long enough to trigger a cooperative fiber yield now take that yield from Effect's own scheduler, which `rc.108` made usable inside Convex's isolate for the first time. The underlying microtask primitive is identical, so behavior should not change—but it is the thing to look at if a long-running query or mutation regresses on this release.
131
211
 
132
212
  - Raise the required `effect` peer version to `^4.0.0-rc.109` (from `^4.0.0-rc.108`), and `@confect/server`'s optional `@effect/platform-node` peer version likewise.
133
213
 
@@ -138,10 +218,10 @@
138
218
  No Confect API changed, and no call-site edits are needed. `rc.110` is a patch release of Effect with nothing removed or renamed, so upgrading is a matter of installing it alongside `@confect/*`.
139
219
 
140
220
  - 3f0255c: Build and test against `convex` 1.44.0. The published `convex` peer ranges are unchanged, so no consumer action is required.
141
- - Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.2.2–9.2.4 — see those versions' changelog entries.
142
- - Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.2.5 — see that version's changelog entries.
143
- - Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.3.0 — see that version's changelog entries.
144
- - Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.4.0 — see that version's changelog entries.
221
+ - Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.2.2–9.2.4—see those versions' changelog entries.
222
+ - Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.2.5—see that version's changelog entries.
223
+ - Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.3.0—see that version's changelog entries.
224
+ - Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.4.0—see that version's changelog entries.
145
225
 
146
226
  The `@effect/platform` and `@effect/cli` peer and dependency floors that 9.4.0 raises do not apply here: this line runs on Effect v4, where those packages are not dependencies at all.
147
227
 
@@ -177,7 +257,7 @@
177
257
 
178
258
  Also worth knowing if you serve an `HttpApi`: a query parameter declared as an array now decodes correctly when a request supplies exactly one value for it.
179
259
 
180
- One internal change rides along. Queries and mutations that run long enough to trigger a cooperative fiber yield now take that yield from Effect's own scheduler, which `rc.108` made usable inside Convex's isolate for the first time. The underlying microtask primitive is identical, so behavior should not change — but it is the thing to look at if a long-running query or mutation regresses on this release.
260
+ One internal change rides along. Queries and mutations that run long enough to trigger a cooperative fiber yield now take that yield from Effect's own scheduler, which `rc.108` made usable inside Convex's isolate for the first time. The underlying microtask primitive is identical, so behavior should not change—but it is the thing to look at if a long-running query or mutation regresses on this release.
181
261
 
182
262
  - a4054ab: The published type declarations are now emitted by TypeScript 7 rather than TypeScript 6. No API changed, but the declaration text differs in places, so an inferred type printed in your editor or in a type error may read slightly differently than before.
183
263
 
@@ -187,9 +267,9 @@
187
267
 
188
268
  - 5a73763: Raise the required `effect` peer version to `^4.0.0-beta.107` (from `^4.0.0-beta.106`), and `@confect/server`'s optional `@effect/platform-node` peer version likewise.
189
269
 
190
- `beta.107` is a patch-only Effect release, so no Confect API changes and no call-site edits are needed — upgrade `effect` alongside `@confect/*` and everything you have written keeps compiling. Your table, argument, and returns schemas still produce the same Convex validators.
270
+ `beta.107` is a patch-only Effect release, so no Confect API changes and no call-site edits are needed—upgrade `effect` alongside `@confect/*` and everything you have written keeps compiling. Your table, argument, and returns schemas still produce the same Convex validators.
191
271
 
192
- Two Effect fixes are worth knowing about if they touch your code. HTTP actions written with `HttpRouter` now collect uploaded file contents far faster on large multipart bodies, and a file part whose stream is cut short — because a parser limit was exceeded or the request body ended early — now fails instead of hanging. Separately, `Duration` values that are equal now hash equally, so a `Duration` used as a `HashMap` key or a `HashSet` member is found regardless of which constructor built it.
272
+ Two Effect fixes are worth knowing about if they touch your code. HTTP actions written with `HttpRouter` now collect uploaded file contents far faster on large multipart bodies, and a file part whose stream is cut short—because a parser limit was exceeded or the request body ended early—now fails instead of hanging. Separately, `Duration` values that are equal now hash equally, so a `Duration` used as a `HashMap` key or a `HashSet` member is found regardless of which constructor built it.
193
273
 
194
274
  ## 10.0.0-next.12
195
275
 
@@ -223,9 +303,9 @@
223
303
 
224
304
  - f782cdd: Raise the required `effect` peer version to `^4.0.0-beta.105` (from `^4.0.0-beta.102`), and `@confect/server`'s optional `@effect/platform-node` peer version likewise.
225
305
 
226
- `beta.103` separates wall-clock time from monotonic elapsed time: `Clock.Clock` now also requires `monotonicTimeNanos` and `monotonicTimeNanosUnsafe`, so a custom `Clock` provided to a Confect function has to supply both. Effects that measure elapsed time — `Effect.timed`, duration metrics, `Sink.withDuration` — read the monotonic accessors instead of the wall clock, and continue to report a zero duration inside queries and mutations, where Confect pins the unsafe accessors to constants to keep Convex's query cache from evicting on every logged span.
306
+ `beta.103` separates wall-clock time from monotonic elapsed time: `Clock.Clock` now also requires `monotonicTimeNanos` and `monotonicTimeNanosUnsafe`, so a custom `Clock` provided to a Confect function has to supply both. Effects that measure elapsed time—`Effect.timed`, duration metrics, `Sink.withDuration`—read the monotonic accessors instead of the wall clock, and continue to report a zero duration inside queries and mutations, where Confect pins the unsafe accessors to constants to keep Convex's query cache from evicting on every logged span.
227
307
 
228
- `beta.103` also moves synchronous Effect runs off `setImmediate`/`setTimeout` and onto the microtask queue, which Convex's query and mutation isolate permits. Confect no longer suppresses cooperative fiber yielding for the synchronous work it performs while your modules load — registration and schema-to-validator compilation — and relies on that scheduling instead. Neither the "Can't use `setTimeout` in queries and mutations" crash nor any other consumer-visible behavior changes, but this is the area to look at if module loading starts misbehaving.
308
+ `beta.103` also moves synchronous Effect runs off `setImmediate`/`setTimeout` and onto the microtask queue, which Convex's query and mutation isolate permits. Confect no longer suppresses cooperative fiber yielding for the synchronous work it performs while your modules load—registration and schema-to-validator compilation—and relies on that scheduling instead. Neither the "Can't use `setTimeout` in queries and mutations" crash nor any other consumer-visible behavior changes, but this is the area to look at if module loading starts misbehaving.
229
309
 
230
310
  `beta.104` renames Effect's schema error constructors to match their `Data` counterparts, which affects any error schema you declare for a Confect function:
231
311
 
@@ -247,11 +327,11 @@
247
327
  ) {}
248
328
  ```
249
329
 
250
- `Schema.ErrorClass` is likewise now `Schema.Error`; the schema for JavaScript `Error` instances that previously went by `Schema.Error` is now `Schema.ErrorInstance`, and `Schema.ErrorReviver` is now `Schema.ErrorInstanceReviver`. Confect's own error types — `DocumentDecodeError`, `BlobNotFoundError`, and the rest — are unchanged in name, shape, and message.
330
+ `Schema.ErrorClass` is likewise now `Schema.Error`; the schema for JavaScript `Error` instances that previously went by `Schema.Error` is now `Schema.ErrorInstance`, and `Schema.ErrorReviver` is now `Schema.ErrorInstanceReviver`. Confect's own error types—`DocumentDecodeError`, `BlobNotFoundError`, and the rest—are unchanged in name, shape, and message.
251
331
 
252
332
  `beta.105` restructures how schema validation failures are reported, but not on the path Confect puts you on: decode and encode failures still surface as `Schema.SchemaError` with a formatted `message`, so error text from `@confect/js`, `@confect/react`, and document decoding is unchanged.
253
333
 
254
- - Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.4.0 — see that version's changelog entries.
334
+ - Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.4.0—see that version's changelog entries.
255
335
 
256
336
  The `@effect/platform` and `@effect/cli` peer and dependency floors that 9.4.0 raises do not apply here: this line runs on Effect v4, where those packages are not dependencies at all.
257
337
 
@@ -259,14 +339,14 @@
259
339
 
260
340
  ### Patch Changes
261
341
 
262
- - Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.3.0 — see that version's changelog entries.
342
+ - Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.3.0—see that version's changelog entries.
263
343
 
264
344
  ## 10.0.0-next.9
265
345
 
266
346
  ### Patch Changes
267
347
 
268
348
  - 0dcc0fb: Raise the required `effect` peer version to `^4.0.0-beta.102` (from `^4.0.0-beta.101`), and `@confect/server`'s optional `@effect/platform-node` peer version likewise.
269
- - 25e8d19: Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.2.5 — see that version's changelog entries.
349
+ - 25e8d19: Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.2.5—see that version's changelog entries.
270
350
 
271
351
  ## 10.0.0-next.8
272
352
 
@@ -300,7 +380,7 @@
300
380
 
301
381
  This is a peer-range-only change with no consumer-visible API consequences. The `beta.99` release only touches `Graph`, CLI (`Command`/`CliConfig`/wizard mode), `Tool` cloning, Redis script eval, and multipart parser internals that Confect doesn't use.
302
382
 
303
- - 2aa7541: Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.2.2–9.2.4 — see those versions' changelog entries.
383
+ - 2aa7541: Sync with `main`: this prerelease line now includes all changes released in `@confect/*` 9.2.2–9.2.4—see those versions' changelog entries.
304
384
 
305
385
  ## 10.0.0-next.1
306
386
 
@@ -308,7 +388,7 @@
308
388
 
309
389
  - 4d98ea8: Raise the required `effect` peer version to `^4.0.0-beta.98` (from `^4.0.0-beta.97`).
310
390
 
311
- `effect`'s `SchemaError` is now exposed as its own public module (`effect/SchemaError`), which changes the import path TypeScript picks when Confect emits `.d.ts` declarations that reference `Schema.SchemaError` (for example in generated `services.d.ts`). Existing `Schema.SchemaError` / `Schema.isSchemaError` usage is unaffected — this is purely a declaration-emit detail that consumers relying on generated types may notice.
391
+ `effect`'s `SchemaError` is now exposed as its own public module (`effect/SchemaError`), which changes the import path TypeScript picks when Confect emits `.d.ts` declarations that reference `Schema.SchemaError` (for example in generated `services.d.ts`). Existing `Schema.SchemaError`/`Schema.isSchemaError` usage is unaffected—this is purely a declaration-emit detail that consumers relying on generated types may notice.
312
392
 
313
393
  - Updated dependencies [4d98ea8]
314
394
  - @confect/core@10.0.0-next.1
@@ -321,20 +401,22 @@
321
401
 
322
402
  Breaking changes for users:
323
403
  - **Schemas** follow Effect v4's Schema API: `Schema.Union([a, b])` (array form), `Schema.Literals([...])` for literal unions, `Schema.optionalKey` in place of `optionalWith({ exact: true })`, `Schema.TaggedErrorClass` in place of `Schema.TaggedError`, and checks like `Schema.String.check(Schema.isMaxLength(...))` in place of piped filters.
324
- - **Option-returning functions** must use a codec with a serializable encoded form, such as `Schema.OptionFromNullOr(...)` — v4's `Schema.Option` encodes to an `Option` instance, which is not a Convex value.
325
- - **Table schemas** may now be transformations (`Schema.decodeTo` chains, `Schema.encodeKeys`), branded structs, suspended schemas, or unions of these — Convex's system fields are carried through the whole encoding chain. Schemas that do not resolve to an object shape at every step (such as `Schema.Class`) are rejected with a descriptive error when the table is defined.
404
+ - **Option-returning functions** must use a codec with a serializable encoded form, such as `Schema.OptionFromNullOr(...)`—v4's `Schema.Option` encodes to an `Option` instance, which is not a Convex value.
405
+ - **Table schemas** may now be transformations (`Schema.decodeTo` chains, `Schema.encodeKeys`), branded structs, suspended schemas, or unions of these—Convex's system fields are carried through the whole encoding chain. Schemas that do not resolve to an object shape at every step (such as `Schema.Class`) are rejected with a descriptive error when the table is defined.
326
406
  - **Clients**: decode failures surface as `SchemaError` rather than `ParseError` in `@confect/js` and `@confect/react`, and `@confect/react`'s `useMutation`/`useAction` handles with an `error` schema now resolve to `Result` (v4's replacement for `Either`).
327
- - **HTTP** is now mounted through the renamed `HttpRouter` module (formerly `HttpApi`). `HttpRouter.make(routes)` takes a single route-registering `Layer` composed from Effect's own `effect/unstable/http` and `effect/unstable/httpapi` modules — `HttpApiBuilder.layer(api)` (with group handler layers supplied via `Layer.provide`; a missing group is a compile-time error), `HttpApiScalar.layer` for docs, `HttpRouter.add` for plain routes, and `HttpRouter.middleware(fn, { global: true })` for middleware, merged with `Layer.mergeAll`. The per-path-prefix record and its `api`/`apiLive`/`middleware`/`scalar` options are gone; Confect registers one catch-all Convex HTTP action at `/`, and plain Convex routes added to the returned router still take precedence. Handlers, middleware, and route-layer construction all run with Confect's Convex-aware `ConfigProvider` in context.
407
+ - **HTTP** is now mounted through the renamed `HttpRouter` module (formerly `HttpApi`). `HttpRouter.make(routes)` takes a single route-registering `Layer` composed from Effect's own `effect/unstable/http` and `effect/unstable/httpapi` modules—`HttpApiBuilder.layer(api)` (with group handler layers supplied via `Layer.provide`; a missing group is a compile-time error), `HttpApiScalar.layer` for docs, `HttpRouter.add` for plain routes, and `HttpRouter.middleware(fn, { global: true })` for middleware, merged with `Layer.mergeAll`. The per-path-prefix record and its `api`/`apiLive`/`middleware`/`scalar` options are gone; Confect registers one catch-all Convex HTTP action at `/`, and plain Convex routes added to the returned router still take precedence. Handlers, middleware, and route-layer construction all run with Confect's Convex-aware `ConfigProvider` in context.
328
408
  - **Node actions** use `effect/unstable/process` (`ChildProcessSpawner`) and `@effect/platform-node`'s `NodeServices` in place of `@effect/platform` `Command`/`NodeContext`.
329
409
  - **Configuration**: Confect's Convex-aware `ConfigProvider` treats empty-string environment variables as missing values (matching Effect v4's built-in providers), so `Config.withDefault` and `Config.option` recover from them.
330
410
  - **CLI**: a malformed `convex.json` now fails codegen with a descriptive error instead of being silently ignored.
331
- - Confect queries no longer stub the global `Date.now`. Queries run with a `Clock` whose unsafe accessors return constants, so Effect-internal reads (log timestamps, spans) never evict a query from Convex's cache; explicit time reads — `Clock.currentTimeMillis`/`currentTimeNanos` or a raw `Date.now()` call — opt the query out and evict as they honestly should.
411
+ - Confect queries no longer stub the global `Date.now`. Queries run with a `Clock` whose unsafe accessors return constants, so Effect-internal reads (log timestamps, spans) never evict a query from Convex's cache; explicit time reads—`Clock.currentTimeMillis`/`currentTimeNanos` or a raw `Date.now()` call—opt the query out and evict as they honestly should.
332
412
 
333
413
  ### Patch Changes
334
414
 
335
415
  - Updated dependencies [70e313e]
336
416
  - @confect/core@10.0.0-next.0
337
417
 
418
+ ## 9.4.2
419
+
338
420
  ## 9.4.1
339
421
 
340
422
  ### Patch Changes
@@ -349,7 +431,7 @@
349
431
 
350
432
  - 16b5ad6: Add first-class paginated queries: declare one with `FunctionSpec.publicPaginatedQuery` (or `internalPaginatedQuery`) and read it with the new `usePaginatedQuery` hook from `@confect/react`.
351
433
 
352
- Pass an `item` schema — the type of one element in a page — in place of `returns`, plus an optional `args` struct for your own arguments. The handler receives `paginationOpts` alongside them and forwards it to `paginate`.
434
+ Pass an `item` schema—the type of one element in a page—in place of `returns`, plus an optional `args` struct for your own arguments. The handler receives `paginationOpts` alongside them and forwards it to `paginate`.
353
435
 
354
436
  ```ts
355
437
  // confect/notes.spec.ts
@@ -474,7 +556,7 @@
474
556
 
475
557
  - 445ea9b: Loosen and align dependency ranges across all packages:
476
558
  - The `convex` peer dependency is now `^1.32.0` in every package (previously pinned exactly to `1.39.1`, or `^1.30.0` in `@confect/react`). The range is validated against convex 1.32.0 through 1.40.0.
477
- - `@confect/server`'s `@effect/platform-node` peer dependency is now optional — it is only needed when using the `@confect/server/node` entrypoint.
559
+ - `@confect/server`'s `@effect/platform-node` peer dependency is now optional—it is only needed when using the `@confect/server/node` entrypoint.
478
560
  - `@confect/cli` now uses caret ranges for its `@effect/platform` and `@effect/platform-node` dependencies so they can deduplicate with the versions resolved for `@confect/server`, and no longer declares an unused direct dependency on `@effect/platform-node-shared`.
479
561
  - `@confect/test` now accepts any `convex-test` release in `>=0.0.50 <0.1.0` instead of exactly 0.0.50.
480
562
 
@@ -493,8 +575,8 @@
493
575
 
494
576
  Your API is now authored as colocated `*.spec.ts`/`*.impl.ts` pairs, one pair per group, and **the file's path within `confect/` is the group's name** (its stem for top-level groups, the dot-joined directory path for nested groups). `GroupSpec.make()` and `GroupSpec.makeNode()` no longer take a name argument.
495
577
  - Each `*.spec.ts` `export default`s its `GroupSpec` (named co-exports like error classes are still allowed).
496
- - Each `*.impl.ts` default-imports its sibling spec, passes it to `FunctionImpl.make` / `GroupImpl.make`, and ends the layer pipeline with `GroupImpl.finalize`—a compile-time completeness check that only typechecks once every function the spec declares has a `FunctionImpl` provided.
497
- - The root `confect/spec.ts`, `confect/impl.ts`, `confect/nodeSpec.ts`, and `confect/nodeImpl.ts` files are gone, along with `Impl.make` and `Impl.finalize`. `confect codegen` deletes any of these (and the stale aggregate `_generated/registeredFunctions.ts` / `_generated/nodeRegisteredFunctions.ts`) on upgrade.
578
+ - Each `*.impl.ts` default-imports its sibling spec, passes it to `FunctionImpl.make`/`GroupImpl.make`, and ends the layer pipeline with `GroupImpl.finalize`—a compile-time completeness check that only typechecks once every function the spec declares has a `FunctionImpl` provided.
579
+ - The root `confect/spec.ts`, `confect/impl.ts`, `confect/nodeSpec.ts`, and `confect/nodeImpl.ts` files are gone, along with `Impl.make` and `Impl.finalize`. `confect codegen` deletes any of these (and the stale aggregate `_generated/registeredFunctions.ts`/`_generated/nodeRegisteredFunctions.ts`) on upgrade.
498
580
 
499
581
  ### Tables are the source of truth, named by their filename
500
582
 
@@ -525,7 +607,7 @@
525
607
 
526
608
  ### Specs and impls: lazy schemas, and impls take the `DatabaseSchema`
527
609
 
528
- `FunctionSpec.*` constructors now take `args`, `returns`, and the optional `error` as `() => Schema` thunks, so importing a spec builds no schemas until a function is invoked. `FunctionImpl.make` and `GroupImpl.make` take the runtime `DatabaseSchema` (the default export of `_generated/schema`) as their first argument instead of the whole `Api`—which keeps the project-wide spec graph out of a function's cold-start module graph. The `Api` module (`Api.make`, the `Api` type) and the generated `_generated/api.ts` / `_generated/nodeApi.ts` files are removed.
610
+ `FunctionSpec.*` constructors now take `args`, `returns`, and the optional `error` as `() => Schema` thunks, so importing a spec builds no schemas until a function is invoked. `FunctionImpl.make` and `GroupImpl.make` take the runtime `DatabaseSchema` (the default export of `_generated/schema`) as their first argument instead of the whole `Api`—which keeps the project-wide spec graph out of a function's cold-start module graph. The `Api` module (`Api.make`, the `Api` type) and the generated `_generated/api.ts`/`_generated/nodeApi.ts` files are removed.
529
611
 
530
612
  **Before:**
531
613
 
@@ -573,7 +655,7 @@
573
655
 
574
656
  A group's runtime is now declared solely by its spec—`GroupSpec.makeNode()` for a Node action group, `GroupSpec.make()` otherwise—mirroring vanilla Convex's per-file `"use node"` directive. The separate `node` namespace is gone: Node specs/impls are ordinary colocated pairs that can live anywhere in `confect/`, and codegen emits the `"use node"` directive based on the spec.
575
657
  - A Node group at `confect/email.spec.ts` is now reached at `refs.public.email.send` instead of `refs.public.node.email.send`.
576
- - `@confect/core` removes `Spec.makeNode`, `Spec.merge`, and `Spec.isConvexSpec` / `Spec.isNodeSpec`; `Spec.make()` is a single mixed-runtime container and `Refs.make(spec)` takes one argument. `GroupSpec.makeNode()`, `FunctionSpec.publicNodeAction()` / `internalNodeAction()` are unchanged.
658
+ - `@confect/core` removes `Spec.makeNode`, `Spec.merge`, and `Spec.isConvexSpec`/`Spec.isNodeSpec`; `Spec.make()` is a single mixed-runtime container and `Refs.make(spec)` takes one argument. `GroupSpec.makeNode()`, `FunctionSpec.publicNodeAction()`/`internalNodeAction()` are unchanged.
577
659
 
578
660
  ### Less work at cold start
579
661
 
@@ -590,7 +672,7 @@
590
672
  ### Migration
591
673
  1. **Tables.** Delete `confect/schema.ts`. Rename each table file to a valid JS identifier (e.g. `confect/tables/notes.ts`); the basename becomes the table name. Drop the name argument from `Table.make`, wrap the field struct in `() =>`, and replace `GenericId.GenericId("x")` with `Id("x")` from `_generated/id`. If you read `table.name` off a bound table, rename it to `table.tableName`.
592
674
  2. **Specs.** Split each group into a colocated `*.spec.ts` that `export default`s `GroupSpec.make()` (no name). Wrap every `args`/`returns`/`error` in `() =>`. Import a table's `Doc`/`Fields` from its wrapper, `import notes from "./_generated/tables/notes"`.
593
- 3. **Impls.** In each `*.impl.ts`, default-import the sibling spec, import `databaseSchema` from `_generated/schema`, pass it to `FunctionImpl.make` / `GroupImpl.make` in place of `api`, end the pipeline with `GroupImpl.finalize`, and `export default` it. Delete the root `confect/spec.ts`, `impl.ts`, `nodeSpec.ts`, and `nodeImpl.ts` (codegen will also remove them).
675
+ 3. **Impls.** In each `*.impl.ts`, default-import the sibling spec, import `databaseSchema` from `_generated/schema`, pass it to `FunctionImpl.make`/`GroupImpl.make` in place of `api`, end the pipeline with `GroupImpl.finalize`, and `export default` it. Delete the root `confect/spec.ts`, `impl.ts`, `nodeSpec.ts`, and `nodeImpl.ts` (codegen will also remove them).
594
676
  4. **Node groups.** Move any `confect/node/<path>` files anywhere you like under `confect/`; the `node/` directory no longer has special meaning. Drop the `node` segment from call sites (`refs.public.node.<group>` → `refs.public.<group>`) and replace `Refs.make(spec, nodeSpec)` with `Refs.make(spec)`.
595
677
  5. **Tests.** If you use `@confect/test`, import `confectSchema` from `_generated/schema`, import the generated `convexSchema` from `_generated/convexSchema`, and pass `convexSchema` as the new second argument to `TestConfect.layer`.
596
678
  6. **Optional.** Adopt submodule Effect imports (`import * as Schema from "effect/Schema"`) in your own `confect/` files for the full cold-start savings.
@@ -634,11 +716,11 @@
634
716
 
635
717
  ### Why
636
718
 
637
- A barrel import of a namespace re-export defeats esbuild's tree-shaking: accessing `Schema.X` from `import { Schema } from "effect"` retains the _entire_ `Schema` namespace, because the bundler can't prune property access on the barrel's `export * as Schema`. So every Convex function's cold-start bundle was pulling all of `effect/Schema` and `effect/Stream` — and, transitively through Schema's `Arbitrary`, `fast-check` — whether the function used them or not.
719
+ A barrel import of a namespace re-export defeats esbuild's tree-shaking: accessing `Schema.X` from `import { Schema } from "effect"` retains the _entire_ `Schema` namespace, because the bundler can't prune property access on the barrel's `export * as Schema`. So every Convex function's cold-start bundle was pulling all of `effect/Schema` and `effect/Stream`—and, transitively through Schema's `Arbitrary`, `fast-check`—whether the function used them or not.
638
720
 
639
721
  Importing from the submodule path tree-shakes normally. On a minimal function this cut the bundle esbuild produces by ~54% (the `effect/Schema` module alone by ~75%) and its cold-start module-evaluation time by ~35%, with `fast-check` dropped entirely. This is also the import style Effect v4 recommends, so it's forward-compatible. A `no-restricted-imports` ESLint rule now enforces it across the codebase (type-only imports and `@effect/vitest` are exempt).
640
722
 
641
- No API changes — your existing code keeps working.
723
+ No API changes—your existing code keeps working.
642
724
 
643
725
  ### Getting the full win in your own code
644
726
 
@@ -5,7 +5,7 @@ type TypeId = typeof TypeId;
5
5
  * A `PaginatedQueryResult` represents the result of a Confect paginated query.
6
6
  * The non-`Failure` variants mirror the statuses of `usePaginatedQuery` from
7
7
  * `convex/react` and all carry `results` and `isLoading`, so the common UI
8
- * shape — render the list, show a spinner while loading — needs only an
8
+ * shape—render the list, show a spinner while loading—needs only an
9
9
  * {@link isFailure} early-out and plain field access.
10
10
  *
11
11
  * Every variant carries `results`, including `Failure`: when a later page
@@ -16,8 +16,8 @@ type TypeId = typeof TypeId;
16
16
  * `loadMore` appears only on `CanLoadMore`, the one state it can make
17
17
  * progress from. The underlying Convex hook exposes it on every status, but
18
18
  * calling it while a page is in flight, once the list is exhausted, or after
19
- * a failure is an intentional no-op there; narrowing to `CanLoadMore` — via
20
- * {@link isCanLoadMore} or {@link match} — makes that statically apparent
19
+ * a failure is an intentional no-op there; narrowing to `CanLoadMore`—via
20
+ * {@link isCanLoadMore} or {@link match}—makes that statically apparent
21
21
  * instead of silently dropping the call.
22
22
  *
23
23
  * When the query declares no `error` schema (`E` is `never`), the `Failure`
@@ -29,7 +29,7 @@ type TypeId = typeof TypeId;
29
29
  */
30
30
  export type PaginatedQueryResult<Item, E = never> = [E] extends [never] ? LoadingFirstPage<Item, E> | LoadingMore<Item, E> | CanLoadMore<Item, E> | Exhausted<Item, E> : LoadingFirstPage<Item, E> | LoadingMore<Item, E> | CanLoadMore<Item, E> | Exhausted<Item, E> | Failure<Item, E>;
31
31
  /**
32
- * Every variant regardless of `E` — the parameter type for guards and
32
+ * Every variant regardless of `E`—the parameter type for guards and
33
33
  * {@link match}, since `PaginatedQueryResult` itself excludes `Failure` when
34
34
  * `E` is `never`.
35
35
  */
@@ -1 +1 @@
1
- {"version":3,"file":"PaginatedQueryResult.js","names":[],"sources":["../src/PaginatedQueryResult.ts"],"sourcesContent":["import * as Equal from \"effect/Equal\";\nimport * as Function from \"effect/Function\";\nimport * as Hash from \"effect/Hash\";\nimport * as Match from \"effect/Match\";\nimport * as Pipeable from \"effect/Pipeable\";\nimport * as Predicate from \"effect/Predicate\";\n\nconst TypeId = \"~@confect/react/PaginatedQueryResult\";\ntype TypeId = typeof TypeId;\n\n/**\n * A `PaginatedQueryResult` represents the result of a Confect paginated query.\n * The non-`Failure` variants mirror the statuses of `usePaginatedQuery` from\n * `convex/react` and all carry `results` and `isLoading`, so the common UI\n * shape — render the list, show a spinner while loading — needs only an\n * {@link isFailure} early-out and plain field access.\n *\n * Every variant carries `results`, including `Failure`: when a later page\n * fails, the pages already loaded are still worth rendering alongside the\n * error, so they are not discarded. `Failure` additionally carries the\n * query's decoded typed error.\n *\n * `loadMore` appears only on `CanLoadMore`, the one state it can make\n * progress from. The underlying Convex hook exposes it on every status, but\n * calling it while a page is in flight, once the list is exhausted, or after\n * a failure is an intentional no-op there; narrowing to `CanLoadMore` — via\n * {@link isCanLoadMore} or {@link match} — makes that statically apparent\n * instead of silently dropping the call.\n *\n * When the query declares no `error` schema (`E` is `never`), the `Failure`\n * variant is excluded from the type entirely, so `isLoading` is accessible\n * without any narrowing.\n *\n * @typeParam Item - The type of a decoded page item.\n * @typeParam E - The type of the decoded typed error in the `Failure` variant.\n */\nexport type PaginatedQueryResult<Item, E = never> = [E] extends [never]\n ?\n | LoadingFirstPage<Item, E>\n | LoadingMore<Item, E>\n | CanLoadMore<Item, E>\n | Exhausted<Item, E>\n :\n | LoadingFirstPage<Item, E>\n | LoadingMore<Item, E>\n | CanLoadMore<Item, E>\n | Exhausted<Item, E>\n | Failure<Item, E>;\n\n/**\n * Every variant regardless of `E` — the parameter type for guards and\n * {@link match}, since `PaginatedQueryResult` itself excludes `Failure` when\n * `E` is `never`.\n */\nexport type Variants<Item, E = never> =\n | LoadingFirstPage<Item, E>\n | LoadingMore<Item, E>\n | CanLoadMore<Item, E>\n | Exhausted<Item, E>\n | Failure<Item, E>;\n\nexport declare namespace PaginatedQueryResult {\n // eslint-disable-next-line @typescript-eslint/no-shadow, import/namespace -- oxlint's namespace resolution misses type-only exports, and `Pipeable` is an interface\n export interface Proto<out Item, out E> extends Pipeable.Pipeable {\n readonly [TypeId]: TypeId;\n readonly \"~Item\": Item;\n readonly \"~E\": E;\n }\n\n export type Item<R> = R extends { readonly \"~Item\": infer Item_ }\n ? Item_\n : never;\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n export type Failure<R> = R extends { readonly \"~E\": infer E } ? E : never;\n}\n\nexport interface LoadingFirstPage<\n Item,\n E = never,\n> extends PaginatedQueryResult.Proto<Item, E> {\n readonly _tag: \"LoadingFirstPage\";\n readonly skipped: boolean;\n readonly results: ReadonlyArray<Item>;\n readonly isLoading: true;\n}\n\nexport interface LoadingMore<\n Item,\n E = never,\n> extends PaginatedQueryResult.Proto<Item, E> {\n readonly _tag: \"LoadingMore\";\n readonly results: ReadonlyArray<Item>;\n readonly isLoading: true;\n}\n\nexport interface CanLoadMore<\n Item,\n E = never,\n> extends PaginatedQueryResult.Proto<Item, E> {\n readonly _tag: \"CanLoadMore\";\n readonly results: ReadonlyArray<Item>;\n readonly isLoading: false;\n readonly loadMore: (numItems: number) => void;\n}\n\nexport interface Exhausted<Item, E = never> extends PaginatedQueryResult.Proto<\n Item,\n E\n> {\n readonly _tag: \"Exhausted\";\n readonly results: ReadonlyArray<Item>;\n readonly isLoading: false;\n}\n\nexport interface Failure<Item, E = never> extends PaginatedQueryResult.Proto<\n Item,\n E\n> {\n readonly _tag: \"Failure\";\n readonly error: E;\n /** The pages loaded before the failure. */\n readonly results: ReadonlyArray<Item>;\n}\n\nexport const isPaginatedQueryResult = (\n u: unknown,\n): u is Variants<unknown, unknown> => Predicate.hasProperty(u, TypeId);\n\nconst PaginatedQueryResultProto = {\n [TypeId]: TypeId,\n pipe(this: Variants<any, any>, ...args: ReadonlyArray<unknown>) {\n return Pipeable.pipeArguments(\n this,\n args as unknown as Parameters<typeof Pipeable.pipeArguments>[1],\n );\n },\n /**\n * `CanLoadMore`'s `loadMore` is excluded from equality and hashing, like\n * function fields generally: two results that render identically are equal\n * even though their callbacks differ by identity.\n */\n [Equal.symbol](this: Variants<any, any>, that: Variants<any, any>): boolean {\n if (this._tag !== that._tag) {\n return false;\n }\n return Match.value(this).pipe(\n Match.tag(\n \"LoadingFirstPage\",\n (self) => self.skipped === (that as LoadingFirstPage<any, any>).skipped,\n ),\n Match.tag(\"LoadingMore\", \"CanLoadMore\", \"Exhausted\", (self) =>\n Equal.equals(self.results, that.results),\n ),\n Match.tag(\n \"Failure\",\n (self) =>\n Equal.equals(self.error, (that as Failure<any, any>).error) &&\n Equal.equals(self.results, (that as Failure<any, any>).results),\n ),\n Match.exhaustive,\n );\n },\n [Hash.symbol](this: Variants<any, any>): number {\n const tagHash = Hash.string(this._tag);\n return Match.value(this).pipe(\n Match.tag(\"LoadingFirstPage\", (self) =>\n Hash.combine(tagHash)(Hash.hash(self.skipped)),\n ),\n Match.tag(\"LoadingMore\", \"CanLoadMore\", \"Exhausted\", (self) =>\n Hash.combine(tagHash)(Hash.hash(self.results)),\n ),\n Match.tag(\"Failure\", (self) =>\n Hash.combine(tagHash)(\n Hash.combine(Hash.hash(self.error))(Hash.hash(self.results)),\n ),\n ),\n Match.exhaustive,\n );\n },\n};\n\nconst noResults: ReadonlyArray<never> = [];\n\nexport const loadingFirstPage = <Item = never, E = never>(options: {\n skipped: boolean;\n}): LoadingFirstPage<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"LoadingFirstPage\" as const,\n skipped: options.skipped,\n results: noResults,\n isLoading: true as const,\n });\n\nexport const loadingMore = <Item, E = never>(options: {\n results: ReadonlyArray<Item>;\n}): LoadingMore<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"LoadingMore\" as const,\n results: options.results,\n isLoading: true as const,\n });\n\nexport const canLoadMore = <Item, E = never>(options: {\n results: ReadonlyArray<Item>;\n loadMore: (numItems: number) => void;\n}): CanLoadMore<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"CanLoadMore\" as const,\n results: options.results,\n isLoading: false as const,\n loadMore: options.loadMore,\n });\n\nexport const exhausted = <Item, E = never>(options: {\n results: ReadonlyArray<Item>;\n}): Exhausted<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"Exhausted\" as const,\n results: options.results,\n isLoading: false as const,\n });\n\nexport const failure = <E, Item = never>(options: {\n error: E;\n results: ReadonlyArray<Item>;\n}): Failure<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"Failure\" as const,\n error: options.error,\n results: options.results,\n });\n\nexport const isLoadingFirstPage = <Item, E>(\n result: Variants<Item, E>,\n): result is LoadingFirstPage<Item, E> => result._tag === \"LoadingFirstPage\";\n\nexport const isLoadingMore = <Item, E>(\n result: Variants<Item, E>,\n): result is LoadingMore<Item, E> => result._tag === \"LoadingMore\";\n\nexport const isCanLoadMore = <Item, E>(\n result: Variants<Item, E>,\n): result is CanLoadMore<Item, E> => result._tag === \"CanLoadMore\";\n\nexport const isExhausted = <Item, E>(\n result: Variants<Item, E>,\n): result is Exhausted<Item, E> => result._tag === \"Exhausted\";\n\nexport const isFailure = <Item, E>(\n result: Variants<Item, E>,\n): result is Failure<Item, E> => result._tag === \"Failure\";\n\nexport const isLoading = <Item, E>(\n result: Variants<Item, E>,\n): result is LoadingFirstPage<Item, E> | LoadingMore<Item, E> =>\n result._tag === \"LoadingFirstPage\" || result._tag === \"LoadingMore\";\n\ntype MatchOptions<Item, E, V, W, X, Y, Z> = {\n readonly onLoadingFirstPage: (skipped: boolean) => V;\n readonly onLoadingMore: (results: ReadonlyArray<Item>) => W;\n readonly onCanLoadMore: (\n results: ReadonlyArray<Item>,\n loadMore: (numItems: number) => void,\n ) => X;\n readonly onExhausted: (results: ReadonlyArray<Item>) => Y;\n} & ([E] extends [never]\n ? {}\n : {\n readonly onFailure: (error: E, results: ReadonlyArray<Item>) => Z;\n });\n\ntype MatchReturns<E, V, W, X, Y, Z> = [E] extends [never]\n ? V | W | X | Y\n : V | W | X | Y | Z;\n\n/**\n * Matches a {@link PaginatedQueryResult} to the appropriate handler based on\n * its tag. If the provided result cannot fail (i.e. `E` is `never`),\n * `onFailure` is not required.\n */\nexport const match: {\n <Item, E, V, W, X, Y, Z = never>(\n options: MatchOptions<Item, E, V, W, X, Y, Z>,\n ): (self: Variants<Item, E>) => MatchReturns<E, V, W, X, Y, Z>;\n <Item, E, V, W, X, Y, Z = never>(\n self: Variants<Item, E>,\n options: MatchOptions<Item, E, V, W, X, Y, Z>,\n ): MatchReturns<E, V, W, X, Y, Z>;\n} = Function.dual(\n 2,\n <Item, E, V, W, X, Y, Z = never>(\n self: Variants<Item, E>,\n options: MatchOptions<Item, E, V, W, X, Y, Z>,\n ): MatchReturns<E, V, W, X, Y, Z> =>\n Match.value(self).pipe(\n Match.tag(\"LoadingFirstPage\", (loadingFirstPage_) =>\n options.onLoadingFirstPage(loadingFirstPage_.skipped),\n ),\n Match.tag(\"LoadingMore\", (loadingMore_) =>\n options.onLoadingMore(loadingMore_.results),\n ),\n Match.tag(\"CanLoadMore\", (canLoadMore_) =>\n options.onCanLoadMore(canLoadMore_.results, canLoadMore_.loadMore),\n ),\n Match.tag(\"Exhausted\", (exhausted_) =>\n options.onExhausted(exhausted_.results),\n ),\n Match.tag(\"Failure\", (failure_) => {\n if (Predicate.hasProperty(options, \"onFailure\")) {\n return options.onFailure(failure_.error, failure_.results);\n }\n throw new Error(\n \"`onFailure` is required when error schema is provided\",\n );\n }),\n Match.exhaustive,\n ) as MatchReturns<E, V, W, X, Y, Z>,\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"PaginatedQueryResult.js","names":[],"sources":["../src/PaginatedQueryResult.ts"],"sourcesContent":["import * as Equal from \"effect/Equal\";\nimport * as Function from \"effect/Function\";\nimport * as Hash from \"effect/Hash\";\nimport * as Match from \"effect/Match\";\nimport * as Pipeable from \"effect/Pipeable\";\nimport * as Predicate from \"effect/Predicate\";\n\nconst TypeId = \"~@confect/react/PaginatedQueryResult\";\ntype TypeId = typeof TypeId;\n\n/**\n * A `PaginatedQueryResult` represents the result of a Confect paginated query.\n * The non-`Failure` variants mirror the statuses of `usePaginatedQuery` from\n * `convex/react` and all carry `results` and `isLoading`, so the common UI\n * shape—render the list, show a spinner while loading—needs only an\n * {@link isFailure} early-out and plain field access.\n *\n * Every variant carries `results`, including `Failure`: when a later page\n * fails, the pages already loaded are still worth rendering alongside the\n * error, so they are not discarded. `Failure` additionally carries the\n * query's decoded typed error.\n *\n * `loadMore` appears only on `CanLoadMore`, the one state it can make\n * progress from. The underlying Convex hook exposes it on every status, but\n * calling it while a page is in flight, once the list is exhausted, or after\n * a failure is an intentional no-op there; narrowing to `CanLoadMore`—via\n * {@link isCanLoadMore} or {@link match}—makes that statically apparent\n * instead of silently dropping the call.\n *\n * When the query declares no `error` schema (`E` is `never`), the `Failure`\n * variant is excluded from the type entirely, so `isLoading` is accessible\n * without any narrowing.\n *\n * @typeParam Item - The type of a decoded page item.\n * @typeParam E - The type of the decoded typed error in the `Failure` variant.\n */\nexport type PaginatedQueryResult<Item, E = never> = [E] extends [never]\n ?\n | LoadingFirstPage<Item, E>\n | LoadingMore<Item, E>\n | CanLoadMore<Item, E>\n | Exhausted<Item, E>\n :\n | LoadingFirstPage<Item, E>\n | LoadingMore<Item, E>\n | CanLoadMore<Item, E>\n | Exhausted<Item, E>\n | Failure<Item, E>;\n\n/**\n * Every variant regardless of `E`—the parameter type for guards and\n * {@link match}, since `PaginatedQueryResult` itself excludes `Failure` when\n * `E` is `never`.\n */\nexport type Variants<Item, E = never> =\n | LoadingFirstPage<Item, E>\n | LoadingMore<Item, E>\n | CanLoadMore<Item, E>\n | Exhausted<Item, E>\n | Failure<Item, E>;\n\nexport declare namespace PaginatedQueryResult {\n // eslint-disable-next-line @typescript-eslint/no-shadow\n export interface Proto<out Item, out E> extends Pipeable.Pipeable {\n readonly [TypeId]: TypeId;\n readonly \"~Item\": Item;\n readonly \"~E\": E;\n }\n\n export type Item<R> = R extends { readonly \"~Item\": infer Item_ }\n ? Item_\n : never;\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n export type Failure<R> = R extends { readonly \"~E\": infer E } ? E : never;\n}\n\nexport interface LoadingFirstPage<\n Item,\n E = never,\n> extends PaginatedQueryResult.Proto<Item, E> {\n readonly _tag: \"LoadingFirstPage\";\n readonly skipped: boolean;\n readonly results: ReadonlyArray<Item>;\n readonly isLoading: true;\n}\n\nexport interface LoadingMore<\n Item,\n E = never,\n> extends PaginatedQueryResult.Proto<Item, E> {\n readonly _tag: \"LoadingMore\";\n readonly results: ReadonlyArray<Item>;\n readonly isLoading: true;\n}\n\nexport interface CanLoadMore<\n Item,\n E = never,\n> extends PaginatedQueryResult.Proto<Item, E> {\n readonly _tag: \"CanLoadMore\";\n readonly results: ReadonlyArray<Item>;\n readonly isLoading: false;\n readonly loadMore: (numItems: number) => void;\n}\n\nexport interface Exhausted<Item, E = never> extends PaginatedQueryResult.Proto<\n Item,\n E\n> {\n readonly _tag: \"Exhausted\";\n readonly results: ReadonlyArray<Item>;\n readonly isLoading: false;\n}\n\nexport interface Failure<Item, E = never> extends PaginatedQueryResult.Proto<\n Item,\n E\n> {\n readonly _tag: \"Failure\";\n readonly error: E;\n /** The pages loaded before the failure. */\n readonly results: ReadonlyArray<Item>;\n}\n\nexport const isPaginatedQueryResult = (\n u: unknown,\n): u is Variants<unknown, unknown> => Predicate.hasProperty(u, TypeId);\n\nconst PaginatedQueryResultProto = {\n [TypeId]: TypeId,\n pipe(this: Variants<any, any>, ...args: ReadonlyArray<unknown>) {\n return Pipeable.pipeArguments(\n this,\n args as unknown as Parameters<typeof Pipeable.pipeArguments>[1],\n );\n },\n /**\n * `CanLoadMore`'s `loadMore` is excluded from equality and hashing, like\n * function fields generally: two results that render identically are equal\n * even though their callbacks differ by identity.\n */\n [Equal.symbol](this: Variants<any, any>, that: Variants<any, any>): boolean {\n if (this._tag !== that._tag) {\n return false;\n }\n return Match.value(this).pipe(\n Match.tag(\n \"LoadingFirstPage\",\n (self) => self.skipped === (that as LoadingFirstPage<any, any>).skipped,\n ),\n Match.tag(\"LoadingMore\", \"CanLoadMore\", \"Exhausted\", (self) =>\n Equal.equals(self.results, that.results),\n ),\n Match.tag(\n \"Failure\",\n (self) =>\n Equal.equals(self.error, (that as Failure<any, any>).error) &&\n Equal.equals(self.results, (that as Failure<any, any>).results),\n ),\n Match.exhaustive,\n );\n },\n [Hash.symbol](this: Variants<any, any>): number {\n const tagHash = Hash.string(this._tag);\n return Match.value(this).pipe(\n Match.tag(\"LoadingFirstPage\", (self) =>\n Hash.combine(tagHash)(Hash.hash(self.skipped)),\n ),\n Match.tag(\"LoadingMore\", \"CanLoadMore\", \"Exhausted\", (self) =>\n Hash.combine(tagHash)(Hash.hash(self.results)),\n ),\n Match.tag(\"Failure\", (self) =>\n Hash.combine(tagHash)(\n Hash.combine(Hash.hash(self.error))(Hash.hash(self.results)),\n ),\n ),\n Match.exhaustive,\n );\n },\n};\n\nconst noResults: ReadonlyArray<never> = [];\n\nexport const loadingFirstPage = <Item = never, E = never>(options: {\n skipped: boolean;\n}): LoadingFirstPage<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"LoadingFirstPage\" as const,\n skipped: options.skipped,\n results: noResults,\n isLoading: true as const,\n });\n\nexport const loadingMore = <Item, E = never>(options: {\n results: ReadonlyArray<Item>;\n}): LoadingMore<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"LoadingMore\" as const,\n results: options.results,\n isLoading: true as const,\n });\n\nexport const canLoadMore = <Item, E = never>(options: {\n results: ReadonlyArray<Item>;\n loadMore: (numItems: number) => void;\n}): CanLoadMore<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"CanLoadMore\" as const,\n results: options.results,\n isLoading: false as const,\n loadMore: options.loadMore,\n });\n\nexport const exhausted = <Item, E = never>(options: {\n results: ReadonlyArray<Item>;\n}): Exhausted<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"Exhausted\" as const,\n results: options.results,\n isLoading: false as const,\n });\n\nexport const failure = <E, Item = never>(options: {\n error: E;\n results: ReadonlyArray<Item>;\n}): Failure<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"Failure\" as const,\n error: options.error,\n results: options.results,\n });\n\nexport const isLoadingFirstPage = <Item, E>(\n result: Variants<Item, E>,\n): result is LoadingFirstPage<Item, E> => result._tag === \"LoadingFirstPage\";\n\nexport const isLoadingMore = <Item, E>(\n result: Variants<Item, E>,\n): result is LoadingMore<Item, E> => result._tag === \"LoadingMore\";\n\nexport const isCanLoadMore = <Item, E>(\n result: Variants<Item, E>,\n): result is CanLoadMore<Item, E> => result._tag === \"CanLoadMore\";\n\nexport const isExhausted = <Item, E>(\n result: Variants<Item, E>,\n): result is Exhausted<Item, E> => result._tag === \"Exhausted\";\n\nexport const isFailure = <Item, E>(\n result: Variants<Item, E>,\n): result is Failure<Item, E> => result._tag === \"Failure\";\n\nexport const isLoading = <Item, E>(\n result: Variants<Item, E>,\n): result is LoadingFirstPage<Item, E> | LoadingMore<Item, E> =>\n result._tag === \"LoadingFirstPage\" || result._tag === \"LoadingMore\";\n\ntype MatchOptions<Item, E, V, W, X, Y, Z> = {\n readonly onLoadingFirstPage: (skipped: boolean) => V;\n readonly onLoadingMore: (results: ReadonlyArray<Item>) => W;\n readonly onCanLoadMore: (\n results: ReadonlyArray<Item>,\n loadMore: (numItems: number) => void,\n ) => X;\n readonly onExhausted: (results: ReadonlyArray<Item>) => Y;\n} & ([E] extends [never]\n ? {}\n : {\n readonly onFailure: (error: E, results: ReadonlyArray<Item>) => Z;\n });\n\ntype MatchReturns<E, V, W, X, Y, Z> = [E] extends [never]\n ? V | W | X | Y\n : V | W | X | Y | Z;\n\n/**\n * Matches a {@link PaginatedQueryResult} to the appropriate handler based on\n * its tag. If the provided result cannot fail (i.e. `E` is `never`),\n * `onFailure` is not required.\n */\nexport const match: {\n <Item, E, V, W, X, Y, Z = never>(\n options: MatchOptions<Item, E, V, W, X, Y, Z>,\n ): (self: Variants<Item, E>) => MatchReturns<E, V, W, X, Y, Z>;\n <Item, E, V, W, X, Y, Z = never>(\n self: Variants<Item, E>,\n options: MatchOptions<Item, E, V, W, X, Y, Z>,\n ): MatchReturns<E, V, W, X, Y, Z>;\n} = Function.dual(\n 2,\n <Item, E, V, W, X, Y, Z = never>(\n self: Variants<Item, E>,\n options: MatchOptions<Item, E, V, W, X, Y, Z>,\n ): MatchReturns<E, V, W, X, Y, Z> =>\n Match.value(self).pipe(\n Match.tag(\"LoadingFirstPage\", (loadingFirstPage_) =>\n options.onLoadingFirstPage(loadingFirstPage_.skipped),\n ),\n Match.tag(\"LoadingMore\", (loadingMore_) =>\n options.onLoadingMore(loadingMore_.results),\n ),\n Match.tag(\"CanLoadMore\", (canLoadMore_) =>\n options.onCanLoadMore(canLoadMore_.results, canLoadMore_.loadMore),\n ),\n Match.tag(\"Exhausted\", (exhausted_) =>\n options.onExhausted(exhausted_.results),\n ),\n Match.tag(\"Failure\", (failure_) => {\n if (Predicate.hasProperty(options, \"onFailure\")) {\n return options.onFailure(failure_.error, failure_.results);\n }\n throw new Error(\n \"`onFailure` is required when error schema is provided\",\n );\n }),\n Match.exhaustive,\n ) as MatchReturns<E, V, W, X, Y, Z>,\n);\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryResult.d.ts","sourceRoot":"","sources":["../src/QueryResult.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"QueryResult.d.ts","sourceRoot":"","sources":["../src/QueryResult.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryResult.js","names":[],"sources":["../src/QueryResult.ts"],"sourcesContent":["import * as Equal from \"effect/Equal\";\nimport * as Function from \"effect/Function\";\nimport * as Hash from \"effect/Hash\";\nimport * as Match from \"effect/Match\";\nimport * as Pipeable from \"effect/Pipeable\";\nimport * as Predicate from \"effect/Predicate\";\n\nconst TypeId = \"~@confect/react/QueryResult\";\ntype TypeId = typeof TypeId;\n\n/**\n * A `QueryResult` represents the result of a Confect query.\n *\n * @typeParam A - The type of the decoded `returns` value in the `Success` variant.\n * @typeParam E - The type of the decoded typed error in the `Failure` variant.\n */\nexport type QueryResult<A, E = never> =\n | Loading<A, E>\n | Success<A, E>\n | Failure<A, E>;\n\nexport declare namespace QueryResult {\n // eslint-disable-next-line import/namespace -- oxlint's namespace resolution misses type-only exports, and `Pipeable` is an interface\n export interface Proto<out A, out E> extends Pipeable.Pipeable {\n readonly [TypeId]: TypeId;\n readonly \"~A\": A;\n readonly \"~E\": E;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n export type Success<R> = R extends { readonly \"~A\": infer A } ? A : never;\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n export type Failure<R> = R extends { readonly \"~E\": infer E } ? E : never;\n}\n\nexport interface Loading<A, E = never> extends QueryResult.Proto<A, E> {\n readonly _tag: \"Loading\";\n readonly skipped: boolean;\n}\n\nexport interface Success<A, E = never> extends QueryResult.Proto<A, E> {\n readonly _tag: \"Success\";\n readonly value: A;\n}\n\nexport interface Failure<A, E = never> extends QueryResult.Proto<A, E> {\n readonly _tag: \"Failure\";\n readonly error: E;\n}\n\nexport const isQueryResult = (u: unknown): u is QueryResult<unknown, unknown> =>\n Predicate.hasProperty(u, TypeId);\n\nconst QueryResultProto = {\n [TypeId]: TypeId,\n pipe(this: QueryResult<any, any>, ...args: ReadonlyArray<unknown>) {\n return Pipeable.pipeArguments(\n this,\n args as unknown as Parameters<typeof Pipeable.pipeArguments>[1],\n );\n },\n [Equal.symbol](\n this: QueryResult<any, any>,\n that: QueryResult<any, any>,\n ): boolean {\n if (this._tag !== that._tag) {\n return false;\n }\n return Match.value(this).pipe(\n Match.tag(\n \"Loading\",\n (self) => self.skipped === (that as Loading<any, any>).skipped,\n ),\n Match.tag(\"Success\", (self) =>\n Equal.equals(self.value, (that as Success<any, any>).value),\n ),\n Match.tag(\"Failure\", (self) =>\n Equal.equals(self.error, (that as Failure<any, any>).error),\n ),\n Match.exhaustive,\n );\n },\n [Hash.symbol](this: QueryResult<any, any>): number {\n const tagHash = Hash.string(this._tag);\n return Match.value(this).pipe(\n Match.tag(\"Loading\", (self) =>\n Hash.combine(tagHash)(Hash.hash(self.skipped)),\n ),\n Match.tag(\"Success\", (self) =>\n Hash.combine(tagHash)(Hash.hash(self.value)),\n ),\n Match.tag(\"Failure\", (self) =>\n Hash.combine(tagHash)(Hash.hash(self.error)),\n ),\n Match.exhaustive,\n );\n },\n};\n\nexport const load = <A = never, E = never>(skipped: boolean): Loading<A, E> =>\n Object.assign(Object.create(QueryResultProto), {\n _tag: \"Loading\" as const,\n skipped,\n });\n\nexport const succeed = <A, E = never>(value: A): Success<A, E> =>\n Object.assign(Object.create(QueryResultProto), {\n _tag: \"Success\" as const,\n value,\n });\n\nexport const fail = <E, A = never>(error: E): Failure<A, E> =>\n Object.assign(Object.create(QueryResultProto), {\n _tag: \"Failure\" as const,\n error,\n });\n\nexport const isLoading = <A, E>(\n queryResult: QueryResult<A, E>,\n): queryResult is Loading<A, E> => queryResult._tag === \"Loading\";\n\nexport const isSuccess = <A, E>(\n queryResult: QueryResult<A, E>,\n): queryResult is Success<A, E> => queryResult._tag === \"Success\";\n\nexport const isFailure = <A, E>(\n queryResult: QueryResult<A, E>,\n): queryResult is Failure<A, E> => queryResult._tag === \"Failure\";\n\ntype MatchOptions<A, E, X, Y, Z> = {\n readonly onLoading: (skipped: boolean) => X;\n readonly onSuccess: (value: A) => Y;\n} & ([E] extends [never] ? {} : { readonly onFailure: (error: E) => Z });\n\ntype MatchReturns<E, X, Y, Z> = [E] extends [never] ? X | Y : X | Y | Z;\n\n/**\n * Matches a {@link QueryResult} to the appropriate handler based on its tag. If\n * the provided `QueryResult` cannot fail (i.e. `E` is `never`), `onFailure` is\n * not required.\n *\n * @example\n * ```tsx\n * const result = QueryResult.match(queryResult, {\n * onLoading: (skipped) => skipped ? null : <p>Loading…</p>,\n * onSuccess: (value) => <p>{value.text}</p>,\n * onFailure: (error) => <p>Error: {error.message}</p>,\n * });\n */\nexport const match: {\n <A, E, X, Y, Z = never>(\n options: MatchOptions<A, E, X, Y, Z>,\n ): (self: QueryResult<A, E>) => MatchReturns<E, X, Y, Z>;\n <A, E, X, Y, Z = never>(\n self: QueryResult<A, E>,\n options: MatchOptions<A, E, X, Y, Z>,\n ): MatchReturns<E, X, Y, Z>;\n} = Function.dual(\n 2,\n <A, E, X, Y, Z = never>(\n self: QueryResult<A, E>,\n options: MatchOptions<A, E, X, Y, Z>,\n ): MatchReturns<E, X, Y, Z> =>\n Match.value(self).pipe(\n Match.tag(\"Loading\", (loading) => options.onLoading(loading.skipped)),\n Match.tag(\"Success\", (success) => options.onSuccess(success.value)),\n Match.tag(\"Failure\", (failure) => {\n if (Predicate.hasProperty(options, \"onFailure\")) {\n return options.onFailure(failure.error);\n }\n throw new Error(\n \"`onFailure` is required when error schema is provided\",\n );\n }),\n Match.exhaustive,\n ) as MatchReturns<E, X, Y, Z>,\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAOA,MAAM,SAAS;AA4Cf,MAAa,iBAAiB,MAC5B,UAAU,YAAY,GAAG,MAAM;AAEjC,MAAM,mBAAmB;EACtB,SAAS;CACV,KAAkC,GAAG,MAA8B;EACjE,OAAO,SAAS,cACd,MACA,IACF;CACF;CACA,CAAC,MAAM,QAEL,MACS;EACT,IAAI,KAAK,SAAS,KAAK,MACrB,OAAO;EAET,OAAO,MAAM,MAAM,IAAI,CAAC,CAAC,KACvB,MAAM,IACJ,YACC,SAAS,KAAK,YAAa,KAA2B,OACzD,GACA,MAAM,IAAI,YAAY,SACpB,MAAM,OAAO,KAAK,OAAQ,KAA2B,KAAK,CAC5D,GACA,MAAM,IAAI,YAAY,SACpB,MAAM,OAAO,KAAK,OAAQ,KAA2B,KAAK,CAC5D,GACA,MAAM,UACR;CACF;CACA,CAAC,KAAK,UAA6C;EACjD,MAAM,UAAU,KAAK,OAAO,KAAK,IAAI;EACrC,OAAO,MAAM,MAAM,IAAI,CAAC,CAAC,KACvB,MAAM,IAAI,YAAY,SACpB,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,OAAO,CAAC,CAC/C,GACA,MAAM,IAAI,YAAY,SACpB,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,KAAK,CAAC,CAC7C,GACA,MAAM,IAAI,YAAY,SACpB,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,KAAK,CAAC,CAC7C,GACA,MAAM,UACR;CACF;AACF;AAEA,MAAa,QAA8B,YACzC,OAAO,OAAO,OAAO,OAAO,gBAAgB,GAAG;CAC7C,MAAM;CACN;AACF,CAAC;AAEH,MAAa,WAAyB,UACpC,OAAO,OAAO,OAAO,OAAO,gBAAgB,GAAG;CAC7C,MAAM;CACN;AACF,CAAC;AAEH,MAAa,QAAsB,UACjC,OAAO,OAAO,OAAO,OAAO,gBAAgB,GAAG;CAC7C,MAAM;CACN;AACF,CAAC;AAEH,MAAa,aACX,gBACiC,YAAY,SAAS;AAExD,MAAa,aACX,gBACiC,YAAY,SAAS;AAExD,MAAa,aACX,gBACiC,YAAY,SAAS;;;;;;;;;;;;;;AAsBxD,MAAa,QAQT,SAAS,KACX,IAEE,MACA,YAEA,MAAM,MAAM,IAAI,CAAC,CAAC,KAChB,MAAM,IAAI,YAAY,YAAY,QAAQ,UAAU,QAAQ,OAAO,CAAC,GACpE,MAAM,IAAI,YAAY,YAAY,QAAQ,UAAU,QAAQ,KAAK,CAAC,GAClE,MAAM,IAAI,YAAY,YAAY;CAChC,IAAI,UAAU,YAAY,SAAS,WAAW,GAC5C,OAAO,QAAQ,UAAU,QAAQ,KAAK;CAExC,MAAM,IAAI,MACR,uDACF;AACF,CAAC,GACD,MAAM,UACR,CACJ"}
1
+ {"version":3,"file":"QueryResult.js","names":[],"sources":["../src/QueryResult.ts"],"sourcesContent":["import * as Equal from \"effect/Equal\";\nimport * as Function from \"effect/Function\";\nimport * as Hash from \"effect/Hash\";\nimport * as Match from \"effect/Match\";\nimport * as Pipeable from \"effect/Pipeable\";\nimport * as Predicate from \"effect/Predicate\";\n\nconst TypeId = \"~@confect/react/QueryResult\";\ntype TypeId = typeof TypeId;\n\n/**\n * A `QueryResult` represents the result of a Confect query.\n *\n * @typeParam A - The type of the decoded `returns` value in the `Success` variant.\n * @typeParam E - The type of the decoded typed error in the `Failure` variant.\n */\nexport type QueryResult<A, E = never> =\n | Loading<A, E>\n | Success<A, E>\n | Failure<A, E>;\n\nexport declare namespace QueryResult {\n export interface Proto<out A, out E> extends Pipeable.Pipeable {\n readonly [TypeId]: TypeId;\n readonly \"~A\": A;\n readonly \"~E\": E;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n export type Success<R> = R extends { readonly \"~A\": infer A } ? A : never;\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n export type Failure<R> = R extends { readonly \"~E\": infer E } ? E : never;\n}\n\nexport interface Loading<A, E = never> extends QueryResult.Proto<A, E> {\n readonly _tag: \"Loading\";\n readonly skipped: boolean;\n}\n\nexport interface Success<A, E = never> extends QueryResult.Proto<A, E> {\n readonly _tag: \"Success\";\n readonly value: A;\n}\n\nexport interface Failure<A, E = never> extends QueryResult.Proto<A, E> {\n readonly _tag: \"Failure\";\n readonly error: E;\n}\n\nexport const isQueryResult = (u: unknown): u is QueryResult<unknown, unknown> =>\n Predicate.hasProperty(u, TypeId);\n\nconst QueryResultProto = {\n [TypeId]: TypeId,\n pipe(this: QueryResult<any, any>, ...args: ReadonlyArray<unknown>) {\n return Pipeable.pipeArguments(\n this,\n args as unknown as Parameters<typeof Pipeable.pipeArguments>[1],\n );\n },\n [Equal.symbol](\n this: QueryResult<any, any>,\n that: QueryResult<any, any>,\n ): boolean {\n if (this._tag !== that._tag) {\n return false;\n }\n return Match.value(this).pipe(\n Match.tag(\n \"Loading\",\n (self) => self.skipped === (that as Loading<any, any>).skipped,\n ),\n Match.tag(\"Success\", (self) =>\n Equal.equals(self.value, (that as Success<any, any>).value),\n ),\n Match.tag(\"Failure\", (self) =>\n Equal.equals(self.error, (that as Failure<any, any>).error),\n ),\n Match.exhaustive,\n );\n },\n [Hash.symbol](this: QueryResult<any, any>): number {\n const tagHash = Hash.string(this._tag);\n return Match.value(this).pipe(\n Match.tag(\"Loading\", (self) =>\n Hash.combine(tagHash)(Hash.hash(self.skipped)),\n ),\n Match.tag(\"Success\", (self) =>\n Hash.combine(tagHash)(Hash.hash(self.value)),\n ),\n Match.tag(\"Failure\", (self) =>\n Hash.combine(tagHash)(Hash.hash(self.error)),\n ),\n Match.exhaustive,\n );\n },\n};\n\nexport const load = <A = never, E = never>(skipped: boolean): Loading<A, E> =>\n Object.assign(Object.create(QueryResultProto), {\n _tag: \"Loading\" as const,\n skipped,\n });\n\nexport const succeed = <A, E = never>(value: A): Success<A, E> =>\n Object.assign(Object.create(QueryResultProto), {\n _tag: \"Success\" as const,\n value,\n });\n\nexport const fail = <E, A = never>(error: E): Failure<A, E> =>\n Object.assign(Object.create(QueryResultProto), {\n _tag: \"Failure\" as const,\n error,\n });\n\nexport const isLoading = <A, E>(\n queryResult: QueryResult<A, E>,\n): queryResult is Loading<A, E> => queryResult._tag === \"Loading\";\n\nexport const isSuccess = <A, E>(\n queryResult: QueryResult<A, E>,\n): queryResult is Success<A, E> => queryResult._tag === \"Success\";\n\nexport const isFailure = <A, E>(\n queryResult: QueryResult<A, E>,\n): queryResult is Failure<A, E> => queryResult._tag === \"Failure\";\n\ntype MatchOptions<A, E, X, Y, Z> = {\n readonly onLoading: (skipped: boolean) => X;\n readonly onSuccess: (value: A) => Y;\n} & ([E] extends [never] ? {} : { readonly onFailure: (error: E) => Z });\n\ntype MatchReturns<E, X, Y, Z> = [E] extends [never] ? X | Y : X | Y | Z;\n\n/**\n * Matches a {@link QueryResult} to the appropriate handler based on its tag. If\n * the provided `QueryResult` cannot fail (i.e. `E` is `never`), `onFailure` is\n * not required.\n *\n * @example\n * ```tsx\n * const result = QueryResult.match(queryResult, {\n * onLoading: (skipped) => skipped ? null : <p>Loading…</p>,\n * onSuccess: (value) => <p>{value.text}</p>,\n * onFailure: (error) => <p>Error: {error.message}</p>,\n * });\n */\nexport const match: {\n <A, E, X, Y, Z = never>(\n options: MatchOptions<A, E, X, Y, Z>,\n ): (self: QueryResult<A, E>) => MatchReturns<E, X, Y, Z>;\n <A, E, X, Y, Z = never>(\n self: QueryResult<A, E>,\n options: MatchOptions<A, E, X, Y, Z>,\n ): MatchReturns<E, X, Y, Z>;\n} = Function.dual(\n 2,\n <A, E, X, Y, Z = never>(\n self: QueryResult<A, E>,\n options: MatchOptions<A, E, X, Y, Z>,\n ): MatchReturns<E, X, Y, Z> =>\n Match.value(self).pipe(\n Match.tag(\"Loading\", (loading) => options.onLoading(loading.skipped)),\n Match.tag(\"Success\", (success) => options.onSuccess(success.value)),\n Match.tag(\"Failure\", (failure) => {\n if (Predicate.hasProperty(options, \"onFailure\")) {\n return options.onFailure(failure.error);\n }\n throw new Error(\n \"`onFailure` is required when error schema is provided\",\n );\n }),\n Match.exhaustive,\n ) as MatchReturns<E, X, Y, Z>,\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAOA,MAAM,SAAS;AA2Cf,MAAa,iBAAiB,MAC5B,UAAU,YAAY,GAAG,MAAM;AAEjC,MAAM,mBAAmB;EACtB,SAAS;CACV,KAAkC,GAAG,MAA8B;EACjE,OAAO,SAAS,cACd,MACA,IACF;CACF;CACA,CAAC,MAAM,QAEL,MACS;EACT,IAAI,KAAK,SAAS,KAAK,MACrB,OAAO;EAET,OAAO,MAAM,MAAM,IAAI,CAAC,CAAC,KACvB,MAAM,IACJ,YACC,SAAS,KAAK,YAAa,KAA2B,OACzD,GACA,MAAM,IAAI,YAAY,SACpB,MAAM,OAAO,KAAK,OAAQ,KAA2B,KAAK,CAC5D,GACA,MAAM,IAAI,YAAY,SACpB,MAAM,OAAO,KAAK,OAAQ,KAA2B,KAAK,CAC5D,GACA,MAAM,UACR;CACF;CACA,CAAC,KAAK,UAA6C;EACjD,MAAM,UAAU,KAAK,OAAO,KAAK,IAAI;EACrC,OAAO,MAAM,MAAM,IAAI,CAAC,CAAC,KACvB,MAAM,IAAI,YAAY,SACpB,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,OAAO,CAAC,CAC/C,GACA,MAAM,IAAI,YAAY,SACpB,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,KAAK,CAAC,CAC7C,GACA,MAAM,IAAI,YAAY,SACpB,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,KAAK,CAAC,CAC7C,GACA,MAAM,UACR;CACF;AACF;AAEA,MAAa,QAA8B,YACzC,OAAO,OAAO,OAAO,OAAO,gBAAgB,GAAG;CAC7C,MAAM;CACN;AACF,CAAC;AAEH,MAAa,WAAyB,UACpC,OAAO,OAAO,OAAO,OAAO,gBAAgB,GAAG;CAC7C,MAAM;CACN;AACF,CAAC;AAEH,MAAa,QAAsB,UACjC,OAAO,OAAO,OAAO,OAAO,gBAAgB,GAAG;CAC7C,MAAM;CACN;AACF,CAAC;AAEH,MAAa,aACX,gBACiC,YAAY,SAAS;AAExD,MAAa,aACX,gBACiC,YAAY,SAAS;AAExD,MAAa,aACX,gBACiC,YAAY,SAAS;;;;;;;;;;;;;;AAsBxD,MAAa,QAQT,SAAS,KACX,IAEE,MACA,YAEA,MAAM,MAAM,IAAI,CAAC,CAAC,KAChB,MAAM,IAAI,YAAY,YAAY,QAAQ,UAAU,QAAQ,OAAO,CAAC,GACpE,MAAM,IAAI,YAAY,YAAY,QAAQ,UAAU,QAAQ,KAAK,CAAC,GAClE,MAAM,IAAI,YAAY,YAAY;CAChC,IAAI,UAAU,YAAY,SAAS,WAAW,GAC5C,OAAO,QAAQ,UAAU,QAAQ,KAAK;CAExC,MAAM,IAAI,MACR,uDACF;AACF,CAAC,GACD,MAAM,UACR,CACJ"}