fluent-convex 0.4.3 → 0.5.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.
- package/dist/builder.d.ts +35 -13
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +104 -28
- package/dist/builder.js.map +1 -1
- package/dist/decorators.d.ts +40 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +148 -0
- package/dist/decorators.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/builder.test-d.ts +749 -46
- package/src/builder.ts +357 -144
- package/src/decorators.ts +218 -0
- package/src/experimental.test-d.ts +65 -0
- package/src/index.ts +9 -0
- package/src/types.ts +2 -0
package/src/builder.test-d.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { describe, it, assertType } from "vitest";
|
|
2
2
|
import { v } from "convex/values";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
defineSchema,
|
|
6
|
+
defineTable,
|
|
7
|
+
type RegisteredQuery,
|
|
8
|
+
type RegisteredMutation,
|
|
9
|
+
} from "convex/server";
|
|
5
10
|
import { createBuilder } from "./builder";
|
|
11
|
+
import { input, returns } from "./decorators";
|
|
12
|
+
import type { QueryCtx, MutationCtx } from "./types";
|
|
6
13
|
|
|
7
14
|
const schema = defineSchema({
|
|
8
15
|
numbers: defineTable({
|
|
@@ -21,7 +28,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
21
28
|
.handler(async ({ input }) => {
|
|
22
29
|
assertType<{ count: number }>(input);
|
|
23
30
|
return { success: true };
|
|
24
|
-
})
|
|
31
|
+
})
|
|
32
|
+
.public();
|
|
25
33
|
});
|
|
26
34
|
|
|
27
35
|
it("should accept Convex v.object() validators", () => {
|
|
@@ -31,7 +39,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
31
39
|
.handler(async ({ input }) => {
|
|
32
40
|
assertType<{ count: number }>(input);
|
|
33
41
|
return { success: true };
|
|
34
|
-
})
|
|
42
|
+
})
|
|
43
|
+
.public();
|
|
35
44
|
});
|
|
36
45
|
|
|
37
46
|
it("should accept Zod object schemas", () => {
|
|
@@ -41,7 +50,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
41
50
|
.handler(async ({ input }) => {
|
|
42
51
|
assertType<{ count: number }>(input);
|
|
43
52
|
return { success: true };
|
|
44
|
-
})
|
|
53
|
+
})
|
|
54
|
+
.public();
|
|
45
55
|
});
|
|
46
56
|
|
|
47
57
|
it("should reject Zod primitive schemas (not objects)", () => {
|
|
@@ -61,7 +71,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
61
71
|
.handler(async ({ input }) => {
|
|
62
72
|
assertType<{ count: number }>(input);
|
|
63
73
|
return { success: true };
|
|
64
|
-
})
|
|
74
|
+
})
|
|
75
|
+
.public();
|
|
65
76
|
});
|
|
66
77
|
});
|
|
67
78
|
|
|
@@ -73,7 +84,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
73
84
|
.returns(v.object({ numbers: v.array(v.number()) }))
|
|
74
85
|
.handler(async () => {
|
|
75
86
|
return { numbers: [1, 2, 3] };
|
|
76
|
-
})
|
|
87
|
+
})
|
|
88
|
+
.public();
|
|
77
89
|
});
|
|
78
90
|
|
|
79
91
|
it("should accept Zod return validators", () => {
|
|
@@ -83,7 +95,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
83
95
|
.returns(z.object({ numbers: z.array(z.number()) }))
|
|
84
96
|
.handler(async () => {
|
|
85
97
|
return { numbers: [1, 2, 3] };
|
|
86
|
-
})
|
|
98
|
+
})
|
|
99
|
+
.public();
|
|
87
100
|
});
|
|
88
101
|
|
|
89
102
|
it("should accept Zod primitive return types", () => {
|
|
@@ -93,7 +106,205 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
93
106
|
.returns(z.number())
|
|
94
107
|
.handler(async () => {
|
|
95
108
|
return 42;
|
|
96
|
-
})
|
|
109
|
+
})
|
|
110
|
+
.public();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should enforce return type when .returns() is specified with Convex validator", () => {
|
|
114
|
+
convex
|
|
115
|
+
.query()
|
|
116
|
+
.input({ count: v.number() })
|
|
117
|
+
.returns(v.object({ numbers: v.array(v.number()) }))
|
|
118
|
+
.handler(async () => {
|
|
119
|
+
// This should work - correct return type
|
|
120
|
+
return { numbers: [1, 2, 3] };
|
|
121
|
+
})
|
|
122
|
+
.public();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("should reject incorrect return type when .returns() is specified with Convex validator", () => {
|
|
126
|
+
convex
|
|
127
|
+
.query()
|
|
128
|
+
.input({ count: v.number() })
|
|
129
|
+
.returns(v.object({ numbers: v.array(v.number()) }))
|
|
130
|
+
// @ts-expect-error Return type mismatch: handler returns { count: number } but .returns() expects { numbers: number[] }
|
|
131
|
+
.handler(async () => {
|
|
132
|
+
return { count: 5 };
|
|
133
|
+
})
|
|
134
|
+
.public();
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("should reject return type with missing required property", () => {
|
|
138
|
+
convex
|
|
139
|
+
.query()
|
|
140
|
+
.input({ count: v.number() })
|
|
141
|
+
.returns(v.object({ numbers: v.array(v.number()), total: v.number() }))
|
|
142
|
+
// @ts-expect-error Return type mismatch: missing 'total' property
|
|
143
|
+
.handler(async () => {
|
|
144
|
+
return { numbers: [1, 2, 3] };
|
|
145
|
+
})
|
|
146
|
+
.public();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("should reject return type with wrong property type", () => {
|
|
150
|
+
convex
|
|
151
|
+
.query()
|
|
152
|
+
.input({ count: v.number() })
|
|
153
|
+
.returns(v.object({ numbers: v.array(v.number()) }))
|
|
154
|
+
// @ts-expect-error Return type mismatch: 'numbers' should be number[] but is string[]
|
|
155
|
+
.handler(async () => {
|
|
156
|
+
return { numbers: ["1", "2", "3"] };
|
|
157
|
+
})
|
|
158
|
+
.public();
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("should enforce return type with Zod validator", () => {
|
|
162
|
+
convex
|
|
163
|
+
.query()
|
|
164
|
+
.input({ count: v.number() })
|
|
165
|
+
.returns(z.object({ numbers: z.array(z.number()) }))
|
|
166
|
+
.handler(async () => {
|
|
167
|
+
// This should work - correct return type
|
|
168
|
+
return { numbers: [1, 2, 3] };
|
|
169
|
+
})
|
|
170
|
+
.public();
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("should reject incorrect return type with Zod validator", () => {
|
|
174
|
+
convex
|
|
175
|
+
.query()
|
|
176
|
+
.input({ count: v.number() })
|
|
177
|
+
.returns(z.object({ numbers: z.array(z.number()) }))
|
|
178
|
+
// @ts-expect-error Return type mismatch: handler returns { count: number } but .returns() expects { numbers: number[] }
|
|
179
|
+
.handler(async () => {
|
|
180
|
+
return { count: 5 };
|
|
181
|
+
})
|
|
182
|
+
.public();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("should enforce primitive return types", () => {
|
|
186
|
+
convex
|
|
187
|
+
.query()
|
|
188
|
+
.input({ count: v.number() })
|
|
189
|
+
.returns(z.string())
|
|
190
|
+
.handler(async () => {
|
|
191
|
+
// This should work - correct return type
|
|
192
|
+
return "hello";
|
|
193
|
+
})
|
|
194
|
+
.public();
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("should reject wrong primitive return type", () => {
|
|
198
|
+
convex
|
|
199
|
+
.query()
|
|
200
|
+
.input({ count: v.number() })
|
|
201
|
+
.returns(z.string())
|
|
202
|
+
// @ts-expect-error Return type mismatch: handler returns number but .returns() expects string
|
|
203
|
+
.handler(async () => {
|
|
204
|
+
return 42;
|
|
205
|
+
})
|
|
206
|
+
.public();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it("should enforce array return types", () => {
|
|
210
|
+
convex
|
|
211
|
+
.query()
|
|
212
|
+
.input({ count: v.number() })
|
|
213
|
+
.returns(v.array(v.number()))
|
|
214
|
+
.handler(async () => {
|
|
215
|
+
// This should work - correct return type
|
|
216
|
+
return [1, 2, 3];
|
|
217
|
+
})
|
|
218
|
+
.public();
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it("should reject wrong array return type", () => {
|
|
222
|
+
convex
|
|
223
|
+
.query()
|
|
224
|
+
.input({ count: v.number() })
|
|
225
|
+
.returns(v.array(v.number()))
|
|
226
|
+
// @ts-expect-error Return type mismatch: handler returns string[] but .returns() expects number[]
|
|
227
|
+
.handler(async () => {
|
|
228
|
+
return ["1", "2", "3"];
|
|
229
|
+
})
|
|
230
|
+
.public();
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it("should allow any return type when .returns() is not specified", () => {
|
|
234
|
+
convex
|
|
235
|
+
.query()
|
|
236
|
+
.input({ count: v.number() })
|
|
237
|
+
.handler(async () => {
|
|
238
|
+
// Should allow any return type
|
|
239
|
+
return { numbers: [1, 2, 3] };
|
|
240
|
+
})
|
|
241
|
+
.public();
|
|
242
|
+
|
|
243
|
+
convex
|
|
244
|
+
.query()
|
|
245
|
+
.input({ count: v.number() })
|
|
246
|
+
.handler(async () => {
|
|
247
|
+
// Should allow different return types
|
|
248
|
+
return { count: 5 };
|
|
249
|
+
})
|
|
250
|
+
.public();
|
|
251
|
+
|
|
252
|
+
convex
|
|
253
|
+
.query()
|
|
254
|
+
.input({ count: v.number() })
|
|
255
|
+
.handler(async () => {
|
|
256
|
+
// Should allow primitive return types
|
|
257
|
+
return 42;
|
|
258
|
+
})
|
|
259
|
+
.public();
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("should enforce return type for mutations", () => {
|
|
263
|
+
convex
|
|
264
|
+
.mutation()
|
|
265
|
+
.input({ value: v.number() })
|
|
266
|
+
.returns(v.id("numbers"))
|
|
267
|
+
.handler(async ({ context, input }) => {
|
|
268
|
+
// This should work - correct return type
|
|
269
|
+
return await context.db.insert("numbers", { value: input.value });
|
|
270
|
+
})
|
|
271
|
+
.public();
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it("should reject incorrect return type for mutations", () => {
|
|
275
|
+
convex
|
|
276
|
+
.mutation()
|
|
277
|
+
.input({ value: v.number() })
|
|
278
|
+
.returns(v.id("numbers"))
|
|
279
|
+
// @ts-expect-error Return type mismatch: handler returns string but .returns() expects Id<"numbers">
|
|
280
|
+
.handler(async () => {
|
|
281
|
+
return "wrong-type";
|
|
282
|
+
})
|
|
283
|
+
.public();
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it("should enforce return type for actions", () => {
|
|
287
|
+
convex
|
|
288
|
+
.action()
|
|
289
|
+
.input({ count: v.number() })
|
|
290
|
+
.returns(v.array(v.number()))
|
|
291
|
+
.handler(async () => {
|
|
292
|
+
// This should work - correct return type
|
|
293
|
+
return [1, 2, 3];
|
|
294
|
+
})
|
|
295
|
+
.public();
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it("should reject incorrect return type for actions", () => {
|
|
299
|
+
convex
|
|
300
|
+
.action()
|
|
301
|
+
.input({ count: v.number() })
|
|
302
|
+
.returns(v.array(v.number()))
|
|
303
|
+
// @ts-expect-error Return type mismatch: handler returns string but .returns() expects number[]
|
|
304
|
+
.handler(async () => {
|
|
305
|
+
return "wrong";
|
|
306
|
+
})
|
|
307
|
+
.public();
|
|
97
308
|
});
|
|
98
309
|
});
|
|
99
310
|
|
|
@@ -123,7 +334,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
123
334
|
assertType(context.auth);
|
|
124
335
|
|
|
125
336
|
return { userId: context.user.id };
|
|
126
|
-
})
|
|
337
|
+
})
|
|
338
|
+
.public();
|
|
127
339
|
});
|
|
128
340
|
|
|
129
341
|
it("should chain multiple middleware", () => {
|
|
@@ -160,7 +372,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
160
372
|
assertType<string>(context.requestId);
|
|
161
373
|
|
|
162
374
|
return { success: true };
|
|
163
|
-
})
|
|
375
|
+
})
|
|
376
|
+
.public();
|
|
164
377
|
});
|
|
165
378
|
|
|
166
379
|
it("should work with mutations", () => {
|
|
@@ -184,7 +397,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
184
397
|
assertType(context.db);
|
|
185
398
|
assertType<string>(input.name);
|
|
186
399
|
return null;
|
|
187
|
-
})
|
|
400
|
+
})
|
|
401
|
+
.public();
|
|
188
402
|
});
|
|
189
403
|
|
|
190
404
|
it("should work with actions", () => {
|
|
@@ -207,7 +421,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
207
421
|
assertType<string>(context.token);
|
|
208
422
|
assertType<string>(input.url);
|
|
209
423
|
return { success: true };
|
|
210
|
-
})
|
|
424
|
+
})
|
|
425
|
+
.public();
|
|
211
426
|
});
|
|
212
427
|
|
|
213
428
|
it("should respect middleware application order", () => {
|
|
@@ -239,7 +454,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
239
454
|
assertType<string>(context.first);
|
|
240
455
|
assertType<string>(context.second);
|
|
241
456
|
return { success: true };
|
|
242
|
-
})
|
|
457
|
+
})
|
|
458
|
+
.public();
|
|
243
459
|
});
|
|
244
460
|
});
|
|
245
461
|
|
|
@@ -251,7 +467,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
251
467
|
.handler(async ({ input }) => {
|
|
252
468
|
assertType<string>(input.id);
|
|
253
469
|
return { id: input.id };
|
|
254
|
-
})
|
|
470
|
+
})
|
|
471
|
+
.public();
|
|
255
472
|
});
|
|
256
473
|
|
|
257
474
|
it("should create mutations", () => {
|
|
@@ -261,7 +478,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
261
478
|
.handler(async ({ input }) => {
|
|
262
479
|
assertType<string>(input.name);
|
|
263
480
|
return { name: input.name };
|
|
264
|
-
})
|
|
481
|
+
})
|
|
482
|
+
.public();
|
|
265
483
|
});
|
|
266
484
|
|
|
267
485
|
it("should create actions", () => {
|
|
@@ -271,50 +489,54 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
271
489
|
.handler(async ({ input }) => {
|
|
272
490
|
assertType<string>(input.url);
|
|
273
491
|
return { url: input.url };
|
|
274
|
-
})
|
|
492
|
+
})
|
|
493
|
+
.public();
|
|
275
494
|
});
|
|
276
495
|
|
|
277
496
|
it("should create internal queries", () => {
|
|
278
497
|
convex
|
|
279
498
|
.query()
|
|
280
|
-
.internal()
|
|
281
499
|
.input({ id: v.string() })
|
|
282
500
|
.handler(async ({ input }) => {
|
|
283
501
|
assertType<string>(input.id);
|
|
284
502
|
return { id: input.id };
|
|
285
|
-
})
|
|
503
|
+
})
|
|
504
|
+
.internal();
|
|
286
505
|
});
|
|
287
506
|
|
|
288
507
|
it("should create internal mutations", () => {
|
|
289
508
|
convex
|
|
290
509
|
.mutation()
|
|
291
|
-
.internal()
|
|
292
510
|
.input({ value: v.number() })
|
|
293
511
|
.handler(async ({ context, input }) => {
|
|
294
512
|
assertType(context.db);
|
|
295
513
|
assertType<number>(input.value);
|
|
296
514
|
return { value: input.value };
|
|
297
|
-
})
|
|
515
|
+
})
|
|
516
|
+
.internal();
|
|
298
517
|
});
|
|
299
518
|
|
|
300
519
|
it("should create internal actions", () => {
|
|
301
520
|
convex
|
|
302
521
|
.action()
|
|
303
|
-
.internal()
|
|
304
522
|
.input({ url: v.string() })
|
|
305
523
|
.handler(async ({ input }) => {
|
|
306
524
|
assertType<string>(input.url);
|
|
307
525
|
return { url: input.url };
|
|
308
|
-
})
|
|
526
|
+
})
|
|
527
|
+
.internal();
|
|
309
528
|
});
|
|
310
529
|
});
|
|
311
530
|
|
|
312
531
|
describe("optional input", () => {
|
|
313
532
|
it("should work without input validation", () => {
|
|
314
|
-
convex
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
533
|
+
convex
|
|
534
|
+
.query()
|
|
535
|
+
.handler(async ({ input }) => {
|
|
536
|
+
assertType<Record<never, never>>(input);
|
|
537
|
+
return { success: true };
|
|
538
|
+
})
|
|
539
|
+
.public();
|
|
318
540
|
});
|
|
319
541
|
|
|
320
542
|
it("should infer optional fields as T | undefined", () => {
|
|
@@ -330,7 +552,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
330
552
|
assertType<string | undefined>(input.name);
|
|
331
553
|
assertType<number | undefined>(input.value);
|
|
332
554
|
return null;
|
|
333
|
-
})
|
|
555
|
+
})
|
|
556
|
+
.public();
|
|
334
557
|
});
|
|
335
558
|
|
|
336
559
|
it("should handle many optional fields with complex types", () => {
|
|
@@ -357,7 +580,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
357
580
|
assertType<string | null | undefined>(input.status);
|
|
358
581
|
assertType<Array<{ x: number; y: number }> | undefined>(input.items);
|
|
359
582
|
return null;
|
|
360
|
-
})
|
|
583
|
+
})
|
|
584
|
+
.public();
|
|
361
585
|
});
|
|
362
586
|
|
|
363
587
|
it("should allow all fields to be optional", () => {
|
|
@@ -373,7 +597,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
373
597
|
assertType<number | undefined>(input.minValue);
|
|
374
598
|
assertType<number | undefined>(input.maxValue);
|
|
375
599
|
return [];
|
|
376
|
-
})
|
|
600
|
+
})
|
|
601
|
+
.public();
|
|
377
602
|
});
|
|
378
603
|
|
|
379
604
|
it("should make all properties required but allow undefined for optional fields", () => {
|
|
@@ -413,7 +638,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
413
638
|
};
|
|
414
639
|
|
|
415
640
|
return { id: input.id };
|
|
416
|
-
})
|
|
641
|
+
})
|
|
642
|
+
.public();
|
|
417
643
|
});
|
|
418
644
|
|
|
419
645
|
it("should work with Partial for truly optional calling patterns", () => {
|
|
@@ -448,7 +674,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
448
674
|
};
|
|
449
675
|
|
|
450
676
|
return null;
|
|
451
|
-
})
|
|
677
|
+
})
|
|
678
|
+
.public();
|
|
452
679
|
});
|
|
453
680
|
|
|
454
681
|
it("should allow empty object when all fields are optional", () => {
|
|
@@ -476,7 +703,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
476
703
|
};
|
|
477
704
|
|
|
478
705
|
return [];
|
|
479
|
-
})
|
|
706
|
+
})
|
|
707
|
+
.public();
|
|
480
708
|
});
|
|
481
709
|
});
|
|
482
710
|
|
|
@@ -499,7 +727,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
499
727
|
assertType<string[]>(input.tags);
|
|
500
728
|
|
|
501
729
|
return { success: true };
|
|
502
|
-
})
|
|
730
|
+
})
|
|
731
|
+
.public();
|
|
503
732
|
});
|
|
504
733
|
|
|
505
734
|
it("should handle optional fields", () => {
|
|
@@ -511,7 +740,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
511
740
|
assertType<number | undefined>(input.age);
|
|
512
741
|
|
|
513
742
|
return { success: true };
|
|
514
|
-
})
|
|
743
|
+
})
|
|
744
|
+
.public();
|
|
515
745
|
});
|
|
516
746
|
|
|
517
747
|
it("should handle v.union()", () => {
|
|
@@ -523,7 +753,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
523
753
|
.handler(async ({ input }) => {
|
|
524
754
|
assertType<string | number>(input.value);
|
|
525
755
|
return { success: true };
|
|
526
|
-
})
|
|
756
|
+
})
|
|
757
|
+
.public();
|
|
527
758
|
});
|
|
528
759
|
|
|
529
760
|
it("should handle v.array()", () => {
|
|
@@ -535,7 +766,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
535
766
|
.handler(async ({ input }) => {
|
|
536
767
|
assertType<string[]>(input.tags);
|
|
537
768
|
return { success: true };
|
|
538
|
-
})
|
|
769
|
+
})
|
|
770
|
+
.public();
|
|
539
771
|
});
|
|
540
772
|
|
|
541
773
|
it("should handle nested v.object()", () => {
|
|
@@ -550,7 +782,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
550
782
|
.handler(async ({ input }) => {
|
|
551
783
|
assertType<{ name: string; age: number }>(input.user);
|
|
552
784
|
return { success: true };
|
|
553
|
-
})
|
|
785
|
+
})
|
|
786
|
+
.public();
|
|
554
787
|
});
|
|
555
788
|
|
|
556
789
|
it("should handle v.literal()", () => {
|
|
@@ -562,7 +795,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
562
795
|
.handler(async ({ input }) => {
|
|
563
796
|
assertType<"user">(input.kind);
|
|
564
797
|
return { success: true };
|
|
565
|
-
})
|
|
798
|
+
})
|
|
799
|
+
.public();
|
|
566
800
|
});
|
|
567
801
|
|
|
568
802
|
it("should handle mix of optional and required fields", () => {
|
|
@@ -578,7 +812,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
578
812
|
assertType<string | undefined>(input.optional);
|
|
579
813
|
assertType<number | undefined>(input.defaulted);
|
|
580
814
|
return { success: true };
|
|
581
|
-
})
|
|
815
|
+
})
|
|
816
|
+
.public();
|
|
582
817
|
});
|
|
583
818
|
});
|
|
584
819
|
|
|
@@ -591,7 +826,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
591
826
|
assertType(context.db);
|
|
592
827
|
assertType(context.auth);
|
|
593
828
|
return { success: true };
|
|
594
|
-
})
|
|
829
|
+
})
|
|
830
|
+
.public();
|
|
595
831
|
});
|
|
596
832
|
|
|
597
833
|
it("mutations should have db and auth", () => {
|
|
@@ -602,7 +838,8 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
602
838
|
assertType(context.db);
|
|
603
839
|
assertType(context.auth);
|
|
604
840
|
return { success: true };
|
|
605
|
-
})
|
|
841
|
+
})
|
|
842
|
+
.public();
|
|
606
843
|
});
|
|
607
844
|
|
|
608
845
|
it("actions should have auth and scheduler", () => {
|
|
@@ -613,31 +850,497 @@ describe("ConvexBuilder Type Tests", () => {
|
|
|
613
850
|
assertType(context.auth);
|
|
614
851
|
assertType(context.scheduler);
|
|
615
852
|
return { success: true };
|
|
853
|
+
})
|
|
854
|
+
.public();
|
|
855
|
+
});
|
|
856
|
+
});
|
|
857
|
+
|
|
858
|
+
describe("function kind selection", () => {
|
|
859
|
+
it("should prevent calling .input() before selecting function kind", () => {
|
|
860
|
+
const builder = convex;
|
|
861
|
+
|
|
862
|
+
// @ts-expect-error - ConvexBuilder does not have an input method. Call .query(), .mutation(), or .action() first.
|
|
863
|
+
builder.input({ id: v.string() });
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
it("should prevent calling .handler() before selecting function kind", () => {
|
|
867
|
+
const builder = convex;
|
|
868
|
+
|
|
869
|
+
// @ts-expect-error - ConvexBuilder does not have a handler method. Call .query(), .mutation(), or .action() first.
|
|
870
|
+
builder.handler(async () => ({ success: true }));
|
|
871
|
+
});
|
|
872
|
+
|
|
873
|
+
it("should prevent calling .use() before selecting function kind", () => {
|
|
874
|
+
const builder = convex;
|
|
875
|
+
const authMiddleware = convex
|
|
876
|
+
.query()
|
|
877
|
+
.middleware(async ({ context, next }) => {
|
|
878
|
+
return next({ context });
|
|
616
879
|
});
|
|
880
|
+
|
|
881
|
+
// @ts-expect-error - ConvexBuilder does not have a use method. Call .query(), .mutation(), or .action() first.
|
|
882
|
+
builder.use(authMiddleware);
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
it("should allow .query() to be called first", () => {
|
|
886
|
+
const builder = convex.query();
|
|
887
|
+
assertType<typeof builder>(builder);
|
|
888
|
+
});
|
|
889
|
+
|
|
890
|
+
it("should allow .mutation() to be called first", () => {
|
|
891
|
+
const builder = convex.mutation();
|
|
892
|
+
assertType<typeof builder>(builder);
|
|
893
|
+
});
|
|
894
|
+
|
|
895
|
+
it("should allow .action() to be called first", () => {
|
|
896
|
+
const builder = convex.action();
|
|
897
|
+
assertType<typeof builder>(builder);
|
|
617
898
|
});
|
|
618
899
|
});
|
|
619
900
|
|
|
620
901
|
describe("order of operations", () => {
|
|
621
|
-
it("should
|
|
902
|
+
it("should prevent calling .public() before .handler()", () => {
|
|
903
|
+
const builder = convex.query().input({ id: v.string() });
|
|
904
|
+
|
|
905
|
+
// @ts-expect-error - ConvexBuilderWithFunctionKind does not have a public method. Call .handler() first.
|
|
906
|
+
builder.public();
|
|
907
|
+
});
|
|
908
|
+
|
|
909
|
+
it("should prevent calling .internal() before .handler()", () => {
|
|
910
|
+
const builder = convex.mutation().input({ name: v.string() });
|
|
911
|
+
|
|
912
|
+
// @ts-expect-error - ConvexBuilderWithFunctionKind does not have an internal method. Call .handler() first.
|
|
913
|
+
builder.internal();
|
|
914
|
+
});
|
|
915
|
+
|
|
916
|
+
it("should allow .public() after .handler()", () => {
|
|
622
917
|
convex
|
|
623
|
-
.internal()
|
|
624
918
|
.query()
|
|
625
919
|
.input({ id: v.string() })
|
|
626
920
|
.handler(async ({ input }) => {
|
|
627
921
|
assertType<string>(input.id);
|
|
628
922
|
return { id: input.id };
|
|
629
|
-
})
|
|
923
|
+
})
|
|
924
|
+
.public();
|
|
630
925
|
});
|
|
631
926
|
|
|
632
|
-
it("should allow .internal() after
|
|
927
|
+
it("should allow .internal() after .handler()", () => {
|
|
633
928
|
convex
|
|
634
929
|
.query()
|
|
635
|
-
.internal()
|
|
636
930
|
.input({ id: v.string() })
|
|
637
931
|
.handler(async ({ input }) => {
|
|
638
932
|
assertType<string>(input.id);
|
|
639
933
|
return { id: input.id };
|
|
934
|
+
})
|
|
935
|
+
.internal();
|
|
936
|
+
});
|
|
937
|
+
});
|
|
938
|
+
|
|
939
|
+
describe("handler uniqueness", () => {
|
|
940
|
+
it("should prevent calling .handler() twice on query", () => {
|
|
941
|
+
const builder = convex
|
|
942
|
+
.query()
|
|
943
|
+
.input({ id: v.string() })
|
|
944
|
+
.handler(async ({ input }) => {
|
|
945
|
+
return { id: input.id };
|
|
946
|
+
});
|
|
947
|
+
|
|
948
|
+
// @ts-expect-error - ConvexBuilderWithHandler does not have a handler method
|
|
949
|
+
builder.handler(async () => ({ error: "should not be called" }));
|
|
950
|
+
});
|
|
951
|
+
|
|
952
|
+
it("should prevent calling .handler() twice on mutation", () => {
|
|
953
|
+
const builder = convex
|
|
954
|
+
.mutation()
|
|
955
|
+
.input({ name: v.string() })
|
|
956
|
+
.handler(async ({ input }) => {
|
|
957
|
+
return { name: input.name };
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
// @ts-expect-error - ConvexBuilderWithHandler does not have a handler method
|
|
961
|
+
builder.handler(async () => ({ error: "should not be called" }));
|
|
962
|
+
});
|
|
963
|
+
|
|
964
|
+
it("should prevent calling .handler() twice on action", () => {
|
|
965
|
+
const builder = convex
|
|
966
|
+
.action()
|
|
967
|
+
.input({ url: v.string() })
|
|
968
|
+
.handler(async ({ input }) => {
|
|
969
|
+
return { url: input.url };
|
|
640
970
|
});
|
|
971
|
+
|
|
972
|
+
// @ts-expect-error - ConvexBuilderWithHandler does not have a handler method
|
|
973
|
+
builder.handler(async () => ({ error: "should not be called" }));
|
|
974
|
+
});
|
|
975
|
+
|
|
976
|
+
it("should prevent calling .handler() twice even with middleware in between", () => {
|
|
977
|
+
const authMiddleware = convex
|
|
978
|
+
.query()
|
|
979
|
+
.middleware(async ({ context, next }) => {
|
|
980
|
+
return next({ context });
|
|
981
|
+
});
|
|
982
|
+
|
|
983
|
+
const builder = convex
|
|
984
|
+
.query()
|
|
985
|
+
.input({ id: v.string() })
|
|
986
|
+
.handler(async ({ input }) => {
|
|
987
|
+
return { id: input.id };
|
|
988
|
+
})
|
|
989
|
+
.use(authMiddleware);
|
|
990
|
+
|
|
991
|
+
// @ts-expect-error - ConvexBuilderWithHandler does not have a handler method
|
|
992
|
+
builder.handler(async () => ({ error: "should not be called" }));
|
|
993
|
+
});
|
|
994
|
+
|
|
995
|
+
it("should prevent calling .handler() twice even with returns validator", () => {
|
|
996
|
+
const builder = convex
|
|
997
|
+
.query()
|
|
998
|
+
.input({ count: v.number() })
|
|
999
|
+
.returns(v.object({ numbers: v.array(v.number()) }))
|
|
1000
|
+
.handler(async () => {
|
|
1001
|
+
return { numbers: [1, 2, 3] };
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
// @ts-expect-error - ConvexBuilderWithHandler does not have a handler method
|
|
1005
|
+
builder.handler(async () => ({ numbers: [] }));
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
it("should allow chaining .use() after handler()", () => {
|
|
1009
|
+
const authMiddleware = convex
|
|
1010
|
+
.query()
|
|
1011
|
+
.middleware(async ({ context, next }) => {
|
|
1012
|
+
return next({ context });
|
|
1013
|
+
});
|
|
1014
|
+
|
|
1015
|
+
const builder = convex
|
|
1016
|
+
.query()
|
|
1017
|
+
.input({ id: v.string() })
|
|
1018
|
+
.handler(async ({ input }) => {
|
|
1019
|
+
return { id: input.id };
|
|
1020
|
+
})
|
|
1021
|
+
.use(authMiddleware);
|
|
1022
|
+
|
|
1023
|
+
// Should be able to call .public() or .internal() after .use()
|
|
1024
|
+
assertType<typeof builder>(builder);
|
|
1025
|
+
});
|
|
1026
|
+
|
|
1027
|
+
it("should prevent calling .returns() after handler()", () => {
|
|
1028
|
+
const builder = convex
|
|
1029
|
+
.query()
|
|
1030
|
+
.input({ count: v.number() })
|
|
1031
|
+
.handler(async () => {
|
|
1032
|
+
return { numbers: [1, 2, 3] };
|
|
1033
|
+
});
|
|
1034
|
+
|
|
1035
|
+
// @ts-expect-error - ConvexBuilderWithHandler does not have a returns method. Call .returns() before .handler().
|
|
1036
|
+
builder.returns(v.object({ numbers: v.array(v.number()) }));
|
|
1037
|
+
});
|
|
1038
|
+
|
|
1039
|
+
it("should allow calling .returns() before handler()", () => {
|
|
1040
|
+
const builder = convex
|
|
1041
|
+
.query()
|
|
1042
|
+
.input({ count: v.number() })
|
|
1043
|
+
.returns(v.object({ numbers: v.array(v.number()) }))
|
|
1044
|
+
.handler(async () => {
|
|
1045
|
+
return { numbers: [1, 2, 3] };
|
|
1046
|
+
});
|
|
1047
|
+
|
|
1048
|
+
// Should be able to call .public() or .internal() after .handler()
|
|
1049
|
+
assertType<typeof builder>(builder);
|
|
1050
|
+
});
|
|
1051
|
+
});
|
|
1052
|
+
|
|
1053
|
+
describe("callable builder functionality", () => {
|
|
1054
|
+
it("should make ConvexBuilderWithHandler callable", () => {
|
|
1055
|
+
const nonRegisteredQuery = convex
|
|
1056
|
+
.query()
|
|
1057
|
+
.input({ count: v.number() })
|
|
1058
|
+
.handler(async ({ context, input }) => {
|
|
1059
|
+
return `the count is ${input.count}`;
|
|
1060
|
+
});
|
|
1061
|
+
|
|
1062
|
+
// Should be callable
|
|
1063
|
+
assertType<
|
|
1064
|
+
(context: any) => (args: { count: number }) => Promise<string>
|
|
1065
|
+
>(nonRegisteredQuery);
|
|
1066
|
+
});
|
|
1067
|
+
|
|
1068
|
+
it("should make registered queries non-callable", () => {
|
|
1069
|
+
const nonRegisteredQuery = convex
|
|
1070
|
+
.query()
|
|
1071
|
+
.input({ count: v.number() })
|
|
1072
|
+
.handler(async ({ context, input }) => {
|
|
1073
|
+
return `the count is ${input.count}`;
|
|
1074
|
+
});
|
|
1075
|
+
|
|
1076
|
+
const registeredQuery = nonRegisteredQuery.public();
|
|
1077
|
+
|
|
1078
|
+
// Should NOT be callable - RegisteredQuery is not a function
|
|
1079
|
+
// @ts-expect-error - RegisteredQuery is not callable
|
|
1080
|
+
registeredQuery({} as any);
|
|
1081
|
+
});
|
|
1082
|
+
|
|
1083
|
+
it("should make registered mutations non-callable", () => {
|
|
1084
|
+
const nonRegisteredMutation = convex
|
|
1085
|
+
.mutation()
|
|
1086
|
+
.input({ value: v.number() })
|
|
1087
|
+
.handler(async ({ context, input }) => {
|
|
1088
|
+
return await context.db.insert("numbers", { value: input.value });
|
|
1089
|
+
});
|
|
1090
|
+
|
|
1091
|
+
const registeredMutation = nonRegisteredMutation.public();
|
|
1092
|
+
|
|
1093
|
+
// Should NOT be callable - RegisteredMutation is not a function
|
|
1094
|
+
// @ts-expect-error - RegisteredMutation is not callable
|
|
1095
|
+
registeredMutation({} as any);
|
|
1096
|
+
});
|
|
1097
|
+
|
|
1098
|
+
it("should make registered actions non-callable", () => {
|
|
1099
|
+
const nonRegisteredAction = convex
|
|
1100
|
+
.action()
|
|
1101
|
+
.input({ url: v.string() })
|
|
1102
|
+
.handler(async ({ input }) => {
|
|
1103
|
+
return { url: input.url };
|
|
1104
|
+
});
|
|
1105
|
+
|
|
1106
|
+
const registeredAction = nonRegisteredAction.public();
|
|
1107
|
+
|
|
1108
|
+
// Should NOT be callable - RegisteredAction is not a function
|
|
1109
|
+
// @ts-expect-error - RegisteredAction is not callable
|
|
1110
|
+
registeredAction({} as any);
|
|
1111
|
+
});
|
|
1112
|
+
|
|
1113
|
+
it("should make internal registered queries non-callable", () => {
|
|
1114
|
+
const nonRegisteredQuery = convex
|
|
1115
|
+
.query()
|
|
1116
|
+
.input({ count: v.number() })
|
|
1117
|
+
.handler(async ({ input }) => {
|
|
1118
|
+
return { count: input.count };
|
|
1119
|
+
});
|
|
1120
|
+
|
|
1121
|
+
const registeredQuery = nonRegisteredQuery.internal();
|
|
1122
|
+
|
|
1123
|
+
// Should NOT be callable - RegisteredQuery is not a function
|
|
1124
|
+
// @ts-expect-error - RegisteredQuery is not callable
|
|
1125
|
+
registeredQuery({} as any);
|
|
1126
|
+
});
|
|
1127
|
+
|
|
1128
|
+
it("should preserve callability through middleware chain", () => {
|
|
1129
|
+
const authMiddleware = convex
|
|
1130
|
+
.query()
|
|
1131
|
+
.middleware(async ({ context, next }) => {
|
|
1132
|
+
return next({
|
|
1133
|
+
context: {
|
|
1134
|
+
...context,
|
|
1135
|
+
userId: "user-123",
|
|
1136
|
+
},
|
|
1137
|
+
});
|
|
1138
|
+
});
|
|
1139
|
+
|
|
1140
|
+
const callableQuery = convex
|
|
1141
|
+
.query()
|
|
1142
|
+
.input({ count: v.number() })
|
|
1143
|
+
.use(authMiddleware)
|
|
1144
|
+
.handler(async ({ context, input }) => {
|
|
1145
|
+
assertType<string>(context.userId);
|
|
1146
|
+
return { count: input.count, userId: context.userId };
|
|
1147
|
+
});
|
|
1148
|
+
|
|
1149
|
+
// Should still be callable after middleware
|
|
1150
|
+
assertType<
|
|
1151
|
+
(
|
|
1152
|
+
context: any
|
|
1153
|
+
) => (args: {
|
|
1154
|
+
count: number;
|
|
1155
|
+
}) => Promise<{ count: number; userId: string }>
|
|
1156
|
+
>(callableQuery);
|
|
1157
|
+
});
|
|
1158
|
+
|
|
1159
|
+
it("should preserve callability after multiple middleware", () => {
|
|
1160
|
+
const authMiddleware = convex
|
|
1161
|
+
.query()
|
|
1162
|
+
.middleware(async ({ context, next }) => {
|
|
1163
|
+
return next({
|
|
1164
|
+
context: {
|
|
1165
|
+
...context,
|
|
1166
|
+
userId: "user-123",
|
|
1167
|
+
},
|
|
1168
|
+
});
|
|
1169
|
+
});
|
|
1170
|
+
|
|
1171
|
+
const loggingMiddleware = convex
|
|
1172
|
+
.query()
|
|
1173
|
+
.middleware(async ({ context, next }) => {
|
|
1174
|
+
return next({
|
|
1175
|
+
context: {
|
|
1176
|
+
...context,
|
|
1177
|
+
requestId: "req-123",
|
|
1178
|
+
},
|
|
1179
|
+
});
|
|
1180
|
+
});
|
|
1181
|
+
|
|
1182
|
+
const callableQuery = convex
|
|
1183
|
+
.query()
|
|
1184
|
+
.input({ count: v.number() })
|
|
1185
|
+
.use(authMiddleware)
|
|
1186
|
+
.use(loggingMiddleware)
|
|
1187
|
+
.handler(async ({ context, input }) => {
|
|
1188
|
+
assertType<string>(context.userId);
|
|
1189
|
+
assertType<string>(context.requestId);
|
|
1190
|
+
return { count: input.count };
|
|
1191
|
+
});
|
|
1192
|
+
|
|
1193
|
+
// Should still be callable after multiple middleware
|
|
1194
|
+
assertType<
|
|
1195
|
+
(
|
|
1196
|
+
context: any
|
|
1197
|
+
) => (args: { count: number }) => Promise<{ count: number }>
|
|
1198
|
+
>(callableQuery);
|
|
1199
|
+
});
|
|
1200
|
+
|
|
1201
|
+
it("should work with mutations", () => {
|
|
1202
|
+
const callableMutation = convex
|
|
1203
|
+
.mutation()
|
|
1204
|
+
.input({ value: v.number() })
|
|
1205
|
+
.handler(async ({ context, input }) => {
|
|
1206
|
+
return await context.db.insert("numbers", { value: input.value });
|
|
1207
|
+
});
|
|
1208
|
+
|
|
1209
|
+
// Should be callable
|
|
1210
|
+
assertType<(context: any) => (args: { value: number }) => Promise<any>>(
|
|
1211
|
+
callableMutation
|
|
1212
|
+
);
|
|
1213
|
+
});
|
|
1214
|
+
|
|
1215
|
+
it("should work with actions", () => {
|
|
1216
|
+
const callableAction = convex
|
|
1217
|
+
.action()
|
|
1218
|
+
.input({ url: v.string() })
|
|
1219
|
+
.handler(async ({ input }) => {
|
|
1220
|
+
return { url: input.url };
|
|
1221
|
+
});
|
|
1222
|
+
|
|
1223
|
+
// Should be callable
|
|
1224
|
+
assertType<
|
|
1225
|
+
(context: any) => (args: { url: string }) => Promise<{ url: string }>
|
|
1226
|
+
>(callableAction);
|
|
1227
|
+
});
|
|
1228
|
+
|
|
1229
|
+
it("should work with optional input", () => {
|
|
1230
|
+
const callableQuery = convex
|
|
1231
|
+
.query()
|
|
1232
|
+
.input({
|
|
1233
|
+
name: v.optional(v.string()),
|
|
1234
|
+
count: v.optional(v.number()),
|
|
1235
|
+
})
|
|
1236
|
+
.handler(async ({ input }) => {
|
|
1237
|
+
return {
|
|
1238
|
+
name: input.name,
|
|
1239
|
+
count: input.count,
|
|
1240
|
+
};
|
|
1241
|
+
});
|
|
1242
|
+
|
|
1243
|
+
// Should be callable
|
|
1244
|
+
assertType<
|
|
1245
|
+
(
|
|
1246
|
+
context: any
|
|
1247
|
+
) => (args: {
|
|
1248
|
+
name?: string;
|
|
1249
|
+
count?: number;
|
|
1250
|
+
}) => Promise<{ name?: string; count?: number }>
|
|
1251
|
+
>(callableQuery);
|
|
1252
|
+
});
|
|
1253
|
+
|
|
1254
|
+
it("should work with return validators", () => {
|
|
1255
|
+
const callableQuery = convex
|
|
1256
|
+
.query()
|
|
1257
|
+
.input({ count: v.number() })
|
|
1258
|
+
.returns(v.object({ numbers: v.array(v.number()) }))
|
|
1259
|
+
.handler(async ({ input }) => {
|
|
1260
|
+
return {
|
|
1261
|
+
numbers: Array(input.count)
|
|
1262
|
+
.fill(0)
|
|
1263
|
+
.map((_, i) => i),
|
|
1264
|
+
};
|
|
1265
|
+
});
|
|
1266
|
+
|
|
1267
|
+
// Should be callable
|
|
1268
|
+
assertType<
|
|
1269
|
+
(
|
|
1270
|
+
context: any
|
|
1271
|
+
) => (args: { count: number }) => Promise<{ numbers: number[] }>
|
|
1272
|
+
>(callableQuery);
|
|
1273
|
+
});
|
|
1274
|
+
|
|
1275
|
+
it("should work with Zod input validators", () => {
|
|
1276
|
+
const callableQuery = convex
|
|
1277
|
+
.query()
|
|
1278
|
+
.input(z.object({ count: z.number() }))
|
|
1279
|
+
.handler(async ({ input }) => {
|
|
1280
|
+
return { count: input.count };
|
|
1281
|
+
});
|
|
1282
|
+
|
|
1283
|
+
// Should be callable
|
|
1284
|
+
assertType<
|
|
1285
|
+
(
|
|
1286
|
+
context: any
|
|
1287
|
+
) => (args: { count: number }) => Promise<{ count: number }>
|
|
1288
|
+
>(callableQuery);
|
|
1289
|
+
});
|
|
1290
|
+
|
|
1291
|
+
it("should work with no input", () => {
|
|
1292
|
+
const callableQuery = convex.query().handler(async () => {
|
|
1293
|
+
return { success: true };
|
|
1294
|
+
});
|
|
1295
|
+
|
|
1296
|
+
// Should be callable
|
|
1297
|
+
assertType<
|
|
1298
|
+
(
|
|
1299
|
+
context: any
|
|
1300
|
+
) => (args: Record<never, never>) => Promise<{ success: boolean }>
|
|
1301
|
+
>(callableQuery);
|
|
1302
|
+
});
|
|
1303
|
+
|
|
1304
|
+
it("should lose callability after .public()", () => {
|
|
1305
|
+
const callableQuery = convex
|
|
1306
|
+
.query()
|
|
1307
|
+
.input({ count: v.number() })
|
|
1308
|
+
.handler(async ({ input }) => {
|
|
1309
|
+
return { count: input.count };
|
|
1310
|
+
});
|
|
1311
|
+
|
|
1312
|
+
// Before .public(), should be callable
|
|
1313
|
+
assertType<
|
|
1314
|
+
(
|
|
1315
|
+
context: any
|
|
1316
|
+
) => (args: { count: number }) => Promise<{ count: number }>
|
|
1317
|
+
>(callableQuery);
|
|
1318
|
+
|
|
1319
|
+
const registeredQuery = callableQuery.public();
|
|
1320
|
+
|
|
1321
|
+
// After .public(), should NOT be callable
|
|
1322
|
+
// @ts-expect-error - RegisteredQuery is not callable
|
|
1323
|
+
registeredQuery({} as any);
|
|
1324
|
+
});
|
|
1325
|
+
|
|
1326
|
+
it("should lose callability after .internal()", () => {
|
|
1327
|
+
const callableMutation = convex
|
|
1328
|
+
.mutation()
|
|
1329
|
+
.input({ value: v.number() })
|
|
1330
|
+
.handler(async ({ context, input }) => {
|
|
1331
|
+
return await context.db.insert("numbers", { value: input.value });
|
|
1332
|
+
});
|
|
1333
|
+
|
|
1334
|
+
// Before .internal(), should be callable
|
|
1335
|
+
assertType<(context: any) => (args: { value: number }) => Promise<any>>(
|
|
1336
|
+
callableMutation
|
|
1337
|
+
);
|
|
1338
|
+
|
|
1339
|
+
const registeredMutation = callableMutation.internal();
|
|
1340
|
+
|
|
1341
|
+
// After .internal(), should NOT be callable
|
|
1342
|
+
// @ts-expect-error - RegisteredMutation is not callable
|
|
1343
|
+
registeredMutation({} as any);
|
|
641
1344
|
});
|
|
642
1345
|
});
|
|
643
1346
|
});
|