@confect/core 10.0.0-next.17 → 10.0.0-next.19

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 (68) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/dist/FunctionProvenance.d.ts +81 -60
  3. package/dist/FunctionProvenance.d.ts.map +1 -1
  4. package/dist/FunctionProvenance.js +9 -9
  5. package/dist/FunctionProvenance.js.map +1 -1
  6. package/dist/FunctionSpec.d.ts +256 -144
  7. package/dist/FunctionSpec.d.ts.map +1 -1
  8. package/dist/FunctionSpec.js +25 -20
  9. package/dist/FunctionSpec.js.map +1 -1
  10. package/dist/GroupPath.d.ts +1 -4
  11. package/dist/GroupPath.d.ts.map +1 -1
  12. package/dist/GroupPath.js.map +1 -1
  13. package/dist/GroupSpec.d.ts +5 -3
  14. package/dist/GroupSpec.d.ts.map +1 -1
  15. package/dist/GroupSpec.js +1 -1
  16. package/dist/GroupSpec.js.map +1 -1
  17. package/dist/Lazy.d.ts +2 -3
  18. package/dist/Lazy.d.ts.map +1 -1
  19. package/dist/Lazy.js +2 -3
  20. package/dist/Lazy.js.map +1 -1
  21. package/dist/MiddlewareSpec.d.ts +2 -2
  22. package/dist/MiddlewareSpec.d.ts.map +1 -1
  23. package/dist/MiddlewareSpec.js +1 -1
  24. package/dist/MiddlewareSpec.js.map +1 -1
  25. package/dist/PaginationError.d.ts +14 -0
  26. package/dist/PaginationError.d.ts.map +1 -0
  27. package/dist/PaginationError.js +25 -0
  28. package/dist/PaginationError.js.map +1 -0
  29. package/dist/Ref.d.ts +66 -20
  30. package/dist/Ref.d.ts.map +1 -1
  31. package/dist/Ref.js +3 -3
  32. package/dist/Ref.js.map +1 -1
  33. package/dist/Refs.d.ts +1 -1
  34. package/dist/Refs.d.ts.map +1 -1
  35. package/dist/Refs.js.map +1 -1
  36. package/dist/SchemaToValidator.d.ts +99 -0
  37. package/dist/SchemaToValidator.d.ts.map +1 -0
  38. package/dist/SchemaToValidator.js +156 -0
  39. package/dist/SchemaToValidator.js.map +1 -0
  40. package/dist/Spec.d.ts +3 -2
  41. package/dist/Spec.d.ts.map +1 -1
  42. package/dist/Spec.js +1 -1
  43. package/dist/Spec.js.map +1 -1
  44. package/dist/Table.d.ts +74 -0
  45. package/dist/Table.d.ts.map +1 -0
  46. package/dist/Table.js +77 -0
  47. package/dist/Table.js.map +1 -0
  48. package/dist/Types.d.ts +8 -2
  49. package/dist/Types.d.ts.map +1 -1
  50. package/dist/Types.js.map +1 -1
  51. package/dist/index.d.ts +3 -0
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +4 -1
  54. package/package.json +4 -4
  55. package/src/FunctionProvenance.ts +84 -71
  56. package/src/FunctionSpec.ts +193 -110
  57. package/src/GroupPath.ts +1 -6
  58. package/src/GroupSpec.ts +6 -6
  59. package/src/Lazy.ts +2 -3
  60. package/src/MiddlewareSpec.ts +2 -2
  61. package/src/PaginationError.ts +72 -0
  62. package/src/Ref.ts +164 -153
  63. package/src/Refs.ts +1 -0
  64. package/src/SchemaToValidator.ts +601 -0
  65. package/src/Spec.ts +4 -4
  66. package/src/Table.ts +426 -0
  67. package/src/Types.ts +9 -3
  68. package/src/index.ts +3 -0
@@ -0,0 +1,601 @@
1
+ import type {
2
+ PropertyValidators,
3
+ Validator,
4
+ VAny,
5
+ VArray,
6
+ VBoolean,
7
+ VBytes,
8
+ VFloat64,
9
+ VId,
10
+ VInt64,
11
+ VLiteral,
12
+ VNull,
13
+ VObject,
14
+ VOptional,
15
+ VRecord,
16
+ VString,
17
+ VUnion,
18
+ } from "convex/values";
19
+ import { v } from "convex/values";
20
+ import { pipe } from "effect/Function";
21
+ import * as Array from "effect/Array";
22
+ import * as Data from "effect/Data";
23
+ import * as Effect from "effect/Effect";
24
+ import * as Match from "effect/Match";
25
+ import * as Number from "effect/Number";
26
+ import * as Option from "effect/Option";
27
+ import * as Predicate from "effect/Predicate";
28
+ import * as Schema from "effect/Schema";
29
+ import * as SchemaAST from "effect/SchemaAST";
30
+ import * as String from "effect/String";
31
+
32
+ import * as GenericId from "./GenericId";
33
+ import type {
34
+ IsAny,
35
+ IsOptional,
36
+ IsRecord,
37
+ IsRecursive,
38
+ IsUnion,
39
+ TypeError,
40
+ UnionToTuple,
41
+ } from "./Types";
42
+
43
+ // Args
44
+
45
+ export const compileArgsSchema = <ConfectValue, ConvexValue>(
46
+ argsSchema: Schema.Codec<ConfectValue, ConvexValue>,
47
+ ): PropertyValidators => {
48
+ const ast = Schema.toEncoded(argsSchema).ast;
49
+
50
+ return pipe(
51
+ ast,
52
+ Match.value,
53
+ Match.tag("Objects", (objectsAst) =>
54
+ Array.isReadonlyArrayEmpty(objectsAst.indexSignatures)
55
+ ? handlePropertySignatures(objectsAst)
56
+ : Effect.fail(new IndexSignaturesAreNotSupportedError()),
57
+ ),
58
+ Match.orElse(() => Effect.fail(new TopLevelMustBeObjectError())),
59
+ Effect.runSync,
60
+ );
61
+ };
62
+
63
+ // Returns
64
+
65
+ export const compileReturnsSchema = <ConfectValue, ConvexValue>(
66
+ schema: Schema.Codec<ConfectValue, ConvexValue>,
67
+ ): Validator<any, any, any> =>
68
+ Effect.runSync(compileAst(Schema.toEncoded(schema).ast));
69
+
70
+ // Table
71
+
72
+ /**
73
+ * Convert a table `Schema` to a table `Validator`.
74
+ */
75
+ export type TableSchemaToTableValidator<
76
+ TableSchema extends Schema.Codec<any, any>,
77
+ > =
78
+ ValueToValidator<TableSchema["Encoded"]> extends infer Vd extends
79
+ | VObject<any, any, any, any>
80
+ | VUnion<any, any, any, any>
81
+ ? Vd
82
+ : never;
83
+
84
+ export const compileTableSchema = <TableSchema extends Schema.Codec<any, any>>(
85
+ schema: TableSchema,
86
+ ): TableSchemaToTableValidator<TableSchema> => {
87
+ const ast = Schema.toEncoded(schema).ast;
88
+
89
+ return pipe(
90
+ ast,
91
+ Match.value,
92
+ Match.tag("Objects", ({ indexSignatures }) =>
93
+ Array.isReadonlyArrayEmpty(indexSignatures)
94
+ ? (compileAst(ast) as Effect.Effect<any>)
95
+ : Effect.fail(new IndexSignaturesAreNotSupportedError()),
96
+ ),
97
+ Match.tag("Union", (unionAst) => compileAst(unionAst)),
98
+ Match.orElse(() => Effect.fail(new TopLevelMustBeObjectOrUnionError())),
99
+ Effect.runSync,
100
+ );
101
+ };
102
+
103
+ // Compiler
104
+
105
+ export type ReadonlyValue =
106
+ | string
107
+ | number
108
+ | bigint
109
+ | boolean
110
+ | ArrayBuffer
111
+ | ReadonlyArrayValue
112
+ | ReadonlyRecordValue
113
+ | null;
114
+
115
+ type ReadonlyArrayValue = readonly ReadonlyValue[];
116
+
117
+ export type ReadonlyRecordValue = {
118
+ readonly [key: string]: ReadonlyValue | undefined;
119
+ };
120
+
121
+ type MutableValue<T> =
122
+ T extends ReadonlyArray<infer El>
123
+ ? MutableValue<El>[]
124
+ : T extends ReadonlyRecordValue
125
+ ? { -readonly [K in keyof T]: MutableValue<Exclude<T[K], undefined>> }
126
+ : T;
127
+
128
+ export type ValueToValidator<Vl> = [Vl] extends [never]
129
+ ? never
130
+ : IsAny<Vl> extends true
131
+ ? VAny
132
+ : [Vl] extends [null]
133
+ ? VNull
134
+ : [Vl] extends [boolean]
135
+ ? [boolean] extends [Vl]
136
+ ? VBoolean
137
+ : VLiteral<Vl>
138
+ : IsUnion<Vl> extends true
139
+ ? IsRecursive<Vl> extends true
140
+ ? VAny
141
+ : [Vl] extends [ReadonlyValue]
142
+ ? UnionValueToValidator<Vl>
143
+ : TypeError<"Provided value is not a valid Convex value", Vl>
144
+ : [Vl] extends [number]
145
+ ? [number] extends [Vl]
146
+ ? VFloat64
147
+ : VLiteral<Vl>
148
+ : [Vl] extends [bigint]
149
+ ? [bigint] extends [Vl]
150
+ ? VInt64
151
+ : VLiteral<Vl>
152
+ : [Vl] extends [string]
153
+ ? Vl extends {
154
+ __tableName: infer TableName extends string;
155
+ }
156
+ ? VId<GenericId.GenericId<TableName>>
157
+ : [string] extends [Vl]
158
+ ? VString
159
+ : VLiteral<Vl>
160
+ : [Vl] extends [ArrayBuffer]
161
+ ? VBytes
162
+ : IsRecursive<Vl> extends true
163
+ ? VAny
164
+ : [Vl] extends [ReadonlyValue]
165
+ ? Vl extends ReadonlyArray<ReadonlyValue>
166
+ ? ArrayValueToValidator<Vl>
167
+ : Vl extends ReadonlyRecordValue
168
+ ? RecordValueToValidator<Vl>
169
+ : TypeError<"Unexpected value", Vl>
170
+ : TypeError<
171
+ "Provided value is not a valid Convex value",
172
+ Vl
173
+ >;
174
+
175
+ type ArrayValueToValidator<Vl extends ReadonlyArray<ReadonlyValue>> =
176
+ Vl extends ReadonlyArray<infer El extends ReadonlyValue>
177
+ ? ValueToValidator<El> extends infer Vd extends Validator<any, any, any>
178
+ ? VArray<MutableValue<El[]>, Vd>
179
+ : never
180
+ : never;
181
+
182
+ type RecordValueToValidator<Vl> = Vl extends ReadonlyRecordValue
183
+ ? {
184
+ -readonly [K in keyof Vl]-?: IsAny<Vl[K]> extends true
185
+ ? IsOptional<Vl, K> extends true
186
+ ? VOptional<VAny>
187
+ : VAny
188
+ : UndefinedOrValueToValidator<Vl[K]>;
189
+ } extends infer VdRecord extends Record<string, any>
190
+ ? MutableValue<Vl> extends infer VlRecord extends Record<string, any>
191
+ ? IsRecord<VlRecord> extends true
192
+ ? VRecord<VlRecord, VString, VdRecord[keyof VdRecord]>
193
+ : VObject<VlRecord, VdRecord>
194
+ : never
195
+ : never
196
+ : never;
197
+
198
+ export type UndefinedOrValueToValidator<Vl extends ReadonlyValue | undefined> =
199
+ undefined extends Vl
200
+ ? [Vl] extends [(infer Val extends ReadonlyValue) | undefined]
201
+ ? ValueToValidator<Val> extends infer Vd extends Validator<
202
+ any,
203
+ "required",
204
+ any
205
+ >
206
+ ? VOptional<Vd>
207
+ : never
208
+ : never
209
+ : [Vl] extends [ReadonlyValue]
210
+ ? ValueToValidator<Vl>
211
+ : never;
212
+
213
+ type UnionValueToValidator<Vl extends ReadonlyValue> = [Vl] extends [
214
+ ReadonlyValue,
215
+ ]
216
+ ? IsUnion<Vl> extends true
217
+ ? UnionToTuple<Vl> extends infer VlTuple extends
218
+ ReadonlyArray<ReadonlyValue>
219
+ ? ValueTupleToValidatorTuple<VlTuple> extends infer VdTuple extends
220
+ Validator<any, "required", any>[]
221
+ ? VUnion<MutableValue<Vl>, VdTuple>
222
+ : TypeError<"Failed to convert value tuple to validator tuple">
223
+ : TypeError<"Failed to convert union to tuple">
224
+ : TypeError<"Expected a union of values, but got a single value instead">
225
+ : TypeError<"Provided value is not a valid Convex value">;
226
+
227
+ type ValueTupleToValidatorTuple<VlTuple extends ReadonlyArray<ReadonlyValue>> =
228
+ VlTuple extends
229
+ | [true, false, ...infer VlRest extends ReadonlyArray<ReadonlyValue>]
230
+ | [false, true, ...infer VlRest extends ReadonlyArray<ReadonlyValue>]
231
+ ? ValueTupleToValidatorTuple<VlRest> extends infer VdRest extends Validator<
232
+ any,
233
+ any,
234
+ any
235
+ >[]
236
+ ? [VBoolean<boolean>, ...VdRest]
237
+ : never
238
+ : VlTuple extends [
239
+ infer Vl extends ReadonlyValue,
240
+ ...infer VlRest extends ReadonlyArray<ReadonlyValue>,
241
+ ]
242
+ ? ValueToValidator<Vl> extends infer Vd extends Validator<any, any, any>
243
+ ? ValueTupleToValidatorTuple<VlRest> extends infer VdRest extends
244
+ Validator<any, "required", any>[]
245
+ ? [Vd, ...VdRest]
246
+ : never
247
+ : never
248
+ : [];
249
+
250
+ export const compileSchema = <T, E>(
251
+ schema: Schema.Codec<T, E>,
252
+ ): ValueToValidator<(typeof schema)["Encoded"]> =>
253
+ Effect.runSync(compileAst(schema.ast)) as any;
254
+
255
+ export const isRecursive = (ast: SchemaAST.AST): boolean =>
256
+ pipe(
257
+ ast,
258
+ Match.value,
259
+ Match.tag(
260
+ "Literal",
261
+ "Null",
262
+ "Boolean",
263
+ "String",
264
+ "Number",
265
+ "BigInt",
266
+ "Unknown",
267
+ "Any",
268
+ "Declaration",
269
+ "UniqueSymbol",
270
+ "Symbol",
271
+ "Undefined",
272
+ "Void",
273
+ "Never",
274
+ "Enum",
275
+ "TemplateLiteral",
276
+ "ObjectKeyword",
277
+ () => false,
278
+ ),
279
+ Match.tag("Union", ({ types }) =>
280
+ Array.some(types, (type) => isRecursive(type)),
281
+ ),
282
+ Match.tag("Objects", ({ propertySignatures }) =>
283
+ Array.some(propertySignatures, ({ type }) => isRecursive(type)),
284
+ ),
285
+ Match.tag(
286
+ "Arrays",
287
+ ({ elements, rest }) =>
288
+ Array.some(elements, (element) => isRecursive(element)) ||
289
+ Array.some(rest, (element) => isRecursive(element)),
290
+ ),
291
+ Match.tag("Suspend", () => true),
292
+ Match.exhaustive,
293
+ );
294
+
295
+ export const compileAst = (
296
+ ast: SchemaAST.AST,
297
+ isOptionalPropertyOfTypeLiteral = false,
298
+ ): Effect.Effect<
299
+ Validator<any, any, any>,
300
+ | UnsupportedSchemaTypeError
301
+ | UnsupportedPropertySignatureKeyTypeError
302
+ | IndexSignaturesAreNotSupportedError
303
+ | MixedIndexAndPropertySignaturesAreNotSupportedError
304
+ | OptionalTupleElementsAreNotSupportedError
305
+ | EmptyTupleIsNotSupportedError
306
+ | EmptyUnionIsNotSupportedError
307
+ > =>
308
+ isRecursive(ast)
309
+ ? Effect.succeed(v.any())
310
+ : pipe(
311
+ ast,
312
+ Match.value,
313
+ Match.tag("Literal", ({ literal }) =>
314
+ pipe(
315
+ literal,
316
+ Match.value,
317
+ Match.whenOr(
318
+ Match.string,
319
+ Match.number,
320
+ Match.bigint,
321
+ Match.boolean,
322
+ (l) => v.literal(l),
323
+ ),
324
+ Match.exhaustive,
325
+ Effect.succeed,
326
+ ),
327
+ ),
328
+ Match.tag("Null", () => Effect.succeed(v.null())),
329
+ Match.tag("Boolean", () => Effect.succeed(v.boolean())),
330
+ Match.tag("String", (stringAst) =>
331
+ GenericId.tableName(stringAst).pipe(
332
+ Option.match({
333
+ onNone: () => Effect.succeed(v.string()),
334
+ onSome: (tableName) => Effect.succeed(v.id(tableName)),
335
+ }),
336
+ ),
337
+ ),
338
+ Match.tag("Number", () => Effect.succeed(v.float64())),
339
+ Match.tag("BigInt", () => Effect.succeed(v.int64())),
340
+ Match.tag("Union", (unionAst) =>
341
+ handleUnion(unionAst, isOptionalPropertyOfTypeLiteral),
342
+ ),
343
+ Match.tag("Objects", (objectsAst) => handleObjects(objectsAst)),
344
+ Match.tag("Arrays", (arraysAst) => handleArrays(arraysAst)),
345
+ Match.tag("Unknown", "Any", () => Effect.succeed(v.any())),
346
+ Match.tag("Declaration", (declaration) =>
347
+ Effect.mapBoth(
348
+ declaration.run(declaration.typeParameters)(
349
+ new ArrayBuffer(0),
350
+ declaration,
351
+ {},
352
+ ) as Effect.Effect<ArrayBuffer, unknown, never>,
353
+ {
354
+ onSuccess: () => v.bytes(),
355
+ onFailure: () =>
356
+ new UnsupportedSchemaTypeError({
357
+ schemaType: declaration._tag,
358
+ }),
359
+ },
360
+ ),
361
+ ),
362
+ Match.tag("Suspend", () => Effect.succeed(v.any())),
363
+ Match.tag(
364
+ "UniqueSymbol",
365
+ "Symbol",
366
+ "Undefined",
367
+ "Void",
368
+ "Never",
369
+ "Enum",
370
+ "TemplateLiteral",
371
+ "ObjectKeyword",
372
+ () =>
373
+ Effect.fail(
374
+ new UnsupportedSchemaTypeError({
375
+ schemaType: ast._tag,
376
+ }),
377
+ ),
378
+ ),
379
+ Match.exhaustive,
380
+ );
381
+
382
+ const handleUnion = (
383
+ { types }: SchemaAST.Union,
384
+ isOptionalPropertyOfTypeLiteral: boolean,
385
+ ) =>
386
+ Effect.gen(function* () {
387
+ const members = isOptionalPropertyOfTypeLiteral
388
+ ? Array.filter(types, Predicate.not(SchemaAST.isUndefined))
389
+ : types;
390
+
391
+ const [firstValidator, secondValidator, ...restValidators] =
392
+ yield* Effect.all(Array.map(members, (type) => compileAst(type)));
393
+
394
+ if (firstValidator === undefined) {
395
+ return yield* new EmptyUnionIsNotSupportedError();
396
+ } else if (secondValidator === undefined) {
397
+ return firstValidator;
398
+ } else {
399
+ return v.union(firstValidator, secondValidator, ...restValidators);
400
+ }
401
+ });
402
+
403
+ const handleObjects = (objectsAst: SchemaAST.Objects) =>
404
+ pipe(
405
+ objectsAst.indexSignatures,
406
+ Array.head,
407
+ Option.match({
408
+ onNone: () => Effect.map(handlePropertySignatures(objectsAst), v.object),
409
+ onSome: ({ parameter, type }) =>
410
+ pipe(
411
+ objectsAst.propertySignatures,
412
+ Array.head,
413
+ Option.match({
414
+ onNone: () =>
415
+ Effect.map(
416
+ Effect.all({
417
+ parameter_: compileAst(parameter),
418
+ type_: compileAst(type),
419
+ }),
420
+ ({ parameter_, type_ }) => v.record(parameter_, type_),
421
+ ),
422
+ onSome: () =>
423
+ Effect.fail(
424
+ new MixedIndexAndPropertySignaturesAreNotSupportedError(),
425
+ ),
426
+ }),
427
+ ),
428
+ }),
429
+ );
430
+
431
+ const handleArrays = ({ elements, rest }: SchemaAST.Arrays) =>
432
+ Effect.gen(function* () {
433
+ const [f, s, ...r] = elements;
434
+
435
+ const elementToValidator = (element: SchemaAST.AST) =>
436
+ SchemaAST.isOptional(element)
437
+ ? Effect.fail(new OptionalTupleElementsAreNotSupportedError())
438
+ : compileAst(element);
439
+
440
+ const arrayItemsValidator = yield* f === undefined
441
+ ? pipe(
442
+ rest,
443
+ Array.head,
444
+ Option.match({
445
+ onNone: () => Effect.fail(new EmptyTupleIsNotSupportedError()),
446
+ onSome: (type) => compileAst(type),
447
+ }),
448
+ )
449
+ : s === undefined
450
+ ? elementToValidator(f)
451
+ : Effect.gen(function* () {
452
+ const firstValidator = yield* elementToValidator(f);
453
+ const secondValidator = yield* elementToValidator(s);
454
+ const restValidators = yield* Effect.forEach(r, elementToValidator);
455
+
456
+ return v.union(firstValidator, secondValidator, ...restValidators);
457
+ });
458
+
459
+ return v.array(arrayItemsValidator);
460
+ });
461
+
462
+ const handlePropertySignatures = (objectsAst: SchemaAST.Objects) =>
463
+ pipe(
464
+ objectsAst.propertySignatures,
465
+ Effect.forEach(({ type, name }) => {
466
+ const isOptional = SchemaAST.isOptional(type);
467
+ if (String.isString(name)) {
468
+ // Somehow, somewhere, keys of type number are being coerced to strings…
469
+ return Option.match(Number.parse(name), {
470
+ onNone: () =>
471
+ Effect.gen(function* () {
472
+ const validator = yield* compileAst(type, isOptional);
473
+
474
+ return {
475
+ propertyName: name,
476
+ validator: isOptional ? v.optional(validator) : validator,
477
+ };
478
+ }),
479
+ onSome: (number) =>
480
+ Effect.fail(
481
+ new UnsupportedPropertySignatureKeyTypeError({
482
+ propertyKey: number,
483
+ }),
484
+ ),
485
+ });
486
+ } else {
487
+ return Effect.fail(
488
+ new UnsupportedPropertySignatureKeyTypeError({ propertyKey: name }),
489
+ );
490
+ }
491
+ }),
492
+ Effect.andThen((propertyNamesWithValidators) =>
493
+ pipe(
494
+ propertyNamesWithValidators,
495
+ Array.reduce(
496
+ {} as Record<string, Validator<any, any, any>>,
497
+ (acc, { propertyName, validator }) => ({
498
+ [propertyName]: validator,
499
+ ...acc,
500
+ }),
501
+ ),
502
+ Effect.succeed,
503
+ ),
504
+ ),
505
+ );
506
+
507
+ // Errors
508
+
509
+ export class TopLevelMustBeObjectError extends Data.TaggedError(
510
+ "TopLevelMustBeObjectError",
511
+ ) {
512
+ /* v8 ignore start */
513
+ override get message() {
514
+ return "Top level schema must be an object";
515
+ }
516
+ /* v8 ignore stop */
517
+ }
518
+
519
+ export class TopLevelMustBeObjectOrUnionError extends Data.TaggedError(
520
+ "TopLevelMustBeObjectOrUnionError",
521
+ ) {
522
+ /* v8 ignore start */
523
+ override get message() {
524
+ return "Top level schema must be an object or a union";
525
+ }
526
+ /* v8 ignore stop */
527
+ }
528
+
529
+ export class UnsupportedPropertySignatureKeyTypeError extends Data.TaggedError(
530
+ "UnsupportedPropertySignatureKeyTypeError",
531
+ )<{
532
+ readonly propertyKey: number | symbol;
533
+ }> {
534
+ /* v8 ignore start */
535
+ override get message() {
536
+ return `Unsupported property signature '${this.propertyKey.toString()}'. Property is of type '${typeof this.propertyKey}' but only 'string' properties are supported.`;
537
+ }
538
+ /* v8 ignore stop */
539
+ }
540
+
541
+ export class EmptyTupleIsNotSupportedError extends Data.TaggedError(
542
+ "EmptyTupleIsNotSupportedError",
543
+ ) {
544
+ /* v8 ignore start */
545
+ override get message() {
546
+ return "Tuple must have at least one element";
547
+ }
548
+ /* v8 ignore stop */
549
+ }
550
+
551
+ export class EmptyUnionIsNotSupportedError extends Data.TaggedError(
552
+ "EmptyUnionIsNotSupportedError",
553
+ ) {
554
+ /* v8 ignore start */
555
+ override get message() {
556
+ return "Union must have at least one member that compiles to a validator";
557
+ }
558
+ /* v8 ignore stop */
559
+ }
560
+
561
+ export class UnsupportedSchemaTypeError extends Data.TaggedError(
562
+ "UnsupportedSchemaTypeError",
563
+ )<{
564
+ readonly schemaType: SchemaAST.AST["_tag"];
565
+ }> {
566
+ /* v8 ignore start */
567
+ override get message() {
568
+ return `Unsupported schema type '${this.schemaType}'`;
569
+ }
570
+ /* v8 ignore stop */
571
+ }
572
+
573
+ export class IndexSignaturesAreNotSupportedError extends Data.TaggedError(
574
+ "IndexSignaturesAreNotSupportedError",
575
+ ) {
576
+ /* v8 ignore start */
577
+ override get message() {
578
+ return "Index signatures are not supported";
579
+ }
580
+ /* v8 ignore stop */
581
+ }
582
+
583
+ export class MixedIndexAndPropertySignaturesAreNotSupportedError extends Data.TaggedError(
584
+ "MixedIndexAndPropertySignaturesAreNotSupportedError",
585
+ ) {
586
+ /* v8 ignore start */
587
+ override get message() {
588
+ return "Mixed index and property signatures are not supported";
589
+ }
590
+ /* v8 ignore stop */
591
+ }
592
+
593
+ export class OptionalTupleElementsAreNotSupportedError extends Data.TaggedError(
594
+ "OptionalTupleElementsAreNotSupportedError",
595
+ ) {
596
+ /* v8 ignore start */
597
+ override get message() {
598
+ return "Optional tuple elements are not supported";
599
+ }
600
+ /* v8 ignore stop */
601
+ }
package/src/Spec.ts CHANGED
@@ -2,7 +2,7 @@ import * as Predicate from "effect/Predicate";
2
2
  import * as Record from "effect/Record";
3
3
  import * as GroupSpec from "./GroupSpec";
4
4
 
5
- export const TypeId = "@confect/core/Spec";
5
+ export const TypeId = "~@confect/core/Spec";
6
6
  export type TypeId = typeof TypeId;
7
7
 
8
8
  export const isSpec = (u: unknown): u is AnyWithProps =>
@@ -23,6 +23,7 @@ export interface Spec<Groups_ extends GroupSpec.AnyWithProps = never> {
23
23
  GroupName
24
24
  >;
25
25
  };
26
+ readonly "~Groups": Groups_;
26
27
 
27
28
  add<Group extends GroupSpec.AnyWithProps>(
28
29
  group: Group,
@@ -40,8 +41,7 @@ export interface Any {
40
41
 
41
42
  export interface AnyWithProps extends Spec<GroupSpec.AnyWithProps> {}
42
43
 
43
- export type Groups<Spec_ extends AnyWithProps> =
44
- Spec_["groups"][keyof Spec_["groups"]];
44
+ export type Groups<Spec_ extends AnyWithProps> = Spec_["~Groups"];
45
45
 
46
46
  const Proto = {
47
47
  [TypeId]: TypeId,
@@ -70,6 +70,6 @@ const makeProto = <Groups_ extends GroupSpec.AnyWithProps>({
70
70
  }): Spec<Groups_> =>
71
71
  Object.assign(Object.create(Proto), {
72
72
  groups,
73
- });
73
+ }) as Spec<Groups_>;
74
74
 
75
75
  export const make = (): Spec => makeProto({ groups: {} });