@confect/core 10.0.0-next.22 → 10.0.0-next.23

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 (69) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/FunctionProvenance.d.ts +34 -25
  3. package/dist/FunctionProvenance.d.ts.map +1 -1
  4. package/dist/FunctionProvenance.js +13 -11
  5. package/dist/FunctionProvenance.js.map +1 -1
  6. package/dist/FunctionSpec.d.ts +12 -8
  7. package/dist/FunctionSpec.d.ts.map +1 -1
  8. package/dist/FunctionSpec.js.map +1 -1
  9. package/dist/GroupPath.d.ts +5 -6
  10. package/dist/GroupPath.d.ts.map +1 -1
  11. package/dist/GroupPath.js.map +1 -1
  12. package/dist/GroupSpec.d.ts +5 -2
  13. package/dist/GroupSpec.d.ts.map +1 -1
  14. package/dist/GroupSpec.js +2 -2
  15. package/dist/GroupSpec.js.map +1 -1
  16. package/dist/Identifier.d.ts +5 -4
  17. package/dist/Identifier.d.ts.map +1 -1
  18. package/dist/Identifier.js +5 -4
  19. package/dist/Identifier.js.map +1 -1
  20. package/dist/Lazy.d.ts +11 -12
  21. package/dist/Lazy.d.ts.map +1 -1
  22. package/dist/Lazy.js +11 -12
  23. package/dist/Lazy.js.map +1 -1
  24. package/dist/MiddlewareSpec.d.ts +27 -25
  25. package/dist/MiddlewareSpec.d.ts.map +1 -1
  26. package/dist/MiddlewareSpec.js +8 -4
  27. package/dist/MiddlewareSpec.js.map +1 -1
  28. package/dist/PaginationError.d.ts +9 -3
  29. package/dist/PaginationError.d.ts.map +1 -1
  30. package/dist/PaginationError.js +9 -3
  31. package/dist/PaginationError.js.map +1 -1
  32. package/dist/PaginationOptions.d.ts +2 -2
  33. package/dist/PaginationOptions.js +2 -2
  34. package/dist/PaginationOptions.js.map +1 -1
  35. package/dist/Ref.d.ts +38 -32
  36. package/dist/Ref.d.ts.map +1 -1
  37. package/dist/Ref.js +25 -25
  38. package/dist/Ref.js.map +1 -1
  39. package/dist/Refs.d.ts +1 -1
  40. package/dist/Refs.d.ts.map +1 -1
  41. package/dist/Refs.js +2 -1
  42. package/dist/Refs.js.map +1 -1
  43. package/dist/Spec.d.ts +14 -11
  44. package/dist/Spec.d.ts.map +1 -1
  45. package/dist/Spec.js +13 -8
  46. package/dist/Spec.js.map +1 -1
  47. package/dist/SystemFields.d.ts +14 -12
  48. package/dist/SystemFields.d.ts.map +1 -1
  49. package/dist/SystemFields.js +8 -6
  50. package/dist/SystemFields.js.map +1 -1
  51. package/dist/Table.d.ts +1 -0
  52. package/dist/Table.d.ts.map +1 -1
  53. package/dist/Table.js.map +1 -1
  54. package/dist/index.js +1 -1
  55. package/package.json +3 -2
  56. package/src/FunctionProvenance.ts +34 -25
  57. package/src/FunctionSpec.ts +12 -8
  58. package/src/GroupPath.ts +5 -6
  59. package/src/GroupSpec.ts +9 -5
  60. package/src/Identifier.ts +5 -4
  61. package/src/Lazy.ts +11 -12
  62. package/src/MiddlewareSpec.ts +27 -25
  63. package/src/PaginationError.ts +9 -3
  64. package/src/PaginationOptions.ts +2 -2
  65. package/src/Ref.ts +38 -32
  66. package/src/Refs.ts +2 -2
  67. package/src/Spec.ts +49 -38
  68. package/src/SystemFields.ts +14 -12
  69. package/src/Table.ts +1 -0
@@ -38,9 +38,8 @@ export interface SuccessValue {
38
38
 
39
39
  /**
40
40
  * The wrap-style middleware implementation shape: receives the downstream
41
- * effect (the remaining middleware plus the function handler) and the
42
- * covered invocation's metadata, and returns the effect that runs in its
43
- * place.
41
+ * effect (the remaining middleware plus the function handler) and the covered
42
+ * invocation's metadata, and returns the effect that runs in its place.
44
43
  *
45
44
  * Mirrors `RpcMiddleware.RpcMiddleware` in Effect.
46
45
  */
@@ -68,8 +67,8 @@ export interface AnyMiddlewareImpl {
68
67
  }
69
68
 
70
69
  /**
71
- * The class shape produced by {@link MiddlewareSpec}. Only the static side is ever
72
- * used—the class is a value-level carrier for the middleware's key, its
70
+ * The class shape produced by {@link MiddlewareSpec}. Only the static side is
71
+ * ever used—the class is a value-level carrier for the middleware's key, its
73
72
  * declared functionTypes, and its (lazily-evaluated) error schema, plus the
74
73
  * type-level `Provides`/`Error` metadata. It is deliberately not a
75
74
  * `Context.Tag`: implementations are registered through the group `Registry`
@@ -133,8 +132,8 @@ export type Provides<MiddlewareSpec_ extends AnyMiddlewareSpec> =
133
132
  : never;
134
133
 
135
134
  /**
136
- * The services a middleware's implementation may consume from middleware
137
- * that runs earlier in the same chain (type-level only, like `provides`).
135
+ * The services a middleware's implementation may consume from middleware that
136
+ * runs earlier in the same chain (type-level only, like `provides`).
138
137
  */
139
138
  export type Requires<MiddlewareSpec_ extends AnyMiddlewareSpec> =
140
139
  MiddlewareSpec_ extends AnyMiddlewareSpec
@@ -165,16 +164,20 @@ export type FunctionTypes<MiddlewareSpec_ extends AnyMiddlewareSpec> =
165
164
  * encode through, and the function types it may attach to.
166
165
  *
167
166
  * ```ts
168
- * class RequireUser extends MiddlewareSpec.MiddlewareSpec<RequireUser, {
169
- * provides: CurrentUser
170
- * }>()("RequireUser", {
167
+ * class RequireUser extends MiddlewareSpec.MiddlewareSpec<
168
+ * RequireUser,
169
+ * {
170
+ * provides: CurrentUser;
171
+ * }
172
+ * >()("RequireUser", {
171
173
  * error: () => NotSignedIn,
172
174
  * functionTypes: { query: true, mutation: true, action: false },
173
175
  * }) {}
174
176
  * ```
175
177
  *
176
178
  * The implementation is server-only and supplied separately via
177
- * `MiddlewareImpl.make` (or `makeByFunctionType`/`provides`) in `@confect/server`.
179
+ * `MiddlewareImpl.make` (or `makeByFunctionType`/`provides`) in
180
+ * `@confect/server`.
178
181
  */
179
182
  export const MiddlewareSpec =
180
183
  <Self, Config extends { provides?: any; requires?: any } = {}>() =>
@@ -265,10 +268,9 @@ type FunctionTypeOf<FunctionSpec_ extends FunctionSpec.AnyWithProps> =
265
268
  type ValidationResult<Errors> = [Errors] extends [never] ? unknown : Errors;
266
269
 
267
270
  /**
268
- * A matching-type Convex-provenance function is rejected rather than
269
- * silently skipped: its raw handler passes through Confect untouched, so
270
- * the middleware could not actually cover it, and skipping it would be a
271
- * policy hole.
271
+ * A matching-type Convex-provenance function is rejected rather than silently
272
+ * skipped: its raw handler passes through Confect untouched, so the middleware
273
+ * could not actually cover it, and skipping it would be a policy hole.
272
274
  */
273
275
  export type ValidateFunction<
274
276
  FunctionSpec_ extends FunctionSpec.AnyWithProps,
@@ -295,8 +297,8 @@ export type ValidateFunction<
295
297
  : never;
296
298
 
297
299
  /**
298
- * Attachment order is chain order, so requiring `requires` to be satisfied
299
- * by already-attached middleware is exactly requiring the provider to run
300
+ * Attachment order is chain order, so requiring `requires` to be satisfied by
301
+ * already-attached middleware is exactly requiring the provider to run
300
302
  * earlier.
301
303
  */
302
304
  export type ValidateAttach<
@@ -344,14 +346,14 @@ type GroupOverlap<
344
346
  : never;
345
347
 
346
348
  /**
347
- * The parameter-type validation applied to the group spec at
348
- * `GroupImpl.make`: every function's attached middleware must have its
349
- * `requires` services provided by some middleware covering that function
350
- * (the group's or the function's own). Checked here—with the group fully
351
- * assembled—rather than at the spec builders, because a function-level
352
- * middleware's `requires` may legitimately be satisfied by a group
353
- * middleware the function spec never sees, and group attachment is
354
- * declaratively order-independent with respect to `addFunction`.
349
+ * The parameter-type validation applied to the group spec at `GroupImpl.make`:
350
+ * every function's attached middleware must have its `requires` services
351
+ * provided by some middleware covering that function (the group's or the
352
+ * function's own). Checked here—with the group fully assembled—rather than at
353
+ * the spec builders, because a function-level middleware's `requires` may
354
+ * legitimately be satisfied by a group middleware the function spec never sees,
355
+ * and group attachment is declaratively order-independent with respect to
356
+ * `addFunction`.
355
357
  */
356
358
  export type ValidateImplRequires<
357
359
  Functions_ extends FunctionSpec.AnyWithProps,
@@ -4,7 +4,9 @@ import * as Match from "effect/Match";
4
4
  import * as Option from "effect/Option";
5
5
  import * as Schema from "effect/Schema";
6
6
 
7
- /** A Convex pagination cursor that no longer describes the current query. */
7
+ /**
8
+ * A Convex pagination cursor that no longer describes the current query.
9
+ */
8
10
  export class InvalidCursor extends Schema.TaggedError<InvalidCursor>()(
9
11
  "InvalidCursor",
10
12
  {
@@ -40,7 +42,9 @@ const fromErrorMessage = (
40
42
  ? Option.some(new InvalidCursor({ cause: error }))
41
43
  : Option.none();
42
44
 
43
- /** Recognizes an invalid-cursor error emitted by a Convex query. */
45
+ /**
46
+ * Recognizes an invalid-cursor error emitted by a Convex query.
47
+ */
44
48
  export const fromConvexQueryError = (
45
49
  error: unknown,
46
50
  ): Option.Option<InvalidCursor> =>
@@ -59,7 +63,9 @@ export const fromConvexQueryError = (
59
63
  Match.exhaustive,
60
64
  );
61
65
 
62
- /** Recognizes the error data attached to Convex's invalid-cursor error. */
66
+ /**
67
+ * Recognizes the error data attached to Convex's invalid-cursor error.
68
+ */
63
69
  export const fromConvexErrorData = (
64
70
  errorData: unknown,
65
71
  ): Option.Option<InvalidCursor> =>
@@ -1,8 +1,8 @@
1
1
  import * as Schema from "effect/Schema";
2
2
 
3
3
  /**
4
- * Schema for the `paginationOpts` argument that every paginated query
5
- * receives. Mirrors `paginationOptsValidator` from `convex/server`.
4
+ * Schema for the `paginationOpts` argument that every paginated query receives.
5
+ * Mirrors `paginationOptsValidator` from `convex/server`.
6
6
  *
7
7
  * Use this as the `paginationOpts` field of a paginated query's args schema.
8
8
  * Beyond `numItems` and `cursor`, Convex's pagination protocol sends the
package/src/Ref.ts CHANGED
@@ -36,8 +36,8 @@ export interface Base<
36
36
 
37
37
  /**
38
38
  * A reference to a single Convex function, as callers see it: the wire name
39
- * plus the data needed to encode args, decode returns, and decode typed
40
- * errors. A ref is one of two shapes, keyed by the spec's provenance.
39
+ * plus the data needed to encode args, decode returns, and decode typed errors.
40
+ * A ref is one of two shapes, keyed by the spec's provenance.
41
41
  */
42
42
  export type Ref<
43
43
  RuntimeAndFunctionType_ extends RuntimeAndFunctionType.RuntimeAndFunctionType,
@@ -81,8 +81,8 @@ export type ConfectRef<
81
81
  /**
82
82
  * Internal form used while mapping a spec to a ref. Supplying the already
83
83
  * derived value types avoids repeatedly expanding `Schema.Struct` for every
84
- * leaf in a generated ref tree; the public `ConfectRef` alias still derives
85
- * the same values from its fields and schemas.
84
+ * leaf in a generated ref tree; the public `ConfectRef` alias still derives the
85
+ * same values from its fields and schemas.
86
86
  */
87
87
  interface ConfectRefWithTypes<
88
88
  RuntimeAndFunctionType_ extends RuntimeAndFunctionType.RuntimeAndFunctionType,
@@ -125,7 +125,9 @@ export interface ConvexRef<
125
125
 
126
126
  export type Any = Ref<any, any, any, any, any>;
127
127
 
128
- /** Erased Confect-provenance ref used by provenance-specific APIs. */
128
+ /**
129
+ * Erased Confect-provenance ref used by provenance-specific APIs.
130
+ */
129
131
  export type AnyConfect = Extract<Any, { readonly _tag: "Confect" }>;
130
132
 
131
133
  export type AnyInternal = Ref<any, "internal", any, any, any>;
@@ -228,7 +230,9 @@ export type Args<Ref_> = Ref_ extends { readonly "~Args": infer Args_ }
228
230
  ? Args_
229
231
  : never;
230
232
 
231
- /** The field map captured by a Confect-provenance ref. */
233
+ /**
234
+ * The field map captured by a Confect-provenance ref.
235
+ */
232
236
  export type ArgsFields<Ref_> = Ref_ extends {
233
237
  readonly _tag: "Confect";
234
238
  readonly args: {
@@ -238,7 +242,9 @@ export type ArgsFields<Ref_> = Ref_ extends {
238
242
  ? ArgsFields_
239
243
  : never;
240
244
 
241
- /** The assembled args schema carried by a Confect-provenance ref. */
245
+ /**
246
+ * The assembled args schema carried by a Confect-provenance ref.
247
+ */
242
248
  export type ArgsSchema<Ref_> = Ref_ extends {
243
249
  readonly _tag: "Confect";
244
250
  readonly args: infer ArgsSchema_ extends FunctionProvenance.AnyArgsSchema;
@@ -481,11 +487,11 @@ export const isConvexError = (error: unknown): error is ConvexError<Value> =>
481
487
  /**
482
488
  * Build a callback-style handler that decodes the ref's typed error from a
483
489
  * caught `ConvexError`, or else forwards the value to `mapUnknownError`. The
484
- * fallback is also invoked when the input *is* a `ConvexError` but the ref
485
- * doesn't declare a typed-error schema—by definition such a value falls
486
- * outside the ref's error contract. Useful when adapting non-Effect APIs (e.g.
487
- * emitter callbacks for streamed subscriptions) to the same error semantics
488
- * that `runWithCodec` provides.
490
+ * fallback is also invoked when the input _is_ a `ConvexError` but the ref
491
+ * doesn't declare a typed-error schema—by definition such a value falls outside
492
+ * the ref's error contract. Useful when adapting non-Effect APIs (e.g. emitter
493
+ * callbacks for streamed subscriptions) to the same error semantics that
494
+ * `runWithCodec` provides.
489
495
  */
490
496
  export const decodeErrorOrElse =
491
497
  <Ref_ extends Any, E>(ref: Ref_, mapUnknownError: (error: unknown) => E) =>
@@ -519,13 +525,13 @@ const errorSchemaOf = (ref: Any): Option.Option<Schema.Codec<any, any>> =>
519
525
  );
520
526
 
521
527
  /**
522
- * Decode `encodedError` against the ref's error schema—the function's
523
- * declared `error` schema unioned with its covering middlewares' error
524
- * schemas. Returns `None` if the ref declares no typed error at all (Confect
525
- * ref without an `error` schema and without failing middleware, or a
526
- * Convex-provenance ref)—by definition there's nothing to decode the value
527
- * into, and the caller is responsible for deciding what to do (typically:
528
- * surface the original value as a defect).
528
+ * Decode `encodedError` against the ref's error schema—the function's declared
529
+ * `error` schema unioned with its covering middlewares' error schemas. Returns
530
+ * `None` if the ref declares no typed error at all (Confect ref without an
531
+ * `error` schema and without failing middleware, or a Convex-provenance ref)—by
532
+ * definition there's nothing to decode the value into, and the caller is
533
+ * responsible for deciding what to do (typically: surface the original value as
534
+ * a defect).
529
535
  */
530
536
  export const decodeError = <Ref_ extends Any>(
531
537
  ref: Ref_,
@@ -541,18 +547,17 @@ export const decodeError = <Ref_ extends Any>(
541
547
 
542
548
  /**
543
549
  * Synchronous counterpart to `decodeError`. Returns `None` when the value is
544
- * not this ref's typed error—either because the ref declares no `error`
545
- * schema, or because `encodedError` doesn't match the one it declares.
550
+ * not this ref's typed error—either because the ref declares no `error` schema,
551
+ * or because `encodedError` doesn't match the one it declares.
546
552
  *
547
553
  * The second case is reachable in normal operation: Convex raises its own
548
- * `ConvexError`s (an `InvalidCursor` pagination error, for instance), and
549
- * those never match a user-declared error schema. Callers pair this with a
550
- * fallback that surfaces the original error, so failing to decode must not
551
- * throw—a `ParseError` here would replace the real error with an opaque one
552
- * and lose the only useful diagnostic. Hence the `Option` suffix rather than
553
- * `Sync`, matching `Schema.decodeUnknownOption`: the sibling `*Sync` helpers
554
- * in this module all throw on a parse failure, and this one deliberately
555
- * doesn't.
554
+ * `ConvexError`s (an `InvalidCursor` pagination error, for instance), and those
555
+ * never match a user-declared error schema. Callers pair this with a fallback
556
+ * that surfaces the original error, so failing to decode must not throw—a
557
+ * `ParseError` here would replace the real error with an opaque one and lose
558
+ * the only useful diagnostic. Hence the `Option` suffix rather than `Sync`,
559
+ * matching `Schema.decodeUnknownOption`: the sibling `*Sync` helpers in this
560
+ * module all throw on a parse failure, and this one deliberately doesn't.
556
561
  */
557
562
  export const decodeErrorOption = <Ref_ extends Any>(
558
563
  ref: Ref_,
@@ -589,10 +594,11 @@ const paginatedKind = (ref: AnyConfect): FunctionProvenance.Paginated =>
589
594
  );
590
595
 
591
596
  /**
592
- * Encode the args of a paginated query ref via its user-args schema—`paginationOpts` is excluded, since the pagination protocol fields are
597
+ * Encode the args of a paginated query ref via its user-args
598
+ * schema—`paginationOpts` is excluded, since the pagination protocol fields are
593
599
  * managed by the client (e.g. `usePaginatedQuery` from `convex/react`), not by
594
- * the caller. Requires a ref built with `FunctionSpec.publicPaginatedQuery`
595
- * (or `internalPaginatedQuery`).
600
+ * the caller. Requires a ref built with `FunctionSpec.publicPaginatedQuery` (or
601
+ * `internalPaginatedQuery`).
596
602
  */
597
603
  export const encodePaginatedQueryArgsSync = <
598
604
  Ref_ extends AnyPublicPaginatedQuery,
package/src/Refs.ts CHANGED
@@ -6,7 +6,7 @@ import type * as FunctionSpec from "./FunctionSpec";
6
6
  import type * as GroupSpec from "./GroupSpec";
7
7
  import type * as MiddlewareSpec from "./MiddlewareSpec";
8
8
  import * as Ref from "./Ref";
9
- import type * as Spec from "./Spec";
9
+ import * as Spec from "./Spec";
10
10
 
11
11
  export type Refs<
12
12
  Spec_ extends Spec.AnyWithProps,
@@ -98,7 +98,7 @@ type Any =
98
98
  export const make = <Spec_ extends Spec.AnyWithProps>(
99
99
  spec: Spec_,
100
100
  ): FromSpec<Spec_> => {
101
- const refs = makeHelper(spec.groups);
101
+ const refs = makeHelper(Spec.groups(spec));
102
102
  return {
103
103
  public: refs as Refs<Spec_, Ref.AnyPublic>,
104
104
  internal: refs as Refs<Spec_, Ref.AnyInternal>,
package/src/Spec.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as Predicate from "effect/Predicate";
2
2
  import * as Record from "effect/Record";
3
+ import * as Struct from "effect/Struct";
3
4
  import * as GroupSpec from "./GroupSpec";
4
5
 
5
6
  export const TypeId = "~@confect/core/Spec";
@@ -15,61 +16,71 @@ export const isSpec = (u: unknown): u is AnyWithProps =>
15
16
  * group lives on the group itself (`GroupSpec.runtime`) and on each function's
16
17
  * `RuntimeAndFunctionType`; the spec does not carry a runtime of its own.
17
18
  */
18
- export interface Spec<Groups_ extends GroupSpec.AnyWithProps = never> {
19
- readonly [TypeId]: TypeId;
20
- readonly groups: {
21
- [GroupName in GroupSpec.Name<Groups_>]: GroupSpec.WithName<
22
- Groups_,
23
- GroupName
24
- >;
25
- };
26
- readonly "~Groups": Groups_;
19
+ export interface Spec<
20
+ Groups_ extends Record.ReadonlyRecord<string, GroupSpec.AnyWithProps> = {},
21
+ > {
22
+ readonly [TypeId]: Readonly<Groups_>;
27
23
 
28
24
  add<Group extends GroupSpec.AnyWithProps>(
29
25
  group: Group,
30
- ): Spec<Groups_ | Group>;
26
+ ): Spec<
27
+ Struct.Assign<Groups_, Record.ReadonlyRecord<GroupSpec.Name<Group>, Group>>
28
+ >;
31
29
 
32
30
  addAt<const Name extends string, Group extends GroupSpec.AnyWithProps>(
33
31
  name: Name,
34
32
  group: Group,
35
- ): Spec<Groups_ | GroupSpec.NamedAt<Group, Name>>;
33
+ ): Spec<
34
+ Struct.Assign<
35
+ Groups_,
36
+ Record.ReadonlyRecord<Name, GroupSpec.NamedAt<Group, Name>>
37
+ >
38
+ >;
36
39
  }
37
40
 
38
41
  export interface Any {
39
- readonly [TypeId]: TypeId;
42
+ readonly [TypeId]: unknown;
40
43
  }
41
44
 
42
- export interface AnyWithProps extends Spec<GroupSpec.AnyWithProps> {}
45
+ export interface AnyWithProps extends Any {
46
+ readonly [TypeId]: Record.ReadonlyRecord<string, GroupSpec.AnyWithProps>;
47
+ }
43
48
 
44
- export type Groups<Spec_ extends AnyWithProps> = Spec_["~Groups"];
49
+ export type Groups<Spec_ extends AnyWithProps> =
50
+ Spec_[TypeId][keyof Spec_[TypeId]];
45
51
 
46
- const Proto = {
47
- [TypeId]: TypeId,
52
+ /**
53
+ * The group record stored by a spec, with its precise member types.
54
+ */
55
+ export const groups = <Spec_ extends AnyWithProps>(
56
+ self: Spec_,
57
+ ): Spec_[TypeId] => self[TypeId];
48
58
 
49
- add<Group extends GroupSpec.AnyWithProps>(this: AnyWithProps, group: Group) {
50
- return makeProto({
51
- groups: Record.set(this.groups, group.name, group),
52
- });
59
+ const makeRecord = <
60
+ Groups_ extends Record.ReadonlyRecord<string, GroupSpec.AnyWithProps>,
61
+ >(
62
+ record: Groups_,
63
+ ): Spec<Groups_> => ({
64
+ [TypeId]: record,
65
+ add<Group extends GroupSpec.AnyWithProps>(group: Group) {
66
+ return makeRecord(
67
+ Struct.assign(
68
+ record,
69
+ Record.singleton<GroupSpec.Name<Group>, Group>(group.name, group),
70
+ ),
71
+ );
53
72
  },
54
-
55
- addAt<Group extends GroupSpec.AnyWithProps>(
56
- this: AnyWithProps,
57
- name: string,
73
+ addAt<const Name extends string, Group extends GroupSpec.AnyWithProps>(
74
+ name: Name,
58
75
  group: Group,
59
76
  ) {
60
- return makeProto({
61
- groups: Record.set(this.groups, name, GroupSpec.withName(name, group)),
62
- });
77
+ return makeRecord(
78
+ Struct.assign(
79
+ record,
80
+ Record.singleton(name, GroupSpec.withName(name, group)),
81
+ ),
82
+ );
63
83
  },
64
- };
65
-
66
- const makeProto = <Groups_ extends GroupSpec.AnyWithProps>({
67
- groups,
68
- }: {
69
- groups: Record.ReadonlyRecord<string, Groups_>;
70
- }): Spec<Groups_> =>
71
- Object.assign(Object.create(Proto), {
72
- groups,
73
- }) as Spec<Groups_>;
84
+ });
74
85
 
75
- export const make = (): Spec => makeProto({ groups: {} });
86
+ export const make = (): Spec => makeRecord({});
@@ -13,7 +13,8 @@ import * as Struct from "effect/Struct";
13
13
  import * as GenericId from "./GenericId";
14
14
 
15
15
  /**
16
- * Produces a schema for Convex system fields. In Confect, system fields include `_id`.
16
+ * Produces a schema for Convex system fields. In Confect, system fields include
17
+ * `_id`.
17
18
  */
18
19
  export const SystemFields = <TableName extends string>(tableName: TableName) =>
19
20
  Schema.Struct({
@@ -154,10 +155,11 @@ const makeExtendAst = (
154
155
  /**
155
156
  * Extend a table schema with Convex system fields.
156
157
  *
157
- * A plain `Struct` gains the fields via `Schema.fieldsAssign` and a `Union`
158
- * has them distributed across its members, preserving the schema's
159
- * `Struct`/`Union` structure. Any other object-shaped schema—one built with
160
- * `Schema.decodeTo`/`Schema.encodeKeys`, a branded struct, a suspended schema—is extended at the AST level: every object node in its encoding chain
158
+ * A plain `Struct` gains the fields via `Schema.fieldsAssign` and a `Union` has
159
+ * them distributed across its members, preserving the schema's `Struct`/`Union`
160
+ * structure. Any other object-shaped schema—one built with
161
+ * `Schema.decodeTo`/`Schema.encodeKeys`, a branded struct, a suspended
162
+ * schema—is extended at the AST level: every object node in its encoding chain
161
163
  * gains the system fields, and each transformation is wrapped so the fields
162
164
  * bypass the user-defined getters. Schemas that do not resolve to an object
163
165
  * shape at every step (such as `Schema.Class`, whose decoded values are class
@@ -218,9 +220,9 @@ export const extendWithSystemFields = <
218
220
  };
219
221
 
220
222
  /**
221
- * Applies the system fields to a single struct, mirroring `Schema.fieldsAssign`.
222
- * Any other (already-extended or opaque) schema falls back to a `Codec` carrying
223
- * the system-field document shape.
223
+ * Applies the system fields to a single struct, mirroring
224
+ * `Schema.fieldsAssign`. Any other (already-extended or opaque) schema falls
225
+ * back to a `Codec` carrying the system-field document shape.
224
226
  */
225
227
  type ApplySystemFields<TableName extends string, S> =
226
228
  S extends Schema.Struct<infer Fields extends Schema.Struct.Fields>
@@ -240,10 +242,10 @@ type ApplySystemFields<TableName extends string, S> =
240
242
  * This mirrors the runtime {@link extendWithSystemFields}: a `Struct` gains the
241
243
  * system fields directly (matching `Schema.fieldsAssign`), and a `Union` has
242
244
  * them distributed across its members (matching
243
- * `union.mapMembers(Tuple.map(Schema.fieldsAssign(...)))`). The `Struct`/`Union`
244
- * structure is preserved rather than collapsed to a bare `Codec`; any other
245
- * schema falls back to a `Codec` carrying the system-field document shape,
246
- * matching the runtime's AST-level extension.
245
+ * `union.mapMembers(Tuple.map(Schema.fieldsAssign(...)))`). The
246
+ * `Struct`/`Union` structure is preserved rather than collapsed to a bare
247
+ * `Codec`; any other schema falls back to a `Codec` carrying the system-field
248
+ * document shape, matching the runtime's AST-level extension.
247
249
  */
248
250
  export type ExtendWithSystemFields<
249
251
  TableName extends string,
package/src/Table.ts CHANGED
@@ -417,6 +417,7 @@ export const make = <const TableSchema_ extends Schema.Codec<any, any>>(
417
417
  * Extract all of the index field paths within a Convex `Validator`.
418
418
  *
419
419
  * This is used when declaring table indexes.
420
+ *
420
421
  * @public
421
422
  */
422
423
  type ExtractFieldPaths<T extends Validator<any, any, any>> =