Confect: Branded types don't work
cc @RJ
I am using effect's branded types for certain ids like this
But these get converted back into a regular string in the type definitions when returned from a query or mutation.
I want to reuse the type definitions I get out of the schemas, but the type definitions have branded types, and the confect functions don't
30 Replies
Hey @devagr—this is probably a current limitation (or what I would consider a limitation) of Confect that you're encountering, in that the values returned from invoking Convex functions built with Confect are the
Encoded
type of the returns
validator schemas. If you want to convert them to the Type
type, you need to manually Schema.decode
. The way I recommend doing this right now is creating a separate file containing the args
and returns
schemas for your functions, and importing that both in your frontend and your backend, where you define your functions. You can see an example of how you might do this in the example/
directory on GitHub (example/convex/functions.schemas.ts
) and (example/convex/functions.ts
). There are actually some very simple React helpers in the library for helping with this as well: example/src/App.tsx
.i can't use the react helpers because i'm using tanstack query
I consider this the main limitation of Confect at the moment, and it's something I'm working to change in v1.0. It's actually a fair amount of work to set this up to work seamlessly, because I have to integrate with how Convex does its type generation/mapping of function paths with the file-system etc.
I haven't looked into Tanstack Query yet because I'm waiting for Tanstack Start to become stable, but I do plan on supporting Confect for this framework as well. I'm happy to take a quick look and see if I can come up with a recommendation for how to do this using Tanstack Query, but basically you just need to
Schema.encode
/Schema.decode
using your args
/returns
validators where you provide/receive values to/from your Convex functions.okay so all i need is to import the same schemas on the client side and decode the result coming out of convex
Yes, exactly! And if you want to provide arguments to a Confect function (and you want to define those args in terms of their schema's
Type
), you need to encode those before passing them in.
I was just looking at Tanstack Query a bit, it should be pretty easy to write a similar kind of helper as are already defined for React. I can look into adding it sometime soon; or if you come up with a solution and want to share it here or contribute it directly, let me know!
Also: It's probably worth noting that some folks prefer to not use Effect types on the frontend (I am not one of those people), so for some the existing behavior is preferred.yeah here's convex's helpers for tanstack query https://github.com/get-convex/convex-react-query/blob/main/src/index.ts
GitHub
convex-react-query/src/index.ts at main · get-convex/convex-react-...
Contribute to get-convex/convex-react-query development by creating an account on GitHub.
yeah i suspected
another issue
I have a schema of a record type like this
and i get this error when trying to deploy this
it doesnt seem to like the record
You're right! The addition of
v.record()
(the Convex validator for TS records) is fairly recent, and I don't support it yet. It should be pretty easy to so I can add that to the docket, but if you don't want to wait I'd recommend just using
or
instead.ah thats nice
i changed it to arrays and it works for now
ideally this shouldn't even be an array, it should be a table in the database
Agreed, but I get the convenience
thanks a lot for your help and for building confect
No problem, thanks for your feedback!
okay one more issue i ran into a while ago that i am not happy with the workaround for
i have certain functions that want to access the database, but if i only access confectquerycontext, it won't work in mutations, and if i access confectmutationcontext it wont work in queries
so right now i have to manually pass in the db, auth, and storage objects into these functions
instead of those being inferred from context
I get this 100%, it kind of sucks right now. v1 will break the contexts down further, such that this isn't an issue. I've actually been working on this recently, and it's just about done (but I don't think it will be released until the v1 release). I think passing the requisite pieces individually is the best workaround in the meantime.
good to know thanks
i was wondering if i can use effect's layers to layer in a generic service, and the layer itself would depend on the mutation and query contexts, but i don't have enough experience with effect's DI system to pull this off
Hm
Yeah you could probably do that actually
i'd also need to wrap your
query
and mutation
functions to provide this layerI'm not a top expert on services/layers myself, but I'm imagining a
ConfectDatabaseReader
service that you create, for which you can construct layers from either a DatabaseReader
or a DatabaseWriter
.
Or actually from a ConfectMutationCtx
or ConfectQueryCtx
If you used those you I don't think you'd need to wrap anything, but you would need to construct the layer and provide it to your helper Effects every time you need to use itthe layer itself would need to somehow depend on
ConfectMutationCtx | ConfectQueryCtx
instead of both or just one
yeah but i have a lot of them and i'd rather just provide the service at the query
and mutation
layer rather than providing the service to every function individuallyI was imagining that you have two different methods of constructing the layer, one which takes
ConfectMutationCtx
and one which takes ConfectQueryCtx
hmm that could work yeah
two services that provide the same generic context but depend on different ones themselves
Yeah, but don't "depend" on in the sense of being a part of the service dependency graph
"depend" on in the sense that you can construct the layer for it using regular functions which accept one or the other
At least that's what I had in mind
(and maybe that was already clear)
Anyways I'm not exactly sure but if you play around with it and find a good workaround for now I'd love to see it
And happy to share feedback/thoughts if I can be helpful
i'll let you know how it goes when i get around to it, right now it works by passing in those dependencies directly
Sounds good!
i've also noticed that since i added confect, it takes much longer to build and deploy the functions, making it slower to iterate
have you noticed this or am i doing something wrong
Using Confect will definitely add overhead, but I haven't tested rigorously how much. I would guess that the type-checking is more heavyweight than the runtime building process—you could try running
convex dev
without type-checking and see if that helps things.
I'm definitely interested in hearing about your experience with Confect's performance impact, as I'd like to minimize it as much as possible.
You could also try Convex's static code generation feature: https://docs.convex.dev/production/project-configuration#using-static-code-generation-betai think ultimately ts-go should solve a lot of that
I'm hoping so too!
you could try running convex dev without type-checkinghow?
convex dev --typecheck=disable
I believe