wasp
wasp copied to clipboard
Implement good support for environment variables
Right now there are some env vars that server requires: PORT, DATABASE_URL, and sometimes JWT_SECRET. We should implement it so in the generated JS code that it fails early if they are missing -> that should probably be done in server/config.js
Also, it would be cool if Wasp understood which ENV vars are required and it would be on the lookout for them in some way -> for example, it would list them in the generated README.
Finally, we should figure out a way for the users to provide their own env vars, and also our env vars, in a nice way -> via .env files. I am not yet sure what is the best way to go about this, but we should probably allow them to define files like .env and .env.development and similar next to the .wasp files, and they would be picked up and appropriately used / placed in the generated code. We would also certainly need to separate them in regard to client vs server code (since client ones are ok being public and server ones are usually private), and also should be careful which ones are ok being committed into git and which ones are not. Create React App has system of env files well defined, so we could look into how they do it. Some npm packagea we will probably want to use are dotenv, maybe cmdenv.
We added .env which contains env vars that are passed to the server. It is not version controled.
Related to #1067
An example way of validating env vars:
import * as z from "zod";
const envSchema = z.object({
NODE_ENV: z.enum(["development", "production"]).default("development"),
PORT: z.coerce.number().default(3000),
GITHUB_CLIENT_ID: z.string({
required_error: "GITHUB_CLIENT_ID is required",
}),
GITHUB_CLIENT_SECRET: z.string({
required_error: "GITHUB_CLIENT_SECRET is required",
}),
GOOGLE_CLIENT_ID: z.string({
required_error: "GOOGLE_CLIENT_ID is required",
}),
GOOGLE_CLIENT_SECRET: z.string({
required_error: "GOOGLE_CLIENT_SECRET is required",
}),
DISCORD_CLIENT_ID: z.string({
required_error: "DISCORD_CLIENT_ID is required",
}),
DISCORD_CLIENT_SECRET: z.string({
required_error: "DISCORD_CLIENT_SECRET is required",
}),
SERVER_URL: z.string({
required_error: "SERVER_URL is required",
}),
CLIENT_URL: z.string({
required_error: "CLIENT_URL is required",
}),
JWT_SECRET: z.string({
required_error: "JWT_SECRET is required",
}),
});
function tryToParseEnv() {
try {
return envSchema.parse(process.env);
} catch (e) {
if (e instanceof z.ZodError) {
e.errors.forEach((error) => {
console.error(error.message);
});
} else {
console.error(e);
}
process.exit(1);
}
}
export const env = tryToParseEnv();
Wasp should also be checking for required env vars when deployed to production. It happens sometimes to Wasp users that they forget about an env var once they deploy a Wasp app, and then those errors manifest in weird ways, and they have hard time debugging them. If Wasp server (or client), when deployed, detected that these vars are missing, logged about it and if needed even crashed, it would be very clear that there is an issue and what it is.
Related #1894
Btw .env.client could be versioned in git if I am correct, it is all public stuff anyway, so we could also version in git something like .env.client.production and have it be picked up by wasp deploy
and/or wasp build
.
Only .env.server (and .env.server.*) need to be gitignored, and those could be managed via a third party service, something like vault.dotenv.org, or HashiCorp's Vault.
We had a user implementing their own script for loading env vars from .env.server.prod
, pretty cool! https://discord.com/channels/686873244791210014/1250104524014616626/1250176625140830328 .