@confect/core 6.0.0 → 7.0.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.
- package/CHANGELOG.md +122 -0
- package/dist/FunctionProvenance.d.ts +12 -3
- package/dist/FunctionProvenance.d.ts.map +1 -1
- package/dist/FunctionProvenance.js +3 -2
- package/dist/FunctionProvenance.js.map +1 -1
- package/dist/FunctionSpec.d.ts +48 -26
- package/dist/FunctionSpec.d.ts.map +1 -1
- package/dist/FunctionSpec.js +2 -2
- package/dist/FunctionSpec.js.map +1 -1
- package/dist/GroupSpec.d.ts +6 -6
- package/dist/Ref.d.ts +59 -25
- package/dist/Ref.d.ts.map +1 -1
- package/dist/Ref.js +70 -15
- package/dist/Ref.js.map +1 -1
- package/package.json +1 -1
- package/src/FunctionProvenance.ts +7 -0
- package/src/FunctionSpec.ts +26 -2
- package/src/Ref.ts +193 -45
package/src/Ref.ts
CHANGED
|
@@ -3,8 +3,10 @@ import type {
|
|
|
3
3
|
FunctionVisibility,
|
|
4
4
|
} from "convex/server";
|
|
5
5
|
import { makeFunctionReference } from "convex/server";
|
|
6
|
+
import type { Value } from "convex/values";
|
|
7
|
+
import { ConvexError } from "convex/values";
|
|
6
8
|
import type { ParseResult } from "effect";
|
|
7
|
-
import { Effect, Match, Schema } from "effect";
|
|
9
|
+
import { Effect, Match, Option, Schema } from "effect";
|
|
8
10
|
import type * as FunctionSpec from "./FunctionSpec";
|
|
9
11
|
import type * as RuntimeAndFunctionType from "./RuntimeAndFunctionType";
|
|
10
12
|
|
|
@@ -13,27 +15,30 @@ export interface Ref<
|
|
|
13
15
|
_FunctionVisibility extends FunctionVisibility,
|
|
14
16
|
_Args,
|
|
15
17
|
_Returns,
|
|
18
|
+
_Error = never,
|
|
16
19
|
> {
|
|
17
20
|
readonly _RuntimeAndFunctionType?: _RuntimeAndFunctionType;
|
|
18
21
|
readonly _FunctionVisibility?: _FunctionVisibility;
|
|
19
22
|
readonly _Args?: _Args;
|
|
20
23
|
readonly _Returns?: _Returns;
|
|
24
|
+
readonly _Error?: _Error;
|
|
21
25
|
/** @internal */
|
|
22
26
|
readonly functionSpec: FunctionSpec.AnyWithProps;
|
|
23
27
|
/** @internal */
|
|
24
28
|
readonly functionNamespace: string;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
export interface Any extends Ref<any, any, any, any> {}
|
|
31
|
+
export interface Any extends Ref<any, any, any, any, any> {}
|
|
28
32
|
|
|
29
|
-
export interface AnyInternal extends Ref<any, "internal", any, any> {}
|
|
33
|
+
export interface AnyInternal extends Ref<any, "internal", any, any, any> {}
|
|
30
34
|
|
|
31
|
-
export interface AnyPublic extends Ref<any, "public", any, any> {}
|
|
35
|
+
export interface AnyPublic extends Ref<any, "public", any, any, any> {}
|
|
32
36
|
|
|
33
37
|
export interface AnyQuery extends Ref<
|
|
34
38
|
RuntimeAndFunctionType.AnyQuery,
|
|
35
39
|
FunctionVisibility,
|
|
36
40
|
any,
|
|
41
|
+
any,
|
|
37
42
|
any
|
|
38
43
|
> {}
|
|
39
44
|
|
|
@@ -41,6 +46,7 @@ export interface AnyMutation extends Ref<
|
|
|
41
46
|
RuntimeAndFunctionType.AnyMutation,
|
|
42
47
|
FunctionVisibility,
|
|
43
48
|
any,
|
|
49
|
+
any,
|
|
44
50
|
any
|
|
45
51
|
> {}
|
|
46
52
|
|
|
@@ -48,6 +54,7 @@ export interface AnyAction extends Ref<
|
|
|
48
54
|
RuntimeAndFunctionType.AnyAction,
|
|
49
55
|
FunctionVisibility,
|
|
50
56
|
any,
|
|
57
|
+
any,
|
|
51
58
|
any
|
|
52
59
|
> {}
|
|
53
60
|
|
|
@@ -55,6 +62,7 @@ export interface AnyPublicQuery extends Ref<
|
|
|
55
62
|
RuntimeAndFunctionType.AnyQuery,
|
|
56
63
|
"public",
|
|
57
64
|
any,
|
|
65
|
+
any,
|
|
58
66
|
any
|
|
59
67
|
> {}
|
|
60
68
|
|
|
@@ -62,6 +70,7 @@ export interface AnyPublicMutation extends Ref<
|
|
|
62
70
|
RuntimeAndFunctionType.AnyMutation,
|
|
63
71
|
"public",
|
|
64
72
|
any,
|
|
73
|
+
any,
|
|
65
74
|
any
|
|
66
75
|
> {}
|
|
67
76
|
|
|
@@ -69,6 +78,7 @@ export interface AnyPublicAction extends Ref<
|
|
|
69
78
|
RuntimeAndFunctionType.AnyAction,
|
|
70
79
|
"public",
|
|
71
80
|
any,
|
|
81
|
+
any,
|
|
72
82
|
any
|
|
73
83
|
> {}
|
|
74
84
|
|
|
@@ -77,7 +87,8 @@ export type GetRuntimeAndFunctionType<Ref_> =
|
|
|
77
87
|
infer RuntimeAndFunctionType_,
|
|
78
88
|
infer _FunctionVisibility,
|
|
79
89
|
infer _Args,
|
|
80
|
-
infer _Returns
|
|
90
|
+
infer _Returns,
|
|
91
|
+
infer _Error
|
|
81
92
|
>
|
|
82
93
|
? RuntimeAndFunctionType_
|
|
83
94
|
: never;
|
|
@@ -87,7 +98,8 @@ export type GetRuntime<Ref_> =
|
|
|
87
98
|
infer RuntimeAndFunctionType_,
|
|
88
99
|
infer _FunctionVisibility,
|
|
89
100
|
infer _Args,
|
|
90
|
-
infer _Returns
|
|
101
|
+
infer _Returns,
|
|
102
|
+
infer _Error
|
|
91
103
|
>
|
|
92
104
|
? RuntimeAndFunctionType.GetRuntime<RuntimeAndFunctionType_>
|
|
93
105
|
: never;
|
|
@@ -97,7 +109,8 @@ export type GetFunctionType<Ref_> =
|
|
|
97
109
|
infer RuntimeAndFunctionType_,
|
|
98
110
|
infer _FunctionVisibility,
|
|
99
111
|
infer _Args,
|
|
100
|
-
infer _Returns
|
|
112
|
+
infer _Returns,
|
|
113
|
+
infer _Error
|
|
101
114
|
>
|
|
102
115
|
? RuntimeAndFunctionType.GetFunctionType<RuntimeAndFunctionType_>
|
|
103
116
|
: never;
|
|
@@ -107,7 +120,8 @@ export type GetFunctionVisibility<Ref_> =
|
|
|
107
120
|
infer _RuntimeAndFunctionType,
|
|
108
121
|
infer FunctionVisibility_,
|
|
109
122
|
infer _Args,
|
|
110
|
-
infer _Returns
|
|
123
|
+
infer _Returns,
|
|
124
|
+
infer _Error
|
|
111
125
|
>
|
|
112
126
|
? FunctionVisibility_
|
|
113
127
|
: never;
|
|
@@ -117,7 +131,8 @@ export type Args<Ref_> =
|
|
|
117
131
|
infer _RuntimeAndFunctionType,
|
|
118
132
|
infer _FunctionVisibility,
|
|
119
133
|
infer Args_,
|
|
120
|
-
infer _Returns
|
|
134
|
+
infer _Returns,
|
|
135
|
+
infer _Error
|
|
121
136
|
>
|
|
122
137
|
? Args_
|
|
123
138
|
: never;
|
|
@@ -131,11 +146,23 @@ export type Returns<Ref_> =
|
|
|
131
146
|
infer _RuntimeAndFunctionType,
|
|
132
147
|
infer _FunctionVisibility,
|
|
133
148
|
infer _Args,
|
|
134
|
-
infer Returns_
|
|
149
|
+
infer Returns_,
|
|
150
|
+
infer _Error
|
|
135
151
|
>
|
|
136
152
|
? Returns_
|
|
137
153
|
: never;
|
|
138
154
|
|
|
155
|
+
export type Error<Ref_> =
|
|
156
|
+
Ref_ extends Ref<
|
|
157
|
+
infer _RuntimeAndFunctionType,
|
|
158
|
+
infer _FunctionVisibility,
|
|
159
|
+
infer _Args,
|
|
160
|
+
infer _Returns,
|
|
161
|
+
infer Error_
|
|
162
|
+
>
|
|
163
|
+
? Error_
|
|
164
|
+
: never;
|
|
165
|
+
|
|
139
166
|
export type FunctionReference<Ref_ extends Any> = ConvexFunctionReference<
|
|
140
167
|
GetFunctionType<Ref_>,
|
|
141
168
|
GetFunctionVisibility<Ref_>
|
|
@@ -146,7 +173,8 @@ export type FromFunctionSpec<FunctionSpec_ extends FunctionSpec.AnyWithProps> =
|
|
|
146
173
|
FunctionSpec.GetRuntimeAndFunctionType<FunctionSpec_>,
|
|
147
174
|
FunctionSpec.GetFunctionVisibility<FunctionSpec_>,
|
|
148
175
|
FunctionSpec.Args<FunctionSpec_>,
|
|
149
|
-
FunctionSpec.Returns<FunctionSpec_
|
|
176
|
+
FunctionSpec.Returns<FunctionSpec_>,
|
|
177
|
+
FunctionSpec.Error<FunctionSpec_>
|
|
150
178
|
>;
|
|
151
179
|
|
|
152
180
|
export const make = <FunctionSpec_ extends FunctionSpec.AnyWithProps>(
|
|
@@ -167,12 +195,25 @@ export const getFunctionReference = <Ref_ extends Any>(
|
|
|
167
195
|
): FunctionReference<Ref_> =>
|
|
168
196
|
makeFunctionReference(getConvexFunctionName(ref)) as FunctionReference<Ref_>;
|
|
169
197
|
|
|
198
|
+
export const hasErrorSchema = (ref: Any): boolean =>
|
|
199
|
+
Match.value(ref.functionSpec.functionProvenance).pipe(
|
|
200
|
+
Match.tag(
|
|
201
|
+
"Confect",
|
|
202
|
+
(confectFunctionProvenance) =>
|
|
203
|
+
confectFunctionProvenance.error !== undefined,
|
|
204
|
+
),
|
|
205
|
+
Match.tag("Convex", () => false),
|
|
206
|
+
Match.exhaustive,
|
|
207
|
+
);
|
|
208
|
+
|
|
170
209
|
export const encodeArgs = <Ref_ extends Any>(
|
|
171
210
|
ref: Ref_,
|
|
172
211
|
args: Args<Ref_>,
|
|
173
212
|
): Effect.Effect<unknown, ParseResult.ParseError> =>
|
|
174
213
|
Match.value(ref.functionSpec.functionProvenance).pipe(
|
|
175
|
-
Match.tag("Confect", (
|
|
214
|
+
Match.tag("Confect", (confectFunctionProvenance) =>
|
|
215
|
+
Schema.encode(confectFunctionProvenance.args)(args),
|
|
216
|
+
),
|
|
176
217
|
Match.tag("Convex", () => Effect.succeed(args)),
|
|
177
218
|
Match.exhaustive,
|
|
178
219
|
);
|
|
@@ -182,7 +223,9 @@ export const decodeReturns = <Ref_ extends Any>(
|
|
|
182
223
|
returns: unknown,
|
|
183
224
|
): Effect.Effect<Returns<Ref_>, ParseResult.ParseError> =>
|
|
184
225
|
Match.value(ref.functionSpec.functionProvenance).pipe(
|
|
185
|
-
Match.tag("Confect", (
|
|
226
|
+
Match.tag("Confect", (confectFunctionProvenance) =>
|
|
227
|
+
Schema.decode(confectFunctionProvenance.returns)(returns),
|
|
228
|
+
),
|
|
186
229
|
Match.tag("Convex", () => Effect.succeed(returns)),
|
|
187
230
|
Match.exhaustive,
|
|
188
231
|
);
|
|
@@ -192,7 +235,9 @@ export const encodeArgsSync = <Ref_ extends Any>(
|
|
|
192
235
|
args: Args<Ref_>,
|
|
193
236
|
): unknown =>
|
|
194
237
|
Match.value(ref.functionSpec.functionProvenance).pipe(
|
|
195
|
-
Match.tag("Confect", (
|
|
238
|
+
Match.tag("Confect", (confectFunctionProvenance) =>
|
|
239
|
+
Schema.encodeSync(confectFunctionProvenance.args)(args),
|
|
240
|
+
),
|
|
196
241
|
Match.tag("Convex", () => args),
|
|
197
242
|
Match.exhaustive,
|
|
198
243
|
);
|
|
@@ -202,52 +247,155 @@ export const decodeReturnsSync = <Ref_ extends Any>(
|
|
|
202
247
|
encodedReturns: unknown,
|
|
203
248
|
): Returns<Ref_> =>
|
|
204
249
|
Match.value(ref.functionSpec.functionProvenance).pipe(
|
|
205
|
-
Match.tag("Confect", (
|
|
250
|
+
Match.tag("Confect", (confectFunctionProvenance) =>
|
|
251
|
+
Schema.decodeSync(confectFunctionProvenance.returns)(encodedReturns),
|
|
252
|
+
),
|
|
206
253
|
Match.tag("Convex", () => encodedReturns),
|
|
207
254
|
Match.exhaustive,
|
|
208
255
|
) as Returns<Ref_>;
|
|
209
256
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
257
|
+
const ConvexErrorIdentifier = Symbol.for("ConvexError");
|
|
258
|
+
|
|
259
|
+
export const isConvexError = (error: unknown): error is ConvexError<Value> =>
|
|
260
|
+
error instanceof ConvexError ||
|
|
261
|
+
(typeof error === "object" &&
|
|
262
|
+
error !== null &&
|
|
263
|
+
ConvexErrorIdentifier in error);
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Build a callback-style handler that decodes the ref's typed error from a
|
|
267
|
+
* caught `ConvexError`, or else forwards the value to `mapUnknownError`. The
|
|
268
|
+
* fallback is also invoked when the input *is* a `ConvexError` but the ref
|
|
269
|
+
* doesn't declare a typed-error schema—by definition such a value falls
|
|
270
|
+
* outside the ref's error contract. Useful when adapting non-Effect APIs (e.g.
|
|
271
|
+
* emitter callbacks for streamed subscriptions) to the same error semantics
|
|
272
|
+
* that `runWithCodec` provides.
|
|
273
|
+
*/
|
|
274
|
+
export const decodeErrorOrElse =
|
|
275
|
+
<Ref_ extends Any, E>(ref: Ref_, mapUnknownError: (error: unknown) => E) =>
|
|
276
|
+
(error: unknown): Error<Ref_> | E => {
|
|
277
|
+
if (isConvexError(error)) {
|
|
278
|
+
const decoded = decodeErrorSync(ref, error.data);
|
|
279
|
+
if (Option.isSome(decoded)) {
|
|
280
|
+
return decoded.value;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return mapUnknownError(error);
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Decode `encodedError` against the ref's error schema. Returns `None` if the
|
|
288
|
+
* ref doesn't declare a typed error (Confect ref without an `error` schema, or
|
|
289
|
+
* a Convex-provenance ref)—by definition there's nothing to decode the value
|
|
290
|
+
* into, and the caller is responsible for deciding what to do (typically:
|
|
291
|
+
* surface the original value as a defect).
|
|
292
|
+
*/
|
|
293
|
+
export const decodeError = <Ref_ extends Any>(
|
|
294
|
+
ref: Ref_,
|
|
295
|
+
encodedError: unknown,
|
|
296
|
+
): Effect.Effect<Option.Option<Error<Ref_>>, ParseResult.ParseError> =>
|
|
297
|
+
Match.value(ref.functionSpec.functionProvenance).pipe(
|
|
298
|
+
Match.tag("Confect", (confectFunctionProvenance) =>
|
|
299
|
+
confectFunctionProvenance.error !== undefined
|
|
300
|
+
? Effect.map(
|
|
301
|
+
Schema.decode(confectFunctionProvenance.error)(encodedError),
|
|
302
|
+
Option.some,
|
|
303
|
+
)
|
|
304
|
+
: Effect.succeed(Option.none<Error<Ref_>>()),
|
|
305
|
+
),
|
|
306
|
+
Match.tag("Convex", () => Effect.succeed(Option.none<Error<Ref_>>())),
|
|
307
|
+
Match.exhaustive,
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Synchronous counterpart to `decodeError`. Throws on schema decode failure;
|
|
312
|
+
* returns `None` when the ref doesn't declare a typed error.
|
|
313
|
+
*/
|
|
314
|
+
export const decodeErrorSync = <Ref_ extends Any>(
|
|
315
|
+
ref: Ref_,
|
|
316
|
+
encodedError: unknown,
|
|
317
|
+
): Option.Option<Error<Ref_>> =>
|
|
318
|
+
Match.value(ref.functionSpec.functionProvenance).pipe(
|
|
319
|
+
Match.tag("Confect", (confectFunctionProvenance) =>
|
|
320
|
+
confectFunctionProvenance.error !== undefined
|
|
321
|
+
? Option.some(
|
|
322
|
+
Schema.decodeSync(confectFunctionProvenance.error)(
|
|
323
|
+
encodedError,
|
|
324
|
+
) as Error<Ref_>,
|
|
325
|
+
)
|
|
326
|
+
: Option.none<Error<Ref_>>(),
|
|
327
|
+
),
|
|
328
|
+
Match.tag("Convex", () => Option.none<Error<Ref_>>()),
|
|
329
|
+
Match.exhaustive,
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
export const maybeDecodeErrorSync = <Ref_ extends Any>(
|
|
333
|
+
ref: Ref_,
|
|
334
|
+
error: unknown,
|
|
335
|
+
): unknown =>
|
|
336
|
+
isConvexError(error)
|
|
337
|
+
? Match.value(ref.functionSpec.functionProvenance).pipe(
|
|
338
|
+
Match.tag("Confect", (confectFunctionProvenance) =>
|
|
339
|
+
confectFunctionProvenance.error !== undefined
|
|
340
|
+
? Schema.decodeSync(confectFunctionProvenance.error)(error.data)
|
|
341
|
+
: error,
|
|
342
|
+
),
|
|
343
|
+
Match.tag("Convex", () => error),
|
|
344
|
+
Match.exhaustive,
|
|
345
|
+
)
|
|
346
|
+
: error;
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Encode args via the ref's args schema, invoke `call`, decode returns via the
|
|
350
|
+
* ref's returns schema, and translate any thrown `ConvexError` into the ref's
|
|
351
|
+
* typed error. Anything else the Promise rejects with—network failures,
|
|
352
|
+
* server-side runtime errors, validation failures, etc.—is passed to
|
|
353
|
+
* `mapUnknownError` to be turned into a typed `E`, or surfaced as a defect when
|
|
354
|
+
* no handler is provided.
|
|
355
|
+
*/
|
|
356
|
+
export const runWithCodec = <Ref_ extends Any, E = never>(
|
|
228
357
|
ref: Ref_,
|
|
229
358
|
args: Args<Ref_>,
|
|
230
|
-
|
|
359
|
+
call: (
|
|
231
360
|
functionReference: FunctionReference<Ref_>,
|
|
232
361
|
encodedArgs: unknown,
|
|
233
|
-
) =>
|
|
234
|
-
|
|
362
|
+
) => PromiseLike<unknown>,
|
|
363
|
+
mapUnknownError?: (error: unknown) => E,
|
|
364
|
+
): Effect.Effect<Returns<Ref_>, E | Error<Ref_> | ParseResult.ParseError> =>
|
|
235
365
|
Effect.gen(function* () {
|
|
236
366
|
const functionReference = getFunctionReference(ref);
|
|
237
367
|
const functionProvenance = ref.functionSpec.functionProvenance;
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
368
|
+
const invoke = (
|
|
369
|
+
encodedArgs: unknown,
|
|
370
|
+
): Effect.Effect<unknown, Error<Ref_> | E> =>
|
|
371
|
+
Effect.tryPromise({
|
|
372
|
+
try: () => Promise.resolve(call(functionReference, encodedArgs)),
|
|
373
|
+
catch: (error): Error<Ref_> | E => {
|
|
374
|
+
if (isConvexError(error)) {
|
|
375
|
+
const decoded = decodeErrorSync(ref, error.data);
|
|
376
|
+
if (Option.isSome(decoded)) {
|
|
377
|
+
return decoded.value;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (mapUnknownError !== undefined) {
|
|
381
|
+
return mapUnknownError(error);
|
|
382
|
+
}
|
|
383
|
+
throw error;
|
|
384
|
+
},
|
|
385
|
+
});
|
|
242
386
|
return yield* Match.value(functionProvenance).pipe(
|
|
243
|
-
Match.tag("Confect", (
|
|
387
|
+
Match.tag("Confect", (confectFunctionProvenance) =>
|
|
244
388
|
Effect.gen(function* () {
|
|
245
|
-
const encodedArgs = yield* Schema.encode(
|
|
246
|
-
|
|
247
|
-
|
|
389
|
+
const encodedArgs = yield* Schema.encode(
|
|
390
|
+
confectFunctionProvenance.args,
|
|
391
|
+
)(args);
|
|
392
|
+
const encodedReturns = yield* invoke(encodedArgs);
|
|
393
|
+
return yield* Schema.decode(confectFunctionProvenance.returns)(
|
|
394
|
+
encodedReturns,
|
|
395
|
+
);
|
|
248
396
|
}),
|
|
249
397
|
),
|
|
250
|
-
Match.tag("Convex", () =>
|
|
398
|
+
Match.tag("Convex", () => invoke(args)),
|
|
251
399
|
Match.exhaustive,
|
|
252
400
|
);
|
|
253
401
|
});
|