diff --git a/web/docs/project/env-vars.md b/web/docs/project/env-vars.md index a0ac725f74..661e21fc7b 100644 --- a/web/docs/project/env-vars.md +++ b/web/docs/project/env-vars.md @@ -218,13 +218,158 @@ We talk about how to define env vars for each deployment option in the [deployme ## Custom Env Var Validations -TODO: when the Zod validation PRs are merged, describe how users can define their own validations. +If your code requires some environment variables, you usually want to ensure that they are correctly defined. In Wasp, you can define your environment variables validation by defining a [Zod object schema](https://zod.dev/?id=basic-usage) and telling Wasp to use it. + +:::info What is Zod? + +[Zod](https://zod.dev/) is a library that lets you define what you expect from your data. For example, you can use Zod to define that: + +- A value should be a string that's a valid email address. +- A value should be a number between 0 and 100. +- ... and much more. + +::: + +Take a look at an example of defining env vars validation: + + + + +```js title="src/env.js" +import * as z from 'zod' + +import { defineEnvValidationSchema } from 'wasp/env' + +export const serverEnvValidationSchema = defineEnvValidationSchema( + z.object({ + STRIPE_API_KEY: z.string({ + required_error: 'STRIPE_API_KEY is required.', + }), + }) +) + +export const clientEnvValidationSchema = defineEnvValidationSchema( + z.object({ + REACT_APP_NAME: z.string().default('TODO App'), + }) +) +``` + + + + +```ts title="src/env.ts" +import * as z from 'zod' + +import { defineEnvValidationSchema } from 'wasp/env' + +export const serverEnvValidationSchema = defineEnvValidationSchema( + z.object({ + STRIPE_API_KEY: z.string({ + required_error: 'STRIPE_API_KEY is required.', + }), + }) +) + +export const clientEnvValidationSchema = defineEnvValidationSchema( + z.object({ + REACT_APP_NAME: z.string().default('TODO App'), + }) +) +``` + +The `defineEnvValidationSchema` function ensures your Zod schema is type-checked. + + + + +```wasp title="main.wasp" +app myApp { + ... + client: { + envValidationSchema: import { clientEnvValidationSchema } from "@src/env", + }, + server: { + envValidationSchema: import { serverEnvValidationSchema } from "@src/env", + }, +} +``` + +You defined schemas for both the client and the server env vars and told Wasp to use them. Wasp merges your env validation schemas with the built-in env vars validation schemas when it validates the `process.env` object on the server and the `import.meta.env` object on the client. + +This means you can use the `env` object to access **your env vars** like this: + +```ts title="src/stripe.ts" +import { env } from 'wasp/server' + +const stripeApiKey = env.STRIPE_API_KEY +``` + +Read more about the env object in the [API Reference](#api-reference). ## API Reference +There are **Wasp-defined** and **user-defined** env vars. Wasp already comes with built-in validation for Wasp-defined env vars. For your env vars, you can define your own validation. + ### Client Env Vars -Access client env vars in your client code using the `env` object like this: +#### User-defined env vars validation + +You can define your client env vars validation like this: + + + + +```js title="src/env.js" +import * as z from 'zod' + +import { defineEnvValidationSchema } from 'wasp/env' + +export const envValidationSchema = defineEnvValidationSchema( + z.object({ + REACT_APP_ANALYTICS_ID: z.string({ + required_error: 'REACT_APP_ANALYTICS_ID is required.', + }), + }) +) +``` + + + + +```ts title="src/env.ts" +import * as z from 'zod' + +import { defineEnvValidationSchema } from 'wasp/env' + +export const envValidationSchema = defineEnvValidationSchema( + z.object({ + REACT_APP_ANALYTICS_ID: z.string({ + required_error: 'REACT_APP_ANALYTICS_ID is required.', + }), + }) +) +``` + +The `defineEnvValidationSchema` function ensures your Zod schema is type-checked. + + + + +```wasp title="main.wasp" +app myApp { + ... + client: { + envValidationSchema: import { envValidationSchema } from "@src/env", + }, +} +``` + +Wasp merges your env validation schemas with the built-in env vars validation schemas when it validates the `import.meta.env` object. + +#### Accessing env vars in client code + +You can access both **Wasp-defined** and **user-defined** client env vars in your client code using the `env` object: @@ -232,7 +377,11 @@ Access client env vars in your client code using the `env` object like this: ```js title="src/App.js" import { env } from 'wasp/client' -console.log(env.REACT_APP_SOME_VAR_NAME) +// Wasp-defined +const apiUrl = env.REACT_APP_API_URL + +// User-defined +const analyticsId = env.REACT_APP_ANALYTICS_ID ``` @@ -241,45 +390,105 @@ console.log(env.REACT_APP_SOME_VAR_NAME) ```ts title="src/App.ts" import { env } from 'wasp/client' -console.log(env.REACT_APP_SOME_VAR_NAME) +// Wasp-defined +const apiUrl = env.REACT_APP_API_URL + +// User-defined +const analyticsId = env.REACT_APP_ANALYTICS_ID ``` -The `env` object is a validated object that Wasp provides to access client env vars. +You can use `import.meta.env.REACT_APP_SOME_VAR_NAME` directly in your code. We don't recommend this since `import.meta.env` isn't validated and missing env vars can cause runtime errors. -You can use `import.meta.env.REACT_APP_SOME_VAR_NAME` directly in your code, but it's not recommended because it's not validated and can lead to runtime errors if the env var is not defined. +### Server Env Vars - +#### User-defined env vars validation -### Server Env Vars +You can define your env vars validation like this: + + + + +```js title="src/env.js" +import * as z from 'zod' + +import { defineEnvValidationSchema } from 'wasp/env' -Access server env vars in your server code using the `env` object like this: +export const envValidationSchema = defineEnvValidationSchema( + z.object({ + STRIPE_API_KEY: z.string({ + required_error: 'STRIPE_API_KEY is required.', + }), + }) +) +``` + + + + +```ts title="src/env.ts" +import * as z from 'zod' + +import { defineEnvValidationSchema } from 'wasp/env' + +export const envValidationSchema = defineEnvValidationSchema( + z.object({ + STRIPE_API_KEY: z.string({ + required_error: 'STRIPE_API_KEY is required.', + }), + }) +) +``` + +The `defineEnvValidationSchema` function ensures your Zod schema is type-checked. + + + + +```wasp title="main.wasp" +app myApp { + ... + server: { + envValidationSchema: import { envValidationSchema } from "@src/env", + }, +} +``` + +Wasp merges your env validation schemas with the built-in env vars validation schemas when it validates the `process.env` object. + +#### Accessing env vars in server code + +You can access both **Wasp-defined** and **user-defined** client env vars in your client code using the `env` object: -```js title="src/App.js" +```js title="src/stripe.js" import { env } from 'wasp/server' -console.log(env.SOME_SECRET) +// Wasp-defined +const serverUrl = env.WASP_SERVER_URL + +// User-defined +const stripeApiKey = env.STRIPE_API_KEY ``` -```ts title="src/App.ts" +```ts title="src/stripe.ts" import { env } from 'wasp/server' -console.log(env.SOME_SECRET) +// Wasp-defined +const serverUrl = env.WASP_SERVER_URL + +// User-defined +const stripeApiKey = env.STRIPE_API_KEY ``` -The `env` object is a validated object that Wasp provides to access server env vars. - -You can use `process.env.SOME_SECRET` directly in your code, but it's not recommended because it's not validated and can lead to runtime errors if the env var is not defined. - - +You can use `process.env.SOME_SECRET` directly in your code. We don't recommend this since `process.env` isn't validated and missing env vars can cause runtime errors.