bini-env 1.0.9 → 1.0.10

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
@@ -1,14 +1,14 @@
1
1
  # bini-env
2
2
 
3
- ![npm](https://img.shields.io/npm/v/bini-env?color=cyan\&style=flat-square)
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
- ![typescript](https://img.shields.io/badge/TypeScript-ready-3178C6?style=flat-square\&logo=typescript)
8
- ![node](https://img.shields.io/badge/node-%3E%3D20.19-339933?style=flat-square\&logo=node.js)
6
+ ![vite](https://img.shields.io/badge/vite-%3E%3D8.0-646CFF?style=flat-square&logo=vite)
7
+ ![typescript](https://img.shields.io/badge/TypeScript-ready-3178C6?style=flat-square&logo=typescript)
8
+ ![node](https://img.shields.io/badge/node-%3E%3D20.19-339933?style=flat-square&logo=node.js)
9
9
 
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, and edge runtimes — without leaking secrets or adding runtime cost.
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.
12
12
 
13
13
  ---
14
14
 
@@ -16,24 +16,25 @@ Loads `.env` in development, uses host-provided variables in production, and wor
16
16
 
17
17
  This library **does NOT magically make env vars safe**.
18
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**.
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
22
 
23
- If you don’t understand this, stop and fix that first.
23
+ If you don't understand this, stop and fix that first.
24
24
 
25
25
  ---
26
26
 
27
27
  ## ✨ Features
28
28
 
29
- * **Universal API** — `getEnv()` / `requireEnv()` work across runtimes
30
- * **Zero-config `.env` loading** in development
31
- * **Strict production behavior** — no file reads, no dotenv
32
- * **Prefix control** — supports `BINI_`, `VITE_`, or custom
33
- * **Tree-shakeable** — no dead code in client bundles
34
- * **Edge-safe** — no static dotenv import
35
- * **Typed** — full TypeScript support
36
- * **Fast** — single load in dev, zero overhead in prod
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
37
38
 
38
39
  ---
39
40
 
@@ -49,7 +50,7 @@ yarn add bini-env
49
50
 
50
51
  ---
51
52
 
52
- ## 🚀 Quick Start (Don’t Overthink It)
53
+ ## 🚀 Quick Start
53
54
 
54
55
  ```ts
55
56
  // vite.config.ts
@@ -61,15 +62,13 @@ export default defineConfig({
61
62
  });
62
63
  ```
63
64
 
64
- Done.
65
-
66
- If this doesn’t work, your project setup is broken — not the plugin.
65
+ Done. If this doesn't work, your project setup is broken — not the plugin.
67
66
 
68
67
  ---
69
68
 
70
69
  ## 🔐 Environment Rules (Read This Twice)
71
70
 
72
- > ✅ **Good news:** Both `BINI_` and `VITE_` prefixes work out of the box — no extra config needed.
71
+ > ✅ Both `BINI_` and `VITE_` prefixes work out of the box — no extra config needed.
73
72
 
74
73
  ### Client (PUBLIC)
75
74
 
@@ -78,16 +77,12 @@ BINI_PUBLIC_API_URL=https://api.example.com
78
77
  VITE_ANALYTICS_ID=UA-XXXX
79
78
  ```
80
79
 
81
- Accessible via:
82
-
83
80
  ```ts
84
81
  import.meta.env.BINI_PUBLIC_API_URL
85
82
  ```
86
83
 
87
84
  👉 **Never put secrets here. Ever.**
88
85
 
89
- ---
90
-
91
86
  ### Server (PRIVATE)
92
87
 
93
88
  ```env
@@ -96,25 +91,59 @@ DATABASE_URL=postgres://...
96
91
  ```
97
92
 
98
93
  ```ts
99
- import { requireEnv } from 'bini-env';
100
-
101
- const pass = requireEnv('SMTP_PASS');
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
102
97
  ```
103
98
 
104
- 👉 If this leaks, it’s your fault, not the library’s.
99
+ 👉 If this leaks, it's your fault, not the library's.
100
+
101
+ ---
102
+
103
+ ## 🌍 Platform Support
104
+
105
+ `getEnv` and `requireEnv` work identically across every supported platform. Write your API routes once — they run everywhere unchanged.
106
+
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()` ✅ |
115
+
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.
105
117
 
106
118
  ---
107
119
 
108
120
  ## 🧠 How It Actually Works
109
121
 
110
- | Mode | Behavior |
111
- | ---------------- | ---------------------------------------- |
112
- | Dev (`vite dev`) | Loads `.env` once via dynamic dotenv |
113
- | Preview | Same as dev |
114
- | Production | Uses `process.env` / host injection only |
115
- | Edge/Deno | Uses native `Deno.env` |
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 |
116
129
 
117
- **No runtime branching in client bundles. No hidden magic.**
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.
131
+
132
+ ---
133
+
134
+ ## 🔄 Auto Server Restart
135
+
136
+ The dev server automatically restarts when any `.env*` file is created or changed in your project root — no manual restart needed.
137
+
138
+ ```
139
+ 12:00:01 [bini-env] .env.local changed — restarting server
140
+ ```
141
+
142
+ Covered events:
143
+ - Creating a new `.env`, `.env.local`, `.env.production`, etc.
144
+ - Editing any existing `.env*` file
145
+
146
+ Editor swap files (`.env.swp`, `.env~`, `.env.bak`) are ignored.
118
147
 
119
148
  ---
120
149
 
@@ -122,18 +151,15 @@ const pass = requireEnv('SMTP_PASS');
122
151
 
123
152
  ```ts
124
153
  biniEnv({
125
- enabled: true,
154
+ enabled : true,
126
155
  clearViteHeader: true,
127
- logo: 'ß',
128
- envPrefix: ['BINI_', 'VITE_']
156
+ logo : 'ß',
157
+ envPrefix : ['BINI_', 'VITE_'],
158
+ loadInPreview : true,
129
159
  });
130
160
  ```
131
161
 
132
- ### Critical Detail
133
-
134
- If you change `envPrefix`, you are changing what gets exposed to the browser.
135
-
136
- Break this → you leak secrets.
162
+ > **Critical:** If you change `envPrefix`, you are changing what gets exposed to the browser. Break this → you leak secrets.
137
163
 
138
164
  ---
139
165
 
@@ -141,38 +167,43 @@ Break this → you leak secrets.
141
167
 
142
168
  ### `getEnv(key)`
143
169
 
144
- Returns `string | undefined`.
170
+ Returns `string | undefined`. Auto-imported in API routes.
145
171
 
146
- Safe fallback reader across:
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)
147
176
 
148
- * `Deno.env`
149
- * `process.env`
150
- * `import.meta.env`
151
-
152
- ---
177
+ ```ts
178
+ const debug = getEnv('DEBUG_MODE');
179
+ ```
153
180
 
154
181
  ### `requireEnv(key)`
155
182
 
156
- Same as `getEnv` but throws:
183
+ Same as `getEnv` but throws if missing:
157
184
 
158
- ```txt
185
+ ```
159
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.
160
189
  ```
161
190
 
162
- Use this for anything critical.
191
+ Use this for anything critical that must exist at startup.
163
192
 
164
- ---
193
+ ```ts
194
+ const dbUrl = requireEnv('DATABASE_URL');
195
+ ```
165
196
 
166
197
  ### `biniEnv(options)`
167
198
 
168
- Vite plugin.
169
-
170
- If your plugin order is wrong and things break, that’s on your config.
199
+ Vite plugin. Handles `.env` loading, terminal output, and dev server watching.
171
200
 
172
201
  ---
173
202
 
174
203
  ## 📂 Env File Resolution Order
175
204
 
205
+ Higher entries take priority:
206
+
176
207
  1. `.env.local`
177
208
  2. `.env.[mode].local`
178
209
  3. `.env.[mode]`
@@ -196,22 +227,23 @@ If you see overhead in production, you did something wrong.
196
227
 
197
228
  ## 🔥 Common Failure Modes
198
229
 
199
- ### 1. “Env is undefined”
200
-
201
- You forgot the prefix.
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`.
202
232
 
203
- ### 2. “Works in dev, broken in prod”
233
+ ### "Works in dev, broken in prod"
234
+ You relied on a `.env` file in production. Set vars in your hosting dashboard.
204
235
 
205
- You relied on `.env` in production.
236
+ ### "Secrets leaked"
237
+ You exposed them via `BINI_` or `VITE_` prefix. Those are public. Use unprefixed vars for secrets.
206
238
 
207
- ### 3. “Secrets leaked”
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.
208
241
 
209
- You exposed them via prefix.
210
-
211
- ### 4. “Types not found”
212
-
213
- Add:
242
+ ### "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.
214
244
 
245
+ ### "Types not found"
246
+ Add to your `tsconfig` or entry file:
215
247
  ```ts
216
248
  /// <reference types="vite/client" />
217
249
  ```
@@ -223,24 +255,22 @@ Add:
223
255
  This library is intentionally simple.
224
256
 
225
257
  If you need:
258
+ - Secret rotation
259
+ - Encrypted envs
260
+ - Runtime validation schemas
226
261
 
227
- * secret rotation
228
- * encrypted envs
229
- * runtime validation schemas
230
-
231
- That’s **your job**, not this package.
262
+ That's **your job**, not this package.
232
263
 
233
264
  ---
234
265
 
235
266
  ## 🤝 Contributing
236
267
 
237
268
  PRs welcome — but:
269
+ - No bloat
270
+ - No magic
271
+ - No runtime cost
238
272
 
239
- * No bloat
240
- * No magic
241
- * No runtime cost
242
-
243
- If it slows startup or increases bundle size, it’s getting rejected.
273
+ If it slows startup or increases bundle size, it's getting rejected.
244
274
 
245
275
  ---
246
276
 
@@ -250,4 +280,4 @@ MIT © Bini.js Team
250
280
 
251
281
  ---
252
282
 
253
- **Ship fast. Leak nothing. Blame config, not tooling.**
283
+ **Ship fast. Leak nothing. Blame config, not tooling.**
package/dist/index.js CHANGED
@@ -1,24 +1,32 @@
1
1
  'use strict';
2
2
 
3
- var fs = require('fs');
4
- var path = require('path');
5
-
6
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
-
8
- var fs__default = /*#__PURE__*/_interopDefault(fs);
9
- var path__default = /*#__PURE__*/_interopDefault(path);
3
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
+ }) : x)(function(x) {
6
+ if (typeof require !== "undefined") return require.apply(this, arguments);
7
+ throw Error('Dynamic require of "' + x + '" is not supported');
8
+ });
10
9
 
11
10
  // src/index.ts
11
+ function isNodeLike() {
12
+ return typeof process !== "undefined" && !!process.env && typeof process.versions === "object" && // Edge runtimes (Vercel, Cloudflare) expose a minimal `process` but not
13
+ // `process.versions.node`. Checking for it keeps us out of edge bundles.
14
+ (typeof process.versions.node === "string" || // Bun sets process.versions.bun
15
+ typeof process.versions.bun === "string");
16
+ }
17
+ function isDenoRuntime() {
18
+ return typeof globalThis.Deno !== "undefined";
19
+ }
12
20
  var originalConsoleLog = console.log.bind(console);
13
21
  var originalConsoleError = console.error.bind(console);
14
- if (typeof process !== "undefined" && process.env && !process.env.NODE_ENV) {
22
+ if (isNodeLike() && !process.env.NODE_ENV) {
15
23
  process.env.NODE_ENV = "production";
16
24
  }
17
25
  var _suppressionApplied = false;
18
26
  function suppressDotenvLogsGlobally() {
19
27
  if (_suppressionApplied) return;
20
28
  _suppressionApplied = true;
21
- if (typeof process !== "undefined" && process.env) {
29
+ if (isNodeLike()) {
22
30
  process.env.DOTENV_QUIET = "true";
23
31
  }
24
32
  const isDotenvNoise = (...args) => {
@@ -68,9 +76,6 @@ var biniLogger = {
68
76
  function getDeno() {
69
77
  return globalThis.Deno;
70
78
  }
71
- function hasProcessEnv() {
72
- return typeof process !== "undefined" && !!process.env;
73
- }
74
79
  function defer(fn) {
75
80
  if (typeof setImmediate !== "undefined") {
76
81
  setImmediate(fn);
@@ -91,7 +96,7 @@ function getEnv(key) {
91
96
  } catch {
92
97
  }
93
98
  }
94
- if (hasProcessEnv()) {
99
+ if (typeof process !== "undefined" && process.env) {
95
100
  const value = process.env[key];
96
101
  if (value !== void 0) {
97
102
  envCache.set(key, value);
@@ -132,8 +137,7 @@ async function loadEnv(projectRoot) {
132
137
  if (_loadPromise) return _loadPromise;
133
138
  _loadPromise = (async () => {
134
139
  try {
135
- if (getDeno()) return;
136
- if (!hasProcessEnv()) return;
140
+ if (isDenoRuntime() || !isNodeLike()) return;
137
141
  const root = projectRoot ?? process.cwd();
138
142
  const nodeEnv = process.env.NODE_ENV ?? "production";
139
143
  const envFiles = [
@@ -142,11 +146,18 @@ async function loadEnv(projectRoot) {
142
146
  `.env.${nodeEnv}.local`,
143
147
  ".env.local"
144
148
  ];
145
- const dotenv = await import('dotenv');
149
+ const [dotenvMod, fsMod, pathMod] = await Promise.all([
150
+ import('dotenv'),
151
+ import('fs'),
152
+ import('path')
153
+ ]);
154
+ const dotenv = dotenvMod;
155
+ const fs = fsMod.default ?? fsMod;
156
+ const path = pathMod.default ?? pathMod;
146
157
  for (const file of envFiles) {
147
- const filePath = path__default.default.join(root, file);
158
+ const filePath = path.join(root, file);
148
159
  try {
149
- await fs__default.default.promises.access(filePath, fs__default.default.constants.R_OK);
160
+ await fs.promises.access(filePath, fs.constants.R_OK);
150
161
  dotenv.config({ path: filePath, override: true });
151
162
  } catch {
152
163
  }
@@ -163,10 +174,20 @@ async function loadEnv(projectRoot) {
163
174
  }
164
175
  var _envFilesCache = null;
165
176
  var _cacheKey = "";
166
- function detectEnvFiles(projectRoot = process.cwd()) {
177
+ function detectEnvFiles(projectRoot) {
178
+ if (!isNodeLike()) return [];
179
+ const root = projectRoot ?? process.cwd();
167
180
  const nodeEnv = process.env.NODE_ENV ?? "production";
168
- const cacheKey = `${projectRoot}:${nodeEnv}`;
181
+ const cacheKey = `${root}:${nodeEnv}`;
169
182
  if (_envFilesCache && _cacheKey === cacheKey) return _envFilesCache;
183
+ let fsSync;
184
+ let pathMod;
185
+ try {
186
+ fsSync = __require("fs");
187
+ pathMod = __require("path");
188
+ } catch {
189
+ return [];
190
+ }
170
191
  const candidates = [
171
192
  ".env.local",
172
193
  `.env.${nodeEnv}.local`,
@@ -176,8 +197,8 @@ function detectEnvFiles(projectRoot = process.cwd()) {
176
197
  const found = [];
177
198
  for (const file of candidates) {
178
199
  try {
179
- const filePath = path__default.default.join(projectRoot, file);
180
- if (fs__default.default.existsSync(filePath)) found.push({ name: file, path: filePath });
200
+ const filePath = pathMod.join(root, file);
201
+ if (fsSync.existsSync(filePath)) found.push({ name: file, path: filePath });
181
202
  } catch {
182
203
  }
183
204
  }
@@ -186,7 +207,9 @@ function detectEnvFiles(projectRoot = process.cwd()) {
186
207
  return found;
187
208
  }
188
209
  function clearLine() {
189
- if (process.stdout.isTTY) process.stdout.write("\x1B[2K\r");
210
+ if (typeof process !== "undefined" && process.stdout?.isTTY) {
211
+ process.stdout.write("\x1B[2K\r");
212
+ }
190
213
  }
191
214
  function printResolvedUrls(urls) {
192
215
  if (!urls) return;
@@ -250,6 +273,25 @@ function biniEnv(options = {}) {
250
273
  } else {
251
274
  defer(triggerLoad);
252
275
  }
276
+ const envGlob = `${getRoot()}/.env*`;
277
+ server.watcher.add(envGlob);
278
+ const onEnvChange = (filePath) => {
279
+ if (/\.(swp|swo|bak|tmp)$|~$/.test(filePath)) return;
280
+ biniLogger.info(
281
+ `env file ${filePath.replace(getRoot() + "/", "")} changed \u2014 restarting server`
282
+ );
283
+ _envLoaded = false;
284
+ _loadPromise = null;
285
+ envCache.clear();
286
+ _envFilesCache = null;
287
+ void server.restart();
288
+ };
289
+ server.watcher.on("add", onEnvChange);
290
+ server.watcher.on("change", onEnvChange);
291
+ server.httpServer?.once("close", () => {
292
+ server.watcher.off("add", onEnvChange);
293
+ server.watcher.off("change", onEnvChange);
294
+ });
253
295
  if (clearViteHeader || logo !== BINI_LOGO) {
254
296
  patchPrintUrls(server, "dev", logo, clearViteHeader, getRoot, true);
255
297
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["path","fs"],"mappings":";;;;;;;;;;;AASA,IAAM,kBAAA,GAAuB,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,OAAO,CAAA;AACrD,IAAM,oBAAA,GAAuB,OAAA,CAAQ,KAAA,CAAM,IAAA,CAAK,OAAO,CAAA;AAMvD,IAAI,OAAO,YAAY,WAAA,IAAe,OAAA,CAAQ,OAAO,CAAC,OAAA,CAAQ,IAAI,QAAA,EAAU;AAC1E,EAAA,OAAA,CAAQ,IAAI,QAAA,GAAW,YAAA;AACzB;AAOA,IAAI,mBAAA,GAAsB,KAAA;AAEnB,SAAS,0BAAA,GAAmC;AACjD,EAAA,IAAI,mBAAA,EAAqB;AACzB,EAAA,mBAAA,GAAsB,IAAA;AAEtB,EAAA,IAAI,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,GAAA,EAAK;AACjD,IAAA,OAAA,CAAQ,IAAI,YAAA,GAAe,MAAA;AAAA,EAC7B;AAEA,EAAA,MAAM,aAAA,GAAgB,IAAI,IAAA,KAA6B;AACrD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA;AACzB,IAAA,OACE,GAAA,CAAI,QAAA,CAAS,UAAU,CAAA,IACvB,GAAA,CAAI,SAAS,cAAc,CAAA,IAC3B,GAAA,CAAI,QAAA,CAAS,eAAe,CAAA;AAAA,EAEhC,CAAA;AAEA,EAAA,OAAA,CAAQ,GAAA,GAAM,IAAI,IAAA,KAAoB;AACpC,IAAA,IAAI,CAAC,aAAA,CAAc,GAAG,IAAI,CAAA,EAAG,kBAAA,CAAmB,GAAG,IAAI,CAAA;AAAA,EACzD,CAAA;AAEA,EAAA,OAAA,CAAQ,KAAA,GAAQ,IAAI,IAAA,KAAoB;AACtC,IAAA,IAAI,CAAC,aAAA,CAAc,GAAG,IAAI,CAAA,EAAG,oBAAA,CAAqB,GAAG,IAAI,CAAA;AAAA,EAC3D,CAAA;AACF;AAGA,0BAAA,EAA2B;AAoC3B,IAAM,SAAA,GAAqB,MAAA;AAC3B,IAAM,kBAAA,GAAqB,CAAC,OAAA,EAAS,OAAO,CAAA;AAG5C,IAAM,eAAA,GAAkB,OAAO,MAAA,CAAO;AAAA,EACpC,OAAA,EAAiB,IAAA;AAAA,EACjB,eAAA,EAAiB,IAAA;AAAA,EACjB,IAAA,EAAiB,SAAA;AAAA,EACjB,SAAA,EAAiB,CAAC,GAAG,kBAAkB,CAAA;AAAA,EACvC,aAAA,EAAiB;AACnB,CAAsE,CAAA;AAYtE,IAAM,QAAA,uBAAe,GAAA,EAAgC;AAarD,SAAS,SAAA,GAAoB;AAC3B,EAAA,OAAO,CAAA,EAAG,SAAA,WAAU,EAAA,iBAAG,IAAI,MAAK,EAAE,kBAAA,CAAmB,OAAA,EAAS,EAAE,MAAA,EAAQ,KAAA,EAAO,CAAC,GAAG,SAAA,aAAY,CAAA;AACjG;AAEO,IAAM,UAAA,GAAa;AAAA,EACxB,KAAK,GAAA,EAAmB;AACtB,IAAA,kBAAA;AAAA,MACE,CAAA,EAAG,SAAA,EAAW,CAAA,CAAA,EAAI,UAAA,cAAc,SAAA,YAAW,UAAA,EAAa,SAAA,aAAY,CAAA,EAAI,GAAG,CAAA;AAAA,KAC7E;AAAA,EACF,CAAA;AAAA,EACA,KAAK,GAAA,EAAmB;AACtB,IAAA,oBAAA;AAAA,MACE,CAAA,EAAG,SAAA,EAAW,CAAA,CAAA,EAAI,wBAAa,EAAG,SAAA,YAAW,cAAA,EAAiB,SAAA,aAAY,CAAA,EAAI,UAAA,cAAa,EAAG,GAAG,GAAG,SAAA,aAAY;AAAA,KAClH;AAAA,EACF,CAAA;AAAA,EACA,KAAA,CAAM,KAAa,GAAA,EAAqB;AACtC,IAAA,MAAM,MAAA,GAAS,eAAe,KAAA,GAC1B;AAAA,IAAA,EAAS,oBAAU,EAAG,GAAA,CAAI,OAAO,CAAA,EAAG,sBAAY,CAAA,GAChD,EAAA;AACJ,IAAA,oBAAA;AAAA,MACE,CAAA,EAAG,SAAA,EAAW,CAAA,CAAA,EAAI,UAAA,WAAU,EAAG,SAAA,YAAW,gBAAA,EAAmB,SAAA,aAAY,CAAA,EAAI,GAAG,CAAA,EAAG,MAAM,CAAA;AAAA,KAC3F;AAAA,EACF;AACF;AAMA,SAAS,OAAA,GAAqC;AAC5C,EAAA,OAAQ,UAAA,CAAmD,IAAA;AAC7D;AAEA,SAAS,aAAA,GAAyB;AAChC,EAAA,OAAO,OAAO,OAAA,KAAY,WAAA,IAAe,CAAC,CAAC,OAAA,CAAQ,GAAA;AACrD;AAGA,SAAS,MAAM,EAAA,EAAsB;AACnC,EAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACvC,IAAA,YAAA,CAAa,EAAE,CAAA;AAAA,EACjB,CAAA,MAAO;AACL,IAAA,OAAA,CAAQ,OAAA,EAAQ,CAAE,IAAA,CAAK,EAAE,CAAA;AAAA,EAC3B;AACF;AAMO,SAAS,OAAO,GAAA,EAAiC;AACtD,EAAA,IAAI,SAAS,GAAA,CAAI,GAAG,GAAG,OAAO,QAAA,CAAS,IAAI,GAAG,CAAA;AAG9C,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AAC9B,MAAA,IAAI,UAAU,KAAA,CAAA,EAAW;AACvB,QAAA,QAAA,CAAS,GAAA,CAAI,KAAK,KAAK,CAAA;AACvB,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAAqB;AAAA,EAC/B;AAGA,EAAA,IAAI,eAAc,EAAG;AACnB,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAC7B,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,QAAA,CAAS,GAAA,CAAI,KAAK,KAAK,CAAA;AACvB,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAGA,EAAA,IAAI;AACF,IAAA,MAAM,UAAU,SAAY;AAC5B,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,KAAA,MAAW,SAAA,IAAa,CAAC,GAAA,EAAK,CAAA,KAAA,EAAQ,GAAG,CAAA,CAAA,EAAI,CAAA,KAAA,EAAQ,GAAG,CAAA,CAAE,CAAA,EAAG;AAC3D,QAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,KAAM,KAAA,CAAA,EAAW;AACpC,UAAA,QAAA,CAAS,GAAA,CAAI,GAAA,EAAK,OAAA,CAAQ,SAAS,CAAC,CAAA;AACpC,UAAA,OAAO,QAAQ,SAAS,CAAA;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAAsD;AAE9D,EAAA,QAAA,CAAS,GAAA,CAAI,KAAK,MAAS,CAAA;AAC3B,EAAA,OAAO,MAAA;AACT;AAMO,SAAS,WAAW,GAAA,EAAqB;AAC9C,EAAA,MAAM,GAAA,GAAM,OAAO,GAAG,CAAA;AACtB,EAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,IAAA,UAAA,CAAW,KAAA;AAAA,MACT,2CAA2C,GAAG,CAAA;AAAA,EAAA,EACzC,SAAA,6DAAwD,SAAA;AAAY,EAAA,EACpE,SAAA,oEAA+D,SAAA,aAAY;AAAA,KAClF;AACA,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mDAAA,EAAsD,GAAG,CAAA,CAAA,CAAG,CAAA;AAAA,EAC9E;AACA,EAAA,OAAO,GAAA;AACT;AASA,IAAI,UAAA,GAAc,KAAA;AAClB,IAAI,YAAA,GAAqC,IAAA;AAEzC,eAAsB,QAAQ,WAAA,EAAqC;AACjE,EAAA,IAAI,UAAA,EAAY;AAChB,EAAA,IAAI,cAAc,OAAO,YAAA;AAEzB,EAAA,YAAA,GAAA,CAAgB,YAAY;AAC1B,IAAA,IAAI;AACF,MAAA,IAAI,SAAQ,EAAG;AACf,MAAA,IAAI,CAAC,eAAc,EAAG;AAEtB,MAAA,MAAM,IAAA,GAAU,WAAA,IAAe,OAAA,CAAQ,GAAA,EAAI;AAC3C,MAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,GAAA,CAAI,QAAA,IAAY,YAAA;AAGxC,MAAA,MAAM,QAAA,GAAW;AAAA,QACf,MAAA;AAAA,QACA,QAAQ,OAAO,CAAA,CAAA;AAAA,QACf,QAAQ,OAAO,CAAA,MAAA,CAAA;AAAA,QACf;AAAA,OACF;AAEA,MAAA,MAAM,MAAA,GAAS,MAAM,OAAO,QAAQ,CAAA;AAEpC,MAAA,KAAA,MAAW,QAAQ,QAAA,EAAU;AAC3B,QAAA,MAAM,QAAA,GAAWA,qBAAA,CAAK,IAAA,CAAK,IAAA,EAAM,IAAI,CAAA;AACrC,QAAA,IAAI;AACF,UAAA,MAAMC,oBAAG,QAAA,CAAS,MAAA,CAAO,QAAA,EAAUA,mBAAA,CAAG,UAAU,IAAI,CAAA;AACpD,UAAA,MAAA,CAAO,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,QAAA,EAAU,MAAM,CAAA;AAAA,QAClD,CAAA,CAAA,MAAQ;AAAA,QAA2B;AAAA,MACrC;AAGA,MAAA,QAAA,CAAS,KAAA,EAAM;AACf,MAAA,UAAA,GAAa,IAAA;AAAA,IAEf,SAAS,KAAA,EAAO;AAGd,MAAA,UAAA,CAAW,KAAA,CAAM,4BAA4B,KAAK,CAAA;AAAA,IAEpD,CAAA,SAAE;AACA,MAAA,YAAA,GAAe,IAAA;AAAA,IACjB;AAAA,EACF,CAAA,GAAG;AAEH,EAAA,OAAO,YAAA;AACT;AAOA,IAAI,cAAA,GAA2C,IAAA;AAC/C,IAAI,SAAA,GAAY,EAAA;AAET,SAAS,cAAA,CAAe,WAAA,GAAsB,OAAA,CAAQ,GAAA,EAAI,EAAsB;AACrF,EAAA,MAAM,OAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,QAAA,IAAY,YAAA;AAC1C,EAAA,MAAM,QAAA,GAAY,CAAA,EAAG,WAAW,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AAC3C,EAAA,IAAI,cAAA,IAAkB,SAAA,KAAc,QAAA,EAAU,OAAO,cAAA;AAErD,EAAA,MAAM,UAAA,GAAa;AAAA,IACjB,YAAA;AAAA,IACA,QAAQ,OAAO,CAAA,MAAA,CAAA;AAAA,IACf,QAAQ,OAAO,CAAA,CAAA;AAAA,IACf;AAAA,GACF;AAEA,EAAA,MAAM,QAA2B,EAAC;AAClC,EAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC7B,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAWD,qBAAA,CAAK,IAAA,CAAK,WAAA,EAAa,IAAI,CAAA;AAC5C,MAAA,IAAIC,mBAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,EAAG,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,CAAA;AAAA,IACxE,CAAA,CAAA,MAAQ;AAAA,IAA8B;AAAA,EACxC;AAEA,EAAA,cAAA,GAAiB,KAAA;AACjB,EAAA,SAAA,GAAiB,QAAA;AACjB,EAAA,OAAO,KAAA;AACT;AAMA,SAAS,SAAA,GAAkB;AACzB,EAAA,IAAI,QAAQ,MAAA,CAAO,KAAA,EAAO,OAAA,CAAQ,MAAA,CAAO,MAAM,WAAW,CAAA;AAC5D;AAEA,SAAS,kBACP,IAAA,EACM;AACN,EAAA,IAAI,CAAC,IAAA,EAAM;AACX,EAAA,IAAI,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG;AACzB,IAAA,kBAAA;AAAA,MACE,CAAA,EAAA,EAAK,UAAA,aAAY,MAAA,EAAI,SAAA,aAAY,WAAA,EAAc,UAAA,YAAW,EAAG,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA,EAAG,SAAA,aAAY;AAAA,KAC3F;AAAA,EACF;AACA,EAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AAC3B,IAAA,kBAAA;AAAA,MACE,CAAA,EAAA,EAAK,UAAA,aAAY,MAAA,EAAI,SAAA,aAAY,WAAA,EAAc,UAAA,YAAW,EAAG,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,EAAG,SAAA,aAAY;AAAA,KAC7F;AAAA,EACF;AACF;AAUA,SAAS,eACP,MAAA,EACA,IAAA,EACA,IAAA,EACA,eAAA,EACA,SACA,YAAA,EACM;AACN,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,MAAM,iBAAA,GAAoB,MAAA,CAAO,SAAA,CAAU,IAAA,CAAK,MAAM,CAAA;AAEtD,EAAA,MAAA,CAAO,YAAY,MAAM;AACvB,IAAA,IAAI,OAAA,EAAS;AACb,IAAA,OAAA,GAAU,IAAA;AAEV,IAAA,IAAI,iBAAiB,SAAA,EAAU;AAC/B,IAAA,kBAAA,CAAmB;AAAA,EAAA,EAAO,sBAAW,EAAG,IAAI,WAAW,SAAA,aAAY,EAAA,EAAK,IAAI,CAAA,CAAA,CAAG,CAAA;AAE/E,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,OAAA,EAAS,CAAA;AACtC,MAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AACpB,QAAA,kBAAA;AAAA,UACE,CAAA,EAAA,EAAK,UAAA,aAAY,MAAA,EAAI,SAAA,aAAY,gBAAA,EAAmB,KAAA,CAAM,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,IAAI,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,SACvF;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAI,eAAA,EAAiB;AACnB,MAAA,iBAAA,CAAkB,OAAO,YAAY,CAAA;AAAA,IACvC,CAAA,MAAO;AACL,MAAA,iBAAA,EAAkB;AAAA,IACpB;AAAA,EACF,CAAA;AACF;AAMO,SAAS,OAAA,CAAQ,OAAA,GAA0C,EAAC,EAAW;AAC5E,EAAA,IAAI,OAAA,CAAQ,YAAY,KAAA,EAAO;AAC7B,IAAA,OAAO,EAAE,MAAM,sBAAA,EAAuB;AAAA,EACxC;AAEA,EAAA,MAAM,EAAE,eAAA,EAAiB,IAAA,EAAM,SAAA,EAAW,eAAc,GAAI;AAAA,IAC1D,GAAG,eAAA;AAAA,IACH,GAAG;AAAA,GACL;AAEA,EAAA,IAAI,cAAA;AACJ,EAAA,MAAM,OAAA,GAAU,MAAM,cAAA,EAAgB,IAAA,IAAQ,QAAQ,GAAA,EAAI;AAE1D,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,sBAAA;AAAA,IAEN,MAAA,GAAqB;AACnB,MAAA,OAAO,EAAE,SAAA,EAAU;AAAA,IACrB,CAAA;AAAA,IAEA,eAAe,GAAA,EAAqB;AAClC,MAAA,cAAA,GAAiB,GAAA;AAAA,IACnB,CAAA;AAAA,IAEA,gBAAgB,MAAA,EAAQ;AAEtB,MAAA,MAAM,WAAA,GAAc,MAAM,KAAK,OAAA,CAAQ,SAAS,CAAA;AAChD,MAAA,IAAI,OAAO,UAAA,EAAY;AACrB,QAAA,MAAA,CAAO,UAAA,CAAW,IAAA,CAAK,WAAA,EAAa,WAAW,CAAA;AAAA,MACjD,CAAA,MAAO;AACL,QAAA,KAAA,CAAM,WAAW,CAAA;AAAA,MACnB;AAGA,MAAA,IAAI,eAAA,IAAmB,SAAS,SAAA,EAAW;AACzC,QAAA,cAAA,CAAe,MAAA,EAAQ,KAAA,EAAO,IAAA,EAAM,eAAA,EAAiB,SAAS,IAAI,CAAA;AAAA,MACpE;AAAA,IACF,CAAA;AAAA,IAEA,uBAAuB,MAAA,EAAQ;AAC7B,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,MAAM,WAAA,GAAc,MAAM,KAAK,OAAA,CAAQ,SAAS,CAAA;AAChD,QAAA,IAAI,OAAO,UAAA,EAAY;AACrB,UAAA,MAAA,CAAO,UAAA,CAAW,IAAA,CAAK,WAAA,EAAa,WAAW,CAAA;AAAA,QACjD,CAAA,MAAO;AACL,UAAA,KAAA,CAAM,WAAW,CAAA;AAAA,QACnB;AAAA,MACF;AAEA,MAAA,IAAI,eAAA,IAAmB,SAAS,SAAA,EAAW;AACzC,QAAA,cAAA,CAAe,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,eAAA,EAAiB,SAAS,aAAa,CAAA;AAAA,MACjF;AAAA,IACF;AAAA,GACF;AACF","file":"index.js","sourcesContent":["// bini-env/src/index.ts\nimport fs from 'fs';\nimport path from 'path';\nimport type { Plugin, PreviewServer, ResolvedConfig, UserConfig, ViteDevServer } from 'vite';\n\n/* ==========================================================================\n Capture originals FIRST — before any patching occurs\n ========================================================================== */\n\nconst originalConsoleLog = console.log.bind(console);\nconst originalConsoleError = console.error.bind(console);\n\n/* ==========================================================================\n Default NODE_ENV — must run before anything else\n ========================================================================== */\n\nif (typeof process !== 'undefined' && process.env && !process.env.NODE_ENV) {\n process.env.NODE_ENV = 'production';\n}\n\n/* ==========================================================================\n DOTENV LOG SUPPRESSION\n Patched once at module load; subsequent calls are no-ops.\n ========================================================================== */\n\nlet _suppressionApplied = false;\n\nexport function suppressDotenvLogsGlobally(): void {\n if (_suppressionApplied) return;\n _suppressionApplied = true;\n\n if (typeof process !== 'undefined' && process.env) {\n process.env.DOTENV_QUIET = 'true';\n }\n\n const isDotenvNoise = (...args: unknown[]): boolean => {\n const msg = args.join(' ');\n return (\n msg.includes('[dotenv@') ||\n msg.includes('injected env') ||\n msg.includes('injecting env')\n );\n };\n\n console.log = (...args: unknown[]) => {\n if (!isDotenvNoise(...args)) originalConsoleLog(...args);\n };\n\n console.error = (...args: unknown[]) => {\n if (!isDotenvNoise(...args)) originalConsoleError(...args);\n };\n}\n\n// Apply once at module load\nsuppressDotenvLogsGlobally();\n\n/* ==========================================================================\n Cross-runtime type declarations\n ========================================================================== */\n\ninterface DenoEnv {\n get(key: string): string | undefined;\n}\ninterface DenoNamespace {\n env: DenoEnv;\n}\n\n/* ==========================================================================\n Public types\n ========================================================================== */\n\nexport interface BiniEnvPluginOptions {\n readonly enabled?: boolean;\n readonly clearViteHeader?: boolean;\n readonly logo?: string;\n readonly envPrefix?: string | string[];\n readonly loadInPreview?: boolean;\n /** @deprecated Suppression is always applied at module load; this option is ignored. */\n readonly suppressDotenvLogs?: boolean;\n}\n\nexport interface DetectedEnvFile {\n readonly name: string;\n readonly path: string;\n}\n\n/* ==========================================================================\n Constants\n ========================================================================== */\n\nconst BINI_LOGO = 'ß';\nconst DEFAULT_ENV_PREFIX = ['BINI_', 'VITE_'] as const;\n\n// suppressDotenvLogs intentionally omitted — it is deprecated and ignored\nconst DEFAULT_OPTIONS = Object.freeze({\n enabled : true,\n clearViteHeader: true,\n logo : BINI_LOGO,\n envPrefix : [...DEFAULT_ENV_PREFIX],\n loadInPreview : true,\n} satisfies Omit<Required<BiniEnvPluginOptions>, 'suppressDotenvLogs'>);\n\nconst enum COLORS {\n CYAN = '\\x1b[36m',\n RESET = '\\x1b[0m',\n GREEN = '\\x1b[32m',\n YELLOW = '\\x1b[33m',\n RED = '\\x1b[31m',\n BOLD = '\\x1b[1m',\n DIM = '\\x1b[2m',\n}\n\nconst envCache = new Map<string, string | undefined>();\n\n/* ==========================================================================\n Standalone logger\n Used for messages emitted outside plugin context (loadEnv, requireEnv,\n standalone getEnv calls) where resolvedConfig.logger is not yet available.\n\n Format mirrors Vite exactly:\n info → 12:00:00 [bini-env] … cyan bold prefix\n warn → 12:00:00 (!) [bini-env] … yellow bold, Vite's (!) convention\n error → 12:00:00 [bini-env] error … red bold, optional dim detail line\n ========================================================================== */\n\nfunction timestamp(): string {\n return `${COLORS.DIM}${new Date().toLocaleTimeString('en-US', { hour12: false })}${COLORS.RESET}`;\n}\n\nexport const biniLogger = {\n info(msg: string): void {\n originalConsoleLog(\n `${timestamp()} ${COLORS.CYAN}${COLORS.BOLD}[bini-env]${COLORS.RESET} ${msg}`,\n );\n },\n warn(msg: string): void {\n originalConsoleError(\n `${timestamp()} ${COLORS.YELLOW}${COLORS.BOLD}(!) [bini-env]${COLORS.RESET} ${COLORS.YELLOW}${msg}${COLORS.RESET}`,\n );\n },\n error(msg: string, err?: unknown): void {\n const detail = err instanceof Error\n ? `\\n ${COLORS.DIM}${err.message}${COLORS.RESET}`\n : '';\n originalConsoleError(\n `${timestamp()} ${COLORS.RED}${COLORS.BOLD}[bini-env] error${COLORS.RESET} ${msg}${detail}`,\n );\n },\n} as const;\n\n/* ==========================================================================\n Runtime helpers\n ========================================================================== */\n\nfunction getDeno(): DenoNamespace | undefined {\n return (globalThis as unknown as { Deno?: DenoNamespace }).Deno;\n}\n\nfunction hasProcessEnv(): boolean {\n return typeof process !== 'undefined' && !!process.env;\n}\n\n/** Schedule a task compatible with Node, Bun, Deno, and edge runtimes. */\nfunction defer(fn: () => void): void {\n if (typeof setImmediate !== 'undefined') {\n setImmediate(fn);\n } else {\n Promise.resolve().then(fn);\n }\n}\n\n/* ==========================================================================\n getEnv\n ========================================================================== */\n\nexport function getEnv(key: string): string | undefined {\n if (envCache.has(key)) return envCache.get(key);\n\n // 1. Deno runtime\n const deno = getDeno();\n if (deno) {\n try {\n const value = deno.env.get(key);\n if (value !== undefined) {\n envCache.set(key, value);\n return value;\n }\n } catch { /* fall through */ }\n }\n\n // 2. Node.js / Bun\n if (hasProcessEnv()) {\n const value = process.env[key];\n if (value !== undefined) {\n envCache.set(key, value);\n return value;\n }\n }\n\n // 3. Vite client (import.meta.env) — also checks BINI_ and VITE_ prefixed variants\n try {\n const metaEnv = import.meta.env as Record<string, string | undefined> | undefined;\n if (metaEnv) {\n for (const candidate of [key, `BINI_${key}`, `VITE_${key}`]) {\n if (metaEnv[candidate] !== undefined) {\n envCache.set(key, metaEnv[candidate]);\n return metaEnv[candidate];\n }\n }\n }\n } catch { /* import.meta.env not available in this runtime */ }\n\n envCache.set(key, undefined);\n return undefined;\n}\n\n/* ==========================================================================\n requireEnv\n ========================================================================== */\n\nexport function requireEnv(key: string): string {\n const val = getEnv(key);\n if (val === undefined) {\n biniLogger.error(\n `Missing required environment variable: \"${key}\"\\n` +\n ` ${COLORS.DIM}→ In development: add it to your .env file.${COLORS.RESET}\\n` +\n ` ${COLORS.DIM}→ In production: set it in your hosting dashboard.${COLORS.RESET}`,\n );\n throw new Error(`[bini-env] Missing required environment variable: \"${key}\"`);\n }\n return val;\n}\n\n/* ==========================================================================\n loadEnv\n - Idempotent: repeated awaits are safe; concurrent calls share one promise.\n - A failed load resets _envLoaded so a retry is possible (e.g. transient\n file-access race on startup).\n ========================================================================== */\n\nlet _envLoaded = false;\nlet _loadPromise: Promise<void> | null = null;\n\nexport async function loadEnv(projectRoot?: string): Promise<void> {\n if (_envLoaded) return;\n if (_loadPromise) return _loadPromise;\n\n _loadPromise = (async () => {\n try {\n if (getDeno()) return; // Deno — env already available via Deno.env\n if (!hasProcessEnv()) return;\n\n const root = projectRoot ?? process.cwd();\n const nodeEnv = process.env.NODE_ENV ?? 'production';\n\n // Load order: lowest → highest priority (later files override earlier ones)\n const envFiles = [\n '.env',\n `.env.${nodeEnv}`,\n `.env.${nodeEnv}.local`,\n '.env.local',\n ];\n\n const dotenv = await import('dotenv');\n\n for (const file of envFiles) {\n const filePath = path.join(root, file);\n try {\n await fs.promises.access(filePath, fs.constants.R_OK);\n dotenv.config({ path: filePath, override: true });\n } catch { /* file absent — skip */ }\n }\n\n // Invalidate cache so newly loaded vars are picked up by getEnv\n envCache.clear();\n _envLoaded = true;\n\n } catch (error) {\n // Surface all load failures — silent swallowing hides misconfigured\n // deployments that are impossible to debug after the fact.\n biniLogger.error('Failed to load .env file', error);\n // Do NOT set _envLoaded — allow a retry on the next call.\n } finally {\n _loadPromise = null;\n }\n })();\n\n return _loadPromise;\n}\n\n/* ==========================================================================\n detectEnvFiles\n Cache key includes both root and NODE_ENV so changes in either invalidate.\n ========================================================================== */\n\nlet _envFilesCache: DetectedEnvFile[] | null = null;\nlet _cacheKey = '';\n\nexport function detectEnvFiles(projectRoot: string = process.cwd()): DetectedEnvFile[] {\n const nodeEnv = process.env.NODE_ENV ?? 'production';\n const cacheKey = `${projectRoot}:${nodeEnv}`;\n if (_envFilesCache && _cacheKey === cacheKey) return _envFilesCache;\n\n const candidates = [\n '.env.local',\n `.env.${nodeEnv}.local`,\n `.env.${nodeEnv}`,\n '.env',\n ];\n\n const found: DetectedEnvFile[] = [];\n for (const file of candidates) {\n try {\n const filePath = path.join(projectRoot, file);\n if (fs.existsSync(filePath)) found.push({ name: file, path: filePath });\n } catch { /* skip unreadable paths */ }\n }\n\n _envFilesCache = found;\n _cacheKey = cacheKey;\n return found;\n}\n\n/* ==========================================================================\n Vite plugin helpers\n ========================================================================== */\n\nfunction clearLine(): void {\n if (process.stdout.isTTY) process.stdout.write('\\x1b[2K\\r');\n}\n\nfunction printResolvedUrls(\n urls: { local: string[]; network: string[] } | null | undefined,\n): void {\n if (!urls) return;\n if (urls.local.length > 0) {\n originalConsoleLog(\n ` ${COLORS.GREEN}➜${COLORS.RESET} Local: ${COLORS.CYAN}${urls.local[0]}${COLORS.RESET}`,\n );\n }\n if (urls.network.length > 0) {\n originalConsoleLog(\n ` ${COLORS.GREEN}➜${COLORS.RESET} Network: ${COLORS.CYAN}${urls.network[0]}${COLORS.RESET}`,\n );\n }\n}\n\ntype ServerLike = ViteDevServer | PreviewServer;\n\n/**\n * Patches server.printUrls to emit the Bini.js header and detected env files,\n * then delegates to the original printUrls or our own URL renderer depending\n * on whether clearViteHeader is enabled.\n * Guards against double-invocation with the `started` flag.\n */\nfunction patchPrintUrls(\n server : ServerLike,\n mode : 'dev' | 'preview',\n logo : string,\n clearViteHeader: boolean,\n getRoot : () => string,\n showEnvFiles: boolean,\n): void {\n let started = false;\n const originalPrintUrls = server.printUrls.bind(server);\n\n server.printUrls = () => {\n if (started) return;\n started = true;\n\n if (clearViteHeader) clearLine();\n originalConsoleLog(`\\n ${COLORS.CYAN}${logo} Bini.js${COLORS.RESET} (${mode})`);\n\n if (showEnvFiles) {\n const found = detectEnvFiles(getRoot());\n if (found.length > 0) {\n originalConsoleLog(\n ` ${COLORS.GREEN}➜${COLORS.RESET} Environments: ${found.map(f => f.name).join(', ')}`,\n );\n }\n }\n\n if (clearViteHeader) {\n printResolvedUrls(server.resolvedUrls);\n } else {\n originalPrintUrls();\n }\n };\n}\n\n/* ==========================================================================\n Vite plugin\n ========================================================================== */\n\nexport function biniEnv(options: Readonly<BiniEnvPluginOptions> = {}): Plugin {\n if (options.enabled === false) {\n return { name: 'vite-plugin-bini-env' };\n }\n\n const { clearViteHeader, logo, envPrefix, loadInPreview } = {\n ...DEFAULT_OPTIONS,\n ...options,\n };\n\n let resolvedConfig: ResolvedConfig;\n const getRoot = () => resolvedConfig?.root ?? process.cwd();\n\n return {\n name: 'vite-plugin-bini-env',\n\n config(): UserConfig {\n return { envPrefix };\n },\n\n configResolved(cfg: ResolvedConfig) {\n resolvedConfig = cfg;\n },\n\n configureServer(server) {\n // Trigger env load once the HTTP server is up, or defer if middleware-only\n const triggerLoad = () => void loadEnv(getRoot());\n if (server.httpServer) {\n server.httpServer.once('listening', triggerLoad);\n } else {\n defer(triggerLoad);\n }\n\n // Only patch printUrls when we actually need to change the output\n if (clearViteHeader || logo !== BINI_LOGO) {\n patchPrintUrls(server, 'dev', logo, clearViteHeader, getRoot, true);\n }\n },\n\n configurePreviewServer(server) {\n if (loadInPreview) {\n const triggerLoad = () => void loadEnv(getRoot());\n if (server.httpServer) {\n server.httpServer.once('listening', triggerLoad);\n } else {\n defer(triggerLoad);\n }\n }\n\n if (clearViteHeader || logo !== BINI_LOGO) {\n patchPrintUrls(server, 'preview', logo, clearViteHeader, getRoot, loadInPreview);\n }\n },\n };\n}\n\nexport type { Plugin } from 'vite';"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// bini-env/src/index.ts\nimport type { Plugin, PreviewServer, ResolvedConfig, UserConfig, ViteDevServer } from 'vite';\n\n/* ==========================================================================\n Runtime detection — must run before anything else\n ========================================================================== */\n\nfunction isNodeLike(): boolean {\n return (\n typeof process !== 'undefined' &&\n !!process.env &&\n typeof process.versions === 'object' &&\n // Edge runtimes (Vercel, Cloudflare) expose a minimal `process` but not\n // `process.versions.node`. Checking for it keeps us out of edge bundles.\n (typeof process.versions.node === 'string' ||\n // Bun sets process.versions.bun\n typeof (process.versions as Record<string, unknown>).bun === 'string')\n );\n}\n\nfunction isDenoRuntime(): boolean {\n return typeof (globalThis as unknown as { Deno?: unknown }).Deno !== 'undefined';\n}\n\n/* ==========================================================================\n Capture originals FIRST — before any patching occurs\n ========================================================================== */\n\nconst originalConsoleLog = console.log.bind(console);\nconst originalConsoleError = console.error.bind(console);\n\n/* ==========================================================================\n Default NODE_ENV — must run before anything else\n ========================================================================== */\n\nif (isNodeLike() && !process.env.NODE_ENV) {\n process.env.NODE_ENV = 'production';\n}\n\n/* ==========================================================================\n DOTENV LOG SUPPRESSION\n Patched once at module load; subsequent calls are no-ops.\n ========================================================================== */\n\nlet _suppressionApplied = false;\n\nexport function suppressDotenvLogsGlobally(): void {\n if (_suppressionApplied) return;\n _suppressionApplied = true;\n\n if (isNodeLike()) {\n process.env.DOTENV_QUIET = 'true';\n }\n\n const isDotenvNoise = (...args: unknown[]): boolean => {\n const msg = args.join(' ');\n return (\n msg.includes('[dotenv@') ||\n msg.includes('injected env') ||\n msg.includes('injecting env')\n );\n };\n\n console.log = (...args: unknown[]) => {\n if (!isDotenvNoise(...args)) originalConsoleLog(...args);\n };\n\n console.error = (...args: unknown[]) => {\n if (!isDotenvNoise(...args)) originalConsoleError(...args);\n };\n}\n\n// Apply once at module load\nsuppressDotenvLogsGlobally();\n\n/* ==========================================================================\n Cross-runtime type declarations\n ========================================================================== */\n\ninterface DenoEnv {\n get(key: string): string | undefined;\n}\ninterface DenoNamespace {\n env: DenoEnv;\n}\n\n/* ==========================================================================\n Public types\n ========================================================================== */\n\nexport interface BiniEnvPluginOptions {\n readonly enabled?: boolean;\n readonly clearViteHeader?: boolean;\n readonly logo?: string;\n readonly envPrefix?: string | string[];\n readonly loadInPreview?: boolean;\n /** @deprecated Suppression is always applied at module load; this option is ignored. */\n readonly suppressDotenvLogs?: boolean;\n}\n\nexport interface DetectedEnvFile {\n readonly name: string;\n readonly path: string;\n}\n\n/* ==========================================================================\n Constants\n ========================================================================== */\n\nconst BINI_LOGO = 'ß';\nconst DEFAULT_ENV_PREFIX = ['BINI_', 'VITE_'] as const;\n\nconst DEFAULT_OPTIONS = Object.freeze({\n enabled : true,\n clearViteHeader: true,\n logo : BINI_LOGO,\n envPrefix : [...DEFAULT_ENV_PREFIX],\n loadInPreview : true,\n} satisfies Omit<Required<BiniEnvPluginOptions>, 'suppressDotenvLogs'>);\n\nconst enum COLORS {\n CYAN = '\\x1b[36m',\n RESET = '\\x1b[0m',\n GREEN = '\\x1b[32m',\n YELLOW = '\\x1b[33m',\n RED = '\\x1b[31m',\n BOLD = '\\x1b[1m',\n DIM = '\\x1b[2m',\n}\n\nconst envCache = new Map<string, string | undefined>();\n\n/* ==========================================================================\n Standalone logger\n ========================================================================== */\n\nfunction timestamp(): string {\n return `${COLORS.DIM}${new Date().toLocaleTimeString('en-US', { hour12: false })}${COLORS.RESET}`;\n}\n\nexport const biniLogger = {\n info(msg: string): void {\n originalConsoleLog(\n `${timestamp()} ${COLORS.CYAN}${COLORS.BOLD}[bini-env]${COLORS.RESET} ${msg}`,\n );\n },\n warn(msg: string): void {\n originalConsoleError(\n `${timestamp()} ${COLORS.YELLOW}${COLORS.BOLD}(!) [bini-env]${COLORS.RESET} ${COLORS.YELLOW}${msg}${COLORS.RESET}`,\n );\n },\n error(msg: string, err?: unknown): void {\n const detail = err instanceof Error\n ? `\\n ${COLORS.DIM}${err.message}${COLORS.RESET}`\n : '';\n originalConsoleError(\n `${timestamp()} ${COLORS.RED}${COLORS.BOLD}[bini-env] error${COLORS.RESET} ${msg}${detail}`,\n );\n },\n} as const;\n\n/* ==========================================================================\n Runtime helpers\n ========================================================================== */\n\nfunction getDeno(): DenoNamespace | undefined {\n return (globalThis as unknown as { Deno?: DenoNamespace }).Deno;\n}\n\n/** Schedule a task compatible with Node, Bun, Deno, and edge runtimes. */\nfunction defer(fn: () => void): void {\n if (typeof setImmediate !== 'undefined') {\n setImmediate(fn);\n } else {\n Promise.resolve().then(fn);\n }\n}\n\n/* ==========================================================================\n getEnv\n ========================================================================== */\n\nexport function getEnv(key: string): string | undefined {\n if (envCache.has(key)) return envCache.get(key);\n\n // 1. Deno runtime\n const deno = getDeno();\n if (deno) {\n try {\n const value = deno.env.get(key);\n if (value !== undefined) {\n envCache.set(key, value);\n return value;\n }\n } catch { /* fall through */ }\n }\n\n // 2. Node.js / Bun / Edge (process.env is available on most edge runtimes too)\n if (typeof process !== 'undefined' && process.env) {\n const value = process.env[key];\n if (value !== undefined) {\n envCache.set(key, value);\n return value;\n }\n }\n\n // 3. Vite client (import.meta.env) — also checks BINI_ and VITE_ prefixed variants\n try {\n const metaEnv = import.meta.env as Record<string, string | undefined> | undefined;\n if (metaEnv) {\n for (const candidate of [key, `BINI_${key}`, `VITE_${key}`]) {\n if (metaEnv[candidate] !== undefined) {\n envCache.set(key, metaEnv[candidate]);\n return metaEnv[candidate];\n }\n }\n }\n } catch { /* import.meta.env not available in this runtime */ }\n\n envCache.set(key, undefined);\n return undefined;\n}\n\n/* ==========================================================================\n requireEnv\n ========================================================================== */\n\nexport function requireEnv(key: string): string {\n const val = getEnv(key);\n if (val === undefined) {\n biniLogger.error(\n `Missing required environment variable: \"${key}\"\\n` +\n ` ${COLORS.DIM}→ In development: add it to your .env file.${COLORS.RESET}\\n` +\n ` ${COLORS.DIM}→ In production: set it in your hosting dashboard.${COLORS.RESET}`,\n );\n throw new Error(`[bini-env] Missing required environment variable: \"${key}\"`);\n }\n return val;\n}\n\n/* ==========================================================================\n loadEnv\n - Only runs on Node-like runtimes (Node.js, Bun).\n - Edge runtimes and Deno skip entirely — they get vars from the host.\n - Idempotent; concurrent calls share one promise.\n ========================================================================== */\n\nlet _envLoaded = false;\nlet _loadPromise: Promise<void> | null = null;\n\nexport async function loadEnv(projectRoot?: string): Promise<void> {\n if (_envLoaded) return;\n if (_loadPromise) return _loadPromise;\n\n _loadPromise = (async () => {\n try {\n // Deno and edge runtimes do not use .env files — vars are injected by host\n if (isDenoRuntime() || !isNodeLike()) return;\n\n const root = projectRoot ?? process.cwd();\n const nodeEnv = process.env.NODE_ENV ?? 'production';\n\n // Load order: lowest → highest priority (later files override earlier ones)\n const envFiles = [\n '.env',\n `.env.${nodeEnv}`,\n `.env.${nodeEnv}.local`,\n '.env.local',\n ];\n\n // Dynamic import keeps `dotenv` and `fs`/`path` out of edge bundles entirely.\n // Bundlers that trace static imports (esbuild, Rollup) will NOT follow\n // a runtime-gated dynamic import when tree-shaking is enabled.\n const [dotenvMod, fsMod, pathMod] = await Promise.all([\n import('dotenv'),\n import('node:fs'),\n import('node:path'),\n ]);\n const dotenv = dotenvMod;\n const fs = fsMod.default ?? fsMod;\n const path = pathMod.default ?? pathMod;\n\n for (const file of envFiles) {\n const filePath = path.join(root, file);\n try {\n await fs.promises.access(filePath, fs.constants.R_OK);\n dotenv.config({ path: filePath, override: true });\n } catch { /* file absent — skip */ }\n }\n\n // Invalidate cache so newly loaded vars are picked up by getEnv\n envCache.clear();\n _envLoaded = true;\n\n } catch (error) {\n biniLogger.error('Failed to load .env file', error);\n // Do NOT set _envLoaded — allow a retry on the next call.\n } finally {\n _loadPromise = null;\n }\n })();\n\n return _loadPromise;\n}\n\n/* ==========================================================================\n detectEnvFiles\n Node-only utility used by the Vite plugin (build-time only, never edge).\n ========================================================================== */\n\nlet _envFilesCache: DetectedEnvFile[] | null = null;\nlet _cacheKey = '';\n\nexport function detectEnvFiles(projectRoot?: string): DetectedEnvFile[] {\n // Guard: this function uses fs synchronously; bail on non-Node runtimes.\n if (!isNodeLike()) return [];\n\n const root = projectRoot ?? process.cwd();\n const nodeEnv = process.env.NODE_ENV ?? 'production';\n const cacheKey = `${root}:${nodeEnv}`;\n if (_envFilesCache && _cacheKey === cacheKey) return _envFilesCache;\n\n // Inline the fs/path usage so no top-level import is needed.\n // This function is only ever called from the Vite plugin (configureServer /\n // configurePreviewServer), which runs in Node — never in an edge bundle.\n let fsSync: typeof import('fs');\n let pathMod: typeof import('path');\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n fsSync = require('node:fs');\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n pathMod = require('node:path');\n } catch {\n return [];\n }\n\n const candidates = [\n '.env.local',\n `.env.${nodeEnv}.local`,\n `.env.${nodeEnv}`,\n '.env',\n ];\n\n const found: DetectedEnvFile[] = [];\n for (const file of candidates) {\n try {\n const filePath = pathMod.join(root, file);\n if (fsSync.existsSync(filePath)) found.push({ name: file, path: filePath });\n } catch { /* skip unreadable paths */ }\n }\n\n _envFilesCache = found;\n _cacheKey = cacheKey;\n return found;\n}\n\n/* ==========================================================================\n Vite plugin helpers\n ========================================================================== */\n\nfunction clearLine(): void {\n if (typeof process !== 'undefined' && process.stdout?.isTTY) {\n process.stdout.write('\\x1b[2K\\r');\n }\n}\n\nfunction printResolvedUrls(\n urls: { local: string[]; network: string[] } | null | undefined,\n): void {\n if (!urls) return;\n if (urls.local.length > 0) {\n originalConsoleLog(\n ` ${COLORS.GREEN}➜${COLORS.RESET} Local: ${COLORS.CYAN}${urls.local[0]}${COLORS.RESET}`,\n );\n }\n if (urls.network.length > 0) {\n originalConsoleLog(\n ` ${COLORS.GREEN}➜${COLORS.RESET} Network: ${COLORS.CYAN}${urls.network[0]}${COLORS.RESET}`,\n );\n }\n}\n\ntype ServerLike = ViteDevServer | PreviewServer;\n\nfunction patchPrintUrls(\n server : ServerLike,\n mode : 'dev' | 'preview',\n logo : string,\n clearViteHeader: boolean,\n getRoot : () => string,\n showEnvFiles : boolean,\n): void {\n let started = false;\n const originalPrintUrls = server.printUrls.bind(server);\n\n server.printUrls = () => {\n if (started) return;\n started = true;\n\n if (clearViteHeader) clearLine();\n originalConsoleLog(`\\n ${COLORS.CYAN}${logo} Bini.js${COLORS.RESET} (${mode})`);\n\n if (showEnvFiles) {\n const found = detectEnvFiles(getRoot());\n if (found.length > 0) {\n originalConsoleLog(\n ` ${COLORS.GREEN}➜${COLORS.RESET} Environments: ${found.map(f => f.name).join(', ')}`,\n );\n }\n }\n\n if (clearViteHeader) {\n printResolvedUrls(server.resolvedUrls);\n } else {\n originalPrintUrls();\n }\n };\n}\n\n/* ==========================================================================\n Vite plugin\n ========================================================================== */\n\nexport function biniEnv(options: Readonly<BiniEnvPluginOptions> = {}): Plugin {\n if (options.enabled === false) {\n return { name: 'vite-plugin-bini-env' };\n }\n\n const { clearViteHeader, logo, envPrefix, loadInPreview } = {\n ...DEFAULT_OPTIONS,\n ...options,\n };\n\n let resolvedConfig: ResolvedConfig;\n const getRoot = () => resolvedConfig?.root ?? process.cwd();\n\n return {\n name: 'vite-plugin-bini-env',\n\n config(): UserConfig {\n return { envPrefix };\n },\n\n configResolved(cfg: ResolvedConfig) {\n resolvedConfig = cfg;\n },\n\n configureServer(server) {\n const triggerLoad = () => void loadEnv(getRoot());\n if (server.httpServer) {\n server.httpServer.once('listening', triggerLoad);\n } else {\n defer(triggerLoad);\n }\n\n // Watch for new or changed .env files and restart the dev server so the\n // fresh variables are picked up. Chokidar (bundled with Vite) handles the\n // add/change events; we reset _envLoaded so loadEnv re-reads on restart.\n const envGlob = `${getRoot()}/.env*`;\n server.watcher.add(envGlob);\n\n const onEnvChange = (filePath: string) => {\n // Ignore editor swap/temp files (.env.swp, .env~, etc.)\n if (/\\.(swp|swo|bak|tmp)$|~$/.test(filePath)) return;\n\n biniLogger.info(\n `env file ${filePath.replace(getRoot() + '/', '')} changed — restarting server`,\n );\n\n // Reset load state so the restarted server re-reads all .env files\n _envLoaded = false;\n _loadPromise = null;\n envCache.clear();\n _envFilesCache = null;\n\n void server.restart();\n };\n\n server.watcher.on('add', onEnvChange);\n server.watcher.on('change', onEnvChange);\n\n // Remove listeners when the server closes so they don't stack across\n // restarts — Vite calls configureServer again on each restart.\n server.httpServer?.once('close', () => {\n server.watcher.off('add', onEnvChange);\n server.watcher.off('change', onEnvChange);\n });\n\n if (clearViteHeader || logo !== BINI_LOGO) {\n patchPrintUrls(server, 'dev', logo, clearViteHeader, getRoot, true);\n }\n },\n\n configurePreviewServer(server) {\n if (loadInPreview) {\n const triggerLoad = () => void loadEnv(getRoot());\n if (server.httpServer) {\n server.httpServer.once('listening', triggerLoad);\n } else {\n defer(triggerLoad);\n }\n }\n\n if (clearViteHeader || logo !== BINI_LOGO) {\n patchPrintUrls(server, 'preview', logo, clearViteHeader, getRoot, loadInPreview);\n }\n },\n };\n}\n\nexport type { Plugin } from 'vite';"]}
package/dist/index.mjs CHANGED
@@ -1,17 +1,30 @@
1
- import fs from 'fs';
2
- import path from 'path';
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
3
7
 
4
8
  // src/index.ts
9
+ function isNodeLike() {
10
+ return typeof process !== "undefined" && !!process.env && typeof process.versions === "object" && // Edge runtimes (Vercel, Cloudflare) expose a minimal `process` but not
11
+ // `process.versions.node`. Checking for it keeps us out of edge bundles.
12
+ (typeof process.versions.node === "string" || // Bun sets process.versions.bun
13
+ typeof process.versions.bun === "string");
14
+ }
15
+ function isDenoRuntime() {
16
+ return typeof globalThis.Deno !== "undefined";
17
+ }
5
18
  var originalConsoleLog = console.log.bind(console);
6
19
  var originalConsoleError = console.error.bind(console);
7
- if (typeof process !== "undefined" && process.env && !process.env.NODE_ENV) {
20
+ if (isNodeLike() && !process.env.NODE_ENV) {
8
21
  process.env.NODE_ENV = "production";
9
22
  }
10
23
  var _suppressionApplied = false;
11
24
  function suppressDotenvLogsGlobally() {
12
25
  if (_suppressionApplied) return;
13
26
  _suppressionApplied = true;
14
- if (typeof process !== "undefined" && process.env) {
27
+ if (isNodeLike()) {
15
28
  process.env.DOTENV_QUIET = "true";
16
29
  }
17
30
  const isDotenvNoise = (...args) => {
@@ -61,9 +74,6 @@ var biniLogger = {
61
74
  function getDeno() {
62
75
  return globalThis.Deno;
63
76
  }
64
- function hasProcessEnv() {
65
- return typeof process !== "undefined" && !!process.env;
66
- }
67
77
  function defer(fn) {
68
78
  if (typeof setImmediate !== "undefined") {
69
79
  setImmediate(fn);
@@ -84,7 +94,7 @@ function getEnv(key) {
84
94
  } catch {
85
95
  }
86
96
  }
87
- if (hasProcessEnv()) {
97
+ if (typeof process !== "undefined" && process.env) {
88
98
  const value = process.env[key];
89
99
  if (value !== void 0) {
90
100
  envCache.set(key, value);
@@ -125,8 +135,7 @@ async function loadEnv(projectRoot) {
125
135
  if (_loadPromise) return _loadPromise;
126
136
  _loadPromise = (async () => {
127
137
  try {
128
- if (getDeno()) return;
129
- if (!hasProcessEnv()) return;
138
+ if (isDenoRuntime() || !isNodeLike()) return;
130
139
  const root = projectRoot ?? process.cwd();
131
140
  const nodeEnv = process.env.NODE_ENV ?? "production";
132
141
  const envFiles = [
@@ -135,7 +144,14 @@ async function loadEnv(projectRoot) {
135
144
  `.env.${nodeEnv}.local`,
136
145
  ".env.local"
137
146
  ];
138
- const dotenv = await import('dotenv');
147
+ const [dotenvMod, fsMod, pathMod] = await Promise.all([
148
+ import('dotenv'),
149
+ import('fs'),
150
+ import('path')
151
+ ]);
152
+ const dotenv = dotenvMod;
153
+ const fs = fsMod.default ?? fsMod;
154
+ const path = pathMod.default ?? pathMod;
139
155
  for (const file of envFiles) {
140
156
  const filePath = path.join(root, file);
141
157
  try {
@@ -156,10 +172,20 @@ async function loadEnv(projectRoot) {
156
172
  }
157
173
  var _envFilesCache = null;
158
174
  var _cacheKey = "";
159
- function detectEnvFiles(projectRoot = process.cwd()) {
175
+ function detectEnvFiles(projectRoot) {
176
+ if (!isNodeLike()) return [];
177
+ const root = projectRoot ?? process.cwd();
160
178
  const nodeEnv = process.env.NODE_ENV ?? "production";
161
- const cacheKey = `${projectRoot}:${nodeEnv}`;
179
+ const cacheKey = `${root}:${nodeEnv}`;
162
180
  if (_envFilesCache && _cacheKey === cacheKey) return _envFilesCache;
181
+ let fsSync;
182
+ let pathMod;
183
+ try {
184
+ fsSync = __require("fs");
185
+ pathMod = __require("path");
186
+ } catch {
187
+ return [];
188
+ }
163
189
  const candidates = [
164
190
  ".env.local",
165
191
  `.env.${nodeEnv}.local`,
@@ -169,8 +195,8 @@ function detectEnvFiles(projectRoot = process.cwd()) {
169
195
  const found = [];
170
196
  for (const file of candidates) {
171
197
  try {
172
- const filePath = path.join(projectRoot, file);
173
- if (fs.existsSync(filePath)) found.push({ name: file, path: filePath });
198
+ const filePath = pathMod.join(root, file);
199
+ if (fsSync.existsSync(filePath)) found.push({ name: file, path: filePath });
174
200
  } catch {
175
201
  }
176
202
  }
@@ -179,7 +205,9 @@ function detectEnvFiles(projectRoot = process.cwd()) {
179
205
  return found;
180
206
  }
181
207
  function clearLine() {
182
- if (process.stdout.isTTY) process.stdout.write("\x1B[2K\r");
208
+ if (typeof process !== "undefined" && process.stdout?.isTTY) {
209
+ process.stdout.write("\x1B[2K\r");
210
+ }
183
211
  }
184
212
  function printResolvedUrls(urls) {
185
213
  if (!urls) return;
@@ -243,6 +271,25 @@ function biniEnv(options = {}) {
243
271
  } else {
244
272
  defer(triggerLoad);
245
273
  }
274
+ const envGlob = `${getRoot()}/.env*`;
275
+ server.watcher.add(envGlob);
276
+ const onEnvChange = (filePath) => {
277
+ if (/\.(swp|swo|bak|tmp)$|~$/.test(filePath)) return;
278
+ biniLogger.info(
279
+ `env file ${filePath.replace(getRoot() + "/", "")} changed \u2014 restarting server`
280
+ );
281
+ _envLoaded = false;
282
+ _loadPromise = null;
283
+ envCache.clear();
284
+ _envFilesCache = null;
285
+ void server.restart();
286
+ };
287
+ server.watcher.on("add", onEnvChange);
288
+ server.watcher.on("change", onEnvChange);
289
+ server.httpServer?.once("close", () => {
290
+ server.watcher.off("add", onEnvChange);
291
+ server.watcher.off("change", onEnvChange);
292
+ });
246
293
  if (clearViteHeader || logo !== BINI_LOGO) {
247
294
  patchPrintUrls(server, "dev", logo, clearViteHeader, getRoot, true);
248
295
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["// bini-env/src/index.ts\nimport fs from 'fs';\nimport path from 'path';\nimport type { Plugin, PreviewServer, ResolvedConfig, UserConfig, ViteDevServer } from 'vite';\n\n/* ==========================================================================\n Capture originals FIRST — before any patching occurs\n ========================================================================== */\n\nconst originalConsoleLog = console.log.bind(console);\nconst originalConsoleError = console.error.bind(console);\n\n/* ==========================================================================\n Default NODE_ENV — must run before anything else\n ========================================================================== */\n\nif (typeof process !== 'undefined' && process.env && !process.env.NODE_ENV) {\n process.env.NODE_ENV = 'production';\n}\n\n/* ==========================================================================\n DOTENV LOG SUPPRESSION\n Patched once at module load; subsequent calls are no-ops.\n ========================================================================== */\n\nlet _suppressionApplied = false;\n\nexport function suppressDotenvLogsGlobally(): void {\n if (_suppressionApplied) return;\n _suppressionApplied = true;\n\n if (typeof process !== 'undefined' && process.env) {\n process.env.DOTENV_QUIET = 'true';\n }\n\n const isDotenvNoise = (...args: unknown[]): boolean => {\n const msg = args.join(' ');\n return (\n msg.includes('[dotenv@') ||\n msg.includes('injected env') ||\n msg.includes('injecting env')\n );\n };\n\n console.log = (...args: unknown[]) => {\n if (!isDotenvNoise(...args)) originalConsoleLog(...args);\n };\n\n console.error = (...args: unknown[]) => {\n if (!isDotenvNoise(...args)) originalConsoleError(...args);\n };\n}\n\n// Apply once at module load\nsuppressDotenvLogsGlobally();\n\n/* ==========================================================================\n Cross-runtime type declarations\n ========================================================================== */\n\ninterface DenoEnv {\n get(key: string): string | undefined;\n}\ninterface DenoNamespace {\n env: DenoEnv;\n}\n\n/* ==========================================================================\n Public types\n ========================================================================== */\n\nexport interface BiniEnvPluginOptions {\n readonly enabled?: boolean;\n readonly clearViteHeader?: boolean;\n readonly logo?: string;\n readonly envPrefix?: string | string[];\n readonly loadInPreview?: boolean;\n /** @deprecated Suppression is always applied at module load; this option is ignored. */\n readonly suppressDotenvLogs?: boolean;\n}\n\nexport interface DetectedEnvFile {\n readonly name: string;\n readonly path: string;\n}\n\n/* ==========================================================================\n Constants\n ========================================================================== */\n\nconst BINI_LOGO = 'ß';\nconst DEFAULT_ENV_PREFIX = ['BINI_', 'VITE_'] as const;\n\n// suppressDotenvLogs intentionally omitted — it is deprecated and ignored\nconst DEFAULT_OPTIONS = Object.freeze({\n enabled : true,\n clearViteHeader: true,\n logo : BINI_LOGO,\n envPrefix : [...DEFAULT_ENV_PREFIX],\n loadInPreview : true,\n} satisfies Omit<Required<BiniEnvPluginOptions>, 'suppressDotenvLogs'>);\n\nconst enum COLORS {\n CYAN = '\\x1b[36m',\n RESET = '\\x1b[0m',\n GREEN = '\\x1b[32m',\n YELLOW = '\\x1b[33m',\n RED = '\\x1b[31m',\n BOLD = '\\x1b[1m',\n DIM = '\\x1b[2m',\n}\n\nconst envCache = new Map<string, string | undefined>();\n\n/* ==========================================================================\n Standalone logger\n Used for messages emitted outside plugin context (loadEnv, requireEnv,\n standalone getEnv calls) where resolvedConfig.logger is not yet available.\n\n Format mirrors Vite exactly:\n info → 12:00:00 [bini-env] … cyan bold prefix\n warn → 12:00:00 (!) [bini-env] … yellow bold, Vite's (!) convention\n error → 12:00:00 [bini-env] error … red bold, optional dim detail line\n ========================================================================== */\n\nfunction timestamp(): string {\n return `${COLORS.DIM}${new Date().toLocaleTimeString('en-US', { hour12: false })}${COLORS.RESET}`;\n}\n\nexport const biniLogger = {\n info(msg: string): void {\n originalConsoleLog(\n `${timestamp()} ${COLORS.CYAN}${COLORS.BOLD}[bini-env]${COLORS.RESET} ${msg}`,\n );\n },\n warn(msg: string): void {\n originalConsoleError(\n `${timestamp()} ${COLORS.YELLOW}${COLORS.BOLD}(!) [bini-env]${COLORS.RESET} ${COLORS.YELLOW}${msg}${COLORS.RESET}`,\n );\n },\n error(msg: string, err?: unknown): void {\n const detail = err instanceof Error\n ? `\\n ${COLORS.DIM}${err.message}${COLORS.RESET}`\n : '';\n originalConsoleError(\n `${timestamp()} ${COLORS.RED}${COLORS.BOLD}[bini-env] error${COLORS.RESET} ${msg}${detail}`,\n );\n },\n} as const;\n\n/* ==========================================================================\n Runtime helpers\n ========================================================================== */\n\nfunction getDeno(): DenoNamespace | undefined {\n return (globalThis as unknown as { Deno?: DenoNamespace }).Deno;\n}\n\nfunction hasProcessEnv(): boolean {\n return typeof process !== 'undefined' && !!process.env;\n}\n\n/** Schedule a task compatible with Node, Bun, Deno, and edge runtimes. */\nfunction defer(fn: () => void): void {\n if (typeof setImmediate !== 'undefined') {\n setImmediate(fn);\n } else {\n Promise.resolve().then(fn);\n }\n}\n\n/* ==========================================================================\n getEnv\n ========================================================================== */\n\nexport function getEnv(key: string): string | undefined {\n if (envCache.has(key)) return envCache.get(key);\n\n // 1. Deno runtime\n const deno = getDeno();\n if (deno) {\n try {\n const value = deno.env.get(key);\n if (value !== undefined) {\n envCache.set(key, value);\n return value;\n }\n } catch { /* fall through */ }\n }\n\n // 2. Node.js / Bun\n if (hasProcessEnv()) {\n const value = process.env[key];\n if (value !== undefined) {\n envCache.set(key, value);\n return value;\n }\n }\n\n // 3. Vite client (import.meta.env) — also checks BINI_ and VITE_ prefixed variants\n try {\n const metaEnv = import.meta.env as Record<string, string | undefined> | undefined;\n if (metaEnv) {\n for (const candidate of [key, `BINI_${key}`, `VITE_${key}`]) {\n if (metaEnv[candidate] !== undefined) {\n envCache.set(key, metaEnv[candidate]);\n return metaEnv[candidate];\n }\n }\n }\n } catch { /* import.meta.env not available in this runtime */ }\n\n envCache.set(key, undefined);\n return undefined;\n}\n\n/* ==========================================================================\n requireEnv\n ========================================================================== */\n\nexport function requireEnv(key: string): string {\n const val = getEnv(key);\n if (val === undefined) {\n biniLogger.error(\n `Missing required environment variable: \"${key}\"\\n` +\n ` ${COLORS.DIM}→ In development: add it to your .env file.${COLORS.RESET}\\n` +\n ` ${COLORS.DIM}→ In production: set it in your hosting dashboard.${COLORS.RESET}`,\n );\n throw new Error(`[bini-env] Missing required environment variable: \"${key}\"`);\n }\n return val;\n}\n\n/* ==========================================================================\n loadEnv\n - Idempotent: repeated awaits are safe; concurrent calls share one promise.\n - A failed load resets _envLoaded so a retry is possible (e.g. transient\n file-access race on startup).\n ========================================================================== */\n\nlet _envLoaded = false;\nlet _loadPromise: Promise<void> | null = null;\n\nexport async function loadEnv(projectRoot?: string): Promise<void> {\n if (_envLoaded) return;\n if (_loadPromise) return _loadPromise;\n\n _loadPromise = (async () => {\n try {\n if (getDeno()) return; // Deno — env already available via Deno.env\n if (!hasProcessEnv()) return;\n\n const root = projectRoot ?? process.cwd();\n const nodeEnv = process.env.NODE_ENV ?? 'production';\n\n // Load order: lowest → highest priority (later files override earlier ones)\n const envFiles = [\n '.env',\n `.env.${nodeEnv}`,\n `.env.${nodeEnv}.local`,\n '.env.local',\n ];\n\n const dotenv = await import('dotenv');\n\n for (const file of envFiles) {\n const filePath = path.join(root, file);\n try {\n await fs.promises.access(filePath, fs.constants.R_OK);\n dotenv.config({ path: filePath, override: true });\n } catch { /* file absent — skip */ }\n }\n\n // Invalidate cache so newly loaded vars are picked up by getEnv\n envCache.clear();\n _envLoaded = true;\n\n } catch (error) {\n // Surface all load failures — silent swallowing hides misconfigured\n // deployments that are impossible to debug after the fact.\n biniLogger.error('Failed to load .env file', error);\n // Do NOT set _envLoaded — allow a retry on the next call.\n } finally {\n _loadPromise = null;\n }\n })();\n\n return _loadPromise;\n}\n\n/* ==========================================================================\n detectEnvFiles\n Cache key includes both root and NODE_ENV so changes in either invalidate.\n ========================================================================== */\n\nlet _envFilesCache: DetectedEnvFile[] | null = null;\nlet _cacheKey = '';\n\nexport function detectEnvFiles(projectRoot: string = process.cwd()): DetectedEnvFile[] {\n const nodeEnv = process.env.NODE_ENV ?? 'production';\n const cacheKey = `${projectRoot}:${nodeEnv}`;\n if (_envFilesCache && _cacheKey === cacheKey) return _envFilesCache;\n\n const candidates = [\n '.env.local',\n `.env.${nodeEnv}.local`,\n `.env.${nodeEnv}`,\n '.env',\n ];\n\n const found: DetectedEnvFile[] = [];\n for (const file of candidates) {\n try {\n const filePath = path.join(projectRoot, file);\n if (fs.existsSync(filePath)) found.push({ name: file, path: filePath });\n } catch { /* skip unreadable paths */ }\n }\n\n _envFilesCache = found;\n _cacheKey = cacheKey;\n return found;\n}\n\n/* ==========================================================================\n Vite plugin helpers\n ========================================================================== */\n\nfunction clearLine(): void {\n if (process.stdout.isTTY) process.stdout.write('\\x1b[2K\\r');\n}\n\nfunction printResolvedUrls(\n urls: { local: string[]; network: string[] } | null | undefined,\n): void {\n if (!urls) return;\n if (urls.local.length > 0) {\n originalConsoleLog(\n ` ${COLORS.GREEN}➜${COLORS.RESET} Local: ${COLORS.CYAN}${urls.local[0]}${COLORS.RESET}`,\n );\n }\n if (urls.network.length > 0) {\n originalConsoleLog(\n ` ${COLORS.GREEN}➜${COLORS.RESET} Network: ${COLORS.CYAN}${urls.network[0]}${COLORS.RESET}`,\n );\n }\n}\n\ntype ServerLike = ViteDevServer | PreviewServer;\n\n/**\n * Patches server.printUrls to emit the Bini.js header and detected env files,\n * then delegates to the original printUrls or our own URL renderer depending\n * on whether clearViteHeader is enabled.\n * Guards against double-invocation with the `started` flag.\n */\nfunction patchPrintUrls(\n server : ServerLike,\n mode : 'dev' | 'preview',\n logo : string,\n clearViteHeader: boolean,\n getRoot : () => string,\n showEnvFiles: boolean,\n): void {\n let started = false;\n const originalPrintUrls = server.printUrls.bind(server);\n\n server.printUrls = () => {\n if (started) return;\n started = true;\n\n if (clearViteHeader) clearLine();\n originalConsoleLog(`\\n ${COLORS.CYAN}${logo} Bini.js${COLORS.RESET} (${mode})`);\n\n if (showEnvFiles) {\n const found = detectEnvFiles(getRoot());\n if (found.length > 0) {\n originalConsoleLog(\n ` ${COLORS.GREEN}➜${COLORS.RESET} Environments: ${found.map(f => f.name).join(', ')}`,\n );\n }\n }\n\n if (clearViteHeader) {\n printResolvedUrls(server.resolvedUrls);\n } else {\n originalPrintUrls();\n }\n };\n}\n\n/* ==========================================================================\n Vite plugin\n ========================================================================== */\n\nexport function biniEnv(options: Readonly<BiniEnvPluginOptions> = {}): Plugin {\n if (options.enabled === false) {\n return { name: 'vite-plugin-bini-env' };\n }\n\n const { clearViteHeader, logo, envPrefix, loadInPreview } = {\n ...DEFAULT_OPTIONS,\n ...options,\n };\n\n let resolvedConfig: ResolvedConfig;\n const getRoot = () => resolvedConfig?.root ?? process.cwd();\n\n return {\n name: 'vite-plugin-bini-env',\n\n config(): UserConfig {\n return { envPrefix };\n },\n\n configResolved(cfg: ResolvedConfig) {\n resolvedConfig = cfg;\n },\n\n configureServer(server) {\n // Trigger env load once the HTTP server is up, or defer if middleware-only\n const triggerLoad = () => void loadEnv(getRoot());\n if (server.httpServer) {\n server.httpServer.once('listening', triggerLoad);\n } else {\n defer(triggerLoad);\n }\n\n // Only patch printUrls when we actually need to change the output\n if (clearViteHeader || logo !== BINI_LOGO) {\n patchPrintUrls(server, 'dev', logo, clearViteHeader, getRoot, true);\n }\n },\n\n configurePreviewServer(server) {\n if (loadInPreview) {\n const triggerLoad = () => void loadEnv(getRoot());\n if (server.httpServer) {\n server.httpServer.once('listening', triggerLoad);\n } else {\n defer(triggerLoad);\n }\n }\n\n if (clearViteHeader || logo !== BINI_LOGO) {\n patchPrintUrls(server, 'preview', logo, clearViteHeader, getRoot, loadInPreview);\n }\n },\n };\n}\n\nexport type { Plugin } from 'vite';"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["// bini-env/src/index.ts\nimport type { Plugin, PreviewServer, ResolvedConfig, UserConfig, ViteDevServer } from 'vite';\n\n/* ==========================================================================\n Runtime detection — must run before anything else\n ========================================================================== */\n\nfunction isNodeLike(): boolean {\n return (\n typeof process !== 'undefined' &&\n !!process.env &&\n typeof process.versions === 'object' &&\n // Edge runtimes (Vercel, Cloudflare) expose a minimal `process` but not\n // `process.versions.node`. Checking for it keeps us out of edge bundles.\n (typeof process.versions.node === 'string' ||\n // Bun sets process.versions.bun\n typeof (process.versions as Record<string, unknown>).bun === 'string')\n );\n}\n\nfunction isDenoRuntime(): boolean {\n return typeof (globalThis as unknown as { Deno?: unknown }).Deno !== 'undefined';\n}\n\n/* ==========================================================================\n Capture originals FIRST — before any patching occurs\n ========================================================================== */\n\nconst originalConsoleLog = console.log.bind(console);\nconst originalConsoleError = console.error.bind(console);\n\n/* ==========================================================================\n Default NODE_ENV — must run before anything else\n ========================================================================== */\n\nif (isNodeLike() && !process.env.NODE_ENV) {\n process.env.NODE_ENV = 'production';\n}\n\n/* ==========================================================================\n DOTENV LOG SUPPRESSION\n Patched once at module load; subsequent calls are no-ops.\n ========================================================================== */\n\nlet _suppressionApplied = false;\n\nexport function suppressDotenvLogsGlobally(): void {\n if (_suppressionApplied) return;\n _suppressionApplied = true;\n\n if (isNodeLike()) {\n process.env.DOTENV_QUIET = 'true';\n }\n\n const isDotenvNoise = (...args: unknown[]): boolean => {\n const msg = args.join(' ');\n return (\n msg.includes('[dotenv@') ||\n msg.includes('injected env') ||\n msg.includes('injecting env')\n );\n };\n\n console.log = (...args: unknown[]) => {\n if (!isDotenvNoise(...args)) originalConsoleLog(...args);\n };\n\n console.error = (...args: unknown[]) => {\n if (!isDotenvNoise(...args)) originalConsoleError(...args);\n };\n}\n\n// Apply once at module load\nsuppressDotenvLogsGlobally();\n\n/* ==========================================================================\n Cross-runtime type declarations\n ========================================================================== */\n\ninterface DenoEnv {\n get(key: string): string | undefined;\n}\ninterface DenoNamespace {\n env: DenoEnv;\n}\n\n/* ==========================================================================\n Public types\n ========================================================================== */\n\nexport interface BiniEnvPluginOptions {\n readonly enabled?: boolean;\n readonly clearViteHeader?: boolean;\n readonly logo?: string;\n readonly envPrefix?: string | string[];\n readonly loadInPreview?: boolean;\n /** @deprecated Suppression is always applied at module load; this option is ignored. */\n readonly suppressDotenvLogs?: boolean;\n}\n\nexport interface DetectedEnvFile {\n readonly name: string;\n readonly path: string;\n}\n\n/* ==========================================================================\n Constants\n ========================================================================== */\n\nconst BINI_LOGO = 'ß';\nconst DEFAULT_ENV_PREFIX = ['BINI_', 'VITE_'] as const;\n\nconst DEFAULT_OPTIONS = Object.freeze({\n enabled : true,\n clearViteHeader: true,\n logo : BINI_LOGO,\n envPrefix : [...DEFAULT_ENV_PREFIX],\n loadInPreview : true,\n} satisfies Omit<Required<BiniEnvPluginOptions>, 'suppressDotenvLogs'>);\n\nconst enum COLORS {\n CYAN = '\\x1b[36m',\n RESET = '\\x1b[0m',\n GREEN = '\\x1b[32m',\n YELLOW = '\\x1b[33m',\n RED = '\\x1b[31m',\n BOLD = '\\x1b[1m',\n DIM = '\\x1b[2m',\n}\n\nconst envCache = new Map<string, string | undefined>();\n\n/* ==========================================================================\n Standalone logger\n ========================================================================== */\n\nfunction timestamp(): string {\n return `${COLORS.DIM}${new Date().toLocaleTimeString('en-US', { hour12: false })}${COLORS.RESET}`;\n}\n\nexport const biniLogger = {\n info(msg: string): void {\n originalConsoleLog(\n `${timestamp()} ${COLORS.CYAN}${COLORS.BOLD}[bini-env]${COLORS.RESET} ${msg}`,\n );\n },\n warn(msg: string): void {\n originalConsoleError(\n `${timestamp()} ${COLORS.YELLOW}${COLORS.BOLD}(!) [bini-env]${COLORS.RESET} ${COLORS.YELLOW}${msg}${COLORS.RESET}`,\n );\n },\n error(msg: string, err?: unknown): void {\n const detail = err instanceof Error\n ? `\\n ${COLORS.DIM}${err.message}${COLORS.RESET}`\n : '';\n originalConsoleError(\n `${timestamp()} ${COLORS.RED}${COLORS.BOLD}[bini-env] error${COLORS.RESET} ${msg}${detail}`,\n );\n },\n} as const;\n\n/* ==========================================================================\n Runtime helpers\n ========================================================================== */\n\nfunction getDeno(): DenoNamespace | undefined {\n return (globalThis as unknown as { Deno?: DenoNamespace }).Deno;\n}\n\n/** Schedule a task compatible with Node, Bun, Deno, and edge runtimes. */\nfunction defer(fn: () => void): void {\n if (typeof setImmediate !== 'undefined') {\n setImmediate(fn);\n } else {\n Promise.resolve().then(fn);\n }\n}\n\n/* ==========================================================================\n getEnv\n ========================================================================== */\n\nexport function getEnv(key: string): string | undefined {\n if (envCache.has(key)) return envCache.get(key);\n\n // 1. Deno runtime\n const deno = getDeno();\n if (deno) {\n try {\n const value = deno.env.get(key);\n if (value !== undefined) {\n envCache.set(key, value);\n return value;\n }\n } catch { /* fall through */ }\n }\n\n // 2. Node.js / Bun / Edge (process.env is available on most edge runtimes too)\n if (typeof process !== 'undefined' && process.env) {\n const value = process.env[key];\n if (value !== undefined) {\n envCache.set(key, value);\n return value;\n }\n }\n\n // 3. Vite client (import.meta.env) — also checks BINI_ and VITE_ prefixed variants\n try {\n const metaEnv = import.meta.env as Record<string, string | undefined> | undefined;\n if (metaEnv) {\n for (const candidate of [key, `BINI_${key}`, `VITE_${key}`]) {\n if (metaEnv[candidate] !== undefined) {\n envCache.set(key, metaEnv[candidate]);\n return metaEnv[candidate];\n }\n }\n }\n } catch { /* import.meta.env not available in this runtime */ }\n\n envCache.set(key, undefined);\n return undefined;\n}\n\n/* ==========================================================================\n requireEnv\n ========================================================================== */\n\nexport function requireEnv(key: string): string {\n const val = getEnv(key);\n if (val === undefined) {\n biniLogger.error(\n `Missing required environment variable: \"${key}\"\\n` +\n ` ${COLORS.DIM}→ In development: add it to your .env file.${COLORS.RESET}\\n` +\n ` ${COLORS.DIM}→ In production: set it in your hosting dashboard.${COLORS.RESET}`,\n );\n throw new Error(`[bini-env] Missing required environment variable: \"${key}\"`);\n }\n return val;\n}\n\n/* ==========================================================================\n loadEnv\n - Only runs on Node-like runtimes (Node.js, Bun).\n - Edge runtimes and Deno skip entirely — they get vars from the host.\n - Idempotent; concurrent calls share one promise.\n ========================================================================== */\n\nlet _envLoaded = false;\nlet _loadPromise: Promise<void> | null = null;\n\nexport async function loadEnv(projectRoot?: string): Promise<void> {\n if (_envLoaded) return;\n if (_loadPromise) return _loadPromise;\n\n _loadPromise = (async () => {\n try {\n // Deno and edge runtimes do not use .env files — vars are injected by host\n if (isDenoRuntime() || !isNodeLike()) return;\n\n const root = projectRoot ?? process.cwd();\n const nodeEnv = process.env.NODE_ENV ?? 'production';\n\n // Load order: lowest → highest priority (later files override earlier ones)\n const envFiles = [\n '.env',\n `.env.${nodeEnv}`,\n `.env.${nodeEnv}.local`,\n '.env.local',\n ];\n\n // Dynamic import keeps `dotenv` and `fs`/`path` out of edge bundles entirely.\n // Bundlers that trace static imports (esbuild, Rollup) will NOT follow\n // a runtime-gated dynamic import when tree-shaking is enabled.\n const [dotenvMod, fsMod, pathMod] = await Promise.all([\n import('dotenv'),\n import('node:fs'),\n import('node:path'),\n ]);\n const dotenv = dotenvMod;\n const fs = fsMod.default ?? fsMod;\n const path = pathMod.default ?? pathMod;\n\n for (const file of envFiles) {\n const filePath = path.join(root, file);\n try {\n await fs.promises.access(filePath, fs.constants.R_OK);\n dotenv.config({ path: filePath, override: true });\n } catch { /* file absent — skip */ }\n }\n\n // Invalidate cache so newly loaded vars are picked up by getEnv\n envCache.clear();\n _envLoaded = true;\n\n } catch (error) {\n biniLogger.error('Failed to load .env file', error);\n // Do NOT set _envLoaded — allow a retry on the next call.\n } finally {\n _loadPromise = null;\n }\n })();\n\n return _loadPromise;\n}\n\n/* ==========================================================================\n detectEnvFiles\n Node-only utility used by the Vite plugin (build-time only, never edge).\n ========================================================================== */\n\nlet _envFilesCache: DetectedEnvFile[] | null = null;\nlet _cacheKey = '';\n\nexport function detectEnvFiles(projectRoot?: string): DetectedEnvFile[] {\n // Guard: this function uses fs synchronously; bail on non-Node runtimes.\n if (!isNodeLike()) return [];\n\n const root = projectRoot ?? process.cwd();\n const nodeEnv = process.env.NODE_ENV ?? 'production';\n const cacheKey = `${root}:${nodeEnv}`;\n if (_envFilesCache && _cacheKey === cacheKey) return _envFilesCache;\n\n // Inline the fs/path usage so no top-level import is needed.\n // This function is only ever called from the Vite plugin (configureServer /\n // configurePreviewServer), which runs in Node — never in an edge bundle.\n let fsSync: typeof import('fs');\n let pathMod: typeof import('path');\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n fsSync = require('node:fs');\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n pathMod = require('node:path');\n } catch {\n return [];\n }\n\n const candidates = [\n '.env.local',\n `.env.${nodeEnv}.local`,\n `.env.${nodeEnv}`,\n '.env',\n ];\n\n const found: DetectedEnvFile[] = [];\n for (const file of candidates) {\n try {\n const filePath = pathMod.join(root, file);\n if (fsSync.existsSync(filePath)) found.push({ name: file, path: filePath });\n } catch { /* skip unreadable paths */ }\n }\n\n _envFilesCache = found;\n _cacheKey = cacheKey;\n return found;\n}\n\n/* ==========================================================================\n Vite plugin helpers\n ========================================================================== */\n\nfunction clearLine(): void {\n if (typeof process !== 'undefined' && process.stdout?.isTTY) {\n process.stdout.write('\\x1b[2K\\r');\n }\n}\n\nfunction printResolvedUrls(\n urls: { local: string[]; network: string[] } | null | undefined,\n): void {\n if (!urls) return;\n if (urls.local.length > 0) {\n originalConsoleLog(\n ` ${COLORS.GREEN}➜${COLORS.RESET} Local: ${COLORS.CYAN}${urls.local[0]}${COLORS.RESET}`,\n );\n }\n if (urls.network.length > 0) {\n originalConsoleLog(\n ` ${COLORS.GREEN}➜${COLORS.RESET} Network: ${COLORS.CYAN}${urls.network[0]}${COLORS.RESET}`,\n );\n }\n}\n\ntype ServerLike = ViteDevServer | PreviewServer;\n\nfunction patchPrintUrls(\n server : ServerLike,\n mode : 'dev' | 'preview',\n logo : string,\n clearViteHeader: boolean,\n getRoot : () => string,\n showEnvFiles : boolean,\n): void {\n let started = false;\n const originalPrintUrls = server.printUrls.bind(server);\n\n server.printUrls = () => {\n if (started) return;\n started = true;\n\n if (clearViteHeader) clearLine();\n originalConsoleLog(`\\n ${COLORS.CYAN}${logo} Bini.js${COLORS.RESET} (${mode})`);\n\n if (showEnvFiles) {\n const found = detectEnvFiles(getRoot());\n if (found.length > 0) {\n originalConsoleLog(\n ` ${COLORS.GREEN}➜${COLORS.RESET} Environments: ${found.map(f => f.name).join(', ')}`,\n );\n }\n }\n\n if (clearViteHeader) {\n printResolvedUrls(server.resolvedUrls);\n } else {\n originalPrintUrls();\n }\n };\n}\n\n/* ==========================================================================\n Vite plugin\n ========================================================================== */\n\nexport function biniEnv(options: Readonly<BiniEnvPluginOptions> = {}): Plugin {\n if (options.enabled === false) {\n return { name: 'vite-plugin-bini-env' };\n }\n\n const { clearViteHeader, logo, envPrefix, loadInPreview } = {\n ...DEFAULT_OPTIONS,\n ...options,\n };\n\n let resolvedConfig: ResolvedConfig;\n const getRoot = () => resolvedConfig?.root ?? process.cwd();\n\n return {\n name: 'vite-plugin-bini-env',\n\n config(): UserConfig {\n return { envPrefix };\n },\n\n configResolved(cfg: ResolvedConfig) {\n resolvedConfig = cfg;\n },\n\n configureServer(server) {\n const triggerLoad = () => void loadEnv(getRoot());\n if (server.httpServer) {\n server.httpServer.once('listening', triggerLoad);\n } else {\n defer(triggerLoad);\n }\n\n // Watch for new or changed .env files and restart the dev server so the\n // fresh variables are picked up. Chokidar (bundled with Vite) handles the\n // add/change events; we reset _envLoaded so loadEnv re-reads on restart.\n const envGlob = `${getRoot()}/.env*`;\n server.watcher.add(envGlob);\n\n const onEnvChange = (filePath: string) => {\n // Ignore editor swap/temp files (.env.swp, .env~, etc.)\n if (/\\.(swp|swo|bak|tmp)$|~$/.test(filePath)) return;\n\n biniLogger.info(\n `env file ${filePath.replace(getRoot() + '/', '')} changed — restarting server`,\n );\n\n // Reset load state so the restarted server re-reads all .env files\n _envLoaded = false;\n _loadPromise = null;\n envCache.clear();\n _envFilesCache = null;\n\n void server.restart();\n };\n\n server.watcher.on('add', onEnvChange);\n server.watcher.on('change', onEnvChange);\n\n // Remove listeners when the server closes so they don't stack across\n // restarts — Vite calls configureServer again on each restart.\n server.httpServer?.once('close', () => {\n server.watcher.off('add', onEnvChange);\n server.watcher.off('change', onEnvChange);\n });\n\n if (clearViteHeader || logo !== BINI_LOGO) {\n patchPrintUrls(server, 'dev', logo, clearViteHeader, getRoot, true);\n }\n },\n\n configurePreviewServer(server) {\n if (loadInPreview) {\n const triggerLoad = () => void loadEnv(getRoot());\n if (server.httpServer) {\n server.httpServer.once('listening', triggerLoad);\n } else {\n defer(triggerLoad);\n }\n }\n\n if (clearViteHeader || logo !== BINI_LOGO) {\n patchPrintUrls(server, 'preview', logo, clearViteHeader, getRoot, loadInPreview);\n }\n },\n };\n}\n\nexport type { Plugin } from 'vite';"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bini-env",
3
- "version": "1.0.9",
4
- "description": "Universal environment variable loader and Vite plugin for Bini.js — works in Node.js, Deno, Bun, and Vite edge functions",
3
+ "version": "1.0.10",
4
+ "description": "Universal environment variable loader and Vite plugin for Bini.js — works across Node.js, Bun, Deno, Vercel Edge, Netlify Edge, and Cloudflare Workers",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -35,9 +35,15 @@
35
35
  "env",
36
36
  "dotenv",
37
37
  "deno",
38
+ "bun",
38
39
  "edge-functions",
40
+ "edge-runtime",
39
41
  "cross-runtime",
40
- "env-loader"
42
+ "env-loader",
43
+ "vercel-edge",
44
+ "netlify-edge",
45
+ "cloudflare-workers",
46
+ "runtime-agnostic"
41
47
  ],
42
48
  "repository": {
43
49
  "type": "git",