@confect/core 10.0.0-next.1 → 10.0.0-next.11
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 +144 -0
- package/dist/FunctionProvenance.d.ts +74 -3
- package/dist/FunctionProvenance.d.ts.map +1 -1
- package/dist/FunctionProvenance.js +44 -4
- package/dist/FunctionProvenance.js.map +1 -1
- package/dist/FunctionSpec.d.ts +42 -9
- package/dist/FunctionSpec.d.ts.map +1 -1
- package/dist/FunctionSpec.js +17 -4
- package/dist/FunctionSpec.js.map +1 -1
- package/dist/GenericId.js +2 -3
- package/dist/GenericId.js.map +1 -1
- package/dist/GroupPath.js +1 -2
- package/dist/GroupSpec.js +1 -2
- package/dist/GroupSpec.js.map +1 -1
- package/dist/Identifier.js +3 -4
- package/dist/Identifier.js.map +1 -1
- package/dist/Lazy.js +1 -2
- package/dist/Lazy.js.map +1 -1
- package/dist/PaginationOptions.d.ts +23 -0
- package/dist/PaginationOptions.d.ts.map +1 -0
- package/dist/PaginationOptions.js +29 -0
- package/dist/PaginationOptions.js.map +1 -0
- package/dist/PaginationResult.d.ts +1 -0
- package/dist/PaginationResult.d.ts.map +1 -1
- package/dist/PaginationResult.js +1 -2
- package/dist/PaginationResult.js.map +1 -1
- package/dist/Ref.d.ts +34 -5
- package/dist/Ref.d.ts.map +1 -1
- package/dist/Ref.js +51 -13
- package/dist/Ref.js.map +1 -1
- package/dist/Refs.js +1 -2
- package/dist/Refs.js.map +1 -1
- package/dist/Registry.js +1 -2
- package/dist/Registry.js.map +1 -1
- package/dist/RuntimeAndFunctionType.js +1 -2
- package/dist/RuntimeAndFunctionType.js.map +1 -1
- package/dist/Spec.js +1 -2
- package/dist/Spec.js.map +1 -1
- package/dist/SystemFields.d.ts.map +1 -1
- package/dist/SystemFields.js +2 -3
- package/dist/SystemFields.js.map +1 -1
- package/dist/Types.d.ts +1 -1
- package/dist/Types.d.ts.map +1 -1
- package/dist/Types.js +1 -2
- package/dist/Types.js.map +1 -1
- package/dist/UserIdentity.js +1 -2
- package/dist/UserIdentity.js.map +1 -1
- package/dist/_virtual/_rolldown/runtime.js +6 -11
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/tsconfig.src.tsbuildinfo +1 -1
- package/package.json +12 -11
- package/src/FunctionProvenance.ts +147 -4
- package/src/FunctionSpec.ts +67 -1
- package/src/PaginationOptions.ts +23 -0
- package/src/PaginationResult.ts +4 -0
- package/src/Ref.ts +90 -25
- package/src/SystemFields.ts +2 -5
- package/src/Types.ts +5 -1
- 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>() =>
|
package/src/FunctionSpec.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type {
|
|
|
5
5
|
RegisteredMutation,
|
|
6
6
|
RegisteredQuery,
|
|
7
7
|
} from "convex/server";
|
|
8
|
-
import
|
|
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
|
+
});
|
package/src/PaginationResult.ts
CHANGED
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 =
|
|
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`.
|
|
354
|
-
*
|
|
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
|
|
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
|
-
?
|
|
364
|
-
|
|
365
|
-
|
|
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
|
-
|
|
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
|
-
|
|
420
|
+
args: Omit<Args<Ref_>, "paginationOpts">,
|
|
377
421
|
): unknown =>
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
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 =
|
|
484
|
+
const decoded = decodeErrorOption(ref, error.data);
|
|
420
485
|
if (Option.isSome(decoded)) {
|
|
421
486
|
return decoded.value;
|
|
422
487
|
}
|
package/src/SystemFields.ts
CHANGED
|
@@ -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
|
|
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
|
-
: {
|
|
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";
|