@zh-moody/safe-env 0.3.4 → 0.3.6

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.en.md CHANGED
@@ -20,7 +20,6 @@ Whether you are writing Vue, React, or Node.js, environment variables are often
20
20
  - **Monorepo Ready**: Supports `cwd` parameter to explicitly specify the `.env` directory, ideal for complex project architectures.
21
21
  - **IDE Enhancement**: Supports `.description()` to view variable usage and documentation directly via hover in your code.
22
22
  - **Rigorous Type Parsing**: Built-in `s.array()`, `s.boolean()` with enhanced conversion, and `.transform()` for chainable piping.
23
- - **Ultra-lightweight**: Only **1.9 KB** after Gzip, with zero runtime dependencies.
24
23
 
25
24
  ---
26
25
 
@@ -35,36 +34,38 @@ npm install @zh-moody/safe-env
35
34
  ### 🚀 Quick Start
36
35
 
37
36
  #### 🔹 [Vite / React / Vue]
37
+
38
38
  For frontend projects, use the Vite plugin for **build-time validation**.
39
39
 
40
40
  **1. Configure Vite Plugin (`vite.config.ts`):**
41
+
41
42
  ```typescript
42
- import { viteSafeEnv } from '@zh-moody/safe-env/vite';
43
- import { schema } from './src/env';
43
+ import { viteSafeEnv } from "@zh-moody/safe-env/vite";
44
+ import { schema } from "./src/env";
44
45
 
45
46
  export default {
46
- plugins: [
47
- viteSafeEnv(schema)
48
- ]
49
- }
47
+ plugins: [viteSafeEnv(schema)],
48
+ };
50
49
  ```
51
50
 
52
51
  **2. Define and Export Config (`src/env.ts`):**
52
+
53
53
  ```typescript
54
- import { safeEnv, s } from '@zh-moody/safe-env';
54
+ import { safeEnv, s } from "@zh-moody/safe-env";
55
55
 
56
56
  export const schema = {
57
57
  VITE_API_URL: s.string().url().description("Backend API Base URL"),
58
58
  VITE_PORT: s.number(3000).description("Development Server Port"),
59
59
  };
60
60
 
61
- export const env = safeEnv(schema, {
62
- source: import.meta.env
61
+ export const env = safeEnv(schema, {
62
+ source: import.meta.env,
63
63
  });
64
64
  ```
65
65
 
66
66
  > **💡 Best Practice: Prevent Vite Type Pollution**
67
67
  > To completely disable the insecure original `import.meta.env.XXX` hints, modify `src/vite-env.d.ts`:
68
+ >
68
69
  > ```typescript
69
70
  > interface ImportMetaEnv {
70
71
  > [key: string]: never;
@@ -74,19 +75,24 @@ export const env = safeEnv(schema, {
74
75
  ---
75
76
 
76
77
  #### 🔸 [Node.js / Server-side]
78
+
77
79
  In Node.js, the library automatically looks for and parses `.env` files on disk.
78
80
 
79
81
  **1. Define Config (`src/config.ts`):**
82
+
80
83
  ```typescript
81
- import { safeEnv, s } from '@zh-moody/safe-env';
82
-
83
- const config = safeEnv({
84
- DB_PASSWORD: s.string().secret().description("Database Password"),
85
- DB_PORT: s.number(5432).min(1).max(65535),
86
- }, {
87
- // Explicitly specify the .env directory for Monorepo or specific deployments
88
- // cwd: '/path/to/project-root'
89
- });
84
+ import { safeEnv, s } from "@zh-moody/safe-env";
85
+
86
+ const config = safeEnv(
87
+ {
88
+ DB_PASSWORD: s.string().secret().description("Database Password"),
89
+ DB_PORT: s.number(5432).min(1).max(65535),
90
+ },
91
+ {
92
+ // Explicitly specify the .env directory for Monorepo or specific deployments
93
+ // cwd: '/path/to/project-root'
94
+ },
95
+ );
90
96
 
91
97
  export default config;
92
98
  ```
@@ -96,6 +102,7 @@ export default config;
96
102
  ### 🛠️ API Reference
97
103
 
98
104
  #### 1. Define Fields (`s.xxx`)
105
+
99
106
  - `s.string(default?)`: String field. Required if no default value.
100
107
  - `s.number(default?)`: Automatically converted to `number` and validated.
101
108
  - `s.boolean(default?)`: Supports `"true"`, `"1"`, `"yes"`, `"on"` as `true`.
@@ -106,43 +113,50 @@ export default config;
106
113
 
107
114
  - **`.secret()`**: Masks the value as `********` in error reports.
108
115
  ```typescript
109
- PASSWORD: s.string().secret()
116
+ PASSWORD: s.string().secret();
110
117
  ```
111
118
  - **`.url()` / `.email()`**: Built-in format validation.
112
119
  ```typescript
113
- API_URL: s.string().url()
120
+ API_URL: s.string().url();
114
121
  ```
115
122
  - **`.regex(pattern, msg?)`**: Custom regex validation.
116
123
  ```typescript
117
- VERSION: s.string().regex(/^v\d+\.\d+\.\d+$/, "Invalid format")
124
+ VERSION: s.string().regex(/^v\d+\.\d+\.\d+$/, "Invalid format");
118
125
  ```
119
126
  - **`.description(text)`**: Adds a description for IDE hover hints.
120
127
  ```typescript
121
- PORT: s.number(3000).description("Server Port")
128
+ PORT: s.number(3000).description("Server Port");
122
129
  ```
123
130
  - **`.transform(fn)`**: Custom data transformation, supports multi-level piping.
124
131
  ```typescript
125
- NAME: s.string().transform(v => v.trim()).transform(v => v.toUpperCase())
132
+ NAME: s.string()
133
+ .transform((v) => v.trim())
134
+ .transform((v) => v.toUpperCase());
126
135
  ```
127
136
  - **`.from(key)`**: Maps environment variable name (Alias).
128
137
  ```typescript
129
- port: s.number().from('VITE_SERVER_PORT')
138
+ port: s.number().from("VITE_SERVER_PORT");
130
139
  ```
131
140
  - **`.min(n)` / `.max(n)`**: Constraints for number values.
132
141
  ```typescript
133
- PORT: s.number().min(1024).max(65535)
142
+ PORT: s.number().min(1024).max(65535);
134
143
  ```
135
144
  - **`.validate(fn, msg?)`**: Fully custom validation logic.
136
145
  ```typescript
137
- INTERNAL_URL: s.string().validate(v => v.endsWith('.internal.com'), 'Must be internal')
146
+ INTERNAL_URL: s.string().validate(
147
+ (v) => v.endsWith(".internal.com"),
148
+ "Must be internal",
149
+ );
138
150
  ```
139
151
 
140
152
  ---
141
153
 
142
154
  ### 🎨 Error Reporting
155
+
143
156
  When validation fails, `safe-env` outputs a structured, adaptive table in the console showing: **Key / Error Reason / Current Value (Masked)**.
144
157
 
145
158
  ---
146
159
 
147
160
  ### 📄 License
161
+
148
162
  [MIT License](./LICENSE) - Copyright (c) 2026 Moody.
package/README.md CHANGED
@@ -20,7 +20,6 @@
20
20
  - **Monorepo 精准定位**:支持 `cwd` 参数,可显式指定配置文件检索目录,适配复杂的项目架构。
21
21
  - **IDE 增强**:支持 `.description()`,在代码中通过悬停直接查看变量用途与文档。
22
22
  - **严谨的类型解析**:内置 `s.array()`, `s.boolean()` 增强转换,支持 `.transform()` 链式 Pipe 处理。
23
- - **极致轻量**:Gzip 压缩后仅 **1.9 KB**,零运行时依赖。
24
23
 
25
24
  ---
26
25
 
@@ -35,36 +34,38 @@ npm install @zh-moody/safe-env
35
34
  ### 🚀 快速上手
36
35
 
37
36
  #### 🔹 [Vite / React / Vue] 使用
37
+
38
38
  在前端,建议配合 Vite 插件实现**构建时校验**。
39
39
 
40
40
  **1. 配置 Vite 插件 (`vite.config.ts`):**
41
+
41
42
  ```typescript
42
- import { viteSafeEnv } from '@zh-moody/safe-env/vite';
43
- import { schema } from './src/env';
43
+ import { viteSafeEnv } from "@zh-moody/safe-env/vite";
44
+ import { schema } from "./src/env";
44
45
 
45
46
  export default {
46
- plugins: [
47
- viteSafeEnv(schema)
48
- ]
49
- }
47
+ plugins: [viteSafeEnv(schema)],
48
+ };
50
49
  ```
51
50
 
52
51
  **2. 定义配置并导出 (`src/env.ts`):**
52
+
53
53
  ```typescript
54
- import { safeEnv, s } from '@zh-moody/safe-env';
54
+ import { safeEnv, s } from "@zh-moody/safe-env";
55
55
 
56
56
  export const schema = {
57
57
  VITE_API_URL: s.string().url().description("后端 API 地址"),
58
58
  VITE_PORT: s.number(3000).description("服务端口"),
59
59
  };
60
60
 
61
- export const env = safeEnv(schema, {
62
- source: import.meta.env
61
+ export const env = safeEnv(schema, {
62
+ source: import.meta.env,
63
63
  });
64
64
  ```
65
65
 
66
66
  > **💡 最佳实践:防止 Vite 类型污染**
67
67
  > 为彻底禁用 `import.meta.env.XXX` 的原生提示,建议修改 `src/vite-env.d.ts`:
68
+ >
68
69
  > ```typescript
69
70
  > interface ImportMetaEnv {
70
71
  > [key: string]: never;
@@ -74,19 +75,24 @@ export const env = safeEnv(schema, {
74
75
  ---
75
76
 
76
77
  #### 🔸 [Node.js / 服务端] 使用
78
+
77
79
  在后端环境,库会自动检索并解析磁盘上的 `.env` 系列文件。
78
80
 
79
81
  **1. 定义配置 (`src/config.ts`):**
82
+
80
83
  ```typescript
81
- import { safeEnv, s } from '@zh-moody/safe-env';
82
-
83
- const config = safeEnv({
84
- DB_PASSWORD: s.string().secret().description("数据库密码"),
85
- DB_PORT: s.number(5432).min(1).max(65535),
86
- }, {
87
- // 在 Monorepo 或特定部署环境下,可显式指定 .env 所在目录
88
- // cwd: '/path/to/project-root'
89
- });
84
+ import { safeEnv, s } from "@zh-moody/safe-env";
85
+
86
+ const config = safeEnv(
87
+ {
88
+ DB_PASSWORD: s.string().secret().description("数据库密码"),
89
+ DB_PORT: s.number(5432).min(1).max(65535),
90
+ },
91
+ {
92
+ // 在 Monorepo 或特定部署环境下,可显式指定 .env 所在目录
93
+ // cwd: '/path/to/project-root'
94
+ },
95
+ );
90
96
 
91
97
  export default config;
92
98
  ```
@@ -96,6 +102,7 @@ export default config;
96
102
  ### 🛠️ API 详解
97
103
 
98
104
  #### 1. 定义字段 (`s.xxx`)
105
+
99
106
  - `s.string(default?)`: 字符串。若无默认值则必填。
100
107
  - `s.number(default?)`: 数字。自动转换为 `number` 类型并校验合法性。
101
108
  - `s.boolean(default?)`: 布尔型。支持将 `"true"`, `"1"`, `"yes"`, `"on"` 解析为 `true`。
@@ -108,43 +115,50 @@ export default config;
108
115
 
109
116
  - **`.secret()`**: 标记敏感数据,报错时该值会以 `********` 遮罩显示。
110
117
  ```typescript
111
- PASSWORD: s.string().secret()
118
+ PASSWORD: s.string().secret();
112
119
  ```
113
120
  - **`.url()` / `.email()`**: 常用格式校验。
114
121
  ```typescript
115
- API_URL: s.string().url()
122
+ API_URL: s.string().url();
116
123
  ```
117
124
  - **`.regex(pattern, msg?)`**: 自定义正则校验。
118
125
  ```typescript
119
- VERSION: s.string().regex(/^v\d+\.\d+\.\d+$/, "格式错误")
126
+ VERSION: s.string().regex(/^v\d+\.\d+\.\d+$/, "格式错误");
120
127
  ```
121
128
  - **`.description(text)`**: 添加变量描述,映射到 IDE 悬停提示中。
122
129
  ```typescript
123
- PORT: s.number(3000).description("服务端口")
130
+ PORT: s.number(3000).description("服务端口");
124
131
  ```
125
132
  - **`.transform(fn)`**: 自定义数据转换,支持多级 Pipe。
126
133
  ```typescript
127
- NAME: s.string().transform(v => v.trim()).transform(v => v.toUpperCase())
134
+ NAME: s.string()
135
+ .transform((v) => v.trim())
136
+ .transform((v) => v.toUpperCase());
128
137
  ```
129
138
  - **`.from(key)`**: 映射环境变量名(别名)。
130
139
  ```typescript
131
- port: s.number().from('VITE_SERVER_PORT')
140
+ port: s.number().from("VITE_SERVER_PORT");
132
141
  ```
133
142
  - **`.min(n)` / `.max(n)`**: 限制数字取值范围。
134
143
  ```typescript
135
- PORT: s.number().min(1024).max(65535)
144
+ PORT: s.number().min(1024).max(65535);
136
145
  ```
137
146
  - **`.validate(fn, msg?)`**: 完全自定义的逻辑校验。
138
147
  ```typescript
139
- INTERNAL_URL: s.string().validate(v => v.endsWith('.internal.com'), 'Must be internal')
148
+ INTERNAL_URL: s.string().validate(
149
+ (v) => v.endsWith(".internal.com"),
150
+ "Must be internal",
151
+ );
140
152
  ```
141
153
 
142
154
  ---
143
155
 
144
156
  ### 🎨 错误报告
157
+
145
158
  当校验失败时,`safe-env` 会在控制台输出结构化的自适应表格,清晰展示:**Key / 错误原因 / 当前值(已脱敏)**。
146
159
 
147
160
  ---
148
161
 
149
162
  ### 📄 开源协议 (License)
163
+
150
164
  [MIT License](./LICENSE) - Copyright (c) 2026 Moody.
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});function l(e){let s={},r=e.split(/\r?\n/);for(let o of r){let i=o.trim();if(!i||i.startsWith("#"))continue;let n=i.indexOf("=");if(n==-1)continue;let c=i.slice(0,n).trim(),t=i.slice(n+1).trim();(t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'"))&&(t=t.slice(1,-1)),s[c]=t}return s}exports.a = l;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var d=(a=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(a,{get:(b,c)=>(typeof require<"u"?require:b)[c]}):a)(function(a){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});exports.a = d;
@@ -0,0 +1,9 @@
1
+ import{a as k}from"./chunk-I7AUKTXE.js";var T="development",R="serve",I="build",$="VITE_DEV_SERVER",S="VITE_";var V=typeof window<"u"&&typeof window.document<"u";function g(s,t=!0){if(V)return`SafeEnv Validation Failed: ${s.map(e=>`${e.key} (${e.error})`).join(", ")}`;let l={r:"\x1B[31m",g:"\x1B[32m",y:"\x1B[33m",b:"\x1B[1m",res:"\x1B[0m",d:"\x1B[2m",cy:"\x1B[36m"},n=(e,p)=>{let i=String(e),d=()=>i.length+(i.match(/[^\x00-\xff]/g)||[]).length;for(;d()>p;)i=i.slice(0,-1);return i+" ".repeat(p-d())},E=Math.max(80,(typeof process<"u"?process.stdout.columns:80)||80)-10,y=Math.floor(E*.3),m=Math.floor(E*.5),r=t?l:{r:"",g:"",y:"",b:"",res:"",d:"",cy:""},c=`
2
+ ${r.r}${r.b}\u274C SafeEnv Validation Failed${r.res}
3
+ `;return c+=` ${r.b}${n("Key",y)} \u2502 ${n("Error",m)} \u2502 Value${r.res}
4
+ `,c+=r.d+"\u2500".repeat(E+5)+r.res+`
5
+ `,s.forEach(e=>{let p=e.value===void 0?"undefined":e.isSecret?"********":`"${e.value}"`,i=e.value===void 0?r.d:e.isSecret?r.y:r.cy;c+=` ${r.y}${n(e.key,y)}${r.res} \u2502 ${r.r}${n(e.error,m)}${r.res} \u2502 ${i}${p}${r.res}
6
+ `}),c+=r.d+"\u2500".repeat(E+5)+r.res+`
7
+ `,c+=` ${r.g}\u{1F4A1} Tip: Check your .env files or schema definitions.${r.res}
8
+ `,c}function F(s){if(V){console.group("%c \u274C SafeEnv Validation Failed ","background: #fee2e2; color: #b91c1c; font-weight: bold; padding: 4px; border-radius: 2px;");let t=s.reduce((l,n)=>(l[n.key]={"Error Message":n.error,"Current Value":n.value===void 0?"undefined":n.isSecret?"********":n.value},l),{});console.table(t),console.log("%c \u{1F4A1} Tip: Check your .env files or schema definitions. ","color: #059669; font-style: italic;"),console.groupEnd()}else console.error(g(s,!0))}var x={};function O(s){let t=g(s,!1);return new Proxy({},{get(l,n){if(n==="__isSafeEnvError")return!0;if(n==="toJSON")return()=>({error:"SafeEnv Validation Failed"});throw new Error(`[safe-env] Cannot access "${String(n)}" because validation failed:
9
+ ${t}`)},ownKeys(){return[]},getOwnPropertyDescriptor(){}})}function U(s,t={}){let{loadProcessEnv:l=!0,prefix:n=S,cwd:E,useCache:y=!0}=t,m=typeof window<"u",r=typeof process<"u"&&(!!process.env.VITE||!!process.env[$]),c=m||r||"source"in t,e={};if("source"in t)e=t.source||{};else if(y&&Object.keys(x).length>0)e=x;else if(typeof process<"u"&&!m)try{let o=t.mode||process.env.NODE_ENV||T,{loadDotEnv:a}=k("./fs-node.cjs"),u={};for(let b of[".env",`.env.${o}`,".env.local",`.env.${o}.local`])u={...u,...a(b,E)};e={...u,...l?process.env:{}}}catch{e={}}let p=Object.keys(e).length;if(y&&(p>0?Object.assign(x,e):Object.keys(x).length>0&&(e=x)),c&&Object.keys(e).length===0)return{};let i={},d=[];for(let o in s){let a=s[o],u=n&&!o.startsWith(n)?n+o:o,b=a.sourceKey||(e[u]!==void 0?u:e[o]!==void 0?o:u),v=e[b];try{if(v===void 0||v===""&&a.default!==void 0){if(a.required&&v===void 0)throw new Error("Missing required field");i[o]=a.default}else{let f=a.parse(v);if(f!==void 0&&a.metadata){let{min:h,max:D,validate:w}=a.metadata;if(typeof f=="number"){if(h!==void 0&&f<h)throw new Error(`Below min ${h}`);if(D!==void 0&&f>D)throw new Error(`Above max ${D}`)}if(w&&!w.fn(f))throw new Error(w.message)}i[o]=f}}catch(f){d.push({key:b,error:f.message,value:v,isSecret:a.metadata?.isSecret})}}if(d.length>0){if(t.throwOnError){let o=new Error(g(d,!0));throw o.plainMessage=g(d,!1),o}return F(d),typeof process<"u"&&process.exit&&!c&&process.exit(1),O(d)}return Object.freeze(i)}export{T as a,R as b,I as c,$ as d,S as e,g as f,F as g,U as h};
@@ -0,0 +1 @@
1
+ function l(e){let s={},r=e.split(/\r?\n/);for(let o of r){let i=o.trim();if(!i||i.startsWith("#"))continue;let n=i.indexOf("=");if(n==-1)continue;let c=i.slice(0,n).trim(),t=i.slice(n+1).trim();(t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'"))&&(t=t.slice(1,-1)),s[c]=t}return s}export{l as a};
@@ -0,0 +1 @@
1
+ var d=(a=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(a,{get:(b,c)=>(typeof require<"u"?require:b)[c]}):a)(function(a){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});export{d as a};
@@ -0,0 +1,9 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _chunkD6WM53FNcjs = require('./chunk-D6WM53FN.cjs');var T="development",R= exports.b ="serve",I= exports.c ="build",$= exports.d ="VITE_DEV_SERVER",S= exports.e ="VITE_";var V=typeof window<"u"&&typeof window.document<"u";function g(s,t=!0){if(V)return`SafeEnv Validation Failed: ${s.map(e=>`${e.key} (${e.error})`).join(", ")}`;let l={r:"\x1B[31m",g:"\x1B[32m",y:"\x1B[33m",b:"\x1B[1m",res:"\x1B[0m",d:"\x1B[2m",cy:"\x1B[36m"},n=(e,p)=>{let i=String(e),d=()=>i.length+(i.match(/[^\x00-\xff]/g)||[]).length;for(;d()>p;)i=i.slice(0,-1);return i+" ".repeat(p-d())},E=Math.max(80,(typeof process<"u"?process.stdout.columns:80)||80)-10,y=Math.floor(E*.3),m=Math.floor(E*.5),r=t?l:{r:"",g:"",y:"",b:"",res:"",d:"",cy:""},c=`
2
+ ${r.r}${r.b}\u274C SafeEnv Validation Failed${r.res}
3
+ `;return c+=` ${r.b}${n("Key",y)} \u2502 ${n("Error",m)} \u2502 Value${r.res}
4
+ `,c+=r.d+"\u2500".repeat(E+5)+r.res+`
5
+ `,s.forEach(e=>{let p=e.value===void 0?"undefined":e.isSecret?"********":`"${e.value}"`,i=e.value===void 0?r.d:e.isSecret?r.y:r.cy;c+=` ${r.y}${n(e.key,y)}${r.res} \u2502 ${r.r}${n(e.error,m)}${r.res} \u2502 ${i}${p}${r.res}
6
+ `}),c+=r.d+"\u2500".repeat(E+5)+r.res+`
7
+ `,c+=` ${r.g}\u{1F4A1} Tip: Check your .env files or schema definitions.${r.res}
8
+ `,c}function F(s){if(V){console.group("%c \u274C SafeEnv Validation Failed ","background: #fee2e2; color: #b91c1c; font-weight: bold; padding: 4px; border-radius: 2px;");let t=s.reduce((l,n)=>(l[n.key]={"Error Message":n.error,"Current Value":n.value===void 0?"undefined":n.isSecret?"********":n.value},l),{});console.table(t),console.log("%c \u{1F4A1} Tip: Check your .env files or schema definitions. ","color: #059669; font-style: italic;"),console.groupEnd()}else console.error(g(s,!0))}var x={};function O(s){let t=g(s,!1);return new Proxy({},{get(l,n){if(n==="__isSafeEnvError")return!0;if(n==="toJSON")return()=>({error:"SafeEnv Validation Failed"});throw new Error(`[safe-env] Cannot access "${String(n)}" because validation failed:
9
+ ${t}`)},ownKeys(){return[]},getOwnPropertyDescriptor(){}})}function U(s,t={}){let{loadProcessEnv:l=!0,prefix:n=S,cwd:E,useCache:y=!0}=t,m=typeof window<"u",r=typeof process<"u"&&(!!process.env.VITE||!!process.env[$]),c=m||r||"source"in t,e={};if("source"in t)e=t.source||{};else if(y&&Object.keys(x).length>0)e=x;else if(typeof process<"u"&&!m)try{let o=t.mode||process.env.NODE_ENV||T,{loadDotEnv:a}=_chunkD6WM53FNcjs.a.call(void 0, "./fs-node.cjs"),u={};for(let b of[".env",`.env.${o}`,".env.local",`.env.${o}.local`])u={...u,...a(b,E)};e={...u,...l?process.env:{}}}catch (e2){e={}}let p=Object.keys(e).length;if(y&&(p>0?Object.assign(x,e):Object.keys(x).length>0&&(e=x)),c&&Object.keys(e).length===0)return{};let i={},d=[];for(let o in s){let a=s[o],u=n&&!o.startsWith(n)?n+o:o,b=a.sourceKey||(e[u]!==void 0?u:e[o]!==void 0?o:u),v=e[b];try{if(v===void 0||v===""&&a.default!==void 0){if(a.required&&v===void 0)throw new Error("Missing required field");i[o]=a.default}else{let f=a.parse(v);if(f!==void 0&&a.metadata){let{min:h,max:D,validate:w}=a.metadata;if(typeof f=="number"){if(h!==void 0&&f<h)throw new Error(`Below min ${h}`);if(D!==void 0&&f>D)throw new Error(`Above max ${D}`)}if(w&&!w.fn(f))throw new Error(w.message)}i[o]=f}}catch(f){d.push({key:b,error:f.message,value:v,isSecret:_optionalChain([a, 'access', _ => _.metadata, 'optionalAccess', _2 => _2.isSecret])})}}if(d.length>0){if(t.throwOnError){let o=new Error(g(d,!0));throw o.plainMessage=g(d,!1),o}return F(d),typeof process<"u"&&process.exit&&!c&&process.exit(1),O(d)}return Object.freeze(i)}exports.a = T; exports.b = R; exports.c = I; exports.d = $; exports.e = S; exports.f = g; exports.g = F; exports.h = U;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});function r(n=".env",t){return{}}exports.loadDotEnv = r;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});require('./chunk-D6WM53FN.cjs');function r(n=".env",t){return{}}exports.loadDotEnv = r;
@@ -1 +1 @@
1
- function r(n=".env",t){return{}}export{r as loadDotEnv};
1
+ import"./chunk-I7AUKTXE.js";function r(n=".env",t){return{}}export{r as loadDotEnv};
package/dist/fs-node.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkMODJPD2Xcjs = require('./chunk-MODJPD2X.cjs');exports.loadDotEnv = _chunkMODJPD2Xcjs.b;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _chunk5LT4H5GXcjs = require('./chunk-5LT4H5GX.cjs');require('./chunk-D6WM53FN.cjs');var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs);var _path = require('path'); var _path2 = _interopRequireDefault(_path);function p(e=".env",n){try{let r=_path2.default.resolve(n||process.cwd(),e);if(_fs2.default.existsSync(r))return _chunk5LT4H5GXcjs.a.call(void 0, _fs2.default.readFileSync(r,"utf-8"))}catch (e2){}return{}}exports.loadDotEnv = p;
package/dist/fs-node.js CHANGED
@@ -1 +1 @@
1
- import{b as a}from"./chunk-WZTPUQ3S.js";export{a as loadDotEnv};
1
+ import{a as t}from"./chunk-FBIIFJ67.js";import"./chunk-I7AUKTXE.js";import o from"fs";import s from"path";function p(e=".env",n){try{let r=s.resolve(n||process.cwd(),e);if(o.existsSync(r))return t(o.readFileSync(r,"utf-8"))}catch{}return{}}export{p as loadDotEnv};
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkWXZ32K3Gcjs = require('./chunk-WXZ32K3G.cjs');var _chunkMODJPD2Xcjs = require('./chunk-MODJPD2X.cjs');function a(n,t,e,o=[]){return{type:n,default:t,required:t===void 0,parse:e,metadata:o.length?{options:o}:{},from(i){return this.sourceKey=i,this},validate(i,r="Custom validation failed"){return this.metadata={...this.metadata,validate:{fn:i,message:r}},this},min(i){return this.metadata={...this.metadata,min:i},this},max(i){return this.metadata={...this.metadata,max:i},this},transform(i){let r=this.parse;return this.parse=s=>i(r(s)),this},secret(){return this.metadata={...this.metadata,isSecret:!0},this},url(){return this.validate(i=>{try{return new URL(String(i)),!0}catch (e2){return!1}},"Invalid URL format")},email(){let i=/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;return this.validate(r=>i.test(String(r)),"Invalid email format")},regex(i,r="Value does not match pattern"){return this.validate(s=>i.test(String(s)),r)},description(i){return this.metadata={...this.metadata,description:i},this}}}var m={string:n=>a("string",n,t=>String(t)),number:n=>a("number",n,t=>{let e=Number(t);if(isNaN(e))throw new Error(`Invalid number: ${t}`);return e}),boolean:n=>a("boolean",n,t=>{if(typeof t=="boolean")return t;if(t===void 0||t==="")return!1;let e=String(t).toLowerCase().trim();if(e==="true"||e==="1"||e==="yes"||e==="on")return!0;if(e==="false"||e==="0"||e==="no"||e==="off")return!1;throw new Error(`Invalid boolean: ${t}`)}),enum:(n,t)=>a("enum",t,e=>{if(!n.includes(e))throw new Error(`Value "${e}" is not one of: ${n.join(", ")}`);return e},n),array:(n,t=",")=>a("array",n,e=>Array.isArray(e)?e:typeof e!="string"?[]:e.split(t).map(o=>o.trim()).filter(Boolean))};exports.parseDotEnv = _chunkMODJPD2Xcjs.a; exports.reportErrors = _chunkWXZ32K3Gcjs.a; exports.s = m; exports.safeEnv = _chunkWXZ32K3Gcjs.b;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunk5LT4H5GXcjs = require('./chunk-5LT4H5GX.cjs');var _chunkSHSPQLLUcjs = require('./chunk-SHSPQLLU.cjs');require('./chunk-D6WM53FN.cjs');function a(i,e,n,s=[]){return{type:i,default:e,required:e===void 0,parse:n,metadata:s.length?{options:s}:{},from(t){return this.sourceKey=t,this},validate(t,r="Custom validation failed"){return this.metadata={...this.metadata,validate:{fn:t,message:r}},this},min(t){return this.metadata={...this.metadata,min:t},this},max(t){return this.metadata={...this.metadata,max:t},this},transform(t){let r=this.parse;return this.parse=o=>t(r(o)),this},secret(){return this.metadata={...this.metadata,isSecret:!0},this},url(){return this.validate(t=>{try{return new URL(String(t)),!0}catch (e2){return!1}},"Invalid URL format")},email(){return this.validate(t=>/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(String(t)),"Invalid email format")},regex(t,r="Value does not match pattern"){return this.validate(o=>t.test(String(o)),r)},description(t){return this.metadata={...this.metadata,description:t},this}}}var p={string:i=>a("string",i,e=>String(e)),number:i=>a("number",i,e=>{let n=Number(e);if(isNaN(n))throw new Error(`Invalid number: ${e}`);return n}),boolean:i=>a("boolean",i,e=>{if(typeof e=="boolean")return e;if(e===void 0||e==="")return!1;let n=String(e).toLowerCase().trim();if(["true","1","yes","on"].includes(n))return!0;if(["false","0","no","off"].includes(n))return!1;throw new Error(`Invalid boolean: ${e}`)}),enum:(i,e)=>a("enum",e,n=>{if(!i.includes(n))throw new Error(`Value "${n}" is not one of: ${i.join(", ")}`);return n},i),array:(i,e=",")=>a("array",i,n=>Array.isArray(n)?n:typeof n!="string"?[]:n.split(e).map(s=>s.trim()).filter(Boolean))};exports.BUILD = _chunkSHSPQLLUcjs.c; exports.DEV = _chunkSHSPQLLUcjs.a; exports.SERVE = _chunkSHSPQLLUcjs.b; exports.VITE_DEV_FLAG = _chunkSHSPQLLUcjs.d; exports.VITE_PREFIX = _chunkSHSPQLLUcjs.e; exports.formatErrorReport = _chunkSHSPQLLUcjs.f; exports.parseDotEnv = _chunk5LT4H5GXcjs.a; exports.reportErrors = _chunkSHSPQLLUcjs.g; exports.s = p; exports.safeEnv = _chunkSHSPQLLUcjs.h;
package/dist/index.d.cts CHANGED
@@ -1,28 +1,25 @@
1
- import { F as FieldDefinition, S as Schema, I as InferSchema, E as EnvError } from './types-CFipqnoe.cjs';
2
- export { B as BaseType } from './types-CFipqnoe.cjs';
1
+ import { F as FieldDefinition, S as Schema, a as SafeEnvOptions, I as InferSchema, E as EnvError } from './types-C7kDNgjd.cjs';
2
+ export { B as BUILD, b as BaseType, D as DEV, c as SERVE, V as VITE_DEV_FLAG, d as VITE_PREFIX } from './types-C7kDNgjd.cjs';
3
3
 
4
4
  declare const s: {
5
- string: (defaultValue?: string) => FieldDefinition<string>;
6
- number: (defaultValue?: number) => FieldDefinition<number>;
7
- boolean: (defaultValue?: boolean) => FieldDefinition<boolean>;
8
- enum: <T extends string>(options: T[], defaultValue?: T) => FieldDefinition<T>;
9
- array: (defaultValue?: string[], separator?: string) => FieldDefinition<string[]>;
5
+ string: (d?: string) => FieldDefinition<string>;
6
+ number: (d?: number) => FieldDefinition<number>;
7
+ boolean: (d?: boolean) => FieldDefinition<boolean>;
8
+ enum: <T extends string>(o: T[], d?: T) => FieldDefinition<T>;
9
+ array: (d?: string[], sep?: string) => FieldDefinition<string[]>;
10
10
  };
11
11
 
12
- interface SafeEnvOptions {
13
- mode?: string;
14
- loadProcessEnv?: boolean;
15
- source?: Record<string, any>;
16
- prefix?: string;
17
- cwd?: string;
18
- }
19
- declare function safeEnv<T extends Schema>(schema: T, options?: SafeEnvOptions): Readonly<InferSchema<T>>;
12
+ declare function safeEnv<T extends Schema>(schema: T, options?: SafeEnvOptions & {
13
+ throwOnError?: boolean;
14
+ useCache?: boolean;
15
+ }): Readonly<InferSchema<T>>;
20
16
 
21
17
  /***
22
18
  * 将 .env 内容字符串解析为对象
23
19
  * */
24
20
  declare function parseDotEnv(content: string): Record<string, string>;
25
21
 
22
+ declare function formatErrorReport(errors: EnvError[], useColor?: boolean): string;
26
23
  declare function reportErrors(errors: EnvError[]): void;
27
24
 
28
- export { EnvError, FieldDefinition, InferSchema, Schema, parseDotEnv, reportErrors, s, safeEnv };
25
+ export { EnvError, FieldDefinition, InferSchema, SafeEnvOptions, Schema, formatErrorReport, parseDotEnv, reportErrors, s, safeEnv };
package/dist/index.d.ts CHANGED
@@ -1,28 +1,25 @@
1
- import { F as FieldDefinition, S as Schema, I as InferSchema, E as EnvError } from './types-CFipqnoe.js';
2
- export { B as BaseType } from './types-CFipqnoe.js';
1
+ import { F as FieldDefinition, S as Schema, a as SafeEnvOptions, I as InferSchema, E as EnvError } from './types-C7kDNgjd.js';
2
+ export { B as BUILD, b as BaseType, D as DEV, c as SERVE, V as VITE_DEV_FLAG, d as VITE_PREFIX } from './types-C7kDNgjd.js';
3
3
 
4
4
  declare const s: {
5
- string: (defaultValue?: string) => FieldDefinition<string>;
6
- number: (defaultValue?: number) => FieldDefinition<number>;
7
- boolean: (defaultValue?: boolean) => FieldDefinition<boolean>;
8
- enum: <T extends string>(options: T[], defaultValue?: T) => FieldDefinition<T>;
9
- array: (defaultValue?: string[], separator?: string) => FieldDefinition<string[]>;
5
+ string: (d?: string) => FieldDefinition<string>;
6
+ number: (d?: number) => FieldDefinition<number>;
7
+ boolean: (d?: boolean) => FieldDefinition<boolean>;
8
+ enum: <T extends string>(o: T[], d?: T) => FieldDefinition<T>;
9
+ array: (d?: string[], sep?: string) => FieldDefinition<string[]>;
10
10
  };
11
11
 
12
- interface SafeEnvOptions {
13
- mode?: string;
14
- loadProcessEnv?: boolean;
15
- source?: Record<string, any>;
16
- prefix?: string;
17
- cwd?: string;
18
- }
19
- declare function safeEnv<T extends Schema>(schema: T, options?: SafeEnvOptions): Readonly<InferSchema<T>>;
12
+ declare function safeEnv<T extends Schema>(schema: T, options?: SafeEnvOptions & {
13
+ throwOnError?: boolean;
14
+ useCache?: boolean;
15
+ }): Readonly<InferSchema<T>>;
20
16
 
21
17
  /***
22
18
  * 将 .env 内容字符串解析为对象
23
19
  * */
24
20
  declare function parseDotEnv(content: string): Record<string, string>;
25
21
 
22
+ declare function formatErrorReport(errors: EnvError[], useColor?: boolean): string;
26
23
  declare function reportErrors(errors: EnvError[]): void;
27
24
 
28
- export { EnvError, FieldDefinition, InferSchema, Schema, parseDotEnv, reportErrors, s, safeEnv };
25
+ export { EnvError, FieldDefinition, InferSchema, SafeEnvOptions, Schema, formatErrorReport, parseDotEnv, reportErrors, s, safeEnv };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{a as l,b as u}from"./chunk-UONNQTFU.js";import{a as f}from"./chunk-WZTPUQ3S.js";function a(n,t,e,o=[]){return{type:n,default:t,required:t===void 0,parse:e,metadata:o.length?{options:o}:{},from(i){return this.sourceKey=i,this},validate(i,r="Custom validation failed"){return this.metadata={...this.metadata,validate:{fn:i,message:r}},this},min(i){return this.metadata={...this.metadata,min:i},this},max(i){return this.metadata={...this.metadata,max:i},this},transform(i){let r=this.parse;return this.parse=s=>i(r(s)),this},secret(){return this.metadata={...this.metadata,isSecret:!0},this},url(){return this.validate(i=>{try{return new URL(String(i)),!0}catch{return!1}},"Invalid URL format")},email(){let i=/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;return this.validate(r=>i.test(String(r)),"Invalid email format")},regex(i,r="Value does not match pattern"){return this.validate(s=>i.test(String(s)),r)},description(i){return this.metadata={...this.metadata,description:i},this}}}var m={string:n=>a("string",n,t=>String(t)),number:n=>a("number",n,t=>{let e=Number(t);if(isNaN(e))throw new Error(`Invalid number: ${t}`);return e}),boolean:n=>a("boolean",n,t=>{if(typeof t=="boolean")return t;if(t===void 0||t==="")return!1;let e=String(t).toLowerCase().trim();if(e==="true"||e==="1"||e==="yes"||e==="on")return!0;if(e==="false"||e==="0"||e==="no"||e==="off")return!1;throw new Error(`Invalid boolean: ${t}`)}),enum:(n,t)=>a("enum",t,e=>{if(!n.includes(e))throw new Error(`Value "${e}" is not one of: ${n.join(", ")}`);return e},n),array:(n,t=",")=>a("array",n,e=>Array.isArray(e)?e:typeof e!="string"?[]:e.split(t).map(o=>o.trim()).filter(Boolean))};export{f as parseDotEnv,l as reportErrors,m as s,u as safeEnv};
1
+ import{a as u}from"./chunk-FBIIFJ67.js";import{a as l,b as f,c as m,d as h,e as y,f as g,g as D,h as T}from"./chunk-E625KLX5.js";import"./chunk-I7AUKTXE.js";function a(i,e,n,s=[]){return{type:i,default:e,required:e===void 0,parse:n,metadata:s.length?{options:s}:{},from(t){return this.sourceKey=t,this},validate(t,r="Custom validation failed"){return this.metadata={...this.metadata,validate:{fn:t,message:r}},this},min(t){return this.metadata={...this.metadata,min:t},this},max(t){return this.metadata={...this.metadata,max:t},this},transform(t){let r=this.parse;return this.parse=o=>t(r(o)),this},secret(){return this.metadata={...this.metadata,isSecret:!0},this},url(){return this.validate(t=>{try{return new URL(String(t)),!0}catch{return!1}},"Invalid URL format")},email(){return this.validate(t=>/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(String(t)),"Invalid email format")},regex(t,r="Value does not match pattern"){return this.validate(o=>t.test(String(o)),r)},description(t){return this.metadata={...this.metadata,description:t},this}}}var p={string:i=>a("string",i,e=>String(e)),number:i=>a("number",i,e=>{let n=Number(e);if(isNaN(n))throw new Error(`Invalid number: ${e}`);return n}),boolean:i=>a("boolean",i,e=>{if(typeof e=="boolean")return e;if(e===void 0||e==="")return!1;let n=String(e).toLowerCase().trim();if(["true","1","yes","on"].includes(n))return!0;if(["false","0","no","off"].includes(n))return!1;throw new Error(`Invalid boolean: ${e}`)}),enum:(i,e)=>a("enum",e,n=>{if(!i.includes(n))throw new Error(`Value "${n}" is not one of: ${i.join(", ")}`);return n},i),array:(i,e=",")=>a("array",i,n=>Array.isArray(n)?n:typeof n!="string"?[]:n.split(e).map(s=>s.trim()).filter(Boolean))};export{m as BUILD,l as DEV,f as SERVE,h as VITE_DEV_FLAG,y as VITE_PREFIX,g as formatErrorReport,u as parseDotEnv,D as reportErrors,p as s,T as safeEnv};
@@ -1,20 +1,15 @@
1
+ declare const DEV = "development";
2
+ declare const SERVE = "serve";
3
+ declare const BUILD = "build";
4
+ declare const VITE_DEV_FLAG = "VITE_DEV_SERVER";
5
+ declare const VITE_PREFIX = "VITE_";
1
6
  type BaseType = "string" | "number" | "boolean" | "enum" | "array";
2
7
  interface FieldDefinition<T = any, D extends string = string> {
3
8
  type: BaseType;
4
9
  default?: T;
5
10
  required: boolean;
6
11
  sourceKey?: string;
7
- metadata?: {
8
- min?: number;
9
- max?: number;
10
- options?: T[];
11
- description?: string;
12
- isSecret?: boolean;
13
- validate?: {
14
- fn: (val: T) => boolean;
15
- message: string;
16
- };
17
- };
12
+ metadata?: any;
18
13
  parse: (val: any) => T;
19
14
  from: (key: string) => FieldDefinition<T, D>;
20
15
  validate: (fn: (val: T) => boolean, message?: string) => FieldDefinition<T, D>;
@@ -35,9 +30,16 @@ interface EnvError {
35
30
  isSecret?: boolean;
36
31
  }
37
32
  type InferSchema<T> = {
38
- [K in keyof T]: T[K] extends FieldDefinition<infer U, infer D> ? string extends D ? U : U & {
39
- readonly __description?: D;
40
- } : never;
33
+ [K in keyof T]: T[K] extends FieldDefinition<infer U, any> ? U : never;
41
34
  };
35
+ interface SafeEnvOptions {
36
+ mode?: string;
37
+ loadProcessEnv?: boolean;
38
+ source?: Record<string, any>;
39
+ prefix?: string;
40
+ cwd?: string;
41
+ /** @internal */ manualSource?: boolean;
42
+ /** @internal */ devMode?: boolean;
43
+ }
42
44
 
43
- export type { BaseType as B, EnvError as E, FieldDefinition as F, InferSchema as I, Schema as S };
45
+ export { BUILD as B, DEV as D, type EnvError as E, type FieldDefinition as F, type InferSchema as I, type Schema as S, VITE_DEV_FLAG as V, type SafeEnvOptions as a, type BaseType as b, SERVE as c, VITE_PREFIX as d };
@@ -1,20 +1,15 @@
1
+ declare const DEV = "development";
2
+ declare const SERVE = "serve";
3
+ declare const BUILD = "build";
4
+ declare const VITE_DEV_FLAG = "VITE_DEV_SERVER";
5
+ declare const VITE_PREFIX = "VITE_";
1
6
  type BaseType = "string" | "number" | "boolean" | "enum" | "array";
2
7
  interface FieldDefinition<T = any, D extends string = string> {
3
8
  type: BaseType;
4
9
  default?: T;
5
10
  required: boolean;
6
11
  sourceKey?: string;
7
- metadata?: {
8
- min?: number;
9
- max?: number;
10
- options?: T[];
11
- description?: string;
12
- isSecret?: boolean;
13
- validate?: {
14
- fn: (val: T) => boolean;
15
- message: string;
16
- };
17
- };
12
+ metadata?: any;
18
13
  parse: (val: any) => T;
19
14
  from: (key: string) => FieldDefinition<T, D>;
20
15
  validate: (fn: (val: T) => boolean, message?: string) => FieldDefinition<T, D>;
@@ -35,9 +30,16 @@ interface EnvError {
35
30
  isSecret?: boolean;
36
31
  }
37
32
  type InferSchema<T> = {
38
- [K in keyof T]: T[K] extends FieldDefinition<infer U, infer D> ? string extends D ? U : U & {
39
- readonly __description?: D;
40
- } : never;
33
+ [K in keyof T]: T[K] extends FieldDefinition<infer U, any> ? U : never;
41
34
  };
35
+ interface SafeEnvOptions {
36
+ mode?: string;
37
+ loadProcessEnv?: boolean;
38
+ source?: Record<string, any>;
39
+ prefix?: string;
40
+ cwd?: string;
41
+ /** @internal */ manualSource?: boolean;
42
+ /** @internal */ devMode?: boolean;
43
+ }
42
44
 
43
- export type { BaseType as B, EnvError as E, FieldDefinition as F, InferSchema as I, Schema as S };
45
+ export { BUILD as B, DEV as D, type EnvError as E, type FieldDefinition as F, type InferSchema as I, type Schema as S, VITE_DEV_FLAG as V, type SafeEnvOptions as a, type BaseType as b, SERVE as c, VITE_PREFIX as d };
package/dist/vite.cjs CHANGED
@@ -1 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkWXZ32K3Gcjs = require('./chunk-WXZ32K3G.cjs');require('./chunk-MODJPD2X.cjs');var _vite = require('vite');function m(t,i={}){return{name:"vite-plugin-safe-env",configResolved(r){let{envDir:o=r.root,prefix:e=r.envPrefix||"VITE_"}=i,s=r.mode,a=_vite.loadEnv.call(void 0, s,o,e);try{_chunkWXZ32K3Gcjs.b.call(void 0, t,{source:a,prefix:Array.isArray(e)?e[0]:e,loadProcessEnv:!1})}catch (e2){process.exit(1)}}}}exports.viteSafeEnv = m;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkSHSPQLLUcjs = require('./chunk-SHSPQLLU.cjs');require('./chunk-D6WM53FN.cjs');var _vite = require('vite');function g(v,f={}){let n=null,o=!1;return{name:"vite-plugin-safe-env",configResolved(e){o=e.command===_chunkSHSPQLLUcjs.b,process.env[_chunkSHSPQLLUcjs.d]=o?"true":"";let{envDir:t=e.root,prefix:r=e.envPrefix||_chunkSHSPQLLUcjs.e}=f,p=_vite.loadEnv.call(void 0, e.mode,t,r);try{_chunkSHSPQLLUcjs.h.call(void 0, v,{source:p,prefix:Array.isArray(r)?r[0]:r,loadProcessEnv:!1,throwOnError:!0}),n=null}catch(s){n=s,o?e.logger.error(s.message):(console.error(s.message),console.error(`\x1B[31m[safe-env] Fatal: Environment validation failed during build. Exiting...\x1B[0m
2
+ `),process.exit(1))}},transform(e,t){if(o&&n&&(e.includes("import.meta.env")||e.includes("safeEnv"))){let r=new Error(n.plainMessage||n.message);throw r.stack="",r}return null}}}exports.viteSafeEnv = g;
package/dist/vite.d.cts CHANGED
@@ -1,19 +1,9 @@
1
1
  import { Plugin } from 'vite';
2
- import { S as Schema } from './types-CFipqnoe.cjs';
2
+ import { S as Schema } from './types-C7kDNgjd.cjs';
3
3
 
4
- interface ViteSafeEnvOptions {
5
- /**
6
- * 环境变量目录,默认为项目根目录
7
- */
8
- envDir?: string;
9
- /**
10
- * 环境变量前缀,默认是 VITE_
11
- */
12
- prefix?: string | string[];
13
- }
14
4
  /**
15
5
  * Vite 插件:在构建或开发启动时校验环境变量
16
6
  */
17
- declare function viteSafeEnv(schema: Schema, options?: ViteSafeEnvOptions): Plugin;
7
+ declare function viteSafeEnv(schema: Schema, options?: any): Plugin;
18
8
 
19
9
  export { viteSafeEnv };
package/dist/vite.d.ts CHANGED
@@ -1,19 +1,9 @@
1
1
  import { Plugin } from 'vite';
2
- import { S as Schema } from './types-CFipqnoe.js';
2
+ import { S as Schema } from './types-C7kDNgjd.js';
3
3
 
4
- interface ViteSafeEnvOptions {
5
- /**
6
- * 环境变量目录,默认为项目根目录
7
- */
8
- envDir?: string;
9
- /**
10
- * 环境变量前缀,默认是 VITE_
11
- */
12
- prefix?: string | string[];
13
- }
14
4
  /**
15
5
  * Vite 插件:在构建或开发启动时校验环境变量
16
6
  */
17
- declare function viteSafeEnv(schema: Schema, options?: ViteSafeEnvOptions): Plugin;
7
+ declare function viteSafeEnv(schema: Schema, options?: any): Plugin;
18
8
 
19
9
  export { viteSafeEnv };
package/dist/vite.js CHANGED
@@ -1 +1,2 @@
1
- import{b as n}from"./chunk-UONNQTFU.js";import"./chunk-WZTPUQ3S.js";import{loadEnv as f}from"vite";function m(t,i={}){return{name:"vite-plugin-safe-env",configResolved(r){let{envDir:o=r.root,prefix:e=r.envPrefix||"VITE_"}=i,s=r.mode,a=f(s,o,e);try{n(t,{source:a,prefix:Array.isArray(e)?e[0]:e,loadProcessEnv:!1})}catch{process.exit(1)}}}}export{m as viteSafeEnv};
1
+ import{b as a,d as i,e as l,h as m}from"./chunk-E625KLX5.js";import"./chunk-I7AUKTXE.js";import{loadEnv as u}from"vite";function g(v,f={}){let n=null,o=!1;return{name:"vite-plugin-safe-env",configResolved(e){o=e.command===a,process.env[i]=o?"true":"";let{envDir:t=e.root,prefix:r=e.envPrefix||l}=f,p=u(e.mode,t,r);try{m(v,{source:p,prefix:Array.isArray(r)?r[0]:r,loadProcessEnv:!1,throwOnError:!0}),n=null}catch(s){n=s,o?e.logger.error(s.message):(console.error(s.message),console.error(`\x1B[31m[safe-env] Fatal: Environment validation failed during build. Exiting...\x1B[0m
2
+ `),process.exit(1))}},transform(e,t){if(o&&n&&(e.includes("import.meta.env")||e.includes("safeEnv"))){let r=new Error(n.plainMessage||n.message);throw r.stack="",r}return null}}}export{g as viteSafeEnv};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zh-moody/safe-env",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "Type-safe environment variables for Node.js and Browser with schema validation.",
5
5
  "author": "Moody",
6
6
  "license": "MIT",
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs);var _path = require('path'); var _path2 = _interopRequireDefault(_path);function o(s){let i={},r=s.split(/\r?\n/);for(let f of r){let n=f.trim();if(!n||n.startsWith("#"))continue;let e=n.indexOf("=");if(e==-1)continue;let l=n.slice(0,e).trim(),t=n.slice(e+1).trim();(t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'"))&&(t=t.slice(1,-1)),i[l]=t}return i}function g(s=".env",i){try{let r=_path2.default.resolve(i||process.cwd(),s);if(_fs2.default.existsSync(r))return o(_fs2.default.readFileSync(r,"utf-8"))}catch (e2){}return{}}exports.a = o; exports.b = g;
@@ -1,3 +0,0 @@
1
- import{b as y}from"./chunk-WZTPUQ3S.js";function $(m){let e={r:"\x1B[31m",g:"\x1B[32m",y:"\x1B[33m",b:"\x1B[1m",res:"\x1B[0m",d:"\x1B[2m",cy:"\x1B[36m"},d=Math.max(80,process.stdout.columns||80)-10,f=Math.floor(d*.3),u=Math.floor(d*.5),l=(r,a)=>{let t=String(r),o=()=>t.length+(t.match(/[^\x00-\xff]/g)||[]).length;for(;o()>a;)t=t.slice(0,-1);return t+" ".repeat(a-o())};console.error(`
2
- ${e.r}${e.b}\u274C SafeEnv Validation Failed${e.res}`),console.error(` ${e.b}${l("Key",f)} \u2502 ${l("Error",u)} \u2502 Value${e.res}`),console.error(e.d+"\u2500".repeat(d+5)+e.res),m.forEach(r=>{let a=r.isSecret?"********":r.value===void 0?"undefined":`"${r.value}"`,t=r.isSecret?e.y:r.value===void 0?e.d:e.cy;console.error(` ${e.y}${l(r.key,f)}${e.res} \u2502 ${e.r}${l(r.error,u)}${e.res} \u2502 ${t}${a}${e.res}`)}),console.error(e.d+"\u2500".repeat(d+5)+e.res),console.error(` ${e.g}\u{1F4A1} Tip: Check your .env files or schema definitions.${e.res}
3
- `)}function b(m,e={}){let{loadProcessEnv:d=!0,source:f,prefix:u="",cwd:l}=e,r;if(f!==void 0)r=f||{};else{let o=e.mode||(typeof process<"u"?process.env.NODE_ENV:"development"),s=[".env",`.env.${o}`,".env.local",`.env.${o}.local`],i={};for(let c of s)i={...i,...y(c,l)};r={...i,...d&&typeof process<"u"?process.env:{}}}let a={},t=[];for(let o in m){let s=m[o],i=s.sourceKey;if(!i){let n=u+o;r[n]!==void 0?i=n:r[o]!==void 0?i=o:i=u?n:o}let c=r[i];try{let n;if(c===void 0||c===""&&s.default!==void 0){if(s.required&&c===void 0)throw new Error("Required field missing");n=s.default}else n=s.parse(c);if(n!==void 0&&s.metadata){let{min:p,max:v,validate:E}=s.metadata;if(typeof n=="number"){if(p!==void 0&&n<p)throw new Error(`Below min ${p}`);if(v!==void 0&&n>v)throw new Error(`Above max ${v}`)}if(E&&!E.fn(n))throw new Error(E.message)}a[o]=n}catch(n){t.push({key:i,error:n.message,value:c,isSecret:s.metadata?.isSecret})}}if(t.length>0){$(t);let o=typeof process<"u"&&!!process.exit,s=typeof process<"u"&&process.env.NODE_ENV==="test";if(o&&!f&&!s)process.exit(1);else throw new Error("SafeEnv: Configuration validation failed.")}return Object.freeze(a)}export{$ as a,b};
@@ -1,3 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _chunkMODJPD2Xcjs = require('./chunk-MODJPD2X.cjs');function $(m){let e={r:"\x1B[31m",g:"\x1B[32m",y:"\x1B[33m",b:"\x1B[1m",res:"\x1B[0m",d:"\x1B[2m",cy:"\x1B[36m"},d=Math.max(80,process.stdout.columns||80)-10,f=Math.floor(d*.3),u=Math.floor(d*.5),l=(r,a)=>{let t=String(r),o=()=>t.length+(t.match(/[^\x00-\xff]/g)||[]).length;for(;o()>a;)t=t.slice(0,-1);return t+" ".repeat(a-o())};console.error(`
2
- ${e.r}${e.b}\u274C SafeEnv Validation Failed${e.res}`),console.error(` ${e.b}${l("Key",f)} \u2502 ${l("Error",u)} \u2502 Value${e.res}`),console.error(e.d+"\u2500".repeat(d+5)+e.res),m.forEach(r=>{let a=r.isSecret?"********":r.value===void 0?"undefined":`"${r.value}"`,t=r.isSecret?e.y:r.value===void 0?e.d:e.cy;console.error(` ${e.y}${l(r.key,f)}${e.res} \u2502 ${e.r}${l(r.error,u)}${e.res} \u2502 ${t}${a}${e.res}`)}),console.error(e.d+"\u2500".repeat(d+5)+e.res),console.error(` ${e.g}\u{1F4A1} Tip: Check your .env files or schema definitions.${e.res}
3
- `)}function b(m,e={}){let{loadProcessEnv:d=!0,source:f,prefix:u="",cwd:l}=e,r;if(f!==void 0)r=f||{};else{let o=e.mode||(typeof process<"u"?process.env.NODE_ENV:"development"),s=[".env",`.env.${o}`,".env.local",`.env.${o}.local`],i={};for(let c of s)i={...i,..._chunkMODJPD2Xcjs.b.call(void 0, c,l)};r={...i,...d&&typeof process<"u"?process.env:{}}}let a={},t=[];for(let o in m){let s=m[o],i=s.sourceKey;if(!i){let n=u+o;r[n]!==void 0?i=n:r[o]!==void 0?i=o:i=u?n:o}let c=r[i];try{let n;if(c===void 0||c===""&&s.default!==void 0){if(s.required&&c===void 0)throw new Error("Required field missing");n=s.default}else n=s.parse(c);if(n!==void 0&&s.metadata){let{min:p,max:v,validate:E}=s.metadata;if(typeof n=="number"){if(p!==void 0&&n<p)throw new Error(`Below min ${p}`);if(v!==void 0&&n>v)throw new Error(`Above max ${v}`)}if(E&&!E.fn(n))throw new Error(E.message)}a[o]=n}catch(n){t.push({key:i,error:n.message,value:c,isSecret:_optionalChain([s, 'access', _ => _.metadata, 'optionalAccess', _2 => _2.isSecret])})}}if(t.length>0){$(t);let o=typeof process<"u"&&!!process.exit,s=typeof process<"u"&&process.env.NODE_ENV==="test";if(o&&!f&&!s)process.exit(1);else throw new Error("SafeEnv: Configuration validation failed.")}return Object.freeze(a)}exports.a = $; exports.b = b;
@@ -1 +0,0 @@
1
- import c from"fs";import a from"path";function o(s){let i={},r=s.split(/\r?\n/);for(let f of r){let n=f.trim();if(!n||n.startsWith("#"))continue;let e=n.indexOf("=");if(e==-1)continue;let l=n.slice(0,e).trim(),t=n.slice(e+1).trim();(t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'"))&&(t=t.slice(1,-1)),i[l]=t}return i}function g(s=".env",i){try{let r=a.resolve(i||process.cwd(),s);if(c.existsSync(r))return o(c.readFileSync(r,"utf-8"))}catch{}return{}}export{o as a,g as b};