Environment variables in Convex functions

how do I use environment variables in convex functions? I tried something along these lines, but it gave me an error: Error: [CONVEX M(user:createUser)] Uncaught ReferenceError: process is not defined
export const createUser = mutation(
async ({ db }, adminSecret: string, data: SimpleDocument<"user">) => {
if (adminSecret !== process.env.ADMIN_SECRET) {
throw new Error("Invalid admin secret")
}
// other stuff
},
)
export const createUser = mutation(
async ({ db }, adminSecret: string, data: SimpleDocument<"user">) => {
if (adminSecret !== process.env.ADMIN_SECRET) {
throw new Error("Invalid admin secret")
}
// other stuff
},
)
14 Replies
ballingt
ballingt3y ago
Hmmm the way we have esbuild (which we use to bundle your functions before we send them to the server) configured we don't compile these in, so you can't really.
MapleLeaf 🍁
MapleLeaf 🍁OP3y ago
mm, well, any way to configure it without actually checking it into source would be fine
ballingt
ballingt3y ago
That's a pretty reasonable thing to want, you'd also need to set them in CI etc. if you deploy your functions from there but that seems fine
jamwt
jamwt3y ago
@MapleLeaf 🍁 we have a roadmap item to have secrets support, but that's a ways off. reasonable question about support for env variables.
ballingt
ballingt3y ago
@MapleLeaf 🍁 without committing to anything, this is the interface you'd want for these, right? Every environment variable accessed in a Convex function is replaced with its value, but only in your code — not environment variables referenced in dependencies you're pulling in?
MapleLeaf 🍁
MapleLeaf 🍁OP3y ago
honestly yeah, values replaced at compile time would work here provided the build is done in CI where the secrets are set followup: I came up with a workaround of adding a secrets.json file, importing that from the functions, then adding it to .gitignore
ballingt
ballingt3y ago
nice I could imagine something like import { MY_SECRET_ENVVAR } from 'env'; but would want to make it very clear this was a build-time thing, maybe import { MY_SECRET_ENVVAR } from 'build-time-env' @MapleLeaf 🍁 talking to @alexcole at lunch today, he suggested writing a mutation temporarily to add a row to a new secrets table and sticking the secret in, or manually editing in the real value in the dashboard editor
MapleLeaf 🍁
MapleLeaf 🍁OP3y ago
that would also work :meowthumbsup:
RJ
RJ3y ago
I wonder if another option might be to bake such secrets/env vars into the signatures of the generated query and mutation functions from _generated/server? This way there would perhaps be less ambiguity that it happens at build time (because those functions are built at build time). Something like this:
export const createUser = mutation(
async ({ db, env }, adminSecret: string, data: SimpleDocument<"user">) => {
if (adminSecret !== env.ADMIN_SECRET) {
throw new Error("Invalid admin secret")
}
// other stuff
},
)
export const createUser = mutation(
async ({ db, env }, adminSecret: string, data: SimpleDocument<"user">) => {
if (adminSecret !== env.ADMIN_SECRET) {
throw new Error("Invalid admin secret")
}
// other stuff
},
)
MapleLeaf 🍁
MapleLeaf 🍁OP3y ago
i like that!
ballingt
ballingt3y ago
We've been talking about this interface! It feels right to me for runtime secrets, but possibly confusing for build-time ones? ie makes sense for secrets you enter in a Convex secrets list in the dashboard
MapleLeaf 🍁
MapleLeaf 🍁OP3y ago
if there's only runtime secrets I think that's also fine
RJ
RJ3y ago
Yeah, only runtime secrets seems fine too, maybe even better? Why would you need both? (I can't think of a reason)
alexcole
alexcole3y ago
Yeah I'm excited about only runtime secrets too! And we designed our QueryCtx and MutationCtx to be extendable with new services like this 🙂

Did you find this page helpful?