@confect/core 10.0.0-next.22 → 10.0.0-next.24
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 +24 -0
- package/dist/FunctionProvenance.d.ts +34 -25
- package/dist/FunctionProvenance.d.ts.map +1 -1
- package/dist/FunctionProvenance.js +13 -11
- package/dist/FunctionProvenance.js.map +1 -1
- package/dist/FunctionSpec.d.ts +12 -8
- package/dist/FunctionSpec.d.ts.map +1 -1
- package/dist/FunctionSpec.js.map +1 -1
- package/dist/GroupPath.d.ts +5 -6
- package/dist/GroupPath.d.ts.map +1 -1
- package/dist/GroupPath.js.map +1 -1
- package/dist/GroupSpec.d.ts +5 -2
- package/dist/GroupSpec.d.ts.map +1 -1
- package/dist/GroupSpec.js +2 -2
- package/dist/GroupSpec.js.map +1 -1
- package/dist/Identifier.d.ts +5 -4
- package/dist/Identifier.d.ts.map +1 -1
- package/dist/Identifier.js +5 -4
- package/dist/Identifier.js.map +1 -1
- package/dist/Lazy.d.ts +11 -12
- package/dist/Lazy.d.ts.map +1 -1
- package/dist/Lazy.js +11 -12
- package/dist/Lazy.js.map +1 -1
- package/dist/MiddlewareSpec.d.ts +27 -25
- package/dist/MiddlewareSpec.d.ts.map +1 -1
- package/dist/MiddlewareSpec.js +8 -4
- package/dist/MiddlewareSpec.js.map +1 -1
- package/dist/PaginationError.d.ts +9 -3
- package/dist/PaginationError.d.ts.map +1 -1
- package/dist/PaginationError.js +9 -3
- package/dist/PaginationError.js.map +1 -1
- package/dist/PaginationOptions.d.ts +2 -2
- package/dist/PaginationOptions.js +2 -2
- package/dist/PaginationOptions.js.map +1 -1
- package/dist/Ref.d.ts +38 -32
- package/dist/Ref.d.ts.map +1 -1
- package/dist/Ref.js +25 -25
- package/dist/Ref.js.map +1 -1
- package/dist/Refs.d.ts +1 -1
- package/dist/Refs.d.ts.map +1 -1
- package/dist/Refs.js +2 -1
- package/dist/Refs.js.map +1 -1
- package/dist/Spec.d.ts +14 -11
- package/dist/Spec.d.ts.map +1 -1
- package/dist/Spec.js +13 -8
- package/dist/Spec.js.map +1 -1
- package/dist/SystemFields.d.ts +14 -12
- package/dist/SystemFields.d.ts.map +1 -1
- package/dist/SystemFields.js +11 -9
- package/dist/SystemFields.js.map +1 -1
- package/dist/Table.d.ts +1 -0
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +6 -5
- package/src/FunctionProvenance.ts +34 -25
- package/src/FunctionSpec.ts +12 -8
- package/src/GroupPath.ts +5 -6
- package/src/GroupSpec.ts +9 -5
- package/src/Identifier.ts +5 -4
- package/src/Lazy.ts +11 -12
- package/src/MiddlewareSpec.ts +27 -25
- package/src/PaginationError.ts +9 -3
- package/src/PaginationOptions.ts +2 -2
- package/src/Ref.ts +38 -32
- package/src/Refs.ts +2 -2
- package/src/Spec.ts +49 -38
- package/src/SystemFields.ts +22 -22
- package/src/Table.ts +1 -0
package/src/MiddlewareSpec.ts
CHANGED
|
@@ -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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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<
|
|
169
|
-
*
|
|
170
|
-
*
|
|
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
|
|
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
|
-
*
|
|
270
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
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,
|
package/src/PaginationError.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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> =>
|
package/src/PaginationOptions.ts
CHANGED
|
@@ -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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
485
|
-
* doesn't declare a typed-error schema—by definition such a value falls
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
*
|
|
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
|
-
*
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
550
|
-
*
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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(
|
|
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<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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<
|
|
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<
|
|
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]:
|
|
42
|
+
readonly [TypeId]: unknown;
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
export interface AnyWithProps extends
|
|
45
|
+
export interface AnyWithProps extends Any {
|
|
46
|
+
readonly [TypeId]: Record.ReadonlyRecord<string, GroupSpec.AnyWithProps>;
|
|
47
|
+
}
|
|
43
48
|
|
|
44
|
-
export type Groups<Spec_ extends AnyWithProps> =
|
|
49
|
+
export type Groups<Spec_ extends AnyWithProps> =
|
|
50
|
+
Spec_[TypeId][keyof Spec_[TypeId]];
|
|
45
51
|
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
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
|
|
61
|
-
|
|
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 =>
|
|
86
|
+
export const make = (): Spec => makeRecord({});
|
package/src/SystemFields.ts
CHANGED
|
@@ -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
|
|
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({
|
|
@@ -61,20 +62,18 @@ const splitSystemFields = (input: { [key: PropertyKey]: unknown }) => {
|
|
|
61
62
|
const wrapGetter = <R>(
|
|
62
63
|
getter: SchemaGetter.Getter<any, any, R>,
|
|
63
64
|
): SchemaGetter.Getter<any, any, R> =>
|
|
64
|
-
|
|
65
|
+
SchemaGetter.transformOptionalEffect((input, options) => {
|
|
65
66
|
if (Option.isNone(input) || !Predicate.isObject(input.value)) {
|
|
66
|
-
return
|
|
67
|
+
return SchemaGetter.run(getter, input, options);
|
|
67
68
|
}
|
|
68
69
|
const { system, rest } = splitSystemFields(input.value);
|
|
69
|
-
return getter
|
|
70
|
-
.
|
|
71
|
-
|
|
72
|
-
|
|
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 = (
|
|
@@ -154,10 +153,11 @@ 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
|
-
*
|
|
159
|
-
*
|
|
160
|
-
* `Schema.decodeTo`/`Schema.encodeKeys`, a branded struct, a suspended
|
|
156
|
+
* A plain `Struct` gains the fields via `Schema.fieldsAssign` and a `Union` has
|
|
157
|
+
* them distributed across its members, preserving the schema's `Struct`/`Union`
|
|
158
|
+
* structure. Any other object-shaped schema—one built with
|
|
159
|
+
* `Schema.decodeTo`/`Schema.encodeKeys`, a branded struct, a suspended
|
|
160
|
+
* schema—is extended at the AST level: every object node in its encoding chain
|
|
161
161
|
* gains the system fields, and each transformation is wrapped so the fields
|
|
162
162
|
* bypass the user-defined getters. Schemas that do not resolve to an object
|
|
163
163
|
* shape at every step (such as `Schema.Class`, whose decoded values are class
|
|
@@ -218,9 +218,9 @@ export const extendWithSystemFields = <
|
|
|
218
218
|
};
|
|
219
219
|
|
|
220
220
|
/**
|
|
221
|
-
* Applies the system fields to a single struct, mirroring
|
|
222
|
-
* Any other (already-extended or opaque) schema falls
|
|
223
|
-
* the system-field document shape.
|
|
221
|
+
* Applies the system fields to a single struct, mirroring
|
|
222
|
+
* `Schema.fieldsAssign`. Any other (already-extended or opaque) schema falls
|
|
223
|
+
* back to a `Codec` carrying the system-field document shape.
|
|
224
224
|
*/
|
|
225
225
|
type ApplySystemFields<TableName extends string, S> =
|
|
226
226
|
S extends Schema.Struct<infer Fields extends Schema.Struct.Fields>
|
|
@@ -240,10 +240,10 @@ type ApplySystemFields<TableName extends string, S> =
|
|
|
240
240
|
* This mirrors the runtime {@link extendWithSystemFields}: a `Struct` gains the
|
|
241
241
|
* system fields directly (matching `Schema.fieldsAssign`), and a `Union` has
|
|
242
242
|
* them distributed across its members (matching
|
|
243
|
-
* `union.mapMembers(Tuple.map(Schema.fieldsAssign(...)))`). The
|
|
244
|
-
* structure is preserved rather than collapsed to a bare
|
|
245
|
-
* schema falls back to a `Codec` carrying the system-field
|
|
246
|
-
* matching the runtime's AST-level extension.
|
|
243
|
+
* `union.mapMembers(Tuple.map(Schema.fieldsAssign(...)))`). The
|
|
244
|
+
* `Struct`/`Union` structure is preserved rather than collapsed to a bare
|
|
245
|
+
* `Codec`; any other schema falls back to a `Codec` carrying the system-field
|
|
246
|
+
* document shape, matching the runtime's AST-level extension.
|
|
247
247
|
*/
|
|
248
248
|
export type ExtendWithSystemFields<
|
|
249
249
|
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>> =
|