jedahu
jedahu4mo ago

register query function dynamically

Is there a way to register query functions programmatically? E.g. register("some/identity:name", query({...}))
25 Replies
ballingt
ballingt4mo ago
There is not, these need to be ESM exports and therefore are statically analyzable. This does exist for HTTP routing though. What kind of thing are you hoping to do?
jedahu
jedahuOP4mo ago
Looking to define something like Endpoint("id", argSchema, returnSchema) in shared code
ballingt
ballingt4mo ago
You can re-export functions defined elsewhere, but not an arbitrary number of them; you need to write the line
export const { myQuery1, myQuery2, myQuery3, myQuery4 } = buildQueryFunctions(args);
export const { myQuery1, myQuery2, myQuery3, myQuery4 } = buildQueryFunctions(args);
jedahu
jedahuOP4mo ago
Currently I can define an endpoint in terms of arg and return schemas but then have to manually pair each definition with convex function ids.
ballingt
ballingt4mo ago
Could you say more? I don't get it yet "define an endpoint in terms of arg and return schemas" sounds like the normal syntax
jedahu
jedahuOP4mo ago
I'm using an external schema library.
ballingt
ballingt4mo ago
you'd like to write these once and then define many queries with that schema? ah so you've got wrappers that add these schema, and you'd like to stamp out many queries with the same args and returns validators? or just one?
jedahu
jedahuOP4mo ago
I'd like to wrap useQuery to take an endpoint definition, and wrap query on the server to take one. I can do this, just with an extra step of manually naming the function on the client.
ballingt
ballingt4mo ago
The thing I describe above sounds doable,
export const myQuery = wrapperThatAddsArgsAndReturns(() => { return thisIsTheImpl() })
export const myQuery = wrapperThatAddsArgsAndReturns(() => { return thisIsTheImpl() })
I don't quite get it yet, coudl you share psuedocode?
jedahu
jedahuOP4mo ago
Yeah, give me a minute...
ballingt
ballingt4mo ago
- wrap useQuery to take an endpoint So you dont' want to use api.foo.bar to carry the type information, you want to use your own schema system for this? - wrap query on the server to take one That should just work
jedahu
jedahuOP4mo ago
// Shared

export const GetUser = Endpoint("getUser", UserIdSchema, UserSchema)

// Server

registerQuery(GetUser, { handler: ({userId}) => {... return user } })
// registerQuery handles encoding and decoding using the GetUser schemas, and exposes the convex query at "getUser"


// Client

mylib.useQuery(GetUser, {userId})
// also handles encoding and decoding
// Shared

export const GetUser = Endpoint("getUser", UserIdSchema, UserSchema)

// Server

registerQuery(GetUser, { handler: ({userId}) => {... return user } })
// registerQuery handles encoding and decoding using the GetUser schemas, and exposes the convex query at "getUser"


// Client

mylib.useQuery(GetUser, {userId})
// also handles encoding and decoding
Currently I have something akin to:
// Shared

export const GetUser = Endpoint(UserIdSchema, UserSchema)

// Server

export const getUserId = registerQuery(GetUser, { handler: ({userId}) => {... return user } })
// registerQuery handles encoding and decoding using the GetUser schemas


// Client

import { api } from "../convex/_generated/api"

mylib.useQuery(api.getUserId, GetUser, {userId})
// also handles encoding and decoding
// Shared

export const GetUser = Endpoint(UserIdSchema, UserSchema)

// Server

export const getUserId = registerQuery(GetUser, { handler: ({userId}) => {... return user } })
// registerQuery handles encoding and decoding using the GetUser schemas


// Client

import { api } from "../convex/_generated/api"

mylib.useQuery(api.getUserId, GetUser, {userId})
// also handles encoding and decoding
ballingt
ballingt4mo ago
Gotcha
jedahu
jedahuOP4mo ago
It's not a big deal. Just good to know if it's possible or not before spending more time on the idea.
ballingt
ballingt4mo ago
You could get closer with
export * from "./asdf.js";
export * from "./asdf.js";
which will export every (still have to be statically defined) export from asdf in this file but you dont get to transform them in that case
jedahu
jedahuOP4mo ago
Already doing that! Thanks for your time.
ballingt
ballingt4mo ago
Sorry about that, we definitely are interesting in what you're doing here Convex is fundamentally an API for defining functions regardless of our TypeScript library — but in terms of anything stable, you currently have to put it in terms of our current TS API out of curiousity is your schema Effect or zod or something else?
jedahu
jedahuOP4mo ago
Effect Trying to achieve something similar to Effect Rpc but with Convex
ballingt
ballingt4mo ago
We want good Effect bindings, if that's what it takes we may be able to add APIs — but not for a little while There's an upcoming project called "components" that we want to get out first, then take stock and see what's missing to allow stuff like this pluggable codegen is one possibel approach
jedahu
jedahuOP4mo ago
Sounds encouraging!
ballingt
ballingt4mo ago
but yeah another is just to let you do this, say export const myFunctions = buildABunchOfFunctions() Would love to see what you come up with, keep in touch re what would be helpful even if it's not something we can add for a while I love @effect/schema, would love to have a version where you define your schema.ts in Effect ( @RJ has played with this) and then you get something similar on the client
jedahu
jedahuOP4mo ago
If/when I publish something I will!
RJ
RJ4mo ago
Hey @jedahu, check out https://rj-dellecese.gitbook.io/confect. I'm actively working on the documentation and the library, but if you're adventurous, you can try it now I am interested in what you're trying to do also—I've thought about it before and talked about it with Tom in the past I have plans to do something kinda more lame in Confect until better options are available But I'm definitely interested in what you find out if you do any more experimenting!
jedahu
jedahuOP4mo ago
Hi RJ. I use your schema conversion code at build time to generate my convex schema.ts file.
RJ
RJ4mo ago
That's awesome to hear @jedahu. I'm curious to know—are you also using other aspects of Confect, or did you just copy out the Schema to Validator compiler? If you're not using Confect, are you also performing Schema validations on data before you read or write data? If so, how?

Did you find this page helpful?