bini-env 1.1.0 → 1.1.2

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/dist/index.d.ts CHANGED
@@ -1,32 +1,34 @@
1
+ import { Context } from 'hono';
1
2
  import { Plugin } from 'vite';
2
3
  export { Plugin } from 'vite';
3
- export { Context } from 'hono';
4
4
 
5
- /** Minimal shape accepted by getEnv / requireEnv. Satisfied by any Hono Context. */
6
- type HonoContext = {
7
- env: unknown;
8
- } & Record<string, unknown>;
5
+ /**
6
+ * bini-env/src/index.ts
7
+ *
8
+ * Two responsibilities only:
9
+ * 1. Tell Vite which env prefixes to expose to import.meta.env (biniEnv plugin)
10
+ * 2. Read env vars from the Hono request context (getEnv / requireEnv)
11
+ *
12
+ * process.env is never used. All runtime env access goes through Hono's env() adapter,
13
+ * which handles Node, Bun, Cloudflare Workers, Deno, and Vercel Edge natively.
14
+ */
15
+
16
+ /**
17
+ * Accepts any Hono Context. Typed against Hono's own Context rather than a
18
+ * loose duck type so misuse is caught at the call site.
19
+ */
20
+ type HonoContext = Context;
9
21
  interface BiniEnvPluginOptions {
10
- readonly enabled?: boolean;
11
- readonly clearViteHeader?: boolean;
12
- readonly logo?: string;
22
+ /** Extra prefixes to expose to import.meta.env, in addition to BINI_ and VITE_. */
13
23
  readonly envPrefix?: string | string[];
14
- readonly loadInPreview?: boolean;
15
- }
16
- interface DetectedEnvFile {
17
- readonly name: string;
18
- readonly path: string;
19
24
  }
20
25
  declare const biniLogger: {
21
26
  readonly info: (msg: string) => void;
22
27
  readonly warn: (msg: string) => void;
23
28
  readonly error: (msg: string, err?: unknown) => void;
24
29
  };
25
- declare function setContext(c: HonoContext): void;
26
- declare function clearContext(): void;
27
- declare function getEnv(c: HonoContext | string, key?: string): string | undefined;
28
- declare function requireEnv(c: HonoContext | string, key?: string): string;
29
- declare function detectEnvFiles(projectRoot?: string): DetectedEnvFile[];
30
+ declare function getEnv(c: HonoContext, key: string): string | undefined;
31
+ declare function requireEnv(c: HonoContext, key: string): string;
30
32
  declare function biniEnv(options?: Readonly<BiniEnvPluginOptions>): Plugin;
31
33
 
32
- export { type BiniEnvPluginOptions, type DetectedEnvFile, type HonoContext, biniEnv, biniLogger, clearContext, detectEnvFiles, getEnv, requireEnv, setContext };
34
+ export { type BiniEnvPluginOptions, type HonoContext, biniEnv, biniLogger, getEnv, requireEnv };
package/dist/index.js CHANGED
@@ -8,228 +8,99 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
8
8
  if (typeof require !== "undefined") return require.apply(this, arguments);
9
9
  throw Error('Dynamic require of "' + x + '" is not supported');
10
10
  });
11
- function isNodeLike() {
12
- return typeof process !== "undefined" && !!process.env && typeof process.versions === "object" && (typeof process.versions.node === "string" || typeof process.versions.bun === "string");
13
- }
14
- var originalConsoleLog = console.log.bind(console);
15
- var originalConsoleError = console.error.bind(console);
16
- if (isNodeLike() && !process.env.NODE_ENV) {
17
- process.env.NODE_ENV = "production";
18
- }
19
- var BINI_LOGO = "\xDF";
20
- var DEFAULT_ENV_PREFIX = ["BINI_", "VITE_"];
21
- var DEFAULT_OPTIONS = Object.freeze({
22
- enabled: true,
23
- clearViteHeader: true,
24
- logo: BINI_LOGO,
25
- envPrefix: [...DEFAULT_ENV_PREFIX],
26
- loadInPreview: true
27
- });
28
- var envCache = /* @__PURE__ */ new Map();
29
- function timestamp() {
30
- return `${"\x1B[2m" /* DIM */}${(/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false })}${"\x1B[0m" /* RESET */}`;
11
+ var C = {
12
+ CYAN: "\x1B[36m",
13
+ RESET: "\x1B[0m",
14
+ YELLOW: "\x1B[33m",
15
+ RED: "\x1B[31m",
16
+ BOLD: "\x1B[1m",
17
+ DIM: "\x1B[2m"
18
+ };
19
+ function _ts() {
20
+ return `${C.DIM}${(/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false })}${C.RESET}`;
31
21
  }
32
22
  var biniLogger = {
33
23
  info(msg) {
34
- originalConsoleLog(
35
- `${timestamp()} ${"\x1B[36m" /* CYAN */}${"\x1B[1m" /* BOLD */}[bini-env]${"\x1B[0m" /* RESET */} ${msg}`
36
- );
24
+ console.log(`${_ts()} ${C.CYAN}${C.BOLD}[bini-env]${C.RESET} ${msg}`);
37
25
  },
38
26
  warn(msg) {
39
- originalConsoleError(
40
- `${timestamp()} ${"\x1B[33m" /* YELLOW */}${"\x1B[1m" /* BOLD */}(!) [bini-env]${"\x1B[0m" /* RESET */} ${"\x1B[33m" /* YELLOW */}${msg}${"\x1B[0m" /* RESET */}`
27
+ console.warn(
28
+ `${_ts()} ${C.YELLOW}${C.BOLD}(!) [bini-env]${C.RESET} ${C.YELLOW}${msg}${C.RESET}`
41
29
  );
42
30
  },
43
31
  error(msg, err) {
44
32
  const detail = err instanceof Error ? `
45
- ${"\x1B[2m" /* DIM */}${err.message}${"\x1B[0m" /* RESET */}` : "";
46
- originalConsoleError(
47
- `${timestamp()} ${"\x1B[31m" /* RED */}${"\x1B[1m" /* BOLD */}[bini-env] error${"\x1B[0m" /* RESET */} ${msg}${detail}`
33
+ ${C.DIM}${err.message}${C.RESET}` : "";
34
+ console.error(
35
+ `${_ts()} ${C.RED}${C.BOLD}[bini-env] error${C.RESET} ${msg}${detail}`
48
36
  );
49
37
  }
50
38
  };
51
- function defer(fn) {
52
- if (typeof setImmediate !== "undefined") {
53
- setImmediate(fn);
54
- } else {
55
- Promise.resolve().then(fn);
56
- }
57
- }
58
- var _honoContext = null;
59
- function setContext(c) {
60
- _honoContext = c;
61
- }
62
- function clearContext() {
63
- _honoContext = null;
64
- }
65
39
  function getEnv(c, key) {
66
- const resolvedKey = typeof c === "string" ? c : key;
67
- const resolvedCtx = typeof c === "string" ? null : c;
68
- const ctx = resolvedCtx ?? _honoContext;
69
- if (ctx) {
70
- try {
71
- const honoEnvs = adapter.env(ctx);
72
- const value = honoEnvs[resolvedKey];
73
- if (value !== void 0) return value;
74
- } catch {
75
- }
76
- }
77
- if (envCache.has(resolvedKey)) return envCache.get(resolvedKey);
78
- if (typeof process !== "undefined" && process.env) {
79
- const value = process.env[resolvedKey];
80
- envCache.set(resolvedKey, value);
81
- return value;
82
- }
83
- envCache.set(resolvedKey, void 0);
84
- return void 0;
40
+ const honoEnvs = adapter.env(c);
41
+ return honoEnvs[key];
85
42
  }
86
43
  function requireEnv(c, key) {
87
- const resolvedKey = typeof c === "string" ? c : key;
88
- const val = getEnv(c, resolvedKey);
89
- if (val === void 0) {
44
+ const val = getEnv(c, key);
45
+ if (!val) {
90
46
  biniLogger.error(
91
- `Missing required environment variable: "${resolvedKey}"
92
- ${"\x1B[2m" /* DIM */}\u2192 In development: set it in your platform's env config.${"\x1B[0m" /* RESET */}
93
- ${"\x1B[2m" /* DIM */}\u2192 In production: set it in your hosting dashboard.${"\x1B[0m" /* RESET */}`
47
+ `Missing required environment variable: "${key}"
48
+ ${C.DIM}-> Set it in your platform's env config or hosting dashboard.${C.RESET}`
94
49
  );
95
- throw new Error(`[bini-env] Missing required environment variable: "${resolvedKey}"`);
50
+ throw new Error(`[bini-env] Missing required environment variable: "${key}"`);
96
51
  }
97
52
  return val;
98
53
  }
99
- var _envFilesCache = null;
100
- var _cacheKey = "";
101
- function detectEnvFiles(projectRoot) {
102
- if (!isNodeLike()) return [];
103
- const root = projectRoot ?? process.cwd();
104
- const nodeEnv = process.env.NODE_ENV ?? "production";
105
- const cacheKey = `${root}:${nodeEnv}`;
106
- if (_envFilesCache && _cacheKey === cacheKey) return _envFilesCache;
107
- let fsSync;
108
- let pathMod;
54
+ var DEFAULT_PREFIXES = ["BINI_", "VITE_"];
55
+ function detectEnvFiles(root) {
109
56
  try {
110
- fsSync = __require("fs");
111
- pathMod = __require("path");
57
+ const fs = __require("fs");
58
+ const path = __require("path");
59
+ const nodeEnv = process.env.NODE_ENV ?? "production";
60
+ return [
61
+ ".env.local",
62
+ `.env.${nodeEnv}.local`,
63
+ `.env.${nodeEnv}`,
64
+ ".env"
65
+ ].filter((f) => fs.existsSync(path.join(root, f)));
112
66
  } catch {
113
67
  return [];
114
68
  }
115
- const candidates = [
116
- ".env.local",
117
- `.env.${nodeEnv}.local`,
118
- `.env.${nodeEnv}`,
119
- ".env"
120
- ];
121
- const found = [];
122
- for (const file of candidates) {
123
- try {
124
- const filePath = pathMod.join(root, file);
125
- if (fsSync.existsSync(filePath)) found.push({ name: file, path: filePath });
126
- } catch {
127
- }
128
- }
129
- _envFilesCache = found;
130
- _cacheKey = cacheKey;
131
- return found;
132
- }
133
- function clearLine() {
134
- if (typeof process !== "undefined" && process.stdout?.isTTY) {
135
- process.stdout.write("\x1B[2K\r");
136
- }
137
69
  }
138
- function printResolvedUrls(urls) {
139
- if (!urls) return;
140
- if (urls.local.length > 0) {
141
- originalConsoleLog(
142
- ` ${"\x1B[32m" /* GREEN */}\u279C${"\x1B[0m" /* RESET */} Local: ${"\x1B[36m" /* CYAN */}${urls.local[0]}${"\x1B[0m" /* RESET */}`
143
- );
144
- }
145
- if (urls.network.length > 0) {
146
- originalConsoleLog(
147
- ` ${"\x1B[32m" /* GREEN */}\u279C${"\x1B[0m" /* RESET */} Network: ${"\x1B[36m" /* CYAN */}${urls.network[0]}${"\x1B[0m" /* RESET */}`
148
- );
149
- }
150
- }
151
- function patchPrintUrls(server, mode, logo, clearViteHeader, getRoot, showEnvFiles) {
152
- let started = false;
153
- const originalPrintUrls = server.printUrls.bind(server);
70
+ function printBanner(server, mode, root) {
71
+ const original = server.printUrls.bind(server);
154
72
  server.printUrls = () => {
155
- if (started) return;
156
- started = true;
157
- if (clearViteHeader) clearLine();
158
- originalConsoleLog(`
159
- ${"\x1B[36m" /* CYAN */}${logo} Bini.js${"\x1B[0m" /* RESET */} (${mode})`);
160
- if (showEnvFiles) {
161
- const found = detectEnvFiles(getRoot());
162
- if (found.length > 0) {
163
- originalConsoleLog(
164
- ` ${"\x1B[32m" /* GREEN */}\u279C${"\x1B[0m" /* RESET */} Environments: ${found.map((f) => f.name).join(", ")}`
165
- );
166
- }
167
- }
168
- if (clearViteHeader) {
169
- printResolvedUrls(server.resolvedUrls);
170
- } else {
171
- originalPrintUrls();
73
+ console.log(`
74
+ ${C.CYAN}\xDF Bini.js${C.RESET} (${mode})`);
75
+ const found = detectEnvFiles(root);
76
+ if (found.length > 0) {
77
+ console.log(` \x1B[32m\u279C\x1B[0m Environments: ${found.join(", ")}`);
172
78
  }
79
+ original();
173
80
  };
174
81
  }
175
82
  function biniEnv(options = {}) {
176
- if (options.enabled === false) {
177
- return { name: "vite-plugin-bini-env" };
178
- }
179
- const { clearViteHeader, logo, envPrefix, loadInPreview } = {
180
- ...DEFAULT_OPTIONS,
181
- ...options
182
- };
183
- let resolvedConfig;
184
- const getRoot = () => resolvedConfig?.root ?? process.cwd();
83
+ const extraPrefixes = options.envPrefix ? Array.isArray(options.envPrefix) ? options.envPrefix : [options.envPrefix] : [];
84
+ const envPrefix = [
85
+ .../* @__PURE__ */ new Set([...DEFAULT_PREFIXES, ...extraPrefixes])
86
+ ];
185
87
  return {
186
- name: "vite-plugin-bini-env",
88
+ name: "bini-env",
187
89
  config() {
188
90
  return { envPrefix };
189
91
  },
190
- configResolved(cfg) {
191
- resolvedConfig = cfg;
192
- },
193
92
  configureServer(server) {
194
- defer(() => envCache.clear());
195
- const envGlob = `${getRoot()}/.env*`;
196
- server.watcher.add(envGlob);
197
- const onEnvChange = (filePath) => {
198
- if (/\.(swp|swo|bak|tmp)$|~$/.test(filePath)) return;
199
- biniLogger.info(
200
- `env file ${filePath.replace(getRoot() + "/", "")} changed \u2014 restarting server`
201
- );
202
- envCache.clear();
203
- _envFilesCache = null;
204
- void server.restart();
205
- };
206
- server.watcher.on("add", onEnvChange);
207
- server.watcher.on("change", onEnvChange);
208
- server.httpServer?.once("close", () => {
209
- server.watcher.off("add", onEnvChange);
210
- server.watcher.off("change", onEnvChange);
211
- });
212
- if (clearViteHeader || logo !== BINI_LOGO) {
213
- patchPrintUrls(server, "dev", logo, clearViteHeader, getRoot, true);
214
- }
93
+ printBanner(server, "dev", server.config.root);
215
94
  },
216
95
  configurePreviewServer(server) {
217
- if (loadInPreview) {
218
- defer(() => envCache.clear());
219
- }
220
- if (clearViteHeader || logo !== BINI_LOGO) {
221
- patchPrintUrls(server, "preview", logo, clearViteHeader, getRoot, loadInPreview);
222
- }
96
+ printBanner(server, "preview", server.config.root);
223
97
  }
224
98
  };
225
99
  }
226
100
 
227
101
  exports.biniEnv = biniEnv;
228
102
  exports.biniLogger = biniLogger;
229
- exports.clearContext = clearContext;
230
- exports.detectEnvFiles = detectEnvFiles;
231
103
  exports.getEnv = getEnv;
232
104
  exports.requireEnv = requireEnv;
233
- exports.setContext = setContext;
234
105
  //# sourceMappingURL=index.js.map
235
106
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["env"],"mappings":"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","file":"index.js","sourcesContent":["// bini-env/src/index.ts\nimport { env } from 'hono/adapter';\nimport type { Plugin, PreviewServer, ResolvedConfig, UserConfig, ViteDevServer } from 'vite';\n\n/* ==========================================================================\n Runtime detection — used by Vite plugin hooks only\n ========================================================================== */\n\nfunction isNodeLike(): boolean {\n return (\n typeof process !== 'undefined' &&\n !!process.env &&\n typeof process.versions === 'object' &&\n (typeof process.versions.node === 'string' ||\n typeof (process.versions as Record<string, unknown>).bun === 'string')\n );\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\n ========================================================================== */\n\nif (isNodeLike() && !process.env.NODE_ENV) {\n process.env.NODE_ENV = 'production';\n}\n\n/* ==========================================================================\n HonoContext duck type\n\n We intentionally do NOT import Context<E,P,I> from hono because Hono 4.12\n added a [GET_MATCH_RESULT] symbol to HonoRequest, making every\n narrowly-typed Context (e.g. Context<BlankEnv, \"/chat\", BlankInput>)\n structurally incompatible with Context<any, any, any>. A minimal duck type\n that only requires what hono/adapter's env() accesses at runtime sidesteps\n the symbol variance entirely. Consumers cast with `c as any` once at the\n call site; the single `env(ctx as any)` below is the only unsafe cast in\n the entire package.\n ========================================================================== */\n\n/** Minimal shape accepted by getEnv / requireEnv. Satisfied by any Hono Context. */\nexport type HonoContext = { env: unknown } & Record<string, unknown>;\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}\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 Required<BiniEnvPluginOptions>);\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\n// Build-time only cache — never used for request-scoped Hono env() results\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 Vite plugin helper\n ========================================================================== */\n\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 Module-level Hono context store\n\n Lets getEnv / requireEnv work without an explicit `c` argument at every\n call site. Register once in a global middleware:\n\n app.use('*', (c, next) => { setContext(c as any); return next(); });\n ========================================================================== */\n\nlet _honoContext: HonoContext | null = null;\n\nexport function setContext(c: HonoContext): void {\n _honoContext = c;\n}\n\nexport function clearContext(): void {\n _honoContext = null;\n}\n\n/* ==========================================================================\n getEnv\n\n Resolution order:\n 1. Explicit Hono Context (c param) — request-scoped, never cached\n 2. Stored Hono Context (setContext) — request-scoped, never cached\n 3. process.env (build-time / Vite plugin hooks — no c available)\n\n Usage:\n getEnv(c as any, 'KEY') — inside a Hono route / middleware\n getEnv('KEY') — outside request context (build-time)\n ========================================================================== */\n\nexport function getEnv(c: HonoContext | string, key?: string): string | undefined {\n const resolvedKey = typeof c === 'string' ? c : key!;\n const resolvedCtx = typeof c === 'string' ? null : c;\n\n // 1 & 2. Hono env() — covers all runtimes: CF Workers, Node, Bun, Deno, Edge\n const ctx = resolvedCtx ?? _honoContext;\n if (ctx) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const honoEnvs = env(ctx as any) as Record<string, string | undefined>;\n const value = honoEnvs[resolvedKey];\n if (value !== undefined) return value; // never cache — request-scoped\n } catch { /* context binding unavailable — fall through */ }\n }\n\n // 3. process.env — build-time only (Vite plugin hooks run outside any request)\n if (envCache.has(resolvedKey)) return envCache.get(resolvedKey);\n\n if (typeof process !== 'undefined' && process.env) {\n const value = process.env[resolvedKey];\n envCache.set(resolvedKey, value);\n return value;\n }\n\n envCache.set(resolvedKey, undefined);\n return undefined;\n}\n\n/* ==========================================================================\n requireEnv\n ========================================================================== */\n\nexport function requireEnv(c: HonoContext | string, key?: string): string {\n const resolvedKey = typeof c === 'string' ? c : key!;\n const val = getEnv(c, resolvedKey);\n if (val === undefined) {\n biniLogger.error(\n `Missing required environment variable: \"${resolvedKey}\"\\n` +\n ` ${COLORS.DIM}→ In development: set it in your platform's env config.${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: \"${resolvedKey}\"`);\n }\n return val;\n}\n\n/* ==========================================================================\n detectEnvFiles\n Node-only — used by the Vite plugin at build/dev time, never on edge.\n ========================================================================== */\n\nlet _envFilesCache: DetectedEnvFile[] | null = null;\nlet _cacheKey = '';\n\nexport function detectEnvFiles(projectRoot?: string): DetectedEnvFile[] {\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 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 defer(() => envCache.clear());\n\n const envGlob = `${getRoot()}/.env*`;\n server.watcher.add(envGlob);\n\n const onEnvChange = (filePath: string) => {\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 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 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 defer(() => envCache.clear());\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';\nexport type { Context } from 'hono';"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["env"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * bini-env/src/index.ts\n *\n * Two responsibilities only:\n * 1. Tell Vite which env prefixes to expose to import.meta.env (biniEnv plugin)\n * 2. Read env vars from the Hono request context (getEnv / requireEnv)\n *\n * process.env is never used. All runtime env access goes through Hono's env() adapter,\n * which handles Node, Bun, Cloudflare Workers, Deno, and Vercel Edge natively.\n */\n\nimport { env } from 'hono/adapter';\nimport type { Context } from 'hono';\nimport type { Plugin, UserConfig, ViteDevServer, PreviewServer } from 'vite';\n\n/* ==========================================================================\n ANSI helpers — used by biniLogger only\n ========================================================================== */\n\nconst C = {\n CYAN : '\\x1b[36m',\n RESET : '\\x1b[0m',\n YELLOW: '\\x1b[33m',\n RED : '\\x1b[31m',\n BOLD : '\\x1b[1m',\n DIM : '\\x1b[2m',\n} as const;\n\n/* ==========================================================================\n Public types\n ========================================================================== */\n\n/**\n * Accepts any Hono Context. Typed against Hono's own Context rather than a\n * loose duck type so misuse is caught at the call site.\n */\nexport type HonoContext = Context;\n\nexport interface BiniEnvPluginOptions {\n /** Extra prefixes to expose to import.meta.env, in addition to BINI_ and VITE_. */\n readonly envPrefix?: string | string[];\n}\n\n/* ==========================================================================\n Logger\n ========================================================================== */\n\nfunction _ts(): string {\n return `${C.DIM}${new Date().toLocaleTimeString('en-US', { hour12: false })}${C.RESET}`;\n}\n\nexport const biniLogger = {\n info(msg: string): void {\n console.log(`${_ts()} ${C.CYAN}${C.BOLD}[bini-env]${C.RESET} ${msg}`);\n },\n warn(msg: string): void {\n console.warn(\n `${_ts()} ${C.YELLOW}${C.BOLD}(!) [bini-env]${C.RESET} ${C.YELLOW}${msg}${C.RESET}`,\n );\n },\n error(msg: string, err?: unknown): void {\n const detail =\n err instanceof Error ? `\\n ${C.DIM}${err.message}${C.RESET}` : '';\n console.error(\n `${_ts()} ${C.RED}${C.BOLD}[bini-env] error${C.RESET} ${msg}${detail}`,\n );\n },\n} as const;\n\n/* ==========================================================================\n getEnv\n\n Reads exclusively from Hono's env() adapter. No process.env fallback.\n Hono handles all platform differences:\n Node / Bun → process.env\n Cloudflare → c.env bindings\n Deno / Netlify → Deno.env.get()\n Vercel Edge → process.env (V8 Node compat)\n ========================================================================== */\n\nexport function getEnv(c: HonoContext, key: string): string | undefined {\n const honoEnvs = env(c) as Record<string, string | undefined>;\n return honoEnvs[key];\n}\n\n/* ==========================================================================\n requireEnv\n\n Same as getEnv but throws immediately if the variable is missing or empty.\n Always handle the thrown error in your route's catch block.\n ========================================================================== */\n\nexport function requireEnv(c: HonoContext, key: string): string {\n const val = getEnv(c, key);\n\n if (!val) {\n biniLogger.error(\n `Missing required environment variable: \"${key}\"\\n` +\n ` ${C.DIM}-> Set it in your platform's env config or hosting dashboard.${C.RESET}`,\n );\n\n throw new Error(`[bini-env] Missing required environment variable: \"${key}\"`);\n }\n\n return val;\n}\n\n/* ==========================================================================\n biniEnv — Vite plugin\n\n Tells Vite which prefixes to expose to import.meta.env.\n Prints the ß Bini.js banner on dev and preview server start.\n Vite handles .env file loading, watching, server restarts, and HMR natively.\n ========================================================================== */\n\nconst DEFAULT_PREFIXES = ['BINI_', 'VITE_'] as const;\n\nfunction detectEnvFiles(root: string): string[] {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const fs = require('node:fs') as typeof import('fs');\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const path = require('node:path') as typeof import('path');\n const nodeEnv = process.env.NODE_ENV ?? 'production';\n return [\n '.env.local',\n `.env.${nodeEnv}.local`,\n `.env.${nodeEnv}`,\n '.env',\n ].filter(f => fs.existsSync(path.join(root, f)));\n } catch {\n return [];\n }\n}\n\nfunction printBanner(server: ViteDevServer | PreviewServer, mode: 'dev' | 'preview', root: string): void {\n const original = server.printUrls.bind(server);\n server.printUrls = () => {\n console.log(`\\n ${C.CYAN}ß Bini.js${C.RESET} (${mode})`);\n const found = detectEnvFiles(root);\n if (found.length > 0) {\n console.log(` \\x1b[32m➜\\x1b[0m Environments: ${found.join(', ')}`);\n }\n original();\n };\n}\n\nexport function biniEnv(options: Readonly<BiniEnvPluginOptions> = {}): Plugin {\n const extraPrefixes = options.envPrefix\n ? (Array.isArray(options.envPrefix) ? options.envPrefix : [options.envPrefix])\n : [];\n\n const envPrefix = [\n ...new Set([...DEFAULT_PREFIXES, ...extraPrefixes]),\n ];\n\n return {\n name: 'bini-env',\n\n config(): UserConfig {\n return { envPrefix };\n },\n\n configureServer(server) {\n printBanner(server, 'dev', server.config.root);\n },\n\n configurePreviewServer(server) {\n printBanner(server, 'preview', server.config.root);\n },\n };\n}\n\n/* ==========================================================================\n Re-exports\n ========================================================================== */\n\nexport type { Plugin } from 'vite';"]}