|
3 | 3 | </br> |
4 | 4 | Nuxt Safe Runtime Config</h1> |
5 | 5 | <p align="center"> |
6 | | -Validate Nuxt runtime config at build time using <b>Zod</b>, <b>Valibot</b>, <b>ArkType</b>, or any Standard Schema compatible library. |
| 6 | +Validate Nuxt runtime config at build or runtime using <b>Zod</b>, <b>Valibot</b>, <b>ArkType</b>, or any Standard Schema compatible library. |
7 | 7 | </p> |
8 | 8 | <br/> |
9 | 9 |
|
10 | 10 | <p align="center"> |
11 | | - <a href="https://www.npmjs.com/package/nuxt-safe-runtime-config"> |
12 | | - <img src="https://img.shields.io/npm/v/nuxt-safe-runtime-config.svg" alt="npm version" /> |
13 | | - </a> |
14 | | - <a href="https://www.npmjs.com/package/nuxt-safe-runtime-config"> |
15 | | - <img src="https://img.shields.io/npm/dm/nuxt-safe-runtime-config.svg" alt="npm downloads" /> |
16 | | - </a> |
17 | | - <a href="https://github.com/onmax/nuxt-safe-runtime-config/blob/main/LICENSE"> |
18 | | - <img src="https://img.shields.io/github/license/onmax/nuxt-safe-runtime-config.svg" alt="License" /> |
19 | | - </a> |
20 | | - <a href="https://nuxt.com"> |
21 | | - <img src="https://img.shields.io/badge/Nuxt-3.0+-00DC82.svg" alt="Nuxt" /> |
22 | | - </a> |
| 11 | + <a href="https://www.npmjs.com/package/nuxt-safe-runtime-config"><img src="https://img.shields.io/npm/v/nuxt-safe-runtime-config.svg" alt="npm version" /></a> |
| 12 | + <a href="https://www.npmjs.com/package/nuxt-safe-runtime-config"><img src="https://img.shields.io/npm/dm/nuxt-safe-runtime-config.svg" alt="npm downloads" /></a> |
| 13 | + <a href="https://github.com/onmax/nuxt-safe-runtime-config/blob/main/LICENSE"><img src="https://img.shields.io/github/license/onmax/nuxt-safe-runtime-config.svg" alt="License" /></a> |
| 14 | + <a href="https://nuxt.com"><img src="https://img.shields.io/badge/Nuxt-3.0+-00DC82.svg" alt="Nuxt" /></a> |
| 15 | +</p> |
23 | 16 |
|
24 | | - <p align="center"> |
25 | | - <a href="https://github.com/nuxt/nuxt/discussions/32301"> |
26 | | - 🔗 Related Nuxt RFC: Enable Standard Schema Validation in Nuxt Config |
27 | | - </a> |
28 | | - </p> |
| 17 | +<p align="center"> |
| 18 | + <a href="https://nuxt-safe-runtime-config.vercel.app">Documentation</a> |
29 | 19 | </p> |
30 | 20 |
|
31 | 21 | ## Features |
32 | 22 |
|
33 | | -- 🔒 **Build-time validation** with Zod, Valibot, ArkType, or any [Standard Schema](https://standardschema.dev/) library |
34 | | -- 🚀 **Runtime validation** (opt-in) validates config when the server starts |
35 | | -- ✨ **Auto-generated types** — `useSafeRuntimeConfig()` is fully typed without manual generics |
36 | | -- 🛠 **ESLint plugin** warns when using `useRuntimeConfig()` instead of the type-safe composable |
37 | | -- ⚡ **Zero runtime overhead** by default — validation happens at build time only |
38 | | - |
39 | | -## Quick Setup |
| 23 | +- **Build-time validation** with Zod, Valibot, ArkType, or any [Standard Schema](https://standardschema.dev/) library |
| 24 | +- **Runtime validation** (opt-in) validates config when the server starts |
| 25 | +- **Auto-generated types** - `useSafeRuntimeConfig()` is fully typed |
| 26 | +- **ESLint plugin** warns when using `useRuntimeConfig()` instead of the type-safe composable |
40 | 27 |
|
41 | | -Install the module: |
| 28 | +## Quick Start |
42 | 29 |
|
43 | 30 | ```bash |
44 | 31 | npx nuxi module add nuxt-safe-runtime-config |
45 | 32 | ``` |
46 | 33 |
|
47 | | -## Usage |
48 | | - |
49 | | -### 1. Define your schema |
50 | | - |
51 | | -Use Zod, Valibot, ArkType, or any Standard Schema compatible library: |
52 | | - |
53 | | -<details> |
54 | | -<summary>With Valibot</summary> |
55 | | - |
56 | | -```typescript |
| 34 | +```ts [nuxt.config.ts] |
57 | 35 | import { number, object, optional, string } from 'valibot' |
58 | 36 |
|
59 | | -const runtimeConfigSchema = object({ |
60 | | - public: object({ |
61 | | - apiBase: string(), |
62 | | - appName: optional(string()), |
63 | | - }), |
| 37 | +const schema = object({ |
| 38 | + public: object({ apiBase: string() }), |
64 | 39 | databaseUrl: string(), |
65 | | - secretKey: string(), |
66 | 40 | port: optional(number()), |
67 | 41 | }) |
68 | | -``` |
69 | | - |
70 | | -</details> |
71 | | - |
72 | | -<details> |
73 | | -<summary>With Zod</summary> |
74 | | - |
75 | | -```typescript |
76 | | -import { z } from 'zod' |
77 | | - |
78 | | -const runtimeConfigSchema = z.object({ |
79 | | - public: z.object({ |
80 | | - apiBase: z.string(), |
81 | | - appName: z.string().optional(), |
82 | | - }), |
83 | | - databaseUrl: z.string(), |
84 | | - secretKey: z.string(), |
85 | | - port: z.number().optional(), |
86 | | -}) |
87 | | -``` |
88 | | - |
89 | | -</details> |
90 | 42 |
|
91 | | -<details> |
92 | | -<summary>With ArkType</summary> |
93 | | - |
94 | | -```typescript |
95 | | -import { type } from 'arktype' |
96 | | - |
97 | | -const runtimeConfigSchema = type({ |
98 | | - 'public': { |
99 | | - 'apiBase': 'string', |
100 | | - 'appName?': 'string' |
101 | | - }, |
102 | | - 'databaseUrl': 'string', |
103 | | - 'secretKey': 'string', |
104 | | - 'port?': 'number' |
105 | | -}) |
106 | | -``` |
107 | | - |
108 | | -</details> |
109 | | - |
110 | | -### 2. Configure in nuxt.config.ts |
111 | | - |
112 | | -```typescript |
113 | 43 | export default defineNuxtConfig({ |
114 | 44 | modules: ['nuxt-safe-runtime-config'], |
115 | | - |
116 | 45 | runtimeConfig: { |
117 | | - databaseUrl: process.env.DATABASE_URL || 'postgresql://localhost:5432/mydb', |
118 | | - secretKey: process.env.SECRET_KEY || 'default-secret-key', |
| 46 | + databaseUrl: process.env.DATABASE_URL || '', |
119 | 47 | port: Number.parseInt(process.env.PORT || '3000'), |
120 | | - public: { |
121 | | - apiBase: process.env.PUBLIC_API_BASE || 'https://api.example.com', |
122 | | - appName: 'My Nuxt App', |
123 | | - }, |
124 | | - }, |
125 | | - |
126 | | - safeRuntimeConfig: { |
127 | | - $schema: runtimeConfigSchema, |
| 48 | + public: { apiBase: 'https://api.example.com' }, |
128 | 49 | }, |
| 50 | + safeRuntimeConfig: { $schema: schema }, |
129 | 51 | }) |
130 | 52 | ``` |
131 | 53 |
|
132 | | -### 3. Use the type-safe composable |
133 | | - |
134 | | -Access your validated config with full type safety — types are auto-generated from your schema: |
135 | | - |
136 | 54 | ```vue |
137 | 55 | <script setup lang="ts"> |
138 | 56 | const config = useSafeRuntimeConfig() |
139 | | -// config.public.apiBase is typed as string |
140 | | -// config.secretKey is typed as string |
| 57 | +// config.public.apiBase - string (typed) |
141 | 58 | </script> |
142 | 59 | ``` |
143 | 60 |
|
144 | | -## Configuration Options |
145 | | - |
146 | | -| Option | Type | Default | Description | |
147 | | -| ------------------- | ------------------------------- | ----------------- | ------------------------------------------ | |
148 | | -| `$schema` | `StandardSchemaV1` | — | Your validation schema (required) | |
149 | | -| `validateAtBuild` | `boolean` | `true` | Validate during dev/build | |
150 | | -| `validateAtRuntime` | `boolean` | `false` | Validate when server starts | |
151 | | -| `onBuildError` | `'throw' \| 'warn' \| 'ignore'` | `'throw'` | How to handle build validation errors | |
152 | | -| `onRuntimeError` | `'throw' \| 'warn' \| 'ignore'` | `'throw'` | How to handle runtime validation errors | |
153 | | -| `logSuccess` | `boolean` | `true` | Log successful validation | |
154 | | -| `logFallback` | `boolean` | `true` | Log when using JSON Schema fallback | |
155 | | -| `jsonSchemaTarget` | `string` | `'draft-2020-12'` | JSON Schema version for runtime validation | |
156 | | - |
157 | | -## Runtime Validation |
158 | | - |
159 | | -By default, validation only runs at build time. Enable runtime validation to catch environment variable issues when the server starts: |
160 | | - |
161 | | -```ts |
162 | | -export default defineNuxtConfig({ |
163 | | - safeRuntimeConfig: { |
164 | | - $schema: runtimeConfigSchema, |
165 | | - validateAtRuntime: true, |
166 | | - }, |
167 | | -}) |
168 | | -``` |
169 | | - |
170 | | -Runtime validation uses [@cfworker/json-schema](https://github.com/cfworker/cfworker/tree/main/packages/json-schema) to validate the config after environment variables are merged. This lightweight validator (~8KB) works on all runtimes including edge (Cloudflare Workers, Vercel Edge, Netlify Edge). It catches issues like: |
171 | | - |
172 | | -- Environment variables with wrong types (e.g., `NUXT_PORT=abc` when expecting a number) |
173 | | -- Missing required environment variables in production |
174 | | -- Invalid values that pass build-time checks but fail at runtime |
175 | | - |
176 | | -## ESLint Integration |
| 61 | +## Documentation |
177 | 62 |
|
178 | | -The module includes an ESLint plugin that warns when using `useRuntimeConfig()` instead of `useSafeRuntimeConfig()`. |
| 63 | +Full documentation at **[nuxt-safe-runtime-config.vercel.app](https://nuxt-safe-runtime-config.vercel.app)** |
179 | 64 |
|
180 | | -### With @nuxt/eslint (Automatic) |
181 | | - |
182 | | -If you use [@nuxt/eslint](https://eslint.nuxt.com), the rule is auto-registered. No configuration needed. |
183 | | - |
184 | | -### Manual Setup |
185 | | - |
186 | | -Add to your `eslint.config.mjs`: |
187 | | - |
188 | | -```javascript |
189 | | -import { configs } from 'nuxt-safe-runtime-config/eslint' |
190 | | - |
191 | | -export default [ |
192 | | - configs.recommended, |
193 | | - // ... your other configs |
194 | | -] |
195 | | -``` |
196 | | - |
197 | | -Or configure manually: |
198 | | - |
199 | | -```javascript |
200 | | -import plugin from 'nuxt-safe-runtime-config/eslint' |
201 | | - |
202 | | -export default [ |
203 | | - { |
204 | | - plugins: { 'safe-runtime-config': plugin }, |
205 | | - rules: { 'safe-runtime-config/prefer-safe-runtime-config': 'warn' }, |
206 | | - }, |
207 | | -] |
208 | | -``` |
209 | | - |
210 | | -The rule includes auto-fix support — run `eslint --fix` to automatically replace `useRuntimeConfig()` calls. |
211 | | - |
212 | | -## Type Safety |
213 | | - |
214 | | -Types are auto-generated at build time from your schema's JSON Schema representation. The `useSafeRuntimeConfig()` composable returns a fully typed object — no manual generics needed: |
215 | | - |
216 | | -```ts |
217 | | -const config = useSafeRuntimeConfig() |
218 | | -// config is fully typed based on your schema |
219 | | -``` |
220 | | - |
221 | | -Generated types are stored in `.nuxt/types/safe-runtime-config.d.ts` and automatically included in your project. |
222 | | - |
223 | | -## Error Messages |
224 | | - |
225 | | -When validation fails, you see detailed error messages: |
226 | | - |
227 | | -``` |
228 | | -[safe-runtime-config] Validation failed! |
229 | | - 1. databaseUrl: Invalid type: Expected string but received undefined |
230 | | - 2. public.apiBase: Invalid type: Expected string but received undefined |
231 | | - 3. port: Invalid type: Expected number but received string |
232 | | -``` |
233 | | - |
234 | | -The module stops the build process until all validation errors are resolved. |
235 | | - |
236 | | -## Why This Module? |
237 | | - |
238 | | -Nuxt's built-in schema validation is designed for module authors and broader configuration. This module focuses specifically on **runtime config validation** using Standard Schema, allowing you to: |
239 | | - |
240 | | -- Use your preferred validation library (Valibot, Zod, ArkType) |
241 | | -- Catch configuration errors at build time |
242 | | -- Optionally validate at runtime for environment variable issues |
243 | | -- Get full type safety in your components |
244 | | - |
245 | | -## Contribution |
246 | | - |
247 | | -<details> |
248 | | - <summary>Local development</summary> |
249 | | - |
250 | | -```bash |
251 | | -# Install dependencies |
252 | | -pnpm install |
253 | | - |
254 | | -# Generate type stubs |
255 | | -pnpm run dev:prepare |
256 | | - |
257 | | -# Develop with the playground |
258 | | -pnpm run dev |
259 | | - |
260 | | -# Build the playground |
261 | | -pnpm run dev:build |
262 | | - |
263 | | -# Run ESLint |
264 | | -pnpm run lint |
265 | | - |
266 | | -# Run Vitest |
267 | | -pnpm run test |
268 | | -pnpm run test:watch |
269 | | - |
270 | | -# Release new version |
271 | | -pnpm run release |
272 | | -``` |
| 65 | +## License |
273 | 66 |
|
274 | | -</details> |
| 67 | +MIT |
0 commit comments