@confect/core 10.0.0-next.9 → 10.1.0

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 (103) hide show
  1. package/CHANGELOG.md +964 -47
  2. package/README.md +3 -1
  3. package/dist/FunctionProvenance.d.ts +166 -68
  4. package/dist/FunctionProvenance.d.ts.map +1 -1
  5. package/dist/FunctionProvenance.js +55 -13
  6. package/dist/FunctionProvenance.js.map +1 -1
  7. package/dist/FunctionSpec.d.ts +320 -138
  8. package/dist/FunctionSpec.d.ts.map +1 -1
  9. package/dist/FunctionSpec.js +56 -13
  10. package/dist/FunctionSpec.js.map +1 -1
  11. package/dist/GenericId.d.ts.map +1 -1
  12. package/dist/GenericId.js +1 -1
  13. package/dist/GroupPath.d.ts +6 -10
  14. package/dist/GroupPath.d.ts.map +1 -1
  15. package/dist/GroupPath.js.map +1 -1
  16. package/dist/GroupSpec.d.ts +25 -12
  17. package/dist/GroupSpec.d.ts.map +1 -1
  18. package/dist/GroupSpec.js +51 -14
  19. package/dist/GroupSpec.js.map +1 -1
  20. package/dist/Identifier.d.ts +6 -5
  21. package/dist/Identifier.d.ts.map +1 -1
  22. package/dist/Identifier.js +6 -5
  23. package/dist/Identifier.js.map +1 -1
  24. package/dist/Lazy.d.ts +11 -14
  25. package/dist/Lazy.d.ts.map +1 -1
  26. package/dist/Lazy.js +11 -14
  27. package/dist/Lazy.js.map +1 -1
  28. package/dist/MiddlewareAttachment.d.ts +171 -0
  29. package/dist/MiddlewareAttachment.d.ts.map +1 -0
  30. package/dist/MiddlewareAttachment.js +48 -0
  31. package/dist/MiddlewareAttachment.js.map +1 -0
  32. package/dist/MiddlewareSpec.d.ts +198 -0
  33. package/dist/MiddlewareSpec.d.ts.map +1 -0
  34. package/dist/MiddlewareSpec.js +60 -0
  35. package/dist/MiddlewareSpec.js.map +1 -0
  36. package/dist/PaginationError.d.ts +20 -0
  37. package/dist/PaginationError.d.ts.map +1 -0
  38. package/dist/PaginationError.js +31 -0
  39. package/dist/PaginationError.js.map +1 -0
  40. package/dist/PaginationOptions.d.ts +23 -0
  41. package/dist/PaginationOptions.d.ts.map +1 -0
  42. package/dist/PaginationOptions.js +29 -0
  43. package/dist/PaginationOptions.js.map +1 -0
  44. package/dist/PaginationResult.d.ts +1 -0
  45. package/dist/PaginationResult.d.ts.map +1 -1
  46. package/dist/PaginationResult.js.map +1 -1
  47. package/dist/Ref.d.ts +135 -47
  48. package/dist/Ref.d.ts.map +1 -1
  49. package/dist/Ref.js +104 -46
  50. package/dist/Ref.js.map +1 -1
  51. package/dist/Refs.d.ts +10 -5
  52. package/dist/Refs.d.ts.map +1 -1
  53. package/dist/Refs.js +5 -4
  54. package/dist/Refs.js.map +1 -1
  55. package/dist/SchemaToValidator.d.ts +99 -0
  56. package/dist/SchemaToValidator.d.ts.map +1 -0
  57. package/dist/SchemaToValidator.js +158 -0
  58. package/dist/SchemaToValidator.js.map +1 -0
  59. package/dist/Spec.d.ts +16 -12
  60. package/dist/Spec.d.ts.map +1 -1
  61. package/dist/Spec.js +14 -9
  62. package/dist/Spec.js.map +1 -1
  63. package/dist/SystemFields.d.ts +20 -19
  64. package/dist/SystemFields.d.ts.map +1 -1
  65. package/dist/SystemFields.js +22 -21
  66. package/dist/SystemFields.js.map +1 -1
  67. package/dist/Table.d.ts +75 -0
  68. package/dist/Table.d.ts.map +1 -0
  69. package/dist/Table.js +77 -0
  70. package/dist/Table.js.map +1 -0
  71. package/dist/Types.d.ts +8 -2
  72. package/dist/Types.d.ts.map +1 -1
  73. package/dist/Types.js.map +1 -1
  74. package/dist/UserIdentity.d.ts.map +1 -1
  75. package/dist/index.d.ts +6 -1
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +9 -4
  78. package/package.json +17 -15
  79. package/src/FunctionProvenance.ts +197 -34
  80. package/src/FunctionSpec.ts +332 -86
  81. package/src/GroupPath.ts +6 -12
  82. package/src/GroupSpec.ts +184 -25
  83. package/src/Identifier.ts +6 -5
  84. package/src/Lazy.ts +11 -14
  85. package/src/MiddlewareAttachment.ts +106 -0
  86. package/src/MiddlewareSpec.ts +392 -0
  87. package/src/PaginationError.ts +78 -0
  88. package/src/PaginationOptions.ts +23 -0
  89. package/src/PaginationResult.ts +4 -0
  90. package/src/Ref.ts +468 -236
  91. package/src/Refs.ts +43 -18
  92. package/src/SchemaToValidator.ts +612 -0
  93. package/src/Spec.ts +50 -39
  94. package/src/SystemFields.ts +40 -42
  95. package/src/Table.ts +427 -0
  96. package/src/Types.ts +9 -3
  97. package/src/index.ts +6 -1
  98. package/dist/Registry.d.ts +0 -24
  99. package/dist/Registry.d.ts.map +0 -1
  100. package/dist/Registry.js +0 -19
  101. package/dist/Registry.js.map +0 -1
  102. package/dist/tsconfig.src.tsbuildinfo +0 -1
  103. package/src/Registry.ts +0 -30
package/src/Spec.ts CHANGED
@@ -1,8 +1,9 @@
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
- export const TypeId = "@confect/core/Spec";
6
+ export const TypeId = "~@confect/core/Spec";
6
7
  export type TypeId = typeof TypeId;
7
8
 
8
9
  export const isSpec = (u: unknown): u is AnyWithProps =>
@@ -10,66 +11,76 @@ export const isSpec = (u: unknown): u is AnyWithProps =>
10
11
 
11
12
  /**
12
13
  * A Confect spec: a flat container of function groups. Groups may be of any
13
- * runtime — a group built with `GroupSpec.makeNode()` (a Node action group) sits
14
+ * runtime—a group built with `GroupSpec.makeNode()` (a Node action group) sits
14
15
  * alongside `GroupSpec.make()` groups in the same namespace. The runtime of a
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
- };
19
+ export interface Spec<
20
+ Groups_ extends Record.ReadonlyRecord<string, GroupSpec.AnyWithProps> = {},
21
+ > {
22
+ readonly [TypeId]: Readonly<Groups_>;
26
23
 
27
24
  add<Group extends GroupSpec.AnyWithProps>(
28
25
  group: Group,
29
- ): Spec<Groups_ | Group>;
26
+ ): Spec<
27
+ Struct.Assign<Groups_, Record.ReadonlyRecord<GroupSpec.Name<Group>, Group>>
28
+ >;
30
29
 
31
30
  addAt<const Name extends string, Group extends GroupSpec.AnyWithProps>(
32
31
  name: Name,
33
32
  group: Group,
34
- ): Spec<Groups_ | GroupSpec.NamedAt<Group, Name>>;
33
+ ): Spec<
34
+ Struct.Assign<
35
+ Groups_,
36
+ Record.ReadonlyRecord<Name, GroupSpec.NamedAt<Group, Name>>
37
+ >
38
+ >;
35
39
  }
36
40
 
37
41
  export interface Any {
38
- readonly [TypeId]: TypeId;
42
+ readonly [TypeId]: unknown;
39
43
  }
40
44
 
41
- export interface AnyWithProps extends Spec<GroupSpec.AnyWithProps> {}
45
+ export interface AnyWithProps extends Any {
46
+ readonly [TypeId]: Record.ReadonlyRecord<string, GroupSpec.AnyWithProps>;
47
+ }
42
48
 
43
49
  export type Groups<Spec_ extends AnyWithProps> =
44
- Spec_["groups"][keyof Spec_["groups"]];
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
- });
84
+ });
74
85
 
75
- export const make = (): Spec => makeProto({ groups: {} });
86
+ export const make = (): Spec => makeRecord({});
@@ -13,12 +13,13 @@ 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({
20
21
  _id: GenericId.GenericId(tableName),
21
- _creationTime: Schema.Number,
22
+ _creationTime: Schema.Finite,
22
23
  });
23
24
 
24
25
  /**
@@ -58,23 +59,21 @@ const splitSystemFields = (input: { [key: PropertyKey]: unknown }) => {
58
59
  * output. Transformations construct fresh objects, so without this the system
59
60
  * fields would be dropped at every transformation step.
60
61
  */
61
- const wrapGetter = (
62
- getter: SchemaGetter.Getter<any, any, any>,
63
- ): SchemaGetter.Getter<any, any, any> =>
64
- new SchemaGetter.Getter((input, options) => {
62
+ const wrapGetter = <R>(
63
+ getter: SchemaGetter.Getter<any, any, R>,
64
+ ): SchemaGetter.Getter<any, any, R> =>
65
+ SchemaGetter.transformOptionalEffect((input, options) => {
65
66
  if (Option.isNone(input) || !Predicate.isObject(input.value)) {
66
- return getter.run(input, options);
67
+ return SchemaGetter.run(getter, input, options);
67
68
  }
68
69
  const { system, rest } = splitSystemFields(input.value);
69
- return getter
70
- .run(Option.some(rest), options)
71
- .pipe(
72
- Effect.map(
73
- Option.map((output) =>
74
- Predicate.isObject(output) ? Struct.assign(output, system) : output,
75
- ),
70
+ return SchemaGetter.run(getter, Option.some(rest), options).pipe(
71
+ Effect.map(
72
+ Option.map((output) =>
73
+ Predicate.isObject(output) ? Struct.assign(output, system) : output,
76
74
  ),
77
- );
75
+ ),
76
+ );
78
77
  });
79
78
 
80
79
  const wrapTransformation = (
@@ -93,8 +92,8 @@ const wrapTransformation = (
93
92
 
94
93
  /**
95
94
  * Builds an AST walker that adds the given system-field property signatures to
96
- * every object node of a schema's AST — including each step of its encoding
97
- * chain — wrapping transformations so the fields survive them.
95
+ * every object node of a schema's AST—including each step of its encoding
96
+ * chain—wrapping transformations so the fields survive them.
98
97
  */
99
98
  const makeExtendAst = (
100
99
  systemPropertySignatures: ReadonlyArray<SchemaAST.PropertySignature>,
@@ -113,7 +112,7 @@ const makeExtendAst = (
113
112
  if (SchemaAST.isUnion(ast)) {
114
113
  return new SchemaAST.Union(
115
114
  Array.map(ast.types, extendAst),
116
- ast.mode,
115
+ ast.options,
117
116
  ast.annotations,
118
117
  ast.checks,
119
118
  ast.encoding === undefined ? undefined : extendEncoding(ast.encoding),
@@ -154,15 +153,15 @@ const makeExtendAst = (
154
153
  /**
155
154
  * Extend a table schema with Convex system fields.
156
155
  *
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
161
- * — is extended at the AST level: every object node in its encoding chain
162
- * gains the system fields, and each transformation is wrapped so the fields
163
- * bypass the user-defined getters. Schemas that do not resolve to an object
164
- * shape at every step (such as `Schema.Class`, whose decoded values are class
165
- * instances) are rejected with a descriptive error.
156
+ * A plain `Struct` gains the fields via `mapFields` and a `Union` has them
157
+ * distributed across its members via `mapMembers`, preserving the schema's
158
+ * checks and `Struct`/`Union` structure. Any other object-shaped schema—one
159
+ * built with `Schema.decodeTo`/`Schema.encodeKeys`, a branded struct, a
160
+ * suspended schema—is extended at the AST level: every object node in its
161
+ * encoding chain gains the system fields, and each transformation is wrapped so
162
+ * the fields bypass the user-defined getters. Schemas that do not resolve to an
163
+ * object shape at every step (such as `Schema.Class`, whose decoded values are
164
+ * class instances) are rejected with a descriptive error.
166
165
  *
167
166
  * Note that struct-level checks on an extended schema observe the value with
168
167
  * the system fields attached, and encoding an extended schema emits the system
@@ -193,11 +192,9 @@ export const extendWithSystemFields = <
193
192
  SchemaAST.isUnion(s.ast) &&
194
193
  Array.isArray((s as { readonly members?: unknown }).members)
195
194
  ) {
196
- return Schema.Union(
197
- Array.map(
198
- (s as Schema.Union<ReadonlyArray<Schema.Top>>).members,
199
- extend,
200
- ),
195
+ return (s as Schema.Union<ReadonlyArray<Schema.Top>>).mapMembers(
196
+ Array.map(extend),
197
+ { unsafePreserveChecks: true },
201
198
  );
202
199
  }
203
200
  if (
@@ -205,8 +202,9 @@ export const extendWithSystemFields = <
205
202
  SchemaAST.isObjects(s.ast) &&
206
203
  typeof (s as { readonly mapFields?: unknown }).mapFields === "function"
207
204
  ) {
208
- return Schema.fieldsAssign(system)(
209
- s as Schema.Struct<Schema.Struct.Fields>,
205
+ return (s as Schema.Struct<Schema.Struct.Fields>).mapFields(
206
+ Struct.assign(system),
207
+ { unsafePreserveChecks: true },
210
208
  );
211
209
  }
212
210
  return Schema.make(extendAst(s.ast));
@@ -219,9 +217,9 @@ export const extendWithSystemFields = <
219
217
  };
220
218
 
221
219
  /**
222
- * Applies the system fields to a single struct, mirroring `Schema.fieldsAssign`.
223
- * Any other (already-extended or opaque) schema falls back to a `Codec` carrying
224
- * the system-field document shape.
220
+ * Applies the system fields to a single struct, mirroring
221
+ * `Schema.fieldsAssign`. Any other (already-extended or opaque) schema falls
222
+ * back to a `Codec` carrying the system-field document shape.
225
223
  */
226
224
  type ApplySystemFields<TableName extends string, S> =
227
225
  S extends Schema.Struct<infer Fields extends Schema.Struct.Fields>
@@ -241,10 +239,10 @@ type ApplySystemFields<TableName extends string, S> =
241
239
  * This mirrors the runtime {@link extendWithSystemFields}: a `Struct` gains the
242
240
  * system fields directly (matching `Schema.fieldsAssign`), and a `Union` has
243
241
  * them distributed across its members (matching
244
- * `union.mapMembers(Tuple.map(Schema.fieldsAssign(...)))`). The `Struct`/`Union`
245
- * structure is preserved rather than collapsed to a bare `Codec`; any other
246
- * schema falls back to a `Codec` carrying the system-field document shape,
247
- * matching the runtime's AST-level extension.
242
+ * `union.mapMembers(Tuple.map(Schema.fieldsAssign(...)))`). The
243
+ * `Struct`/`Union` structure is preserved rather than collapsed to a bare
244
+ * `Codec`; any other schema falls back to a `Codec` carrying the system-field
245
+ * document shape, matching the runtime's AST-level extension.
248
246
  */
249
247
  export type ExtendWithSystemFields<
250
248
  TableName extends string,
@@ -264,7 +262,7 @@ export type ExtendWithSystemFields<
264
262
 
265
263
  /**
266
264
  * The decoded/encoded document shape: a table's fields plus Convex's system
267
- * fields. Deliberately a bare intersection (no `Expand`/`Simplify`) — flattening
265
+ * fields. Deliberately a bare intersection (no `Expand`/`Simplify`)—flattening
268
266
  * it with a homomorphic mapped type collapses to `{ [x: string]: any }` when
269
267
  * `Document` is still an unresolved generic, which breaks structural
270
268
  * comparability in the database reader/writer plumbing.