bini-env 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,15 +1,28 @@
1
1
  import { Context } from 'hono';
2
- import { Plugin } from 'vite';
3
- export { Plugin } from 'vite';
4
2
 
5
3
  type HonoContext = Context;
4
+ type EnvSource = Record<string, unknown>;
5
+ type EnvInput = HonoContext | EnvSource | undefined | null;
6
6
  declare const biniLogger: {
7
7
  readonly info: (msg: string) => void;
8
8
  readonly warn: (msg: string) => void;
9
9
  readonly error: (msg: string, err?: unknown) => void;
10
10
  };
11
- declare function getEnv(c: HonoContext, key: string): string | undefined;
12
- declare function requireEnv(c: HonoContext, key: string): string;
13
- declare function biniEnv(): Plugin;
11
+ /**
12
+ * Reads one variable. Returns `undefined` when it is missing or is not a string
13
+ * (Cloudflare bindings such as KV namespaces are not env strings).
14
+ */
15
+ declare function getEnv(source: EnvInput, key: string): string | undefined;
16
+ /** Reads one variable and throws (after logging) when it is missing or empty. */
17
+ declare function requireEnv(source: EnvInput, key: string): string;
18
+ interface EnvCheck {
19
+ ok: boolean;
20
+ /** Names only, never values. */
21
+ missing: string[];
22
+ }
23
+ /** Checks several variables at once and logs every missing name in one message. */
24
+ declare function checkEnv(source: EnvInput, keys: readonly string[]): EnvCheck;
25
+ /** Requires several variables at once. Throws one error listing all that are missing. */
26
+ declare function requireEnvs<K extends string>(source: EnvInput, keys: readonly K[]): Record<K, string>;
14
27
 
15
- export { type HonoContext, biniEnv, biniLogger, getEnv, requireEnv };
28
+ export { type EnvCheck, type EnvInput, type EnvSource, type HonoContext, biniLogger, checkEnv, getEnv, requireEnv, requireEnvs };
package/dist/index.js CHANGED
@@ -1,13 +1,6 @@
1
- 'use strict';
1
+ import { env } from 'hono/adapter';
2
2
 
3
- var adapter = require('hono/adapter');
4
-
5
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
6
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
7
- }) : x)(function(x) {
8
- if (typeof require !== "undefined") return require.apply(this, arguments);
9
- throw Error('Dynamic require of "' + x + '" is not supported');
10
- });
3
+ // src/index.ts
11
4
  var C = {
12
5
  CYAN: "\x1B[36m",
13
6
  RESET: "\x1B[0m",
@@ -16,112 +9,73 @@ var C = {
16
9
  BOLD: "\x1B[1m",
17
10
  DIM: "\x1B[2m"
18
11
  };
19
- function _ts() {
12
+ function timestamp() {
20
13
  return `${C.DIM}${(/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false })}${C.RESET}`;
21
14
  }
22
15
  var biniLogger = {
23
16
  info(msg) {
24
- console.log(`${_ts()} ${C.CYAN}${C.BOLD}[bini-env]${C.RESET} ${msg}`);
17
+ console.log(`${timestamp()} ${C.CYAN}${C.BOLD}[bini-env]${C.RESET} ${msg}`);
25
18
  },
26
19
  warn(msg) {
27
- console.warn(
28
- `${_ts()} ${C.YELLOW}${C.BOLD}(!) [bini-env]${C.RESET} ${C.YELLOW}${msg}${C.RESET}`
29
- );
20
+ console.warn(`${timestamp()} ${C.YELLOW}${C.BOLD}(!) [bini-env]${C.RESET} ${C.YELLOW}${msg}${C.RESET}`);
30
21
  },
31
22
  error(msg, err) {
32
23
  const detail = err instanceof Error ? `
33
24
  ${C.DIM}${err.message}${C.RESET}` : "";
34
- console.error(
35
- `${_ts()} ${C.RED}${C.BOLD}[bini-env] error${C.RESET} ${msg}${detail}`
36
- );
25
+ console.error(`${timestamp()} ${C.RED}${C.BOLD}[bini-env] error${C.RESET} ${msg}${detail}`);
37
26
  }
38
27
  };
39
- function getEnv(c, key) {
40
- const honoEnvs = adapter.env(c);
41
- return honoEnvs[key];
28
+ function isContext(value) {
29
+ if (typeof value !== "object" || value === null) return false;
30
+ const v = value;
31
+ return typeof v.req === "object" && v.req !== null && typeof v.get === "function";
32
+ }
33
+ function runtimeEnv() {
34
+ const g = globalThis;
35
+ if (g.process?.env) return g.process.env;
36
+ try {
37
+ const obj = g.Deno?.env?.toObject?.();
38
+ if (obj) return obj;
39
+ } catch {
40
+ }
41
+ return void 0;
42
42
  }
43
- function requireEnv(c, key) {
44
- const val = getEnv(c, key);
45
- if (!val) {
43
+ function toEnvObject(source) {
44
+ if (isContext(source)) return env(source);
45
+ return source ?? runtimeEnv();
46
+ }
47
+ function getEnv(source, key) {
48
+ const value = toEnvObject(source)?.[key];
49
+ return typeof value === "string" ? value : void 0;
50
+ }
51
+ function requireEnv(source, key) {
52
+ const value = getEnv(source, key);
53
+ if (!value) {
46
54
  biniLogger.error(
47
55
  `Missing required environment variable: "${key}"
48
- ${C.DIM}-> Set it in your platform's env config or hosting dashboard.${C.RESET}`
56
+ ${C.DIM}-> Set it in your hosting dashboard (or in .env for dev, preview and bini-server).${C.RESET}`
49
57
  );
50
58
  throw new Error(`[bini-env] Missing required environment variable: "${key}"`);
51
59
  }
52
- return val;
60
+ return value;
53
61
  }
54
- var ENV_PREFIXES = ["BINI_", "VITE_"];
55
- function detectEnvFiles(root) {
56
- try {
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)));
66
- } catch {
67
- return [];
62
+ function checkEnv(source, keys) {
63
+ const missing = keys.filter((k) => !getEnv(source, k));
64
+ if (missing.length > 0) {
65
+ biniLogger.error(`Missing environment variables: ${missing.join(", ")}`);
68
66
  }
67
+ return { ok: missing.length === 0, missing };
69
68
  }
70
- function injectEnvIntoProcess(mode, envDir) {
71
- if (typeof process === "undefined" || !process.env) return 0;
72
- const { loadEnv } = __require("vite");
73
- const loaded = loadEnv(mode, envDir, "");
74
- let injected = 0;
75
- for (const [key, value] of Object.entries(loaded)) {
76
- const isPrefixed = ENV_PREFIXES.some((p) => key.startsWith(p));
77
- if (isPrefixed) continue;
78
- if (!value) continue;
79
- if (process.env[key] !== void 0) continue;
80
- process.env[key] = value;
81
- injected++;
69
+ function requireEnvs(source, keys) {
70
+ const { missing } = checkEnv(source, keys);
71
+ if (missing.length > 0) {
72
+ throw new Error(`[bini-env] Missing environment variables: ${missing.join(", ")}`);
82
73
  }
83
- return injected;
84
- }
85
- function printBanner(server, mode, root) {
86
- const original = server.printUrls.bind(server);
87
- server.printUrls = () => {
88
- console.log(`
89
- ${C.CYAN}\xDF Bini.js${C.RESET} (${mode})`);
90
- const found = detectEnvFiles(root);
91
- if (found.length > 0) {
92
- console.log(` \x1B[32m\u279C\x1B[0m Environments: ${found.join(", ")}`);
93
- }
94
- original();
95
- };
96
- }
97
- function biniEnv() {
98
- return {
99
- name: "bini-env",
100
- config(userConfig, { command, mode }) {
101
- if (command === "serve" && userConfig.envDir !== false) {
102
- const envDir = typeof userConfig.envDir === "string" ? userConfig.envDir : userConfig.root ?? process.cwd();
103
- try {
104
- injectEnvIntoProcess(mode, envDir);
105
- } catch (err) {
106
- biniLogger.warn(
107
- `Failed to inject .env into process.env: ${err.message}`
108
- );
109
- }
110
- }
111
- return { envPrefix: [...ENV_PREFIXES] };
112
- },
113
- configureServer(server) {
114
- printBanner(server, "dev", server.config.root);
115
- },
116
- configurePreviewServer(server) {
117
- printBanner(server, "preview", server.config.root);
118
- }
119
- };
74
+ const out = {};
75
+ for (const k of keys) out[k] = getEnv(source, k);
76
+ return out;
120
77
  }
121
78
 
122
- exports.biniEnv = biniEnv;
123
- exports.biniLogger = biniLogger;
124
- exports.getEnv = getEnv;
125
- exports.requireEnv = requireEnv;
79
+ export { biniLogger, checkEnv, getEnv, requireEnv, requireEnvs };
126
80
  //# sourceMappingURL=index.js.map
127
81
  //# 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":["import { env } from 'hono/adapter';\nimport type { Context } from 'hono';\nimport type { Plugin, UserConfig, ViteDevServer, PreviewServer } from 'vite';\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\nexport type HonoContext = Context;\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\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\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\nconst ENV_PREFIXES = ['BINI_', 'VITE_'] as const;\n\nfunction detectEnvFiles(root: string): string[] {\n try {\n const fs = require('node:fs') as typeof import('fs');\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 injectEnvIntoProcess(mode: string, envDir: string): number {\n if (typeof process === 'undefined' || !process.env) return 0;\n\n const { loadEnv } = require('vite') as typeof import('vite');\n const loaded = loadEnv(mode, envDir, '');\n let injected = 0;\n\n for (const [key, value] of Object.entries(loaded)) {\n const isPrefixed = ENV_PREFIXES.some((p) => key.startsWith(p));\n if (isPrefixed) continue;\n if (!value) continue;\n if (process.env[key] !== undefined) continue;\n process.env[key] = value;\n injected++;\n }\n\n return injected;\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(): Plugin {\n return {\n name: 'bini-env',\n\n config(userConfig: UserConfig, { command, mode }): UserConfig {\n if (command === 'serve' && userConfig.envDir !== false) {\n const envDir =\n typeof userConfig.envDir === 'string'\n ? userConfig.envDir\n : userConfig.root ?? process.cwd();\n\n try {\n injectEnvIntoProcess(mode, envDir);\n } catch (err) {\n biniLogger.warn(\n `Failed to inject .env into process.env: ${(err as Error).message}`,\n );\n }\n }\n\n return { envPrefix: [...ENV_PREFIXES] };\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\nexport type { Plugin } from 'vite';"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["honoEnv"],"mappings":"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","file":"index.js","sourcesContent":["import { env as honoEnv } from 'hono/adapter';\nimport type { Context } from 'hono';\n\nexport type HonoContext = Context;\nexport type EnvSource = Record<string, unknown>;\nexport type EnvInput = HonoContext | EnvSource | undefined | null;\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\nfunction timestamp(): 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(`${timestamp()} ${C.CYAN}${C.BOLD}[bini-env]${C.RESET} ${msg}`);\n },\n warn(msg: string): void {\n console.warn(`${timestamp()} ${C.YELLOW}${C.BOLD}(!) [bini-env]${C.RESET} ${C.YELLOW}${msg}${C.RESET}`);\n },\n error(msg: string, err?: unknown): void {\n const detail = err instanceof Error ? `\\n ${C.DIM}${err.message}${C.RESET}` : '';\n console.error(`${timestamp()} ${C.RED}${C.BOLD}[bini-env] error${C.RESET} ${msg}${detail}`);\n },\n} as const;\n\nfunction isContext(value: unknown): value is HonoContext {\n if (typeof value !== 'object' || value === null) return false;\n const v = value as { req?: unknown; get?: unknown };\n return typeof v.req === 'object' && v.req !== null && typeof v.get === 'function';\n}\n\n/** Best-effort read of the current runtime's environment when no source is given. */\nfunction runtimeEnv(): EnvSource | undefined {\n const g = globalThis as {\n process?: { env?: EnvSource };\n Deno?: { env?: { toObject?: () => EnvSource } };\n };\n if (g.process?.env) return g.process.env;\n try {\n const obj = g.Deno?.env?.toObject?.();\n if (obj) return obj;\n } catch {\n // Deno.env needs --allow-env; treat as unavailable\n }\n return undefined;\n}\n\nfunction toEnvObject(source: EnvInput): EnvSource | undefined {\n if (isContext(source)) return honoEnv(source) as EnvSource;\n return source ?? runtimeEnv();\n}\n\n/**\n * Reads one variable. Returns `undefined` when it is missing or is not a string\n * (Cloudflare bindings such as KV namespaces are not env strings).\n */\nexport function getEnv(source: EnvInput, key: string): string | undefined {\n const value = toEnvObject(source)?.[key];\n return typeof value === 'string' ? value : undefined;\n}\n\n/** Reads one variable and throws (after logging) when it is missing or empty. */\nexport function requireEnv(source: EnvInput, key: string): string {\n const value = getEnv(source, key);\n if (!value) {\n biniLogger.error(\n `Missing required environment variable: \"${key}\"\\n` +\n ` ${C.DIM}-> Set it in your hosting dashboard (or in .env for dev, preview and bini-server).${C.RESET}`,\n );\n throw new Error(`[bini-env] Missing required environment variable: \"${key}\"`);\n }\n return value;\n}\n\nexport interface EnvCheck {\n ok: boolean;\n /** Names only, never values. */\n missing: string[];\n}\n\n/** Checks several variables at once and logs every missing name in one message. */\nexport function checkEnv(source: EnvInput, keys: readonly string[]): EnvCheck {\n const missing = keys.filter((k) => !getEnv(source, k));\n if (missing.length > 0) {\n biniLogger.error(`Missing environment variables: ${missing.join(', ')}`);\n }\n return { ok: missing.length === 0, missing };\n}\n\n/** Requires several variables at once. Throws one error listing all that are missing. */\nexport function requireEnvs<K extends string>(source: EnvInput, keys: readonly K[]): Record<K, string> {\n const { missing } = checkEnv(source, keys);\n if (missing.length > 0) {\n throw new Error(`[bini-env] Missing environment variables: ${missing.join(', ')}`);\n }\n const out = {} as Record<K, string>;\n for (const k of keys) out[k] = getEnv(source, k) as string;\n return out;\n}"]}
package/dist/node.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ declare function envFilesFor(root: string, mode: string): string[];
2
+ interface LoadEnvResult {
3
+ files: string[];
4
+ injected: number;
5
+ }
6
+ declare function loadEnvFiles(root?: string, mode?: string): LoadEnvResult;
7
+
8
+ export { type LoadEnvResult, envFilesFor, loadEnvFiles };
package/dist/node.js ADDED
@@ -0,0 +1,37 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import path from 'path';
3
+ import { parseEnv } from 'util';
4
+
5
+ // src/node.ts
6
+ function envFilesFor(root, mode) {
7
+ return [`.env.${mode}.local`, `.env.${mode}`, ".env.local", ".env"].map((file) => path.join(root, file)).filter((file) => existsSync(file));
8
+ }
9
+ function loadEnvFiles(root = process.cwd(), mode = process.env.NODE_ENV ?? "production") {
10
+ const files = envFilesFor(root, mode);
11
+ let injected = 0;
12
+ for (const file of files) {
13
+ let raw;
14
+ try {
15
+ raw = readFileSync(file, "utf8");
16
+ } catch {
17
+ continue;
18
+ }
19
+ if (raw.charCodeAt(0) === 65279) raw = raw.slice(1);
20
+ let parsed;
21
+ try {
22
+ parsed = parseEnv(raw);
23
+ } catch {
24
+ continue;
25
+ }
26
+ for (const [key, value] of Object.entries(parsed)) {
27
+ if (value === void 0 || process.env[key] !== void 0) continue;
28
+ process.env[key] = value;
29
+ injected++;
30
+ }
31
+ }
32
+ return { files, injected };
33
+ }
34
+
35
+ export { envFilesFor, loadEnvFiles };
36
+ //# sourceMappingURL=node.js.map
37
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/node.ts"],"names":[],"mappings":";;;;;AAIO,SAAS,WAAA,CAAY,MAAc,IAAA,EAAwB;AAChE,EAAA,OAAO,CAAC,CAAA,KAAA,EAAQ,IAAI,CAAA,MAAA,CAAA,EAAU,CAAA,KAAA,EAAQ,IAAI,CAAA,CAAA,EAAI,YAAA,EAAc,MAAM,CAAA,CAC/D,GAAA,CAAI,CAAC,SAAS,IAAA,CAAK,IAAA,CAAK,IAAA,EAAM,IAAI,CAAC,CAAA,CACnC,OAAO,CAAC,IAAA,KAAS,UAAA,CAAW,IAAI,CAAC,CAAA;AACtC;AAOO,SAAS,YAAA,CACd,OAAe,OAAA,CAAQ,GAAA,IACvB,IAAA,GAAe,OAAA,CAAQ,GAAA,CAAI,QAAA,IAAY,YAAA,EACxB;AACf,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,IAAA,EAAM,IAAI,CAAA;AACpC,EAAA,IAAI,QAAA,GAAW,CAAA;AAEf,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI;AACF,MAAA,GAAA,GAAM,YAAA,CAAa,MAAM,MAAM,CAAA;AAAA,IACjC,CAAA,CAAA,MAAQ;AACN,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,GAAA,CAAI,WAAW,CAAC,CAAA,KAAM,OAAQ,GAAA,GAAM,GAAA,CAAI,MAAM,CAAC,CAAA;AAEnD,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,SAAS,GAAG,CAAA;AAAA,IACvB,CAAA,CAAA,MAAQ;AACN,MAAA;AAAA,IACF;AAEA,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACjD,MAAA,IAAI,UAAU,MAAA,IAAa,OAAA,CAAQ,GAAA,CAAI,GAAG,MAAM,MAAA,EAAW;AAC3D,MAAA,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA;AACnB,MAAA,QAAA,EAAA;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,OAAO,QAAA,EAAS;AAC3B","file":"node.js","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { parseEnv } from 'node:util';\n\nexport function envFilesFor(root: string, mode: string): string[] {\n return [`.env.${mode}.local`, `.env.${mode}`, '.env.local', '.env']\n .map((file) => path.join(root, file))\n .filter((file) => existsSync(file));\n}\n\nexport interface LoadEnvResult {\n files: string[];\n injected: number;\n}\n\nexport function loadEnvFiles(\n root: string = process.cwd(),\n mode: string = process.env.NODE_ENV ?? 'production',\n): LoadEnvResult {\n const files = envFilesFor(root, mode);\n let injected = 0;\n\n for (const file of files) {\n let raw: string;\n try {\n raw = readFileSync(file, 'utf8');\n } catch {\n continue;\n }\n\n if (raw.charCodeAt(0) === 0xfeff) raw = raw.slice(1);\n\n let parsed: Record<string, string | undefined>;\n try {\n parsed = parseEnv(raw) as Record<string, string | undefined>;\n } catch {\n continue;\n }\n\n for (const [key, value] of Object.entries(parsed)) {\n if (value === undefined || process.env[key] !== undefined) continue;\n process.env[key] = value;\n injected++;\n }\n }\n\n return { files, injected };\n}"]}
package/dist/vite.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { Plugin } from 'vite';
2
+ export { Plugin } from 'vite';
3
+
4
+ declare function biniEnv(): Plugin;
5
+
6
+ export { biniEnv };
package/dist/vite.js ADDED
@@ -0,0 +1,104 @@
1
+ import path from 'path';
2
+ import { existsSync } from 'fs';
3
+ import { loadEnv } from 'vite';
4
+
5
+ // src/vite.ts
6
+ var ENV_PREFIXES = ["BINI_", "VITE_"];
7
+ var SECRET_NAME = /SECRET|PASSWORD|PASSWD|PRIVATE|TOKEN/i;
8
+ var C = {
9
+ CYAN: "\x1B[36m",
10
+ YELLOW: "\x1B[33m",
11
+ GREEN: "\x1B[32m",
12
+ BOLD: "\x1B[1m",
13
+ DIM: "\x1B[2m",
14
+ RESET: "\x1B[0m"
15
+ };
16
+ var biniLogger = {
17
+ warn(msg) {
18
+ const ts = `${C.DIM}${(/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false })}${C.RESET}`;
19
+ console.warn(`${ts} ${C.YELLOW}${C.BOLD}(!) [bini-env]${C.RESET} ${C.YELLOW}${msg}${C.RESET}`);
20
+ }
21
+ };
22
+ function envFilesFor(root, mode) {
23
+ return [`.env.${mode}.local`, `.env.${mode}`, ".env.local", ".env"].map((file) => path.join(root, file)).filter((file) => existsSync(file));
24
+ }
25
+ var warnedPublicSecrets = /* @__PURE__ */ new Set();
26
+ function injectEnvIntoProcess(mode, envDir) {
27
+ const loaded = loadEnv(mode, envDir, "");
28
+ let injected = 0;
29
+ for (const [key, value] of Object.entries(loaded)) {
30
+ const isPrefixed = ENV_PREFIXES.some((p) => key.startsWith(p));
31
+ if (isPrefixed && SECRET_NAME.test(key) && !warnedPublicSecrets.has(key)) {
32
+ warnedPublicSecrets.add(key);
33
+ biniLogger.warn(
34
+ `"${key}" starts with a public prefix (${ENV_PREFIXES.join(" / ")}) so it is bundled into client code. Rename it without the prefix if it is a secret.`
35
+ );
36
+ }
37
+ if (value === void 0 || process.env[key] !== void 0) continue;
38
+ process.env[key] = value;
39
+ injected++;
40
+ }
41
+ return injected;
42
+ }
43
+ function hideReadyLine(logger) {
44
+ const originalInfo = logger.info.bind(logger);
45
+ logger.info = ((msg, options) => {
46
+ if (typeof msg === "string" && msg.includes("ready in")) return;
47
+ originalInfo(msg, options);
48
+ });
49
+ }
50
+ function printBanner(server, label) {
51
+ const { root, mode } = server.config;
52
+ const originalPrintUrls = server.printUrls.bind(server);
53
+ server.printUrls = () => {
54
+ console.log(`
55
+ ${C.CYAN}\xDF Bini.js${C.RESET} (${label})`);
56
+ const files = envFilesFor(root, mode).map((f) => path.basename(f));
57
+ if (files.length > 0) {
58
+ console.log(` ${C.GREEN}\u279C${C.RESET} Environments: ${files.join(", ")}`);
59
+ }
60
+ originalPrintUrls();
61
+ };
62
+ }
63
+ function biniEnv() {
64
+ return {
65
+ name: "bini-env",
66
+ enforce: "pre",
67
+ config(userConfig, { command, mode }) {
68
+ if (userConfig.envDir !== false) {
69
+ const root = path.resolve(userConfig.root ?? process.cwd());
70
+ const envDir = typeof userConfig.envDir === "string" ? path.resolve(root, userConfig.envDir) : root;
71
+ try {
72
+ if (command === "serve") {
73
+ injectEnvIntoProcess(mode, envDir);
74
+ } else {
75
+ const loaded = loadEnv(mode, envDir, [...ENV_PREFIXES]);
76
+ for (const key of Object.keys(loaded)) {
77
+ if (SECRET_NAME.test(key) && !warnedPublicSecrets.has(key)) {
78
+ warnedPublicSecrets.add(key);
79
+ biniLogger.warn(
80
+ `"${key}" starts with a public prefix (${ENV_PREFIXES.join(" / ")}) so it is bundled into client code. Rename it without the prefix if it is a secret.`
81
+ );
82
+ }
83
+ }
84
+ }
85
+ } catch (err) {
86
+ biniLogger.warn(`Failed to load .env files: ${err.message}`);
87
+ }
88
+ }
89
+ return { envPrefix: [...ENV_PREFIXES] };
90
+ },
91
+ configureServer(server) {
92
+ hideReadyLine(server.config.logger);
93
+ printBanner(server, "dev");
94
+ },
95
+ configurePreviewServer(server) {
96
+ hideReadyLine(server.config.logger);
97
+ printBanner(server, "preview");
98
+ }
99
+ };
100
+ }
101
+
102
+ export { biniEnv };
103
+ //# sourceMappingURL=vite.js.map
104
+ //# sourceMappingURL=vite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/vite.ts"],"names":[],"mappings":"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","file":"vite.js","sourcesContent":["import path from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { loadEnv } from 'vite';\nimport type { Logger, Plugin, PreviewServer, UserConfig, ViteDevServer } from 'vite';\n\nconst ENV_PREFIXES = ['BINI_', 'VITE_'] as const;\nconst SECRET_NAME = /SECRET|PASSWORD|PASSWD|PRIVATE|TOKEN/i;\n\nconst C = {\n CYAN: '\\x1b[36m',\n YELLOW: '\\x1b[33m',\n GREEN: '\\x1b[32m',\n BOLD: '\\x1b[1m',\n DIM: '\\x1b[2m',\n RESET: '\\x1b[0m',\n} as const;\n\nconst biniLogger = {\n warn(msg: string): void {\n const ts = `${C.DIM}${new Date().toLocaleTimeString('en-US', { hour12: false })}${C.RESET}`;\n console.warn(`${ts} ${C.YELLOW}${C.BOLD}(!) [bini-env]${C.RESET} ${C.YELLOW}${msg}${C.RESET}`);\n },\n} as const;\n\nfunction envFilesFor(root: string, mode: string): string[] {\n return [`.env.${mode}.local`, `.env.${mode}`, '.env.local', '.env']\n .map((file) => path.join(root, file))\n .filter((file) => existsSync(file));\n}\n\nconst warnedPublicSecrets = new Set<string>();\n\nfunction injectEnvIntoProcess(mode: string, envDir: string): number {\n const loaded = loadEnv(mode, envDir, '');\n let injected = 0;\n\n for (const [key, value] of Object.entries(loaded)) {\n const isPrefixed = ENV_PREFIXES.some((p) => key.startsWith(p));\n\n if (isPrefixed && SECRET_NAME.test(key) && !warnedPublicSecrets.has(key)) {\n warnedPublicSecrets.add(key);\n biniLogger.warn(\n `\"${key}\" starts with a public prefix (${ENV_PREFIXES.join(' / ')}) so it is bundled into client code. ` +\n `Rename it without the prefix if it is a secret.`,\n );\n }\n\n if (value === undefined || process.env[key] !== undefined) continue;\n process.env[key] = value;\n injected++;\n }\n\n return injected;\n}\n\nfunction hideReadyLine(logger: Logger): void {\n const originalInfo = logger.info.bind(logger);\n logger.info = ((msg: string, options?: Parameters<Logger['info']>[1]) => {\n if (typeof msg === 'string' && msg.includes('ready in')) return;\n originalInfo(msg, options);\n }) as Logger['info'];\n}\n\nfunction printBanner(server: ViteDevServer | PreviewServer, label: 'dev' | 'preview'): void {\n const { root, mode } = server.config;\n const originalPrintUrls = server.printUrls.bind(server);\n\n server.printUrls = () => {\n console.log(`\\n ${C.CYAN}ß Bini.js${C.RESET} (${label})`);\n const files = envFilesFor(root, mode).map((f) => path.basename(f));\n if (files.length > 0) {\n console.log(` ${C.GREEN}➜${C.RESET} Environments: ${files.join(', ')}`);\n }\n originalPrintUrls();\n };\n}\n\nexport function biniEnv(): Plugin {\n return {\n name: 'bini-env',\n enforce: 'pre',\n\n config(userConfig: UserConfig, { command, mode }): UserConfig {\n if (userConfig.envDir !== false) {\n const root = path.resolve(userConfig.root ?? process.cwd());\n const envDir =\n typeof userConfig.envDir === 'string'\n ? path.resolve(root, userConfig.envDir)\n : root;\n\n try {\n if (command === 'serve') {\n injectEnvIntoProcess(mode, envDir);\n } else {\n const loaded = loadEnv(mode, envDir, [...ENV_PREFIXES]);\n for (const key of Object.keys(loaded)) {\n if (SECRET_NAME.test(key) && !warnedPublicSecrets.has(key)) {\n warnedPublicSecrets.add(key);\n biniLogger.warn(\n `\"${key}\" starts with a public prefix (${ENV_PREFIXES.join(' / ')}) so it is bundled into client code. ` +\n `Rename it without the prefix if it is a secret.`,\n );\n }\n }\n }\n } catch (err) {\n biniLogger.warn(`Failed to load .env files: ${(err as Error).message}`);\n }\n }\n return { envPrefix: [...ENV_PREFIXES] };\n },\n\n configureServer(server) {\n hideReadyLine(server.config.logger);\n printBanner(server, 'dev');\n },\n\n configurePreviewServer(server) {\n hideReadyLine(server.config.logger);\n printBanner(server, 'preview');\n },\n };\n}\n\nexport type { Plugin } from 'vite';"]}
package/package.json CHANGED
@@ -1,15 +1,23 @@
1
1
  {
2
2
  "name": "bini-env",
3
- "version": "2.0.0",
4
- "description": "Universal environment variable loader and Vite plugin for Bini.js — powered by Hono, works across Node.js, Bun, Deno, Vercel Edge, Netlify Edge, and Cloudflare Workers",
5
- "main": "./dist/index.cjs",
3
+ "version": "2.0.1",
4
+ "description": "Universal environment variable loader and Vite plugin for Bini.js",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
6
7
  "module": "./dist/index.js",
7
8
  "types": "./dist/index.d.ts",
8
9
  "exports": {
9
10
  ".": {
10
11
  "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js",
12
- "require": "./dist/index.cjs"
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./vite": {
15
+ "types": "./dist/vite.d.ts",
16
+ "default": "./dist/vite.js"
17
+ },
18
+ "./node": {
19
+ "types": "./dist/node.d.ts",
20
+ "default": "./dist/node.js"
13
21
  }
14
22
  },
15
23
  "files": [
@@ -17,13 +25,16 @@
17
25
  "README.md",
18
26
  "LICENSE"
19
27
  ],
20
- "sideEffects": true,
28
+ "sideEffects": [
29
+ "./dist/vite.js"
30
+ ],
21
31
  "scripts": {
22
32
  "build": "tsup",
23
33
  "dev": "tsup --watch",
24
- "prepublishOnly": "npm run build",
34
+ "prepublishOnly": "npm run build && npm run check:edge",
25
35
  "test": "node --test",
26
- "type-check": "tsc --noEmit"
36
+ "type-check": "tsc --noEmit",
37
+ "check:edge": "node -e \"const fs=require('fs');const s=fs.readFileSync('dist/index.js','utf8');const re=/(?:from\\s*['\\\"]|require\\(\\s*['\\\"])(node:|vite)/;if(re.test(s)){console.error('[bini-env] edge entry leaks node:/vite imports:');console.error(s.match(re)[0]);process.exit(1)}else{console.log('[bini-env] dist/index.js is edge-safe')}\""
27
38
  },
28
39
  "keywords": [
29
40
  "vite",
@@ -65,18 +76,18 @@
65
76
  "optional": false
66
77
  },
67
78
  "vite": {
68
- "optional": false
79
+ "optional": true
69
80
  }
70
81
  },
71
82
  "devDependencies": {
72
- "@types/node": "26.1.2",
83
+ "@types/node": "^22.10.0",
73
84
  "hono": "^4.8.4",
74
85
  "tsup": "^8.5.1",
75
86
  "typescript": "^5.8.3",
76
87
  "vite": "^8.0.8"
77
88
  },
78
89
  "engines": {
79
- "node": ">=20.19.0 || >=22.12.0"
90
+ "node": ">=20.12.0"
80
91
  },
81
92
  "publishConfig": {
82
93
  "access": "public",
package/dist/index.d.mts DELETED
@@ -1,15 +0,0 @@
1
- import { Context } from 'hono';
2
- import { Plugin } from 'vite';
3
- export { Plugin } from 'vite';
4
-
5
- type HonoContext = Context;
6
- declare const biniLogger: {
7
- readonly info: (msg: string) => void;
8
- readonly warn: (msg: string) => void;
9
- readonly error: (msg: string, err?: unknown) => void;
10
- };
11
- declare function getEnv(c: HonoContext, key: string): string | undefined;
12
- declare function requireEnv(c: HonoContext, key: string): string;
13
- declare function biniEnv(): Plugin;
14
-
15
- export { type HonoContext, biniEnv, biniLogger, getEnv, requireEnv };