fluent-convex 0.10.0 → 0.12.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/README.md +420 -0
- package/dist/ConvexBuilderWithFunctionKind.d.ts +9 -3
- package/dist/ConvexBuilderWithFunctionKind.d.ts.map +1 -1
- package/dist/ConvexBuilderWithFunctionKind.js +13 -12
- package/dist/ConvexBuilderWithFunctionKind.js.map +1 -1
- package/dist/ConvexBuilderWithHandler.d.ts +4 -0
- package/dist/ConvexBuilderWithHandler.d.ts.map +1 -1
- package/dist/ConvexBuilderWithHandler.js +17 -6
- package/dist/ConvexBuilderWithHandler.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/zod/index.d.ts +3 -0
- package/dist/zod/index.d.ts.map +1 -0
- package/dist/zod/index.js +2 -0
- package/dist/zod/index.js.map +1 -0
- package/dist/zod/withZod.d.ts +55 -0
- package/dist/zod/withZod.d.ts.map +1 -0
- package/dist/zod/withZod.js +87 -0
- package/dist/zod/withZod.js.map +1 -0
- package/package.json +13 -7
- package/src/ConvexBuilderWithFunctionKind.ts +19 -43
- package/src/ConvexBuilderWithHandler.ts +32 -14
- package/src/builder-core.test-d.ts +25 -38
- package/src/context-helper.test.ts +1 -1
- package/src/error-paths.test.ts +7 -7
- package/src/extensibility.test.ts +70 -24
- package/src/index.ts +0 -7
- package/src/input-validation.test-d.ts +0 -55
- package/src/middleware-onion.test.ts +4 -4
- package/src/middleware.test-d.ts +0 -1
- package/src/returns-validation.test-d.ts +0 -71
- package/src/types.ts +7 -2
- package/src/zod/index.ts +7 -0
- package/src/zod/withZod.test-d.ts +209 -0
- package/src/zod/withZod.test.ts +180 -0
- package/src/zod/withZod.ts +196 -0
- package/dist/zod_support.d.ts +0 -22
- package/dist/zod_support.d.ts.map +0 -1
- package/dist/zod_support.js +0 -18
- package/dist/zod_support.js.map +0 -1
- package/src/zod_support.ts +0 -61
package/README.md
ADDED
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
# Fluent Convex
|
|
4
|
+
|
|
5
|
+
A fluent API builder for Convex functions with middleware support, inspired by [oRPC](https://orpc.unnoq.com/).
|
|
6
|
+
|
|
7
|
+
**[Live Docs & Interactive Showcase](https://friendly-zebra-716.convex.site)** -- see every feature in action with live demos and real source code.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Middleware support** - Compose reusable middleware for authentication, logging, and more ([docs](https://friendly-zebra-716.convex.site/middleware))
|
|
12
|
+
- **Callable builders** - Define logic once, call it directly from other handlers, and register it multiple ways ([docs](https://friendly-zebra-716.convex.site/reusable-chains))
|
|
13
|
+
- **Type-safe** - Full TypeScript support with type inference
|
|
14
|
+
- **Fluent API** - Chain methods for a clean, readable syntax ([docs](https://friendly-zebra-716.convex.site/basics))
|
|
15
|
+
- **Plugin system** - Extend with plugins like `fluent-convex/zod` for Zod schema support ([docs](https://friendly-zebra-716.convex.site/zod-plugin))
|
|
16
|
+
- **Extensible** - Build your own plugins with the `_clone()` factory pattern ([docs](https://friendly-zebra-716.convex.site/custom-plugins))
|
|
17
|
+
- **Works with Convex** - Built on top of Convex's function system
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install fluent-convex
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
> For a complete walkthrough with live demos, see the **[Getting Started guide](https://friendly-zebra-716.convex.site/)**.
|
|
28
|
+
|
|
29
|
+
**Important:** All functions must end with `.public()` or `.internal()` to be registered with Convex.
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { createBuilder } from "fluent-convex";
|
|
33
|
+
import { v } from "convex/values";
|
|
34
|
+
import type { DataModel } from "./_generated/dataModel";
|
|
35
|
+
|
|
36
|
+
const convex = createBuilder<DataModel>();
|
|
37
|
+
|
|
38
|
+
// Simple query
|
|
39
|
+
export const listNumbers = convex
|
|
40
|
+
.query()
|
|
41
|
+
.input({ count: v.number() })
|
|
42
|
+
.handler(async (context, input) => {
|
|
43
|
+
const numbers = await context.db
|
|
44
|
+
.query("numbers")
|
|
45
|
+
.order("desc")
|
|
46
|
+
.take(input.count);
|
|
47
|
+
|
|
48
|
+
return { numbers: numbers.map((n) => n.value) };
|
|
49
|
+
})
|
|
50
|
+
.public(); // Must end with .public() or .internal()
|
|
51
|
+
|
|
52
|
+
// With middleware
|
|
53
|
+
const authMiddleware = convex.query().createMiddleware(async (context, next) => {
|
|
54
|
+
const identity = await context.auth.getUserIdentity();
|
|
55
|
+
if (!identity) {
|
|
56
|
+
throw new Error("Unauthorized");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return next({
|
|
60
|
+
...context,
|
|
61
|
+
user: {
|
|
62
|
+
id: identity.subject,
|
|
63
|
+
name: identity.name ?? "Unknown",
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export const listNumbersAuth = convex
|
|
69
|
+
.query()
|
|
70
|
+
.use(authMiddleware)
|
|
71
|
+
.input({ count: v.number() })
|
|
72
|
+
.handler(async (context, input) => {
|
|
73
|
+
const numbers = await context.db
|
|
74
|
+
.query("numbers")
|
|
75
|
+
.order("desc")
|
|
76
|
+
.take(input.count);
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
viewer: context.user.name, // user is available from middleware!
|
|
80
|
+
numbers: numbers.map((n) => n.value),
|
|
81
|
+
};
|
|
82
|
+
})
|
|
83
|
+
.public();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Validation
|
|
87
|
+
|
|
88
|
+
> See the **[Validation docs](https://friendly-zebra-716.convex.site/validation)** for a side-by-side comparison of all three approaches with live demos.
|
|
89
|
+
|
|
90
|
+
fluent-convex supports three flavors of input validation through the same `.input()` API:
|
|
91
|
+
|
|
92
|
+
1. **Property validators** -- `{ count: v.number() }` (simplest)
|
|
93
|
+
2. **Object validators** -- `v.object({ count: v.number() })` (with `.returns()` support)
|
|
94
|
+
3. **Zod schemas** -- `z.object({ count: z.number().min(1) })` (via the Zod plugin)
|
|
95
|
+
|
|
96
|
+
## Middleware
|
|
97
|
+
|
|
98
|
+
> See the **[Middleware docs](https://friendly-zebra-716.convex.site/middleware)** for detailed examples of both patterns.
|
|
99
|
+
|
|
100
|
+
There are two main middleware patterns:
|
|
101
|
+
|
|
102
|
+
- **Context-enrichment** -- adds new properties to the context (e.g. `ctx.user`)
|
|
103
|
+
- **Onion (wrap)** -- runs code before *and* after the handler (e.g. timing, error handling)
|
|
104
|
+
|
|
105
|
+
## Reusable Chains & Callables
|
|
106
|
+
|
|
107
|
+
> See the **[Reusable Chains docs](https://friendly-zebra-716.convex.site/reusable-chains)** for full examples with live demos.
|
|
108
|
+
|
|
109
|
+
Because the builder is immutable, you can stop the chain at any point and reuse that partial builder later. A builder with a `.handler()` but no `.public()` / `.internal()` is called a **callable** -- a fully-typed function you can:
|
|
110
|
+
|
|
111
|
+
1. **Call directly** from inside other handlers (no additional Convex function invocation)
|
|
112
|
+
2. **Register** as a standalone Convex endpoint
|
|
113
|
+
3. **Extend** with more middleware and register multiple ways
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
// 1. Define a callable - NOT yet registered with Convex
|
|
117
|
+
const getNumbers = convex
|
|
118
|
+
.query()
|
|
119
|
+
.input({ count: v.number() })
|
|
120
|
+
.handler(async (ctx, args) => {
|
|
121
|
+
const rows = await ctx.db.query("numbers").order("desc").take(args.count);
|
|
122
|
+
return rows.map((r) => r.value);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// 2. Register it as a public query
|
|
126
|
+
export const listNumbers = getNumbers.public();
|
|
127
|
+
|
|
128
|
+
// 3. Call it directly from inside another handler - no additional function invocation!
|
|
129
|
+
export const getNumbersWithTimestamp = convex
|
|
130
|
+
.query()
|
|
131
|
+
.input({ count: v.number() })
|
|
132
|
+
.handler(async (ctx, args) => {
|
|
133
|
+
const numbers = await getNumbers(ctx, args); // <-- direct call
|
|
134
|
+
return { numbers, fetchedAt: Date.now() };
|
|
135
|
+
})
|
|
136
|
+
.public();
|
|
137
|
+
|
|
138
|
+
// 4. Register the same callable with different middleware
|
|
139
|
+
export const listNumbersProtected = getNumbers.use(authMiddleware).public();
|
|
140
|
+
export const listNumbersLogged = getNumbers.use(withLogging("logged")).public();
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The callable syntax is `callable(ctx, args)` -- the first argument passes the context (so the middleware chain runs with the right ctx), the second passes the validated arguments.
|
|
144
|
+
|
|
145
|
+
## Plugins
|
|
146
|
+
|
|
147
|
+
### Zod Plugin (`fluent-convex/zod`)
|
|
148
|
+
|
|
149
|
+
> See the **[Zod Plugin docs](https://friendly-zebra-716.convex.site/zod-plugin)** for live demos including refinement validation.
|
|
150
|
+
|
|
151
|
+
The Zod plugin adds Zod schema support for `.input()` and `.returns()`, with **full runtime validation** including refinements (`.min()`, `.max()`, `.email()`, etc.).
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
npm install zod convex-helpers
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
> **Note:** `zod` and `convex-helpers` are optional peer dependencies of `fluent-convex`. They're only needed if you use the Zod plugin.
|
|
158
|
+
|
|
159
|
+
Usage:
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
import { createBuilder } from "fluent-convex";
|
|
163
|
+
import { WithZod } from "fluent-convex/zod";
|
|
164
|
+
import { z } from "zod";
|
|
165
|
+
import type { DataModel } from "./_generated/dataModel";
|
|
166
|
+
|
|
167
|
+
const convex = createBuilder<DataModel>();
|
|
168
|
+
|
|
169
|
+
export const listNumbers = convex
|
|
170
|
+
.query()
|
|
171
|
+
.extend(WithZod) // Enable Zod support
|
|
172
|
+
.input(
|
|
173
|
+
z.object({
|
|
174
|
+
count: z.number().int().min(1).max(100), // Refinements enforced at runtime!
|
|
175
|
+
})
|
|
176
|
+
)
|
|
177
|
+
.returns(z.object({ numbers: z.array(z.number()) }))
|
|
178
|
+
.handler(async (context, input) => {
|
|
179
|
+
const numbers = await context.db.query("numbers").take(input.count);
|
|
180
|
+
return { numbers: numbers.map((n) => n.value) };
|
|
181
|
+
})
|
|
182
|
+
.public();
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Key features:
|
|
186
|
+
- **Full runtime validation** - Zod refinements (`.min()`, `.max()`, `.email()`, `.regex()`, etc.) are enforced server-side. Args are validated before the handler runs; return values after.
|
|
187
|
+
- **Structural conversion** - Zod schemas are automatically converted to Convex validators for Convex's built-in validation.
|
|
188
|
+
- **Composable** - `.extend(WithZod)` preserves the `WithZod` type through `.use()`, `.input()`, and `.returns()` chains.
|
|
189
|
+
- **Plain validators still work** - You can mix Zod and Convex validators in the same builder chain.
|
|
190
|
+
|
|
191
|
+
## Extensibility
|
|
192
|
+
|
|
193
|
+
> See the **[Custom Plugins docs](https://friendly-zebra-716.convex.site/custom-plugins)** for a complete worked example with live demo.
|
|
194
|
+
|
|
195
|
+
You can extend the builder with your own plugins by subclassing `ConvexBuilderWithFunctionKind` and overriding the `_clone()` factory method.
|
|
196
|
+
|
|
197
|
+
### Writing a Plugin
|
|
198
|
+
|
|
199
|
+
The `_clone()` method is called internally by `.use()`, `.input()`, and `.returns()` to create new builder instances. By overriding it, your plugin's type is preserved through the entire builder chain.
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
import {
|
|
203
|
+
ConvexBuilderWithFunctionKind,
|
|
204
|
+
type GenericDataModel,
|
|
205
|
+
type FunctionType,
|
|
206
|
+
type Context,
|
|
207
|
+
type EmptyObject,
|
|
208
|
+
type ConvexArgsValidator,
|
|
209
|
+
type ConvexReturnsValidator,
|
|
210
|
+
type ConvexBuilderDef,
|
|
211
|
+
} from "fluent-convex";
|
|
212
|
+
|
|
213
|
+
class MyPlugin<
|
|
214
|
+
TDataModel extends GenericDataModel = GenericDataModel,
|
|
215
|
+
TFunctionType extends FunctionType = FunctionType,
|
|
216
|
+
TCurrentContext extends Context = EmptyObject,
|
|
217
|
+
TArgsValidator extends ConvexArgsValidator | undefined = undefined,
|
|
218
|
+
TReturnsValidator extends ConvexReturnsValidator | undefined = undefined,
|
|
219
|
+
> extends ConvexBuilderWithFunctionKind<
|
|
220
|
+
TDataModel,
|
|
221
|
+
TFunctionType,
|
|
222
|
+
TCurrentContext,
|
|
223
|
+
TArgsValidator,
|
|
224
|
+
TReturnsValidator
|
|
225
|
+
> {
|
|
226
|
+
// Accept both builder instances (from .extend()) and raw defs (from _clone())
|
|
227
|
+
constructor(builderOrDef: any) {
|
|
228
|
+
const def =
|
|
229
|
+
builderOrDef instanceof ConvexBuilderWithFunctionKind
|
|
230
|
+
? (builderOrDef as any).def
|
|
231
|
+
: builderOrDef;
|
|
232
|
+
super(def);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Override _clone() to preserve MyPlugin through the chain
|
|
236
|
+
protected _clone(def: ConvexBuilderDef<any, any, any>): any {
|
|
237
|
+
return new MyPlugin(def);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Add custom methods
|
|
241
|
+
myCustomMethod(param: string) {
|
|
242
|
+
console.log("Custom method called with:", param);
|
|
243
|
+
return this;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Usage:
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
export const myQuery = convex
|
|
252
|
+
.query()
|
|
253
|
+
.extend(MyPlugin)
|
|
254
|
+
.myCustomMethod("hello") // Custom method from plugin
|
|
255
|
+
.use(authMiddleware) // .use() preserves MyPlugin type
|
|
256
|
+
.input({ count: v.number() })
|
|
257
|
+
.handler(async (ctx, input) => { ... })
|
|
258
|
+
.public();
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Composing Multiple Plugins
|
|
262
|
+
|
|
263
|
+
Plugins can be composed with `.extend()`:
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
export const myQuery = convex
|
|
267
|
+
.query()
|
|
268
|
+
.extend(MyPlugin)
|
|
269
|
+
.extend(WithZod) // WithZod overrides .input()/.returns() from MyPlugin
|
|
270
|
+
.myCustomMethod("hello")
|
|
271
|
+
.input(z.object({ count: z.number() }))
|
|
272
|
+
.handler(async (ctx, input) => { ... })
|
|
273
|
+
.public();
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Flexible Method Ordering
|
|
277
|
+
|
|
278
|
+
The builder API is flexible about method ordering, allowing you to structure your code in the way that makes the most sense for your use case.
|
|
279
|
+
|
|
280
|
+
### Middleware After Handler
|
|
281
|
+
|
|
282
|
+
You can add middleware **after** defining the handler, which is useful when you want to wrap existing handlers with additional functionality:
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
export const getNumbers = convex
|
|
286
|
+
.query()
|
|
287
|
+
.input({ count: v.number() })
|
|
288
|
+
.handler(async (context, input) => {
|
|
289
|
+
return await context.db.query("numbers").take(input.count);
|
|
290
|
+
})
|
|
291
|
+
.use(authMiddleware) // Middleware added after handler
|
|
292
|
+
.public();
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Callable Builders
|
|
296
|
+
|
|
297
|
+
Before registering a function with `.public()` or `.internal()`, the builder is **callable** -- you can invoke it directly from other handlers (see [Reusable Chains](#reusable-chains--callables) above) or use it in tests:
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
// A callable (not yet registered)
|
|
301
|
+
const getDouble = convex
|
|
302
|
+
.query()
|
|
303
|
+
.input({ count: v.number() })
|
|
304
|
+
.handler(async (context, input) => {
|
|
305
|
+
return { doubled: input.count * 2 };
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// Call it from another handler
|
|
309
|
+
export const tripled = convex
|
|
310
|
+
.query()
|
|
311
|
+
.input({ count: v.number() })
|
|
312
|
+
.handler(async (ctx, input) => {
|
|
313
|
+
const { doubled } = await getDouble(ctx, input);
|
|
314
|
+
return { tripled: doubled + input.count };
|
|
315
|
+
})
|
|
316
|
+
.public();
|
|
317
|
+
|
|
318
|
+
// Or call it directly in tests
|
|
319
|
+
const mockContext = {} as any;
|
|
320
|
+
const result = await getDouble(mockContext, { count: 5 });
|
|
321
|
+
console.log(result); // { doubled: 10 }
|
|
322
|
+
|
|
323
|
+
// Register it when you also need it as a standalone endpoint
|
|
324
|
+
export const doubleNumber = getDouble.public();
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Method Ordering Rules
|
|
328
|
+
|
|
329
|
+
- **`.returns()`** must be called **before** `.handler()`
|
|
330
|
+
- **`.use()`** can be called **before or after** `.handler()`
|
|
331
|
+
- **`.public()`** or **`.internal()`** must be called **after** `.handler()` and is **required** to register the function
|
|
332
|
+
- Functions are **callable** before registration, **non-callable** after registration
|
|
333
|
+
- **All exported functions must end with `.public()` or `.internal()`** - functions without registration will not be available in your Convex API
|
|
334
|
+
|
|
335
|
+
## API
|
|
336
|
+
|
|
337
|
+
### Methods
|
|
338
|
+
|
|
339
|
+
- `.query()` - Define a Convex query
|
|
340
|
+
- `.mutation()` - Define a Convex mutation
|
|
341
|
+
- `.action()` - Define a Convex action
|
|
342
|
+
- `.public()` - Register the function as public (required to register)
|
|
343
|
+
- `.internal()` - Register the function as internal/private (required to register)
|
|
344
|
+
- `.input(validator)` - Set input validation (Convex validators)
|
|
345
|
+
- `.returns(validator)` - Set return validation (Convex validators)
|
|
346
|
+
- `.use(middleware)` - Apply middleware
|
|
347
|
+
- `.createMiddleware(fn)` - Create a middleware function
|
|
348
|
+
- `.handler(fn)` - Define the function handler
|
|
349
|
+
- `.extend(plugin)` - Extend the builder with a plugin class
|
|
350
|
+
|
|
351
|
+
## Caveats
|
|
352
|
+
|
|
353
|
+
### Circular types when calling `api.*` in the same file
|
|
354
|
+
|
|
355
|
+
When a function calls other functions via `api.*` in the same file, and those functions don't have explicit `.returns()` validators, TypeScript may report circular initializer errors (TS7022). This is a standard Convex/TypeScript limitation, not specific to fluent-convex. Workarounds:
|
|
356
|
+
1. Add `.returns()` to the **called** functions -- this gives them explicit return types, breaking the cycle
|
|
357
|
+
2. Move the calling function to a separate file
|
|
358
|
+
3. Use `internal.*` from a different module
|
|
359
|
+
|
|
360
|
+
## Documentation
|
|
361
|
+
|
|
362
|
+
The **[live docs site](https://friendly-zebra-716.convex.site)** is an interactive showcase that demonstrates every feature with working live demos. The code snippets shown on the docs site are the actual source code powering the app -- imported via Vite `?raw` imports, so what you see is what runs.
|
|
363
|
+
|
|
364
|
+
Sections:
|
|
365
|
+
- [Getting Started](https://friendly-zebra-716.convex.site/) -- builder setup and overview
|
|
366
|
+
- [Basics](https://friendly-zebra-716.convex.site/basics) -- queries, mutations, and the fluent chain
|
|
367
|
+
- [Validation](https://friendly-zebra-716.convex.site/validation) -- property validators, object validators, and Zod schemas
|
|
368
|
+
- [Middleware](https://friendly-zebra-716.convex.site/middleware) -- context-enrichment and onion middleware
|
|
369
|
+
- [Reusable Chains](https://friendly-zebra-716.convex.site/reusable-chains) -- callable syntax and composability
|
|
370
|
+
- [Zod Plugin](https://friendly-zebra-716.convex.site/zod-plugin) -- runtime refinement validation
|
|
371
|
+
- [Custom Plugins](https://friendly-zebra-716.convex.site/custom-plugins) -- building your own plugins with `.extend()`
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
The docs source lives in [`/apps/docs`](./apps/docs) and is auto-deployed on every push to `main`.
|
|
376
|
+
|
|
377
|
+
## Development
|
|
378
|
+
|
|
379
|
+
This is a monorepo using npm workspaces:
|
|
380
|
+
|
|
381
|
+
- `/packages/fluent-convex` - The core library (includes the Zod plugin at `fluent-convex/zod`)
|
|
382
|
+
- `/apps/example` - Example Convex app
|
|
383
|
+
- `/apps/docs` - Interactive docs & showcase site ([live](https://friendly-zebra-716.convex.site))
|
|
384
|
+
|
|
385
|
+
### Setup
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
npm install
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
This will install dependencies for all workspaces.
|
|
392
|
+
|
|
393
|
+
### Building
|
|
394
|
+
|
|
395
|
+
```bash
|
|
396
|
+
npm run build
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### Running tests
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
npm test
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Running the example
|
|
406
|
+
|
|
407
|
+
```bash
|
|
408
|
+
cd apps/example
|
|
409
|
+
npm run dev
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Running the docs locally
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
npm run docs:dev
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
## Credits
|
|
419
|
+
|
|
420
|
+
Borrowed heavily from [oRPC](https://orpc.unnoq.com/learn-and-contribute/overview) and helped out by AI.
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
import type { GenericDataModel } from "convex/server";
|
|
2
|
+
import type { GenericValidator, PropertyValidators } from "convex/values";
|
|
2
3
|
import { ConvexBuilderWithHandler } from "./ConvexBuilderWithHandler";
|
|
3
4
|
import { InferredArgs, InferredHandlerReturn } from "./types";
|
|
4
5
|
import { ConvexBuilderDef } from "./types";
|
|
5
6
|
import { CallableBuilder } from "./types";
|
|
6
7
|
import type { ConvexMiddleware } from "./middleware";
|
|
7
8
|
import type { FunctionType, Context, EmptyObject, ConvexArgsValidator, ConvexReturnsValidator } from "./types";
|
|
8
|
-
import { type ValidatorInput, type ToConvexArgsValidator, type ReturnsValidatorInput, type ToConvexReturnsValidator } from "./zod_support";
|
|
9
9
|
export declare class ConvexBuilderWithFunctionKind<TDataModel extends GenericDataModel = GenericDataModel, TFunctionType extends FunctionType = FunctionType, TCurrentContext extends Context = EmptyObject, TArgsValidator extends ConvexArgsValidator | undefined = undefined, TReturnsValidator extends ConvexReturnsValidator | undefined = undefined> {
|
|
10
10
|
protected def: ConvexBuilderDef<TFunctionType, TArgsValidator, TReturnsValidator>;
|
|
11
11
|
constructor(def: ConvexBuilderDef<TFunctionType, TArgsValidator, TReturnsValidator>);
|
|
12
|
+
/**
|
|
13
|
+
* Factory method for creating new builder instances. Subclasses (plugins)
|
|
14
|
+
* override this to return their own type, ensuring that methods like
|
|
15
|
+
* `.use()`, `.input()`, `.returns()` preserve the plugin type through the chain.
|
|
16
|
+
*/
|
|
17
|
+
protected _clone(def: ConvexBuilderDef<any, any, any>): any;
|
|
12
18
|
extend<TResult>(fn: (builder: this) => TResult): TResult;
|
|
13
19
|
extend<TResult>(cls: new (builder: this) => TResult): TResult;
|
|
14
20
|
$context<U extends Context>(): {
|
|
@@ -21,8 +27,8 @@ export declare class ConvexBuilderWithFunctionKind<TDataModel extends GenericDat
|
|
|
21
27
|
createMiddleware<UOutContext extends Context>(middleware: ConvexMiddleware<TCurrentContext, UOutContext>): ConvexMiddleware<TCurrentContext, UOutContext>;
|
|
22
28
|
createMiddleware<UInContext extends Context, UOutContext extends Context>(middleware: ConvexMiddleware<UInContext, UOutContext>): ConvexMiddleware<UInContext, UOutContext>;
|
|
23
29
|
use<UOutContext extends Context>(middleware: ConvexMiddleware<TCurrentContext, UOutContext>): ConvexBuilderWithFunctionKind<TDataModel, TFunctionType, TCurrentContext & UOutContext, TArgsValidator, TReturnsValidator>;
|
|
24
|
-
input<UInput extends
|
|
25
|
-
returns<UReturns extends
|
|
30
|
+
input<UInput extends PropertyValidators | GenericValidator>(validator: UInput): ConvexBuilderWithFunctionKind<TDataModel, TFunctionType, TCurrentContext, UInput extends ConvexArgsValidator ? UInput : ConvexArgsValidator, TReturnsValidator>;
|
|
31
|
+
returns<UReturns extends GenericValidator>(validator: UReturns): ConvexBuilderWithFunctionKind<TDataModel, TFunctionType, TCurrentContext, TArgsValidator, UReturns extends ConvexReturnsValidator ? UReturns : ConvexReturnsValidator>;
|
|
26
32
|
handler<TReturn extends InferredHandlerReturn<TReturnsValidator, any> = InferredHandlerReturn<TReturnsValidator, any>>(handlerFn: (context: TCurrentContext, input: InferredArgs<TArgsValidator>) => Promise<TReturn>): ConvexBuilderWithHandler<TDataModel, TFunctionType, TCurrentContext, TArgsValidator, TReturnsValidator, InferredHandlerReturn<TReturnsValidator, TReturn>> & CallableBuilder<TCurrentContext, TArgsValidator, InferredHandlerReturn<TReturnsValidator, TReturn>>;
|
|
27
33
|
}
|
|
28
34
|
//# sourceMappingURL=ConvexBuilderWithFunctionKind.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConvexBuilderWithFunctionKind.d.ts","sourceRoot":"","sources":["../src/ConvexBuilderWithFunctionKind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAuB,MAAM,cAAc,CAAC;AAC1E,OAAO,KAAK,EACV,YAAY,EACZ,OAAO,EACP,WAAW,EACX,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"ConvexBuilderWithFunctionKind.d.ts","sourceRoot":"","sources":["../src/ConvexBuilderWithFunctionKind.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { ConvexBuilderWithHandler } from "./ConvexBuilderWithHandler";
|
|
2
2
|
import { extend as extendBuilder } from "./extend";
|
|
3
|
-
import { isZodSchema, toConvexValidator, } from "./zod_support";
|
|
4
3
|
export class ConvexBuilderWithFunctionKind {
|
|
5
4
|
def;
|
|
6
5
|
constructor(def) {
|
|
7
6
|
this.def = def;
|
|
8
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Factory method for creating new builder instances. Subclasses (plugins)
|
|
10
|
+
* override this to return their own type, ensuring that methods like
|
|
11
|
+
* `.use()`, `.input()`, `.returns()` preserve the plugin type through the chain.
|
|
12
|
+
*/
|
|
13
|
+
_clone(def) {
|
|
14
|
+
return new ConvexBuilderWithFunctionKind(def);
|
|
15
|
+
}
|
|
9
16
|
extend(fnOrCls) {
|
|
10
17
|
return extendBuilder(this, fnOrCls);
|
|
11
18
|
}
|
|
@@ -20,27 +27,21 @@ export class ConvexBuilderWithFunctionKind {
|
|
|
20
27
|
return middleware;
|
|
21
28
|
}
|
|
22
29
|
use(middleware) {
|
|
23
|
-
return
|
|
30
|
+
return this._clone({
|
|
24
31
|
...this.def,
|
|
25
32
|
middlewares: [...this.def.middlewares, middleware],
|
|
26
33
|
});
|
|
27
34
|
}
|
|
28
35
|
input(validator) {
|
|
29
|
-
|
|
30
|
-
? toConvexValidator(validator)
|
|
31
|
-
: validator;
|
|
32
|
-
return new ConvexBuilderWithFunctionKind({
|
|
36
|
+
return this._clone({
|
|
33
37
|
...this.def,
|
|
34
|
-
argsValidator:
|
|
38
|
+
argsValidator: validator,
|
|
35
39
|
});
|
|
36
40
|
}
|
|
37
41
|
returns(validator) {
|
|
38
|
-
|
|
39
|
-
? toConvexValidator(validator)
|
|
40
|
-
: validator;
|
|
41
|
-
return new ConvexBuilderWithFunctionKind({
|
|
42
|
+
return this._clone({
|
|
42
43
|
...this.def,
|
|
43
|
-
returnsValidator:
|
|
44
|
+
returnsValidator: validator,
|
|
44
45
|
});
|
|
45
46
|
}
|
|
46
47
|
handler(handlerFn) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConvexBuilderWithFunctionKind.js","sourceRoot":"","sources":["../src/ConvexBuilderWithFunctionKind.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ConvexBuilderWithFunctionKind.js","sourceRoot":"","sources":["../src/ConvexBuilderWithFunctionKind.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAYtE,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,UAAU,CAAC;AAEnD,MAAM,OAAO,6BAA6B;IAO9B,GAAG,CAIX;IAEF,YACE,GAAuE;QAEvE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACO,MAAM,CAAC,GAAoC;QACnD,OAAO,IAAI,6BAA6B,CAAC,GAAG,CAAC,CAAC;IAChD,CAAC;IAID,MAAM,CACJ,OAAwE;QAExE,OAAO,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,QAAQ;QAKN,OAAO;YACL,gBAAgB,CACd,UAA4C;gBAE5C,OAAO,UAAU,CAAC;YACpB,CAAC;SACF,CAAC;IACJ,CAAC;IAYD,gBAAgB,CACd,UAAqD;QAErD,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,GAAG,CACD,UAA0D;QAQ1D,OAAO,IAAI,CAAC,MAAM,CAAC;YACjB,GAAG,IAAI,CAAC,GAAG;YACX,WAAW,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,UAAiC,CAAC;SAC1E,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CACH,SAAiB;QAQjB,OAAO,IAAI,CAAC,MAAM,CAAC;YACjB,GAAG,IAAI,CAAC,GAAG;YACX,aAAa,EAAE,SAAS;SACzB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CACL,SAAmB;QAQnB,OAAO,IAAI,CAAC,MAAM,CAAC;YACjB,GAAG,IAAI,CAAC,GAAG;YACX,gBAAgB,EAAE,SAAS;SAC5B,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CAML,SAGqB;QAcrB,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CACb,0EAA0E,CAC3E,CAAC;QACJ,CAAC;QAED,4EAA4E;QAC5E,mFAAmF;QACnF,oFAAoF;QACpF,MAAM,UAAU,GAAG,KAAK,EACtB,cAAuB,EACvB,QAAsC,EACtC,EAAE;YACF,OAAO,SAAS,CAAC,cAAiC,EAAE,QAAQ,CAAC,CAAC;QAChE,CAAC,CAAC;QAIF,OAAO,IAAI,wBAAwB,CAOjC;YACA,GAAG,IAAI,CAAC,GAAG;YACX,OAAO,EAAE,UAAiB;SAC3B,CAQiE,CAAC;IACrE,CAAC;CACF"}
|
|
@@ -23,6 +23,10 @@ export declare class ConvexBuilderWithHandler<TDataModel extends GenericDataMode
|
|
|
23
23
|
* of the chain (remaining middleware + handler). This allows middleware to
|
|
24
24
|
* run code before and after downstream execution, catch errors, measure
|
|
25
25
|
* timing, etc.
|
|
26
|
+
*
|
|
27
|
+
* When transform hooks are present (set by plugins):
|
|
28
|
+
* - `argsTransform` runs before the middleware chain (validates/transforms args).
|
|
29
|
+
* - `returnsTransform` runs after the handler (validates/transforms the return value).
|
|
26
30
|
*/
|
|
27
31
|
private _executeWithMiddleware;
|
|
28
32
|
use<UOutContext extends Context>(middleware: ConvexMiddleware<TCurrentContext, UOutContext>): ConvexBuilderWithHandler<TDataModel, TFunctionType, TCurrentContext & UOutContext, TArgsValidator, TReturnsValidator, THandlerReturn> & CallableBuilder<TCurrentContext & UOutContext, TArgsValidator, THandlerReturn>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConvexBuilderWithHandler.d.ts","sourceRoot":"","sources":["../src/ConvexBuilderWithHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EAOtB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,gBAAgB,EAAuB,MAAM,cAAc,CAAC;AAE1E,OAAO,KAAK,EACV,YAAY,EACZ,OAAO,EACP,WAAW,EACX,mBAAmB,EACnB,sBAAsB,EAEtB,gBAAgB,EAChB,YAAY,EACZ,eAAe,EAIf,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;GASG;AACH,KAAK,oBAAoB,CACvB,iBAAiB,SAAS,sBAAsB,GAAG,SAAS,EAC5D,cAAc,IACZ,CAAC,iBAAiB,CAAC,SAAS,CAAC,sBAAsB,CAAC,GACpD,OAAO,CAAC,kBAAkB,CAAC,iBAAiB,CAAC,CAAC,GAC9C,OAAO,CAAC,cAAc,CAAC,CAAC;AAE5B,qBAAa,wBAAwB,CACnC,UAAU,SAAS,gBAAgB,GAAG,gBAAgB,EACtD,aAAa,SAAS,YAAY,GAAG,YAAY,EACjD,eAAe,SAAS,OAAO,GAAG,WAAW,EAC7C,cAAc,SAAS,mBAAmB,GAAG,SAAS,GAAG,SAAS,EAClE,iBAAiB,SAAS,sBAAsB,GAAG,SAAS,GAAG,SAAS,EACxE,cAAc,GAAG,GAAG;IAEpB,SAAS,CAAC,GAAG,EAAE,gBAAgB,CAC7B,aAAa,EACb,cAAc,EACd,iBAAiB,CAClB,CAAC;gBAGA,GAAG,EAAE,gBAAgB,CAAC,aAAa,EAAE,cAAc,EAAE,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"ConvexBuilderWithHandler.d.ts","sourceRoot":"","sources":["../src/ConvexBuilderWithHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,8 +5,8 @@ export class ConvexBuilderWithHandler {
|
|
|
5
5
|
constructor(def) {
|
|
6
6
|
this.def = def;
|
|
7
7
|
// Create a callable function that delegates to _call
|
|
8
|
-
const callable = ((context) => {
|
|
9
|
-
return this._call(context);
|
|
8
|
+
const callable = ((context, args) => {
|
|
9
|
+
return this._call(context, args);
|
|
10
10
|
});
|
|
11
11
|
// Copy properties from prototype to the callable function
|
|
12
12
|
// This is a bit of a hack to make the function behave like an instance of the class
|
|
@@ -28,22 +28,29 @@ export class ConvexBuilderWithHandler {
|
|
|
28
28
|
return extendBuilder(this, fnOrCls);
|
|
29
29
|
}
|
|
30
30
|
// Internal method to handle the call
|
|
31
|
-
_call(context) {
|
|
31
|
+
async _call(context, args) {
|
|
32
32
|
const { handler, middlewares } = this.def;
|
|
33
33
|
if (!handler) {
|
|
34
34
|
throw new Error("Handler not set.");
|
|
35
35
|
}
|
|
36
|
-
return
|
|
37
|
-
return this._executeWithMiddleware(middlewares, context, handler, args);
|
|
38
|
-
};
|
|
36
|
+
return this._executeWithMiddleware(middlewares, context, handler, args);
|
|
39
37
|
}
|
|
40
38
|
/**
|
|
41
39
|
* Execute middleware as an onion: each middleware's `next()` runs the rest
|
|
42
40
|
* of the chain (remaining middleware + handler). This allows middleware to
|
|
43
41
|
* run code before and after downstream execution, catch errors, measure
|
|
44
42
|
* timing, etc.
|
|
43
|
+
*
|
|
44
|
+
* When transform hooks are present (set by plugins):
|
|
45
|
+
* - `argsTransform` runs before the middleware chain (validates/transforms args).
|
|
46
|
+
* - `returnsTransform` runs after the handler (validates/transforms the return value).
|
|
45
47
|
*/
|
|
46
48
|
async _executeWithMiddleware(middlewares, initialContext, handler, args) {
|
|
49
|
+
// Run args transform hook if present (e.g. Zod validation from plugin)
|
|
50
|
+
const { argsTransform, returnsTransform } = this.def;
|
|
51
|
+
if (argsTransform) {
|
|
52
|
+
args = argsTransform(args);
|
|
53
|
+
}
|
|
47
54
|
let handlerResult;
|
|
48
55
|
// Build a recursive chain where calling `next(ctx)` runs the next
|
|
49
56
|
// middleware, and the innermost `next` runs the handler.
|
|
@@ -60,6 +67,10 @@ export class ConvexBuilderWithHandler {
|
|
|
60
67
|
};
|
|
61
68
|
};
|
|
62
69
|
await createNext(0)(initialContext);
|
|
70
|
+
// Run returns transform hook if present (e.g. Zod validation from plugin)
|
|
71
|
+
if (returnsTransform) {
|
|
72
|
+
handlerResult = returnsTransform(handlerResult);
|
|
73
|
+
}
|
|
63
74
|
return handlerResult;
|
|
64
75
|
}
|
|
65
76
|
use(middleware) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConvexBuilderWithHandler.js","sourceRoot":"","sources":["../src/ConvexBuilderWithHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,uBAAuB,EACvB,aAAa,EACb,qBAAqB,GACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,UAAU,CAAC;AAkCnD,MAAM,OAAO,wBAAwB;IAQzB,GAAG,CAIX;IAEF,YACE,GAAuE;QAEvE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QAEf,qDAAqD;QACrD,MAAM,QAAQ,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"ConvexBuilderWithHandler.js","sourceRoot":"","sources":["../src/ConvexBuilderWithHandler.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,5 +5,4 @@ export { ConvexBuilderWithHandler } from "./ConvexBuilderWithHandler";
|
|
|
5
5
|
export type { ConvexMiddleware, AnyConvexMiddleware, } from "./middleware";
|
|
6
6
|
export type { Context, ConvexArgsValidator, ConvexReturnsValidator, InferArgs, QueryCtx, MutationCtx, ActionCtx, FunctionType, Visibility, EmptyObject, ConvexBuilderDef, } from "./types";
|
|
7
7
|
export type { GenericDataModel } from "convex/server";
|
|
8
|
-
export { isZodSchema, toConvexValidator, type ValidatorInput, type ReturnsValidatorInput, } from "./zod_support";
|
|
9
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,YAAY,EACV,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,OAAO,EACP,mBAAmB,EACnB,sBAAsB,EACtB,SAAS,EACT,QAAQ,EACR,WAAW,EACX,SAAS,EACT,YAAY,EACZ,UAAU,EACV,WAAW,EACX,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,YAAY,EACV,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,OAAO,EACP,mBAAmB,EACnB,sBAAsB,EACtB,SAAS,EACT,QAAQ,EACR,WAAW,EACX,SAAS,EACT,YAAY,EACZ,UAAU,EACV,WAAW,EACX,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,5 +2,4 @@ export { createBuilder } from "./builder";
|
|
|
2
2
|
export { ConvexBuilder } from "./ConvexBuilder";
|
|
3
3
|
export { ConvexBuilderWithFunctionKind } from "./ConvexBuilderWithFunctionKind";
|
|
4
4
|
export { ConvexBuilderWithHandler } from "./ConvexBuilderWithHandler";
|
|
5
|
-
export { isZodSchema, toConvexValidator, } from "./zod_support";
|
|
6
5
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC"}
|