@dotenvage/node 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +337 -0
- package/bin/dotenvage-next.js +18 -0
- package/bin/dotenvage.js +265 -0
- package/dotenvage-napi.darwin-arm64.node +0 -0
- package/dotenvage-napi.darwin-x64.node +0 -0
- package/dotenvage-napi.linux-arm64-musl.node +0 -0
- package/examples/app-config.ts +129 -0
- package/examples/auto-encrypt.ts +132 -0
- package/examples/basic.js +127 -0
- package/examples/encrypt-decrypt.ts +56 -0
- package/examples/load-env.ts +51 -0
- package/examples/nextjs-config.ts +132 -0
- package/examples/tsconfig.json +22 -0
- package/index.d.ts +57 -0
- package/index.js +582 -0
- package/nextjs/README.md +271 -0
- package/nextjs/config.d.ts +32 -0
- package/nextjs/config.mjs +59 -0
- package/nextjs/loader.d.ts +22 -0
- package/nextjs/loader.mjs +117 -0
- package/nextjs/preinit.d.ts +13 -0
- package/nextjs/preinit.mjs +106 -0
- package/nextjs/wrapper.mjs +87 -0
- package/package.json +91 -0
package/nextjs/README.md
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# Next.js Integration with dotenvage
|
|
2
|
+
|
|
3
|
+
This directory contains utilities for integrating dotenvage with
|
|
4
|
+
Next.js applications, ensuring that encrypted environment variables
|
|
5
|
+
are properly loaded before Next.js processes them.
|
|
6
|
+
|
|
7
|
+
## The Problem
|
|
8
|
+
|
|
9
|
+
Next.js loads environment variables from `.env*` files using
|
|
10
|
+
`@next/env` **before** your `next.config.mjs` runs. If your `.env`
|
|
11
|
+
files contain encrypted values (like `ENC[AGE:...]`), Next.js will try
|
|
12
|
+
to use those encrypted values directly, which won't work.
|
|
13
|
+
|
|
14
|
+
Additionally, for `NEXT_PUBLIC_*` variables that need to be available
|
|
15
|
+
in Edge Runtime (middleware), Next.js must inline them at build time.
|
|
16
|
+
If the values are encrypted when Next.js reads them, they'll be
|
|
17
|
+
inlined as encrypted strings, which is useless.
|
|
18
|
+
|
|
19
|
+
## The Solution
|
|
20
|
+
|
|
21
|
+
We leverage the fact that `@next/env` **does not overwrite** existing
|
|
22
|
+
`process.env` values. By loading and decrypting environment variables
|
|
23
|
+
**before** Next.js starts, we ensure:
|
|
24
|
+
|
|
25
|
+
1. Encrypted values are decrypted and set in `process.env` first
|
|
26
|
+
2. When `@next/env` runs, it sees existing values and preserves them
|
|
27
|
+
3. Decrypted values are available for Next.js to inline into the build
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
**For Edge Runtime (middleware) support (recommended):**
|
|
32
|
+
|
|
33
|
+
Use the `dotenvage-next` bin script to start Next.js:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"scripts": {
|
|
38
|
+
"dev": "dotenvage-next dev",
|
|
39
|
+
"build": "dotenvage-next build"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
And wrap your config:
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
import { withDotenvage } from "@dotenvage/node/nextjs/config";
|
|
48
|
+
|
|
49
|
+
export default withDotenvage({
|
|
50
|
+
// Your Next.js config
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**For server-side only (no Edge Runtime):**
|
|
55
|
+
|
|
56
|
+
Use `loadEnv()` in your config file:
|
|
57
|
+
|
|
58
|
+
```javascript
|
|
59
|
+
import { loadEnv } from "@dotenvage/node/nextjs";
|
|
60
|
+
|
|
61
|
+
loadEnv();
|
|
62
|
+
|
|
63
|
+
export default {
|
|
64
|
+
// Your Next.js config
|
|
65
|
+
};
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Files
|
|
69
|
+
|
|
70
|
+
### `config.mjs`
|
|
71
|
+
|
|
72
|
+
A configuration wrapper for API consistency. This is mainly for
|
|
73
|
+
convenience when using the `dotenvage-next` wrapper script.
|
|
74
|
+
|
|
75
|
+
**Note:** For Edge Runtime (middleware) support, you MUST use the
|
|
76
|
+
`dotenvage-next` wrapper script. For server-side only (no Edge
|
|
77
|
+
Runtime), you can use `loadEnv()` directly (see `loader.mjs` below).
|
|
78
|
+
|
|
79
|
+
**Usage in `next.config.mjs`:**
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
import { withDotenvage } from "@dotenvage/node/nextjs/config";
|
|
83
|
+
import nextMDX from "@next/mdx";
|
|
84
|
+
|
|
85
|
+
const nextConfig = {
|
|
86
|
+
// Your Next.js config
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const withMDX = nextMDX({
|
|
90
|
+
// MDX options
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
export default withDotenvage(withMDX(nextConfig));
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Note:** When using `dotenvage-next` wrapper script, env vars are
|
|
97
|
+
already loaded, so this wrapper is just a pass-through for
|
|
98
|
+
consistency.
|
|
99
|
+
|
|
100
|
+
### `loader.mjs` (For server-side only, no Edge Runtime)
|
|
101
|
+
|
|
102
|
+
A standard loader for use in `next.config.mjs` when you don't use Edge
|
|
103
|
+
Runtime (middleware). Use this when you only need server-side code to
|
|
104
|
+
access encrypted environment variables.
|
|
105
|
+
|
|
106
|
+
**Important:** This works for server-side code (API routes, server
|
|
107
|
+
components) because `loadEnv()` runs in `next.config.mjs` and can
|
|
108
|
+
decrypt values before server-side code accesses them. However, it does
|
|
109
|
+
NOT work for Edge Runtime (middleware) because Next.js inlines
|
|
110
|
+
`NEXT_PUBLIC_*` variables at build time, BEFORE `next.config.mjs`
|
|
111
|
+
runs.
|
|
112
|
+
|
|
113
|
+
For Edge Runtime support, you MUST use the `dotenvage-next` wrapper
|
|
114
|
+
script.
|
|
115
|
+
|
|
116
|
+
**Usage in `next.config.mjs` (server-side only):**
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
import { loadEnv } from "@dotenvage/node/nextjs";
|
|
120
|
+
|
|
121
|
+
// Load and decrypt environment variables
|
|
122
|
+
loadEnv();
|
|
123
|
+
|
|
124
|
+
export default {
|
|
125
|
+
// Your Next.js config
|
|
126
|
+
};
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Note:** When using `loadEnv()` in the config file, `@next/env` will
|
|
130
|
+
have already loaded encrypted values, but `loadEnv()` overwrites them
|
|
131
|
+
with decrypted values, so server-side code sees the decrypted values.
|
|
132
|
+
|
|
133
|
+
### `nextjs-preinit.mjs`
|
|
134
|
+
|
|
135
|
+
A pre-initialization loader that must run **before** Next.js starts.
|
|
136
|
+
This is critical for ensuring `NEXT_PUBLIC_*` variables are available
|
|
137
|
+
in Edge Runtime.
|
|
138
|
+
|
|
139
|
+
**Usage options:**
|
|
140
|
+
|
|
141
|
+
1. **Via Node.js `-r` flag:**
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"scripts": {
|
|
146
|
+
"dev": "node -r @dotenvage/node/nextjs/preinit node_modules/.bin/next dev",
|
|
147
|
+
"build": "node -r @dotenvage/node/nextjs/preinit node_modules/.bin/next build"
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
1. **Via wrapper script (recommended):**
|
|
153
|
+
|
|
154
|
+
See `wrapper.mjs` below.
|
|
155
|
+
|
|
156
|
+
### `nextjs-wrapper.mjs`
|
|
157
|
+
|
|
158
|
+
A wrapper script that loads environment variables and then starts
|
|
159
|
+
Next.js. This is the easiest way to ensure proper loading order.
|
|
160
|
+
|
|
161
|
+
**The wrapper automatically:**
|
|
162
|
+
|
|
163
|
+
- Detects your package manager (pnpm/npm/yarn) by checking for lock
|
|
164
|
+
files
|
|
165
|
+
- Uses the correct package manager's `exec` command to run Next.js
|
|
166
|
+
- Handles path resolution automatically for all package manager setups
|
|
167
|
+
- Works reliably in monorepos and pnpm workspaces
|
|
168
|
+
|
|
169
|
+
**Usage - Update your `package.json`:**
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"scripts": {
|
|
174
|
+
"dev": "dotenvage-next dev",
|
|
175
|
+
"build": "dotenvage-next build"
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
That's it! No need to create local wrapper scripts - the
|
|
181
|
+
`dotenvage-next` bin script handles everything automatically. The
|
|
182
|
+
`dotenvage-next` command is installed when you install
|
|
183
|
+
`@dotenvage/node`.
|
|
184
|
+
|
|
185
|
+
## Complete Integration Example
|
|
186
|
+
|
|
187
|
+
1. **Install dotenvage:**
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
npm install @dotenvage/node
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
2. **Encrypt your `.env` files:**
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
npx dotenvage encrypt .env.local
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
3. **Set your encryption key as an environment variable:**
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
export EKG_AGE_KEY=your-key-name
|
|
203
|
+
# or
|
|
204
|
+
export DOTENVAGE_AGE_KEY="your-age-key-string"
|
|
205
|
+
# or
|
|
206
|
+
export AGE_KEY="your-age-key-string"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
4. **Create a wrapper script** (see `wrapper.mjs` example above, or
|
|
210
|
+
use the one in this directory)
|
|
211
|
+
|
|
212
|
+
5. **Update your `next.config.mjs`** (optional, for additional
|
|
213
|
+
safety):
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
import { loadEnv } from "@dotenvage/node/nextjs";
|
|
217
|
+
|
|
218
|
+
// This is a backup - the preinit loader should have already loaded
|
|
219
|
+
// but this ensures variables are available if preinit wasn't used
|
|
220
|
+
loadEnv();
|
|
221
|
+
|
|
222
|
+
export default {
|
|
223
|
+
// Your Next.js config
|
|
224
|
+
env: {
|
|
225
|
+
// Explicitly expose critical variables to ensure they're inlined
|
|
226
|
+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY:
|
|
227
|
+
process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY || "",
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## How It Works
|
|
233
|
+
|
|
234
|
+
1. **Pre-init loader runs first** → Decrypts `.env` files → Sets
|
|
235
|
+
values in `process.env`
|
|
236
|
+
2. **Next.js starts** → `@next/env` runs → Sees existing values →
|
|
237
|
+
Doesn't overwrite
|
|
238
|
+
3. **Next.js builds** → Inlines `NEXT_PUBLIC_*` variables → Uses
|
|
239
|
+
decrypted values ✅
|
|
240
|
+
4. **Edge Runtime** → Has access to decrypted `NEXT_PUBLIC_*`
|
|
241
|
+
variables ✅
|
|
242
|
+
|
|
243
|
+
## Troubleshooting
|
|
244
|
+
|
|
245
|
+
### Variables still encrypted in Edge Runtime
|
|
246
|
+
|
|
247
|
+
- Make sure you're using the pre-init loader (not just the standard
|
|
248
|
+
loader)
|
|
249
|
+
- Verify the wrapper script is being used in your `package.json`
|
|
250
|
+
scripts
|
|
251
|
+
- Check that the encryption key is set correctly
|
|
252
|
+
|
|
253
|
+
### Variables not loading
|
|
254
|
+
|
|
255
|
+
- Check that your encryption key environment variable is set
|
|
256
|
+
- Verify your `.env` files contain encrypted values (starting with
|
|
257
|
+
`ENC[AGE:`)
|
|
258
|
+
- Check console output for error messages from the loader
|
|
259
|
+
|
|
260
|
+
### Build fails
|
|
261
|
+
|
|
262
|
+
- In production/Vercel, ensure the encryption key is set as an
|
|
263
|
+
environment variable
|
|
264
|
+
- The pre-init loader will fail hard in production if it can't decrypt
|
|
265
|
+
files
|
|
266
|
+
- Check Vercel environment variables section in your project settings
|
|
267
|
+
|
|
268
|
+
## See Also
|
|
269
|
+
|
|
270
|
+
- [dotenvage main documentation](../../README.md)
|
|
271
|
+
- [Next.js environment variables documentation](https://nextjs.org/docs/app/building-your-application/configuring/environment-variables)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js configuration wrapper that automatically loads encrypted environment variables
|
|
3
|
+
*
|
|
4
|
+
* @module @dotenvage/node/nextjs/config
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { NextConfig } from 'next'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Wraps a Next.js configuration object to ensure dotenvage is loaded.
|
|
11
|
+
* Environment variables are automatically loaded when this module is imported.
|
|
12
|
+
*
|
|
13
|
+
* @param config - Next.js config object or function
|
|
14
|
+
* @returns The same config (pass-through wrapper)
|
|
15
|
+
*/
|
|
16
|
+
export function withDotenvage(
|
|
17
|
+
config: NextConfig | ((phase: string) => NextConfig),
|
|
18
|
+
): NextConfig | ((phase: string) => NextConfig)
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Wraps a Next.js configuration function to ensure dotenvage is loaded.
|
|
22
|
+
* Useful when you need to access the build phase.
|
|
23
|
+
*
|
|
24
|
+
* @param configFn - Next.js config function
|
|
25
|
+
* @returns The same function (pass-through wrapper)
|
|
26
|
+
*/
|
|
27
|
+
export function withDotenvageConfig(
|
|
28
|
+
configFn: (
|
|
29
|
+
phase: string,
|
|
30
|
+
defaultConfig: NextConfig,
|
|
31
|
+
) => NextConfig | Promise<NextConfig>,
|
|
32
|
+
): (phase: string, defaultConfig: NextConfig) => NextConfig | Promise<NextConfig>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js configuration wrapper for dotenvage integration.
|
|
3
|
+
*
|
|
4
|
+
* This wrapper can be used in two ways:
|
|
5
|
+
*
|
|
6
|
+
* 1. **With wrapper script (recommended for Edge Runtime):**
|
|
7
|
+
* Use `dotenvage-next` bin script to start Next.js:
|
|
8
|
+
* "dev": "dotenvage-next dev"
|
|
9
|
+
* "build": "dotenvage-next build"
|
|
10
|
+
* The wrapper script loads env vars BEFORE Next.js starts, ensuring
|
|
11
|
+
* they're available everywhere including Edge Runtime.
|
|
12
|
+
*
|
|
13
|
+
* 2. **Without wrapper script (server-side only, no Edge Runtime):**
|
|
14
|
+
* Use `loadEnv()` from `@dotenvage/node/nextjs` in your config file:
|
|
15
|
+
* import { loadEnv } from '@dotenvage/node/nextjs'
|
|
16
|
+
* loadEnv()
|
|
17
|
+
* Note: This only works for server-side code, not Edge Runtime/middleware.
|
|
18
|
+
*
|
|
19
|
+
* Usage in next.config.mjs:
|
|
20
|
+
* import { withDotenvage } from '@dotenvage/node/nextjs/config'
|
|
21
|
+
* import nextMDX from '@next/mdx'
|
|
22
|
+
*
|
|
23
|
+
* const nextConfig = {
|
|
24
|
+
* // your config
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* export default withDotenvage(nextConfig)
|
|
28
|
+
*
|
|
29
|
+
* IMPORTANT: When using `dotenvage-next` wrapper script, env vars are
|
|
30
|
+
* already loaded, so this wrapper is just a pass-through for consistency.
|
|
31
|
+
* When NOT using the wrapper script, use `loadEnv()` directly in your config.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Wraps a Next.js configuration object.
|
|
36
|
+
* This is mainly for convenience and API consistency.
|
|
37
|
+
* When using `dotenvage-next` wrapper script, env vars are already loaded.
|
|
38
|
+
*
|
|
39
|
+
* @param {import('next').NextConfig | ((phase: string) => import('next').NextConfig)} config - Next.js config object or function
|
|
40
|
+
* @returns {import('next').NextConfig | ((phase: string) => import('next').NextConfig)} The same config (pass-through)
|
|
41
|
+
*/
|
|
42
|
+
export function withDotenvage(config) {
|
|
43
|
+
// Pass-through wrapper for API consistency
|
|
44
|
+
// When using `dotenvage-next` wrapper script, env vars are already loaded
|
|
45
|
+
return config;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Wraps a Next.js configuration function to ensure dotenvage is loaded.
|
|
50
|
+
* Useful when you need to access the build phase.
|
|
51
|
+
*
|
|
52
|
+
* @param {(phase: string, defaultConfig: import('next').NextConfig) => import('next').NextConfig} configFn - Next.js config function
|
|
53
|
+
* @returns {(phase: string, defaultConfig: import('next').NextConfig) => import('next').NextConfig} The same function (pass-through)
|
|
54
|
+
*/
|
|
55
|
+
export function withDotenvageConfig(configFn) {
|
|
56
|
+
// Pass-through wrapper for API consistency
|
|
57
|
+
// When using `dotenvage-next` wrapper script, env vars are already loaded
|
|
58
|
+
return configFn;
|
|
59
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js environment variable loader using dotenvage
|
|
3
|
+
*
|
|
4
|
+
* @module @dotenvage/node/nextjs
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Loads environment variables from encrypted .env files
|
|
9
|
+
* This runs automatically when this module is imported
|
|
10
|
+
* Always loads from dotenvage in all environments (local, Vercel CI, production)
|
|
11
|
+
*/
|
|
12
|
+
export function loadEnv(): void
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get all environment variables (for testing/debugging)
|
|
16
|
+
*/
|
|
17
|
+
export function getAllEnvVars(): Record<string, string>
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get variable names (for testing/debugging)
|
|
21
|
+
*/
|
|
22
|
+
export function getEnvVarNames(): string[]
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js environment variable loader using dotenvage
|
|
3
|
+
*
|
|
4
|
+
* This module loads encrypted .env files at runtime, making environment
|
|
5
|
+
* variables available to the Next.js application.
|
|
6
|
+
*
|
|
7
|
+
* It automatically loads encrypted .env files in all environments:
|
|
8
|
+
* - Local development (loads from .env, .env.local, etc.)
|
|
9
|
+
* - Vercel CI (loads from committed encrypted .env files)
|
|
10
|
+
* - Production builds (loads from committed encrypted .env files)
|
|
11
|
+
*
|
|
12
|
+
* For Vercel CI, you only need to set the encryption key as an environment variable:
|
|
13
|
+
* - EKG_AGE_KEY (for key name-based lookup: ekg/dr-rs-ekg)
|
|
14
|
+
* - DOTENVAGE_AGE_KEY or AGE_KEY (for direct key string)
|
|
15
|
+
*
|
|
16
|
+
* Encrypted .env files are committed to git and loaded at runtime.
|
|
17
|
+
* No need to sync environment variables to Vercel separately.
|
|
18
|
+
*
|
|
19
|
+
* Usage in next.config.mjs:
|
|
20
|
+
* import { loadEnv } from '@dotenvage/node/nextjs'
|
|
21
|
+
* loadEnv()
|
|
22
|
+
*/
|
|
23
|
+
import * as dotenvage from "../index.js";
|
|
24
|
+
|
|
25
|
+
let loaded = false;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Loads environment variables from encrypted .env files
|
|
29
|
+
* This runs automatically when this module is imported
|
|
30
|
+
* Always loads from dotenvage in all environments (local, Vercel CI, production)
|
|
31
|
+
*/
|
|
32
|
+
export function loadEnv() {
|
|
33
|
+
// Only load once
|
|
34
|
+
if (loaded) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
// Create loader and load environment variables from encrypted .env files
|
|
40
|
+
// This mutates process.env with decrypted values
|
|
41
|
+
// Works in all environments: local, Vercel CI, production
|
|
42
|
+
const loader = dotenvage.JsEnvLoader.new();
|
|
43
|
+
loader.load();
|
|
44
|
+
|
|
45
|
+
const variableNames = loader.getAllVariableNames();
|
|
46
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
47
|
+
|
|
48
|
+
if (!isProduction || process.env.VERCEL) {
|
|
49
|
+
console.log(
|
|
50
|
+
`✓ Loaded ${variableNames.length} environment variables from dotenvage`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
loaded = true;
|
|
55
|
+
} catch (error) {
|
|
56
|
+
// Always show errors - we need to know if loading fails
|
|
57
|
+
const errorMessage =
|
|
58
|
+
error instanceof Error ? error.message : String(error);
|
|
59
|
+
console.error(
|
|
60
|
+
"❌ Failed to load environment variables from dotenvage:",
|
|
61
|
+
errorMessage
|
|
62
|
+
);
|
|
63
|
+
console.error("");
|
|
64
|
+
console.error(" Make sure one of these is set:");
|
|
65
|
+
console.error(
|
|
66
|
+
" - EKG_AGE_KEY (for key name-based lookup: ekg/dr-rs-ekg)"
|
|
67
|
+
);
|
|
68
|
+
console.error(" - DOTENVAGE_AGE_KEY (direct key string)");
|
|
69
|
+
console.error(" - AGE_KEY (direct key string)");
|
|
70
|
+
console.error(
|
|
71
|
+
" - EKG_AGE_KEY_NAME in .env file (points to key file location)"
|
|
72
|
+
);
|
|
73
|
+
console.error("");
|
|
74
|
+
|
|
75
|
+
// In production/Vercel, fail hard - we need env vars to work
|
|
76
|
+
if (process.env.NODE_ENV === "production" || process.env.VERCEL) {
|
|
77
|
+
console.error(
|
|
78
|
+
" This is a production build. Environment variables are required!"
|
|
79
|
+
);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// In development, warn but continue (might be missing key for testing)
|
|
84
|
+
console.warn(
|
|
85
|
+
" Continuing in development mode, but some features may not work."
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// Mark as loaded to prevent retry loops
|
|
89
|
+
loaded = true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get all environment variables (for testing/debugging)
|
|
95
|
+
*/
|
|
96
|
+
export function getAllEnvVars() {
|
|
97
|
+
try {
|
|
98
|
+
const loader = dotenvage.JsEnvLoader.new();
|
|
99
|
+
return loader.getAllVariables();
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error("Error getting environment variables:", error);
|
|
102
|
+
return {};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get variable names (for testing/debugging)
|
|
108
|
+
*/
|
|
109
|
+
export function getEnvVarNames() {
|
|
110
|
+
try {
|
|
111
|
+
const loader = dotenvage.JsEnvLoader.new();
|
|
112
|
+
return loader.getAllVariableNames();
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error("Error getting variable names:", error);
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-initialization environment variable loader for Next.js
|
|
3
|
+
*
|
|
4
|
+
* This module loads encrypted .env files BEFORE Next.js loads its own .env files.
|
|
5
|
+
* It must be loaded before Next.js starts (via -r flag, require hook, or wrapper script).
|
|
6
|
+
*
|
|
7
|
+
* @module @dotenvage/node/nextjs/preinit
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// This module has side effects (loads environment variables)
|
|
11
|
+
// TypeScript declaration for importing the module
|
|
12
|
+
declare const _default: void
|
|
13
|
+
export default _default
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-initialization environment variable loader for Next.js
|
|
3
|
+
*
|
|
4
|
+
* This module loads encrypted .env files BEFORE Next.js loads its own .env files.
|
|
5
|
+
* It must be loaded before Next.js starts (via -r flag, require hook, or wrapper script).
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT: Next.js's @next/env does NOT overwrite existing process.env values.
|
|
8
|
+
* By loading encrypted env vars FIRST, we ensure:
|
|
9
|
+
* 1. Encrypted values are decrypted and set in process.env
|
|
10
|
+
* 2. When @next/env runs, it sees existing values and doesn't overwrite them
|
|
11
|
+
* 3. Decrypted values are preserved throughout the Next.js build/runtime
|
|
12
|
+
*
|
|
13
|
+
* This is critical for Edge Runtime (middleware) where NEXT_PUBLIC_* variables
|
|
14
|
+
* need to be inlined at build time.
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* - Via -r flag: node -r @dotenvage/node/nextjs/preinit node_modules/.bin/next dev
|
|
18
|
+
* - Via wrapper script: See wrapper.mjs
|
|
19
|
+
*/
|
|
20
|
+
import * as dotenvage from "../index.js";
|
|
21
|
+
|
|
22
|
+
let loaded = false;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Loads environment variables from encrypted .env files
|
|
26
|
+
* This runs immediately when this module is imported
|
|
27
|
+
*
|
|
28
|
+
* Note: @next/env respects existing process.env values and won't overwrite them,
|
|
29
|
+
* so by loading first, our decrypted values take precedence over the encrypted .env files.
|
|
30
|
+
*/
|
|
31
|
+
function loadEnvPreinit() {
|
|
32
|
+
// Only load once
|
|
33
|
+
if (loaded) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
// Store which variables existed before loading (for debugging)
|
|
39
|
+
const existingVars = new Set(Object.keys(process.env));
|
|
40
|
+
|
|
41
|
+
// Create loader and load environment variables from encrypted .env files
|
|
42
|
+
// This mutates process.env with decrypted values
|
|
43
|
+
const loader = dotenvage.JsEnvLoader.new();
|
|
44
|
+
loader.load();
|
|
45
|
+
|
|
46
|
+
const variableNames = loader.getAllVariableNames();
|
|
47
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
48
|
+
|
|
49
|
+
// Check which variables we loaded that didn't exist before
|
|
50
|
+
const newlyLoadedVars = variableNames.filter(
|
|
51
|
+
(name) => !existingVars.has(name)
|
|
52
|
+
);
|
|
53
|
+
const overwrittenVars = variableNames.filter((name) =>
|
|
54
|
+
existingVars.has(name)
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
if (!isProduction || process.env.VERCEL) {
|
|
58
|
+
console.log(
|
|
59
|
+
`✓ Pre-initialized ${variableNames.length} environment variables from dotenvage`
|
|
60
|
+
);
|
|
61
|
+
if (
|
|
62
|
+
overwrittenVars.length > 0 &&
|
|
63
|
+
process.env.NODE_ENV === "development"
|
|
64
|
+
) {
|
|
65
|
+
console.log(
|
|
66
|
+
` Note: ${overwrittenVars.length} variables already existed and were preserved`
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
loaded = true;
|
|
72
|
+
} catch (error) {
|
|
73
|
+
// Always show errors - we need to know if loading fails
|
|
74
|
+
const errorMessage =
|
|
75
|
+
error instanceof Error ? error.message : String(error);
|
|
76
|
+
console.error(
|
|
77
|
+
"❌ Failed to pre-initialize environment variables from dotenvage:",
|
|
78
|
+
errorMessage
|
|
79
|
+
);
|
|
80
|
+
console.error("");
|
|
81
|
+
console.error(" Make sure one of these is set:");
|
|
82
|
+
console.error(
|
|
83
|
+
" - EKG_AGE_KEY (for key name-based lookup: ekg/dr-rs-ekg)"
|
|
84
|
+
);
|
|
85
|
+
console.error(" - DOTENVAGE_AGE_KEY (direct key string)");
|
|
86
|
+
console.error(" - AGE_KEY (direct key string)");
|
|
87
|
+
console.error("");
|
|
88
|
+
|
|
89
|
+
// In production/Vercel, fail hard - we need env vars to work
|
|
90
|
+
if (process.env.NODE_ENV === "production" || process.env.VERCEL) {
|
|
91
|
+
console.error(
|
|
92
|
+
" This is a production build. Environment variables are required!"
|
|
93
|
+
);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// In development, warn but continue
|
|
98
|
+
console.warn(
|
|
99
|
+
" Continuing in development mode, but some features may not work."
|
|
100
|
+
);
|
|
101
|
+
loaded = true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Auto-load when this module is imported
|
|
106
|
+
loadEnvPreinit();
|