bini-env 1.1.0 → 1.1.1

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 CHANGED
@@ -3,43 +3,31 @@
3
3
  ![npm](https://img.shields.io/npm/v/bini-env?color=cyan&style=flat-square)
4
4
  ![npm downloads](https://img.shields.io/npm/dm/bini-env?style=flat-square)
5
5
  ![license](https://img.shields.io/npm/l/bini-env?style=flat-square)
6
- ![vite](https://img.shields.io/badge/vite-%3E%3D8.0-646CFF?style=flat-square&logo=vite)
7
- ![hono](https://img.shields.io/badge/hono-%3E%3D4.0-E36002?style=flat-square&logo=hono)
6
+ ![vite](https://img.shields.io/badge/vite-8.x-646CFF?style=flat-square&logo=vite)
7
+ ![hono](https://img.shields.io/badge/hono-4.x-E36002?style=flat-square&logo=hono)
8
8
  ![typescript](https://img.shields.io/badge/TypeScript-ready-3178C6?style=flat-square&logo=typescript)
9
9
  ![node](https://img.shields.io/badge/node-%3E%3D20.19-339933?style=flat-square&logo=node.js)
10
10
 
11
- **Zero-config environment variable system + Vite plugin for Bini.js**
12
- Powered by [Hono](https://hono.dev) — reads env vars from the request context so variables are always resolved from the correct runtime binding, whether you're on Node.js, Bun, Deno, Vercel Edge, Netlify Edge, or Cloudflare Workers.
11
+ **Zero-config environment variable system + Vite plugin for Bini.js**
13
12
 
14
- ---
15
-
16
- ## ⚠️ Before You Use This
17
-
18
- This library **does NOT magically make env vars safe**.
19
-
20
- - Anything exposed to the client (`import.meta.env`) is **public**.
21
- - Only server-side code (`getEnv`, `requireEnv`) can safely access secrets.
22
- - Misconfigured prefixes = **data leak**.
23
-
24
- If you don't understand this, stop and fix that first.
13
+ Powered by [Hono](https://hono.dev) — reads env vars from the Hono request context so variables are always resolved from the correct runtime binding, whether you're on Node.js, Bun, Deno, Vercel Edge, Netlify Edge, or Cloudflare Workers.
25
14
 
26
15
  ---
27
16
 
28
- ## ✨ Features
17
+ ## Features
29
18
 
30
- - **Hono-native API** — `getEnv(c, key)` / `requireEnv(c, key)` read from Hono's request context
31
- - **Universal runtime support** — CF Workers, Node, Bun, Deno, Vercel Edge, Netlify Edge
32
- - **Zero dotenv** — no `.env` file parsing at runtime; vars come from the host
33
- - **Build-time `process.env` fallback** — for Vite plugin hooks that run outside a request
34
- - **Auto server restart** — dev server restarts when `.env` files are created or changed
35
- - **Prefix control** — supports `BINI_`, `VITE_`, or custom
36
- - **Tree-shakeable** — no dead code in client bundles
37
- - **Typed** — full TypeScript support with exported `HonoContext` duck type
38
- - **Fast** — zero overhead; no file reads in production
19
+ - **Hono-native** — `getEnv(c, key)` / `requireEnv(c, key)` read directly from the Hono request context
20
+ - **Universal runtime** — CF Workers, Node, Bun, Deno, Vercel Edge, Netlify Edge — Hono's adapter handles all of it
21
+ - **Zero dotenv** — no `.env` parsing at runtime; vars come from the host platform
22
+ - **Vite-native dev** — `.env` loading, file watching, and server restarts are handled by Vite itself
23
+ - **Dev banner** — prints `ß Bini.js (dev/preview)` and lists detected `.env` files on server start
24
+ - **Prefix control** — `BINI_` and `VITE_` included out of the box, extend with your own
25
+ - **Tree-shakeable** — nothing lands in the client bundle that shouldn't
26
+ - **Typed** — full TypeScript support with an exported `HonoContext` type
39
27
 
40
28
  ---
41
29
 
42
- ## 📦 Installation
30
+ ## Installation
43
31
 
44
32
  ```bash
45
33
  pnpm add bini-env hono
@@ -53,7 +41,9 @@ yarn add bini-env hono
53
41
 
54
42
  ---
55
43
 
56
- ## 🚀 Quick Start
44
+ ## Quick Start
45
+
46
+ **1. Register the Vite plugin**
57
47
 
58
48
  ```ts
59
49
  // vite.config.ts
@@ -65,18 +55,34 @@ export default defineConfig({
65
55
  })
66
56
  ```
67
57
 
58
+ **2. Read env vars in your Hono handlers**
59
+
68
60
  ```ts
69
- // src/app/api/example.ts
61
+ // src/app/api/hello.ts
70
62
  import { Hono } from 'hono'
71
63
  import { getEnv, requireEnv } from 'bini-env'
72
64
 
73
65
  const app = new Hono()
74
66
 
75
- app.get('/hello', (c) => {
76
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
- const ctx = c as any
78
- const name = getEnv(ctx, 'APP_NAME') ?? 'World'
79
- return c.json({ message: `Hello, ${name}!` })
67
+ app.post('/hello', async (c) => {
68
+ try {
69
+ const ctx = c as any
70
+
71
+ // requireEnv throws if the var is missing — fail fast on required config
72
+ const apiKey = requireEnv(ctx, 'MY_API_KEY')
73
+
74
+ // getEnv returns undefined if missing — use ?? to provide a default
75
+ const appName = getEnv(ctx, 'APP_NAME') ?? 'World'
76
+ const timeout = parseInt(getEnv(ctx, 'TIMEOUT_MS') ?? '5000')
77
+
78
+ return c.json({ message: `Hello, ${appName}!` })
79
+
80
+ } catch (error: any) {
81
+ if (error.message?.includes('[bini-env] Missing required')) {
82
+ return c.json({ error: error.message }, 500)
83
+ }
84
+ return c.json({ error: 'Something went wrong.' }, 500)
85
+ }
80
86
  })
81
87
 
82
88
  export default app
@@ -84,155 +90,213 @@ export default app
84
90
 
85
91
  ---
86
92
 
87
- ## 🔐 Environment Rules (Read This Twice)
88
-
89
- > ✅ Both `BINI_` and `VITE_` prefixes work out of the box — no extra config needed.
93
+ ## Usage Pattern
90
94
 
91
- ### Client (PUBLIC)
95
+ **Always pass `c` explicitly.** Cast it once at the top of the handler, then use `ctx` throughout.
92
96
 
93
- ```env
94
- BINI_PUBLIC_API_URL=https://api.example.com
95
- VITE_ANALYTICS_ID=UA-XXXX
97
+ ```ts
98
+ app.post('/example', async (c) => {
99
+ try {
100
+ const ctx = c as any
101
+
102
+ // Required vars — handler throws immediately if missing
103
+ const dbUrl = requireEnv(ctx, 'DATABASE_URL')
104
+ const apiKey = requireEnv(ctx, 'STRIPE_SECRET_KEY')
105
+
106
+ // Optional vars — fall back to sensible defaults
107
+ const model = getEnv(ctx, 'AI_MODEL') ?? 'gpt-4o'
108
+ const region = getEnv(ctx, 'AWS_REGION') ?? 'us-east-1'
109
+ const maxRetries = parseInt(getEnv(ctx, 'MAX_RETRIES') ?? '3')
110
+ const debug = getEnv(ctx, 'DEBUG_MODE') === 'true'
111
+
112
+ // ... rest of handler
113
+
114
+ } catch (error: any) {
115
+ if (error.message?.includes('[bini-env] Missing required')) {
116
+ return c.json({ error: error.message }, 500)
117
+ }
118
+ return c.json({ error: 'Something went wrong.' }, 500)
119
+ }
120
+ })
96
121
  ```
97
122
 
123
+ **The pattern in three steps:**
124
+
125
+ 1. `const ctx = c as any` — once, at the top of the handler
126
+ 2. `requireEnv(ctx, 'KEY')` — for vars the handler cannot run without
127
+ 3. `getEnv(ctx, 'KEY') ?? 'default'` — for optional vars with sensible defaults
128
+
129
+ ---
130
+
131
+ ## Environment Prefixes
132
+
133
+ ### `BINI_` — server-side vars
134
+
135
+ `BINI_` is bini-env's own prefix. Variables are **not** exposed to `import.meta.env` by default, making it the right choice for server-side config and secrets.
136
+
137
+ To additionally expose a `BINI_` var to the client, add it to `envPrefix` explicitly:
138
+
98
139
  ```ts
99
- import.meta.env.BINI_PUBLIC_API_URL
140
+ biniEnv({ envPrefix: ['BINI_', 'VITE_', 'MY_PUBLIC_'] })
100
141
  ```
101
142
 
102
- 👉 **Never put secrets here. Ever.**
143
+ ### `VITE_` — public client vars
103
144
 
104
- ### Server (PRIVATE)
145
+ `VITE_` is Vite's built-in prefix. Any var starting with `VITE_` is bundled into your client-side JavaScript and is publicly visible.
105
146
 
106
147
  ```env
107
- SMTP_PASS=super_secret
108
- DATABASE_URL=postgres://...
148
+ VITE_ANALYTICS_ID=UA-XXXX # bundled into client JS — public
149
+ VITE_API_URL=https://api.example.com # bundled into client JS — public
109
150
  ```
110
151
 
111
152
  ```ts
112
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
- const ctx = c as any
114
- const pass = requireEnv(ctx, 'SMTP_PASS') // throws if missing
115
- const db = getEnv(ctx, 'DATABASE_URL') // returns undefined if missing
153
+ // accessible anywhere, including the browser
154
+ import.meta.env.VITE_ANALYTICS_ID
116
155
  ```
117
156
 
118
- 👉 If this leaks, it's your fault, not the library's.
157
+ ### Choosing the right prefix
119
158
 
120
- ---
159
+ ```env
160
+ # ✓ use VITE_ for anything the browser needs
161
+ VITE_API_URL=https://api.example.com
121
162
 
122
- ## 🌍 Platform Support
163
+ # ✓ use BINI_ for server-side config
164
+ BINI_FEATURE_FLAG=true
123
165
 
124
- `getEnv` and `requireEnv` resolve vars from Hono's `env(c)` adapter, which maps to the correct source on every supported platform automatically.
166
+ # ✓ no prefix for secrets — read via getEnv(ctx, key) only
167
+ DATABASE_URL=postgres://...
168
+ STRIPE_SECRET_KEY=sk_live_...
169
+ ```
170
+
171
+ > Avoid defining the same variable under two different prefixes — your code will silently read whichever one it finds first.
125
172
 
126
- | Platform | Runtime | Where vars come from | How `env(c)` reads them |
127
- | -------------------- | ------------- | ----------------------------------- | ---------------------------- |
128
- | Node.js | Node | System env / platform dashboard | `process.env` ✅ |
129
- | Bun | Bun | System env / platform dashboard | `process.env` ✅ |
130
- | Vercel Edge | V8 isolate | Project settings → Environment Vars | `process.env` ✅ |
131
- | Netlify Edge | Deno | Site settings → Environment Vars | `Deno.env.get()` ✅ |
132
- | Cloudflare Workers | V8 isolate | `wrangler.toml [vars]` / dashboard | CF bindings via `c.env` ✅ |
133
- | Deno Deploy | Deno | Project settings → Environment Vars | `Deno.env.get()` ✅ |
173
+ ### Prefix summary
134
174
 
135
- > **Cloudflare note:** Secrets added via `wrangler secret put` are only available inside the fetch handler via `c.env` — this is a Cloudflare Workers architecture constraint, not a bini-env limitation. `getEnv` reads them correctly when called with `c` inside a route handler.
175
+ | Prefix | Exposed to browser | Use for |
176
+ |--------|--------------------|---------|
177
+ | `BINI_` | No (unless added to `envPrefix`) | Server-side config |
178
+ | `VITE_` | Yes, always | Public client config |
179
+ | No prefix | No | Secrets — server only |
136
180
 
137
181
  ---
138
182
 
139
- ## 🧠 How It Actually Works
183
+ ## Platform Support
140
184
 
141
- `getEnv(c, key)` resolves in this order:
185
+ `getEnv` and `requireEnv` delegate to Hono's `env(c)` adapter, which reads from the correct source on every supported platform automatically. Your code never changes regardless of where it deploys.
142
186
 
143
- 1. **`env(c)` from `hono/adapter`** — the Hono request context. This is the primary and correct source on every runtime. Never cached — request-scoped.
144
- 2. **Stored context** — if you called `setContext(c)` in a global middleware, `getEnv('KEY')` (no `c`) uses it.
145
- 3. **`process.env`** — build-time only, for Vite plugin hooks that run outside any request.
187
+ | Platform | Runtime | Env source | How Hono reads it |
188
+ |----------|---------|------------|-------------------|
189
+ | Node.js | Node | System env / platform dashboard | `process.env` ✅ |
190
+ | Bun | Bun | System env / platform dashboard | `process.env` ✅ |
191
+ | Vercel Edge | V8 isolate | Project settings → Env Vars | `process.env` ✅ |
192
+ | Netlify Edge | Deno | Site settings → Env Vars | `Deno.env.get()` ✅ |
193
+ | Cloudflare Workers | V8 isolate | `wrangler.toml` / dashboard | CF bindings via `c.env` ✅ |
194
+ | Deno Deploy | Deno | Project settings → Env Vars | `Deno.env.get()` ✅ |
146
195
 
147
- `dotenv` is not used anywhere. Variables must be set in your platform's environment config.
196
+ > **Cloudflare note:** Secrets set via `wrangler secret put` are only available inside the fetch handler via `c.env` — this is a Workers architecture constraint. `getEnv(ctx, key)` reads them correctly as long as you pass `c`.
148
197
 
149
198
  ---
150
199
 
151
- ## 🔄 Auto Server Restart
200
+ ## How It Works
152
201
 
153
- The dev server automatically restarts when any `.env*` file is created or changed in your project root.
202
+ ### The plugin — `biniEnv()`
154
203
 
155
- ```
156
- 12:00:01 [bini-env] .env.local changed — restarting server
204
+ Does two things: tells Vite which env prefixes to expose to `import.meta.env`, and prints the `ß Bini.js` banner with detected `.env` files when the dev or preview server starts.
205
+
206
+ ```ts
207
+ // what biniEnv() does internally
208
+ config() {
209
+ return { envPrefix: ['BINI_', 'VITE_', ...yourExtras] }
210
+ }
157
211
  ```
158
212
 
159
- Covered events:
160
- - Creating a new `.env`, `.env.local`, `.env.production`, etc.
161
- - Editing any existing `.env*` file
213
+ On server start you will see:
162
214
 
163
- Editor swap files (`.env.swp`, `.env~`, `.env.bak`) are ignored.
215
+ ```
216
+ ß Bini.js (dev)
217
+ ➜ Environments: .env.local, .env
218
+ ➜ Local: http://localhost:3000/
219
+ ➜ Network: http://192.168.1.7:3000/
220
+ ```
164
221
 
165
- ---
222
+ Vite handles everything else natively: loading `.env`, `.env.local`, `.env.[mode]` files during dev, watching and restarting on change, injecting prefixed vars into `import.meta.env` at build time, and HMR when env files change. bini-env does not reimplement any of that.
166
223
 
167
- ## ⚙️ Plugin Options
224
+ ### The env functions — `getEnv` / `requireEnv`
168
225
 
169
- ```ts
170
- biniEnv({
171
- enabled : true,
172
- clearViteHeader: true,
173
- logo : 'ß',
174
- envPrefix : ['BINI_', 'VITE_'],
175
- loadInPreview : true,
176
- })
177
- ```
226
+ Both functions read exclusively from `env(c)` via `hono/adapter` — the Hono request context. There are no `process.env` fallbacks. Every read is request-scoped and resolved by Hono's adapter for the current platform.
178
227
 
179
- > **Critical:** If you change `envPrefix`, you are changing what gets exposed to the browser. Break this → you leak secrets.
228
+ `dotenv` is never used. In production, vars are set in your hosting platform's environment config.
180
229
 
181
230
  ---
182
231
 
183
- ## 📚 API
232
+ ## API Reference
184
233
 
185
234
  ### `getEnv(c, key)`
186
235
 
187
- Returns `string | undefined`. Reads from Hono's request context.
236
+ Returns `string | undefined`. Reads from the Hono request context.
188
237
 
189
238
  ```ts
190
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
191
- const ctx = c as any
192
- const debug = getEnv(ctx, 'DEBUG_MODE')
193
- ```
239
+ app.get('/config', async (c) => {
240
+ const ctx = c as any
194
241
 
195
- Also works without `c` outside a request (build-time / Vite hooks):
242
+ const region = getEnv(ctx, 'AWS_REGION') ?? 'us-east-1'
243
+ const logLevel = getEnv(ctx, 'LOG_LEVEL') ?? 'info'
244
+ const debug = getEnv(ctx, 'DEBUG_MODE') === 'true'
196
245
 
197
- ```ts
198
- const debug = getEnv('DEBUG_MODE')
246
+ return c.json({ region, logLevel, debug })
247
+ })
199
248
  ```
200
249
 
201
250
  ### `requireEnv(c, key)`
202
251
 
203
- Same as `getEnv` but throws if the variable is missing:
252
+ Returns `string`. Throws immediately if the variable is missing or empty. Logs a descriptive error to the terminal on failure.
204
253
 
205
- ```
206
- [bini-env] Missing required environment variable: "SMTP_PASS"
207
- → In development: set it in your platform's env config.
208
- → In production: set it in your hosting dashboard.
254
+ ```ts
255
+ app.post('/send-email', async (c) => {
256
+ try {
257
+ const ctx = c as any
258
+
259
+ const smtpHost = requireEnv(ctx, 'SMTP_HOST')
260
+ const smtpPass = requireEnv(ctx, 'SMTP_PASS')
261
+ const smtpPort = parseInt(getEnv(ctx, 'SMTP_PORT') ?? '587')
262
+
263
+ // ... send email
264
+
265
+ return c.json({ sent: true })
266
+
267
+ } catch (error: any) {
268
+ if (error.message?.includes('[bini-env] Missing required')) {
269
+ return c.json({ error: error.message }, 500)
270
+ }
271
+ return c.json({ error: 'Failed to send email.' }, 500)
272
+ }
273
+ })
209
274
  ```
210
275
 
211
- ```ts
212
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
213
- const ctx = c as any
214
- const dbUrl = requireEnv(ctx, 'DATABASE_URL')
276
+ On failure, the terminal will show:
277
+
278
+ ```
279
+ [bini-env] error Missing required environment variable: "SMTP_HOST"
280
+ -> Set it in your platform's env config or hosting dashboard.
215
281
  ```
216
282
 
217
- ### `setContext(c)` / `clearContext()`
283
+ ### `biniEnv(options?)`
218
284
 
219
- Store a Hono context module-level so `getEnv('KEY')` works without passing `c` at every call site. Register once in a global middleware:
285
+ Vite plugin. Registers `BINI_` and `VITE_` as env prefixes and optionally adds more.
220
286
 
221
287
  ```ts
222
- app.use('*', (c, next) => {
223
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
224
- setContext(c as any)
225
- return next()
226
- })
288
+ biniEnv()
289
+ // or with extra prefixes
290
+ biniEnv({ envPrefix: ['MY_PUBLIC_'] })
227
291
  ```
228
292
 
229
- ### `biniEnv(options)`
230
-
231
- Vite plugin. Handles terminal output and dev server watching.
293
+ | Option | Type | Default | Description |
294
+ |--------|------|---------|-------------|
295
+ | `envPrefix` | `string \| string[]` | `[]` | Extra prefixes to expose to `import.meta.env`, in addition to `BINI_` and `VITE_` |
232
296
 
233
297
  ### `biniLogger`
234
298
 
235
- Standalone logger that uses Vite-style terminal output. Available for use in your own Bini.js plugins.
299
+ Vite-style terminal logger. Use it in your own Bini.js plugins or server-side code.
236
300
 
237
301
  ```ts
238
302
  import { biniLogger } from 'bini-env'
@@ -244,102 +308,84 @@ biniLogger.error('Something broke', error)
244
308
 
245
309
  ### `HonoContext`
246
310
 
247
- Exported duck type satisfied by any Hono `Context`. Use it if you need to type a wrapper:
311
+ Exported type (`Context` from Hono). Use it to type helper functions that group env reads, so you only cast `c as any` once per entry point.
248
312
 
249
313
  ```ts
250
314
  import type { HonoContext } from 'bini-env'
251
315
 
252
- function readConfig(c: HonoContext) {
253
- return getEnv(c, 'CONFIG_KEY')
316
+ function readDbConfig(c: HonoContext) {
317
+ const ctx = c as any
318
+ return {
319
+ url: requireEnv(ctx, 'DATABASE_URL'),
320
+ poolSize: parseInt(getEnv(ctx, 'DB_POOL_SIZE') ?? '10'),
321
+ ssl: getEnv(ctx, 'DB_SSL') !== 'false',
322
+ }
254
323
  }
255
324
  ```
256
325
 
257
326
  ---
258
327
 
259
- ## 📂 Env File Resolution Order (Dev only)
328
+ ## Performance
260
329
 
261
- The Vite plugin watches these files and triggers a server restart on change:
330
+ | Metric | Dev | Prod |
331
+ |--------|-----|------|
332
+ | File reads | 0 | 0 |
333
+ | Runtime cost | ~0ms | 0 |
334
+ | Bundle impact | Minimal | Tree-shaken |
262
335
 
263
- 1. `.env.local`
264
- 2. `.env.[mode].local`
265
- 3. `.env.[mode]`
266
- 4. `.env`
267
-
268
- In production, none of these are read. Variables must come from your platform.
336
+ No dotenv. No disk reads. No caching layer. `getEnv` is a direct call to Hono's adapter on every invocation — request-scoped and correct.
269
337
 
270
338
  ---
271
339
 
272
- ## ⚡ Performance
340
+ ## Troubleshooting
273
341
 
274
- | Metric | Dev | Prod |
275
- | ------------- | -------- | ----------- |
276
- | File Reads | 0 | 0 |
277
- | Runtime Cost | ~0ms | 0 |
278
- | Bundle Impact | Minimal | Tree-shaken |
342
+ ### "Env var is undefined in production"
279
343
 
280
- No dotenv. No disk reads. No overhead.
344
+ Vars set in `.env` files are only loaded by Vite during local development. In production, set your variables in your hosting platform's environment dashboard (Vercel, Netlify, Cloudflare, etc.).
281
345
 
282
- ---
346
+ ### "Works in dev, undefined in prod"
283
347
 
284
- ## 🔥 Common Failure Modes
285
-
286
- ### "Env is undefined in production"
287
- You relied on a `.env` file in production. Set vars in your hosting dashboard — bini-env does not read `.env` files at runtime.
288
-
289
- ### "Works in dev, broken in prod"
290
- Same as above. Production vars come from the host, not from files.
291
-
292
- ### "Secrets leaked"
293
- You exposed them via `BINI_` or `VITE_` prefix. Those are public. Use unprefixed vars for secrets and only read them server-side via `getEnv(c, key)`.
348
+ Same as above. Local dev works because Vite loads `.env` files automatically. Production requires platform-level configuration.
294
349
 
295
350
  ### "Cloudflare secret not found"
296
- Secrets added via `wrangler secret put` are only available via `c.env` inside your handler — which is exactly where `getEnv(c, key)` reads from. Make sure you're passing `c`.
351
+
352
+ Secrets set via `wrangler secret put` are only available via `c.env` inside a handler — which is exactly what `getEnv(ctx, key)` reads. Ensure you are passing `c` to the function.
297
353
 
298
354
  ### "TypeScript error: Context not assignable to HonoContext"
299
- Hono 4.12 added a `[GET_MATCH_RESULT]` symbol to `HonoRequest` that breaks structural assignability. Cast once per handler:
355
+
356
+ Hono 4.12+ added a symbol to `HonoRequest` that can break structural assignability in strict TypeScript projects. Cast once per handler:
300
357
 
301
358
  ```ts
302
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
303
359
  const ctx = c as any
304
- const key = requireEnv(ctx, 'MY_KEY')
305
360
  ```
306
361
 
307
362
  ### "Types not found"
308
- Add to your `tsconfig` or entry file:
363
+
364
+ Add to your `tsconfig.json` or entry file:
365
+
309
366
  ```ts
310
367
  /// <reference types="vite/client" />
311
368
  ```
312
369
 
313
370
  ---
314
371
 
315
- ## 🧪 Reality Check
316
-
317
- This library is intentionally simple.
318
-
319
- If you need:
320
- - Secret rotation
321
- - Encrypted envs
322
- - Runtime validation schemas
372
+ ## Compatibility
323
373
 
324
- That's **your job**, not this package.
374
+ | Tool | Version | Notes |
375
+ |------|---------|-------|
376
+ | Vite | 8.x | `envPrefix` hook is fully compatible; empty prefix array is never passed |
377
+ | Hono | 4.x | `hono/adapter` `env()` is stable across all 4.x releases |
378
+ | TypeScript | 5.x | Full type support via exported `HonoContext` |
379
+ | Node.js | ≥ 20.19 | Minimum required version |
325
380
 
326
381
  ---
327
382
 
328
- ## 🤝 Contributing
383
+ ## Contributing
329
384
 
330
- PRs welcome — but:
331
- - No bloat
332
- - No magic
333
- - No runtime cost
334
-
335
- If it slows startup or increases bundle size, it's getting rejected.
385
+ PRs are welcome. The goal of this library is to stay minimal and runtime-cost-free. Contributions that add unnecessary complexity, increase bundle size, or introduce startup overhead will not be accepted.
336
386
 
337
387
  ---
338
388
 
339
- ## 📄 License
340
-
341
- MIT © Bini.js Team
342
-
343
- ---
389
+ ## License
344
390
 
345
- **Ship fast. Leak nothing. Blame config, not tooling.**
391
+ MIT © Bini.js Team
package/dist/index.d.mts CHANGED
@@ -1,32 +1,34 @@
1
+ import { Context } from 'hono';
1
2
  import { Plugin } from 'vite';
2
3
  export { Plugin } from 'vite';
3
- export { Context } from 'hono';
4
4
 
5
- /** Minimal shape accepted by getEnv / requireEnv. Satisfied by any Hono Context. */
6
- type HonoContext = {
7
- env: unknown;
8
- } & Record<string, unknown>;
5
+ /**
6
+ * bini-env/src/index.ts
7
+ *
8
+ * Two responsibilities only:
9
+ * 1. Tell Vite which env prefixes to expose to import.meta.env (biniEnv plugin)
10
+ * 2. Read env vars from the Hono request context (getEnv / requireEnv)
11
+ *
12
+ * process.env is never used. All runtime env access goes through Hono's env() adapter,
13
+ * which handles Node, Bun, Cloudflare Workers, Deno, and Vercel Edge natively.
14
+ */
15
+
16
+ /**
17
+ * Accepts any Hono Context. Typed against Hono's own Context rather than a
18
+ * loose duck type so misuse is caught at the call site.
19
+ */
20
+ type HonoContext = Context;
9
21
  interface BiniEnvPluginOptions {
10
- readonly enabled?: boolean;
11
- readonly clearViteHeader?: boolean;
12
- readonly logo?: string;
22
+ /** Extra prefixes to expose to import.meta.env, in addition to BINI_ and VITE_. */
13
23
  readonly envPrefix?: string | string[];
14
- readonly loadInPreview?: boolean;
15
- }
16
- interface DetectedEnvFile {
17
- readonly name: string;
18
- readonly path: string;
19
24
  }
20
25
  declare const biniLogger: {
21
26
  readonly info: (msg: string) => void;
22
27
  readonly warn: (msg: string) => void;
23
28
  readonly error: (msg: string, err?: unknown) => void;
24
29
  };
25
- declare function setContext(c: HonoContext): void;
26
- declare function clearContext(): void;
27
- declare function getEnv(c: HonoContext | string, key?: string): string | undefined;
28
- declare function requireEnv(c: HonoContext | string, key?: string): string;
29
- declare function detectEnvFiles(projectRoot?: string): DetectedEnvFile[];
30
+ declare function getEnv(c: HonoContext, key: string): string | undefined;
31
+ declare function requireEnv(c: HonoContext, key: string): string;
30
32
  declare function biniEnv(options?: Readonly<BiniEnvPluginOptions>): Plugin;
31
33
 
32
- export { type BiniEnvPluginOptions, type DetectedEnvFile, type HonoContext, biniEnv, biniLogger, clearContext, detectEnvFiles, getEnv, requireEnv, setContext };
34
+ export { type BiniEnvPluginOptions, type HonoContext, biniEnv, biniLogger, getEnv, requireEnv };
package/dist/index.d.ts CHANGED
@@ -1,32 +1,34 @@
1
+ import { Context } from 'hono';
1
2
  import { Plugin } from 'vite';
2
3
  export { Plugin } from 'vite';
3
- export { Context } from 'hono';
4
4
 
5
- /** Minimal shape accepted by getEnv / requireEnv. Satisfied by any Hono Context. */
6
- type HonoContext = {
7
- env: unknown;
8
- } & Record<string, unknown>;
5
+ /**
6
+ * bini-env/src/index.ts
7
+ *
8
+ * Two responsibilities only:
9
+ * 1. Tell Vite which env prefixes to expose to import.meta.env (biniEnv plugin)
10
+ * 2. Read env vars from the Hono request context (getEnv / requireEnv)
11
+ *
12
+ * process.env is never used. All runtime env access goes through Hono's env() adapter,
13
+ * which handles Node, Bun, Cloudflare Workers, Deno, and Vercel Edge natively.
14
+ */
15
+
16
+ /**
17
+ * Accepts any Hono Context. Typed against Hono's own Context rather than a
18
+ * loose duck type so misuse is caught at the call site.
19
+ */
20
+ type HonoContext = Context;
9
21
  interface BiniEnvPluginOptions {
10
- readonly enabled?: boolean;
11
- readonly clearViteHeader?: boolean;
12
- readonly logo?: string;
22
+ /** Extra prefixes to expose to import.meta.env, in addition to BINI_ and VITE_. */
13
23
  readonly envPrefix?: string | string[];
14
- readonly loadInPreview?: boolean;
15
- }
16
- interface DetectedEnvFile {
17
- readonly name: string;
18
- readonly path: string;
19
24
  }
20
25
  declare const biniLogger: {
21
26
  readonly info: (msg: string) => void;
22
27
  readonly warn: (msg: string) => void;
23
28
  readonly error: (msg: string, err?: unknown) => void;
24
29
  };
25
- declare function setContext(c: HonoContext): void;
26
- declare function clearContext(): void;
27
- declare function getEnv(c: HonoContext | string, key?: string): string | undefined;
28
- declare function requireEnv(c: HonoContext | string, key?: string): string;
29
- declare function detectEnvFiles(projectRoot?: string): DetectedEnvFile[];
30
+ declare function getEnv(c: HonoContext, key: string): string | undefined;
31
+ declare function requireEnv(c: HonoContext, key: string): string;
30
32
  declare function biniEnv(options?: Readonly<BiniEnvPluginOptions>): Plugin;
31
33
 
32
- export { type BiniEnvPluginOptions, type DetectedEnvFile, type HonoContext, biniEnv, biniLogger, clearContext, detectEnvFiles, getEnv, requireEnv, setContext };
34
+ export { type BiniEnvPluginOptions, type HonoContext, biniEnv, biniLogger, getEnv, requireEnv };