fluent-convex 0.7.1 → 0.7.2

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.
@@ -0,0 +1,277 @@
1
+ import type { GenericDataModel } from "convex/server";
2
+ import { InferredArgs } from "./types";
3
+ import { InferHandlerReturn } from "./types";
4
+ import { ConvexBuilderDef } from "./types";
5
+ import { CallableBuilder } from "./types";
6
+ import { ConvexBuilderWithHandler } from "./ConvexBuilderWithHandler";
7
+ import type { ConvexMiddleware, AnyConvexMiddleware } from "./middleware";
8
+ import type {
9
+ FunctionType,
10
+ Context,
11
+ EmptyObject,
12
+ ConvexArgsValidator,
13
+ ConvexReturnsValidator,
14
+ QueryCtx,
15
+ MutationCtx,
16
+ ActionCtx,
17
+ } from "./types";
18
+ import {
19
+ type ValidatorInput,
20
+ type ToConvexArgsValidator,
21
+ isZodSchema,
22
+ toConvexValidator,
23
+ type ReturnsValidatorInput,
24
+ type ToConvexReturnsValidator,
25
+ } from "./zod_support";
26
+
27
+ export class ConvexBuilder<
28
+ TDataModel extends GenericDataModel = GenericDataModel,
29
+ TFunctionType extends FunctionType | undefined = undefined,
30
+ TInitialContext extends Context = EmptyObject,
31
+ TCurrentContext extends Context = EmptyObject,
32
+ TArgsValidator extends ConvexArgsValidator | undefined = undefined,
33
+ TReturnsValidator extends ConvexReturnsValidator | undefined = undefined,
34
+ > {
35
+ protected def: ConvexBuilderDef<
36
+ TFunctionType,
37
+ TArgsValidator,
38
+ TReturnsValidator
39
+ >;
40
+
41
+ constructor(
42
+ def: ConvexBuilderDef<TFunctionType, TArgsValidator, TReturnsValidator>
43
+ ) {
44
+ this.def = def;
45
+ }
46
+
47
+ query(
48
+ this: ConvexBuilder<
49
+ TDataModel,
50
+ undefined,
51
+ TInitialContext,
52
+ TCurrentContext,
53
+ TArgsValidator,
54
+ TReturnsValidator
55
+ >
56
+ ): ConvexBuilder<
57
+ TDataModel,
58
+ "query",
59
+ QueryCtx<TDataModel>,
60
+ QueryCtx<TDataModel>
61
+ > {
62
+ return new ConvexBuilder({
63
+ ...this.def,
64
+ functionType: "query",
65
+ }) as any;
66
+ }
67
+
68
+ mutation(
69
+ this: ConvexBuilder<
70
+ TDataModel,
71
+ undefined,
72
+ TInitialContext,
73
+ TCurrentContext,
74
+ TArgsValidator,
75
+ TReturnsValidator
76
+ >
77
+ ): ConvexBuilder<
78
+ TDataModel,
79
+ "mutation",
80
+ MutationCtx<TDataModel>,
81
+ MutationCtx<TDataModel>
82
+ > {
83
+ return new ConvexBuilder({
84
+ ...this.def,
85
+ functionType: "mutation",
86
+ }) as any;
87
+ }
88
+
89
+ action(
90
+ this: ConvexBuilder<
91
+ TDataModel,
92
+ undefined,
93
+ TInitialContext,
94
+ TCurrentContext,
95
+ TArgsValidator,
96
+ TReturnsValidator
97
+ >
98
+ ): ConvexBuilder<
99
+ TDataModel,
100
+ "action",
101
+ ActionCtx<TDataModel>,
102
+ ActionCtx<TDataModel>
103
+ > {
104
+ return new ConvexBuilder({
105
+ ...this.def,
106
+ functionType: "action",
107
+ }) as any;
108
+ }
109
+
110
+ $context<U extends Context>(): ConvexBuilder<
111
+ TDataModel,
112
+ TFunctionType,
113
+ U & EmptyObject,
114
+ U,
115
+ TArgsValidator,
116
+ TReturnsValidator
117
+ > {
118
+ return new ConvexBuilder({
119
+ ...this.def,
120
+ middlewares: [],
121
+ }) as any;
122
+ }
123
+
124
+ middleware<UOutContext extends Context>(
125
+ middleware: ConvexMiddleware<TInitialContext, UOutContext>
126
+ ): ConvexMiddleware<TInitialContext, UOutContext>;
127
+ middleware<UInContext extends Context, UOutContext extends Context>(
128
+ middleware: ConvexMiddleware<UInContext, UOutContext>
129
+ ): ConvexMiddleware<UInContext, UOutContext>;
130
+ middleware<UInContext extends Context, UOutContext extends Context>(
131
+ middleware: ConvexMiddleware<UInContext, UOutContext>
132
+ ): ConvexMiddleware<UInContext, UOutContext> {
133
+ return middleware;
134
+ }
135
+
136
+ use<UOutContext extends Context>(
137
+ this: ConvexBuilder<
138
+ TDataModel,
139
+ FunctionType,
140
+ TInitialContext,
141
+ TCurrentContext,
142
+ TArgsValidator,
143
+ TReturnsValidator
144
+ >,
145
+ middleware: ConvexMiddleware<TCurrentContext, UOutContext>
146
+ ): ConvexBuilder<
147
+ TDataModel,
148
+ TFunctionType,
149
+ TInitialContext,
150
+ TCurrentContext & UOutContext,
151
+ TArgsValidator,
152
+ TReturnsValidator
153
+ > {
154
+ return new ConvexBuilder({
155
+ ...this.def,
156
+ middlewares: [...this.def.middlewares, middleware as AnyConvexMiddleware],
157
+ }) as any;
158
+ }
159
+
160
+ input<UInput extends ValidatorInput>(
161
+ this: ConvexBuilder<
162
+ TDataModel,
163
+ FunctionType,
164
+ TInitialContext,
165
+ TCurrentContext,
166
+ TArgsValidator,
167
+ TReturnsValidator
168
+ >,
169
+ validator: UInput
170
+ ): ConvexBuilder<
171
+ TDataModel,
172
+ TFunctionType,
173
+ TInitialContext,
174
+ TCurrentContext,
175
+ ToConvexArgsValidator<UInput>,
176
+ TReturnsValidator
177
+ > {
178
+ const convexValidator = (
179
+ isZodSchema(validator) ? toConvexValidator(validator) : validator
180
+ ) as ToConvexArgsValidator<UInput>;
181
+
182
+ return new ConvexBuilder({
183
+ ...this.def,
184
+ argsValidator: convexValidator,
185
+ }) as any;
186
+ }
187
+
188
+ returns<UReturns extends ReturnsValidatorInput>(
189
+ this: ConvexBuilder<
190
+ TDataModel,
191
+ FunctionType,
192
+ TInitialContext,
193
+ TCurrentContext,
194
+ TArgsValidator,
195
+ TReturnsValidator
196
+ >,
197
+ validator: UReturns
198
+ ): ConvexBuilder<
199
+ TDataModel,
200
+ TFunctionType,
201
+ TInitialContext,
202
+ TCurrentContext,
203
+ TArgsValidator,
204
+ ToConvexReturnsValidator<UReturns>
205
+ > {
206
+ const convexValidator = (
207
+ isZodSchema(validator) ? toConvexValidator(validator) : validator
208
+ ) as ToConvexReturnsValidator<UReturns>;
209
+
210
+ return new ConvexBuilder({
211
+ ...this.def,
212
+ returnsValidator: convexValidator,
213
+ }) as any;
214
+ }
215
+
216
+ handler<
217
+ TReturn extends InferHandlerReturn<
218
+ TReturnsValidator,
219
+ any
220
+ > = InferHandlerReturn<TReturnsValidator, any>,
221
+ >(
222
+ this: ConvexBuilder<
223
+ TDataModel,
224
+ FunctionType,
225
+ TInitialContext,
226
+ TCurrentContext,
227
+ TArgsValidator,
228
+ TReturnsValidator
229
+ >,
230
+ handlerFn: (options: {
231
+ context: TCurrentContext;
232
+ input: InferredArgs<TArgsValidator>;
233
+ }) => Promise<TReturn>
234
+ ): ConvexBuilderWithHandler<
235
+ TDataModel,
236
+ TFunctionType & FunctionType,
237
+ TCurrentContext,
238
+ TArgsValidator,
239
+ TReturnsValidator,
240
+ InferHandlerReturn<TReturnsValidator, TReturn>
241
+ > &
242
+ CallableBuilder<
243
+ TCurrentContext,
244
+ TArgsValidator,
245
+ InferHandlerReturn<TReturnsValidator, TReturn>
246
+ > {
247
+ if (this.def.handler) {
248
+ throw new Error(
249
+ "Handler already defined. Only one handler can be set per function chain."
250
+ );
251
+ }
252
+
253
+ const rawHandler = async (
254
+ transformedCtx: Context,
255
+ baseArgs: InferredArgs<TArgsValidator>
256
+ ) => {
257
+ return handlerFn({
258
+ context: transformedCtx as TCurrentContext,
259
+ input: baseArgs,
260
+ });
261
+ };
262
+
263
+ type InferredReturn = InferHandlerReturn<TReturnsValidator, TReturn>;
264
+
265
+ return new ConvexBuilderWithHandler<
266
+ TDataModel,
267
+ TFunctionType & FunctionType,
268
+ TCurrentContext,
269
+ TArgsValidator,
270
+ TReturnsValidator,
271
+ InferredReturn
272
+ >({
273
+ ...this.def,
274
+ handler: rawHandler as any,
275
+ } as any) as any;
276
+ }
277
+ }
@@ -0,0 +1,185 @@
1
+ import {
2
+ type GenericDataModel,
3
+ type RegisteredQuery,
4
+ type RegisteredMutation,
5
+ type RegisteredAction,
6
+ queryGeneric,
7
+ internalQueryGeneric,
8
+ mutationGeneric,
9
+ internalMutationGeneric,
10
+ actionGeneric,
11
+ internalActionGeneric,
12
+ } from "convex/server";
13
+ import { applyMiddlewares } from "./builder";
14
+ import { InferredArgs } from "./types";
15
+ import { ConvexBuilderDef } from "./types";
16
+ import { CallableBuilder } from "./types";
17
+ import type { ConvexMiddleware, AnyConvexMiddleware } from "./middleware";
18
+ import type {
19
+ FunctionType,
20
+ Context,
21
+ EmptyObject,
22
+ ConvexArgsValidator,
23
+ ConvexReturnsValidator,
24
+ QueryCtx,
25
+ MutationCtx,
26
+ ActionCtx,
27
+ } from "./types";
28
+
29
+ export class ConvexBuilderWithHandler<
30
+ TDataModel extends GenericDataModel = GenericDataModel,
31
+ TFunctionType extends FunctionType = FunctionType,
32
+ TCurrentContext extends Context = EmptyObject,
33
+ TArgsValidator extends ConvexArgsValidator | undefined = undefined,
34
+ TReturnsValidator extends ConvexReturnsValidator | undefined = undefined,
35
+ THandlerReturn = any,
36
+ > {
37
+ private def: ConvexBuilderDef<
38
+ TFunctionType,
39
+ TArgsValidator,
40
+ TReturnsValidator
41
+ >;
42
+
43
+ constructor(
44
+ def: ConvexBuilderDef<TFunctionType, TArgsValidator, TReturnsValidator>
45
+ ) {
46
+ this.def = def;
47
+
48
+ // Make the instance callable by returning a Proxy
49
+ return new Proxy(this, {
50
+ apply: (_target, _thisArg, args: [TCurrentContext]) => {
51
+ return this._call(args[0]);
52
+ },
53
+ }) as any;
54
+ }
55
+
56
+ // Internal method to handle the call
57
+ private _call(
58
+ context: TCurrentContext
59
+ ): (args: InferredArgs<TArgsValidator>) => Promise<THandlerReturn> {
60
+ const { handler, middlewares } = this.def;
61
+
62
+ if (!handler) {
63
+ throw new Error("Handler not set.");
64
+ }
65
+
66
+ return async (args: InferredArgs<TArgsValidator>) => {
67
+ const transformedContext = await applyMiddlewares(context, middlewares);
68
+ return handler(transformedContext as any, args);
69
+ };
70
+ }
71
+
72
+ use<UOutContext extends Context>(
73
+ middleware: ConvexMiddleware<TCurrentContext, UOutContext>
74
+ ): ConvexBuilderWithHandler<
75
+ TDataModel,
76
+ TFunctionType,
77
+ TCurrentContext & UOutContext,
78
+ TArgsValidator,
79
+ TReturnsValidator,
80
+ THandlerReturn
81
+ > &
82
+ CallableBuilder<
83
+ TCurrentContext & UOutContext,
84
+ TArgsValidator,
85
+ THandlerReturn
86
+ > {
87
+ return new ConvexBuilderWithHandler({
88
+ ...this.def,
89
+ middlewares: [...this.def.middlewares, middleware as AnyConvexMiddleware],
90
+ }) as any;
91
+ }
92
+
93
+ public(): TFunctionType extends "query"
94
+ ? RegisteredQuery<
95
+ "public",
96
+ InferredArgs<TArgsValidator>,
97
+ Promise<THandlerReturn>
98
+ >
99
+ : TFunctionType extends "mutation"
100
+ ? RegisteredMutation<
101
+ "public",
102
+ InferredArgs<TArgsValidator>,
103
+ Promise<THandlerReturn>
104
+ >
105
+ : TFunctionType extends "action"
106
+ ? RegisteredAction<
107
+ "public",
108
+ InferredArgs<TArgsValidator>,
109
+ Promise<THandlerReturn>
110
+ >
111
+ : never {
112
+ return this._register("public") as any;
113
+ }
114
+
115
+ internal(): TFunctionType extends "query"
116
+ ? RegisteredQuery<
117
+ "internal",
118
+ InferredArgs<TArgsValidator>,
119
+ Promise<THandlerReturn>
120
+ >
121
+ : TFunctionType extends "mutation"
122
+ ? RegisteredMutation<
123
+ "internal",
124
+ InferredArgs<TArgsValidator>,
125
+ Promise<THandlerReturn>
126
+ >
127
+ : TFunctionType extends "action"
128
+ ? RegisteredAction<
129
+ "internal",
130
+ InferredArgs<TArgsValidator>,
131
+ Promise<THandlerReturn>
132
+ >
133
+ : never {
134
+ return this._register("internal") as any;
135
+ }
136
+
137
+ private _register(visibility: "public" | "internal"): any {
138
+ const {
139
+ functionType,
140
+ argsValidator,
141
+ returnsValidator,
142
+ handler,
143
+ middlewares,
144
+ } = this.def;
145
+
146
+ if (!functionType) {
147
+ throw new Error(
148
+ "Function type not set. Call .query(), .mutation(), or .action() first."
149
+ );
150
+ }
151
+
152
+ if (!handler) {
153
+ throw new Error(
154
+ "Handler not set. Call .handler() before .public() or .internal()."
155
+ );
156
+ }
157
+
158
+ // Compose the handler with all middlewares (including those added after .handler())
159
+ const composedHandler = async (
160
+ baseCtx:
161
+ | QueryCtx<TDataModel>
162
+ | MutationCtx<TDataModel>
163
+ | ActionCtx<TDataModel>,
164
+ baseArgs: any
165
+ ) => {
166
+ const transformedContext = await applyMiddlewares(baseCtx, middlewares);
167
+ return handler(transformedContext as any, baseArgs);
168
+ };
169
+
170
+ const config = {
171
+ args: argsValidator || {},
172
+ ...(returnsValidator ? { returns: returnsValidator } : {}),
173
+ handler: composedHandler,
174
+ } as any;
175
+
176
+ const isPublic = visibility === "public";
177
+ const registrationFn = {
178
+ query: isPublic ? queryGeneric : internalQueryGeneric,
179
+ mutation: isPublic ? mutationGeneric : internalMutationGeneric,
180
+ action: isPublic ? actionGeneric : internalActionGeneric,
181
+ }[functionType];
182
+
183
+ return registrationFn(config);
184
+ }
185
+ }