Skip to content

Commit 34d6c5b

Browse files
feat: Deprecate Manual Declarations of clientEnv & serverEnv (#1071)
* Deprecate Manual Declarations of clientEnv * Deprecate Manual Declarations of serverEnv * update templates and docs with new env structure * Apply suggestions from code review Co-authored-by: Julius Marminge <[email protected]>
1 parent 0a833dd commit 34d6c5b

File tree

13 files changed

+30
-235
lines changed

13 files changed

+30
-235
lines changed

Diff for: cli/template/base/src/env/client.mjs

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
// @ts-check
2-
import { clientEnv, clientSchema } from "./schema.mjs";
2+
import { clientSchema } from "./schema.mjs";
3+
4+
/**
5+
* You can't destruct `process.env` as a regular object, so we do
6+
* a workaround. This is because Next.js evaluates this at build time,
7+
* and only used environment variables are included in the build.
8+
* @type {{ [key: string]: string | undefined; }}
9+
*/
10+
let clientEnv = {};
11+
Object.keys(clientSchema.shape).forEach(
12+
(key) => (clientEnv[key] = process.env[key]),
13+
);
314

415
const _clientEnv = clientSchema.safeParse(clientEnv);
516

Diff for: cli/template/base/src/env/schema.mjs

-19
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,6 @@ export const serverSchema = z.object({
99
NODE_ENV: z.enum(["development", "test", "production"]),
1010
});
1111

12-
/**
13-
* You can't destruct `process.env` as a regular object in the Next.js
14-
* middleware, so you have to do it manually here.
15-
* @type {{ [k in keyof z.infer<typeof serverSchema>]: z.infer<typeof serverSchema>[k] | undefined }}
16-
*/
17-
export const serverEnv = {
18-
NODE_ENV: process.env.NODE_ENV,
19-
};
20-
2112
/**
2213
* Specify your client-side environment variables schema here.
2314
* This way you can ensure the app isn't built with invalid env vars.
@@ -26,13 +17,3 @@ export const serverEnv = {
2617
export const clientSchema = z.object({
2718
// NEXT_PUBLIC_CLIENTVAR: z.string(),
2819
});
29-
30-
/**
31-
* You can't destruct `process.env` as a regular object, so you have to do
32-
* it manually here. This is because Next.js evaluates this at build time,
33-
* and only used environment variables are included in the build.
34-
* @type {{ [k in keyof z.infer<typeof clientSchema>]: z.infer<typeof clientSchema>[k] | undefined }}
35-
*/
36-
export const clientEnv = {
37-
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
38-
};

Diff for: cli/template/base/src/env/server.mjs

+12-1
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,20 @@
33
* This file is included in `/next.config.mjs` which ensures the app isn't built with invalid env vars.
44
* It has to be a `.mjs`-file to be imported there.
55
*/
6-
import { serverSchema, serverEnv } from "./schema.mjs";
6+
import { serverSchema } from "./schema.mjs";
77
import { env as clientEnv, formatErrors } from "./client.mjs";
88

9+
/**
10+
* You can't destruct `process.env` as a regular object, so we do
11+
* a workaround. This is because Next.js evaluates this at build time,
12+
* and only used environment variables are included in the build.
13+
* @type {{ [key: string]: string | undefined; }}
14+
*/
15+
let serverEnv = {};
16+
Object.keys(serverSchema.shape).forEach(
17+
(key) => (serverEnv[key] = process.env[key]),
18+
);
19+
920
const _serverEnv = serverSchema.safeParse(serverEnv);
1021

1122
if (!_serverEnv.success) {

Diff for: cli/template/extras/src/env/schema/with-auth-prisma.mjs

-24
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,6 @@ export const serverSchema = z.object({
2323
DISCORD_CLIENT_SECRET: z.string(),
2424
});
2525

26-
/**
27-
* You can't destruct `process.env` as a regular object in the Next.js
28-
* middleware, so you have to do it manually here.
29-
* @type {{ [k in keyof z.infer<typeof serverSchema>]: z.infer<typeof serverSchema>[k] | undefined }}
30-
*/
31-
export const serverEnv = {
32-
DATABASE_URL: process.env.DATABASE_URL,
33-
NODE_ENV: process.env.NODE_ENV,
34-
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
35-
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
36-
DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID,
37-
DISCORD_CLIENT_SECRET: process.env.DISCORD_CLIENT_SECRET,
38-
};
39-
4026
/**
4127
* Specify your client-side environment variables schema here.
4228
* This way you can ensure the app isn't built with invalid env vars.
@@ -45,13 +31,3 @@ export const serverEnv = {
4531
export const clientSchema = z.object({
4632
// NEXT_PUBLIC_CLIENTVAR: z.string(),
4733
});
48-
49-
/**
50-
* You can't destruct `process.env` as a regular object, so you have to do
51-
* it manually here. This is because Next.js evaluates this at build time,
52-
* and only used environment variables are included in the build.
53-
* @type {{ [k in keyof z.infer<typeof clientSchema>]: z.infer<typeof clientSchema>[k] | undefined }}
54-
*/
55-
export const clientEnv = {
56-
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
57-
};

Diff for: cli/template/extras/src/env/schema/with-auth.mjs

-23
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,6 @@ export const serverSchema = z.object({
2222
DISCORD_CLIENT_SECRET: z.string(),
2323
});
2424

25-
/**
26-
* You can't destruct `process.env` as a regular object in the Next.js
27-
* middleware, so you have to do it manually here.
28-
* @type {{ [k in keyof z.infer<typeof serverSchema>]: z.infer<typeof serverSchema>[k] | undefined }}
29-
*/
30-
export const serverEnv = {
31-
NODE_ENV: process.env.NODE_ENV,
32-
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
33-
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
34-
DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID,
35-
DISCORD_CLIENT_SECRET: process.env.DISCORD_CLIENT_SECRET,
36-
};
37-
3825
/**
3926
* Specify your client-side environment variables schema here.
4027
* This way you can ensure the app isn't built with invalid env vars.
@@ -43,13 +30,3 @@ export const serverEnv = {
4330
export const clientSchema = z.object({
4431
// NEXT_PUBLIC_CLIENTVAR: z.string(),
4532
});
46-
47-
/**
48-
* You can't destruct `process.env` as a regular object, so you have to do
49-
* it manually here. This is because Next.js evaluates this at build time,
50-
* and only used environment variables are included in the build.
51-
* @type {{ [k in keyof z.infer<typeof clientSchema>]: z.infer<typeof clientSchema>[k] | undefined }}
52-
*/
53-
export const clientEnv = {
54-
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
55-
};

Diff for: cli/template/extras/src/env/schema/with-prisma.mjs

-20
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,6 @@ export const serverSchema = z.object({
1010
NODE_ENV: z.enum(["development", "test", "production"]),
1111
});
1212

13-
/**
14-
* You can't destruct `process.env` as a regular object in the Next.js
15-
* middleware, so you have to do it manually here.
16-
* @type {{ [k in keyof z.infer<typeof serverSchema>]: z.infer<typeof serverSchema>[k] | undefined }}
17-
*/
18-
export const serverEnv = {
19-
DATABASE_URL: process.env.DATABASE_URL,
20-
NODE_ENV: process.env.NODE_ENV,
21-
};
22-
2313
/**
2414
* Specify your client-side environment variables schema here.
2515
* This way you can ensure the app isn't built with invalid env vars.
@@ -28,13 +18,3 @@ export const serverEnv = {
2818
export const clientSchema = z.object({
2919
// NEXT_PUBLIC_CLIENTVAR: z.string(),
3020
});
31-
32-
/**
33-
* You can't destruct `process.env` as a regular object, so you have to do
34-
* it manually here. This is because Next.js evaluates this at build time,
35-
* and only used environment variables are included in the build.
36-
* @type {{ [k in keyof z.infer<typeof clientSchema>]: z.infer<typeof clientSchema>[k] | undefined }}
37-
*/
38-
export const clientEnv = {
39-
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
40-
};

Diff for: www/src/pages/ar/usage/env-variables.md

+1-16
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,16 @@ dir: rtl
2222

2323
## ملف schema.mjs
2424

25-
هذا هو الملف الذي ستعمل علية. يَحتوي على مُخططين ، أحدهما environment variables من جانب الخادم والآخر من جانب العميل بالإضافة إلى Object الـ "clientEnv".
25+
هذا هو الملف الذي ستعمل علية. يَحتوي على مُخططين ، أحدهما environment variables من جانب الخادم والآخر من جانب العميل ".
2626

2727
```ts:env/schema.mjs
2828
export const serverSchema = z.object({
2929
// DATABASE_URL: z.string().url(),
3030
});
3131

32-
export const serverEnv = {
33-
// DATABASE_URL: process.env.DATABASE_URL,
34-
};
35-
3632
export const clientSchema = z.object({
3733
// NEXT_PUBLIC_WS_KEY: z.string(),
3834
});
39-
40-
export const clientEnv = {
41-
// NEXT_PUBLIC_WS_KEY: process.env.NEXT_PUBLIC_WS_KEY,
42-
};
4335
```
4436

4537
### الـ Server Schema
@@ -51,8 +43,6 @@ export const clientEnv = {
5143

5244
أنشئ الـ client-side environment variables هنا، حتى تجعلهم متاحيت للـ client أضف `NEXT_PUBLIC` قبل الاسم.
5345

54-
### الـ clientEnv Object
55-
5646
هُنا حيثُ تقوم بعمل Destruct لـ `process.env`
5747
تحتاج Zod الي Object لتكون قادرة على تصحيح المُدخلات وبسبب طريقة عمل Next.js فلن نستطيع فعل هذا تلقائيا لذلك يجب أن تتم هذة العملية يدويا، لا تقلق فـ Typescript تقوم بتحذيرك إذا ارتكبت خطاّ.
5848

@@ -109,11 +99,6 @@ export const serverSchema = z.object({
10999
// ...
110100
TWITTER_API_TOKEN: z.string(),
111101
});
112-
113-
export const serverEnv = {
114-
// ...
115-
TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
116-
};
117102
```
118103

119104
**ملحوطة:** النص الفارغ تتعامل معة zod علي أنه نص صحيح، إذا ما اردت ان تُغيّر هذا الاسلوب فإستخدم `z.string().min(1)`

Diff for: www/src/pages/en/usage/env-variables.md

-21
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,9 @@ export const serverSchema = z.object({
2828
// DATABASE_URL: z.string().url(),
2929
});
3030

31-
export const serverEnv = {
32-
// DATABASE_URL: process.env.DATABASE_URL,
33-
};
34-
3531
export const clientSchema = z.object({
3632
// NEXT_PUBLIC_WS_KEY: z.string(),
3733
});
38-
39-
export const clientEnv = {
40-
// NEXT_PUBLIC_WS_KEY: process.env.NEXT_PUBLIC_WS_KEY,
41-
};
4234
```
4335

4436
### Server Schema
@@ -53,14 +45,6 @@ Define your client-side environment variables schema here.
5345

5446
To expose them to the client you need to prefix them with `NEXT_PUBLIC`. Validation will fail if you don't to help you detect invalid configuration.
5547

56-
### clientEnv Object
57-
58-
Destruct the `process.env` here.
59-
60-
We need a JavaScript object that we can parse our Zod-schemas with and due to the way Next.js handles environment variables, you can't destruct `process.env` like a regular object, so we need to do it manually.
61-
62-
TypeScript will help you make sure that you have entered the keys in both `clientEnv` as well as `clientSchema`.
63-
6448
```ts
6549
// ❌ This doesn't work, we need to destruct it manually
6650
const schema = z.object({
@@ -120,11 +104,6 @@ export const serverSchema = z.object({
120104
// ...
121105
TWITTER_API_TOKEN: z.string(),
122106
});
123-
124-
export const serverEnv = {
125-
// ...
126-
TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
127-
};
128107
```
129108

130109
_**NOTE:** An empty string is still a string, so `z.string()` will accept an empty string as a valid value. If you want to make sure that the environment variable is not empty, you can use `z.string().min(1)`._

Diff for: www/src/pages/fr/usage/env-variables.md

+1-22
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,16 @@ _TLDR; Si vous désirez ajouter une nouvelle variable d’environnement, vous de
2222

2323
## schema.mjs
2424

25-
C'est le fichier que vous allez modifier. Il contient deux schémas, l'un est pour les variables d'environnement côté serveur et le second est pour le côté client connu sous l'objet `clientEnv`.
25+
C'est le fichier que vous allez modifier. Il contient deux schémas, l'un est pour les variables d'environnement côté serveur et le second est pour le côté client connu.
2626

2727
```ts:env/schema.mjs
2828
export const serverSchema = z.object({
2929
// DATABASE_URL: z.string().url(),
3030
});
3131

32-
export const serverEnv = {
33-
// DATABASE_URL: process.env.DATABASE_URL,
34-
};
35-
3632
export const clientSchema = z.object({
3733
// NEXT_PUBLIC_WS_KEY: z.string(),
3834
});
39-
40-
export const clientEnv = {
41-
// NEXT_PUBLIC_WS_KEY: process.env.NEXT_PUBLIC_WS_KEY,
42-
};
4335
```
4436

4537
### Schéma Serveur
@@ -54,14 +46,6 @@ Définissez votre schéma de variables d'environnement du côté client ici.
5446

5547
Pour les exposer au client, vous devez les préfixer avec `NEXT_PUBLIC`. La validation échouera si vous ne le faites pas, afin de vous aider à détecter une configuration non valide.
5648

57-
### Objet clientEnv
58-
59-
Déstructurez `process.env` ici.
60-
61-
Nous avons besoin d'un objet JavaScript avec lequel nous pouvons analyser nos schémas Zod et en raison de la façon dont Next.js gère les variables d'environnement, vous ne pouvez pas déstructurez `process.env` comme un objet régulier. Du coup nous devons le faire manuellement.
62-
63-
TypeScript vous aidera à vous assurer que vous avez entré les clés dans `clientEnv` ainsi que `clientSchema`.
64-
6549
```ts
6650
// ❌ Cela ne fonctionne pas, nous devons le déstructurer manuellement
6751
const schema = z.object({
@@ -121,11 +105,6 @@ export const serverSchema = z.object({
121105
// ...
122106
TWITTER_API_TOKEN: z.string(),
123107
});
124-
125-
export const serverEnv = {
126-
// ...
127-
TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
128-
};
129108
```
130109

131110
_**NOTE:** Une chaîne vide est toujours une chaîne, donc `z.string()` acceptera une chaîne vide comme valeur valide. Si vous voulez vous assurer que la variable d'environnement n'est pas vide, vous pouvez utiliser `z.string().min(1)`._

Diff for: www/src/pages/no/usage/env-variables.md

+1-22
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,16 @@ _TLDR; Hvis du vil legge til en ny miljøvariabel, må du definere den i både `
2121

2222
## schema.mjs
2323

24-
Endringene skjer i denne filen. Den inneholder to skjemaer, ett for servermiljøvariabler og ett for klientmiljøvariabler, og et `clientEnv`-objekt.
24+
Endringene skjer i denne filen. Den inneholder to skjemaer, ett for servermiljøvariabler og ett for klientmiljøvariabler.
2525

2626
```ts:env/schema.mjs
2727
export const serverSchema = z.object({
2828
// DATABASE_URL: z.string().url(),
2929
});
3030

31-
export const serverEnv = {
32-
// DATABASE_URL: process.env.DATABASE_URL,
33-
};
34-
3531
export const clientSchema = z.object({
3632
// NEXT_PUBLIC_WS_KEY: z.string(),
3733
});
38-
39-
export const clientEnv = {
40-
// NEXT_PUBLIC_WS_KEY: process.env.NEXT_PUBLIC_WS_KEY,
41-
};
4234
```
4335

4436
### Oppsett av Serverskjema
@@ -53,14 +45,6 @@ Definer ditt skjema for klientmiljøvariabeler her.
5345

5446
For å gjøre dem tilgjengelige for klienten, __ du prefiksere dem med `NEXT_PUBLIC`. Validering vil mislykkes hvis du ikke gjør det, for å hjelpe deg med å oppdage en ugyldig konfigurasjon.
5547

56-
### clientEnv-Objektet
57-
58-
I denne filen må vi få tilgang til verdiene fra `process.env`-objektet.
59-
60-
Vi trenger et JavaScript-objekt som vi kan analysere gjennom Zod-skjemaene og på grunn av måten Next.js håndterer miljøvariabler kan vi ikke destrukturere `process.env`-objektet som et normalt objekt. Derfor må vi gjøre det manuelt.
61-
62-
TypeScript vil hjelpe deg med å sørge for at du legger nøklene i både `clientEnv` og `clientSchema`.
63-
6448
```ts
6549
// ❌ Dette fungerer ikke. Vi må destrukturere den manuelt.
6650
const schema = z.object({
@@ -118,11 +102,6 @@ export const serverSchema = z.object({
118102
// ...
119103
TWITTER_API_TOKEN: z.string(),
120104
});
121-
122-
export const serverEnv = {
123-
// ...
124-
TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
125-
};
126105
```
127106

128107
_**MERK:** En tom streng er fortsatt en streng, så `z.string()` vil godta en tom streng som en gyldig verdi. Hvis du vil forsikre deg om at miljøvariabelen ikke er tom, kan du bruke `z.string().min(1)`._

0 commit comments

Comments
 (0)