@confect/core 10.0.0-next.1 → 10.0.0-next.10

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 (61) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/dist/FunctionProvenance.d.ts +74 -3
  3. package/dist/FunctionProvenance.d.ts.map +1 -1
  4. package/dist/FunctionProvenance.js +44 -4
  5. package/dist/FunctionProvenance.js.map +1 -1
  6. package/dist/FunctionSpec.d.ts +42 -9
  7. package/dist/FunctionSpec.d.ts.map +1 -1
  8. package/dist/FunctionSpec.js +17 -4
  9. package/dist/FunctionSpec.js.map +1 -1
  10. package/dist/GenericId.js +2 -3
  11. package/dist/GenericId.js.map +1 -1
  12. package/dist/GroupPath.js +1 -2
  13. package/dist/GroupSpec.js +1 -2
  14. package/dist/GroupSpec.js.map +1 -1
  15. package/dist/Identifier.js +3 -4
  16. package/dist/Identifier.js.map +1 -1
  17. package/dist/Lazy.js +1 -2
  18. package/dist/Lazy.js.map +1 -1
  19. package/dist/PaginationOptions.d.ts +23 -0
  20. package/dist/PaginationOptions.d.ts.map +1 -0
  21. package/dist/PaginationOptions.js +29 -0
  22. package/dist/PaginationOptions.js.map +1 -0
  23. package/dist/PaginationResult.d.ts +1 -0
  24. package/dist/PaginationResult.d.ts.map +1 -1
  25. package/dist/PaginationResult.js +1 -2
  26. package/dist/PaginationResult.js.map +1 -1
  27. package/dist/Ref.d.ts +34 -5
  28. package/dist/Ref.d.ts.map +1 -1
  29. package/dist/Ref.js +51 -13
  30. package/dist/Ref.js.map +1 -1
  31. package/dist/Refs.js +1 -2
  32. package/dist/Refs.js.map +1 -1
  33. package/dist/Registry.js +1 -2
  34. package/dist/Registry.js.map +1 -1
  35. package/dist/RuntimeAndFunctionType.js +1 -2
  36. package/dist/RuntimeAndFunctionType.js.map +1 -1
  37. package/dist/Spec.js +1 -2
  38. package/dist/Spec.js.map +1 -1
  39. package/dist/SystemFields.d.ts.map +1 -1
  40. package/dist/SystemFields.js +2 -3
  41. package/dist/SystemFields.js.map +1 -1
  42. package/dist/Types.d.ts +1 -1
  43. package/dist/Types.d.ts.map +1 -1
  44. package/dist/Types.js +1 -2
  45. package/dist/Types.js.map +1 -1
  46. package/dist/UserIdentity.js +1 -2
  47. package/dist/UserIdentity.js.map +1 -1
  48. package/dist/_virtual/_rolldown/runtime.js +6 -11
  49. package/dist/index.d.ts +1 -0
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +3 -3
  52. package/dist/tsconfig.src.tsbuildinfo +1 -1
  53. package/package.json +11 -10
  54. package/src/FunctionProvenance.ts +147 -4
  55. package/src/FunctionSpec.ts +67 -1
  56. package/src/PaginationOptions.ts +23 -0
  57. package/src/PaginationResult.ts +4 -0
  58. package/src/Ref.ts +90 -25
  59. package/src/SystemFields.ts +2 -5
  60. package/src/Types.ts +5 -1
  61. package/src/index.ts +1 -0
@@ -1,13 +1,16 @@
1
1
  import type { DefaultFunctionArgs } from "convex/server";
2
- import type { Schema } from "effect";
3
2
  import * as Data from "effect/Data";
3
+ import * as Schema from "effect/Schema";
4
4
  import * as Lazy from "./Lazy";
5
+ import * as PaginationOptions from "./PaginationOptions";
6
+ import * as PaginationResult from "./PaginationResult";
5
7
 
6
8
  export type FunctionProvenance = Data.TaggedEnum<{
7
9
  Confect: {
8
10
  args: Schema.Codec<any, any>;
9
11
  returns: Schema.Codec<any, any>;
10
12
  error?: Schema.Codec<any, any>;
13
+ kind: ConfectKind;
11
14
  };
12
15
  Convex: {
13
16
  /** @internal */
@@ -17,15 +20,43 @@ export type FunctionProvenance = Data.TaggedEnum<{
17
20
  };
18
21
  }>;
19
22
 
23
+ /**
24
+ * The declaration shape of a Confect function — orthogonal to both the
25
+ * provenance origin (Confect vs Convex) and the function type
26
+ * (query/mutation/action). A `Standard` function declares its `args` and
27
+ * `returns` schemas directly; a `Paginated` function declares `userArgs` and
28
+ * `item` schemas from which the Convex-facing `args`/`returns` are composed.
29
+ */
30
+ export type ConfectKind = Standard | Paginated;
31
+
32
+ export interface Standard {
33
+ readonly _tag: "Standard";
34
+ }
35
+
36
+ export interface Paginated<
37
+ UserArgs extends AnyUserArgs = AnyUserArgs,
38
+ Item extends Schema.Codec<any, any> = Schema.Codec<any, any>,
39
+ > {
40
+ readonly _tag: "Paginated";
41
+ /** User-declared args — no `paginationOpts`. */
42
+ readonly userArgs: UserArgs;
43
+ /** Page element schema. */
44
+ readonly item: Item;
45
+ /** Mutable array of items — the page decode target. */
46
+ readonly page: Schema.Codec<any, any>;
47
+ }
48
+
20
49
  export interface Confect<
21
50
  Args extends Schema.Codec<any, any>,
22
51
  Returns extends Schema.Codec<any, any>,
23
52
  Error extends Schema.Codec<any, any> = never,
53
+ Kind extends ConfectKind = ConfectKind,
24
54
  > {
25
55
  readonly _tag: "Confect";
26
56
  readonly args: Args;
27
57
  readonly returns: Returns;
28
58
  readonly error?: Error;
59
+ readonly kind: Kind;
29
60
  }
30
61
 
31
62
  export interface AnyConfect extends Confect<
@@ -44,6 +75,8 @@ export interface AnyConvex extends Convex<DefaultFunctionArgs, any> {}
44
75
 
45
76
  export const FunctionProvenance = Data.taggedEnum<FunctionProvenance>();
46
77
 
78
+ const Standard: Standard = { _tag: "Standard" };
79
+
47
80
  /**
48
81
  * Build a `Confect` provenance from lazy schema thunks. `args`, `returns`,
49
82
  * and `error` are exposed as sync lazy memoised getters (via {@link Lazy.defineProperty})
@@ -68,8 +101,8 @@ export const Confect = <
68
101
  args: () => Args,
69
102
  returns: () => Returns,
70
103
  error?: () => Error,
71
- ): Confect<Args, Returns, Error> => {
72
- const provenance = { _tag: "Confect" as const };
104
+ ): Confect<Args, Returns, Error, Standard> => {
105
+ const provenance = { _tag: "Confect" as const, kind: Standard };
73
106
 
74
107
  Lazy.defineProperty(provenance, "args", args);
75
108
  Lazy.defineProperty(provenance, "returns", returns);
@@ -77,7 +110,117 @@ export const Confect = <
77
110
  Lazy.defineProperty(provenance, "error", error);
78
111
  }
79
112
 
80
- return provenance as Confect<Args, Returns, Error>;
113
+ return provenance as Confect<Args, Returns, Error, Standard>;
114
+ };
115
+
116
+ /**
117
+ * Any struct-shaped, context-free schema usable as a paginated query's user
118
+ * args. A structural bound rather than `Schema.Struct<Schema.Struct.Fields>`
119
+ * because `Schema.Struct` is not covariant in its fields parameter — concrete
120
+ * structs do not extend `Schema.Struct<Schema.Struct.Fields>`.
121
+ */
122
+ // eslint-disable-next-line import/namespace -- oxlint's namespace resolution misses type-only exports, and `Schema` is an interface/namespace
123
+ export interface AnyUserArgs extends Schema.Codec<any, any> {
124
+ readonly fields: Schema.Struct.Fields;
125
+ }
126
+
127
+ /**
128
+ * The composed args schema of a paginated query: the user-declared fields
129
+ * plus the `paginationOpts` field managed by Convex's pagination protocol.
130
+ *
131
+ * The `extends infer ... extends` conditional lets TypeScript accept the
132
+ * composed struct where `Schema.Codec<any, any>` is required even while
133
+ * `UserArgs` is an unresolved type parameter; for concrete user args it
134
+ * evaluates away entirely.
135
+ */
136
+ export type PaginatedArgs<UserArgs extends AnyUserArgs> =
137
+ Schema.Struct<
138
+ UserArgs["fields"] & {
139
+ paginationOpts: typeof PaginationOptions.PaginationOptions;
140
+ }
141
+ > extends infer ComposedArgs extends Schema.Codec<any, any>
142
+ ? ComposedArgs
143
+ : never;
144
+
145
+ /**
146
+ * The composed returns schema of a paginated query: a `PaginationResult` of
147
+ * the item schema. Same deferred-conditional device as {@link PaginatedArgs}.
148
+ */
149
+ export type PaginatedReturns<Item extends Schema.Codec<any, any>> =
150
+ PaginationResult.PaginationResult<Item> extends infer ComposedReturns extends
151
+ Schema.Codec<any, any>
152
+ ? ComposedReturns
153
+ : never;
154
+
155
+ export interface ConfectPaginated<
156
+ UserArgs extends AnyUserArgs,
157
+ Item extends Schema.Codec<any, any>,
158
+ Error extends Schema.Codec<any, any> = never,
159
+ > extends Confect<
160
+ PaginatedArgs<UserArgs>,
161
+ PaginatedReturns<Item>,
162
+ Error,
163
+ Paginated<UserArgs, Item>
164
+ > {}
165
+
166
+ export interface AnyConfectPaginated extends ConfectPaginated<
167
+ AnyUserArgs,
168
+ Schema.Codec<any, any>,
169
+ Schema.Codec<any, any>
170
+ > {}
171
+
172
+ /**
173
+ * Build the provenance of a paginated query from lazy schema thunks, with the
174
+ * same laziness contract as {@link Confect}. The user-facing schemas live on
175
+ * the `Paginated` kind (`kind.userArgs`, `kind.item`, `kind.page`) — the kind
176
+ * container is built eagerly (it is cheap) while the schemas inside it stay
177
+ * lazy. The composed Convex-facing `args`/`returns` are derived lazily from
178
+ * them: `args` spreads the user fields plus `paginationOpts`, and `returns`
179
+ * wraps the item in `PaginationResult`. Composition living here means the
180
+ * composed schemas can never drift from the stored user schemas.
181
+ */
182
+ export const ConfectPaginated = <
183
+ UserArgs extends AnyUserArgs,
184
+ Item extends Schema.Codec<any, any>,
185
+ Error extends Schema.Codec<any, any> = never,
186
+ >(
187
+ userArgs: () => UserArgs,
188
+ item: () => Item,
189
+ error?: () => Error,
190
+ ): ConfectPaginated<UserArgs, Item, Error> => {
191
+ const kind = { _tag: "Paginated" as const };
192
+ const paginatedKind = kind as Paginated<UserArgs, Item>;
193
+
194
+ Lazy.defineProperty(kind, "userArgs", userArgs);
195
+ Lazy.defineProperty(kind, "item", item);
196
+ Lazy.defineProperty(kind, "page", () =>
197
+ Schema.mutable(Schema.Array(paginatedKind.item)),
198
+ );
199
+
200
+ const provenance = { _tag: "Confect" as const, kind: paginatedKind };
201
+ const self = provenance as ConfectPaginated<UserArgs, Item, Error>;
202
+
203
+ Lazy.defineProperty(provenance, "args", () => {
204
+ const fields = paginatedKind.userArgs.fields;
205
+ if ("paginationOpts" in fields) {
206
+ throw new globalThis.Error(
207
+ "A paginated query's args schema must not declare `paginationOpts` — " +
208
+ "it is added automatically from the `PaginationOptions` schema",
209
+ );
210
+ }
211
+ return Schema.Struct({
212
+ ...fields,
213
+ paginationOpts: PaginationOptions.PaginationOptions,
214
+ });
215
+ });
216
+ Lazy.defineProperty(provenance, "returns", () =>
217
+ PaginationResult.PaginationResult(paginatedKind.item),
218
+ );
219
+ if (error !== undefined) {
220
+ Lazy.defineProperty(provenance, "error", error);
221
+ }
222
+
223
+ return self;
81
224
  };
82
225
 
83
226
  export const Convex = <_Args extends DefaultFunctionArgs, _Returns>() =>
@@ -5,7 +5,7 @@ import type {
5
5
  RegisteredMutation,
6
6
  RegisteredQuery,
7
7
  } from "convex/server";
8
- import type { Schema } from "effect";
8
+ import * as Schema from "effect/Schema";
9
9
  import * as Predicate from "effect/Predicate";
10
10
  import * as FunctionProvenance from "./FunctionProvenance";
11
11
  import { validateConfectFunctionIdentifier } from "./Identifier";
@@ -244,11 +244,77 @@ const make =
244
244
  });
245
245
  };
246
246
 
247
+ /**
248
+ * `Schema.Struct` fields that must not declare `paginationOpts`. Used to
249
+ * reject a user args schema that redeclares the field the paginated
250
+ * constructors add themselves; the check reports at the `args` thunk with an
251
+ * unsatisfiable type when violated.
252
+ */
253
+ type ForbidPaginationOpts<UserArgs extends FunctionProvenance.AnyUserArgs> =
254
+ "paginationOpts" extends keyof UserArgs["fields"]
255
+ ? { readonly fields: { readonly paginationOpts: never } }
256
+ : unknown;
257
+
258
+ const makePaginated =
259
+ <
260
+ RuntimeAndFunctionType_ extends
261
+ RuntimeAndFunctionType.RuntimeAndFunctionType,
262
+ FunctionVisibility_ extends FunctionVisibility,
263
+ >(
264
+ runtimeAndFunctionType: RuntimeAndFunctionType_,
265
+ functionVisibility: FunctionVisibility_,
266
+ ) =>
267
+ <
268
+ const Name_ extends string,
269
+ Item_ extends Schema.Codec<any, any>,
270
+ UserArgs_ extends FunctionProvenance.AnyUserArgs = Schema.Struct<{}>,
271
+ Error_ extends Schema.Codec<any, any> = never,
272
+ >({
273
+ name,
274
+ args,
275
+ item,
276
+ error,
277
+ }: {
278
+ name: Name_;
279
+ /** User-declared args, without `paginationOpts` — it is added automatically. */
280
+ args?: (() => UserArgs_) & ForbidPaginationOpts<UserArgs_>;
281
+ /** The page element schema. */
282
+ item: () => Item_;
283
+ error?: () => Error_;
284
+ }): FunctionSpec<
285
+ RuntimeAndFunctionType_,
286
+ FunctionVisibility_,
287
+ Name_,
288
+ FunctionProvenance.ConfectPaginated<UserArgs_, Item_, Error_>
289
+ > => {
290
+ validateConfectFunctionIdentifier(name);
291
+
292
+ return Object.assign(Object.create(Proto), {
293
+ runtimeAndFunctionType,
294
+ functionVisibility,
295
+ name,
296
+ functionProvenance: FunctionProvenance.ConfectPaginated(
297
+ // When `args` is omitted, `UserArgs_` is its `Schema.Struct<{}>` default.
298
+ args ?? ((() => Schema.Struct({})) as unknown as () => UserArgs_),
299
+ item,
300
+ error,
301
+ ),
302
+ });
303
+ };
304
+
247
305
  export const publicQuery = make(RuntimeAndFunctionType.ConvexQuery, "public");
248
306
  export const internalQuery = make(
249
307
  RuntimeAndFunctionType.ConvexQuery,
250
308
  "internal",
251
309
  );
310
+ export const publicPaginatedQuery = makePaginated(
311
+ RuntimeAndFunctionType.ConvexQuery,
312
+ "public",
313
+ );
314
+ export const internalPaginatedQuery = makePaginated(
315
+ RuntimeAndFunctionType.ConvexQuery,
316
+ "internal",
317
+ );
252
318
  export const publicMutation = make(
253
319
  RuntimeAndFunctionType.ConvexMutation,
254
320
  "public",
@@ -0,0 +1,23 @@
1
+ import * as Schema from "effect/Schema";
2
+
3
+ /**
4
+ * Schema for the `paginationOpts` argument that every paginated query
5
+ * receives. Mirrors `paginationOptsValidator` from `convex/server`.
6
+ *
7
+ * Use this as the `paginationOpts` field of a paginated query's args schema.
8
+ * Beyond `numItems` and `cursor`, Convex's pagination protocol sends the
9
+ * optional fields (`endCursor`, `id`, `maximumRowsRead`, `maximumBytesRead`)
10
+ * with real requests — most notably `usePaginatedQuery` from `convex/react`
11
+ * always includes `id`, and includes `endCursor` when splitting pages.
12
+ * Declaring them is required for the generated Convex argument validator to
13
+ * accept those requests and for the fields to survive decoding and reach
14
+ * `paginate`.
15
+ */
16
+ export const PaginationOptions = Schema.Struct({
17
+ numItems: Schema.Number,
18
+ cursor: Schema.Union([Schema.String, Schema.Null]),
19
+ endCursor: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])),
20
+ id: Schema.optionalKey(Schema.Number),
21
+ maximumRowsRead: Schema.optionalKey(Schema.Number),
22
+ maximumBytesRead: Schema.optionalKey(Schema.Number),
23
+ });
@@ -1,5 +1,9 @@
1
1
  import * as Schema from "effect/Schema";
2
2
 
3
+ export type PaginationResult<Doc extends Schema.Codec<any, any>> = ReturnType<
4
+ typeof PaginationResult<Doc>
5
+ >;
6
+
3
7
  export const PaginationResult = <Doc extends Schema.Codec<any, any>>(
4
8
  Doc: Doc,
5
9
  ) =>
package/src/Ref.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import type {
2
2
  FunctionReference as ConvexFunctionReference,
3
3
  FunctionVisibility,
4
+ PaginationOptions,
5
+ PaginationResult,
4
6
  } from "convex/server";
5
7
  import { makeFunctionReference } from "convex/server";
6
8
  import type { Value } from "convex/values";
@@ -44,6 +46,17 @@ export interface AnyQuery extends Ref<
44
46
  any
45
47
  > {}
46
48
 
49
+ export interface AnyPublicPaginatedQuery extends Ref<
50
+ RuntimeAndFunctionType.AnyQuery,
51
+ "public",
52
+ {
53
+ [key: string]: any;
54
+ paginationOpts: PaginationOptions;
55
+ },
56
+ PaginationResult<any>,
57
+ any
58
+ > {}
59
+
47
60
  export interface AnyMutation extends Ref<
48
61
  RuntimeAndFunctionType.AnyMutation,
49
62
  FunctionVisibility,
@@ -315,7 +328,7 @@ export const decodeErrorOrElse =
315
328
  <Ref_ extends Any, E>(ref: Ref_, mapUnknownError: (error: unknown) => E) =>
316
329
  (error: unknown): Error<Ref_> | E => {
317
330
  if (isConvexError(error)) {
318
- const decoded = decodeErrorSync(ref, error.data);
331
+ const decoded = decodeErrorOption(ref, error.data);
319
332
  if (Option.isSome(decoded)) {
320
333
  return decoded.value;
321
334
  }
@@ -350,44 +363,96 @@ export const decodeError = <Ref_ extends Any>(
350
363
  );
351
364
 
352
365
  /**
353
- * Synchronous counterpart to `decodeError`. Throws on schema decode failure;
354
- * returns `None` when the ref doesn't declare a typed error.
366
+ * Synchronous counterpart to `decodeError`. Returns `None` when the value is
367
+ * not this ref's typed error — either because the ref declares no `error`
368
+ * schema, or because `encodedError` doesn't match the one it declares.
369
+ *
370
+ * The second case is reachable in normal operation: Convex raises its own
371
+ * `ConvexError`s (an `InvalidCursor` pagination error, for instance), and
372
+ * those never match a user-declared error schema. Callers pair this with a
373
+ * fallback that surfaces the original error, so failing to decode must not
374
+ * throw — a `ParseError` here would replace the real error with an opaque one
375
+ * and lose the only useful diagnostic. Hence the `Option` suffix rather than
376
+ * `Sync`, matching `Schema.decodeUnknownOption`: the sibling `*Sync` helpers
377
+ * in this module all throw on a parse failure, and this one deliberately
378
+ * doesn't.
355
379
  */
356
- export const decodeErrorSync = <Ref_ extends Any>(
380
+ export const decodeErrorOption = <Ref_ extends Any>(
357
381
  ref: Ref_,
358
382
  encodedError: unknown,
359
383
  ): Option.Option<Error<Ref_>> =>
360
384
  Match.value(ref.functionSpec.functionProvenance).pipe(
361
385
  Match.tag("Confect", (confectFunctionProvenance) =>
362
386
  "error" in confectFunctionProvenance
363
- ? Option.some(
364
- Schema.decodeUnknownSync(confectFunctionProvenance.error)(
365
- encodedError,
366
- ) as Error<Ref_>,
367
- )
387
+ ? (Schema.decodeUnknownOption(confectFunctionProvenance.error)(
388
+ encodedError,
389
+ ) as Option.Option<Error<Ref_>>)
368
390
  : Option.none<Error<Ref_>>(),
369
391
  ),
370
392
  Match.tag("Convex", () => Option.none<Error<Ref_>>()),
371
393
  Match.exhaustive,
372
394
  );
373
395
 
374
- export const maybeDecodeErrorSync = <Ref_ extends Any>(
396
+ const missingPaginatedProvenanceError = (ref: Any) =>
397
+ new globalThis.Error(
398
+ `Paginated query ref "${getConvexFunctionName(ref)}" was not built with ` +
399
+ "`FunctionSpec.publicPaginatedQuery` (or `FunctionSpec.internalPaginatedQuery`). " +
400
+ "Paginated encoding and decoding require the user-args and item schemas " +
401
+ "those constructors store. Define the function as, e.g.:\n\n" +
402
+ " FunctionSpec.publicPaginatedQuery({\n" +
403
+ ' name: "...",\n' +
404
+ " args: () => Schema.Struct({ ... }), // optional; without paginationOpts\n" +
405
+ " item: () => ItemSchema,\n" +
406
+ " })",
407
+ );
408
+
409
+ /**
410
+ * Encode the args of a paginated query ref via its user-args schema —
411
+ * `paginationOpts` is excluded, since the pagination protocol fields are
412
+ * managed by the client (e.g. `usePaginatedQuery` from `convex/react`), not by
413
+ * the caller. Requires a ref built with `FunctionSpec.publicPaginatedQuery`
414
+ * (or `internalPaginatedQuery`).
415
+ */
416
+ export const encodePaginatedQueryArgsSync = <
417
+ Ref_ extends AnyPublicPaginatedQuery,
418
+ >(
375
419
  ref: Ref_,
376
- error: unknown,
420
+ args: Omit<Args<Ref_>, "paginationOpts">,
377
421
  ): unknown =>
378
- isConvexError(error)
379
- ? Match.value(ref.functionSpec.functionProvenance).pipe(
380
- Match.tag("Confect", (confectFunctionProvenance) =>
381
- "error" in confectFunctionProvenance
382
- ? Schema.decodeUnknownSync(confectFunctionProvenance.error)(
383
- error.data,
384
- )
385
- : error,
386
- ),
387
- Match.tag("Convex", () => error),
388
- Match.exhaustive,
389
- )
390
- : error;
422
+ Match.value(ref.functionSpec.functionProvenance).pipe(
423
+ Match.tag("Confect", (confectFunctionProvenance) => {
424
+ if (confectFunctionProvenance.kind._tag !== "Paginated") {
425
+ throw missingPaginatedProvenanceError(ref);
426
+ }
427
+ return Schema.encodeUnknownSync(confectFunctionProvenance.kind.userArgs)(
428
+ args,
429
+ );
430
+ }),
431
+ Match.tag("Convex", () => args),
432
+ Match.exhaustive,
433
+ );
434
+
435
+ /**
436
+ * Decode a page of a paginated query's results via the ref's item schema.
437
+ * Requires a ref built with `FunctionSpec.publicPaginatedQuery` (or
438
+ * `internalPaginatedQuery`).
439
+ */
440
+ export const decodePaginationPageSync = <Ref_ extends AnyPublicPaginatedQuery>(
441
+ ref: Ref_,
442
+ encodedPage: unknown,
443
+ ): Returns<Ref_>["page"] =>
444
+ Match.value(ref.functionSpec.functionProvenance).pipe(
445
+ Match.tag("Confect", (confectFunctionProvenance) => {
446
+ if (confectFunctionProvenance.kind._tag !== "Paginated") {
447
+ throw missingPaginatedProvenanceError(ref);
448
+ }
449
+ return Schema.decodeUnknownSync(confectFunctionProvenance.kind.page)(
450
+ encodedPage,
451
+ );
452
+ }),
453
+ Match.tag("Convex", () => encodedPage),
454
+ Match.exhaustive,
455
+ ) as Returns<Ref_>["page"];
391
456
 
392
457
  /**
393
458
  * Encode args via the ref's args schema, invoke `call`, decode returns via the
@@ -416,7 +481,7 @@ export const runWithCodec = <Ref_ extends Any, E = never>(
416
481
  try: () => Promise.resolve(call(functionReference, encodedArgs)),
417
482
  catch: (error): Error<Ref_> | E => {
418
483
  if (isConvexError(error)) {
419
- const decoded = decodeErrorSync(ref, error.data);
484
+ const decoded = decodeErrorOption(ref, error.data);
420
485
  if (Option.isSome(decoded)) {
421
486
  return decoded.value;
422
487
  }
@@ -191,9 +191,7 @@ export const extendWithSystemFields = <
191
191
  if (
192
192
  s.ast.encoding === undefined &&
193
193
  SchemaAST.isUnion(s.ast) &&
194
- Array.isArray(
195
- (s as Partial<Schema.Union<ReadonlyArray<Schema.Top>>>).members,
196
- )
194
+ Array.isArray((s as { readonly members?: unknown }).members)
197
195
  ) {
198
196
  return Schema.Union(
199
197
  Array.map(
@@ -205,8 +203,7 @@ export const extendWithSystemFields = <
205
203
  if (
206
204
  s.ast.encoding === undefined &&
207
205
  SchemaAST.isObjects(s.ast) &&
208
- typeof (s as Partial<Schema.Struct<Schema.Struct.Fields>>).mapFields ===
209
- "function"
206
+ typeof (s as { readonly mapFields?: unknown }).mapFields === "function"
210
207
  ) {
211
208
  return Schema.fieldsAssign(system)(
212
209
  s as Schema.Struct<Schema.Struct.Fields>,
package/src/Types.ts CHANGED
@@ -66,7 +66,11 @@ export type DeepMutable<T> =
66
66
  ? Set<DeepMutable<V>>
67
67
  : [keyof T] extends [never]
68
68
  ? T
69
- : { -readonly [K in keyof T]: DeepMutable<T[K]> };
69
+ : {
70
+ -readonly [K in keyof T]: IsOptional<T, K> extends true
71
+ ? DeepMutable<Exclude<T[K], undefined>>
72
+ : DeepMutable<T[K]>;
73
+ };
70
74
 
71
75
  export type TypeError<Message extends string, T = never> = [Message, T];
72
76
 
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ export * as GroupPath from "./GroupPath";
5
5
  export * as GroupSpec from "./GroupSpec";
6
6
  export * as Identifier from "./Identifier";
7
7
  export * as Lazy from "./Lazy";
8
+ export * as PaginationOptions from "./PaginationOptions";
8
9
  export * as PaginationResult from "./PaginationResult";
9
10
  export * as Ref from "./Ref";
10
11
  export * as Refs from "./Refs";