bini-env 1.0.10 → 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,281 +3,389 @@
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)
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)
7
8
  ![typescript](https://img.shields.io/badge/TypeScript-ready-3178C6?style=flat-square&logo=typescript)
8
9
  ![node](https://img.shields.io/badge/node-%3E%3D20.19-339933?style=flat-square&logo=node.js)
9
10
 
10
- **Zero-config environment variable system + Vite plugin for Bini.js**
11
- Loads `.env` in development, uses host-provided variables in production, and works across Node.js, Bun, Deno, Vercel Edge, Netlify Edge, and Cloudflare Workers — without leaking secrets or adding runtime cost.
11
+ **Zero-config environment variable system + Vite plugin for Bini.js**
12
12
 
13
- ---
14
-
15
- ## ⚠️ Before You Use This
16
-
17
- This library **does NOT magically make env vars safe**.
18
-
19
- - Anything exposed to the client (`import.meta.env`) is **public**.
20
- - Only server-side code (`getEnv`, `requireEnv`) can safely access secrets.
21
- - Misconfigured prefixes = **data leak**.
22
-
23
- 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.
24
14
 
25
15
  ---
26
16
 
27
- ## ✨ Features
17
+ ## Features
28
18
 
29
- - **Universal API** — `getEnv()` / `requireEnv()` work across all runtimes
30
- - **Zero-config `.env` loading** in development
31
- - **Edge-safe** — no static `fs`, `path`, or `dotenv` imports in bundles
32
- - **Auto server restart** — dev server restarts when `.env` files are created or changed
33
- - **Strict production behavior** — no file reads, no dotenv
34
- - **Prefix control** — supports `BINI_`, `VITE_`, or custom
35
- - **Tree-shakeable** — no dead code in client bundles
36
- - **Typed** — full TypeScript support
37
- - **Fast** — single load in dev, zero overhead in prod
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
38
27
 
39
28
  ---
40
29
 
41
- ## 📦 Installation
30
+ ## Installation
42
31
 
43
32
  ```bash
44
- pnpm add bini-env
33
+ pnpm add bini-env hono
45
34
  # or
46
- npm install bini-env
35
+ npm install bini-env hono
47
36
  # or
48
- yarn add bini-env
37
+ yarn add bini-env hono
49
38
  ```
50
39
 
40
+ > `hono` is a required peer dependency.
41
+
51
42
  ---
52
43
 
53
- ## 🚀 Quick Start
44
+ ## Quick Start
45
+
46
+ **1. Register the Vite plugin**
54
47
 
55
48
  ```ts
56
49
  // vite.config.ts
57
- import { defineConfig } from 'vite';
58
- import { biniEnv } from 'bini-env';
50
+ import { defineConfig } from 'vite'
51
+ import { biniEnv } from 'bini-env'
59
52
 
60
53
  export default defineConfig({
61
54
  plugins: [biniEnv()]
62
- });
55
+ })
63
56
  ```
64
57
 
65
- Done. If this doesn't work, your project setup is broken — not the plugin.
58
+ **2. Read env vars in your Hono handlers**
66
59
 
67
- ---
60
+ ```ts
61
+ // src/app/api/hello.ts
62
+ import { Hono } from 'hono'
63
+ import { getEnv, requireEnv } from 'bini-env'
68
64
 
69
- ## 🔐 Environment Rules (Read This Twice)
65
+ const app = new Hono()
70
66
 
71
- > ✅ Both `BINI_` and `VITE_` prefixes work out of the box — no extra config needed.
67
+ app.post('/hello', async (c) => {
68
+ try {
69
+ const ctx = c as any
72
70
 
73
- ### Client (PUBLIC)
71
+ // requireEnv throws if the var is missing — fail fast on required config
72
+ const apiKey = requireEnv(ctx, 'MY_API_KEY')
74
73
 
75
- ```env
76
- BINI_PUBLIC_API_URL=https://api.example.com
77
- VITE_ANALYTICS_ID=UA-XXXX
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
+ }
86
+ })
87
+
88
+ export default app
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Usage Pattern
94
+
95
+ **Always pass `c` explicitly.** Cast it once at the top of the handler, then use `ctx` throughout.
96
+
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
+ })
78
121
  ```
79
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
+
80
139
  ```ts
81
- import.meta.env.BINI_PUBLIC_API_URL
140
+ biniEnv({ envPrefix: ['BINI_', 'VITE_', 'MY_PUBLIC_'] })
82
141
  ```
83
142
 
84
- 👉 **Never put secrets here. Ever.**
143
+ ### `VITE_` — public client vars
85
144
 
86
- ### 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.
87
146
 
88
147
  ```env
89
- SMTP_PASS=super_secret
90
- 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
91
150
  ```
92
151
 
93
152
  ```ts
94
- // getEnv and requireEnv are auto-imported in API routes
95
- const pass = requireEnv('SMTP_PASS'); // throws if missing
96
- const db = getEnv('DATABASE_URL'); // returns undefined if missing
153
+ // accessible anywhere, including the browser
154
+ import.meta.env.VITE_ANALYTICS_ID
97
155
  ```
98
156
 
99
- 👉 If this leaks, it's your fault, not the library's.
157
+ ### Choosing the right prefix
100
158
 
101
- ---
159
+ ```env
160
+ # ✓ use VITE_ for anything the browser needs
161
+ VITE_API_URL=https://api.example.com
102
162
 
103
- ## 🌍 Platform Support
163
+ # ✓ use BINI_ for server-side config
164
+ BINI_FEATURE_FLAG=true
104
165
 
105
- `getEnv` and `requireEnv` work identically across every supported platform. Write your API routes once — they run everywhere unchanged.
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.
106
172
 
107
- | Platform | Runtime | Where vars come from | How `getEnv` reads them |
108
- | ------------------ | ------------- | ------------------------------------- | ----------------------- |
109
- | Node.js | Node | `.env` file / system env | `process.env` ✅ |
110
- | Bun | Bun | `.env` file / system env | `process.env` ✅ |
111
- | Vercel Edge | V8 isolate | Project settings → Environment Vars | `process.env` ✅ |
112
- | Netlify Edge | Deno | Site settings → Environment Vars | `Deno.env.get()` ✅ |
113
- | Cloudflare Workers | V8 isolate | `wrangler.toml [vars]` / dashboard | `process.env` ✅ |
114
- | Deno Deploy | Deno | Project settings → Environment Vars | `Deno.env.get()` ✅ |
173
+ ### Prefix summary
115
174
 
116
- > **Cloudflare note:** Variables set in `wrangler.toml [vars]` or the dashboard work with `getEnv` at the top level. 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.
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 |
117
180
 
118
181
  ---
119
182
 
120
- ## 🧠 How It Actually Works
183
+ ## Platform Support
121
184
 
122
- | Mode | Behavior |
123
- | ---------------- | ------------------------------------------------- |
124
- | Dev (`vite dev`) | Loads `.env` once via dynamic dotenv |
125
- | Preview | Same as dev |
126
- | Production | Uses `process.env` / host injection only |
127
- | Deno / Netlify Edge | Uses native `Deno.env` |
128
- | Vercel / Cloudflare Edge | Uses `process.env` injected by the host |
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.
129
186
 
130
- `fs`, `path`, and `dotenv` are **never imported at the top level**. They are dynamically imported at runtime, inside Node-only guards, so edge bundlers never trace them into your bundle.
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()` ✅ |
195
+
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`.
131
197
 
132
198
  ---
133
199
 
134
- ## 🔄 Auto Server Restart
200
+ ## How It Works
201
+
202
+ ### The plugin — `biniEnv()`
135
203
 
136
- The dev server automatically restarts when any `.env*` file is created or changed in your project root — no manual restart needed.
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.
137
205
 
206
+ ```ts
207
+ // what biniEnv() does internally
208
+ config() {
209
+ return { envPrefix: ['BINI_', 'VITE_', ...yourExtras] }
210
+ }
138
211
  ```
139
- 12:00:01 [bini-env] .env.local changed — restarting server
212
+
213
+ On server start you will see:
214
+
140
215
  ```
216
+ ß Bini.js (dev)
217
+ ➜ Environments: .env.local, .env
218
+ ➜ Local: http://localhost:3000/
219
+ ➜ Network: http://192.168.1.7:3000/
220
+ ```
221
+
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.
141
223
 
142
- Covered events:
143
- - Creating a new `.env`, `.env.local`, `.env.production`, etc.
144
- - Editing any existing `.env*` file
224
+ ### The env functions — `getEnv` / `requireEnv`
145
225
 
146
- Editor swap files (`.env.swp`, `.env~`, `.env.bak`) are ignored.
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.
227
+
228
+ `dotenv` is never used. In production, vars are set in your hosting platform's environment config.
147
229
 
148
230
  ---
149
231
 
150
- ## ⚙️ Plugin Options
232
+ ## API Reference
233
+
234
+ ### `getEnv(c, key)`
235
+
236
+ Returns `string | undefined`. Reads from the Hono request context.
151
237
 
152
238
  ```ts
153
- biniEnv({
154
- enabled : true,
155
- clearViteHeader: true,
156
- logo : 'ß',
157
- envPrefix : ['BINI_', 'VITE_'],
158
- loadInPreview : true,
159
- });
239
+ app.get('/config', async (c) => {
240
+ const ctx = c as any
241
+
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'
245
+
246
+ return c.json({ region, logLevel, debug })
247
+ })
160
248
  ```
161
249
 
162
- > **Critical:** If you change `envPrefix`, you are changing what gets exposed to the browser. Break this → you leak secrets.
250
+ ### `requireEnv(c, key)`
163
251
 
164
- ---
252
+ Returns `string`. Throws immediately if the variable is missing or empty. Logs a descriptive error to the terminal on failure.
165
253
 
166
- ## 📚 API
254
+ ```ts
255
+ app.post('/send-email', async (c) => {
256
+ try {
257
+ const ctx = c as any
167
258
 
168
- ### `getEnv(key)`
259
+ const smtpHost = requireEnv(ctx, 'SMTP_HOST')
260
+ const smtpPass = requireEnv(ctx, 'SMTP_PASS')
261
+ const smtpPort = parseInt(getEnv(ctx, 'SMTP_PORT') ?? '587')
169
262
 
170
- Returns `string | undefined`. Auto-imported in API routes.
263
+ // ... send email
171
264
 
172
- Lookup order:
173
- 1. `Deno.env.get(key)` — Deno / Netlify Edge
174
- 2. `process.env[key]` — Node, Bun, Vercel Edge, Cloudflare Workers
175
- 3. `import.meta.env[key]` — Vite client (prefixed variants only)
265
+ return c.json({ sent: true })
176
266
 
177
- ```ts
178
- const debug = getEnv('DEBUG_MODE');
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
+ })
179
274
  ```
180
275
 
181
- ### `requireEnv(key)`
182
-
183
- Same as `getEnv` but throws if missing:
276
+ On failure, the terminal will show:
184
277
 
185
278
  ```
186
- [bini-env] Missing required environment variable: "SMTP_PASS"
187
- → In development: add it to your .env file.
188
- → In production: set it in your hosting dashboard.
279
+ [bini-env] error Missing required environment variable: "SMTP_HOST"
280
+ -> Set it in your platform's env config or hosting dashboard.
189
281
  ```
190
282
 
191
- Use this for anything critical that must exist at startup.
283
+ ### `biniEnv(options?)`
284
+
285
+ Vite plugin. Registers `BINI_` and `VITE_` as env prefixes and optionally adds more.
192
286
 
193
287
  ```ts
194
- const dbUrl = requireEnv('DATABASE_URL');
288
+ biniEnv()
289
+ // or with extra prefixes
290
+ biniEnv({ envPrefix: ['MY_PUBLIC_'] })
195
291
  ```
196
292
 
197
- ### `biniEnv(options)`
293
+ | Option | Type | Default | Description |
294
+ |--------|------|---------|-------------|
295
+ | `envPrefix` | `string \| string[]` | `[]` | Extra prefixes to expose to `import.meta.env`, in addition to `BINI_` and `VITE_` |
198
296
 
199
- Vite plugin. Handles `.env` loading, terminal output, and dev server watching.
297
+ ### `biniLogger`
200
298
 
201
- ---
299
+ Vite-style terminal logger. Use it in your own Bini.js plugins or server-side code.
202
300
 
203
- ## 📂 Env File Resolution Order
301
+ ```ts
302
+ import { biniLogger } from 'bini-env'
204
303
 
205
- Higher entries take priority:
304
+ biniLogger.info('Server ready')
305
+ biniLogger.warn('Missing optional var')
306
+ biniLogger.error('Something broke', error)
307
+ ```
206
308
 
207
- 1. `.env.local`
208
- 2. `.env.[mode].local`
209
- 3. `.env.[mode]`
210
- 4. `.env`
309
+ ### `HonoContext`
211
310
 
212
- Loaded once. Cached. No repeated disk reads.
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.
312
+
313
+ ```ts
314
+ import type { HonoContext } from 'bini-env'
315
+
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
+ }
323
+ }
324
+ ```
213
325
 
214
326
  ---
215
327
 
216
- ## ⚡ Performance
328
+ ## Performance
217
329
 
218
- | Metric | Dev | Prod |
219
- | ------------- | --------- | ----------- |
220
- | File Reads | 1–5 | 0 |
221
- | Runtime Cost | ~5ms once | 0 |
222
- | Bundle Impact | Minimal | Tree-shaken |
330
+ | Metric | Dev | Prod |
331
+ |--------|-----|------|
332
+ | File reads | 0 | 0 |
333
+ | Runtime cost | ~0ms | 0 |
334
+ | Bundle impact | Minimal | Tree-shaken |
223
335
 
224
- If you see overhead in production, you did something wrong.
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.
225
337
 
226
338
  ---
227
339
 
228
- ## 🔥 Common Failure Modes
340
+ ## Troubleshooting
229
341
 
230
- ### "Env is undefined"
231
- You forgot the prefix (`BINI_` or `VITE_`) on a client-side var, or you're reading an unprefixed secret from `import.meta.env`.
342
+ ### "Env var is undefined in production"
232
343
 
233
- ### "Works in dev, broken in prod"
234
- You relied on a `.env` file in production. Set vars in your hosting dashboard.
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.).
235
345
 
236
- ### "Secrets leaked"
237
- You exposed them via `BINI_` or `VITE_` prefix. Those are public. Use unprefixed vars for secrets.
346
+ ### "Works in dev, undefined in prod"
238
347
 
239
- ### "Works on Node, broken on Vercel/Netlify/Cloudflare"
240
- You had the old version with static `fs`/`path` imports. Upgrade — this version is edge-safe.
348
+ Same as above. Local dev works because Vite loads `.env` files automatically. Production requires platform-level configuration.
241
349
 
242
350
  ### "Cloudflare secret not found"
243
- Secrets added via `wrangler secret put` are only available via `c.env` inside your handler. Use `wrangler.toml [vars]` for anything `getEnv` needs at the top level.
244
351
 
245
- ### "Types not found"
246
- Add to your `tsconfig` or entry file:
247
- ```ts
248
- /// <reference types="vite/client" />
249
- ```
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.
250
353
 
251
- ---
354
+ ### "TypeScript error: Context not assignable to HonoContext"
252
355
 
253
- ## 🧪 Reality Check
356
+ Hono 4.12+ added a symbol to `HonoRequest` that can break structural assignability in strict TypeScript projects. Cast once per handler:
254
357
 
255
- This library is intentionally simple.
358
+ ```ts
359
+ const ctx = c as any
360
+ ```
256
361
 
257
- If you need:
258
- - Secret rotation
259
- - Encrypted envs
260
- - Runtime validation schemas
362
+ ### "Types not found"
261
363
 
262
- That's **your job**, not this package.
364
+ Add to your `tsconfig.json` or entry file:
263
365
 
264
- ---
366
+ ```ts
367
+ /// <reference types="vite/client" />
368
+ ```
265
369
 
266
- ## 🤝 Contributing
370
+ ---
267
371
 
268
- PRs welcome — but:
269
- - No bloat
270
- - No magic
271
- - No runtime cost
372
+ ## Compatibility
272
373
 
273
- If it slows startup or increases bundle size, it's getting rejected.
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 |
274
380
 
275
381
  ---
276
382
 
277
- ## 📄 License
383
+ ## Contributing
278
384
 
279
- MIT © Bini.js Team
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.
280
386
 
281
387
  ---
282
388
 
283
- **Ship fast. Leak nothing. Blame config, not tooling.**
389
+ ## License
390
+
391
+ MIT © Bini.js Team
package/dist/index.d.mts CHANGED
@@ -1,29 +1,34 @@
1
+ import { Context } from 'hono';
1
2
  import { Plugin } from 'vite';
2
3
  export { Plugin } from 'vite';
3
4
 
4
- declare function suppressDotenvLogsGlobally(): void;
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;
5
21
  interface BiniEnvPluginOptions {
6
- readonly enabled?: boolean;
7
- readonly clearViteHeader?: boolean;
8
- readonly logo?: string;
22
+ /** Extra prefixes to expose to import.meta.env, in addition to BINI_ and VITE_. */
9
23
  readonly envPrefix?: string | string[];
10
- readonly loadInPreview?: boolean;
11
- /** @deprecated Suppression is always applied at module load; this option is ignored. */
12
- readonly suppressDotenvLogs?: boolean;
13
- }
14
- interface DetectedEnvFile {
15
- readonly name: string;
16
- readonly path: string;
17
24
  }
18
25
  declare const biniLogger: {
19
26
  readonly info: (msg: string) => void;
20
27
  readonly warn: (msg: string) => void;
21
28
  readonly error: (msg: string, err?: unknown) => void;
22
29
  };
23
- declare function getEnv(key: string): string | undefined;
24
- declare function requireEnv(key: string): string;
25
- declare function loadEnv(projectRoot?: string): Promise<void>;
26
- 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;
27
32
  declare function biniEnv(options?: Readonly<BiniEnvPluginOptions>): Plugin;
28
33
 
29
- export { type BiniEnvPluginOptions, type DetectedEnvFile, biniEnv, biniLogger, detectEnvFiles, getEnv, loadEnv, requireEnv, suppressDotenvLogsGlobally };
34
+ export { type BiniEnvPluginOptions, type HonoContext, biniEnv, biniLogger, getEnv, requireEnv };
package/dist/index.d.ts CHANGED
@@ -1,29 +1,34 @@
1
+ import { Context } from 'hono';
1
2
  import { Plugin } from 'vite';
2
3
  export { Plugin } from 'vite';
3
4
 
4
- declare function suppressDotenvLogsGlobally(): void;
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;
5
21
  interface BiniEnvPluginOptions {
6
- readonly enabled?: boolean;
7
- readonly clearViteHeader?: boolean;
8
- readonly logo?: string;
22
+ /** Extra prefixes to expose to import.meta.env, in addition to BINI_ and VITE_. */
9
23
  readonly envPrefix?: string | string[];
10
- readonly loadInPreview?: boolean;
11
- /** @deprecated Suppression is always applied at module load; this option is ignored. */
12
- readonly suppressDotenvLogs?: boolean;
13
- }
14
- interface DetectedEnvFile {
15
- readonly name: string;
16
- readonly path: string;
17
24
  }
18
25
  declare const biniLogger: {
19
26
  readonly info: (msg: string) => void;
20
27
  readonly warn: (msg: string) => void;
21
28
  readonly error: (msg: string, err?: unknown) => void;
22
29
  };
23
- declare function getEnv(key: string): string | undefined;
24
- declare function requireEnv(key: string): string;
25
- declare function loadEnv(projectRoot?: string): Promise<void>;
26
- 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;
27
32
  declare function biniEnv(options?: Readonly<BiniEnvPluginOptions>): Plugin;
28
33
 
29
- export { type BiniEnvPluginOptions, type DetectedEnvFile, biniEnv, biniLogger, detectEnvFiles, getEnv, loadEnv, requireEnv, suppressDotenvLogsGlobally };
34
+ export { type BiniEnvPluginOptions, type HonoContext, biniEnv, biniLogger, getEnv, requireEnv };